185 lines
6.1 KiB
MQL5
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);
| |||
}
| |||
//+------------------------------------------------------------------+
|