//+------------------------------------------------------------------+ //| ExportAll.mq5 - bars (per timeframe list) to Common\Files | //| Throwaway research tool. Opens no trades. | //| | //| Run via the strategy tester with an ini whose tested symbol has | //| the DEEPEST history (EURUSD D1 from 1995): the tester only | //| serves history from ~1 year before FromDate, so the tested | //| symbol's range sets the ceiling for every CopyRates below. | //| | //| NOTE: H4 requests for symbols other than the tested one failed | //| with err=4401 (history not ready) on a D1 pass. Export H4 in a | //| SEPARATE H4 pass rather than expecting one run to do both. | //| The calendar is NOT exportable here at all - see ExportCalendar. | //+------------------------------------------------------------------+ #property copyright "claude" #property version "1.10" input string ExportTag = "bars"; input string SymbolsD1 = "SP500,NAS100,US30,DAX40,UK100,ESXEUR,F40EUR,JPN225,ASXAUD,HSIHKD,IBXEUR,EURUSD,GBPUSD,USDJPY,USDCHF,USDCAD,AUDUSD,NZDUSD,EURJPY,EURGBP,GBPJPY,AUDJPY,XAUUSD,XAGUSD,XTIUSD,XBRUSD,BTCUSD,ETHUSD"; input string SymbolsH4 = ""; input bool DoCalendar = false; bool DumpBars(const string sym, const ENUM_TIMEFRAMES tf) { MqlRates r[]; ArraySetAsSeries(r, false); // oldest -> newest, matches numpy int got = CopyRates(sym, tf, 0, 500000, r); if(got <= 0) { PrintFormat("ExportAll: %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) 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("ExportAll: %s %s -> %d bars (%s .. %s)", sym, EnumToString(tf), got, TimeToString(r[0].time, TIME_DATE), TimeToString(r[got - 1].time, TIME_DATE)); return true; } void DumpList(const string list, const ENUM_TIMEFRAMES tf, int &ok, int &fail) { string syms[]; int n = StringSplit(list, ',', syms); for(int i = 0; i < n; i++) { string s = syms[i]; StringTrimLeft(s); StringTrimRight(s); if(StringLen(s) == 0) continue; //--- without SymbolSelect an unlisted symbol reads back as zero bars and //--- looks like missing history rather than an unselected symbol. if(!SymbolSelect(s, true)) PrintFormat("ExportAll: SymbolSelect(%s) failed (err=%d)", s, GetLastError()); if(DumpBars(s, tf)) ok++; else fail++; } } //--- 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) { int ok = 0, fail = 0; if(StringLen(SymbolsD1) > 0) DumpList(SymbolsD1, PERIOD_D1, ok, fail); if(StringLen(SymbolsH4) > 0) DumpList(SymbolsH4, PERIOD_H4, ok, fail); PrintFormat("ExportAll: DONE bars ok=%d fail=%d", ok, fail); } int OnInit(void) { return(INIT_SUCCEEDED); } void OnTick(void) { }