Warrior_EA/Scripts/ExportIndicatorBuffers.mq5

185 lines
6.1 KiB
MQL5

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