Compare commits

...

2 Commits

Author SHA1 Message Date
Pietro Giacobazzi 392706088a PaPP v2 indicatore: disegna anche le 7 MA come linee separate (input ShowMA)
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-16 19:24:36 +00:00
Pietro Giacobazzi f2515243e3 PaPP v2 indicatore: fix linea invisibile - attende dati D1, bulk load + cache mediana, ricalcolo robusto
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-16 19:19:33 +00:00
+139 -23
View File
@@ -7,21 +7,40 @@
#property description "PaPP Median - Mediana 7 MA (3g-1y)"
#property description "Calcolo ancorato a D1 = linea uguale su ogni timeframe"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
#property indicator_buffers 8
#property indicator_plots 8
input int FontSize = 9;
input bool Smooth = true; // interpola tra i valori D1 -> linea morbida
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
double Buff_Median[];
double B0[],B1[],B2[],B3[],B4[],B5[],B6[];
int gDays[7] = {365,182,121,30,14,7,3};
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];
string _pfx = "PM_";
//+------------------------------------------------------------------+
// scrive il valore nel buffer della MA m
void SetBuf(int m,int idx,double v)
{
switch(m)
{
case 0: B0[idx]=v; break;
case 1: B1[idx]=v; break;
case 2: B2[idx]=v; break;
case 3: B3[idx]=v; break;
case 4: B4[idx]=v; break;
case 5: B5[idx]=v; break;
case 6: B6[idx]=v; break;
}
}
//+------------------------------------------------------------------+
int TimeToBars(int d)
{
@@ -45,13 +64,36 @@ int OnInit()
}
SetIndexBuffer(0,Buff_Median,INDICATOR_DATA);
SetIndexBuffer(1,B0,INDICATOR_DATA);
SetIndexBuffer(2,B1,INDICATOR_DATA);
SetIndexBuffer(3,B2,INDICATOR_DATA);
SetIndexBuffer(4,B3,INDICATOR_DATA);
SetIndexBuffer(5,B4,INDICATOR_DATA);
SetIndexBuffer(6,B5,INDICATOR_DATA);
SetIndexBuffer(7,B6,INDICATOR_DATA);
ArraySetAsSeries(Buff_Median,true);
ArraySetAsSeries(B0,true); ArraySetAsSeries(B1,true);
ArraySetAsSeries(B2,true); ArraySetAsSeries(B3,true);
ArraySetAsSeries(B4,true); ArraySetAsSeries(B5,true);
ArraySetAsSeries(B6,true);
//--- plot 0 = mediana (linea principale)
PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);
PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrGold);
PlotIndexSetInteger(0,PLOT_LINE_WIDTH,2);
PlotIndexSetString(0,PLOT_LABEL,"PaPP Median");
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
//--- plot 1..7 = le 7 MA
for(int p=0;p<7;p++)
{
PlotIndexSetInteger(p+1,PLOT_DRAW_TYPE,ShowMA?DRAW_LINE:DRAW_NONE);
PlotIndexSetInteger(p+1,PLOT_LINE_COLOR,gCol[p]);
PlotIndexSetInteger(p+1,PLOT_LINE_WIDTH,1);
PlotIndexSetString(p+1,PLOT_LABEL,"MA "+IntegerToString(gDays[p])+"g");
PlotIndexSetDouble(p+1,PLOT_EMPTY_VALUE,0.0);
}
IndicatorSetString(INDICATOR_SHORTNAME,"PaPP Median");
return INIT_SUCCEEDED;
}
@@ -93,6 +135,27 @@ double MedianAtD1(int d1shift)
return Median(vals,cnt);
}
//+------------------------------------------------------------------+
// interpolazione lineare con fallback se uno dei valori manca
double Interp(double vStart,double vEnd,double frac)
{
if(vStart>0 && vEnd>0) return vStart+frac*(vEnd-vStart);
if(vEnd>0) return vEnd;
return vStart;
}
//+------------------------------------------------------------------+
// Mediana dei primi n valori di src
double MedianN(const double &src[],int n)
{
if(n<=0) return 0;
double a[]; ArrayResize(a,n);
for(int i=0;i<n;i++) a[i]=src[i];
ArraySort(a);
if((n&1)==1) return a[n/2];
return 0.5*(a[n/2-1]+a[n/2]);
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
@@ -109,34 +172,87 @@ int OnCalculate(const int rates_total,
ArraySetAsSeries(close,true);
ArraySetAsSeries(time,true);
int limit = rates_total - prev_calculated;
if(limit>1) limit=rates_total-1;
//--- i dati D1 devono essere pronti, altrimenti ritenta al prossimo tick
int d1bars = Bars(_Symbol,ANCHOR_TF);
if(d1bars<2) return 0;
if(BarsCalculated(hMA[0])<=0) return 0;
for(int idx=limit;idx>=0;idx--)
//--- carica le 7 MA D1 in blocco e calcola la mediana per ogni barra D1
double med_d1[]; ArrayResize(med_d1,d1bars); ArraySetAsSeries(med_d1,true);
double cols[][7]; ArrayResize(cols,d1bars);
for(int m=0;m<7;m++)
{
//--- barra D1 che contiene il tempo di questa barra grafico
int d1cur = iBarShift(_Symbol,ANCHOR_TF,time[idx],false);
if(d1cur<0) { Buff_Median[idx]=0; continue; }
double tmp[]; ArraySetAsSeries(tmp,true);
int got = CopyBuffer(hMA[m],0,0,d1bars,tmp);
if(got<=0) return 0; // non pronto: ritenta
for(int s=0;s<d1bars;s++) cols[s][m] = (s<got) ? tmp[s] : 0.0;
}
for(int s=0;s<d1bars;s++)
{
double vv[7]; int c=0;
for(int m=0;m<7;m++) if(cols[s][m]>0) { vv[c]=cols[s][m]; c++; }
med_d1[s] = MedianN(vv,c);
}
if(!Smooth)
//--- range di barre grafico da (ri)calcolare:
// tutto al primo load o quando nasce una nuova barra D1, altrimenti solo oggi
static int s_lastD1 = -1;
int recalcFrom;
if(prev_calculated==0 || d1bars!=s_lastD1)
recalcFrom = rates_total-1;
else
{
datetime todayOpen = iTime(_Symbol,ANCHOR_TF,0);
recalcFrom = 0;
while(recalcFrom < rates_total-1 && time[recalcFrom] >= todayOpen) recalcFrom++;
}
s_lastD1 = d1bars;
for(int idx=recalcFrom; idx>=0; idx--)
{
int d1cur = iBarShift(_Symbol,ANCHOR_TF,time[idx],false);
if(d1cur<0 || d1cur>=d1bars)
{
//--- gradino: ultima barra D1 chiusa (non-repaint)
Buff_Median[idx]=MedianAtD1(d1cur+1);
Buff_Median[idx]=0;
for(int m=0;m<7;m++) SetBuf(m,idx,0.0);
continue;
}
//--- linea morbida: interpola tra mediana di inizio e fine giornata
double vEnd = MedianAtD1(d1cur); // giornata corrente
double vStart = MedianAtD1(d1cur+1); // giornata precedente
datetime t0 = iTime(_Symbol,ANCHOR_TF,d1cur);
datetime t1 = (d1cur>0) ? iTime(_Symbol,ANCHOR_TF,d1cur-1)
: t0 + PeriodSeconds(ANCHOR_TF);
double frac = (t1>t0) ? (double)(time[idx]-t0)/(double)(t1-t0) : 0.0;
frac = MathMax(0.0,MathMin(1.0,frac));
int sj=d1cur+1; // barra D1 precedente (inizio giornata)
if(vStart>0 && vEnd>0) Buff_Median[idx]=vStart+frac*(vEnd-vStart);
else if(vEnd>0) Buff_Median[idx]=vEnd;
else Buff_Median[idx]=vStart;
//--- frazione di giornata trascorsa (solo se Smooth)
double frac=0.0;
if(Smooth)
{
datetime t0 = iTime(_Symbol,ANCHOR_TF,d1cur);
datetime t1 = (d1cur>0) ? iTime(_Symbol,ANCHOR_TF,d1cur-1)
: t0 + PeriodSeconds(ANCHOR_TF);
frac = (t1>t0) ? (double)(time[idx]-t0)/(double)(t1-t0) : 0.0;
frac = MathMax(0.0,MathMin(1.0,frac));
}
//--- mediana
if(!Smooth)
Buff_Median[idx] = (sj<d1bars) ? med_d1[sj] : 0.0;
else
{
double vS = (sj<d1bars) ? med_d1[sj] : 0.0;
Buff_Median[idx] = Interp(vS,med_d1[d1cur],frac);
}
//--- le 7 MA
for(int m=0;m<7;m++)
{
double val;
if(!Smooth)
val = (sj<d1bars) ? cols[sj][m] : 0.0;
else
{
double vS2 = (sj<d1bars) ? cols[sj][m] : 0.0;
val = Interp(vS2,cols[d1cur][m],frac);
}
SetBuf(m,idx,val);
}
}
DrawInfo();