//+------------------------------------------------------------------+ //| EP_Checks.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 "Checks the entropy pooling library against results known in closed form," #property description "on synthetic Gaussian scenarios: identities, the exponential tilt, bounds," #property description "infeasibility, marginal cost, second-moment views and the scenario budget." #include #include #include #include #include #include input int InpRows = 200000; // synthetic scenarios input int InpSeed = 7; // random seed int g_failed=0; //+------------------------------------------------------------------+ //| One line per check: the measured miss against its tolerance. | //+------------------------------------------------------------------+ void Check(const string what,const double miss,const double tol) { const bool ok=(MathIsValidNumber(miss) && MathAbs(miss)<=tol); if(!ok) g_failed++; PrintFormat(" %-52s %10.2e (tol %.0e) %s",what,miss,tol,(ok ? "ok" : "FAILED")); } //+------------------------------------------------------------------+ //| Three correlated Gaussian returns, T rows. | //+------------------------------------------------------------------+ void Gaussian(const int T,const int seed,CEpScenarios &scen) { MathSrand(seed); const double L[3][3]={{0.010,0.0,0.0},{0.006,0.008,0.0},{-0.002,0.003,0.012}}; matrix x; x.Init(T,3); int err=0; for(int t=0;t= view gives the equality posterior; a slack one the prior vector qe=q; CEpViews bind; bind.AddMean(0,EP_AT_LEAST,ma+0.5*sa); bind.Pool(scen,p,solver,q,r); Check("binding >= view against the equality posterior, * T",MaxDiff(q,qe)*T,1e-9); //--- 4. a view no reweighting can reach is reported CEpViews reach; reach.AddMean(0,EP_EQUAL,a.Max()+0.001); const bool pooled=reach.Pool(scen,p,solver,q,r); Check("unreachable mean view reported as infeasible",(!pooled && r.status==EP_INFEASIBLE ? 0.0 : 1.0),0.0); //--- 5. the multiplier is the price of moving the target const double c0=ma+0.3*sa,h=1e-6*sa; double cost=0.0,unused=0.0; const double up=EntropyAt(scen,p,solver,c0+h,unused); const double dn=EntropyAt(scen,p,solver,c0-h,unused); EntropyAt(scen,p,solver,c0,cost); Check("marginal cost against a finite difference, relative",cost/((up-dn)/(2.0*h))-1.0,1e-6); //--- 6. volatility and correlation views land after re-referencing passes CEpViews moments; moments.AddVolatility(0,EP_EQUAL,1.3*sa); moments.AddCorrelation(0,1,EP_EQUAL,0.80); moments.Pool(scen,p,solver,q,r); Check("vol view met, relative",EpVolatility(a,q)/(1.3*sa)-1.0,1e-9); Check("correlation view met",EpCorrelation(a,b,q)-0.80,1e-9); PrintFormat(" second-moment views took %d passes and %u ms",moments.Passes(),r.ms); //--- 7. a tail probability view is linear and exact CEpViews tail; tail.AddTail(0,ma-2.0*sa,EP_EQUAL,0.05); tail.Pool(scen,p,solver,q,r); Check("tail probability view met",EpTailProbability(a,q,ma-2.0*sa)-0.05,1e-12); //--- 8. conditioning never leaves fewer scenarios than the budget double absa[]; ArrayResize(absa,T); for(int t=0;t