//+------------------------------------------------------------------+ //| GrayMatrixTrade.mqh | //| Jay Davis | //| 512jay.github.io | //+------------------------------------------------------------------+ #property copyright "Jay Davis" #property link "512jay.github.io" #property version "1.03" #include "Database.mqh" #include input bool RunInVirtualMode = false; // Run in virtual mode? //+------------------------------------------------------------------+ //| Wrapper class for CTrade class | //+------------------------------------------------------------------+ class GrayMatrixTrade : public CTrade { private: protected: public: GrayMatrixTrade(); ~GrayMatrixTrade(); virtual bool OrderSend(const MqlTradeRequest &request, MqlTradeResult &result); bool PositionModify(const string symbol, const double sl, const double tp); bool PositionModify(const ulong ticket, const double sl, const double tp); virtual bool PositionClose(const ulong ticket, const ulong deviation); virtual bool PositionClose(const string symbol, const ulong deviation); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ GrayMatrixTrade::GrayMatrixTrade() { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ GrayMatrixTrade::~GrayMatrixTrade() { } //+------------------------------------------------------------------+ //| Send order | //+------------------------------------------------------------------+ bool GrayMatrixTrade::OrderSend(const MqlTradeRequest &request, MqlTradeResult &result) { if(!MQLInfoInteger(MQL_TESTER)) { MqlTradeRequest aRequest = request; bool inserted = InsertMqlTradeRequest(aRequest); if(RunInVirtualMode) if(inserted) return true; else return false; } bool res; string action=""; string fmt =""; //--- action if(m_async_mode) res=::OrderSendAsync(request, result); else res=::OrderSend(request, result); //--- check if(res) { if(m_log_level>LOG_LEVEL_ERRORS) PrintFormat(__FUNCTION__+": %s [%s]", FormatRequest(action, request), FormatRequestResult(fmt, request, result)); } else { if(m_log_level>LOG_LEVEL_NO) PrintFormat(__FUNCTION__+": %s [%s]", FormatRequest(action, request), FormatRequestResult(fmt, request, result)); } //--- return the result return(res); } //+------------------------------------------------------------------+ //| Close specified opened position | //+------------------------------------------------------------------+ bool GrayMatrixTrade::PositionClose(const string symbol, const ulong deviation=ULONG_MAX) { //Print(__FUNCTION__,__FUNCSIG__); bool partial_close=false; int retry_count =10; uint retcode =TRADE_RETCODE_REJECT; //--- check stopped if(IsStopped(__FUNCTION__)) return(false); //--- clean ClearStructures(); m_request.comment ="closed"; // Set special identifying information. //--- check filling if(!FillingCheck(symbol)) return(false); do { //--- check if(SelectPosition(symbol)) { if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) { //--- prepare request for close BUY position m_request.type =ORDER_TYPE_SELL; m_request.price=SymbolInfoDouble(symbol, SYMBOL_BID); } else { //--- prepare request for close SELL position m_request.type =ORDER_TYPE_BUY; m_request.price=SymbolInfoDouble(symbol, SYMBOL_ASK); } } else { //--- position not found m_result.retcode=retcode; return(false); } //--- setting request m_request.action =TRADE_ACTION_DEAL; m_request.symbol =symbol; m_request.volume =PositionGetDouble(POSITION_VOLUME); m_request.magic =m_magic; m_request.deviation=(deviation==ULONG_MAX) ? m_deviation : deviation; //--- check volume double max_volume=SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX); if(m_request.volume>max_volume) { m_request.volume=max_volume; partial_close=true; } else partial_close=false; //--- hedging? just send order if(IsHedging()) { m_request.position=PositionGetInteger(POSITION_TICKET); return(OrderSend(m_request, m_result)); } //--- order send if(!OrderSend(m_request, m_result)) { if(--retry_count!=0) continue; if(retcode==TRADE_RETCODE_DONE_PARTIAL) m_result.retcode=retcode; return(false); } //--- WARNING. If position volume exceeds the maximum volume allowed for deal, //--- and when the asynchronous trade mode is on, for safety reasons, position is closed not completely, //--- but partially. It is decreased by the maximum volume allowed for deal. if(m_async_mode) break; retcode=TRADE_RETCODE_DONE_PARTIAL; if(partial_close) Sleep(1000); } while(partial_close); //--- succeed return(true); } //+------------------------------------------------------------------+ //| Close specified opened position | //+------------------------------------------------------------------+ bool GrayMatrixTrade::PositionClose(const ulong ticket, const ulong deviation=ULONG_MAX) { //--- check stopped if(IsStopped(__FUNCTION__)) return(false); //--- check position existence if(!PositionSelectByTicket(ticket)) return(false); string symbol=PositionGetString(POSITION_SYMBOL); //--- clean ClearStructures(); m_request.comment ="closed"; // Set special identifying information. //--- check filling if(!FillingCheck(symbol)) return(false); //--- check if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) { //--- prepare request for close BUY position m_request.type =ORDER_TYPE_SELL; m_request.price=SymbolInfoDouble(symbol, SYMBOL_BID); } else { //--- prepare request for close SELL position m_request.type =ORDER_TYPE_BUY; m_request.price=SymbolInfoDouble(symbol, SYMBOL_ASK); } //--- setting request m_request.action =TRADE_ACTION_DEAL; m_request.position =ticket; m_request.symbol =symbol; m_request.volume =PositionGetDouble(POSITION_VOLUME); m_request.magic =m_magic; m_request.deviation=(deviation==ULONG_MAX) ? m_deviation : deviation; //--- close position return(OrderSend(m_request, m_result)); } //+------------------------------------------------------------------+ //| Modify specified opened position | //+------------------------------------------------------------------+ bool GrayMatrixTrade::PositionModify(const string symbol, const double sl, const double tp) { //--- check stopped if(IsStopped(__FUNCTION__)) return(false); //--- check position existence if(!SelectPosition(symbol)) return(false); //--- clean ClearStructures(); //--- setting request m_request.action =TRADE_ACTION_SLTP; m_request.symbol =symbol; m_request.magic =m_magic; m_request.sl =sl; m_request.tp =tp; m_request.position=PositionGetInteger(POSITION_TICKET); //--- action and return the result return(OrderSend(m_request, m_result)); } //+------------------------------------------------------------------+ //| Modify specified opened position | //+------------------------------------------------------------------+ bool GrayMatrixTrade::PositionModify(const ulong ticket, const double sl, const double tp) { Print(__FUNCTION__); //--- check stopped if(IsStopped(__FUNCTION__)) return(false); //--- check position existence if(!PositionSelectByTicket(ticket)) return(false); //--- clean ClearStructures(); //--- setting request m_request.action =TRADE_ACTION_SLTP; m_request.position=ticket; m_request.symbol =PositionGetString(POSITION_SYMBOL); m_request.magic =m_magic; m_request.sl =sl; m_request.tp =tp; //--- action and return the result return(OrderSend(m_request, m_result)); } //+------------------------------------------------------------------+