//+------------------------------------------------------------------+ //| PaPP_CrossExport.mq5 | //| PaPP v2 | //| Esporta in CSV TUTTI gli incroci tra le 9 linee (prezzo+Mediana | //| +7 MA), calcolati ANCORATI a D1 (come l'indicatore), con il | //| contesto di ogni incrocio e gli esiti futuri a 1/3/5/10/20 g. | //| Si puo' esportare un intervallo di date oppure tutto lo storico. | //+------------------------------------------------------------------+ #property copyright "PaPP v2" #property version "1.00" #property script_show_inputs //--- input input string InpSymbol = ""; // simbolo ("" = simbolo del grafico) input bool InpAllHistory = true; // true = tutto lo storico D1 input datetime InpStart = D'2010.01.01'; // inizio intervallo (se AllHistory=false) input datetime InpEnd = D'2100.01.01'; // fine intervallo (se AllHistory=false) input string InpFileName = ""; // nome file ("" = automatico) input bool InpBaseline = true; // crea anche il file baseline (tutte le barre D1) //--- costanti (stesse 7 MA dell'indicatore) #define ANCHOR_TF PERIOD_D1 #define NSER 9 // PRICE, MED, MA365..MA3 #define KSLOPE 5 // barre per pendenza / variazione cluster #define MAXH 20 // orizzonte massimo per gli esiti int gDays[7] = {365,182,121,30,14,7,3}; string SER[NSER]= {"PRICE","MED","MA365","MA182","MA121","MA30","MA14","MA7","MA3"}; int gHor[5] = {1,3,5,10,20}; //--- contenitore per un buffer MA dinamico (MQL5 non permette double ma[7][]) struct MABuf { double v[]; }; //+------------------------------------------------------------------+ int TimeToBarsD1(string sym,int d) { datetime n = TimeCurrent(); if(n==0) return MathMax(1,(int)((long)d*86400L/PeriodSeconds(ANCHOR_TF))); return MathMax(1,Bars(sym,ANCHOR_TF,n-(long)d*86400,n)); } //+------------------------------------------------------------------+ // valore valido = positivo e finito (MT5 usa EMPTY_VALUE=DBL_MAX nei warmup) bool IsVal(double v) { return (v>0.0 && v<1.0e12); } //+------------------------------------------------------------------+ double Median7(double &v[]) // mediana dei valori validi in v[0..6] { double a[]; int c=0; ArrayResize(a,7); for(int m=0;m<7;m++) if(IsVal(v[m])) { a[c]=v[m]; c++; } if(c==0) return 0; ArrayResize(a,c); ArraySort(a); if((c&1)==1) return a[c/2]; return 0.5*(a[c/2-1]+a[c/2]); } //+------------------------------------------------------------------+ void OnStart() { string sym = (InpSymbol=="") ? _Symbol : InpSymbol; if(!SymbolSelect(sym,true)) { Print("Simbolo non valido: ",sym); return; } int digits = (int)SymbolInfoInteger(sym,SYMBOL_DIGITS); //--- handle delle 7 MA su D1 + ATR int hMA[7]; for(int m=0;m<7;m++) { int per = TimeToBarsD1(sym,gDays[m]); hMA[m] = iMA(sym,ANCHOR_TF,per,0,MODE_SMA,PRICE_CLOSE); if(hMA[m]==INVALID_HANDLE) { Print("iMA fallita m=",m); return; } } int hATR = iATR(sym,ANCHOR_TF,14); if(hATR==INVALID_HANDLE) { Print("iATR fallita"); return; } //--- attendo che lo storico D1 sia pronto int total=0; for(int t=0; t<100; t++) { total = Bars(sym,ANCHOR_TF); bool ok = (total>MAXH+KSLOPE+50); for(int m=0;m<7 && ok;m++) if(BarsCalculated(hMA[m])=total) break; Sleep(100); } total = Bars(sym,ANCHOR_TF); if(total<=MAXH+KSLOPE+50) { Print("Storico D1 insufficiente: ",total," barre"); return; } //--- carico tutta la storia D1 (indice 0 = piu' vecchio) datetime tm[]; double cl[],hi[],lo[],atr[]; MABuf ma[7]; ArraySetAsSeries(tm,false); ArraySetAsSeries(cl,false); ArraySetAsSeries(hi,false); ArraySetAsSeries(lo,false); ArraySetAsSeries(atr,false); if(CopyTime(sym,ANCHOR_TF,0,total,tm)<=0) { Print("CopyTime KO"); return; } if(CopyClose(sym,ANCHOR_TF,0,total,cl)<=0) { Print("CopyClose KO"); return; } if(CopyHigh(sym,ANCHOR_TF,0,total,hi)<=0) { Print("CopyHigh KO"); return; } if(CopyLow(sym,ANCHOR_TF,0,total,lo)<=0) { Print("CopyLow KO"); return; } if(CopyBuffer(hATR,0,0,total,atr)<=0) { Print("CopyATR KO"); return; } for(int m=0;m<7;m++) { ArraySetAsSeries(ma[m].v,false); if(CopyBuffer(hMA[m],0,0,total,ma[m].v)<=0) { Print("CopyBuffer MA KO m=",m); return; } } int n = ArraySize(cl); //--- costruisco le 9 serie allineate per barra: S[i][k] double S[][NSER]; ArrayResize(S,n); for(int i=0;i=from) { iStart=i; break; } for(int i=n-1;i>=0;i--) if(tm[i]<=to) { iEnd=i; break; } //--- apro il file CSV string fname = (InpFileName=="") ? ("PaPP_crosses_"+sym+"_D1.csv") : InpFileName; int fh = FileOpen(fname,FILE_WRITE|FILE_TXT|FILE_ANSI); if(fh==INVALID_HANDLE) { Print("FileOpen KO: ",fname," err=",GetLastError()); return; } //--- header string head = "time,symbol,pair,a,b,dir,price,med,ma365,ma182,ma121,ma30,ma14,ma7,ma3," "dist_med_pct,cluster_pct,cluster_exp,slope_a,slope_b,trend,atr_pct,dow,month"; for(int hh=0;hh<5;hh++) { string s=IntegerToString(gHor[hh]); head += ",ret_"+s+",mfe_"+s+",mae_"+s+",dir_"+s+",rev_"+s; } for(int b=1;b<=MAXH;b++) head += ",cret_"+IntegerToString(b); // traiettoria forward bar-by-bar head += ",bars_to_revert,disc_max_pct"; FileWriteString(fh,head+"\r\n"); //--- file baseline (una riga per OGNI barra D1 valida): serve per il confronto // "extra-rendimento" = incrocio vs giorno qualunque nello stesso regime int fhB = INVALID_HANDLE; if(InpBaseline) { string bname = "PaPP_bars_"+sym+"_D1.csv"; fhB = FileOpen(bname,FILE_WRITE|FILE_TXT|FILE_ANSI); if(fhB==INVALID_HANDLE) Print("FileOpen baseline KO: ",bname," err=",GetLastError()); else { string bh = "time,symbol,price,med,dist_med_pct,cluster_pct,cluster_exp,trend,atr_pct,dow,month,bars_to_revert,disc_max_pct"; for(int b=1;b<=MAXH;b++) bh += ",cret_"+IntegerToString(b); FileWriteString(fhB,bh+"\r\n"); } } //--- scansione incroci long rows=0, brows=0; for(int i=iStart;i<=iEnd;i++) { if(icmax)cmax=v; if(vcmaxP)cmaxP=v; if(vma365)?1:-1; double atr_pct = atr[i]/price*100.0; MqlDateTime dt; TimeToStruct(tm[i],dt); //--- traiettoria forward (rendimento cumulato a +1..+MAXH), calcolata una volta per barra string bpath=""; for(int b=1;b<=MAXH;b++) { int iB=i+b; if(iB>n-1) bpath += ","; else bpath += ","+DoubleToString((cl[iB]-cl[i])/cl[i]*100.0,5); } //--- esito globale: ritorno alla Mediana entro MAXH int side = (price>med)?1:-1; int b2rev=-1; double discMax=0; int jmax = MathMin(i+MAXH,n-1); for(int j=i+1;j<=jmax;j++) { if(!IsVal(S[j][0]) || !IsVal(S[j][1])) continue; int sj=(S[j][0]>S[j][1])?1:-1; if(b2rev<0 && sj!=side) b2rev=j-i; double d=(S[j][0]-S[j][1])/S[j][1]*100.0; if(MathAbs(d)>MathAbs(discMax)) discMax=d; } //--- riga baseline (barra qualunque, indipendente dagli incroci) if(fhB!=INVALID_HANDLE) { string br = TimeToString(tm[i],TIME_DATE)+","+sym+"," +DoubleToString(price,digits)+","+DoubleToString(med,digits)+"," +DoubleToString(dist_med,5)+","+DoubleToString(cluster,5)+"," +DoubleToString(cluster_exp,5)+","+IntegerToString(trend)+"," +DoubleToString(atr_pct,5)+","+IntegerToString(dt.day_of_week)+"," +IntegerToString(dt.mon)+"," +(b2rev>0?IntegerToString(b2rev):"")+","+DoubleToString(discMax,5) +bpath; FileWriteString(fhB,br+"\r\n"); brows++; } //--- controllo ogni coppia (a,b) for(int a=0;a0) dir=1; else if(d0>=0 && d1<0) dir=-1; if(dir==0) continue; double slope_a = (S[i][a]-S[i-KSLOPE][a])/S[i-KSLOPE][a]*100.0; double slope_b = (S[i][b]-S[i-KSLOPE][b])/S[i-KSLOPE][b]*100.0; double thr = 0.25*atr_pct; string row = StringFormat("%s,%s,%sx%s,%s,%s,%d,", TimeToString(tm[i],TIME_DATE),sym,SER[a],SER[b],SER[a],SER[b],dir); row += DoubleToString(price,digits)+","+DoubleToString(med,digits)+","; for(int k=2;kn-1 || S[i][0]<=0) { row += ",,,,,"; continue; } double ret=(cl[iH]-cl[i])/cl[i]*100.0; double mxh=-1e18,mnl=1e18; for(int j=i+1;j<=iH;j++){ if(hi[j]>mxh)mxh=hi[j]; if(lo[j]thr)?1:((ret<-thr)?-1:0); int rev=(b2rev>0 && b2rev<=h)?1:0; row += ","+DoubleToString(ret,5)+","+DoubleToString(mfe,5)+"," +DoubleToString(mae,5)+","+IntegerToString(dlab)+","+IntegerToString(rev); } row += bpath; // traiettoria forward (uguale per ogni coppia di questa barra) row += ","+(b2rev>0?IntegerToString(b2rev):"")+","+DoubleToString(discMax,5); FileWriteString(fh,row+"\r\n"); rows++; } if((i%200)==0) Comment(StringFormat("PaPP export: %d/%d barre, %d eventi",i-iStart,iEnd-iStart,(int)rows)); } FileClose(fh); if(fhB!=INVALID_HANDLE) FileClose(fhB); for(int m=0;m<7;m++) IndicatorRelease(hMA[m]); IndicatorRelease(hATR); Comment(""); PrintFormat("PaPP export COMPLETATO: %d incroci -> %s (cartella MQL5\\Files)",(int)rows,fname); if(InpBaseline) PrintFormat("Baseline: %d barre -> PaPP_bars_%s_D1.csv",(int)brows,sym); Print("Periodo: ",TimeToString(tm[iStart])," -> ",TimeToString(tm[iEnd])); } //+------------------------------------------------------------------+