| //+------------------------------------------------------------------+
|
| //| 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) { }
|