// --- VARIÁVEIS GLOBAIS ---
JSONArray velas;
float[] aberturas, máximas, mínimas, fechamentos, volumes;
float preçoAtual, ATH , LOW= 0;
String ech = "1m";
ArrayList clustersLiquidação = new ArrayList();
ArrayList contagensCluster = new ArrayList();
//ArrayList suportes = new ArrayList();
ArrayList suporteQuebrado = new ArrayList();
int aleatório= 0;
ArrayList suportes = new ArrayList();
ArrayList quebrasSuporte = new ArrayList();
String símbolo = "BTCUSDT";
int contagemSímbolo=1;
String[] símbolos = {
"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); // Taxas de financiamento de 1000 derniers
float[] fetchFundingRates(String symbol, int limit) {
float[] taxas = novo float[limite];
String url = "https://fapi.generallink.top/fapi/v1/fundingRate?symbol=" + symbol + "&limit=" + limit;
tentar {
String raw = join(loadStrings(url), "");
JSONArray arr = parseJSONArray(raw);
println(" nome do financiamento: "+ arr.size());
para (int i = 0; i < arr.size(); i++) {
JSONObject obj = arr.getJSONObject(i);
taxas[i] = float(obj.getString("taxaDeFundamento"));
se ( taxas[i] < 0) println( " detecteeeee");
}
} catch(Exception e) {
println("Erro ao buscar taxas de financiamento: " + e);
}
taxas de retorno;
}
// --- PARÂMETROS (como suas entradas Pine) ---
int lookbackVol = 50;
float volMult = 2.5;
float wickRatio = 0.6f;
float minBodyRatio = 0.1f;
float proximityPts = 20f; // tolerância para agrupamento de clusters
int pivotLeft = 5;
int pivotRight = 5;
int interval = 1000; // 1000 ms = 1 segundo
int últimaAtualização = 0;
larguras inteiras;
// --- Cálculo da EMA ---
float[] ema(float[] data, int period) {
float[] ema = new float[data.length];
float alpha = 2.0 / (período + 1.0);
// Inicialização: começamos com o primeiro valor bruto
ema[0] = data[0];
para (int i = 1; i < data.length; i++) {
ema[i] = alpha * data[i] + (1 - alpha) * ema[i-1];
}
retornar ema;
}
// --- CONFIGURAR ---
void setup() {
//tamanho(1200, 800);
tela cheia();
//tamanho(int(larguraExibição*2),int(alturaExibição));
símbolo = símbolos[contagemSímbolo];
buscarDados( símbolo );
larguras = int(largura*8.7);//8.1
taxasDeFinanciamento = buscarTaxasDeFinanciamento(símbolo, 1000); // Últimas 1000 taxas de financiamento
//frameRate(1);
// Altere o símbolo se desejar
}
float startDist;
zoom flutuante = 1,0;
float offsetX = 0;
float offsetY = 0;
void touchStarted() {
se (touches.length == 2) {
distânciaInicial = dist(touches[0].x, touches[0].y, touches[1].x, touches[1].y);
}
}
void touchMoved() {
se (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); // limita o zoom
distânciaInicial = novaDist;
} senão se (touches.length == 1) {
offsetX += (touches[0].x - pmouseX) / zoom;
offsetY += (touches[0].y - pmouseY) / zoom;
}
}
// Arraste com o mouse (útil para testes no PC)
void mouseDragged() {
offsetX += (mouseX - pmouseX) / zoom;
offsetY += (mouseY - pmouseY) / zoom;
se ( mouseX < largura && mouseX > largura-100 && mouseY > altura-200 && mouseY < altura-100){
++gapMin;
}
se ( mouseX < largura && mouseX > largura-100 && mouseY > altura-100 && mouseY < altura){
--gapMin;
}
}
void mousePressed()
{
//++countSymbol;
//preencher(255);
//rect(largura-200, 100,200,200);
se ( mouseX > largura-200 && mouseY < 300 && mouseY >100 )
++countSymbol;
se ( mouseX > largura-200 && mouseY < 500 && mouseY >300 )
--contarSímbolo;
se (contagemSímbolo<0)
countSymbol = 0;
se (contagemSímbolo>101)
countSymbol = 0;
//texto(símbolos[contagemSímbolo],largura-150,150);
símbolo = símbolos[contagemSímbolo];
}
void mouseReleased()
{
se ( mouseX < largura && mouseX > largura-100 && mouseY > altura-200 && mouseY < altura-100){
++gapMin;
}
se ( mouseX < largura && mouseX > largura-100 && mouseY > altura-100 && mouseY < altura){
--gapMin;
}
}
float rsi(int i, float[] closes, int period) {
se (i < período) retorne 50; // padrão se não houver dados suficientes
ganho de ponto flutuante = 0, perda = 0;
para (int j = 1; j <= período; j++) {
mudança de ponto flutuante = fecha[i - j + 1] - fecha[i - j];
se (variação > 0) ganho += variação;
caso contrário, perda -= mudança;
}
float avgGain = ganho / período;
float avgLoss = perda / período;
Se (perda média == 0) retorne 100; // RSI máximo se não houver perda
float rs = ganho médio / perda média;
retornar 100 - (100 / (1 + rs));
}
int n = 30; // tamanho da janela
float tolerance = 100.5; // margem para dizer "atinge o limite máximo"
void detectarResistência(int i, float[] highs, float[] closes) {
se (i < n) retornar; // ainda não há dados suficientes
// Selecionamos o valor máximo das últimas n velas
float maxRecent = highs[i];
para (int j = 1; j < n; j++) {
se (highs[i - j] > maxRecent) {
maxRecent = highs[i - j];
}
}
Contamos quantas vezes o preço "chegou perto" do máximo.
int toques = 0;
para (int j = 0; j < n; j++) {
se (abs(highs[i - j] - maxRecent) < tolerância) {
toques++;
}
}
// Cálculo do RSI não será exibido
// vender na baixa
float rsiValue = rsi(i, closes, 27);
// Se ocorrer com frequência, mas a temperatura não ultrapassar 100 °C, sinalize
se (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);
preencher(255, 255, 0, 150);
semAcidente();
rect(xp, y, 30, 15);
//preencher(255);
textAlign(CENTRO);
texto("CURTO ×100", xp, y - 10);
}
}
// --- DESENHAR LOOP ---
void desenhar() {
aleatório = 0;
se (millis() - últimaAtualização >= intervalo) {
//fetchData(symbol); // Atualizamos os dados
/*closes = new float[666]; // redefine o array de closures
supports.clear(); // Limpamos a lista de suportes
supportBreaks.clear(); // limpa a lista de pausas
liquidationClusters.clear(); // limpamos os clusters de liquidação
clusterCounts.clear();
supportBroken.clear();*/
símbolo = símbolos[contagemSímbolo];
buscarDados( símbolo );
últimaAtualização = millis(); // Reiniciamos o contador para zero
}
pushMatrix();
traduzir(largura/2 + deslocamentoX*zoom, altura/2 + deslocamentoY*zoom-400);
//translate(largura/2 + offsetX, altura/2 + offsetY-400);
escala(zoom);
//fetchData("BTCUSDT");
fundo(20);
acidente vascular cerebral (255);
preencher(200);
// limites verticais para dimensionamento
float maxP = max(closes);;
float minP = min(fecha);
/*
para (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);
preencher(255, 25, 255,150);
semAcidente();
rect(xpr-20, y - 40,40,40);
}
para (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);
preencher(25, 255, 255,150);
semAcidente();
rect(xpr-20, y - 40,40,40);
}
*/
// --- PRÓXIMO ---
acidente vascular cerebral(255, 255, 0);
float yATH = map(ATH, minP, maxP, height-50, 50);
linha(50, yATH, largura-50, yATH);
preencher(255, 255, 0);
text("ATH " + ATH, 55, yATH-5);
preencher(255,0,0,55);retângulo(50,yATH,larguras,100);
// --- PRÓXIMO ---
acidente vascular cerebral (25, 255, 255);
yATH = map(LOW, minP, maxP, height-50, 50);
linha(50, yATH, largura-50, yATH);
preencher(255, 255, 0);
texto("BAIXO " + BAIXO, 55, yATH-5);
preencher(0,255,0,55);retângulo(50,yATH,larguras,-100);
// Gráfico de preços (gráfico de linhas de fechamento)
/*
para (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);
acidente vascular cerebral (180);
peso do golpe (2);
linha(x1, y1, x2, y2);
abre = novo float[n];
altas = novo float[n];
baixos = novo float[n];
fecha = novo float[n];
}*/
peso do golpe (1,3);
preencher(223,12);
iniciarForma();
para (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);
vértice(x, y);
// pedidos limitados
}
fimForma();
semAcidente();
float[] ema3 = ema(closes, 666);//18
peso do golpe (3);
semPreenchimento();
para (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);
se (ema3[i] > ema3[i-1]) {
stroke(0, 255, 0); // vertical se estiver para cima
} outro {
stroke(255, 0, 0); // vermelho se descendo
}
linha(x1 , y1, x2 , y2);
}
ema3 = ema(fecha, 18);//18
peso do golpe (3);
semPreenchimento();
para (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);
se (ema3[i] > ema3[i-1]) {
stroke(0, 255, 0); // vertical se estiver para cima
} outro {
stroke(255, 0, 0); // vermelho se descendo
}
linha(x1 , y1, x2 , y2);
}
/*
// largura de cada vela + espaço
vela flutuanteW = 5;
float spacing = 2; // espaço entre as velas
float chartWidth = (candleW + spacing) * closes.length;
para (int i = 0; i < closes.length; i++) {
// X com espaçamento regular
float x = 50 + i * (candleW + spacing);
// mapeamento 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);
// --- Pavio ---
acidente vascular cerebral (200);
linha(x, yh, x, yl);
// --- Corpo ---
se (fecha[i] >= abre[i]) {
preencher(0, 200, 0);
traço(0, 200, 0);
rect(x - candleW/2, yc, candleW, yo - yc);
} outro {
preencher(200, 0, 0);
acidente vascular cerebral(200, 0, 0);
rect(x - candleW/2, yo, candleW, yc - yo);
}
}
*/
para (int i = 0; i < closes.length; i++) {
float x = map(i, 0, closes.length - 1, 50, widths-50);
// mapeamento 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);
// largura de uma vela
vela flutuanteW = 4,5;
// --- Pavio ---
se (fecha[i] >= abre[i])
// Vela verde
acidente vascular cerebral(0,200,0);
outro
acidente vascular cerebral(200,0,0);
peso do golpe (1,3);
linha(x, yh, x, yl);
semAcidente();
// --- Corpo ---
se (fecha[i] >= abre[i]) {
// Vela verde
preencher(0, 200, 0);
traço(0, 200, 0);
rect(x - candleW/2, yc, candleW, yo - yc);
} outro {
// Vela vermelha
preencher(200, 0, 0);
acidente vascular cerebral(200, 0, 0);
rect(x - candleW/2, yo, candleW, yc - yo);
}
boolean baseHistorique = true;
se ( i > 84)
para (int j = 0; j < 83; j++) {
se (lows[i-j-1] < lows[i]) {
basHistorique = falso;
quebrar;
}
}
senão baseHistorique = falso;
se (downHistory)
{
//se (rsiC>10 && rsiC < 50-Indicator && basHistorique){
//if (rsiC < 45 && basHistorico){
//if (rsiC < 35 && basHistorico){// && dados[i]< prixHaut-20)
// Posicione o ponto
float xp = map(i, 0, closes.length - 1, 50, widths-50);
float y = map(lows[i], minP, maxP, height - 50, 50);
preencher(255, 0, 0,150);
semAcidente();
rect(xp-20, y - 40,40,40);
//elipse(xp-5, y, 10, 10);
preencher(0, 255, 0);
textAlign(CENTRO);
//rect(x-decX, y - 8,10,10);
///bas[i]=1;
se (lows[i] < lows[i-83])
texto("LL", xp, y - 10);
outro
texto("HL", xp, y - 10);
// bas[i]=1;
// em uma compra
//CONFIRM= verdadeiro;
}
booleano HautHistorique = verdadeiro;
se ( i > 84)
para (int j = 0; j < 83; j++) {
se (highs[i-j-1] > highs[i]) {
HautHistorique = falso;
quebrar;
}
}
senão HautHistorique = falso;
se (Alta História)
{
//se (rsiC>10 && rsiC < 50-Indicator && basHistorique){
//if (rsiC < 45 && basHistorico){
//if (rsiC < 35 && basHistorico){// && dados[i]< prixHaut-20)
// Posicione seu ponto
float xp = map(i, 0, closes.length - 1, 50, widths-50);
float y = map(highs[i], minP, maxP, height - 50, 50);
preencher(255, 255, 0,150);
semAcidente();
rect(xp-20, y - 40,40,40);
//elipse(xp-5, y, 10, 10);
preencher(0, 255, 255);
textAlign(CENTRO);
//rect(x-decX, y - 8,10,10);
///bas[i]=1;
se ( highs[i] > highs[i-83])
texto("HH", xp, y - 10);
outro
texto("Hl", xp, y - 10);
// bas[i]=1;
se ( 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);
acidente vascular cerebral(255,255,0);
linha(xp, y, xi,yi);
}
// em uma compra
//CONFIRM= verdadeiro;
}
//////////// os pequenos picos
baseHistorique = verdadeiro;
se ( i > 9)
para (int j = 0; j < 8; j++) {
se (lows[i-j-1] < lows[i]) {
basHistorique = falso;
quebrar;
}
}
senão baseHistorique = falso;
se (downHistory)
{
//se (rsiC>10 && rsiC < 50-Indicator && basHistorique){
//if (rsiC < 45 && basHistorico){
//if (rsiC < 35 && basHistorico){// && dados[i]< prixHaut-20)
// Posicione seu ponto
float xp = map(i, 0, closes.length - 1, 50, widths-50);
float y = map(lows[i], minP, maxP, height - 50, 50);
preencher(255, 0, 0,150);
semAcidente();
//rect(xp-20, y - 40,40,40);
elipse(xp-5, y, 10, 10);
preencher(0, 255, 0);
textAlign(CENTRO);
//rect(x-decX, y - 8,10,10);
///bas[i]=1;
// se (lows[i] < lows[i-83])
//texto("LL", xp, y - 10);
//outro
//texto("HL", xp, y - 10);
// bas[i]=1;
// em uma compra
//CONFIRM= verdadeiro;
}
TopHistorical = verdadeiro;
se ( i > 9)
para (int j = 0; j < 8; j++) {
se (highs[i-j-1] > highs[i]) {
HautHistorique = falso;
quebrar;
}
}
senão HautHistorique = falso;
se (Alta História)
{
//se (rsiC>10 && rsiC < 50-Indicator && basHistorique){
//if (rsiC < 45 && basHistorico){
//if (rsiC < 35 && basHistorico){// && dados[i]< prixHaut-20)
// Posicione seu ponto
float xp = map(i, 0, closes.length - 1, 50, widths-50);
float y = map(highs[i], minP, maxP, height - 50, 50);
preencher(255, 255, 0,150);
semAcidente();
//rect(xp-20, y - 40,40,40);
elipse(xp-5, y, 10, 10);
preencher(0, 255, 255);
textAlign(CENTRO);
//rect(x-decX, y - 8,10,10);
///bas[i]=1;
se ( highs[i] > highs[i-7])
texto("HH", xp, y - 10);
outro
texto("Hl", xp, y - 10);
// bas[i]=1;
/*se ( 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);
acidente vascular cerebral(255,255,0);
linha(xp, y, xi,yi);
}*/
// em uma compra
//CONFIRM= verdadeiro;
}
// As resistências quando o preço não sobe
detectarResistência(i, máximas, fechamentos);
}
/*
para (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);
preencher(0,255,0,123);
rect(x-10, yh,10,yh-yl);
//abre = novo float[n];
//highs = novo float[n];
//lows = novo float[n];
//fecha = novo float[n];
// pedidos limitados
}
acidente vascular cerebral(0,0,255);
acidente vascular cerebral (25, 255, 255);
*/
peso do golpe (2);
// --- Clusters de liquidação ---
acidente vascular cerebral(255, 0, 0);
para (int i=0; i
float lvl = liquidationClusters.get(i);
float y = map(lvl, minP, maxP, height-50, 50);
linha(50, y, larguras-50, y);
preencher(255, 0, 0);
texto("LC x" + clusterCounts.get(i), widths-100, y-5);
}
/*
// --- Suportes e interrupções ---
para (int i=0; i
float nível = supports.get(i);
float y = map(lvl, minP, maxP, height-50, 50);
se (supportBroken.get(i)) {
stroke(25, 50, 255); // break = laranja
} outro {
stroke(0, 200, 255); // suporte = vert
}
linha(50, y, largura-50, y);
}*/
// --- Mapa de Calor dos Clusters ---
//desenharClusters(minP, maxP);
// --- Mapa de Calor dos Clusters ---
desenharClusters(minP, maxP);
// --- Suportes (áreas verdes) ---
desenharSuportes(minP, maxP);
// --- Interrupções (áreas laranja espessas) ---
drawBreaks(minP, maxP);
//detectResistances();
//desenharSinais(minP, maxP);
//drawClusters(minPrice, maxPrice);
desenharRetângulosDeNegociação(fechamentos, máximas, mínimas, minP, maxP);
desenharFVG(minP, maxP);
/*
int frIndex = fundingRates.length - 1; // na parte da última taxa de financiamento
// Percorremos as velas começando pela extremidade
para (int i = closes.length - 1; i >= 0 && frIndex >= 0; i -= 8) {
se (fundingRates[frIndex] < 0) {
float x = map(i, 0, closes.length - 1, 50, widths - 50);
preencher(255, 255, 0, 70); // amarelo
rect(x-5, 0, 10, height); // barra amarela na vela correspondente
}
frIndex--; // avançamos na tabela de financiamento
}
*/
se ( i == "1h")
///// sinal do verme... desculpe, dos shorts... xP
para (int i = 0; i < fundingRates.length; ++i) {
//for (int i = fundingRates.length; i < 1 ; --i) {
//int candleIndex = i * 8; // si ech = 1h
se (fundingRates[i] < 0) {
Só podemos recuperar 1000 francos
// 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 = altura/2;
preencher(255, 255, 0, 70); // amarelo
//rect(x-5, y-5, 10, 10); // quadrado pequeno
rect(x-5, 0, 10, altura); // pequeno quadrado
tamanhoDoTexto(33);
preencher(255);
texto( "CURTO ", x-5,150);
}
}
textSize(12);
popMatrix();
String[] labels = {"1s", "1m", "3m", "15m","1day","1h","2h"}; // texto dos intervalos
int wld=0;
para (int i=0;i
{ preencher(i*10,255-i*10,i);
rect(i,0,100,100);
preencher(0,0,0);
texto( rótulos[wld % labels.length], 40+i,50);
++wld;
}
preencher(255,255,255);
texto(me, 20, 130);
se ( mouseX < 100 && mouseY < 100 ){
i = "1s"; buscarDados( símbolo );
}
se ( mouseX < 200 && mouseX > 100 && mouseY < 100 ){
i = "1m"; buscarDados( símbolo );
}
se ( mouseX < 300 && mouseX > 200 && mouseY < 100 ){
i = "3m";fetchData( símbolo );
}
se ( mouseX < 400 && mouseX > 300 && mouseY < 100 ){
i = "15m";
buscarDados( símbolo );
}
se ( mouseX < 500 && mouseX > 400 && mouseY < 100 ){
i = "1d";
buscarDados( símbolo ); ;
}
se ( mouseX < 600 && mouseX > 500 && mouseY < 100 ){
i = "1h";
buscarDados( símbolo ); ;
}
se ( mouseX < 700 && mouseX > 600 && mouseY < 100 ){
ech = "2h";
buscarDados( símbolo ); ;
}
se ( mouseX < 900 && mouseX > 670 && mouseY < 100 ){
i = "30m";
buscarDados(símbolo);
}
//rect(largura-100,altura-200,100,100);
//rect(largura-100,altura-100,100,100);
//rect(largura-200,0,largura,300);
texto(símbolos[contagemSímbolo],largura-150,150);
// textSize(30);
//preencher(t13?0:255,t13?255:0,0);
texto ("PREÇO : " + nf(closes[999],0,2),10,altura-220);
retângulo(largura-100,altura-200,100,100);
retângulo(largura-100,altura-100,100,100);
texto ( gapMin, largura-30, altura-250);
}
// --- BUSCAR DADOS ---
void fetchData(String symbol) {
//closes = new float[666];//[666]; // r������������init tableau de clôtures
supports.clear(); // Limpamos a lista de suportes
supportBreaks.clear(); // limpa a lista de pausas
liquidationClusters.clear(); // limpamos os clusters de liquidação
clusterCounts.clear();
suporteQuebrado.limpar();
String url = "https://api.generallink.top/api/v3/klines?symbol=" + símbolo + "&interval="+ech+"&limit=2500";
tentar {
String raw = join(loadStrings(url), "");
velas = parseJSONArray(bruto);
int n = candles.size();
println("vela = "+ n);
abre = novo float[n];
altas = novo float[n];
baixos = novo float[n];
fecha = novo float[n];
volumes = novo float[n];
para (int i = 0; i < n; i++) {
JSONArray c = candles.getJSONArray(i);
abre[i] = float(c.getString(1));
highs[i] = float(c.getString(2));
lows[i] = float(c.getString(3));
fecha[i] = float(c.getString(4));
volumes[i] = float(c.getString(5));
// Exemplo simplificado de detecção
se (suportes.tamanho() > 0) {
float últimoFechamento = fecha[i];
float prevClose = closes[i-1];
para (int s = supports.size()-1; s >= 0; s--) {
float sprice = supports.get(s);
// Condição de ruptura: passagens de fechamento sob o suporte
se (prevClose >= target && lastClose < target) {
supportBreaks.add(sprice);
}
}
}
}
prixAtual = fecha[n-1];
ATH = máximo(fechamentos);
BAIXO = min(fechamentos);
detectarClusters();
detectarSuportes();
detectarClustersAndFVG(gapMin);
} catch (Exception e) {
println("Erro na API: " + e.getMessage());
}
}
float gapMin = 1;
// Classe para armazenar lacunas com índices de velas
classe Gap {
flutuar baixo, alto;
int startIdx, endIdx; // índices das velas
booleano de alta; // verdadeiro = gap de alta, falso = gap de baixa
Gap(float l, float h, int start, int end, boolean bullishGap) {
baixo = l;
alto = h;
startIdx = início;
endIdx = fim;
otimista = gap de alta;
}
}
// Listas globais para FVG
ArrayList fvgUp = new ArrayList();
ArrayList fvgDn = new ArrayList();
// Detecção de FVG (versão simplificada e testável)
void detectarClustersAndFVG(float gapMin) {
fvgUp.limpar();
fvgDn.limpar();
para (int i=2; i
// --- FVG otimista ---
se (mínimos[i] - máximos[i-2] > intervaloMin) {
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 baixista ---
se (mínimos[i-2] - máximos[i] > intervaloMin) {
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);
}
}
}
// Desenho FVG (retângulos horizontais “de vela a vela”)
void drawFVG(float minP, float maxP) {
semAcidente();
// FVG otimista
para (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);
preencher(0, 255, 0, 90); // vertical semitransparente
traço(0, 180, 0);
rect(x1, min(y1,y2), max(x2-x1, 2)+100, abs(y2-y1)); // largura mínima 2px
semAcidente();
preencher(255);
textAlign(ESQUERDA, CENTRO);
texto("Long FVG " + nf(g.low,0,2) + "-" + nf(g.high,0,2), x1 + 3, min(y1,y2) + abs(y2-y1)/2);
}
// FVG baixista
para (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);
preencher(0, 100, 255, 90); // azul semitransparente
traço(0, 0, 180);
rect(x1, min(y1,y2), max(x2-x1, 2)+100, abs(y2-y1)); // largura mínima 2px
semAcidente();
preencher(255);
textAlign(ESQUERDA, CENTRO);
texto("FVG curto " + nf(g.low,0,2) + "-" + nf(g.high,0,2), x1 + 3, min(y1,y2) + abs(y2-y1)/2);
}
}
/*
Armazenamos as lacunas como pares (mínimo, máximo)
classe Gap {
flutuar baixo, alto;
Lacuna(float l, float h) {
baixo = l;
alto = h;
}
}
ArrayList fvgUp = new ArrayList();
ArrayList fvgDn = new ArrayList();
void detectarClustersAndFVG() {
liquidationClusters.clear();
clusterCounts.clear();
fvgUp.limpar();
fvgDn.limpar();
// média simples do volume
float volMA = 0;
para (int i=0; i
volMA += volumes[i];
}
volMA /= volumes.comprimento;
para (int i=0; i
float corpo = abs(fecha[i]-abre[i]);
vela flutuante = máximas[i]-mínimas[i];
float wickUp = highs[i]-max(opens[i], closes[i]);
float wickDn = min(opens[i], closes[i]) - lows[i];
// --- Liquidação de detecção de cluster ---
se (volumes[i] > volMA*volMult && candle > 0 && body/candle <= minBodyRatio) {
float liquidPrice = Float.NaN;
se (wickUp/candle >= wickRatio) liquidPrice = highs[i];
senão se (wickDn/candle >= wickRatio) liquidPrice = lows[i];
se (!Float.isNaN(liquidPrice)) adicioneCluster(liquidPrice);
}
*/
/*
// --- Detecção de Lacunas de Valor Justo (FVG) ---
se (i >= 2) {
// FVG em tendência de alta (mínima atual > máxima de 2 velas atrás)
se (mínimos[i] > máximos[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 em tendência de baixa (máxima atual igual à mínima de 2 velas atrás)
se (altos[i] < baixos[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; // tolerância mínima para considerar um FVG
se (i >= 2) {
// FVG otimista
se (mínimos[i] - máximos[i-2] > intervaloMin) {
fvgUp.add(new Gap(highs[i-2], lows[i]));
println("FVG UP:", highs[i-2], "->", lows[i]);
}
// FVG baixista
se (mínimos[i-2] - máximos[i] > intervaloMin) {
fvgDn.add(new Gap(highs[i], lows[i-2]));
println("FVG DOWN:", highs[i], "->", lows[i-2]);
}
}
}
}
void drawFVG(float minP, float maxP) {
semAcidente();
// FVG verde otimista
para (Gap g : fvgUp) {
float y1 = map(g.high, minP, maxP, height-50, 50);
float y2 = map(g.low, minP, maxP, height-50, 50);
acidente vascular cerebral (255);
preencher(0, 255, 0); // vértice transparente
rect(50, y1, widths-100, y2-y1);
preencher(0, 180);
texto("FVG" + nf(g.low,0,2)+"-"+nf(g.high,0,2), larguras-490, y1+12);
}
// FVG azul baixista
para (Gap g : fvgDn) {
float y1 = map(g.high, minP, maxP, height-50, 50);
float y2 = map(g.low, minP, maxP, height-50, 50);
acidente vascular cerebral(255,0,0);
preencher(0, 100, 255); // azul transparente
rect(50, y1, widths-100, y2-y1);
preencher(0, 180);
texto("FVG" + nf(g.low,0,2)+"-"+nf(g.high,0,2), larguras-490, y1+12);
}
}
*/
// --- DETECTAR AGLOMERADOS DE LIQUIDAÇÃO ---
void detectarClusters() {
liquidationClusters.clear();
clusterCounts.clear();
// média simples do volume
float volMA = 0;
para (int i=0; i
volMA += volumes[i];
}
volMA /= volumes.comprimento;
para (int i=0; i
float corpo = abs(fecha[i]-abre[i]);
vela flutuante = máximas[i]-mínimas[i];
float wickUp = highs[i]-max(opens[i], closes[i]);
float wickDn = min(opens[i], closes[i]) - lows[i];
se (volumes[i] > volMA*volMult && candle > 0 && body/candle <= minBodyRatio) {
float liquidPrice = Float.NaN;
se (wickUp/candle >= wickRatio) liquidPrice = highs[i];
senão se (wickDn/candle >= wickRatio) liquidPrice = lows[i];
se (!Float.isNaN(liquidPrice)) adicioneCluster(liquidPrice);
}
}
}
// --- Agrupar clusters próximos ---
void addCluster(float price) {
para (int i=0; i
se (abs(liquidationClusters.get(i) - preço) <= proximityPts) {
// increment
clusterCounts.set(i, clusterCounts.get(i)+1);
retornar;
}
}
liquidationClusters.add(price);
clusterCounts.add(1);
}
// --- DETECTAR SUPORTES + QUEBRAS ---
void detectarSuportes() {
supports.clear();
suporteQuebrado.limpar();
para (int i=pivotLeft; i
booleano isPivot = verdadeiro;
para (int j=1; j<=pivotLeft; j++) se (lows[i] >= lows[i-j]) isPivot=false;
para (int j=1; j<=pivotRight; j++) se (lows[i] >= lows[i+j]) isPivot=false;
se (éPivot) {
float s = lows[i];
suporta.adicionar(s);
// quebrar?
boolean broken = (closes[closes.length-1] < s);
suporteBroken.adicionar(quebrado);
}
}
}
// --- Clusters de liquidação em heatmap ---
void drawClusters(float minP, float maxP) {
semAcidente();
para (int i=0; i
float lvl = liquidationClusters.get(i);
int count = clusterCounts.get(i);
// mapeamento de preços para y
float y = map(lvl, minP, maxP, height-50, 50);
// Intensidade proporcional ao número de ocorrências
int alpha = constrain(40 + count*30, 40, 200);
int rectHeight = 6 + count*2; // ��������paisseur de zone
preencher(255, 0, 0, alfa);
rect(50, y - rectHeight/2, widths-100, rectHeight);
// texto discreto à direita
preencher(255, 200);
texto(nível + " Cluster de liquidação x" + contagem, larguras-490, y-5);
}
}
// --- Suportes (áreas verdes) ---
void drawSuportes(float minP, float maxP) {
semAcidente();
para (int i=0; i
float nível = supports.get(i);
float y = map(lvl, minP, maxP, height-50, 50);
preencher(0, 200, 0, 100); // verde translúcido
rect(50, y-3, widths-100, 6);
preencher(0, 255, 0);
texto(nível+" Suporte", 60, y-5);
}
}
// --- Interrupções de suporte (áreas laranja espessas) ---
void drawBreaks(float minP, float maxP) {
semAcidente();
para (int i=0; i
float lvl = supportBreaks.get(i);
float y = map(lvl, minP, maxP, height-50, 50);
preencher(255, 140, 0, 150); // laranja semi-opaco
rect(50, y-4, widths-100, 8);
preencher(255, 180, 0);
texto("Pausa de suporte", 60, y-6);
}
}
///////#######
// --- Análise de cluster para áreas de compra/venda ---
float clusterZoneMargin = 5f; // margem ao redor do cluster para desenhar a zona
void drawClusterZones(float minP, float maxP) {
para (int i=0; i
float lvl = liquidationClusters.get(i);
int count = clusterCounts.get(i);
// Mapeamento de preço -> e
float y = map(lvl, minP, maxP, height-50, 50);
// Defina a cor de acordo com a tendência (ex.: tons claros = promoção, tons escuros = compra)
float wickUp = highs[i] - max(opens[i], closes[i]);
float wickDn = min(opens[i], closes[i]) - lows[i];
boolean isBuyZone = wickDn > wickUp; // pavio inferior maior
boolean isSellZone = wickUp > wickDn; // pavio mais alto maior
// Ajuste a opacidade e a espessura de acordo com o número de ocorrências
int alpha = constrain(60 + count*30, 60, 200);
int rectHeight = 6 + count*2;
se (isBuyZone) {
preencher(0, 0, 255, alfa);
rect(50, y - clusterZoneMargin, widths-100, clusterZoneMargin*2);
preencher(0, 0, 255);
texto("Compre x"+contagem, larguras-180, y);
}
se (isSellZone) {
preencher(255, 0, 0, alfa);
rect(50, y - clusterZoneMargin, widths-100, clusterZoneMargin*2);
preencher(255, 0, 0);
texto("Venda x"+contagem, larguras-180, y);
}
}
}
////////€€
// --- Configurações ---
float rsiOverbought = 70f;
float rsiOversold = 45f;
int rsiLength = 27; // Comprimento do RSI
int shortTrendLength = 33; // número de velas para calcular a tendência de baixa
float rectMargin = 10f; // espessura do retângulo
// --- Cálculo simples do RSI ---
float calcRSI(float[] closes, int idx, int length) {
Se (idx < comprimento) retorne 50; // valor neutro se não houver dados suficientes
ganho de ponto flutuante = 0, perda = 0;
para (int i=idx-length+1; i<=idx; i++) {
float diff = closes[i] - closes[i-1];
se (diferença > 0) ganho += diferença;
caso contrário, perda -= diferença;
}
se (perda == 0) retorne 100;
retornar 100 - (100 / (1 + ganho/perda));
}
// --- Detecção de tendências de curto prazo ---
boolean isShortDowntrend(float[] closes, int idx, int len) {
se (idx < len) retorne falso;
retornar closes[idx] < closes[idx-len];
}
boolean isShortUptrend(float[] closes, int idx, int len) {
se (idx < len) retorne falso;
retornar closes[idx] > closes[idx-len];
}
void drawTradeRectangles(float[] closes, float[] highs, float[] lows, float minP, float maxP) {
para (int i=comprimentoDaTendênciaCurta; i
float rsi = calcRSI(closes, i, rsiLength);
// Calculando a posição X de acordo com a linha do tempo
float x = map(i, 0, closes.length-1, 50, widths-50);
// --- Sinal de venda ---
se (rsi >= rsiOverbought && isShortDowntrend(closes, i, shortTrendLength)) {
float recentHigh = highs[i];
float y = map(recentHigh, minP, maxP, height-50, 50);
preencher(255, 0, 0, 80);
rect(x-10, y-rectMargin, 20, rectMargin*2); // retângulo centralizado em x
preencher(255, 0, 0);
texto("S", x, y-rectMargin-5); // texto logo acima do retângulo
}
// --- Sinal de compra ---
se (rsi <= rsiSobrevendido && isShortUptrend(closes, i, shortTrendLength)) {
float recentLow = lows[i];
float y = map(recentLow, minP, maxP, height-50, 50);
preencher(0, 0, 255, 80);
rect(x-10, y-rectMargin, 20, rectMargin*2); // retângulo centralizado em x
preencher(0, 0, 255);
texto("B", x, y-rectMargin-5); // texto logo acima do retângulo
}
}
}