//+------------------------------------------------------------------+ //| EP_WalkForward.mq5 | //| MMQ — Muhammad Minhas Qamar | //| www.mql5.com/en/articles/24757 | //+------------------------------------------------------------------+ #property copyright "MMQ — Muhammad Minhas Qamar" #property link "https://www.mql5.com/en/articles/24757" #property version "1.00" #property strict #property script_show_inputs #property description "Walks forward through a basket's history and forecasts the book's next-bar" #property description "VaR and ES from each probability vector, using only the bars before it." #property description "Scores coverage, the joint VaR-ES loss, and the variance forecast." #include #include #include #include #include #include input group "Data" input string InpSymbols = "EURUSD,GBPUSD,AUDUSD,USDJPY,USDCHF"; // basket input string InpWeights = "0.2,0.2,0.2,-0.2,-0.2"; // book notional per symbol, same order input int InpBars = 5000; // D1 bars requested per symbol input group "Test" input int InpWarmup = 1000; // rows before the first forecast input double InpLevel = 0.025; // tail level for VaR and ES input group "Methods" input int InpWindow = 250; // long rolling window input int InpShortWindow = 60; // short rolling window input double InpHalfLife = 250.0; // decay half-life, bars input int InpStateWindow = 20; // trailing volatility of the book, bars input double InpKernelBand = 0.5; // kernel bandwidth, share of the state's std input double InpMinEns = 250; // scenario budget for conditioning //--- the forecasters, in table order enum ENUM_METHOD { M_ROLLING, // rolling window, long M_ROLLING_SHORT, // rolling window, short M_DECAY, // exponential decay M_EWMA, // RiskMetrics variance with a normal tail M_KERNEL, // decay times a Gaussian kernel on the state M_STATE_FREE, // entropy pooling on the state, no budget M_STATE, // entropy pooling on the state, ENS budget M_COUNT }; //--- running scores of one forecaster struct SScore { int hits; // bars at or below the VaR int degenerate; // bars whose tail held no loss to average double ens_sum; double ens_min; double fz[]; // joint VaR-ES loss per bar double ql[]; // QLIKE loss of the variance per bar }; //+------------------------------------------------------------------+ //| Split a comma list, trimming spaces. | //+------------------------------------------------------------------+ int SplitList(const string text,string &out[]) { const int n=StringSplit(text,',',out); for(int i=0;i0 && hits0.0 ? mu/MathSqrt(lr/n) : 0.0); } //+------------------------------------------------------------------+ //| Probability vectors over the rows before r only. | //+------------------------------------------------------------------+ void RollingBefore(const int T,const int r,const int window,vector &p) { p.Init(T); p.Fill(0.0); const int a=MathMax(0,r-window); for(int i=a;i=0.0 || vol<=0.0) { score[m].degenerate++; score[m].fz[s]=0.0; score[m].ql[s]=0.0; continue; } score[m].fz[s]=Fz0(y,var,es,InpLevel); score[m].ql[s]=MathLog(vol*vol)+y*y/(vol*vol); } } const string names[M_COUNT]={StringFormat("rolling %d",InpWindow),StringFormat("rolling %d",InpShortWindow), StringFormat("decay %.0f",InpHalfLife),"EWMA 0.94 normal","decay x kernel", "state, no budget",StringFormat("state, ENS >= %.0f",InpMinEns)}; PrintFormat("EP_WalkForward: %d forecasts in %u ms",N,GetTickCount()-t0); PrintFormat("%-18s %6s %6s %7s %8s %9s %8s %8s %8s %9s","method","ENS","minENS","hits", "Kupiec p","FZ0","DM roll","DM decay","DM kern","QLIKE"); for(int m=0;m