// --- ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ---

Массив candles;

float[] opens, highs, lows, closes, volumes;

float prixActuel, ATH , LOW= 0;

String ech = "1m";

ArrayList liquidationClusters = new ArrayList();

ArrayList clusterCounts = new ArrayList();

//ArrayList supports = new ArrayList();

ArrayList supportBroken = new ArrayList();

int random= 0;

ArrayList supports = new ArrayList();

ArrayList supportBreaks = new ArrayList();

String symbol = "BTCUSDT";

int countSymbol=1;

String[] symbols = {

"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 resistances = new ArrayList();

float fundingRates[] ;//= fetchFundingRates(symbol, 1000); // Ставки финансирования 1000 дернир

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

float[] rates = new float[limit];

String url = "https://fapi.binance.com/fapi/v1/fundingRate?symbol=" + symbol + "&limit=" + limit;

пытаться {

String raw = join(loadStrings(url), "");

JSONArray arr = parseJSONArray(raw);

println("Название фонда: " + arr.size());

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

JSONObject obj = arr.getJSONObject(i);

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

if ( rates[i] < 0) println( " detecteeeeee");

}

} catch(Exception e) {

println("Ошибка при получении ставок финансирования: " + e);

}

процент возврата;

}

// --- ПАРАМЕТРЫ (аналогичные вашим входам Pine) ---

int lookbackVol = 50;

float volMult = 2.5;

float wickRatio = 0.6f;

float minBodyRatio = 0.1f;

float proximityPts = 20f; // допуск для группировки кластеров

int pivotLeft = 5;

int pivotRight = 5;

int interval = 1000; // 1000 мс = 1 секунда

int lastUpdate = 0;

целочисленные ширины;

// --- Расчет EMA ---

float[] ema(float[] data, int period) {

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

float alpha = 2.0 / (period + 1.0);

// Инициализация: начинаем с первого исходного значения

ema[0] = data[0];

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

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

}

вернуть эма;

}

// --- НАСТРАИВАТЬ ---

void setup() {

//size(1200, 800);

полноэкранный();

//size(int(displayWidth*2),int( displayHeight));

symbol = symbols[countSymbol];

fetchData( symbol );

widths = int(width*8.7); //8.1

fundingRates = fetchFundingRates(symbol, 1000); // Последние 1000 ставок финансирования

//frameRate(1);

// При желании измените символ.

}

float startDist;

float zoom = 1.0;

float offsetX = 0;

float offsetY = 0;

void touchStarted() {

if (touches.length == 2) {

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

}

}

void touchMoved() {

if (touches.length == 2) {

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

float d = newDist / startDist;

zoom *= d;

zoom = constrain(zoom, 0.1, 10); // ограничивает масштабирование

startDist = newDist;

} else if (touches.length == 1) {

offsetX += (touches[0].x - pmouseX) / zoom;

offsetY += (touches[0].y - pmouseY) / zoom;

}

}

// Перетаскивание мышью (полезно для тестирования на ПК)

void mouseDragged() {

offsetX += (mouseX - pmouseX) / zoom;

offsetY += (mouseY - pmouseY) / zoom;

if ( mouseX < width && mouseX > width-100 && mouseY > height-200 && mouseY < height-100){

++gapMin;

}

if ( mouseX < width && mouseX > width-100 && mouseY > height-100 && mouseY < height){

--gapMin;

}

}

void mousePressed()

{

//++countSymbol;

//fill(255);

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

if ( mouseX > width-200 && mouseY < 300 && mouseY >100 )

++countSymbol;

if ( mouseX > width-200 && mouseY < 500 && mouseY >300 )

--countSymbol;

если (countSymbol<0)

countSymbol =0;

если (countSymbol>101)

countSymbol =0;

//text(symbols[countSymbol],width-150,150);

symbol = symbols[countSymbol];

}

void mouseReleased()

{

if ( mouseX < width && mouseX > width-100 && mouseY > height-200 && mouseY < height-100){

++gapMin;

}

if ( mouseX < width && mouseX > width-100 && mouseY > height-100 && mouseY < height){

--gapMin;

}

}

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

if (i < period) return 50; // значение по умолчанию, если данных недостаточно

Коэффициент прироста по плавающей запятой = 0, коэффициент потерь = 0;

for (int j = 1; j <= period; j++) {

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

если (изменение > 0) выигрыш += изменение;

иначе потеря -= изменение;

}

float avgGain = gain / period;

float avgLoss = loss / period;

if (avgLoss == 0) return 100; // Максимальный RSI, если нет потерь

float rs = avgGain / avgLoss;

вернуть 100 - (100 / (1 + rs));

}

int n = 30; // размер окна

float tolerance = 100.5; // отступ для обозначения "достижения потолка"

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

if (i < n) return; // пока недостаточно данных

// Мы берем максимальное значение за последние n свечей

float maxRecent = highs[i];

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

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

maxRecent = highs[i - j];

}

}

// Мы подсчитываем, сколько раз цена "достигла" максимума

int touchess = 0;

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

if (abs(highs[i - j] - maxRecent) < tolerance) {

touchess++;

}

}

// Расчет RSI не отображается

// продавать на самом дне

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

// Если температура поднимается часто, но не превышает 100°C, подавайте сигнал.

if (touchess > 2 && closes[i] < highs[i] - tolerance && 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);

fill(255, 255, 0, 150);

noStroke();

rect(xp, y, 30, 15);

//fill(255);

textAlign(CENTER);

text("КОРОТКО ×100", xp, y - 10);

}

}

// --- ЦИКЛ РИСОВАНИЯ ---

void draw() {

random =0;

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

//fetchData(symbol); // Обновляем данные

/*closes = new float[666]; // сбрасывает массив замыканий

supports.clear(); // Мы очищаем список опор

supportBreaks.clear(); // очистить список перерывов

liquidationClusters.clear(); // мы удаляем кластеры ликвидации

clusterCounts.clear();

supportBroken.clear();*/

symbol = symbols[countSymbol];

fetchData( symbol );

lastUpdate = millis(); // Сбрасываем счетчик до нуля

}

pushMatrix();

translate(width/2 + offsetX*zoom, height/2 + offsetY*zoom-400);

//translate(width/2 + offsetX, height/2 + offsetY-400);

масштабирование(zoom);

//fetchData("BTCUSDT");

фон(20);

инсульт(255);

fill(200);

// Вертикальные ограничения для масштабирования

float maxP = max(closes);;

float minP = min(closes);

/*

for (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, height - 50, 50);

fill(255, 25, 255,150);

noStroke();

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

}

for (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, height - 50, 50);

fill(25, 255, 255,150);

noStroke();

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

}

*/

// --- СЛЕДУЮЩИЙ ---

stroke(255, 255, 0);

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

линия(50, yATH, ширина-50, yATH);

fill(255, 255, 0);

текст("ATH " + ATH, 55, yATH-5);

fill(255,0,0,55);rect(50,yATH,widths,100);

// --- СЛЕДУЮЩИЙ ---

stroke(25, 255, 255);

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

линия(50, yATH, ширина-50, yATH);

fill(255, 255, 0);

text("LOW " + LOW, 55, yATH-5);

fill(0,255,0,55);rect(50,yATH,widths,-100);

// График цены (линейный график закрытия)

/*

for (int i=1; i

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

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

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

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

stroke(180);

strokeWeight(2);

line(x1, y1, x2, y2);

opens = new float[n];

highs = new float[n];

lows = new float[n];

closes = new float[n];

}*/

strokeWeight(1.3);

fill(223,12);

beginShape();

for (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, height - 50, 50);

вершина(x, y);

// лимитные ордера

}

endShape();

noStroke();

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

strokeWeight(3);

noFill();

for (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, height-50, 50);

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

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

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

stroke(0, 255, 0); // вертикально, если вверх

} еще {

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

}

line(x1 , y1, x2 , y2);

}

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

strokeWeight(3);

noFill();

for (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, height-50, 50);

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

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

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

stroke(0, 255, 0); // вертикально, если вверх

} еще {

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

}

line(x1 , y1, x2 , y2);

}

/*

// ширина каждой свечи + пространство

плавающая свечаW = 5;

float spacing = 2; // расстояние между свечами

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

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

// X с обычным интервалом

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

// отображение Y

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

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

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

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

// --- Фитиль ---

stroke(200);

line(x, yh, x, yl);

// --- Корпус ---

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

fill(0, 200, 0);

stroke(0, 200, 0);

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

} еще {

fill(200, 0, 0);

stroke(200, 0, 0);

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

}

}

*/

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

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

// отображение Y

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

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

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

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

// ширина свечи

float candleW = 4.5;

// --- Фитиль ---

если (closes[i] >= opens[i])

// Зелёная свеча

stroke(0,200,0);

еще

stroke(200,0,0);

strokeWeight(1.3);

line(x, yh, x, yl);

noStroke();

// --- Корпус ---

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

// Зелёная свеча

fill(0, 200, 0);

stroke(0, 200, 0);

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

} еще {

Красная свеча

fill(200, 0, 0);

stroke(200, 0, 0);

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

}

логическое значение baseHistorique = true;

если ( i > 84)

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

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

basHistorique = false;

перерыв;

}

}

иначе baseHistorique = false;

if (downHistory)

{

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

//если (rsiC < 45 && basHistorique){

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

// Укажите желаемое положение

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

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

fill(255, 0, 0,150);

noStroke();

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

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

fill(0, 255, 0);

textAlign(CENTER);

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

///bas[i]=1;

если ( lows[i] < lows[i-83])

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

еще

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

// bas[i]=1;

// при покупке

//CONFIRM= true;

}

логическое значение HautHistorique = true;

если ( i > 84)

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

если (highs[i-j-1] > highs[i]) {

HautHistorique = false;

перерыв;

}

}

иначе HautHistorique = false;

если (HautHistorique)

{

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

//если (rsiC < 45 && basHistorique){

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

// Расположите точку

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

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

fill(255, 255, 0,150);

noStroke();

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

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

fill(0, 255, 255);

textAlign(CENTER);

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

///bas[i]=1;

если ( highs[i] > highs[i-83])

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

еще

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

// bas[i]=1;

если ( i<990)

{

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

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

stroke(255,255,0);

линия (xp, y, xi, yi);

}

// при покупке

//CONFIRM= true;

}

//////////// небольшие вершины

baseHistorique = true;

если ( i > 9)

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

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

basHistorique = false;

перерыв;

}

}

иначе baseHistorique = false;

if (downHistory)

{

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

//если (rsiC < 45 && basHistorique){

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

// Расположите точку

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

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

fill(255, 0, 0,150);

noStroke();

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

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

fill(0, 255, 0);

textAlign(CENTER);

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

///bas[i]=1;

// если ( lows[i] < lows[i-83])

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

//еще

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

// bas[i]=1;

// при покупке

//CONFIRM= true;

}

TopHistorical = true;

если ( i > 9)

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

если (highs[i-j-1] > highs[i]) {

HautHistorique = false;

перерыв;

}

}

иначе HautHistorique = false;

если (HautHistorique)

{

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

//если (rsiC < 45 && basHistorique){

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

// Укажите желаемое положение

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

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

fill(255, 255, 0,150);

noStroke();

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

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

fill(0, 255, 255);

textAlign(CENTER);

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

///bas[i]=1;

если ( highs[i] > highs[i-7])

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

еще

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

// bas[i]=1;

/*if ( i<990)

{

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

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

stroke(255,255,0);

линия (xp, y, xi, yi);

}*/

// при покупке

//CONFIRM= true;

}

// Уровни сопротивления, при которых цена не поднимается

detectResistance(i, highs, closes);

}

/*

for (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, height - 50, 50);

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

fill(0,255,0,123);

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

//opens = new float[n];

//highs = new float[n];

//lows = new float[n];

//closes = new float[n];

// лимитные ордера

}

stroke(0,0,255);

stroke(25, 255, 255);

*/

strokeWeight(2);

// --- Ликвидационные кластеры ---

stroke(255, 0, 0);

for (int i=0; i

float lvl = liquidationClusters.get(i);

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

line(50, y, widths-50, y);

fill(255, 0, 0);

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

}

/*

// --- Опоры и разрывы ---

for (int i=0; i

float lvl = supports.get(i);

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

if (supportBroken.get(i)) {

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

} еще {

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

}

line(50, y, width-50, y);

}*/

// --- Тепловая карта кластеров ---

//drawClusters(minP, maxP);

// --- Тепловая карта кластеров ---

drawClusters(minP, maxP);

// --- Опоры (зеленые зоны) ---

drawSupports(minP, maxP);

// --- Разрывы (толстые оранжевые области) ---

drawBreaks(minP, maxP);

//detectResistances();

//drawSignals(minP, maxP);

//drawClusters(minPrice, maxPrice);

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

drawFVG(minP, maxP);

/*

int frIndex = fundingRates.length - 1; // on part du dernier funding rate

// Мы перебираем свечи, начиная с конца.

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

if (fundingRates[frIndex] < 0) {

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

fill(255, 255, 0, 70); // желтый

rect(x-5, 0, 10, height); // желтая полоса на соответствующей свече

}

frIndex--; // мы продвигаемся дальше в таблице финансирования

}

*/

если ( i == "1h")

///// Признак червя... извините, шорты... xP

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

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

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

if (fundingRates[i] < 0) {

// Мы можем вернуть только 1000 франков

// 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) );

float y = высота/2;

fill(255, 255, 0, 70); // желтый

//rect(x-5, y-5, 10, 10); // маленький квадрат

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

textSize(33);

fill(255);

text( "КОРОТКИЙ ", x-5,150);

}

}

textSize(12);

popMatrix();

String[] labels = {"1s", "1m", "3m", "15m","1day","1h","2h"}; // текст интервалов

int wld=0;

for ( int i=0;i

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

rect(i,0,100,100);

fill(0,0,0);

текст( метки[wld % метки.длина], 40+i,50);

++wld;

}

fill(255,255,255);

текст( меня, 20, 130);

if ( mouseX < 100 && mouseY < 100 ){

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

}

if ( mouseX < 200 && mouseX > 100 && mouseY < 100 ){

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

}

if ( mouseX < 300 && mouseX > 200 && mouseY < 100 ){

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

}

if ( mouseX < 400 && mouseX > 300 && mouseY < 100 ){

i = "15м";

fetchData( symbol );

}

if ( mouseX < 500 && mouseX > 400 && mouseY < 100 ){

i = "1d";

fetchData( symbol ); ;

}

if ( mouseX < 600 && mouseX > 500 && mouseY < 100 ){

i = "1h";

fetchData( symbol ); ;

}

if ( mouseX < 700 && mouseX > 600 && mouseY < 100 ){

ech = "2h";

fetchData( symbol ); ;

}

if ( mouseX < 900 && mouseX > 670 && mouseY < 100 ){

i = "30м";

fetchData(symbol);

}

//rect(width-100,height-200,100,100);

//rect(width-100,height-100,100,100);

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

текст(символы[countSymbol], ширина - 150, 150);

// textSize(30);

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

текст ("ЦЕНА :" + nf(closes[999],0,2),10,height-220);

rect(width-100,height-200,100,100);

rect(width-100,height-100,100,100);

текст ( gapMin, ширина-30, высота-250);

}

// --- ПОЛУЧЕНИЕ ДАННЫХ ---

void fetchData(String symbol) {

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

supports.clear(); // Мы очищаем список опор

supportBreaks.clear(); // очистить список перерывов

liquidationClusters.clear(); // мы удаляем кластеры ликвидации

clusterCounts.clear();

supportBroken.clear();

Строковый URL = "https://api.binance.com/api/v3/klines?symbol=" + символ + "&interval="+ech+"&limit=2500";

пытаться {

String raw = join(loadStrings(url), "");

candles = parseJSONArray(raw);

int n = candles.size();

println("свеча = "+ n);

opens = new float[n];

highs = new float[n];

lows = new float[n];

closes = new float[n];

volumes = new float[n];

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

JSONArray c = candles.getJSONArray(i);

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

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

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

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

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

// Упрощенный пример обнаружения

if (supports.size() > 0) {

float lastClose = closes[i];

float prevClose = closes[i-1];

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

float price = supports.get(s);

// Условие разрыва: закрытый проход проходит под опорой

if (prevClose >= target && lastClose < target) {

supportBreaks.add(sprice);

}

}

}

}

prixActuel = closes[n-1];

ATH = max(closes);

НИЗКИЙ = минимум (закрывается);

detectClusters();

detectSupports();

detectClustersAndFVG(gapMin);

} catch (Exception e) {

println("Ошибка API: " + e.getMessage());

}

}

float gapMin = 1;

// Класс для хранения разрывов между свечами и индексами свечей

класс Gap {

плавать низко, высоко;

int startIdx, endIdx; // индексы свечей

логическое значение: бычий; // true = бычий разрыв, false = медвежий

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

низкий = л;

высокий = ч;

startIdx = start;

endIdx = end;

бычий = бычий разрыв;

}

}

// Глобальные списки для FVG

ArrayList fvgUp = new ArrayList();

ArrayList fvgDn = new ArrayList();

// Обнаружение FVG (упрощенная и проверяемая версия)

void detectClustersAndFVG(float gapMin) {

fvgUp.clear();

fvgDn.clear();

for (int i=2; i

// --- FVG настроен оптимистично ---

if (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 ---

if (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);

}

}

}

// Рисунок в формате FVG (горизонтальные прямоугольники «от свечи к свече»)

void drawFVG(float minP, float maxP) {

noStroke();

// FVG бычий тренд

for (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, height-50, 50);

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

fill(0, 255, 0, 90); // вертикальный полупрозрачный

stroke(0, 180, 0);

rect(x1, min(y1,y2), max(x2-x1, 2)+100, abs(y2-y1)); // минимальная ширина 2px

noStroke();

fill(255);

textAlign(LEFT, CENTER);

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

}

// FVG медвежий

for (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, height-50, 50);

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

fill(0, 100, 255, 90); // полупрозрачный синий

stroke(0, 0, 180);

rect(x1, min(y1,y2), max(x2-x1, 2)+100, abs(y2-y1)); // минимальная ширина 2px

noStroke();

fill(255);

textAlign(LEFT, CENTER);

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

}

}

/*

Мы храним пробелы парами (низкий, высокий).

класс Gap {

плавать низко, высоко;

Gap(float l, float h) {

низкий = л;

высокий = ч;

}

}

ArrayList fvgUp = new ArrayList();

ArrayList fvgDn = new ArrayList();

void detectClustersAndFVG() {

liquidationClusters.clear();

clusterCounts.clear();

fvgUp.clear();

fvgDn.clear();

// простое среднее значение объема

float volMA = 0;

for (int i=0; i

volMA += volumes[i];

}

volMA /= volumes.length;

for (int i=0; i

float body = abs(closes[i]-opens[i]);

плавающая свеча = максимумы[i]-минимумы[i];

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

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

// --- Ликвидация кластерного обнаружения ---

if (volumes[i] > volMA*volMult && candle > 0 && body/candle <= minBodyRatio) {

float liquidPrice = Float.NaN;

if (wickUp/candle >= wickRatio) liquidPrice = highs[i];

else if (wickDn/candle >= wickRatio) liquidPrice = lows[i];

if (!Float.isNaN(liquidPrice)) addCluster(liquidPrice);

}

*/

/*

// --- Обнаружение разрывов в справедливой стоимости (FVG) ---

если (i >= 2) {

// Бычий тренд FVG (текущий минимум > максимум двух свечей назад)

если (lows[i] > highs[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 медвежий тренд (текущий максимум равен минимуму двух свечей назад)

if (highs[i] < lows[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; // минимальный допуск для учета FVG

если (i >= 2) {

// FVG бычий тренд

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

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

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

}

// FVG медвежий

if (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) {

noStroke();

// FVG бычий зеленый

for (Gap g : fvgUp) {

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

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

инсульт(255);

fill(0, 255, 0); // вертикальный прозрачный

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

fill(0, 180);

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

}

// Синие медведи FVG

for (Gap g : fvgDn) {

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

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

stroke(255,0,0);

fill(0, 100, 255); // синий прозрачный

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

fill(0, 180);

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

}

}

*/

// --- ОБНАРУЖЕНИЕ КЛАСТЕРОВ ЛИКВИДАЦИИ ---

void detectClusters() {

liquidationClusters.clear();

clusterCounts.clear();

// простое среднее значение объема

float volMA = 0;

for (int i=0; i

volMA += volumes[i];

}

volMA /= volumes.length;

for (int i=0; i

float body = abs(closes[i]-opens[i]);

плавающая свеча = максимумы[i]-минимумы[i];

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

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

if (volumes[i] > volMA*volMult && candle > 0 && body/candle <= minBodyRatio) {

float liquidPrice = Float.NaN;

if (wickUp/candle >= wickRatio) liquidPrice = highs[i];

else if (wickDn/candle >= wickRatio) liquidPrice = lows[i];

if (!Float.isNaN(liquidPrice)) addCluster(liquidPrice);

}

}

}

// --- Сгруппировать близлежащие кластеры ---

void addCluster(float price) {

for (int i=0; i

if (abs(liquidationClusters.get(i) - price) <= proximityPts) {

// увеличение

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

возвращаться;

}

}

liquidationClusters.add(price);

clusterCounts.add(1);

}

// --- ОБНАРУЖЕНИЕ ОПОР И РАЗРЫВОВ ---

void detectSupports() {

supports.clear();

supportBroken.clear();

for (int i=pivotLeft; i

boolean isPivot = true;

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

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

if (isPivot) {

float s = lows[i];

supports.add(s);

// перерыв?

boolean broken = (closes[closes.length-1] < s);

supportBroken.add(broken);

}

}

}

// --- Тепловая карта ликвидационных кластеров ---

void drawClusters(float minP, float maxP) {

noStroke();

for (int i=0; i

float lvl = liquidationClusters.get(i);

int count = clusterCounts.get(i);

// сопоставление цены с y

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

// Интенсивность пропорциональна количеству вхождений

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

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

fill(255, 0, 0, alpha);

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

// незаметный текст справа

fill(255, 200);

text(lvl+ "Кластер ликвидации x" + count, widths-490, y-5);

}

}

// --- Опоры (зеленые зоны) ---

void drawSupports(float minP, float maxP) {

noStroke();

for (int i=0; i

float lvl = supports.get(i);

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

fill(0, 200, 0, 100); // полупрозрачный зеленый

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

fill(0, 255, 0);

text(lvl+" Поддержка", 60, y-5);

}

}

// --- Опорные точки (толстые оранжевые области) ---

void drawBreaks(float minP, float maxP) {

noStroke();

for (int i=0; i

float lvl = supportBreaks.get(i);

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

fill(255, 140, 0, 150); // оранжевый полупрозрачный

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

fill(255, 180, 0);

text("Support Break", 60, y-6);

}

}

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

// --- Кластерный анализ зон купли/продажи ---

float clusterZoneMargin = 5f; // отступ вокруг кластера для отрисовки зоны

void drawClusterZones(float minP, float maxP) {

for (int i=0; i

float lvl = liquidationClusters.get(i);

int count = clusterCounts.get(i);

// Сопоставление цены -> и

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

// Определяйте цвет в соответствии с трендом (например, яркие блики = распродажа, светлые блики = покупка)

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

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

boolean isBuyZone = wickDn > wickUp; // больший нижний фитиль

boolean isSellZone = wickUp > wickDn; // больший, более высокий фитиль

// Отрегулируйте прозрачность и толщину в зависимости от количества вхождений

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

int rectHeight = 6 + count*2;

if (isBuyZone) {

fill(0, 0, 255, alpha);

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

fill(0, 0, 255);

text("Achat x"+count, widths-180, y);

}

if (isSellZone) {

fill(255, 0, 0, alpha);

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

fill(255, 0, 0);

text("Vente x"+count, widths-180, y);

}

}

}

////////€€

// --- Настройки ---

float rsiOverbought = 70f;

float rsiOversold = 45f;

int rsiLength = 27; // Длина RSI

int shortTrendLength = 33; // количество свечей для расчета краткосрочного тренда

float rectMargin = 10f; // толщина прямоугольника

// --- Простой расчет RSI ---

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

if (idx < length) return 50; // нейтральное значение, если данных недостаточно

Коэффициент прироста по плавающей запятой = 0, коэффициент потерь = 0;

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

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

если (разница > 0) gain += diff;

иначе потеря -= разница;

}

Если потеря равна 0, вернуть 100;

возврат 100 - (100 / (1 + прибыль/убыток));

}

// --- Выявление краткосрочных трендов ---

boolean isShortDowntrend(float[] closes, int idx, int len) {

if (idx < len) return false;

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

}

boolean isShortUptrend(float[] closes, int idx, int len) {

if (idx < len) return false;

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

}

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

for (int i=shortTrendLength; i

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

// Расчет положения по оси X в соответствии с временной шкалой

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

// --- Сигнал о продаже ---

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

float recentHigh = highs[i];

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

fill(255, 0, 0, 80);

rect(x-10, y-rectMargin, 20, rectMargin*2); // прямоугольник, центрированный по оси x

fill(255, 0, 0);

text("S", x, y-rectMargin-5); // текст непосредственно над прямоугольником

}

// --- Сигнал на покупку ---

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

float recentLow = lows[i];

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

fill(0, 0, 255, 80);

rect(x-10, y-rectMargin, 20, rectMargin*2); // прямоугольник, центрированный по оси x

fill(0, 0, 255);

text("B", x, y-rectMargin-5); // текст непосредственно над прямоугольником

}

}

}