// --- 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
}
}
}