PaPP v2 indicatore: Cluster contestualizzato con percentile storico (stretto/normale/largo) + valore tipico

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Pietro Giacobazzi
2026-06-17 06:53:56 +00:00
parent cf3525f7af
commit a1023b573e
+40 -5
View File
@@ -17,6 +17,7 @@ input bool ShowMA = true; // mostra anche le 7 MA (oltre alla mediana)
#define ANCHOR_TF PERIOD_D1 // calcolo ancorato a D1: linea identica su ogni TF
#define KSLOPE 5 // barre D1 per velocita'/accelerazione
#define NVOL 14 // barre D1 per la volatilita'
#define CLWIN 252 // finestra D1 (~1 anno) per il percentile del cluster
double Buff_Median[];
double B0[],B1[],B2[],B3[],B4[],B5[],B6[];
@@ -25,6 +26,7 @@ int gDays[7] = {365,182,121,30,14,7,3};
color gCol[7] = {clrDodgerBlue,clrDeepSkyBlue,clrTurquoise,clrLimeGreen,clrOrange,clrTomato,clrRed};
int hMA[7];
int bars[7];
struct PBuf { double v[]; }; // buffer dinamico per copiare una MA
string _pfx = "PM_"; // oggetti pannello
string _pfx2 = "PME_"; // etichette a fine linea
@@ -199,6 +201,38 @@ void ScaleMetrics(double &velo,double &acc,double &vol)
velo=MedArr(va,cv); acc=MedArr(aa,ca); vol=MedArr(wa,cw);
}
//+------------------------------------------------------------------+
// Contestualizza il cluster: percentile dell'ampiezza attuale sugli ultimi 'win' giorni D1
// cur = cluster oggi, pctl = posizione 0..1 nella storia, typ = ampiezza tipica (mediana storica)
void ClusterStats(int win,double &cur,double &pctl,double &typ)
{
cur=0; pctl=0.5; typ=0;
int need=win+1;
PBuf mb[7];
for(int m=0;m<7;m++)
{
ArraySetAsSeries(mb[m].v,true);
if(CopyBuffer(hMA[m],0,0,need,mb[m].v)!=need) return;
}
double cl[]; int cc=0; ArrayResize(cl,win);
for(int j=1;j<=win;j++)
{
double vals[7]; int vc=0;
for(int m=0;m<7;m++){ double v=mb[m].v[j]; if(IsVal(v)) vals[vc++]=v; }
if(vc<2) continue;
double md=MedArr(vals,vc);
if(md<=0) continue;
double ds=0;
for(int m=0;m<vc;m++) ds+=MathAbs(vals[m]-md)/md*100.0;
cl[cc++]=ds/vc;
}
if(cc<=0) return;
cur=cl[0]; // j=1 = ultima barra D1 chiusa
typ=MedArr(cl,cc);
int below=0; for(int k=0;k<cc;k++) if(cl[k]<=cur) below++;
pctl=(double)below/cc;
}
//+------------------------------------------------------------------+
// interpolazione lineare con fallback se uno dei valori manca
double Interp(double vStart,double vEnd,double frac)
@@ -343,11 +377,12 @@ void DrawInfo()
Lbl("M","Median: "+DoubleToString(median,_Digits),x,y,FontSize,clrGold,false); y+=lh;
Lbl("D","Dist: "+distS,x,y,FontSize,distC,true); y+=lh+2;
//--- Cluster (dispersione media delle MA dalla mediana)
double ds=0; int dc=0;
for(int m=0;m<7;m++) { double v=GetMA(m,1); if(v>0) { ds+=MathAbs(v-median)/median*100; dc++; } }
double clu = (dc>0)?ds/dc:0;
Lbl("V","Cluster +/-"+DoubleToString(clu,3)+"%",x,y,FontSize,clrGray,false); y+=lh;
//--- Cluster contestualizzato: valore + percentile storico (stretto/normale/largo)
double clu_cur,clu_pctl,clu_typ; ClusterStats(CLWIN,clu_cur,clu_pctl,clu_typ);
string clab = (clu_pctl<0.33)?"stretto":((clu_pctl>0.66)?"largo":"normale");
color cclr = (clu_pctl<0.33)?clrLimeGreen:((clu_pctl>0.66)?clrTomato:clrSilver);
Lbl("V",StringFormat("Cluster %.3f%% P%.0f %s (tip %.3f%%)",clu_cur,clu_pctl*100,clab,clu_typ),
x,y,FontSize,cclr,false); y+=lh;
//--- Velocita'/Accelerazione/Volatilita' = mediana delle 7 scale (dalle nostre MA)
double velo,acc,volat; ScaleMetrics(velo,acc,volat);