//+------------------------------------------------------------------+ //| ExportBars.mq5 - dump OHLCV to Common\Files for research | //| Throwaway research tool. Opens no trades, reads no indicators. | //+------------------------------------------------------------------+ #property copyright "claude" #property version "1.10" input string ExportTag = "bars"; // file prefix input string ExportSymbols = "EURUSD,GBPUSD,USDJPY,USDCHF,USDCAD,AUDUSD,NZDUSD"; input string ExportPeriods = "H1,H4,D1"; ENUM_TIMEFRAMES TfFromString(const string s) { if(s == "M15") return PERIOD_M15; if(s == "M30") return PERIOD_M30; if(s == "H1") return PERIOD_H1; if(s == "H4") return PERIOD_H4; if(s == "D1") return PERIOD_D1; if(s == "W1") return PERIOD_W1; return PERIOD_CURRENT; } bool DumpOne(const string sym, const ENUM_TIMEFRAMES tf) { MqlRates r[]; ArraySetAsSeries(r, false); // oldest -> newest, matches numpy int got = -1; //--- a non-tested symbol's history may still be syncing on the first request for(int attempt = 0; attempt < 5 && got <= 0; attempt++) { got = CopyRates(sym, tf, 0, 500000, r); if(got <= 0) Sleep(1000); } if(got <= 0) { PrintFormat("ExportBars: %s %s -> CopyRates failed (err=%d)", sym, EnumToString(tf), GetLastError()); return false; } string name = StringFormat("%s_%s_%s.csv", ExportTag, sym, EnumToString(tf)); int h = FileOpen(name, FILE_WRITE | FILE_CSV | FILE_ANSI | FILE_COMMON, ','); if(h == INVALID_HANDLE) { PrintFormat("ExportBars: FileOpen %s failed (err=%d)", name, GetLastError()); return false; } FileWrite(h, "time", "open", "high", "low", "close", "tick_volume", "spread"); int digits = (int)SymbolInfoInteger(sym, SYMBOL_DIGITS); if(digits <= 0) digits = 5; for(int i = 0; i < got; i++) FileWrite(h, TimeToString(r[i].time, TIME_DATE | TIME_MINUTES), DoubleToString(r[i].open, digits), DoubleToString(r[i].high, digits), DoubleToString(r[i].low, digits), DoubleToString(r[i].close, digits), (string)r[i].tick_volume, (string)r[i].spread); FileClose(h); PrintFormat("ExportBars: %s %s -> %d bars (%s .. %s) file=%s", sym, EnumToString(tf), got, TimeToString(r[0].time, TIME_DATE), TimeToString(r[got - 1].time, TIME_DATE), name); return true; } //--- OnDeinit, not OnInit: by then the tester has walked the whole range, so //--- CopyRates returns every bar of the pass rather than only the warm-up. void OnDeinit(const int reason) { string syms[], tfs[]; int ns = StringSplit(ExportSymbols, ',', syms); int nt = StringSplit(ExportPeriods, ',', tfs); int ok = 0, fail = 0; for(int i = 0; i < ns; i++) { string sym = syms[i]; StringTrimLeft(sym); StringTrimRight(sym); if(StringLen(sym) == 0) continue; //--- nudge the symbol into the working set; without this a symbol that is //--- not in Market Watch reads back as zero bars and looks like missing //--- history rather than an unselected symbol. if(!SymbolSelect(sym, true)) PrintFormat("ExportBars: SymbolSelect(%s) failed (err=%d)", sym, GetLastError()); for(int j = 0; j < nt; j++) { string t = tfs[j]; StringTrimLeft(t); StringTrimRight(t); ENUM_TIMEFRAMES tf = TfFromString(t); if(tf == PERIOD_CURRENT) continue; if(DumpOne(sym, tf)) ok++; else fail++; } } PrintFormat("ExportBars: DONE ok=%d fail=%d", ok, fail); } int OnInit(void) { return(INIT_SUCCEEDED); } void OnTick(void) { }