// --- 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.generallink.top/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.generallink.top/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

}

}

}