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