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