//+------------------------------------------------------------------+ //| Dump4.mqh | //| Copyright 2026, Allan NiƱal | //| https://www.allanninal.dev/mql5 | //+------------------------------------------------------------------+ //| MT4 test harness for an indicator, run as an EA in the Strategy | //| Tester (MT4 iCustom takes its inputs at compile time, so the | //| test EA defines IndValue(buf,shift) with its iCustom call | //| BEFORE including this file). | //| During the test: on every new bar, records which signal buffers | //| are set on the bar that just closed; on every tick, counts | //| signals drawn on the live bar (must stay 0). | //| At the end (tester/files): | //| __.csv time,open,high,low,close,b... | //| for every bar (empty = no value) | //| repaint___.csv closed bars checked, signals | //| seen live, mismatches with the | //| final values, live-bar signals | //+------------------------------------------------------------------+ // SPDX-License-Identifier: LicenseRef-PolyForm-Noncommercial-1.0.0 (see LICENSE) #property strict //--- a test EA may #define DUMP4_BUFFERS / DUMP4_PROBE before the include #ifndef DUMP4_BUFFERS #define DUMP4_BUFFERS "0,2,3" #endif #ifndef DUMP4_PROBE #define DUMP4_PROBE "2,3" #endif input string InpTag = "default"; // Tag for the output file names input string InpBuffers = DUMP4_BUFFERS; // Buffers to dump input string InpProbe = DUMP4_PROBE; // Signal buffers checked for repainting int g_bufs[],g_probe[]; datetime g_bar=0; datetime g_rec_t[]; int g_rec_i[]; // the bar's position counted from the oldest bar (stable as bars are added) int g_rec_f[]; int g_rec_n=0,g_live0=0; void ParseInts(const string text,int &out[]) { string parts[]; int n=StringSplit(text,',',parts); ArrayResize(out,n); for(int k=0; k=0; s--) { string row=TimeToString(Time[s],TIME_DATE|TIME_MINUTES)+","+DoubleToString(Open[s],_Digits)+","+ DoubleToString(High[s],_Digits)+","+DoubleToString(Low[s],_Digits)+","+DoubleToString(Close[s],_Digits); for(int k=0; k=Bars || Time[s]!=g_rec_t[r]) { lost++; // the bar could not be found again: counts as a failure continue; } if(g_rec_f[r]!=0) sig++; if(Flags(s)!=g_rec_f[r]) bad++; } h=FileOpen("repaint_"+name,FILE_WRITE|FILE_TXT|FILE_ANSI); if(h!=INVALID_HANDLE) { FileWriteString(h,StringFormat("closed_bars_checked,%d\nsignals_seen_live,%d\nmismatches,%d\nlive_bar_signals,%d\nbars,%d\nnot_found,%d\n", g_rec_n-lost,sig,bad,g_live0,Bars,lost)); FileClose(h); } PrintFormat("Dump4 %s: %d bars dumped; %d closed bars checked (%d not found), %d signals, %d mismatches, %d live-bar signals", name,Bars,g_rec_n-lost,lost,sig,bad,g_live0); } double OnTester() { Finish(); return(0.0); } void OnDeinit(const int reason) { Finish(); } //+------------------------------------------------------------------+