//+------------------------------------------------------------------+ //| EasyTradeEvent_INCL.mqh | //| Calli | //| https://www.mql5.com/de/users/gooly | //+------------------------------------------------------------------+ #property copyright "Calli" #property link "https://www.mql5.com/de/users/gooly" //+------------------------------------------------------------------+ //| Enums | //+------------------------------------------------------------------+ enum €DeBug { €DebugNon, €DebugAll, €DebugSend, €DebugMatch, €DebugETE, €DebugConf, } WhatDebug; DBG_ENUM_RESOLVER(€DeBug); enum €SetMoveTpSl { €setTpSl, €MoveTpSl }; DBG_ENUM_RESOLVER(€SetMoveTpSl); enum €TrdType { €BUY, // 0 €SELL, // 1 €BUYSTOP, // 2 €SELLSTOP, // 3 €BUYLIMIT, // 4 €SELLLIMIT, // 5 €BUYSTOPLIMIT, // 6 €SELLSTOPLIMIT, // 7 €BuyPlanA, // 8 Buys of Strategy 1 €BuyPlanB, // 9 Buys of Strategy 2 €SellPlanA, // 10 Sells of Strategy 1 €SellPlanB, // 11 Sells of Strategy 2 €CLOSEBY, // 12 €BALANCE, // 13 Avoid cr/bal forum.mql4.com/32363#325360 €CREDIT, // 14 Never select canceled orders. €NOTyp, // 15 €NOSignal, // 16 €Send, // 17 Send Order PendingOrder || Buy €OK, // 18 €Fail, // 19 €ChgTpSl, // 20 €Placed, // 21 €Trigg, // 22 €Closed, // 23 €XlsTP, // 24 €XlsSL, // 25 €ExpAdv, // 26 €Manual, // 27 €StpOut, // 28 €Roll, // 29 €Margin, // 30 €Split, // 31 €TrDeal, // 32 €TrPend, // 33 €TrSlTp, // 34 €TrModif, // 35 €TrRmve, // 36 €TrClsBy, // 37 €Conf, // 38 €Open, // 39 €Close, // 40 €Reverse, // 41 €CloseBy, // 42 €NotFound, // 43 €NoOp, // 44 }; // %2==0 => BUY; %2==1 => Sell //*/ DBG_ENUM_RESOLVER(€TrdType); //+------------------------------------------------------------------+ //| defines | //+------------------------------------------------------------------+ #define fmax3(a,b,c) fmax(a,fmax(b,c)) #define fmin3(a,b,c) fmin(a,fmin(b,c)) #define _e2s(e) EnumToString(e) #define _d2D(p) DoubleToString(p,_Digits) #define _d21(p) DoubleToString(p,1) #define _d22(p) DoubleToString(p,2) #define _t2Sec(t) TimeToString(t,TIME_SECONDS) #define _t2All(t) TimeToString(t,TIME_DATE|TIME_SECONDS) #define matchPOS 0 #define matchCLS 1 #define matchMAG 2 #define FunLine __FUNCTION__+"["+(string)__LINE__+"] " //+------------------------------------------------------------------+ //| variables & structs | //+------------------------------------------------------------------+ /* match[][] is used to match a pending order as ProfitTarget. As soon as a PenOrd is triggered it can close an open pos if there is a match of ticket #1 and #2 and mag */ ulong match[][3]; //--- 3 Arrays the user need not to know them: MqlTradeRequest ReqFAIL[], // dealing with request that failed ReqCHCK[]; // check trading // to track open positions and orders e.g. to write a csv file after it was closed struct _opTrd { ulong uID, uMag, uDevOrInf; datetime tDiff, tUpd, tFrc, tOpn, tCls; double dStLim, dOpn, dUpd, dSL, dTP, dCls, dPrf, dVol; €TrdType dir, kind, status; } oPoBU[], oPoSE[], oOrBU[], oOrSE[], cLstBU = {}, cLstSE = {}; ulong DeBugORDER = 0; //+------------------------------------------------------------------+ //| tools | //+------------------------------------------------------------------+ string err(int e = -1, int fromLine = -1) { if ( e == -1 && _LastError == 0 ) { return(""); } if ( fromLine > 0 ) { return( StringFormat("L[%i] err:%i", fromLine, e) ); } return( StringFormat("err:%i", e) ); //ErrorDescription(e) } // for addong a struckt to an array of these structs template int ArrayAdd(T &arr[], const T &itm) { int i = ArraySize(arr), j = ArrayResize(arr, i + 1); if(j < i) { Print("ArrayAdd() FAILED: ", err()); } arr[i] = itm; return(i); } // for getting a new empty element of an array to fill it template int ArrayNew(T &arr[]) { int i = ArraySize(arr), j = ArrayResize(arr, i + 1); if(j < i) { Print("ArrayAd() FAILED: ", err()); } ZeroMemory(arr[i]); return(i); } template int ArrayNew(T &arr[][]) { int i = ArrayRange(arr, 0), j = ArrayResize(arr, i + 1); if(j < i) { Print("ArrayNew() FAILED: ", err()); } j = ArrayRange(arr, 1); while(j-- > 0) { arr[i][j] = 0; } return(i); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ €TrdType convOrdTyp(const ENUM_DEAL_ENTRY ot) { switch(ot) { case DEAL_ENTRY_IN: return(€Open); case DEAL_ENTRY_OUT: return(€Close); case DEAL_ENTRY_INOUT: return(€Reverse); case DEAL_ENTRY_OUT_BY: return(€CloseBy); } return(€NOTyp); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ €TrdType convOrdTyp(const ENUM_DEAL_REASON ot) { switch(ot) { case DEAL_REASON_CLIENT: return(€Manual); case DEAL_REASON_MOBILE: return(€Manual); case DEAL_REASON_WEB: return(€Manual); case DEAL_REASON_EXPERT: return(€ExpAdv); case DEAL_REASON_SL: return(€XlsSL); case DEAL_REASON_TP: return(€XlsTP); case DEAL_REASON_SO: return(€StpOut); case DEAL_REASON_ROLLOVER: return(€Roll); case DEAL_REASON_VMARGIN: return(€Margin); case DEAL_REASON_SPLIT: return(€Split); } return(€NOTyp); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ €TrdType convOrdTyp(const ENUM_DEAL_TYPE ot) { switch(ot) { case DEAL_TYPE_BUY: return(€BUY); case DEAL_TYPE_SELL: return(€SELL); case DEAL_TYPE_BUY_CANCELED: return(€Fail); case DEAL_TYPE_SELL_CANCELED: return(€Fail); } return(€NOTyp); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ €TrdType convOrdTyp(const ENUM_ORDER_STATE ot) { switch(ot) { case ORDER_STATE_STARTED: return(€Send); case ORDER_STATE_PLACED: return(€Placed); case ORDER_STATE_CANCELED: return(€Fail); case ORDER_STATE_PARTIAL: return(€OK); case ORDER_STATE_FILLED: return(€OK); case ORDER_STATE_REJECTED: return(€Fail); case ORDER_STATE_EXPIRED: return(€Fail); case ORDER_STATE_REQUEST_ADD: return(€Send); case ORDER_STATE_REQUEST_MODIFY: return(€OK); case ORDER_STATE_REQUEST_CANCEL: return(€Fail); } return(€NOTyp); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ €TrdType convReqAct(const ENUM_TRADE_REQUEST_ACTIONS at) { switch(at) { case TRADE_ACTION_DEAL: return(€TrDeal); case TRADE_ACTION_PENDING: return(€TrPend); case TRADE_ACTION_SLTP: return(€TrSlTp); case TRADE_ACTION_MODIFY: return(€TrModif); case TRADE_ACTION_REMOVE: return(€TrRmve); case TRADE_ACTION_CLOSE_BY: return(€TrClsBy); } return(€NOTyp); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ €TrdType convOrdTyp(const ENUM_ORDER_TYPE ot) { switch(ot) { case ORDER_TYPE_BUY: return(€BUY); case ORDER_TYPE_SELL: return(€SELL); case ORDER_TYPE_BUY_LIMIT: return(€BUYLIMIT); case ORDER_TYPE_SELL_LIMIT: return(€SELLLIMIT); case ORDER_TYPE_BUY_STOP: return(€BUYSTOP); case ORDER_TYPE_SELL_STOP: return(€SELLSTOP); case ORDER_TYPE_BUY_STOP_LIMIT: return(€BUYSTOPLIMIT); case ORDER_TYPE_SELL_STOP_LIMIT: return(€SELLSTOPLIMIT); case ORDER_TYPE_CLOSE_BY: return(€CLOSEBY); } return(€NOTyp); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ €TrdType getPosTyp(const string s) { if ( StringFind(s, "Buy") != -1 ) { if ( StringFind(s, "Stop") != -1 ) { return(€BUYSTOP); } if ( StringFind(s, "Limi") != -1 ) { return(€BUYLIMIT); } return(€BUY); } if ( StringFind(s, "Sell") != -1 ) { if ( StringFind(s, "Stop") != -1 ) { return(€SELLSTOP); } if ( StringFind(s, "Limi") != -1 ) { return(€SELLLIMIT); } return(€SELL); } return(€NOTyp); } /*+------------------------------------------------------------------+ //| admin function & vars prepared of open position | //| these function are not meant to be used by the EAs/users | //| tradeCloseOpnPos() close opposite position //| tradePrtOpPos() print specif. open position //+------------------------------------------------------------------*/ /*use: adminRmvOpPos(const ulong id,const double p=0.0) ulong adminRmvOpPos(MqlTradeResult& result) {*/ //*/ //use: adminRmvOpPos(pID, exPrc) ulong adminRmvOpPos(const ulong id, const double p = 0.0) { // 1st check the buys int i = ArraySize(oPoBU); while(i-- > 0) { if (oPoBU[i].uID != id) continue; cLstBU = oPoBU[i]; cLstBU.tCls = TimeCurrent(); cLstBU.dCls = p; cLstBU.dPrf = (oPoBU[i].dir % 2 == 0 ? 1.0 : -1.0) * (p - oPoBU[i].dOpn) / _Point; if (WhatDebug == €DebugConf || WhatDebug == €DebugAll) { Print(__FUNCTION__, "[", __LINE__, "] ", prtOneOpnPos(oPoBU[i].uID, FunLine), "\n CLS: ", _t2Sec(cLstBU.tCls), " (", _t2Sec(cLstBU.tCls - oPoBU[i].tOpn), ") ", (p < _Point ? "" : _d2D(p) + " => " + _d21( cLstBU.dPrf )), " PIP"); } ArrayRemove(oPoBU, i, 1); return(id); } // now check the sells i = ArraySize(oPoSE); while(i-- > 0) { if (oPoSE[i].uID != id) continue; cLstSE = oPoSE[i]; cLstSE.tCls = TimeCurrent(); cLstSE.dCls = p; cLstSE.dPrf = (oPoSE[i].dir % 2 == 0 ? 1.0 : -1.0) * (p - oPoSE[i].dOpn) / _Point; if (WhatDebug == €DebugConf || WhatDebug == €DebugAll) { Print(__FUNCTION__, "[", __LINE__, "] ", prtOneOpnPos(oPoBU[i].uID, FunLine), "\n CLS: ", _t2Sec(cLstSE.tCls), " (", _t2Sec(cLstSE.tCls - cLstSE.tOpn), ") ", (p < _Point ? "" : _d2D(p) + " => " + _d21( cLstSE.dPrf )), " PIP"); } ArrayRemove(oPoSE, i, 1); return(id); } return(0); } //+------------------------------------------------------------------+ //| Vars and functions dealing with match[][] to match IDs | //+------------------------------------------------------------------+ //--- an array to match with the results in OnTradingEvent, items are deleted when confirmed /* in EasyTradeEvent_INCL.mqh used to match a pending order as ProfitTarget, as soon as a PenOrd is triggered it can close ajn open pos if they match: ulong match[][3]; #define matchPOS 0 #define matchCLS 1 #define matchMAG 2 */ // find the mag number for the identification int getOpMatch(const ulong m, const ulong pX) { int i = ArrayRange(match, 0); while(i-- > 0) { if (match[i][matchMAG] == m && match[i][matchCLS] == pX ) { if (WhatDebug == €DebugMatch || WhatDebug == €DebugAll) { Print(__LINE__, " found match[", i, "] p:", match[i][matchPOS], " >c:", match[i][matchCLS], "< >m:", match[i][matchMAG]); } return( i ); } } return(-1); } // list all open = not yet confirmed void listOpMatch(const string from = "", const string cmt = "") { int i = ArrayRange(match, 0); while(i-- > 0) { Print((from != "" ? (string)__LINE__ : from), " list match[", i, "] p:", match[i][matchPOS], " c:", match[i][matchCLS], " m:", match[i][matchMAG], " ", cmt); } return; } // remove an item as it is confirmd bool rmvOpMatch(const int i) { if (WhatDebug == €DebugMatch || WhatDebug == €DebugAll) { Print(FunLine, " del match[", i, "] p:", match[i][matchPOS], " c:", match[i][matchCLS], " m:", match[i][matchMAG]); } if (ArrayRemove(match, i, 1)) { return(true); } return(false); } //+------------------------------------------------------------------+ //| confReq (two) to remove item in ReqCHCK as confirmation | //+------------------------------------------------------------------+ //called in OnTradeTransaction: confReq(sym, m, trans, request); #ifdef DBG_TRACE_ETE_INCL_CONFREQ #undef DBG_TRACE_ETE_INCL_CONFREQ #define DBG_TRACE_ETE_INCL_CONFREQ(x) x #define DBG_TRACE_ETE_INCL_CONFREQ_RETURN(x) DBG_MSG_TRACE_RETURN_VAR(x) #else #define DBG_TRACE_ETE_INCL_CONFREQ(x) #define DBG_TRACE_ETE_INCL_CONFREQ_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x) #endif int confReq(const string sym, const ulong mag, const MqlTradeTransaction &tr, const MqlTradeRequest &rq) { DBG_TRACE_ETE_INCL_CONFREQ( DBG_MSG_TRACE_BEGIN; DBG_MSG_VAR(sym); DBG_MSG_VAR(mag); DBG_MSG_VAR(tr); DBG_MSG_VAR(rq); ); PERF_COUNTER_BEGIN; // if ( WhatDebug == €DebugConf || WhatDebug == €DebugAll) // Print(__FUNCTION__, "[", __LINE__, "] Conf rq.a:", _e2s(rq.action), " rq.t:", _e2s(rq.type), " rq.o:", rq.order, " rq.p:", rq.position, " m:", mag); int i = ArraySize(ReqCHCK); if (i == 0) // m=mag, { // 515 list match[0] p:2 c:3 m:1643853600011 //listOpMatch(); // p==3, o==3, tr.order_type=ORDER_TYPE_SELL_LIMIT (3), tr.order_state=ORDER_STATE_FILLED (4) //prtListOpnOrdr(); // p==0, o==2, v==2 tr.order_type=ORDER_TYPE_BUY_LIMIT (2), tr.order_state=TRADE_TRANSACTION_ORDER_UPDATE (1) (4)o==2,p==0 //prtListOpnPos(); // p==2, o==2, v==0 tr.order_type=ORDER_TYPE_BUY_LIMIT (2), tr.order_state=ORDER_STATE_FILLED (4) //ArrayPrint(ReqCHCK); // tradeCloseTcktByPos(const ulong t1, const ulong t2, const ulong m) DBG_TRACE_ETE_INCL_CONFREQ_RETURN(-1); } while(i-- > 0) //if(mag==1673007790 || ReqCHCK[i].magic==1673007790) DebugBreak(); { if( (mag != ReqCHCK[i].magic) || (sym != ReqCHCK[i].symbol) ) { continue; } DBG_TRACE_ETE_INCL_CONFREQ( DBG_MSG_VAR(ReqCHCK[i].action); DBG_MSG_VAR(ReqCHCK[i].type); ); // if (WhatDebug == €DebugConf || WhatDebug == €DebugAll) // { Print(__FUNCTION__, "[", __LINE__, "] Conf rq.a:", _e2s(rq.action), " rq.t:", _e2s(rq.type), " ", i, "].a:", ReqCHCK[i].action, " ", i, "].t:", ReqCHCK[i].type, " rq.o:", rq.order, " rq.p:", rq.position, " m:", mag); } if( DBG_MSG_EVAL((ReqCHCK[i].type == rq.type) && (ReqCHCK[i].action == rq.action)) ) { //Print(__FUNCTION__,"[",__LINE__,"] Conf ",_e2s(ReqCHCK[i].type)," ReqCHCK[",i,"] o:",ReqCHCK[i].deviation," m: ",mag," ",_e2s(ReqCHCK[i].action)," ",_e2s(ReqCHCK[i].type)); ArrayRemove(ReqCHCK, i, 1); DBG_TRACE_ETE_INCL_CONFREQ_RETURN(i); } if( DBG_MSG_EVAL((ReqCHCK[i].action == TRADE_ACTION_DEAL) && (ReqCHCK[i].deviation == tr.order)) ) // tr.type==TRADE_TRANSACTION_HISTORY_ADD (3) tr.order==4,position==2, price>_Point { //Print(__FUNCTION__,"[",__LINE__,"] Conf DEAL ReqCHCK[",i,"] o:",ReqCHCK[i].deviation," m: ",mag," ",_e2s(ReqCHCK[i].action)," ",_e2s(ReqCHCK[i].type)); ArrayRemove(ReqCHCK, i, 1); DBG_TRACE_ETE_INCL_CONFREQ_RETURN(i); } if( DBG_MSG_EVAL(ReqCHCK[i].action == TRADE_ACTION_SLTP) ) // && ReqCHCK[i].deviation == rq.position) { // dev==2 rq.position == 2 { //Print(__FUNCTION__, "[", __LINE__, "] Conf CLOSE BY SL,TP: ReqCHCK[", i, "] o:", ReqCHCK[i].deviation, " m: ", mag, " p:", rq.position, " ", _e2s(ReqCHCK[i].action), " ", _e2s(ReqCHCK[i].type)); DBG_TRACE_ETE_INCL_CONFREQ( DBG_MSG_VAR(ReqCHCK[i].deviation); DBG_MSG_VAR(ReqCHCK[i].action); DBG_MSG_VAR(ReqCHCK[i].type); ); ulong idCls = adminRmvOpPos(ReqCHCK[i].position, fmax(rq.price, tr.price)); ArrayRemove(ReqCHCK, i, 1); // SL/TP changed DBG_TRACE_ETE_INCL_CONFREQ_RETURN(i); } if( DBG_MSG_EVAL((rq.action == TRADE_ACTION_MODIFY) && (rq.order == ReqCHCK[i].order)) ) { //Print(__FUNCTION__,"[",__LINE__,"] Conf mod.Ord : ReqCHCK[",i,"] o:",ReqCHCK[i].deviation," m: ",mag," rq.o:",rq.order," ",_e2s(ReqCHCK[i].action)," ",_e2s(ReqCHCK[i].type)); ArrayRemove(ReqCHCK, i, 1); return(i); } if( DBG_MSG_EVAL((tr.type == TRADE_TRANSACTION_DEAL_ADD) && (ReqCHCK[i].deviation == tr.order)) ) { //Print(__FUNCTION__,"[",__LINE__,"] Conf CLS 1by1 ReqCHCK[",i,"] o:",ReqCHCK[i].deviation," m: ",mag," ",_e2s(ReqCHCK[i].action)," ",_e2s(ReqCHCK[i].type)); ArrayRemove(ReqCHCK, i, 1); DBG_TRACE_ETE_INCL_CONFREQ_RETURN(i); } if( DBG_MSG_EVAL(tr.type == TRADE_TRANSACTION_HISTORY_ADD) ) { listOpMatch();//int i = getOpMatch(mag, prtListOpnOrdr(); prtListOpnPos(); ArrayPrint(ReqCHCK); // match[0] p:2 c:3 m:1643853600011 tr.p=2 tr.o=2 ReqCHCK[i].action == TRADE_ACTION_CLOSE_BY && && ReqCHCK[i].deviation == tr.order // Order[0] oT:2 m:1643853600011 pT:0 Pr:1.12670 SL:1.12370 PT:1.13370=> ORDER_TYPE_BUY_LIMIT @ 00:00:00 // Position[0] o:0 m:1643853600011 t:3 p:3 Pr:1.12985 SL:1.13470 PT:0.00000=> POSITION_TYPE_SELL @ 02:02:22 } } if ( WhatDebug == €DebugConf || WhatDebug == €DebugAll ) { i = ArraySize(ReqCHCK); while(i-- > 0) { Print(__FUNCTION__, "[", __LINE__, "] CHECK ReqCHCK[", i, "] o:", ReqCHCK[i].deviation, " ", _e2s(ReqCHCK[i].action), " ", _e2s(ReqCHCK[i].type)); } } DBG_TRACE_ETE_INCL_CONFREQ( i = ArraySize(ReqCHCK); while(i-- > 0) { DBG_MSG_VAR(ReqCHCK[i].deviation); DBG_MSG_VAR(ReqCHCK[i].action); DBG_MSG_VAR(ReqCHCK[i].type); } ); DBG_TRACE_ETE_INCL_CONFREQ_RETURN(-1); } //## int confReq(const string sym, const ulong mag, const MqlTradeTransaction &tr, const MqlTradeRequest &rq, const MqlTradeResult &rs) { DBG_TRACE_ETE_INCL_CONFREQ( DBG_MSG_TRACE_BEGIN; DBG_MSG_VAR(sym); DBG_MSG_VAR(mag); DBG_MSG_VAR(tr); DBG_MSG_VAR(rq); DBG_MSG_VAR(rs); ); PERF_COUNTER_BEGIN; int i = ArraySize(ReqCHCK); if (i == 0) // m=mag, { // 515 list match[0] p:2 c:3 m:1643853600011 //listOpMatch(); // p==3, o==3, tr.order_type=ORDER_TYPE_SELL_LIMIT (3), tr.order_state=ORDER_STATE_FILLED (4) //prtListOpnOrdr(); // p==0, o==2, v==2 tr.order_type=ORDER_TYPE_BUY_LIMIT (2), tr.order_state=TRADE_TRANSACTION_ORDER_UPDATE (1) (4)o==2,p==0 //prtListOpnPos(); // p==2, o==2, v==0 tr.order_type=ORDER_TYPE_BUY_LIMIT (2), tr.order_state=ORDER_STATE_FILLED (4) //ArrayPrint(ReqCHCK); // tradeCloseTcktByPos(const ulong t1, const ulong t2, const ulong m) DBG_TRACE_ETE_INCL_CONFREQ_RETURN(-1); } while(i-- > 0) //if(mag==1673007790 || ReqCHCK[i].magic==1673007790) DebugBreak(); { if( (mag != ReqCHCK[i].magic) || (sym != ReqCHCK[i].symbol) ) { continue; } DBG_TRACE_ETE_INCL_CONFREQ( DBG_MSG_VAR(ReqCHCK[i].action); DBG_MSG_VAR(ReqCHCK[i].type); ); if( DBG_MSG_EVAL((ReqCHCK[i].action == TRADE_ACTION_PENDING) && (ReqCHCK[i].deviation == rs.order)) ) { //Print(__FUNCTION__,"[",__LINE__,"] Conf DEAL ReqCHCK[",i,"] o:",ReqCHCK[i].deviation," m: ",mag," ",_e2s(ReqCHCK[i].action)," ",_e2s(ReqCHCK[i].type)); // if (rq.type%2==0) //## buys { int b=ArraySize(oOrBU); while(b-->0) { if (oOrBU[b].uID == rs.order) { oOrBU[b].status = €Placed; ArrayRemove(ReqCHCK, i, 1); DBG_TRACE_ETE_INCL_CONFREQ_RETURN(i); return(i); } } } } } DBG_TRACE_ETE_INCL_CONFREQ_RETURN(-1); } //called in OnTradeTRansaction: confReq(sym, m, trans, request); int confReq(const string sym, const ulong mag, const ulong p, const ENUM_DEAL_ENTRY how) { DBG_TRACE_ETE_INCL_CONFREQ( DBG_MSG_TRACE_BEGIN; DBG_MSG_VAR(sym); DBG_MSG_VAR(mag); DBG_MSG_VAR(p); DBG_MSG_VAR(how); ); PERF_COUNTER_BEGIN; int reg_chk_ptr = ArraySize(ReqCHCK); DBG_TRACE_ETE_INCL_CONFREQ( DBG_MSG_VAR(reg_chk_ptr); ); while(reg_chk_ptr-- > 0) { if (mag != ReqCHCK[reg_chk_ptr].magic) { continue; } // if (sym != ReqCHCK[i].symbol) continue; if( DBG_MSG_EVAL((ReqCHCK[reg_chk_ptr].action == TRADE_ACTION_CLOSE_BY) && (how == DEAL_ENTRY_OUT_BY) && (p == ReqCHCK[reg_chk_ptr].position_by)) ) { //Print(__FUNCTION__, "[", __LINE__, "] Conf ", _e2s(ReqCHCK[i].type), " ReqCHCK[", i, "] o:", ReqCHCK[i].deviation, " m: ", mag, " ", _e2s(ReqCHCK[i].action), " ", _e2s(ReqCHCK[i].type)); DBG_TRACE_ETE_INCL_CONFREQ( DBG_MSG_VAR(ReqCHCK[reg_chk_ptr].type); DBG_MSG_VAR(ReqCHCK[reg_chk_ptr].deviation); DBG_MSG_VAR(ReqCHCK[reg_chk_ptr].action); ); ArrayRemove(ReqCHCK, reg_chk_ptr, 1); DBG_TRACE_ETE_INCL_CONFREQ_RETURN(reg_chk_ptr); } if( DBG_MSG_EVAL((ReqCHCK[reg_chk_ptr].action == TRADE_ACTION_DEAL) && (how == DEAL_ENTRY_OUT) && (p == ReqCHCK[reg_chk_ptr].position)) ) { //Print(__FUNCTION__, "[", __LINE__, "] Conf ", _e2s(ReqCHCK[i].type), " ReqCHCK[", i, "] o:", ReqCHCK[i].deviation, " m: ", mag, " ", _e2s(ReqCHCK[i].action), " ", _e2s(ReqCHCK[i].type)); DBG_TRACE_ETE_INCL_CONFREQ( DBG_MSG_VAR(ReqCHCK[reg_chk_ptr].type); DBG_MSG_VAR(ReqCHCK[reg_chk_ptr].deviation); DBG_MSG_VAR(ReqCHCK[reg_chk_ptr].action); ); ArrayRemove(ReqCHCK, reg_chk_ptr, 1); DBG_TRACE_ETE_INCL_CONFREQ_RETURN(reg_chk_ptr); } }// DEAL_ENTRY_OUT (1) p==2 mag==... DBG_TRACE_ETE_INCL_CONFREQ( DBG_MSG_VAR(how); DBG_MSG_VAR(mag); DBG_MSG_VAR(p); ); DBG_TRACE_ETE_INCL_CONFREQ_RETURN(0); } /* to be detected: Order placed, L: 682 Position opened L: 675 Stop of StopLimit triggered => StoLimitOrder => LimitOrder Pending order triggered => position Position closed Order deleted SL & TP placed SL & TP modified L:874 SL & TP deleted SL & TP triggered => position (partly) closed L:842 */ //10004: error_string = "Ret["+(string)error_code+"] TRADE_RETCODE_REQUOTE: Requote"; break; //10016: error_string = "Ret["+(string)error_code+"] TRADE_RETCODE_INVALID_STOPS: Invalid stops in the request"; break; bool chkFail(const string from, MqlTradeRequest &req, MqlTradeResult &res) //10004=requote, { if(WhatDebug == €DebugSend || WhatDebug == €DebugAll) Print(from, " tC: ", _t2All(TimeCurrent()), " (long)tC:", (string)(ulong)TimeCurrent(), " => ", (string)req.magic, " ", req.comment, " rq.id: ", res.request_id, " rs.d: ", res.deal, " rs.o: ", res.order, " rs.ret: ", res.retcode); if (res.retcode == 10004) // requote { double d; if (req.action == TRADE_ACTION_DEAL) { if (req.type == ORDER_TYPE_SELL ) { d = (req.price - req.tp); if ( res.bid < req.tp - d) return(false); if ( req.tp > 0 ) req.tp = res.bid - fabs(req.price - req.tp); if ( req.sl > 0 ) req.sl = res.bid + fabs(req.price - req.sl); req.price = res.bid; } if (req.type == ORDER_TYPE_BUY ) { d = (req.tp - req.price); if ( res.ask > req.tp + d) return(false); if ( req.tp > 0 ) req.tp = res.ask + fabs(req.price - req.tp); if ( req.sl > 0 ) req.sl = res.ask - fabs(req.price - req.sl); req.price = res.ask; } } if(!OrderSendAsync(req, res)) { Print("\n", __FUNCTION__, "[", __LINE__, "] ################ 2nd FAIL: 1st. TRADE_ACTION_DEAL REQUOTE ########\n ORDER_TYPE_CLOSE_BY OrderSendAsync error ", err(_LastError), " rs.order ", res.retcode, "\ntC ", _t2All(TimeCurrent()), " ask: ", _d2D(SymbolInfoDouble(_Symbol, SYMBOL_ASK)), " bid: ", _d2D(SymbolInfoDouble(_Symbol, SYMBOL_BID)) ); //Print(__FUNCTION__,"[",__LINE__,"] ",prtRequ(req)); Print(__FUNCTION__,"[",__LINE__,"] ",prtResult(res)); return(false); } else { Print("\n", __FUNCTION__, "[", __LINE__, "] ####################### 2nd TRY 1st. TRADE_ACTION_DEAL REQUOTE tC:", (string)(ulong)TimeCurrent(), " => ", (string)req.magic, "\n ", _Symbol, " ", req.magic, " ", TimeToString(TimeCurrent(), TIME_SECONDS), " ", req.comment, "\n SELL-STOP with SL & TP r.ID: ", res.request_id, " d.O: ", res.deal, " r.O: ", res.order, " r.ret: ", res.retcode); chkREQ(FunLine, req, res.order); ResetLastError(); // err: 4756=ERR_TRADE_SEND_FAILED, 10013=TRADE_RETCODE_INVALID, return(true); } } if (res.retcode == 10016) // Invalid stops { Print(__FUNCTION__, "[", __LINE__, "] (", from, ") retcode 10016=Invalid stops in the request: bid:", _d2D(SymbolInfoDouble(_Symbol, SYMBOL_BID)), " ask:", _d2D(SymbolInfoDouble(_Symbol, SYMBOL_ASK))); prtRequ(req, __LINE__); prtResult(res, __LINE__); DebugBreak(); } if (res.retcode == 10019) // Ret[10019] TRADE_RETCODE_NO_MONEY { Print(__FUNCTION__, "[", __LINE__, "] (", from, ") retcode 10019= TRADE_RETCODE_NO_MONEY Free Margin: ", _d22(AccountInfoDouble(ACCOUNT_MARGIN_FREE)), " Bal:", _d22(AccountInfoDouble(ACCOUNT_BALANCE)), " Equ:", _d22(AccountInfoDouble(ACCOUNT_EQUITY))); prtRequ(req, __LINE__); prtResult(res, __LINE__); DebugBreak(); } req.deviation = (ulong)res.retcode + 1000000 * res.retcode_external; // ret: 10 004 ret_srv: int i = ArrayAdd(ReqFAIL, req); int j = ArraySize(ReqFAIL); while(j-- > 0) { Print(__FUNCTION__, "[", __LINE__, "][", j, "] (", from, ") err: ", ReqFAIL[j].deviation, " o:", ReqFAIL[i].deviation, " act:", _e2s(ReqFAIL[j].action), " typ:", _e2s(ReqFAIL[j].type)); } return(false); } //use chkREQ(req); void chkREQ(const string from, MqlTradeRequest &req, const ulong o) { req.deviation = o; int i = ArrayAdd(ReqCHCK, req); Print(FunLine, from, " ADD ReqCHCK[", i, "] o:", o, " .dev: ", ReqCHCK[i].deviation, " act:", _e2s(ReqCHCK[i].action), " typ:", _e2s(ReqCHCK[i].type)); return; int j = ArraySize(ReqCHCK); while(j-- > 0) { Print(FunLine, from, " o:", o, " .dev: ", ReqCHCK[i].deviation, " act:", _e2s(ReqCHCK[j].action), " typ:", _e2s(ReqCHCK[j].type)); } } //+------------------------------------------------------------------+ string prtTrans(const MqlTradeTransaction &trans, const int l = 0) { //--- //if (TimeCurrent()< D'2022.10.04 03:03:00' || trans.order_state != ORDER_STATE_FILLED ) return(""); string desc = "\nstruct TRANS[" + (string)l + "]:\r\ntype[" + (string)((int)trans.type) + "] " + _e2s(trans.type) + "\r\n"; desc += "Symbol: " + trans.symbol + "\r\n"; desc += "Deal ticket: " + (string)trans.deal + "\r\n"; desc += "Deal type[" + (string)((int)trans.deal_type) + "] " + _e2s(trans.deal_type) + "\r\n"; desc += "Order ticket: " + (string)trans.order + "\r\n"; desc += "Order type[" + (string)((int)trans.order_type) + "]: " + _e2s(trans.order_type) + "\r\n"; desc += "Order state[" + (string)((int)trans.order_state) + "]: " + _e2s(trans.order_state) + "\r\n"; desc += "Order time type: " + _e2s(trans.time_type) + "\r\n"; desc += "Order expiration: " + TimeToString(trans.time_expiration) + "\r\n"; desc += "Price: " + StringFormat("%G", trans.price) + "\r\n"; desc += "Price trigger: " + StringFormat("%G", trans.price_trigger) + "\r\n"; desc += "Stop Loss: " + StringFormat("%G", trans.price_sl) + "\r\n"; desc += "Take Profit: " + StringFormat("%G", trans.price_tp) + "\r\n"; desc += "Volume: " + StringFormat("%G", trans.volume) + "\r\n"; desc += "Position Ticket: " + (string)trans.position + "\r\n"; desc += "Position by: " + (string)trans.position_by + "\r\n"; //--- den erhaltenen String zurückgeben //Print(desc); return(desc); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string prtRequ(const MqlTradeRequest &rq, const int l = 0) { //if (TimeCurrent()< D'2022.10.04 03:03:00' ) return(""); string ret = "struct REQUEST[" + (string)l + "]:" + _e2s(rq.type) + "\r\n" + "action[" + (string)((int)rq.action) + "] " + _e2s(rq.action) + "\r\n"; ret += "Mag.Nr. " + (string)rq.magic + "\r\n"; ret += "Order Ticket " + (string)rq.order + "\r\n"; ret += "Symbol " + rq.symbol + "\r\n"; ret += "Vol. " + _d22(rq.volume) + "\r\n"; ret += "Preis " + _d2D(rq.price) + "\r\n"; ret += "StopLimit " + _d2D(rq.stoplimit) + "\r\n"; ret += "SL " + _d2D(rq.sl) + "\r\n"; ret += "TP " + _d2D(rq.tp) + "\r\n"; ret += "Deviat. " + (string)rq.deviation + "\r\n"; ret += "Ordertyp[" + (string)((int)rq.type) + "] " + _e2s(rq.type) + "\r\n"; ret += "Durchführung " + _e2s(rq.type_filling) + "\r\n"; ret += "Typ d. Ablauffrist " + _e2s(rq.type_time) + "\r\n"; ret += "Ablauffrist der Pending-Order " + _t2All(rq.expiration) + "\r\n"; ret += "Kommentar " + (rq.comment) + "\r\n"; ret += "Position ticket " + (string)rq.position + "\r\n"; ret += "Ticket of opposite position " + (string)rq.position_by + "\r\n"; Print(ret); return(ret); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string prtResult(const MqlTradeResult &rs, const int l = 0) { //if (TimeCurrent()< D'2022.10.04 03:03:00' ) return(""); string ret = "struct RESULT[" + (string)l + "]\nretCode " + err(rs.retcode) + "\r\n"; ret += "Deal-Ticket " + (string)rs.deal + "\r\n"; ret += "Order-Ticket " + (string)rs.order + "\r\n"; ret += "conf. Vol " + _d22(rs.volume) + "\r\n"; ret += "conf. Preis " + _d2D(rs.price) + "\r\n"; ret += "akt.Bid (Requote Preis) " + _d2D(rs.bid) + "\r\n"; ret += "akt.Ask (Requote Preis) " + _d2D(rs.ask) + "\r\n"; ret += "Kommentar " + rs.comment + "\r\n"; ret += "Term.ID " + (string)rs.request_id + "\r\n"; ret += "exter. RestCode " + (string)rs.retcode_external + "\r\n"; Print(ret); return(ret); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string prtReqCheck(const MqlTradeCheckResult &rc, const int l = 0) { //if (TimeCurrent()< D'2022.10.04 03:03:00' ) return(""); string ret = "struct RESULT[" + (string)l + "]\nretCode " + err(rc.retcode) + "\r\n"; ret += "Balance " + _d22(rc.balance) + "\r\n"; ret += "Equity " + _d22(rc.equity) + "\r\n"; ret += "profit " + _d22(rc.profit) + "\r\n"; ret += "margin " + _d22(rc.margin) + "\r\n"; ret += "margin_free " + _d22(rc.margin_free) + "\r\n"; ret += "margin_level " + _d22(rc.margin_level) + "\r\n"; ret += "Comment " + rc.comment + "\r\n"; Print(ret); return(ret); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string prtListOpnOrdr(const ulong oID = 0, const ulong mag = 0, const int l = 0, const bool all = true) { uint i = OrdersTotal(); while(i-- > 0) { ulong t = OrderGetTicket(i); if (t >= 0) { if ( all || (mag != 0 && mag == OrderGetInteger(ORDER_MAGIC)) || (oID != 0 && oID == t)) { string ret = StringFormat("Order[%i] oT:%s m:%s pT:%s Pr:%s SL:%s PT:%s=> %s @ %s", l, (string)t, (string)(ulong)fmax(0, OrderGetInteger(ORDER_MAGIC)), (string)(ulong)OrderGetInteger(ORDER_POSITION_ID), _d2D(OrderGetDouble(ORDER_PRICE_OPEN)), _d2D(OrderGetDouble(ORDER_SL)), _d2D(OrderGetDouble(ORDER_TP)), _e2s((ENUM_ORDER_TYPE) OrderGetInteger(ORDER_TYPE)), _t2Sec((datetime)OrderGetInteger(ORDER_TIME_DONE)) ); Print(ret); //return(ret); } } } return("" + __FUNCTION__ + "[" + (string)l + "]\nOrder o:" + (string)oID + " m:" + (string)mag + " not found as open pend. order Err:" + err(_LastError) + "\n"); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string prtOpnOrdr(const ulong tckt, const int l = 0) { if (OrderSelect(tckt)) { string ret = StringFormat("Order oT:%s m:%s pT:%s Pr:%s SL:%s PT:%s=> %s @ %s", (string)tckt, (string)(ulong)fmax(0, OrderGetInteger(ORDER_MAGIC)), (string)(ulong)OrderGetInteger(ORDER_POSITION_ID), _d2D(OrderGetDouble(ORDER_PRICE_OPEN)), _d2D(OrderGetDouble(ORDER_SL)), _d2D(OrderGetDouble(ORDER_TP)), _e2s((ENUM_ORDER_TYPE) OrderGetInteger(ORDER_TYPE)), _t2Sec((datetime)OrderGetInteger(ORDER_TIME_DONE)) ); Print(ret); //return(ret); } return("" + __FUNCTION__ + "[" + (string)l + "]\nOrder o:" + (string)tckt + " not found as open pend. order, Err:" + err(_LastError) + "\n"); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string prtListOpnPos(const ulong oID = 0, const ulong mag = 0, const int l = 0, const bool all = true) { uint i = PositionsTotal(); while(i-- > 0) { ulong t = PositionGetTicket(i); if (t >= 0) { if ( true || (mag != 0 && mag == PositionGetInteger(POSITION_MAGIC)) || (oID != 0 && oID == t)) { string ret = StringFormat("Position[%i] o:%s m:%s t:%s p:%s Pr:%s SL:%s PT:%s=> %s @ %s", i, (string)oID, (string)(ulong)fmax(mag, PositionGetInteger(POSITION_MAGIC)), (string)t, (string)(ulong)PositionGetInteger(POSITION_IDENTIFIER), _d2D(PositionGetDouble(POSITION_PRICE_OPEN)), _d2D(PositionGetDouble(POSITION_SL)), _d2D(PositionGetDouble(POSITION_TP)), _e2s((ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE)), _t2Sec((datetime)PositionGetInteger(POSITION_TIME_UPDATE)) ); Print(ret); //return(ret); } } } return("" + __FUNCTION__ + "[" + (string)l + "]\n#########\nPosition p:" + (string)oID + " m:" + (string)mag + " not found as open pend. order Err:" + err(_LastError) + "\n"); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string prtOneOpnPos(const ulong tckt, const string from) { if (PositionSelectByTicket(tckt)) { string ret = StringFormat("Position m:%s o:%s p:%s Pr:%s SL:%s TP:%s => %s @ %s (from:%s)", (string)(ulong)PositionGetInteger(POSITION_MAGIC), (string)tckt, (string)(ulong)PositionGetInteger(POSITION_IDENTIFIER), _d2D(PositionGetDouble(POSITION_PRICE_OPEN)), _d2D(PositionGetDouble(POSITION_SL)), _d2D(PositionGetDouble(POSITION_TP)), _e2s((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)), _t2Sec((datetime)PositionGetInteger(POSITION_TIME_UPDATE)), from ); Print(ret); //return(ret); } return(FunLine + "\n#########\nPosition p:" + (string)tckt + " not found as open pend. order Err:" + err(_LastError) + "\n"); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string prtHistDeal(ulong hD, const int l = 0) { //if (TimeCurrent()< D'2022.10.04 03:03:00' ) return(""); if (hD <= 0) { /*Print(__FUNCTION__,"[",__LINE__,"] Deal[",hD,"] from line: ",(string)l," invalid");*/ return(""); } HistoryDealSelect(hD); ulong uMag = HistoryDealGetInteger(hD, DEAL_MAGIC), //myMag = StringFormat(" myMag:>%I64u< ", uMag), uPos = HistoryDealGetInteger(hD, DEAL_POSITION_ID), uOrd = HistoryDealGetInteger(hD, DEAL_ORDER); double dPrc = HistoryDealGetDouble(hD, DEAL_PRICE); string ret = StringFormat( "DEAL Info\nM:%s D:%s O:%s P:%s p:%s\nmov: %s\nwhy: %s\n", (string)uMag, (string)hD, (string)uOrd, (string)uPos, _d2D(dPrc), _e2s((ENUM_DEAL_ENTRY)HistoryDealGetInteger(hD, DEAL_ENTRY)), _e2s((ENUM_DEAL_REASON)HistoryDealGetInteger(hD, DEAL_REASON)) ); //Print(ret); return(ret); } //+------------------------------------------------------------------+