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>
132 lines
7.2 KiB
MQL5
132 lines
7.2 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| DumpSymbolSpecs.mq5 |
|
|
//| Write every Market Watch symbol's contract and SWAP specification |
|
|
//| to Common\Files\Warrior_EA\symbol_specs.csv, for the research |
|
|
//| cost model. Read-only: no orders, no chart changes. |
|
|
//| |
|
|
//| Swap is the reason this exists. Bar history carries no swap, and |
|
|
//| the research policy is to charge the CURRENT swap, negative on |
|
|
//| both sides, every night, with the 3-day rollover applied. Whether |
|
|
//| SYMBOL_SWAP_LONG/SHORT is the per-night figure or already the |
|
|
//| tripled one is NOT answered by the API; this dump records what |
|
|
//| the spec says together with SYMBOL_SWAP_ROLLOVER3DAYS so the |
|
|
//| research side can compare it against a real deal's DEAL_SWAP. |
|
|
//+------------------------------------------------------------------+
|
|
#property script_show_inputs
|
|
#property strict
|
|
|
|
input bool AllSymbols = true; // true = every symbol the server offers, false = Market Watch only
|
|
|
|
string Q(const string s) { return "\"" + s + "\""; }
|
|
|
|
void OnStart()
|
|
{
|
|
string dir = "Warrior_EA";
|
|
FolderCreate(dir, FILE_COMMON);
|
|
string path = dir + "\\symbol_specs.csv";
|
|
int h = FileOpen(path, FILE_WRITE | FILE_TXT | FILE_ANSI | FILE_COMMON | FILE_SHARE_READ | FILE_SHARE_WRITE);
|
|
if(h == INVALID_HANDLE)
|
|
{
|
|
Print("DumpSymbolSpecs: cannot open ", path, " err=", GetLastError());
|
|
return;
|
|
}
|
|
FileWriteString(h, "symbol,path,digits,point,contract_size,tick_size,tick_value,calc_mode,trade_mode,"
|
|
"swap_mode,swap_long,swap_short,swap_3days,spread_now,spread_float,"
|
|
"currency_base,currency_profit,currency_margin,volume_min,volume_step,volume_max,"
|
|
"session_deals,server_time\n");
|
|
int total = SymbolsTotal(!AllSymbols);
|
|
int written = 0;
|
|
for(int i = 0; i < total; i++)
|
|
{
|
|
string s = SymbolName(i, !AllSymbols);
|
|
if(s == "")
|
|
continue;
|
|
//--- SymbolInfo* on a symbol that is not selected returns stale zeros for some fields;
|
|
//--- select it for the read and leave the Market Watch as we found it.
|
|
bool wasSelected = SymbolInfoInteger(s, SYMBOL_SELECT) != 0;
|
|
if(!wasSelected)
|
|
SymbolSelect(s, true);
|
|
string line = Q(s) + "," + Q(SymbolInfoString(s, SYMBOL_PATH)) + ","
|
|
+ IntegerToString(SymbolInfoInteger(s, SYMBOL_DIGITS)) + ","
|
|
+ DoubleToString(SymbolInfoDouble(s, SYMBOL_POINT), 8) + ","
|
|
+ DoubleToString(SymbolInfoDouble(s, SYMBOL_TRADE_CONTRACT_SIZE), 4) + ","
|
|
+ DoubleToString(SymbolInfoDouble(s, SYMBOL_TRADE_TICK_SIZE), 8) + ","
|
|
+ DoubleToString(SymbolInfoDouble(s, SYMBOL_TRADE_TICK_VALUE), 6) + ","
|
|
+ IntegerToString(SymbolInfoInteger(s, SYMBOL_TRADE_CALC_MODE)) + ","
|
|
+ IntegerToString(SymbolInfoInteger(s, SYMBOL_TRADE_MODE)) + ","
|
|
+ IntegerToString(SymbolInfoInteger(s, SYMBOL_SWAP_MODE)) + ","
|
|
+ DoubleToString(SymbolInfoDouble(s, SYMBOL_SWAP_LONG), 6) + ","
|
|
+ DoubleToString(SymbolInfoDouble(s, SYMBOL_SWAP_SHORT), 6) + ","
|
|
+ IntegerToString(SymbolInfoInteger(s, SYMBOL_SWAP_ROLLOVER3DAYS)) + ","
|
|
+ IntegerToString(SymbolInfoInteger(s, SYMBOL_SPREAD)) + ","
|
|
+ IntegerToString(SymbolInfoInteger(s, SYMBOL_SPREAD_FLOAT)) + ","
|
|
+ Q(SymbolInfoString(s, SYMBOL_CURRENCY_BASE)) + ","
|
|
+ Q(SymbolInfoString(s, SYMBOL_CURRENCY_PROFIT)) + ","
|
|
+ Q(SymbolInfoString(s, SYMBOL_CURRENCY_MARGIN)) + ","
|
|
+ DoubleToString(SymbolInfoDouble(s, SYMBOL_VOLUME_MIN), 4) + ","
|
|
+ DoubleToString(SymbolInfoDouble(s, SYMBOL_VOLUME_STEP), 4) + ","
|
|
+ DoubleToString(SymbolInfoDouble(s, SYMBOL_VOLUME_MAX), 4) + ","
|
|
+ IntegerToString(SymbolInfoInteger(s, SYMBOL_SESSION_DEALS)) + ","
|
|
+ TimeToString(TimeTradeServer(), TIME_DATE | TIME_SECONDS) + "\n";
|
|
FileWriteString(h, line);
|
|
written++;
|
|
if(!wasSelected)
|
|
SymbolSelect(s, false);
|
|
}
|
|
FileClose(h);
|
|
Print("DumpSymbolSpecs: wrote ", written, " symbols to Common\\Files\\", path,
|
|
" (swap_mode: 0=disabled 1=points 2=base currency 3=margin currency 4=deposit currency "
|
|
"5=% annual current price 6=% annual open price 7=points reopen 8=% reopen)");
|
|
DumpDeals(dir);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| The account's own deal history - the only ground truth for what a |
|
|
//| swap "point" and a commission actually cost. DEAL_SWAP is booked |
|
|
//| on the closing deal for the whole life of the position; paired |
|
|
//| with the opening deal of the same position id it yields the swap |
|
|
//| per lot per night that the spec's figure has to reproduce. |
|
|
//+------------------------------------------------------------------+
|
|
void DumpDeals(const string dir)
|
|
{
|
|
datetime to = TimeCurrent();
|
|
datetime from = to - 400 * 86400;
|
|
if(!HistorySelect(from, to))
|
|
{
|
|
Print("DumpSymbolSpecs: HistorySelect failed err=", GetLastError());
|
|
return;
|
|
}
|
|
string path = dir + "\\deal_history.csv";
|
|
int h = FileOpen(path, FILE_WRITE | FILE_TXT | FILE_ANSI | FILE_COMMON | FILE_SHARE_READ | FILE_SHARE_WRITE);
|
|
if(h == INVALID_HANDLE)
|
|
{
|
|
Print("DumpSymbolSpecs: cannot open ", path, " err=", GetLastError());
|
|
return;
|
|
}
|
|
FileWriteString(h, "ticket,position_id,symbol,time,type,entry,volume,price,swap,commission,profit,magic,comment\n");
|
|
int n = HistoryDealsTotal();
|
|
int written = 0;
|
|
for(int i = 0; i < n; i++)
|
|
{
|
|
ulong t = HistoryDealGetTicket(i);
|
|
if(t == 0)
|
|
continue;
|
|
string line = IntegerToString((long)t) + ","
|
|
+ IntegerToString((long)HistoryDealGetInteger(t, DEAL_POSITION_ID)) + ","
|
|
+ Q(HistoryDealGetString(t, DEAL_SYMBOL)) + ","
|
|
+ TimeToString((datetime)HistoryDealGetInteger(t, DEAL_TIME), TIME_DATE | TIME_SECONDS) + ","
|
|
+ IntegerToString((long)HistoryDealGetInteger(t, DEAL_TYPE)) + ","
|
|
+ IntegerToString((long)HistoryDealGetInteger(t, DEAL_ENTRY)) + ","
|
|
+ DoubleToString(HistoryDealGetDouble(t, DEAL_VOLUME), 4) + ","
|
|
+ DoubleToString(HistoryDealGetDouble(t, DEAL_PRICE), 8) + ","
|
|
+ DoubleToString(HistoryDealGetDouble(t, DEAL_SWAP), 4) + ","
|
|
+ DoubleToString(HistoryDealGetDouble(t, DEAL_COMMISSION), 4) + ","
|
|
+ DoubleToString(HistoryDealGetDouble(t, DEAL_PROFIT), 4) + ","
|
|
+ IntegerToString((long)HistoryDealGetInteger(t, DEAL_MAGIC)) + ","
|
|
+ Q(HistoryDealGetString(t, DEAL_COMMENT)) + "\n";
|
|
FileWriteString(h, line);
|
|
written++;
|
|
}
|
|
FileClose(h);
|
|
Print("DumpSymbolSpecs: wrote ", written, " deals (last 400 days) to Common\\Files\\", path);
|
|
}
|
|
//+------------------------------------------------------------------+
|