// --- VARIABLES GLOBALES ---

JSONArray bougies;

float[] ouvertures, hauts, bas, fermetures, volumes;

float prixActuel, ATH , BAS= 0;

String ech = "1m";

ArrayList clustersLiquidation = new ArrayList();

ArrayList compteursCluster = new ArrayList();

//ArrayList supports = new ArrayList();

ArrayList supportBrisé = new ArrayList();

int aléatoire= 0;

ArrayList supports = new ArrayList();

ArrayList rupturesSupport = new ArrayList();

String symbole = "BTCUSDT";

int compteSymbol=1;

String[] symboles = {

"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 résistances = nouvelle ArrayList();

float fundingRates[] ;//= fetchFundingRates(symbol, 1000); // 1000 derniers taux de financement

float[] fetchFundingRates(String symbol, int limit) {

float[] taux = nouveau float[limite];

URL de chaîne = "https://fapi.binance.com/fapi/v1/fundingRate?symbol=" + symbol + "&limit=" + limit;

essayer {

Chaîne brute = join(loadStrings(url), "");

JSONArray arr = parseJSONArray(raw);

println( " nom du financement : "+ arr.size());

pour (int i = 0; i < arr.size(); i++) {

JSONObject obj = arr.getJSONObject(i);

taux[i] = float(obj.getString("fundingRate"));

si ( taux[i] < 0) println( " détectereeeee");

}

} catch(Exception e) {

println("Erreur fetchFundingRates : " + e);

}

taux de rendement ;

}

// --- PARAMÈTRES (comme tes inputs Pine) ---

int lookbackVol = 50;

float volMult = 2,5;

float wickRatio = 0,6f;

float minBodyRatio = 0.1f;

float proximityPts = 20f; // tolérance pour grouper clusters

int pivotGauche = 5;

int pivotDroite = 5;

int interval = 1000; // 1000 ms = 1 seconde

int dernièreMiseÀJour = 0;

largeurs entières ;

// --- Calcul de la moyenne mobile exponentielle (EMA) ---

float[] ema(float[] données, int période) {

float[] ema = nouveau float[data.length];

flottant alpha = 2.0 / (période + 1.0);

// initialisation : on démarre avec la première valeur brute

ema[0] = données[0];

pour (int i = 1; i < data.length; i++) {

ema[i] = alpha * data[i] + (1 - alpha) * ema[i-1];

}

retour ema;

}

// --- INSTALLATION ---

void setup() {

//taille(1200, 800);

pleinécran();

//taille(int(largeur d'affichage*2),int(hauteur d'affichage));

symbole = symboles[countSymbol];

récupérerDonnées( symbole );

largeurs = int(largeur * 8,7); // 8,1

fundingRates = fetchFundingRates( symbol , 1000); // 1000 derniers funding rates

//frameRate(1);

// change le symbole si tu veux

}

flottant startDist;

zoom flottant = 1.0;

flottant offsetX = 0;

flottant offsetY = 0;

void touchStarted() {

si (touches.length == 2) {

startDist = dist(touches[0].x, touches[0].y, touches[1].x, touches[1].y);

}

}

void touchMoved() {

si (touches.length == 2) {

float newDist = dist(touches[0].x, touches[0].y, touches[1].x, touches[1].y);

flottant d = nouvelleDist / startDist;

zoom *= d;

zoom = contrainte(zoom, 0.1, 10); // limite le zoom

startDist = newDist;

} sinon si (touches.length == 1) {

décalageX += (touches[0].x - pmouseX) / zoom;

décalageY += (touches[0].y - pmouseY) / zoom;

}

}

// Drag avec la souris (utile pour test sur PC)

void sourisDragged() {

décalageX += (mouseX - pmouseX) / zoom;

décalageY += (sourisY - sourisY) / zoom ;

si ( sourisX < largeur && sourisX > largeur-100 && sourisY > hauteur-200 && sourisY < hauteur-100){

++écartMin;

}

si ( sourisX < largeur && sourisX > largeur-100 && sourisY > hauteur-100 && sourisY < hauteur){

--écartMin;

}

}

void sourisPressée()

{

//++countSymbole;

//remplir(255);

//rect(largeur-200, 100,200,200);

si (mouseX > largeur-200 && sourisY < 300 && sourisY >100)

++countSymbol;

si (mouseX > largeur-200 && sourisY < 500 && sourisY >300)

--countSymbole;

si (countSymbol<0)

countSymbol = 0 ;

si (countSymbol>101)

countSymbol = 0 ;

//texte(symboles[countSymbol],largeur-150,150);

symbole = symboles[countSymbol];

}

void sourisRelâchée()

{

si ( sourisX < largeur && sourisX > largeur-100 && sourisY > hauteur-200 && sourisY < hauteur-100){

++écartMin;

}

si ( sourisX < largeur && sourisX > largeur-100 && sourisY > hauteur-100 && sourisY < hauteur){

--écartMin;

}

}

float rsi(int i, float[] closes, int period) {

if (i < period) return 50; // par défaut si pas assez de data

gain flottant = 0, perte = 0 ;

pour (int j = 1; j <= période; j++) {

float change = closes[i - j + 1] - closes[i - j];

si (changement > 0) gain += changement ;

sinon perte -= changement ;

}

float avgGain = gain / période;

float avgLoss = perte / période ;

if (avgLoss == 0) return 100; // RSI max si aucune perte

float rs = gain moyen / perte moyenne ;

retourner 100 - (100 / (1 + rs));

}

int n = 30; // taille de la fenêtre

float tolerance = 100.5; // marge pour dire "ça tape le plafond"

void detectResistance(int i, float[] highs, float[] closes) {

if (i < n) return; // pas assez de données encore

// On prend la valeur max sur les n dernières bougies

float maxRecent = hauts[i];

pour (int j = 1; j < n; j++) {

si (highs[i - j] > maxRecent) {

maxRécent = hauts[i - j];

}

}

// On compte combien de fois le prix a "tapé" près du max

entier touches = 0;

pour (int j = 0; j < n; j++) {

si (abs(highs[i - j] - maxRecent) < tolérance) {

touches++;

}

}

// calcul du rsi poyr ne pas afficher

// des sell en bas

float rsiValue = rsi(i, closes, 27);

// Si ça tape souvent mais ça ne dépasse pas, signal

si (sans contact > 2 && closes[i] < highs[i] - tolérance && rsiValue > 60) {

float xp = map(i, 0, closes.length - 1, 50, widths - 50);

float y = map(highs[i], min(closes), max(closes), height - 50, 50);

remplir(255, 255, 0, 150);

pas de Stroke();

rect(xp, y, 30, 15);

//remplir(255);

textAlign(CENTRE);

texte("COURT ×100", xp, y - 10);

}

}

// --- BOUCLE DE DESSIN ---

void dessiner() {

aléatoire = 0 ;

si (millis() - lastUpdate >= interval) {

//fetchData(symbol); // On rafraîchit les données

/*closes = new float[666]; // réinit tableau de clôtures

supports.clear(); // on vide la liste des supports

supportBreaks.clear(); // on vide la liste des breaks

liquidationClusters.clear(); // on vide les clusters de liquidation

clusterCounts.clear();

supportBroken.clear();*/

symbole = symboles[countSymbol];

récupérerDonnées( symbole );

lastUpdate = millis(); // On remet le compteur à zéro

}

pousserMatrix();

translate(largeur/2 + décalageX*zoom, hauteur/2 + décalageY*zoom-400);

//translate(largeur/2 + décalageX, hauteur/2 + décalageY-400);

mise à l'échelle(zoom);

//fetchData("BTCUSDT");

arrière-plan(20);

coup(255);

remplir(200);

// bornes verticales pour mise à l��������échelle

float maxP = max(closes);

float minP = min(closes);

/*

pour (int i = 0; i < closes.length; i+=10) {

float xpr = map(i, 0, closes.length - 1, 50, widths-50);

float y = map(lows[i], minP, maxP, hauteur - 50, 50);

remplir(255, 25, 255,150);

pas de Stroke();

rect(xpr-20, y - 40,40,40);

}

pour (int i = 5; i < closes.length; i+=10) {

float xpr = map(i, 0, closes.length - 1, 50, widths-50);

float y = map(lows[i], minP, maxP, hauteur - 50, 50);

remplir(25, 255, 255,150);

pas de Stroke();

rect(xpr-20, y - 40,40,40);

}

*/

// --- SUIVANT ---

trait(255, 255, 0);

float yATH = map(ATH, minP, maxP, hauteur-50, 50);

ligne(50, yATH, largeurs-50, yATH);

remplir(255, 255, 0);

texte("ATH " + ATH, 55, yATH-5);

remplir(255,0,0,55);rect(50,yATH,largeurs,100);

// --- SUIVANT ---

coup(25, 255, 255);

yATH = map(LOW, minP, maxP, hauteur-50, 50);

ligne(50, yATH, largeurs-50, yATH);

remplir(255, 255, 0);

texte("BAS " + BAS, 55, yATH-5);

remplir(0,255,0,55);rect(50,yATH,largeurs,-100);

// tracé du prix (close line chart)

/*

pour (int i=1; i

float x1 = map(i-1, 0, closes.length, 50, width-50);

float y1 = map(closes[i-1], minP, maxP, hauteur-50, 50);

float x2 = map(i, 0, closes.length, 50, width-50);

float y2 = map(closes[i], minP, maxP, hauteur-50, 50);

coup(180);

strokeWeight(2);

ligne(x1, y1, x2, y2);

ouvre = nouveau float[n];

hauts = nouveau float[n];

bas = nouveau float[n];

ferme = nouveau float[n];

}*/

strokeWeight(1,3);

remplir(223,12);

débutForme();

pour (int i = 0; i < closes.length; i++) {

float x = map(i, 0, closes.length - 1, 50, widths-50);

float y = map(closes[i], minP, maxP, hauteur - 50, 50);

sommet(x, y);

// ordres limits

}

finForme();

pas de Stroke();

float[] ema3 = ema(closes, 666);//18

strokeWeight(3);

noFill();

pour (int i = 1; i < ema3.length; i++) {

float x1 = map(i-1, 0, closes.length-1, 50, widths-50);

float y1 = map(ema3[i-1], minP, maxP, hauteur-50, 50);

float x2 = map(i, 0, closes.length-1, 50, widths-50);

float y2 = map(ema3[i], minP, maxP, hauteur-50, 50);

si (ema3[i] > ema3[i-1]) {

stroke(0, 255, 0); // vertical si vers le haut

} autre {

stroke(255, 0, 0); // rouge si descend

}

ligne(x1 , y1, x2 , y2);

}

ema3 = ema(closes, 18);//18

strokeWeight(3);

noFill();

pour (int i = 1; i < ema3.length; i++) {

float x1 = map(i-1, 0, closes.length-1, 50, widths-50);

float y1 = map(ema3[i-1], minP, maxP, hauteur-50, 50);

float x2 = map(i, 0, closes.length-1, 50, widths-50);

float y2 = map(ema3[i], minP, maxP, hauteur-50, 50);

si (ema3[i] > ema3[i-1]) {

stroke(0, 255, 0); // vertical si vers le haut

} autre {

stroke(255, 0, 0); // rouge si descend

}

ligne(x1 , y1, x2 , y2);

}

/*

// largeur de chaque bougie + espace

float candleW = 5;

float spacing = 2; // espace entre les bougies

float chartWidth = (candleW + espacement) * closes.length;

pour (int i = 0; i < closes.length; i++) {

// X avec espacement régulier

float x = 50 + i * (candleW + espacement);

// cartographie Y

float yo = map(opens[i], minP, maxP, hauteur - 50, 50);

float yc = map(closes[i], minP, maxP, hauteur - 50, 50);

float yh = map(highs[i], minP, maxP, hauteur - 50, 50);

float yl = map(lows[i], minP, maxP, hauteur - 50, 50);

// --- Mèche ---

coup(200);

ligne(x, yh, x, yl);

// --- Corps ---

si (closes[i] >= opens[i]) {

remplir(0, 200, 0);

trait(0, 200, 0);

rect(x - candleW/2, yc, candleW, yo - yc);

} autre {

remplir(200, 0, 0);

trait(200, 0, 0);

rect(x - candleW/2, yo, candleW, yc - yo);

}

}

*/

pour (int i = 0; i < closes.length; i++) {

float x = map(i, 0, closes.length - 1, 50, widths-50);

// cartographie Y

float yo = map(opens[i], minP, maxP, hauteur - 50, 50);

float yc = map(closes[i], minP, maxP, hauteur - 50, 50);

float yh = map(highs[i], minP, maxP, hauteur - 50, 50);

float yl = map(lows[i], minP, maxP, hauteur - 50, 50);

// largeur d’une bougie

float candleW = 4,5;

// --- Mèche ---

si (closes[i] >= opens[i])

// Bougie verte

trait(0,200,0);

autre

coup(200,0,0);

strokeWeight(1,3);

ligne(x, yh, x, yl);

pas de Stroke();

// --- Corps ---

si (closes[i] >= opens[i]) {

// Bougie verte

remplir(0, 200, 0);

trait(0, 200, 0);

rect(x - candleW/2, yc, candleW, yo - yc);

} autre {

// Bougie rouge

remplir(200, 0, 0);

trait(200, 0, 0);

rect(x - candleW/2, yo, candleW, yc - yo);

}

booléen baseHistorique = vrai ;

si ( i > 84 )

pour (int j = 0; j < 83; j++) {

si (lows[i-j-1] < lows[i]) {

basHistorique = false;

casser;

}

}

sinon baseHistorique = faux ;

si (downHistory)

{

//if (rsiC>10 && rsiC < 50-Indicateur && basHistorique){

//si (rsiC < 45 && basHistorique){

//if (rsiC < 35 && basHistorique){// && data[i]< prixHaut-20)

// Positionnez le point

float xp = map(i, 0, closes.length - 1, 50, widths-50);

float y = map(lows[i], minP, maxP, hauteur - 50, 50);

remplir(255, 0, 0,150);

pas de Stroke();

rect(xp-20, y - 40,40,40);

//ellipse(xp-5, y, 10, 10);

remplir(0, 255, 0);

textAlign(CENTRE);

//rect(x-decX, y - 8,10,10);

///bas[i]=1;

si ( bas[i] < bas[i-83])

texte("LL", xp, y - 10);

autre

texte("HL", xp, y - 10);

// bas[i]=1;

// sur un achat

//CONFIRM= vrai;

}

booléen HautHistorique = vrai;

si ( i > 84 )

pour (int j = 0; j < 83; j++) {

si (highs[i-j-1] > highs[i]) {

HautHistorique = faux ;

casser;

}

}

sinon HautHistorique = faux ;

si (HautHistorique)

{

//if (rsiC>10 && rsiC < 50-Indicateur && basHistorique){

//si (rsiC < 45 && basHistorique){

//if (rsiC < 35 && basHistorique){// && data[i]< prixHaut-20)

// Positionnez le point

float xp = map(i, 0, closes.length - 1, 50, widths-50);

float y = map(highs[i], minP, maxP, hauteur - 50, 50);

remplir(255, 255, 0,150);

pas de Stroke();

rect(xp-20, y - 40,40,40);

//ellipse(xp-5, y, 10, 10);

remplir(0, 255, 255);

textAlign(CENTRE);

//rect(x-decX, y - 8,10,10);

///bas[i]=1;

si (highs[i] > highs[i-83])

texte("HH", xp, y - 10);

autre

texte("Hl", xp, y - 10);

// bas[i]=1;

si ( i<990 )

{

float xi = map(i+9, 0, closes.length - 1, 50, widths-50);

float yi = map(highs[i+9], minP, maxP, hauteur - 50, 50);

trait(255,255,0);

ligne(xp, y, xi,yi);

}

// sur un achat

//CONFIRM= vrai;

}

//////////// les petits sommets

baseHistorique = vrai;

si (i > 9)

pour (int j = 0; j < 8; j++) {

si (lows[i-j-1] < lows[i]) {

basHistorique = false;

casser;

}

}

sinon baseHistorique = faux ;

si (downHistory)

{

//if (rsiC>10 && rsiC < 50-Indicateur && basHistorique){

//si (rsiC < 45 && basHistorique){

//if (rsiC < 35 && basHistorique){// && data[i]< prixHaut-20)

// Positionnez le point

float xp = map(i, 0, closes.length - 1, 50, widths-50);

float y = map(lows[i], minP, maxP, hauteur - 50, 50);

remplir(255, 0, 0,150);

pas de Stroke();

//rect(xp-20, y - 40,40,40);

ellipse(xp-5, y, 10, 10);

remplir(0, 255, 0);

textAlign(CENTRE);

//rect(x-decX, y - 8,10,10);

///bas[i]=1;

// si ( bas[i] < bas[i-83])

//texte("LL", xp, y - 10);

//autre

//texte("HL", xp, y - 10);

// bas[i]=1;

// sur un achat

//CONFIRM= vrai;

}

TopHistorique = vrai ;

si (i > 9)

pour (int j = 0; j < 8; j++) {

si (highs[i-j-1] > highs[i]) {

HautHistorique = faux ;

casser;

}

}

sinon HautHistorique = faux ;

si (HautHistorique)

{

//if (rsiC>10 && rsiC < 50-Indicateur && basHistorique){

//si (rsiC < 45 && basHistorique){

//if (rsiC < 35 && basHistorique){// && data[i]< prixHaut-20)

// Positionnez le point

float xp = map(i, 0, closes.length - 1, 50, widths-50);

float y = map(highs[i], minP, maxP, hauteur - 50, 50);

remplir(255, 255, 0,150);

pas de Stroke();

//rect(xp-20, y - 40,40,40);

ellipse(xp-5, y, 10, 10);

remplir(0, 255, 255);

textAlign(CENTRE);

//rect(x-decX, y - 8,10,10);

///bas[i]=1;

si (highs[i] > highs[i-7])

texte("HH", xp, y - 10);

autre

texte("Hl", xp, y - 10);

// bas[i]=1;

/*si ( i<990 )

{

float xi = map(i+9, 0, closes.length - 1, 50, widths-50);

float yi = map(highs[i+9], minP, maxP, hauteur - 50, 50);

trait(255,255,0);

ligne(xp, y, xi,yi);

}*/

// sur un achat

//CONFIRM= vrai;

}

// les resistances quand le prix n arrive pzs à monter

détecterRésistance(i, hauts, fermetures);

}

/*

pour (int i = 0; i < closes.length; i++) {

float x = map(i, 0, closes.length - 1, 50, width-50);

//float y = map(closes[i], minP, maxP, height - 50, 50);

float yh = map(highs[i], minP, maxP, hauteur - 50, 50);

float yl = map(lows[i], minP, maxP, hauteur - 50, 50);

remplir(0,255,0,123);

rect(x-10, yh,10,yh-yl);

//ouvre = nouveau float[n];

//highs = nouveau float[n];

//lows = nouveau float[n];

//fermeture = nouveau float[n];

// ordres limits

}

trait(0,0,255);

coup(25, 255, 255);

*/

strokeWeight(2);

// --- Clusters de liquidation ---

trait(255, 0, 0);

pour (int i=0; i

float lvl = liquidationClusters.get(i);

float y = map(lvl, minP, maxP, hauteur-50, 50);

ligne(50, y, largeurs-50, y);

remplir(255, 0, 0);

texte("LC x" + clusterCounts.get(i), largeurs-100, y-5);

}

/*

// --- Supports et cassures ---

pour (int i=0; i

float lvl = supports.get(i);

float y = map(lvl, minP, maxP, hauteur-50, 50);

si (supportBroken.get(i)) {

stroke(25, 50, 255); // cassure = orange

} autre {

trait(0, 200, 255); // support = vert

}

ligne(50, y, largeur-50, y);

}*/

// --- Carte thermique des clusters ---

//dessinerClusters(minP, maxP);

// --- Carte thermique des clusters ---

dessinerClusters(minP, maxP);

// --- Supports (zones vertes) ---

dessinerSupports(minP, maxP);

// --- Breaks (zones oranges épaisses) ---

dessinerPauses(minP, maxP);

//détecterLesRésistances();

//dessinerSignaux(minP, maxP);

//dessinerClusters(prixmin, prixmax);

dessinerTradeRectangles(closes, highs, lows, minP, maxP);

dessinerFVG(minP, maxP);

/*

int frIndex = fundingRates.length - 1; // partie du dernier taux de financement

// on boucle sur les bougies en partant de la fin

pour (int i = closes.length - 1; i >= 0 && frIndex >= 0; i -= 8) {

si (fundingRates[frIndex] < 0) {

float x = map(i, 0, closes.length - 1, 50, widths - 50);

fill(255, 255, 0, 70); // jaune

rect(x-5, 0, 10, height); // barre jaune sur la bougie correspondante

}

frIndex--; // on avance dans le tableau des funding

}

*/

si ( i == "1h")

///// signe du ver... pardon du short ...xP

pour (int i = 0; i < fundingRates.length; ++i) {

//for (int i = fundingRates.length; i < 1 ; --i) {

//int candleIndex = i * 8; // si ech = 1h

si (fundingRates[i] < 0) {

// on ne peux que recup 1000 fr

// float x = map(i*8 , 0, fundingRates.length-1, 50, widths-50);

float x = map(i*8- 600 , 0, closes.length-1, 50, (widths-50) );

flottant y = hauteur/2;

fill( 255, 255, 0,70); // jaune

//rect(x-5, y-5, 10, 10); // petit carré

rect(x-5, 0, 10, hauteur); // petit carré

taille du texte(33);

remplir(255);

texte( "COURT ", x-5,150);

}

}

taille du texte(12);

popMatrix();

String[] labels = {"1s", "1m", "3m", "15m", "1day", "1h", "2h"}; // texte desintervalle

int wld=0;

pour ( int i=0;i

{ remplir(i*10,255-i*10,i);

rect(i,0,100,100);

remplir(0,0,0);

texte( étiquettes[wld % étiquettes.longueur], 40+i,50);

++wld;

}

remplir(255,255,255);

texte( moi, 20, 130);

si ( sourisX < 100 && sourisY < 100 ){

i = "1s";fetchData( symbole );

}

si ( sourisX < 200 && sourisX > 100 && sourisY < 100 ){

i = "1m";fetchData( symbole );

}

si ( sourisX < 300 && sourisX > 200 && sourisY < 100 ){

i = "3m";fetchData( symbole );

}

si ( sourisX < 400 && sourisX > 300 && sourisY < 100 ){

i = "15m";

récupérerDonnées( symbole );

}

si ( sourisX < 500 && sourisX > 400 && sourisY < 100 ){

i = "1d";

récupérerDonnées( symbole ); ;

}

si ( sourisX < 600 && sourisX > 500 && sourisY < 100 ){

i = "1h";

récupérerDonnées( symbole ); ;

}

si ( sourisX < 700 && sourisX > 600 && sourisY < 100 ){

ech = "2h";

récupérerDonnées( symbole ); ;

}

si ( sourisX < 900 && sourisX > 670 && sourisY < 100 ){

i = "30m";

récupérerData(symbole);

}

//rect(largeur-100,hauteur-200,100,100);

//rect(largeur-100,hauteur-100,100,100);

//rect(largeur-200,0,largeur,300);

texte(symboles[countSymbol],largeur-150,150);

// textSize(30);

//remplir(t13?0:255,t13?255:0,0);

texte ("PRIX :" + nf(closes[999],0,2),10,hauteur-220);

rect(largeur-100,hauteur-200,100,100);

rect(largeur-100,hauteur-100,100,100);

texte ( écartMin, largeur-30, hauteur-250);

}

// --- RÉCUPÉRER LES DONNÉES ---

void fetchData(String symbol) {

//closes = new float[666];//[666]; // r������������init tableau de clôtures

supports.clear(); // on vide la liste des supports

supportBreaks.clear(); // on vide la liste des breaks

liquidationClusters.clear(); // on vide les clusters de liquidation

clusterCounts.clear();

supportBroken.clear();

URL de chaîne = "https://api.binance.com/api/v3/klines?symbol=" + symbole + "&interval="+ech+"&limit=2500" ;

essayer {

Chaîne brute = join(loadStrings(url), "");

bougies = analyserJSONArray(brut);

int n = bougies.taille();

println("bougie = "+ n);

ouvre = nouveau float[n];

hauts = nouveau float[n];

bas = nouveau float[n];

ferme = nouveau float[n];

volumes = nouveau float[n];

pour (int i = 0; i < n; i++) {

JSONArray c = candles.getJSONArray(i);

ouvre[i] = float(c.getString(1));

hauts[i] = float(c.getString(2));

bas[i] = float(c.getString(3));

closes[i] = float(c.getString(4));

volumes[i] = float(c.getString(5));

// Exemple simplifié de détection

si (supports.size() > 0) {

float lastClose = closes[i];

float prevClose = closes[i-1];

pour (int s = supports.size()-1; s >= 0; s--) {

float sprice = supports.get(s);

// condition de cassure : close passe sous le support

si (prevClose >= cible && lastClose < cible) {

supportBreaks.add(sprice);

}

}

}

}

prixActuel = closes[n-1];

ATH = max(closes);

BAS = min(fermeture);

détecter les clusters();

détecterSupports();

détecterClustersAndFVG(écartMin);

} catch (Exception e) {

println("Erreur API : " + e.getMessage());

}

}

float gapMin = 1;

// Classe pour stocker les gaps avec indices des bougies

classe Gap {

flotter bas, haut;

int startIdx, endIdx; // indices bougies

boolean bullish; // true = gap haussier, false = baissier

Gap(float l, float h, int start, int end, boolean bullishGap) {

bas = l;

haut = h;

startIdx = début;

endIdx = fin;

haussier = écart haussier ;

}

}

// Listes globales pour FVG

ArrayList fvgUp = new ArrayList();

ArrayList fvgDn = new ArrayList();

// Détection FVG (version simplifiée et testable)

void detectClustersAndFVG(float gapMin) {

fvgUp.clear();

fvgDn.clear();

pour (int i=2; i

// --- FVG haussier ---

si (lows[i] - highs[i-2] > gapMin) {

fvgUp.add(new Gap(highs[i-2], lows[i], i-2, i, true));

//ln("FVG UP:", highs[i-2], "->", lows[i], "indices", i-2, "->", i);

}

// --- FVG baissier ---

si (lows[i-2] - highs[i] > gapMin) {

fvgDn.add(new Gap(highs[i], lows[i-2], i-2, i, false));

//println("FVG DOWN:", highs[i], "->", lows[i-2], "indices", i-2, "->", i);

}

}

}

// Dessin FVG (rectangles horizontaux “bougie à bougie”)

void drawFVG(float minP, float maxP) {

pas de Stroke();

// FVG haussiers

pour (Gap g : fvgUp) {

float x1 = map(g.startIdx, 0, closes.length-1, 50, widths-50);

float x2 = map(g.endIdx, 0, closes.length-1, 50, widths-50);

float y1 = map(g.high, minP, maxP, hauteur-50, 50);

float y2 = map(g.low, minP, maxP, hauteur-50, 50);

fill(0, 255, 0, 90); // vert semi-transparent

trait(0, 180, 0);

rect(x1, min(y1,y2), max(x2-x1, 2)+100, abs(y2-y1)); // largeur minimale 2px

pas de Stroke();

remplir(255);

textAlign(GAUCHE, CENTRE);

texte("Long FVG " + nf(g.low,0,2) + "-" + nf(g.high,0,2), x1 + 3, min(y1,y2) + abs(y2-y1)/2);

}

// FVG baissiers

pour (Gap g : fvgDn) {

float x1 = map(g.startIdx, 0, closes.length-1, 50, widths-50);

float x2 = map(g.endIdx, 0, closes.length-1, 50, widths-50);

float y1 = map(g.high, minP, maxP, hauteur-50, 50);

float y2 = map(g.low, minP, maxP, hauteur-50, 50);

fill(0, 100, 255, 90); // bleu semi-transparent

trait(0, 0, 180);

rect(x1, min(y1,y2), max(x2-x1, 2)+100, abs(y2-y1)); // largeur minimale 2px

pas de Stroke();

remplir(255);

textAlign(GAUCHE, CENTRE);

texte("FVG court " + nf(g.low,0,2) + "-" + nf(g.high,0,2), x1 + 3, min(y1,y2) + abs(y2-y1)/2);

}

}

/*

on stocke les gaps comme paires (low, high)

classe Gap {

flotter bas, haut;

Gap(float l, float h) {

bas = l;

haut = h;

}

}

ArrayList fvgUp = new ArrayList();

ArrayList fvgDn = new ArrayList();

void detectClustersAndFVG() {

liquidationClusters.clear();

clusterCounts.clear();

fvgUp.clear();

fvgDn.clear();

// moyenne simple du volume

flottant volMA = 0;

pour (int i=0; i

volMA += volumes[i];

}

volMA /= volumes.length;

pour (int i=0; i

corps flottant = abs(fermeture[i]-ouverture[i]);

bougie flottante = hauts[i]-bas[i];

float wickUp = highs[i]-max(opens[i], closes[i]);

float wickDn = min(opens[i], closes[i]) - lows[i];

// --- Détection clusters liquidation ---

si (volumes[i] > volMA*volMult && bougie > 0 && corps/bougie <= minBodyRatio) {

float liquidPrice = Float.NaN;

si (wickUp/bougie >= wickRatio) prix_liquide = hauts[i];

sinon si (wickDn/candle >= wickRatio) liquidPrice = lows[i];

si (!Float.isNaN(liquidPrice)) ajouterCluster(liquidPrice);

}

*/

/*

// --- Détection des Fair Value Gaps (FVG) ---

si (i >= 2) {

// FVG haussier (low actuel > high d�����������������il y a 2 bougies)

si (bas[i] > hauts[i-2]) {

//fvgUp.add(new Gap(highs[i-2], lows[i]));

fvgUp.add(new Gap(highs[i-2], lows[i]));

//fvgDn.add(new Gap(highs[i], lows[i-2]));

}

// FVG baissier (high actuel < low d’il y a 2 bougies)

si (hauts[i] < bas[i-2]) {

// fvgDn.add(new Gap(highs[i], lows[i-2]));

// fvgUp.add(new Gap(highs[i-2], lows[i]));

fvgDn.add(new Gap(highs[i], lows[i-2]));

}

}

*/

/*

float gapMin = 1000; // tolérance minimale pour consid��������rer un FVG

si (i >= 2) {

// FVG haussier

si (lows[i] - highs[i-2] > gapMin) {

fvgUp.add(new Gap(highs[i-2], lows[i]));

println("FVG UP:", highs[i-2], "->", lows[i]);

}

// FVG baissier

si (lows[i-2] - highs[i] > gapMin) {

fvgDn.add(new Gap(highs[i], lows[i-2]));

println("FVG DOWN:", highs[i], "->", lows[i-2]);

}

}

}

}

void drawFVG(float minP, float maxP) {

pas de Stroke();

// FVG haussiers vert

pour (Gap g : fvgUp) {

float y1 = map(g.high, minP, maxP, hauteur-50, 50);

float y2 = map(g.low, minP, maxP, hauteur-50, 50);

coup(255);

remplir(0, 255, 0); // vert transparent

rect(50, y1, largeurs-100, y2-y1);

remplir(0, 180);

texte("FVG" + nf(g.low,0,2)+"-"+nf(g.high,0,2), largeurs-490, y1+12);

}

// FVG baissiers bleu

pour (Gap g : fvgDn) {

float y1 = map(g.high, minP, maxP, hauteur-50, 50);

float y2 = map(g.low, minP, maxP, hauteur-50, 50);

coup(255,0,0);

remplir(0, 100, 255); // bleu transparent

rect(50, y1, largeurs-100, y2-y1);

remplir(0, 180);

texte("FVG" + nf(g.low,0,2)+"-"+nf(g.high,0,2), largeurs-490, y1+12);

}

}

*/

// --- DÉTECTION DES AMPLOTS DE LIQUIDATION ---

void detectClusters() {

liquidationClusters.clear();

clusterCounts.clear();

// moyenne simple du volume

flottant volMA = 0;

pour (int i=0; i

volMA += volumes[i];

}

volMA /= volumes.length;

pour (int i=0; i

corps flottant = abs(fermeture[i]-ouverture[i]);

bougie flottante = hauts[i]-bas[i];

float wickUp = highs[i]-max(opens[i], closes[i]);

float wickDn = min(opens[i], closes[i]) - lows[i];

si (volumes[i] > volMA*volMult && bougie > 0 && corps/bougie <= minBodyRatio) {

float liquidPrice = Float.NaN;

si (wickUp/bougie >= wickRatio) prix_liquide = hauts[i];

sinon si (wickDn/candle >= wickRatio) liquidPrice = lows[i];

si (!Float.isNaN(liquidPrice)) ajouterCluster(liquidPrice);

}

}

}

// --- Grouper les clusters proches ---

void ajouterCluster(prix flottant) {

pour (int i=0; i

si (abs(liquidationClusters.get(i) - prix) <= proximitéPts) {

// incrémenter

clusterCounts.set(i, clusterCounts.get(i)+1);

retour;

}

}

liquidationClusters.add(prix);

clusterCounts.add(1);

}

// --- DÉTECTION DES SUPPORTS ET DES RUPTURES ---

void detectSupports() {

supports.clear();

supportBroken.clear();

pour (int i=pivotLeft; i

booléen isPivot = vrai ;

pour (int j=1; j<=pivotLeft; j++) si (lows[i] >= lows[i-j]) isPivot=false;

pour (int j=1; j<=pivotRight; j++) si (lows[i] >= lows[i+j]) isPivot=false;

si (estPivot) {

flottant s = bas[i];

supports.add(s);

// cassure ?

booléen cassé = (fermeture[fermeture.longueur-1] < s);

supportBroken.add(broken);

}

}

}

// --- Clusters de liquidation en heatmap ---

void dessinerClusters(float minP, float maxP) {

pas de Stroke();

pour (int i=0; i

float lvl = liquidationClusters.get(i);

int count = clusterCounts.get(i);

// mapping du prix vers y

float y = map(lvl, minP, maxP, hauteur-50, 50);

// intensit�� proportionnelle au nombre d’occurrences

int alpha = contrainte(40 + count*30, 40, 200);

int rectHeight = 6 + count*2; // ��������passeur de zone

remplir(255, 0, 0, alpha);

rect(50, y - rectHeight/2, largeurs-100, rectHeight);

// texte discret à droite

remplir(255, 200);

texte(lvl+ " Liquidation cluster x" + count, largeurs-490, y-5);

}

}

// --- Supports (zones vertes) ---

void drawSupports(float minP, float maxP) {

pas de Stroke();

pour (int i=0; i

float lvl = supports.get(i);

float y = map(lvl, minP, maxP, hauteur-50, 50);

fill(0, 200, 0, 100); // vert translucide

rect(50, y-3, largeurs-100, 6);

remplir(0, 255, 0);

texte(lvl+" Support", 60, y-5);

}

}

// --- Breaks de support (zones oranges ����������������������������paisses) ---

void drawBreaks(float minP, float maxP) {

pas de Stroke();

pour (int i=0; i

float lvl = supportBreaks.get(i);

float y = map(lvl, minP, maxP, hauteur-50, 50);

remplir(255, 140, 0, 150); // orange semi-opaque

rect(50, y-4, largeurs-100, 8);

remplir(255, 180, 0);

texte("Rupture de support", 60, y-6);

}

}

///////#######

// --- Analyse clusters pour zones d'achat/vente ---

float clusterZoneMargin = 5f; // marge autour du cluster pour dessiner la zone

void dessinerZonesDeGroupement(float minP, float maxP) {

pour (int i=0; i

float lvl = liquidationClusters.get(i);

int count = clusterCounts.get(i);

// Cartographie du prix -> et

float y = map(lvl, minP, maxP, hauteur-50, 50);

// Définir couleur selon tendance (ex: mèche haute = vente, mèche basse = achat)

float wickUp = highs[i] - max(opens[i], closes[i]);

float wickDn = min(opens[i], closes[i]) - lows[i];

boolean isBuyZone = wickDn > wickUp; // plus grande mèche basse

booléen isSellZone = mècheUp > mècheDn; // mèche plus haute et plus grande

// Ajuster opacité et épaisseur selon le nombre d’occurrences

int alpha = contrainte(60 + count*30, 60, 200);

int rectHeight = 6 + count*2;

si (isBuyZone) {

remplir(0, 0, 255, alpha);

rect(50, y - clusterZoneMargin, largeurs-100, clusterZoneMargin*2);

remplir(0, 0, 255);

texte("Achat x"+count, largeurs-180, y);

}

si (isSellZone) {

remplir(255, 0, 0, alpha);

rect(50, y - clusterZoneMargin, largeurs-100, clusterZoneMargin*2);

remplir(255, 0, 0);

texte("Vente x"+count, largeurs-180, y);

}

}

}

////////€€

// --- Paramètres ---

float rsiOverbought = 70f;

flottant rsiOversold = 45f;

int rsiLength = 27; // longueur RSI

int shortTrendLength = 33; // nb bougies pour calculer tendance courte

float rectMargin = 10f; // épaisseur du rectangle

// --- Calcul simple du RSI ---

float calcRSI(float[] closes, int idx, int length) {

if (idx < length) return 50; // valeur neutre si pas assez de données

gain flottant = 0, perte = 0 ;

pour (int i=idx-length+1; i<=idx; i++) {

float diff = closes[i] - closes[i-1];

si (diff > 0) gain += diff;

sinon perte -= diff;

}

si (perte == 0) retourner 100 ;

retourner 100 - (100 / (1 + gain/perte));

}

// --- Détection tendance courte ---

booléen isShortDowntrend(float[] closes, int idx, int len) {

si (idx < len) retourner faux ;

renvoie closes[idx] < closes[idx-len];

}

booléen isShortUptrend(float[] closes, int idx, int len) {

si (idx < len) retourner faux ;

retourner closes[idx] > closes[idx-len];

}

void drawTradeRectangles(float[] closes, float[] highs, float[] lows, float minP, float maxP) {

pour (int i=shortTrendLength; i

float rsi = calcRSI(closes, i, rsiLength);

// Calcul position X selon timeline

float x = map(i, 0, closes.length-1, 50, widths-50);

// --- Signal vente ---

si (rsi >= rsiOverbought && isShortDowntrend(closes, i, shortTrendLength)) {

float recentHigh = highs[i];

float y = map(recentHigh, minP, maxP, hauteur-50, 50);

remplir(255, 0, 0, 80);

rect(x-10, y-rectMargin, 20, rectMargin*2); // rectangle centré sur x

remplir(255, 0, 0);

text("S", x, y-rectMargin-5); // texte juste au-dessus du rectangle

}

// --- Signal achat ---

si (rsi <= rsiOversold && isShortUptrend(closes, i, shortTrendLength)) {

float recentLow = lows[i];

float y = map(recentLow, minP, maxP, hauteur-50, 50);

remplir(0, 0, 255, 80);

rect(x-10, y-rectMargin, 20, rectMargin*2); // rectangle centré sur x

remplir(0, 0, 255);

text("B", x, y-rectMargin-5); // texte juste au-dessus du rectangle

}

}

}