1063 lines
83 KiB
MQL5
1063 lines
83 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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<typename T>
|
|
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<typename T>
|
|
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<typename T>
|
|
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);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|