//+------------------------------------------------------------------+ //| CustomOrderSend.mq5 | //| Copyright 2022, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "2022, MetaQuotes Ltd." #property link "https://www.mql5.com" #property description "Simulate trades by market and pending orders in internal account classes." #property description "Trades are performed manually (ad hoc from keyboard), which mimics a Trade Panel." #define SHOW_WARNINGS // output extended info into the log, with changes in data state #define WARNING Print // use simple Print for warnings (instead of a built-in format with line numbers etc.) #include "..\..\Include\CustomTrade.mqh" #include "..\..\Include\MqlTradeSync.mqh" input double Volume; // Volume (0 = minimal lot) input int Distance2SLTP = 0; // Distance to SL/TP in points (0 = no) const double Lot = Volume == 0 ? SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN) : Volume; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { if(AccountInfoInteger(ACCOUNT_TRADE_MODE) != ACCOUNT_TRADE_MODE_DEMO) { Alert("This is a test EA! Run it on a DEMO account only!"); return INIT_FAILED; } // setup timer for periodic trade state display EventSetTimer(1); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Keyboard scan codes | //+------------------------------------------------------------------+ #define KEY_B 66 #define KEY_C 67 #define KEY_D 68 #define KEY_L 76 #define KEY_R 82 #define KEY_S 83 #define KEY_U 85 //+------------------------------------------------------------------+ //| Chart events handler for keyboard monitoring | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(id == CHARTEVENT_KEYDOWN) { MqlTradeRequestSync request; const double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); const double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); const double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); switch((int)lparam) { case KEY_B: request.buy(Lot, 0, Distance2SLTP ? ask - point * Distance2SLTP : Distance2SLTP, Distance2SLTP ? ask + point * Distance2SLTP : Distance2SLTP); break; case KEY_S: request.sell(Lot, 0, Distance2SLTP ? bid + point * Distance2SLTP : Distance2SLTP, Distance2SLTP ? bid - point * Distance2SLTP : Distance2SLTP); break; case KEY_U: if(Distance2SLTP) { request.buyLimit(Lot, ask - point * Distance2SLTP); } break; case KEY_L: if(Distance2SLTP) { request.sellLimit(Lot, bid + point * Distance2SLTP); } break; case KEY_C: for(int i = PositionsTotal() - 1; i >= 0; i--) { request.close(PositionGetTicket(i)); } break; case KEY_D: for(int i = OrdersTotal() - 1; i >= 0; i--) { request.remove(OrderGetTicket(i)); } break; case KEY_R: CustomTrade::PrintTradeHistory(); break; } } } //+------------------------------------------------------------------+ //| Timer event handler | //+------------------------------------------------------------------+ void OnTimer() { Comment(CustomTrade::ReportTradeState()); CustomTrade::DisplayTrades(); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int) { Comment(""); } //+------------------------------------------------------------------+