//+------------------------------------------------------------------+ //| ExportIndicatorBuffers.mq5 | //| Dump every buffer of the AD/Wyckoff indicator suite over full | //| history to CSV, so the research pipeline can use the PRODUCTION | //| definitions instead of a Python re-implementation of them. | //| | //| Read-only: creates indicator handles, copies buffers, writes | //| files under Common\Files\Warrior_EA\indicators\. No orders, no | //| chart changes, no writes to any model or AltData file. | //| | //| Buffer counts are not exposed by the API for a custom indicator, | //| so each is probed from 0 upward until a copy fails - that is the | //| only way to learn the count, and a failed probe is not an error. | //+------------------------------------------------------------------+ #property script_show_inputs #property strict input string InpSymbols = "EURUSD,GBPUSD,USDJPY,AUDUSD,USDCAD,XAUUSD,SP500,BTCUSD"; input string InpTimeframes = "M15,H1"; // must match the research timeframes input int InpMaxBars = 400000; // per symbol/timeframe input int InpMaxBuffers = 12; // probe ceiling string IndicatorList[] = {"ADCumulativeDelta", "ADShorteningOfThrust", "ADWyckoffEventStream", "ADWyckoffFailedStructure", "ADWyckoffSignificantBarInversion", "ADZigZag", "ADVolume", "ADTWAP"}; ENUM_TIMEFRAMES TfFromString(const string s) { if(s == "M1") return PERIOD_M1; if(s == "M5") return PERIOD_M5; 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; return PERIOD_CURRENT; } //--- how many buffers does this handle actually publish? int ProbeBuffers(const int h, const int bars) { double tmp[]; int n = 0; for(int b = 0; b < InpMaxBuffers; b++) { if(CopyBuffer(h, b, 0, MathMin(16, bars), tmp) <= 0) break; n++; } return n; } bool ExportOne(const string sym, const string tfName, const string indName) { ENUM_TIMEFRAMES tf = TfFromString(tfName); int have = Bars(sym, tf); if(have <= 100) { PrintFormat(" %s %s %s: only %d bars, skipped", sym, tfName, indName, have); return false; } int bars = MathMin(have, InpMaxBars); int h = iCustom(sym, tf, indName); if(h == INVALID_HANDLE) { PrintFormat(" %s %s %s: INVALID_HANDLE err=%d", sym, tfName, indName, GetLastError()); return false; } //--- an indicator needs a moment to calculate its first pass over deep history int spins = 0; while(BarsCalculated(h) < bars && spins < 600) { Sleep(100); spins++; } int ready = BarsCalculated(h); if(ready <= 100) { PrintFormat(" %s %s %s: BarsCalculated=%d, skipped", sym, tfName, indName, ready); IndicatorRelease(h); return false; } bars = MathMin(bars, ready); int nbuf = ProbeBuffers(h, bars); if(nbuf <= 0) { PrintFormat(" %s %s %s: no readable buffers", sym, tfName, indName); IndicatorRelease(h); return false; } //--- pull the buffers and the bar times, oldest-first datetime times[]; if(CopyTime(sym, tf, 0, bars, times) <= 0) { IndicatorRelease(h); return false; } ArraySetAsSeries(times, false); double buf[][12]; ArrayResize(buf, bars); double one[]; for(int b = 0; b < nbuf; b++) { if(CopyBuffer(h, b, 0, bars, one) <= 0) continue; ArraySetAsSeries(one, false); for(int i = 0; i < bars && i < ArraySize(one); i++) buf[i][b] = one[i]; } string dir = "Warrior_EA\\indicators"; FolderCreate(dir, FILE_COMMON); string path = dir + "\\" + sym + "_" + tfName + "_" + indName + ".csv"; int fh = FileOpen(path, FILE_WRITE | FILE_TXT | FILE_ANSI | FILE_COMMON | FILE_SHARE_READ | FILE_SHARE_WRITE); if(fh == INVALID_HANDLE) { PrintFormat(" cannot write %s err=%d", path, GetLastError()); IndicatorRelease(h); return false; } string head = "time"; for(int b = 0; b < nbuf; b++) head += ",b" + IntegerToString(b); FileWriteString(fh, head + "\n"); int written = 0; for(int i = 0; i < bars; i++) { //--- skip the leading warm-up where every buffer is still empty bool any = false; for(int b = 0; b < nbuf; b++) if(buf[i][b] != EMPTY_VALUE && MathAbs(buf[i][b]) < 1e15) { any = true; break; } if(!any) continue; string line = IntegerToString((long)times[i]); for(int b = 0; b < nbuf; b++) { double v = buf[i][b]; line += "," + ((v == EMPTY_VALUE || MathAbs(v) >= 1e15) ? "" : DoubleToString(v, 8)); } FileWriteString(fh, line + "\n"); written++; } FileClose(fh); IndicatorRelease(h); PrintFormat(" %s %s %-34s %d buffers, %d rows", sym, tfName, indName, nbuf, written); return true; } void OnStart() { string syms[], tfs[]; int ns = StringSplit(InpSymbols, ',', syms); int nt = StringSplit(InpTimeframes, ',', tfs); int ok = 0, fail = 0; for(int s = 0; s < ns; s++) { string sym = syms[s]; StringTrimLeft(sym); StringTrimRight(sym); if(!SymbolSelect(sym, true)) { PrintFormat(" %s: not available on this server", sym); continue; } for(int t = 0; t < nt; t++) { string tfn = tfs[t]; StringTrimLeft(tfn); StringTrimRight(tfn); for(int k = 0; k < ArraySize(IndicatorList); k++) { if(ExportOne(sym, tfn, IndicatorList[k])) ok++; else fail++; } } } PrintFormat("ExportIndicatorBuffers: %d exported, %d skipped -> Common\\Files\\Warrior_EA\\indicators", ok, fail); } //+------------------------------------------------------------------+