// --- ZMIENNE GLOBALNE ---
Tablica JSON świec;
float[] otwarcia, maksima, minima, zamknięcia, wolumeny;
float cenaAktualna, ATH , LOW= 0;
String ech = "1m";
ArrayList klastryLikwidacji = new ArrayList();
ArrayList liczbyKlastra = new ArrayList();
//ArrayList wsparcia = new ArrayList();
ArrayList wsparcieZłamane = new ArrayList();
int losowa= 0;
ArrayList wsparcia = new ArrayList();
ArrayList złamaniaWsparcia = new ArrayList();
String symbol = "BTCUSDT";
int liczbaSymboli=1;
String[] symbole = {
"BTCUSDT", "PAXGUSDT","BTCUSDC","TRUMPUSDC","ANIMEUSDC", "CAKEUSDC", "VIRTUALUSDC", "SAHARAUSDC","CUSDC","FUSDC", "PEPEUSDT","ETHUSDT", "BNBUSDT", "SOLUSDT", "XRPUSDT", "DOGEUSDT", "ADAUSDT", "AVAXUSDT", "AUCTIONUSD", "DOTUSDT",
„TRXUSDT”, „LTCUSDT”, „LINKUSDT”, „BCHUSDT”, „ATOMUSDT”, „XLMUSDT”, „HMSTRUSD”, „UNIUSDT”, „ETCUSDT”, „FILUSDT”, „ICPUSDT”,
„HBARUSDT”, „APTUSDT”, „IMXUSDT”, „ARBUSDT”, „NEARUSDT”, „OPUSDT”, „GRTUSDT”, „VETUSDT”, „EGLDUSDT”, „SANDUSDT”,
"AXSUSDT", "MANAUSDT", "STXUSDT", "XTZUSDT", "THETAUSDT", "RNDRUSDT", "AAVEUSDT", "KAVAUSDT", "ALGOUSDT", "DYDXUSDT",
„TUSDT”, „CROUSDT”, „FTMUSDT”, „GALAUSDT”, „CHZUSDT”, „ENJUSDT”, „ONEUSDT”, „RUNEUSDT”, „ZILUSDT”, „LRCUSDT”,
„FLOWUSDT”, „ROSEUSDT”, „CRVUSDT”, „ENSUSDT”, „ZRXUSDT”, „BATUSDT”, „KSMUSDT”, „COMPUSDT”, „WAVESUSDT”, „1INCHUSDT”,
„BALUSDT”, „SUSHIUSDT”, „XEMUSDT”, „YFIUSDT”, „BNTUSDT”, „SKLUSDT”, „OCEANUSDT”, „ANKRUSDT”, „CELOUSDT”, „GLMRUSDT”,
"SRMUSDT", "MOVRUSDT", "CTSIUSDT", "REEFUSDT", "CVCUSDT", "BANDUSDT", "LITUSDT", "API3USDT", "ALICEUSDT", "RLCUSDT",
„KNCUSDT”, „STORJUSDT”, „NKNUSDT”, „DENTUSDT”, „POWRUSDT”, „RENUSDT”, „ARPAUSDT”, „VTHOUSDT”, „TRBUSDT”, „IDEXUSDT”,
„FORTHUSDT”, „MTLUSDT”, „PERLUSDT”, „SYSUSDT”, „TLMUSDT”, „UFTUSDT”, „XNOUSDT”, „XVGUSDT”, „ELAUSDT”, „BICOUSDT”
};
ArrayList opory = nowy ArrayList();
float fundingRates[] ;//= fetchFundingRates(symbol, 1000); // 1000 ostatnich stawek finansowania
float[] fetchFundingRates(Symbol ciągu, limit int) {
float[] stawki = nowy float[limit];
Ciąg url = "https://fapi.binance.com/fapi/v1/fundingRate?symbol=" + symbol + "&limit=" + limit;
próbować {
Surowy ciąg znaków = join(loadStrings(url), "");
JSONArray arr = parseJSONArray(raw);
println( " nazwa finansowania : "+ arr.size());
dla (int i = 0; i < arr.size(); i++) {
Obiekt JSONObject obj = arr.getJSONObject(i);
stawki[i] = float(obj.getString("fundingRate"));
jeśli (rates[i] < 0) println( "wykryjeeee");
}
} catch(Wyjątek e) {
println("Błąd pobieraniaRates: " + e);
}
stopy zwrotu;
}
// --- PARAMETRY (jak Twoje dane wejściowe Pine) ---
int lookbackVol = 50;
float volMult = 2,5;
współczynnik knota pływakowego = 0,6f;
float minBodyRatio = 0,1f;
float likelihoodPts = 20f; // tolerancja dla grupowania klastrów
int pivotLeft = 5;
int pivotRight = 5;
int interval = 1000; // 1000 ms = 1 sekunda
int ostatniaAktualizacja = 0;
int szerokości;
// --- Obliczenia EMA ---
float[] ema(float[] dane, int okres) {
float[] ema = nowy float[dane.długość];
float alfa = 2,0 / (okres + 1,0);
// Inicjalizacja: zaczynamy od pierwszej surowej wartości
ema[0] = dane[0];
dla (int i = 1; i < data.length; i++) {
ema[i] = alfa * dane[i] + (1 - alfa) * ema[i-1];
}
zwróć e-mail;
}
// --- ORGANIZOWAĆ COŚ ---
void setup() {
//rozmiar(1200, 800);
pełny ekran();
//rozmiar(int(szerokośćwyświetlana*2),int(wysokośćwyświetlana));
symbol = symbole[liczbaSymboli];
pobierzDane( symbol );
szerokości = int(szerokość*8,7);//8,1
fundingRates = fetchFundingRates(symbol, 1000); // Ostatnie 1000 stawek finansowania
//szybkość klatek(1);
// Zmień symbol, jeśli chcesz
}
float startDist;
float zoom = 1,0;
float offsetX = 0;
float offsetY = 0;
void touchStarted() {
jeśli (długość dotyka == 2) {
startDist = dist(dotyka[0].x, dotyka[0].y, dotyka[1].x, dotyka[1].y);
}
}
void touchMoved() {
jeśli (długość dotyka == 2) {
float newDist = dist(dotyka[0].x, dotyka[0].y, dotyka[1].x, dotyka[1].y);
float d = newDist / startDist;
powiększenie *= d;
zoom = constrain(zoom, 0.1, 10); // ogranicza zoom
startDist = newDist;
} w przeciwnym razie jeśli (dotyka.długość == 1) {
offsetX += (dotyka[0].x - pmouseX) / zoom;
offsetY += (dotyka[0].y - pmouseY) / zoom;
}
}
// Przeciągnij myszką (przydatne do testowania na komputerze)
void mouseDragged() {
offsetX += (mouseX - pmouseX) / zoom;
offsetY += (mouseY - pmouseY) / zoom;
jeśli (myszX < szerokość && myszX > szerokość-100 && myszY > wysokość-200 && myszY < wysokość-100){
++przerwa min.;
}
jeśli (myszX < szerokość && myszX > szerokość-100 && myszY > wysokość-100 && myszY < wysokość){
--gapMin;
}
}
void mousePressed()
{
//++countSymbol;
//wypełnij(255);
//rect(szerokość-200, 100,200,200);
jeśli ( mouseX > width-200 && mouseY < 300 && mouseY >100 )
++countSymbol;
jeśli ( mouseX > width-200 && mouseY < 500 && mouseY >300 )
--countSymbol;
jeśli (liczbaSymbolów<0)
liczbaSymbol =0;
jeśli (liczbaSymbolów>101)
liczbaSymbol =0;
//tekst(symbole[liczbaSymboli],szerokość-150,150);
symbol = symbole[liczbaSymboli];
}
void mouseReleased()
{
jeśli (myszX < szerokość && myszX > szerokość-100 && myszY > wysokość-200 && myszY < wysokość-100){
++przerwa min.;
}
jeśli (myszX < szerokość && myszX > szerokość-100 && myszY > wysokość-100 && myszY < wysokość){
--gapMin;
}
}
float rsi(int i, float[] zamyka, int okres) {
jeśli (i < okres) zwróć 50; // wartość domyślna, jeśli nie ma wystarczającej ilości danych
wzmocnienie pływaka = 0, strata = 0;
dla (int j = 1; j <= okres; j++) {
zmiana float = zamyka[i - j + 1] - zamyka[i - j];
jeśli (zmiana > 0) zysk += zmiana;
w przeciwnym razie strata -= zmiana;
}
float avgGain = wzmocnienie / okres;
float avgLoss = strata / okres;
jeśli (avgLoss == 0) zwróć 100; // Maksymalny RSI, jeśli nie ma strat
float rs = średnie wzmocnienie / średnia strata;
zwróć 100 - (100 / (1 + rs));
}
int n = 30; // rozmiar okna
tolerancja float = 100,5; // margines wskazujący, że „uderza w sufit”
void detectResistance(int i, float[] maks., float[] zamyka) {
jeśli (i < n) return; // jeszcze za mało danych
// Bierzemy maksymalną wartość z ostatnich n świec
float maxRecent = highs[i];
dla (int j = 1; j < n; j++) {
jeśli (wysokie[i - j] > maxOstatnie) {
maxRecent = maks. [i - j];
}
}
// Liczymy, ile razy cena „dotknęła” blisko maksimum
int touchess = 0;
dla (int j = 0; j < n; j++) {
jeśli (abs(highs[i - j] - maxRecent) < tolerancja) {
dotykalny++;
}
}
// Obliczenia RSI nie będą wyświetlane
// sprzedaj na dole
float rsiValue = rsi(i, zamyka, 27);
// Jeśli temperatura uderza często, ale nie przekracza 100°C, daj znać
jeśli (touchess > 2 && closes[i] < highs[i] - tolerancja && rsiValue > 60) {
float xp = mapa(i, 0, długość zamknięcia - 1, 50, szerokości - 50);
float y = map(highs[i], min(zamyka), max(zamyka), height - 50, 50);
wypełnij(255, 255, 0, 150);
noStroke();
prostokąt(xp, y, 30, 15);
//wypełnij(255);
Wyrównanie tekstu(CENTRUM);
tekst("KRÓTKI ×100", xp, y - 10);
}
}
// --- NARYSUJ PĘTLĘ ---
pustka rysuj() {
losowo =0;
jeśli (millis() - ostatnia aktualizacja >= interwał) {
//fetchData(symbol); // Odświeżamy dane
/*closes = new float[666]; // resetuje tablicę zamknięć
support.clear(); // Czyścimy listę podpór
supportBreaks.clear(); // wyczyść listę przerw
liquidationClusters.clear(); // zobacz klastry likwidacji
clusterCounts.clear();
supportBroken.clear();*/
symbol = symbole[liczbaSymboli];
pobierzDane( symbol );
lastUpdate = millis(); // Resetujemy licznik do zera
}
pushMatrix();
przesuń(szerokość/2 + przesunięcieX*powiększenie, wysokość/2 + przesunięcieY*powiększenie-400);
//tłumacz(szerokość/2 + przesunięcieX, wysokość/2 + przesunięcieY-400);
skala(powiększenie);
//pobierzDane("BTCUSDT");
tło(20);
udar (255);
wypełnij(200);
// pionowe ograniczenia skalowania
float maxP = max(zamyka);;
float minP = min(zamyka);
/*
dla (int i = 0; i < closes.length; i+=10) {
float xpr = map(i, 0, closes.length - 1, 50, widths-50);
float y = mapa(niskie[i], minP, maxP, wysokość - 50, 50);
wypełnij(255, 25, 255,150);
noStroke();
prostokąt(xpr-20, y - 40,40,40);
}
dla (int i = 5; i < closes.length; i+=10) {
float xpr = map(i, 0, closes.length - 1, 50, widths-50);
float y = mapa(niskie[i], minP, maxP, wysokość - 50, 50);
wypełnij(25, 255, 255,150);
noStroke();
prostokąt(xpr-20, y - 40,40,40);
}
*/
// --- NASTĘPNY ---
udar(255, 255, 0);
float yATH = mapa(ATH, minP, maxP, wysokość-50, 50);
linia(50, yATH, szerokość-50, yATH);
wypełnij(255, 255, 0);
tekst("ATH " + ATH, 55, yATH-5);
wypełnij(255,0,0,55);prostokąt(50,yATH,szerokości,100);
// --- NASTĘPNY ---
udar(25, 255, 255);
yATH = mapa(NISKI, minP, maksP, wysokość-50, 50);
linia(50, yATH, szerokość-50, yATH);
wypełnij(255, 255, 0);
tekst("NISKI " + NISKI, 55, yATH-5);
wypełnij(0,255,0,55);prostokąt(50,yATH,szerokości,-100);
// Wykres cen (wykres liniowy zamknięcia)
/*
dla (int i=1; i
float x1 = mapa(i-1, 0, długość zamknięcia, 50, szerokość-50);
float y1 = mapa(zamyka[i-1], minP, maxP, wysokość-50, 50);
float x2 = mapa(i, 0, długość zamknięcia, 50, szerokość-50);
float y2 = mapa(zamknięcia[i], minP, maxP, wysokość-50, 50);
udar (180);
strokeWeight(2);
linia(x1, y1, x2, y2);
otwiera = nowy float[n];
wysokie wartości = nowy float[n];
lows = nowy float[n];
zamyka = nowy float[n];
}*/
strokeWeight(1.3);
wypełnij(223,12);
beginShape();
dla (int i = 0; i < closes.length; i++) {
float x = mapa(i, 0, długość zamknięcia - 1, 50, szerokości-50);
float y = mapa(zamknięcia[i], minP, maxP, wysokość - 50, 50);
wierzchołek(x, y);
// zlecenia limitowane
}
koniecKształtu();
noStroke();
float[] ema3 = ema(zamyka, 666);//18
strokeWeight(3);
noFill();
dla (int i = 1; i < ema3.length; i++) {
float x1 = mapa(i-1, 0, długość zamknięcia-1, 50, szerokości-50);
float y1 = mapa(ema3[i-1], minP, maxP, wysokość-50, 50);
float x2 = mapa(i, 0, długość zamknięcia-1, 50, szerokości-50);
float y2 = mapa(ema3[i], minP, maxP, wysokość-50, 50);
jeśli (ema3[i] > ema3[i-1]) {
stroke(0, 255, 0); // pion jeśli w górę
} w przeciwnym razie {
stroke(255, 0, 0); // czerwony si descend
}
linia(x1 , y1, x2 , y2);
}
ema3 = ema(zamyka, 18);//18
strokeWeight(3);
noFill();
dla (int i = 1; i < ema3.length; i++) {
float x1 = mapa(i-1, 0, długość zamknięcia-1, 50, szerokości-50);
float y1 = mapa(ema3[i-1], minP, maxP, wysokość-50, 50);
float x2 = mapa(i, 0, długość zamknięcia-1, 50, szerokości-50);
float y2 = mapa(ema3[i], minP, maxP, wysokość-50, 50);
jeśli (ema3[i] > ema3[i-1]) {
stroke(0, 255, 0); // pion jeśli w górę
} w przeciwnym razie {
stroke(255, 0, 0); // czerwony si descend
}
linia(x1 , y1, x2 , y2);
}
/*
// szerokość każdej świecy + spacja
świeca typu float W = 5;
odstęp między świecami = 2; // odstęp między świecami
wykres zmiennoprzecinkowy Szerokość = (świeca Szerokość + odstęp) * długość zamknięcia;
dla (int i = 0; i < closes.length; i++) {
// X z regularnymi odstępami
float x = 50 + i * (świeca W + odstęp);
// mapowanie Y
float yo = mapa(otwiera[i], minP, maxP, wysokość - 50, 50);
float yc = mapa(zamknięcia[i], minP, maxP, wysokość - 50, 50);
float yh = mapa(wysokość[i], minP, maxP, wysokość - 50, 50);
float yl = mapa(niskie[i], minP, maxP, wysokość - 50, 50);
// --- Knot ---
udar (200);
linia(x, yh, x, yl);
// --- Korpus ---
jeśli (zamyka[i] >= otwiera[i]) {
wypełnij(0, 200, 0);
udar(0, 200, 0);
rect(x - świecaW/2, yc, świecaW, yo - yc);
} w przeciwnym razie {
wypełnij(200, 0, 0);
udar(200, 0, 0);
rect(x - świecaW/2, yo, świecaW, yc - yo);
}
}
*/
dla (int i = 0; i < closes.length; i++) {
float x = mapa(i, 0, długość zamknięcia - 1, 50, szerokości-50);
// mapowanie Y
float yo = mapa(otwiera[i], minP, maxP, wysokość - 50, 50);
float yc = mapa(zamknięcia[i], minP, maxP, wysokość - 50, 50);
float yh = mapa(wysokość[i], minP, maxP, wysokość - 50, 50);
float yl = mapa(niskie[i], minP, maxP, wysokość - 50, 50);
// szerokość świecy
świeca typu float W = 4,5;
// --- Knot ---
jeśli (zamyka[i] >= otwiera[i])
// Zielona świeca
udar(0,200,0);
w przeciwnym razie
udar(200,0,0);
strokeWeight(1.3);
linia(x, yh, x, yl);
noStroke();
// --- Korpus ---
jeśli (zamyka[i] >= otwiera[i]) {
// Zielona świeca
wypełnij(0, 200, 0);
udar(0, 200, 0);
rect(x - świecaW/2, yc, świecaW, yo - yc);
} w przeciwnym razie {
// Czerwona świeca
wypełnij(200, 0, 0);
udar(200, 0, 0);
rect(x - świecaW/2, yo, świecaW, yc - yo);
}
wartość logiczna baseHistorique = true;
jeśli (i > 84)
dla (int j = 0; j < 83; j++) {
jeśli (minimalne[i-j-1] < minimowe[i]) {
basHistorique = false;
przerwa;
}
}
w przeciwnym razie baseHistorique = false;
jeśli (downHistory)
{
//jeśli (rsiC>10 && rsiC < 50-Indicator && basHistorique){
//if (rsiC < 45 && basHistorique){
//if (rsiC < 35 && basHistorique){// && data[i]< prixHaut-20)
// Pozycjonowanie punktu
float xp = mapa(i, 0, długość zamknięcia - 1, 50, szerokości-50);
float y = mapa(niskie[i], minP, maxP, wysokość - 50, 50);
wypełnij(255, 0, 0,150);
noStroke();
prostokąt(xp-20, y - 40,40,40);
//elipsa(xp-5, y, 10, 10);
wypełnij(0, 255, 0);
Wyrównanie tekstu(CENTRUM);
//rect(x-decX, y - 8,10,10);
///bas[i]=1;
jeśli (lows[i] < lows[i-83])
tekst("LL", xp, y - 10);
w przeciwnym razie
tekst("HL", xp, y - 10);
// bas[i]=1;
// na niekupiony
//POTWIERDŹ= prawda;
}
boolean HautHistorique = true;
jeśli (i > 84)
dla (int j = 0; j < 83; j++) {
jeśli (wysokości[i-j-1] > wysokości[i]) {
HautHistorique = false;
przerwa;
}
}
w przeciwnym razie HautHistorique = false;
jeśli (HautHistorique)
{
//jeśli (rsiC>10 && rsiC < 50-Indicator && basHistorique){
//if (rsiC < 45 && basHistorique){
//if (rsiC < 35 && basHistorique){// && data[i]< prixHaut-20)
// Pozycjonowanie punktu
float xp = mapa(i, 0, długość zamknięcia - 1, 50, szerokości-50);
float y = mapa(wysokość[i], minP, maxP, wysokość - 50, 50);
wypełnij(255, 255, 0,150);
noStroke();
prostokąt(xp-20, y - 40,40,40);
//elipsa(xp-5, y, 10, 10);
wypełnij(0, 255, 255);
Wyrównanie tekstu(CENTRUM);
//rect(x-decX, y - 8,10,10);
///bas[i]=1;
jeśli (wysokości[i] > wysokości[i-83])
tekst("HH", xp, y - 10);
w przeciwnym razie
tekst("Hl", xp, y - 10);
// bas[i]=1;
jeśli (i<990)
{
float xi = mapa(i+9, 0, długość zamknięcia - 1, 50, szerokości-50);
float yi = mapa(wysokość[i+9], minP, maxP, wysokość - 50, 50);
udar(255,255,0);
linia(xp, y, xi, yi);
}
// na niekupiony
//POTWIERDŹ= prawda;
}
//////////// małe szczyty
baseHistorique = true;
jeśli (i > 9)
dla (int j = 0; j < 8; j++) {
jeśli (minimalne[i-j-1] < minimowe[i]) {
basHistorique = false;
przerwa;
}
}
w przeciwnym razie baseHistorique = false;
jeśli (downHistory)
{
//jeśli (rsiC>10 && rsiC < 50-Indicator && basHistorique){
//if (rsiC < 45 && basHistorique){
//if (rsiC < 35 && basHistorique){// && data[i]< prixHaut-20)
// Pozycjonowanie punktu
float xp = mapa(i, 0, długość zamknięcia - 1, 50, szerokości-50);
float y = mapa(niskie[i], minP, maxP, wysokość - 50, 50);
wypełnij(255, 0, 0,150);
noStroke();
//prostokąt(xp-20, y - 40,40,40);
elipsa(xp-5, y, 10, 10);
wypełnij(0, 255, 0);
Wyrównanie tekstu(CENTRUM);
//rect(x-decX, y - 8,10,10);
///bas[i]=1;
// jeśli (lows[i] < lows[i-83])
//tekst("LL", xp, y - 10);
//w przeciwnym razie
//tekst("HL", xp, y - 10);
// bas[i]=1;
// na niekupiony
//POTWIERDŹ= prawda;
}
TopHistorical = true;
jeśli (i > 9)
dla (int j = 0; j < 8; j++) {
jeśli (wysokości[i-j-1] > wysokości[i]) {
HautHistorique = false;
przerwa;
}
}
w przeciwnym razie HautHistorique = false;
jeśli (HautHistorique)
{
//jeśli (rsiC>10 && rsiC < 50-Indicator && basHistorique){
//if (rsiC < 45 && basHistorique){
//if (rsiC < 35 && basHistorique){// && data[i]< prixHaut-20)
// Pozycjonowanie punktu
float xp = mapa(i, 0, długość zamknięcia - 1, 50, szerokości-50);
float y = mapa(wysokość[i], minP, maxP, wysokość - 50, 50);
wypełnij(255, 255, 0,150);
noStroke();
//prostokąt(xp-20, y - 40,40,40);
elipsa(xp-5, y, 10, 10);
wypełnij(0, 255, 255);
Wyrównanie tekstu(CENTRUM);
//rect(x-decX, y - 8,10,10);
///bas[i]=1;
jeśli (wysokości[i] > wysokości[i-7])
tekst("HH", xp, y - 10);
w przeciwnym razie
tekst("Hl", xp, y - 10);
// bas[i]=1;
/*jeśli ( i<990)
{
float xi = mapa(i+9, 0, długość zamknięcia - 1, 50, szerokości-50);
float yi = mapa(wysokość[i+9], minP, maxP, wysokość - 50, 50);
udar(255,255,0);
linia(xp, y, xi, yi);
}*/
// na niekupiony
//POTWIERDŹ= prawda;
}
// Opory, gdy cena nie rośnie
detectResistance(i, maks., zamyka się);
}
/*
dla (int i = 0; i < closes.length; i++) {
float x = mapa(i, 0, długość zamknięcia - 1, 50, szerokość-50);
//float y = map(closes[i], minP, maxP, height - 50, 50);
float yh = mapa(wysokość[i], minP, maxP, wysokość - 50, 50);
float yl = mapa(niskie[i], minP, maxP, wysokość - 50, 50);
wypełnij(0,255,0,123);
prostokąt(x-10, yh,10,yh-yl);
//otwiera = nowy float[n];
//highs = nowy float[n];
//lows = nowy float[n];
//zamyka = nowy float[n];
// zlecenia limitowane
}
udar(0,0,255);
udar(25, 255, 255);
*/
strokeWeight(2);
// --- Klastry likwidacyjne ---
udar(255, 0, 0);
dla (int i=0; i
float lvl = liquidationClusters.get(i);
float y = mapa(poziom, minP, maxP, wysokość-50, 50);
linia(50, y, szerokości-50, y);
wypełnij(255, 0, 0);
tekst("LC x" + clusterCounts.get(i), szerokości-100, y-5);
}
/*
// --- Wspiera i łamie ---
dla (int i=0; i
float lvl = obsługuje.get(i);
float y = mapa(poziom, minP, maxP, wysokość-50, 50);
jeśli (supportBroken.get(i)) {
stroke(25, 50, 255); // break = orange
} w przeciwnym razie {
stroke(0, 200, 255); // wsparcie = vert
}
linia(50, y, szerokość-50, y);
}*/
// --- Mapa cieplna klastrów ---
//drawClusters(minP, maxP);
// --- Mapa cieplna klastrów ---
narysujKlastry(minP, maxP);
// --- Wsparcie (zielone obszary) ---
narysujObsługuje(minP, maxP);
// --- Przerwy (grube pomarańczowe obszary) ---
narysujPrzerwy(minP, maxP);
//wykryjoporności();
//drawSignals(minP, maxP);
//drawClusters(minimalna cena, maksymalna cena);
drawTradeRectangles(zamknięcia, maksima, minima, minP, maks.P);
narysujFVG(minP, maxP);
/*
int frIndex = fundingRates.length - 1; // na ostatniej części stopy finansowania
// Zaczynamy od końca i przechodzimy przez świece
dla (int i = closes.length - 1; i >= 0 && frIndex >= 0; i -= 8) {
jeśli (fundingRates[frIndex] < 0) {
float x = mapa(i, 0, długość zamknięcia - 1, 50, szerokości - 50);
wypełnij(255, 255, 0, 70); // żółty
rect(x-5, 0, 10, wysokość); // żółty pasek na odpowiedniej świecy
}
frIndex--; // idziemy naprzód w tabeli finansowania
}
*/
jeśli (i == "1h")
///// znak robaka... przepraszam, te spodenki... xP
dla (int i = 0; i < fundingRates.length; ++i) {
//dla (int i = fundingRates.length; i < 1 ; --i) {
//int candleIndex = i * 8; // si ech = 1h
jeśli (fundingRates[i] < 0) {
// Możemy odzyskać tylko 1000 franków
// float x = map(i*8 , 0, fundingRates.length-1, 50, widths-50);
float x = mapa(i*8- 600 , 0, długość zamknięcia-1, 50, (szerokości-50) );
float y = wysokość/2;
wypełnij(255, 255, 0, 70); // żółty
//rect(x-5, y-5, 10, 10); // mały kwadrat
rect(x-5, 0, 10, height); // petit carré
Rozmiar tekstu(33);
wypełnij(255);
tekst("KRÓTKI ", x-5,150);
}
}
Rozmiar tekstu(12);
popMatrix();
String[] labels = {"1s", "1m", "3m", "15m","1day","1h","2h"}; // tekst interwałów
int wld=0;
dla ( int i=0;i
{ wypełnij(i*10,255-i*10,i);
prostokąt(i,0,100,100);
wypełnij(0,0,0);
tekst(etykiety[wld % etykiety.długość], 40+i,50);
++wld;
}
wypełnij(255,255,255);
tekst(ja, 20, 130);
jeśli (myszX < 100 i myszY < 100){
i = "1s";pobierzDane( symbol );
}
jeśli (myszX < 200 i myszX > 100 i myszY < 100){
i = "1m";pobierzDane( symbol );
}
jeśli ( mouseX < 300 && mouseX > 200 && mouseY < 100 ){
i = "3m";pobierzDane( symbol );
}
jeśli (myszX < 400 i myszX > 300 i myszY < 100){
i = "15m";
pobierzDane( symbol );
}
jeśli ( mouseX < 500 && mouseX > 400 && mouseY < 100 ){
i = "1d";
pobierzDane( symbol ); ;
}
jeśli ( mouseX < 600 && mouseX > 500 && mouseY < 100 ){
i = "1 godz.";
pobierzDane( symbol ); ;
}
jeśli (myszX < 700 i myszX > 600 i myszY < 100){
ech = "2h";
pobierzDane( symbol ); ;
}
jeśli ( mouseX < 900 && mouseX > 670 && mouseY < 100 ){
i = "30m";
pobierzDane(symbol);
}
//rect(szerokość-100,wysokość-200,100,100);
//rect(szerokość-100,wysokość-100,100,100);
//rect(szerokość-200,0,szerokość,300);
tekst(symbole[liczbaSymboli],szerokość-150,150);
// Rozmiar tekstu(30);
//wypełnij(t13?0:255,t13?255:0,0);
tekst ("PRIX :" + nf(zamyka[999],0,2),10,wysokość-220);
prostokąt(szerokość-100,wysokość-200,100,100);
prostokąt(szerokość-100,wysokość-100,100,100);
tekst (gapMin, szerokość-30, wysokość-250);
}
// --- POBIERZ DANE ---
void fetchData(Symbol ciągu) {
//closes = new float[666];//[666]; // r�����������init tableau de clôtures
support.clear(); // Wyczyść listę podpór
supportBreaks.clear(); // wyczyść listę przerw
liquidationClusters.clear(); // zobacz klastry likwidacji
clusterCounts.clear();
supportBroken.clear();
String url = "https://api.binance.com/api/v3/klines?symbol=" + symbol + "&interval="+ech+"&limit=2500";
próbować {
Surowy ciąg znaków = join(loadStrings(url), "");
świece = parseJSONArray(raw);
int n = świece.rozmiar();
println("świeca = "+ n);
otwiera = nowy float[n];
wysokie wartości = nowy float[n];
lows = nowy float[n];
zamyka = nowy float[n];
wolumeny = nowy float[n];
dla (int i = 0; i < n; i++) {
JSONArray c = świece.getJSONArray(i);
otwiera[i] = float(c.getString(1));
highs[i] = float(c.getString(2));
lows[i] = float(c.getString(3));
zamyka[i] = float(c.getString(4));
tomy[i] = float(c.getString(5));
// Uproszczony przykład wykrywania
jeśli (obsługuje rozmiar() > 0) {
float lastClose = zamyka[i];
float prevClose = zamyka[i-1];
dla (int s = obsługuje rozmiar()-1; s >= 0; s--) {
float sprice = obsługuje.get(s);
// Warunek przerwania: zamknięcie przechodzi pod podporą
jeśli (poprzednieZamknięcie >= cel i ostatnieZamknięcie < cel) {
supportBreaks.add(cena);
}
}
}
}
prixActuel = closes[n-1];
ATH = max(zamyka);
NISKI= min(zamyka);
wykryjKlastry();
detectSupports();
wykryjKlastryIFVG(gapMin);
} catch (Wyjątek e) {
println("Błąd API: " + e.getMessage());
}
}
float gapMin = 1;
// Klasa do przechowywania luk z indeksami świec
klasa Gap {
unosić się nisko, wysoko;
int startIdx, endIdx; // indeksy świec
boolowski byczy; // prawda = luka bycza, fałsz = niedźwiedzi
Gap(float l, float h, int start, int end, boolean bullishGap) {
niski = l;
wysoki = h;
startIdx = start;
endIdx = koniec;
byczy = bullishGap;
}
}
// Listy globalne dla FVG
ArrayList fvgUp = nowa ArrayList();
ArrayList fvgDn = nowa ArrayList();
// Wykrywanie FVG (wersja uproszczona i testowalna)
void detectClustersAndFVG(float gapMin) {
fvgUp.clear();
fvgDn.clear();
dla (int i=2; i
// --- FVG byczy ---
jeśli (minimalne[i] - maksymalne[i-2] > luka min) {
fvgUp.add(nowa luka(wysokie[i-2], niskie[i], i-2, i, prawda));
//ln("FVG UP:", maks. [i-2], "->", min. [i], "indeksy", i-2, "->", i);
}
// --- FVG niedźwiedzi ---
jeśli (minimalne[i-2] - maksymalne[i] > luka min) {
fvgDn.add(nowa luka(wysokie[i], niskie[i-2], i-2, i, fałsz));
//println("FVG W DÓŁ:", maks.[i], "->", min.[i-2], "indeksy", i-2, "->", i);
}
}
}
// Rysunek FVG (prostokąty poziome „od świecy do świecy”)
void drawFVG(float minP, float maxP) {
noStroke();
// FVG byczy
dla (Odstęp g: fvgUp) {
float x1 = map(g.startIdx, 0, closes.length-1, 50, widths-50);
float x2 = mapa(g.endIdx, 0, długość zamknięcia-1, 50, szerokości-50);
float y1 = mapa(g.high, minP, maxP, wysokość-50, 50);
float y2 = mapa(g.low, minP, maxP, wysokość-50, 50);
fill(0, 255, 0, 90); // pionowa półprzezroczysta
udar(0, 180, 0);
rect(x1, min(y1,y2), max(x2-x1, 2)+100, abs(y2-y1)); // minimalna szerokość 2px
noStroke();
wypełnij(255);
textAlign(LEWO, ŚRODEK);
tekst("Długi FVG " + nf(g.low,0,2) + "-" + nf(g.high,0,2), x1 + 3, min(y1,y2) + abs(y2-y1)/2);
}
// FVG niedźwiedzi
dla (Odstęp g: fvgDn) {
float x1 = map(g.startIdx, 0, closes.length-1, 50, widths-50);
float x2 = mapa(g.endIdx, 0, długość zamknięcia-1, 50, szerokości-50);
float y1 = mapa(g.high, minP, maxP, wysokość-50, 50);
float y2 = mapa(g.low, minP, maxP, wysokość-50, 50);
fill(0, 100, 255, 90); // półprzezroczysty niebieski
udar(0, 0, 180);
rect(x1, min(y1,y2), max(x2-x1, 2)+100, abs(y2-y1)); // minimalna szerokość 2px
noStroke();
wypełnij(255);
textAlign(LEWO, ŚRODEK);
tekst("Krótki FVG " + nf(g.low,0,2) + "-" + nf(g.high,0,2), x1 + 3, min(y1,y2) + abs(y2-y1)/2);
}
}
/*
Przechowujemy luki jako pary (niska, wysoka)
klasa Gap {
unosić się nisko, wysoko;
Gap(float l, float h) {
niski = l;
wysoki = h;
}
}
ArrayList fvgUp = nowa ArrayList();
ArrayList fvgDn = nowa ArrayList();
void detectClustersAndFVG() {
likwidacjaKlastrów.clear();
clusterCounts.clear();
fvgUp.clear();
fvgDn.clear();
// prosta średnia wolumenu
float volMA = 0;
dla (int i=0; i
volMA += objętości[i];
}
volMA /= długość woluminów;
dla (int i=0; i
float body = abs(zamyka[i]-otwiera[i]);
świeca float = maksima[i]-minima[i];
float wickUp = highs[i]-max(otwiera[i], zamyka[i]);
float wickDn = min(otwiera[i], zamyka[i]) - dołki[i];
// --- Likwidacja wykrywania klastrów ---
jeśli (wolumeny[i] > volMA*volMult && świeca > 0 && korpus/świeca <= minBodyRatio) {
float liquidPrice = Float.NaN;
jeśli (wickUp/świeca >= współczynnik wicka) liquidPrice = maksima[i];
w przeciwnym razie jeśli (wickDn/świeca >= wickRatio) liquidPrice = lows[i];
jeśli (!Float.isNaN(cenapłynu)) dodajCluster(cenapłynu);
}
*/
/*
// --- Wykrywanie luk w wartości godziwej (FVG) ---
jeśli (i >= 2) {
// Byczy FVG (bieżące minimum > maksimum sprzed 2 świec)
jeśli (minimalne[i] > maksymalne[i-2]) {
//fvgUp.add(nowa luka(wysokie[i-2], niskie[i]));
fvgUp.add(nowa przerwa(wysokie[i-2], niskie[i]));
//fvgDn.add(nowa luka(wysokie[i], niskie[i-2]));
}
// FVG niedźwiedzi (aktualny szczyt i dołek sprzed 2 świec)
jeśli (wysokie[i] < niskie[i-2]) {
// fvgDn.add(nowa luka(wysokie[i], niskie[i-2]));
// fvgUp.add(nowa przerwa(wysokie[i-2], niskie[i]));
fvgDn.add(nowa luka(wysokie[i], niskie[i-2]));
}
}
*/
/*
float gapMin = 1000; // minimalna tolerancja, aby rozważyć FVG
jeśli (i >= 2) {
// FVG byczy
jeśli (minimalne[i] - maksymalne[i-2] > luka min) {
fvgUp.add(nowa przerwa(wysokie[i-2], niskie[i]));
println("FVG UP:", maks.[i-2], "->", min.[i]);
}
// FVG niedźwiedzi
jeśli (minimalne[i-2] - maksymalne[i] > luka min) {
fvgDn.add(nowa luka(wysokie[i], niskie[i-2]));
println("FVG W DÓŁ:", maks.[i], "->", min.[i-2]);
}
}
}
}
void drawFVG(float minP, float maxP) {
noStroke();
// FVG byczy zielony
dla (Odstęp g: fvgUp) {
float y1 = mapa(g.high, minP, maxP, wysokość-50, 50);
float y2 = mapa(g.low, minP, maxP, wysokość-50, 50);
udar (255);
fill(0, 255, 0); // przezroczysty pionowy
rect(50, y1, szerokości-100, y2-y1);
wypełnij(0, 180);
tekst("FVG" + nf(g.low,0,2)+"-"+nf(g.high,0,2), szerokości-490, y1+12);
}
// FVG niedźwiedzi niebieski
dla (Odstęp g: fvgDn) {
float y1 = mapa(g.high, minP, maxP, wysokość-50, 50);
float y2 = mapa(g.low, minP, maxP, wysokość-50, 50);
udar(255,0,0);
fill(0, 100, 255); // niebieski przezroczysty
rect(50, y1, szerokości-100, y2-y1);
wypełnij(0, 180);
tekst("FVG" + nf(g.low,0,2)+"-"+nf(g.high,0,2), szerokości-490, y1+12);
}
}
*/
// --- WYKRYWANIE KLASTRÓW LIKWIDACYJNYCH ---
void detectClusters() {
likwidacjaKlastrów.clear();
clusterCounts.clear();
// prosta średnia wolumenu
float volMA = 0;
dla (int i=0; i
volMA += objętości[i];
}
volMA /= długość woluminów;
dla (int i=0; i
float body = abs(zamyka[i]-otwiera[i]);
świeca float = maksima[i]-minima[i];
float wickUp = highs[i]-max(otwiera[i], zamyka[i]);
float wickDn = min(otwiera[i], zamyka[i]) - dołki[i];
jeśli (wolumeny[i] > volMA*volMult && świeca > 0 && korpus/świeca <= minBodyRatio) {
float liquidPrice = Float.NaN;
jeśli (wickUp/świeca >= współczynnik wicka) liquidPrice = maksima[i];
w przeciwnym razie jeśli (wickDn/świeca >= wickRatio) liquidPrice = lows[i];
jeśli (!Float.isNaN(cenapłynu)) dodajCluster(cenapłynu);
}
}
}
// --- Grupuj pobliskie klastry ---
void addCluster(cena zmiennoprzecinkowa) {
dla (int i=0; i
jeśli (abs(liquidationClusters.get(i) - cena) <= likelihoodPts) {
// inkrementacja
clusterCounts.set(i, clusterCounts.get(i)+1);
powrót;
}
}
liquidationClusters.add(cena);
clusterCounts.add(1);
}
// --- WYKRYWANIE WSPARĆ + PRZERW ---
void detectSupports() {
obsługuje.clear();
supportBroken.clear();
dla (int i=pivotLeft; i
wartość logiczna isPivot = true;
dla (int j=1; j<=pivotLeft; j++) jeśli (lows[i] >= lows[i-j]) isPivot=false;
dla (int j=1; j<=pivotRight; j++) jeśli (lows[i] >= lows[i+j]) isPivot=false;
jeśli (jestPivot) {
float s = lows[i];
obsługuje.add(s);
// przerwa?
logiczny zepsuty = (zamyka[zamyka.długość-1] < s);
supportBroken.add(broken);
}
}
}
// --- Clusters de liquidation en heatmap ---
void drawClusters(float minP, float maxP) {
noStroke();
dla (int i=0; i
float lvl = liquidationClusters.get(i);
int count = clusterCounts.get(i);
// mapowanie cen na y
float y = mapa(poziom, minP, maxP, wysokość-50, 50);
// Intensywność proporcjonalna do liczby wystąpień
int alpha = constrain(40 + count*30, 40, 200);
int rectHeight = 6 + count*2; // ��������paisseur de zone
wypełnij(255, 0, 0, alfa);
rect(50, y - rectHeight/2, szerokości-100, rectHeight);
// dyskretny tekst po prawej stronie
wypełnij(255, 200);
tekst(poziom+ "Klaster likwidacyjny x" + liczba, szerokości-490, y-5);
}
}
// --- Wsparcie (zielone obszary) ---
void drawSupports(float minP, float maxP) {
noStroke();
dla (int i=0; i
float lvl = obsługuje.get(i);
float y = mapa(poziom, minP, maxP, wysokość-50, 50);
fill(0, 200, 0, 100); // półprzezroczysty zielony
prostokąt(50, y-3, szerokości-100, 6);
wypełnij(0, 255, 0);
tekst(poziom+"Wsparcie", 60, y-5);
}
}
// --- Przerwy w podparciu (grube pomarańczowe obszary) ---
void drawBreaks(float minP, float maxP) {
noStroke();
dla (int i=0; i
float lvl = supportBreaks.get(i);
float y = mapa(poziom, minP, maxP, wysokość-50, 50);
fill(255, 140, 0, 150); // pomarańczowy półprzezroczysty
prostokąt(50, y-4, szerokości-100, 8);
wypełnij(255, 180, 0);
text("Przerwa w wsparciu", 60, y-6);
}
}
///////#######
// --- Analiza skupień dla obszarów kupna/sprzedaży ---
float clusterZoneMargin = 5f; // margines wokół klastra, aby narysować strefę
void drawClusterZones(float minP, float maxP) {
dla (int i=0; i
float lvl = liquidationClusters.get(i);
int count = clusterCounts.get(i);
// Cena mapowania -> i
float y = mapa(poziom, minP, maxP, wysokość-50, 50);
// Zdefiniuj kolor zgodnie z trendem (np. mocne akcenty = wyprzedaż, słabe akcenty = zakup)
float wickUp = highs[i] - max(otwiera[i], zamyka[i]);
float wickDn = min(otwiera[i], zamyka[i]) - minima[i];
boolean isBuyZone = wickDn > wickUp; // większy dolny knot
boolean isSellZone = wickUp > wickDn; // większy, wyższy knot
// Dostosuj krycie i grubość w zależności od liczby wystąpień
int alpha = constrain(60 + count*30, 60, 200);
int rectHeight = 6 + count*2;
jeśli (jestStrefaKupująca) {
wypełnij(0, 0, 255, alfa);
rect(50, y - clusterZoneMargin, szerokości-100, clusterZoneMargin*2);
wypełnij(0, 0, 255);
text("Zakup x"+count, widths-180, y);
}
jeśli (jestStrefąSprzedaży) {
wypełnij(255, 0, 0, alfa);
rect(50, y - clusterZoneMargin, szerokości-100, clusterZoneMargin*2);
wypełnij(255, 0, 0);
text("Vente x"+count, widths-180, y);
}
}
}
////////€€
// --- Ustawienia ---
float rsiOverbought = 70f;
float rsiOversold = 45f;
int rsiLength = 27; // długość RSI
int shortTrendLength = 33; // liczba świec do obliczenia trendu krótkiego
float rectMargin = 10f; // grubość prostokąta
// --- Proste obliczenie RSI ---
float calcRSI(float[] zamyka, int idx, int długość) {
jeśli (idx < length) zwróć 50; // wartość neutralna, jeśli nie ma wystarczającej ilości danych
wzmocnienie pływaka = 0, strata = 0;
dla (int i=idx-długość+1; i<=idx; i++) {
float diff = zamyka[i] - zamyka[i-1];
jeśli (różnica > 0) wzmocnienie += różnica;
w przeciwnym razie strata -= diff;
}
jeśli (strata == 0) zwróć 100;
zwrot 100 - (100 / (1 + zysk/strata));
}
// --- Wykrywanie trendów krótkoterminowych ---
boolean isShortDowntrend(float[] closes, int idx, int len) {
jeśli (idx < len) zwróć fałsz;
zwróć closes[idx] < closes[idx-len];
}
boolean isShortUptrend(float[] closes, int idx, int len) {
jeśli (idx < len) zwróć fałsz;
zwróć zamyka[idx] > zamyka[idx-len];
}
void drawTradeRectangles(float[] zamknięcia, float[] maksima, float[] minima, float minP, float maxP) {
dla (int i=krótka długość trendu; i
float rsi = calcRSI(zamknięcia, i, rsiLength);
// Obliczanie pozycji X na podstawie osi czasu
float x = mapa(i, 0, długość zamknięcia-1, 50, szerokości-50);
// --- Sygnał sprzedaży ---
jeśli (rsi >= rsiOverbought && isShortDowntrend(zamknięcia, i, shortTrendLength)) {
float recentHigh = highs[i];
float y = mapa(recentHigh, minP, maxP, wysokość-50, 50);
wypełnij(255, 0, 0, 80);
rect(x-10, y-rectMargin, 20, rectMargin*2); // prostokąt wyśrodkowany na x
wypełnij(255, 0, 0);
text("S", x, y-rectMargin-5); // tekst tuż nad prostokątem
}
// --- Sygnał kupna ---
jeśli (rsi <= rsiOversold && isShortUptrend(zamyka, i, shortTrendLength)) {
float recentLow = lows[i];
float y = mapa(ostatniNiski, minP, maxP, wysokość-50, 50);
wypełnij(0, 0, 255, 80);
rect(x-10, y-rectMargin, 20, rectMargin*2); // prostokąt wyśrodkowany na x
wypełnij(0, 0, 255);
text("B", x, y-rectMargin-5); // tekst tuż nad prostokątem
}
}
}