forked from mnbvc188199/Warrior_EA
DumpSymbolSpecs exports symbol specifications and deal history so the research cost model uses the account's real commission and swap rather than assumptions. ExportIndicatorBuffers dumps every AD/Wyckoff indicator buffer over full history, so the research conditions on the PRODUCTION detectors rather than a Python re-implementation of them - which is what made the Wyckoff verdict a verdict on the indicators rather than on my approximation of them. Both are read-only: handles, CopyBuffer, and writes under Common\Files. No orders, no chart changes, no writes to any model or AltData file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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);
| |
}
| |
//+------------------------------------------------------------------+
|