883 lines
100 KiB
MQL5
883 lines
100 KiB
MQL5
/*+------------------------------------------------------------------+
|
|
//| EasyTradeEvent.mqh |
|
|
//| #include <EasyTradeEvent.mqh> <= to copy & paste |
|
|
//| Calli |
|
|
//| https://www.mql5.com/de/users/gooly |
|
|
|
|
It is as usual: the nomal case of sending an order is easy
|
|
but its error handling is 100 times more complex and complicated :(
|
|
|
|
The functionality of MQ's Trade.mqh is nice but it is not ideal (fast)
|
|
in case if errors and it does not harmonize well with OnTradeTransaction().
|
|
OnTradeTransaction() is triggered from not at all to four times for one
|
|
trading act set by a trader :(
|
|
|
|
Imagine:
|
|
speed matters for your EA,
|
|
it is trading several symbols on different charts,
|
|
suddenly the prices are moving up fast and your EA needs to act fast,
|
|
normally it has to loop through all positions of all symbols and directions,
|
|
but it only needs its own one ot two buy positions :(
|
|
|
|
Therfore:
|
|
two arrays are managed one for buys on for sells (oPoBU[],oPoSE[]),
|
|
with their information and PositionSelectByTicket() exists a straight
|
|
acces to the positions that matters to modify them (trail, close..)
|
|
bypassing all the other existing positions.
|
|
|
|
Several ideas and requirements are processed:
|
|
1) Find the single trigger of OnTradeTransaction() that matters.
|
|
2) If an order fails the request and the result are used to react.
|
|
E.g. in case of requotes result has valid bid and ask which are used
|
|
if the offset is not too big.
|
|
3) The magic number is used as an individual ID for the confirmation
|
|
in OnTradeTransaction as sometimes the other IDs are missing :(
|
|
Therefore the magic number is created by (ulong)TimeCurrent() which is
|
|
enough if the trader (EA) doesn't send masses of orders..
|
|
4) When an order was accepted by the server a function chkREQ() adds
|
|
the sent reqest to the array ReqCHCK for confirmation via
|
|
OnTradeTransaction().
|
|
5) To pass required information some fields of the trade structs are abused
|
|
like deviation. This way we do not need to declare, fill, administrate,
|
|
and delete additional data structures just for the admin. We use what already exists :)
|
|
6) Here we use OrderSendAsync() as the EA quickly returns right after the
|
|
order was accepted by the server in order to prepare the tracking of the sent order.
|
|
7) If OrderSendAsync() failed chkFail() tries to heal the problem or to inform the user (EA).
|
|
8) If OrderSendAsync() succeded chkREQ() is called to prepare the confirmation by
|
|
OnTradeTransaction().
|
|
9) In OnTradeTransaction(), the first thing that is collected is information
|
|
about the various IDs (tickets, magic,...), what ever is available because
|
|
often these values are not assigned :(
|
|
10)Then we go through a complicated and heterogeneous network of return codes
|
|
of the structure MqlTradeResult and the types of the structure MqlTradeTransaction.
|
|
|
|
I wish there were a simpler solution, but it would have to be offered by MetaQuotes,
|
|
simply limited to what an EA needs for confirmation, error detection, and handling.
|
|
Let's hope and pray ;)
|
|
|
|
//+------------------------------------------------------------------*/
|
|
#property library
|
|
#property copyright "Calli"
|
|
#property link "https://www.mql5.com/de/users/gooly"
|
|
#property version "1.00"
|
|
|
|
#include "EasyTradeEvent_INCL 02.mqh"
|
|
|
|
|
|
|
|
/*+------------------------------------------------------------------+
|
|
//| trading functions prepared for handling confirmation & errors |
|
|
//|
|
|
//| these function are meant to be used by the EAs/users |
|
|
//| tradeClosePartPos(): close pos. partly by an opp. pend. Order
|
|
//| tradeCloseTckt(): close pos. by #ticket & volume
|
|
//| tradeCloseTcktByPos(): close pos1 (#t1) by pos2 (#t2) & mag
|
|
//| tradeCloseOpnPos(): close specified position
|
|
//|
|
|
//| tradeMoveTPSLPos():
|
|
//| tradeNewTPSLPos():
|
|
//| tradeTrailTPSLPos():
|
|
//| tradeNewTPSLOrd():
|
|
//| prtOneOpnPos():
|
|
//| tradePenOrdTP(): set TP as Pending Order to partly close Pos.
|
|
//|
|
|
//|
|
|
//|
|
|
//+------------------------------------------------------------------*/
|
|
|
|
ulong sndOrder(_opTrd &ord, const string cmt="") {
|
|
MqlTradeRequest rq={};
|
|
MqlTradeResult rs={};
|
|
MqlTradeCheckResult rc={};
|
|
bool newRecord = false;
|
|
ulong pID = 0;
|
|
|
|
switch (ord.dir) {
|
|
case €BUY:
|
|
case €SELL:
|
|
rq.action = TRADE_ACTION_DEAL; // pending order
|
|
rq.type = ORDER_TYPE_SELL; // Ordertyp
|
|
rq.deviation = ord.uDevOrInf;
|
|
rq.magic = ord.uMag;
|
|
rq.symbol = _Symbol; // Instrument
|
|
rq.volume = ord.dVol; // Volumen von 0.1 Lot
|
|
rq.price = ord.dOpn;
|
|
rq.sl = ord.dSL;
|
|
rq.tp = ord.dTP;
|
|
rq.comment = "Market-Order Sell Mag: "+(string)(rq.magic%1000000);
|
|
break;
|
|
|
|
case €BUYSTOP:
|
|
case €SELLSTOP:
|
|
case €BUYLIMIT:
|
|
case €SELLLIMIT:
|
|
case €BUYSTOPLIMIT:
|
|
rq.action = TRADE_ACTION_PENDING; // pending order
|
|
rq.type = ORDER_TYPE_BUY_STOP_LIMIT; // Ordertyp
|
|
rq.deviation = ord.uDevOrInf;
|
|
rq.symbol = _Symbol; // Instrument
|
|
rq.magic = ord.uMag;
|
|
rq.volume = ord.dVol;
|
|
rq.price = ord.dOpn;
|
|
rq.stoplimit = ord.dStLim;
|
|
rq.sl = ord.dSL;
|
|
rq.tp = ord.dTP;
|
|
rq.comment = cmt != "" ? cmt : "BuyStpLimit Mag: "+(string)(rq.magic%1000000); // it mussn't be tooo long
|
|
break;
|
|
|
|
case €SELLSTOPLIMIT:
|
|
default: return(0);
|
|
}
|
|
if( !OrderCheck(rq,rc) ) {
|
|
ord.status = €Fail;
|
|
Print(FunLine,"TRADE_RETCODE_NO_MONEY ",err(_LastError)," res.order ",rs.retcode," ",err(rs.retcode)," r.D: ",rs.deal," r.O: ",rs.order);
|
|
Print(FunLine,prtRequ(rq));
|
|
Print(FunLine,prtReqCheck(rc));
|
|
return(0); // 0=failed
|
|
}
|
|
|
|
if (OrderSendAsync(rq,rs)) {
|
|
ord.uID = rs.order;
|
|
//Print("\n",FunLine," ####################### OK ",EnumToString(typ)," sent \n",__LINE__," ",_Symbol," ",rq.magic," ",TimeToString(TimeCurrent(),TIME_SECONDS)," ",
|
|
// rq.comment,"\n in:",_d2D(prc),"TP:",_d2D(rq.tp)," SL:",_d2D(rq.sl)," r.ID: ",rs.request_id," d.O: ",rs.deal," r.O: ",rs.order," r.ret: ",rs.retcode);
|
|
chkREQ(FunLine,rq,rs.order);
|
|
return(rs.order);
|
|
|
|
} else { // FAILED :(
|
|
Print(FunLine," OrderSendAsync error ",err(_LastError)," res.order ",rs.retcode," ",err(rs.retcode)," r.D: ",rs.deal," r.O: ",rs.order,
|
|
"\ntC ",_t2All(TimeCurrent())," Cmt ",rq.comment);
|
|
//Print(FunLine," ",prtRequ(rq));
|
|
//Print(FunLine," ", prtResult(rs));
|
|
if (_LastError == TRADE_RETCODE_NO_MONEY) {
|
|
Print(FunLine," TRADE_RETCODE_NO_MONEY ",err(_LastError)," res.order ",rs.retcode," ",err(rs.retcode)," r.D: ",rs.deal," r.O: ",rs.order);
|
|
Print(FunLine," ",prtRequ(rq));
|
|
Print(FunLine," ",prtReqCheck(rc));
|
|
return(0);
|
|
}
|
|
|
|
if (chkFail(FunLine,rq,rs)) { // with chkREQ(FunLine,rq,pID) in chkFail()
|
|
pID = rs.order;
|
|
ResetLastError(); // err: 4756=ERR_TRADE_SEND_FAILED, 10013=TRADE_RETCODE_INVALID,
|
|
return(pID);
|
|
}
|
|
if (chkFail(FunLine,rq,rs)) { // next try // with chkREQ(FunLine,rq,pID) in chkFail()
|
|
pID = rs.order;
|
|
ResetLastError(); // err: 4756=ERR_TRADE_SEND_FAILED, 10013=TRADE_RETCODE_INVALID,
|
|
return(pID);
|
|
}
|
|
}
|
|
return(pID);
|
|
}
|
|
|
|
|
|
// use: tradePenOrdTP(oOrBU[i], 1.2, fmax(pLim,pStp), 100.0*_Point);
|
|
bool tradePenOrdSL(_opTrd &ord, const double vol, const double diff) {
|
|
MqlTradeRequest reqClsBY = {}; // ZeroMemory(reqClsBY);
|
|
MqlTradeResult resClsBY = {}; // ZeroMemory(resClsBY);
|
|
|
|
//DebugBreak();
|
|
|
|
if ( ord.dir % 2 == 0 ) {
|
|
reqClsBY.type = ORDER_TYPE_SELL_STOP; // opposite direction
|
|
reqClsBY.price = ord.dOpn - diff;
|
|
|
|
} else {
|
|
reqClsBY.type = ORDER_TYPE_BUY_STOP; // opposite direction
|
|
reqClsBY.price = ord.dOpn + diff;
|
|
}
|
|
|
|
reqClsBY.action = TRADE_ACTION_PENDING; // pending order
|
|
reqClsBY.magic = ord.uMag;
|
|
reqClsBY.symbol = _Symbol; // Instrument
|
|
reqClsBY.volume = vol; // Volumen von 0.1 Lot
|
|
reqClsBY.comment = "penTrail SL Mag: "+(string)(ord.uMag%1000000);
|
|
|
|
Print("\n",FunLine," ####################### OK: 1st. ORDER for _CLOSE_BY tC:",(string)(ulong)TimeCurrent()," => ",
|
|
"\n BaseOrder: ",_e2s(ord.dir)," ",(string)ord.uID," ",(string)ord.uMag," @ ",_d2D(ord.dOpn)," ",TimeToString(TimeCurrent(),TIME_SECONDS),
|
|
"\n ClsByOrd: ",_e2s(reqClsBY.type)," vol: ",reqClsBY.volume," cmt: ",reqClsBY.comment);
|
|
|
|
ResetLastError(); // err: 4756=ERR_TRADE_SEND_FAILED, 10013=TRADE_RETCODE_INVALID,
|
|
if(!OrderSendAsync(reqClsBY,resClsBY)) {
|
|
Print("\n",__FUNCTION__,"[",__LINE__,"] ################ FAIL: 1st. ORDER_TYPE_CLOSE_BY ########",
|
|
"\n ORDER_TYPE_CLOSE_BY OrderSendAsync error ",err(_LastError)," res.order ",resClsBY.retcode,
|
|
"\ntC ",_t2All(TimeCurrent())," ask: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_ASK))
|
|
);
|
|
Print(FunLine,prtRequ(reqClsBY));
|
|
Print(FunLine,prtResult(resClsBY));
|
|
return( chkFail(FunLine,reqClsBY,resClsBY) );
|
|
//ExpertRemove();
|
|
} else {
|
|
//DebugBreak();
|
|
int i = ArrayNew(match);
|
|
match[i][matchPOS]=ord.uID; //should be triggered first
|
|
match[i][matchMAG]=ord.uMag;
|
|
match[i][matchCLS]=resClsBY.order; //when triggered should close by matchPOS
|
|
|
|
chkREQ(FunLine,reqClsBY,resClsBY.order);
|
|
ResetLastError(); // err: 4756=ERR_TRADE_SEND_FAILED, 10013=TRADE_RETCODE_INVALID,
|
|
return(true);
|
|
|
|
}
|
|
return(false);
|
|
|
|
}
|
|
|
|
|
|
// use: tradePenOrdTP(oOrBU[i], 1.2, fmax(pLim,pStp), 100.0*_Point);
|
|
bool tradePenOrdTP(_opTrd &ord, const double vol, const double diff) {
|
|
MqlTradeRequest reqClsBY = {}; // ZeroMemory(reqClsBY);
|
|
MqlTradeResult resClsBY = {}; // ZeroMemory(resClsBY);
|
|
|
|
|
|
if ( ord.dir % 2 == 0 ) {
|
|
int i = ArrayNew(oOrSE); // <= get a new element set to zero
|
|
reqClsBY.type = ORDER_TYPE_SELL_LIMIT; // opposite direction
|
|
oOrSE[i].dir = €SELLLIMIT; // opposite direction
|
|
oOrSE[i].dOpn = ord.dOpn + diff;
|
|
oOrSE[i].kind = €CloseBy;
|
|
oOrSE[i].uMag = ord.uMag;
|
|
oOrSE[i].uDevOrInf = DEVI;
|
|
oOrSE[i].dVol = vol;
|
|
oOrSE[i].status = €Send;
|
|
reqClsBY.action = TRADE_ACTION_PENDING; // pending order
|
|
reqClsBY.price = oOrSE[i].dOpn;
|
|
reqClsBY.magic = ord.uMag;
|
|
reqClsBY.symbol = _Symbol; // Instrument
|
|
reqClsBY.volume = oOrSE[i].dVol; // Volumen von 0.1 Lot
|
|
reqClsBY.comment = "penTrail TP Mag: "+(string)(ord.uMag%1000000);
|
|
|
|
} else {
|
|
int i = ArrayNew(oOrBU); // <= get a new element set to zero
|
|
reqClsBY.type = ORDER_TYPE_BUY_LIMIT; // opposite direction
|
|
oOrBU[i].dir = €BUYLIMIT; // opposite direction
|
|
oOrBU[i].dOpn = ord.dOpn - diff;
|
|
oOrBU[i].kind = €CloseBy;
|
|
oOrBU[i].uMag = ord.uMag;
|
|
oOrBU[i].uDevOrInf = DEVI;
|
|
oOrBU[i].dVol = vol;
|
|
oOrBU[i].status = €Send;
|
|
|
|
reqClsBY.action = TRADE_ACTION_PENDING; // pending order
|
|
reqClsBY.price = oOrBU[i].dOpn;
|
|
reqClsBY.magic = ord.uMag;
|
|
reqClsBY.symbol = _Symbol; // Instrument
|
|
reqClsBY.volume = oOrBU[i].dVol; // Volumen von 0.1 Lot
|
|
reqClsBY.comment = "penTrail TP Mag: "+(string)(ord.uMag%1000000);
|
|
}
|
|
|
|
|
|
Print("\n",FunLine," ####################### OK: 1st. ORDER for _CLOSE_BY tC:",(string)(ulong)TimeCurrent()," => ",
|
|
"\n BaseOrder: ",_e2s(ord.dir)," ",(string)ord.uID," ",(string)ord.uMag," @ ",_d2D(ord.dOpn)," ",TimeToString(TimeCurrent(),TIME_SECONDS),
|
|
"\n ClsByOrd: ",_e2s(reqClsBY.type)," p: ",_d2D(reqClsBY.price)," vol: ",reqClsBY.volume," cmt: ",reqClsBY.comment);
|
|
|
|
ResetLastError(); // err: 4756=ERR_TRADE_SEND_FAILED, 10013=TRADE_RETCODE_INVALID, 10015Invalid price in the request
|
|
if(!OrderSendAsync(reqClsBY,resClsBY)) {
|
|
Print("\n",__FUNCTION__,"[",__LINE__,"] ################ FAIL: 1st. ORDER_TYPE_CLOSE_BY ########",
|
|
"\n ORDER_TYPE_CLOSE_BY OrderSendAsync error ",err(_LastError)," res.order ",resClsBY.retcode,
|
|
"\ntC ",_t2All(TimeCurrent())," ask: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_ASK))
|
|
);
|
|
Print(FunLine,prtRequ(reqClsBY));
|
|
Print(FunLine,prtResult(resClsBY));
|
|
return( chkFail(FunLine,reqClsBY,resClsBY) );
|
|
//ExpertRemove();
|
|
} else {
|
|
//DebugBreak();
|
|
int m = ArrayNew(match);
|
|
match[m][matchPOS]=ord.uID; //should be triggered first
|
|
match[m][matchMAG]=ord.uMag;
|
|
match[m][matchCLS]=resClsBY.order; //when triggered should close by matchPOS
|
|
|
|
chkREQ(FunLine,reqClsBY,resClsBY.order);
|
|
ResetLastError(); // err: 4756=ERR_TRADE_SEND_FAILED, 10013=TRADE_RETCODE_INVALID,
|
|
return(true);
|
|
|
|
}
|
|
return(false);
|
|
|
|
}
|
|
|
|
bool tradeCloseOpnPos(_opTrd &op[]) {
|
|
int i = ArraySize(op),
|
|
sz = i;
|
|
if (sz<1) return(false);
|
|
while(i-->0) {
|
|
if (WhatDebug == €DebugConf || WhatDebug == €DebugAll)
|
|
Print(__FUNCTION__,"[",__LINE__,"] CHECK cls #",op[i].uID," => ",prtOneOpnPos(op[i].uID,FunLine));
|
|
DeBugORDER = op[i].uID;
|
|
bool ok = tradeCloseTckt(op[i].uID);
|
|
if (!ok) { // tradeCloseTckt(op[i].uID)) {
|
|
Print(__FUNCTION__,"[",__LINE__,"] CLOSE #",op[i].uID," FAILED ",prtOneOpnPos(op[i].uID,FunLine));
|
|
} //else already closed so array access error: Print(__FUNCTION__,"[",__LINE__,"] CLOSE #",oPO[i].uID," OK ",prtOneOpnPos(i));
|
|
}
|
|
return(true);
|
|
}
|
|
|
|
//use: tradeCloseTckt(ticket) //, const ulong deviation=5);
|
|
bool tradeCloseTckt(const ulong ticket, const ulong deviation=0)
|
|
{
|
|
//--- check stopped
|
|
if(IsStopped()) return(false);
|
|
if(!PositionSelectByTicket(ticket)) {
|
|
adminRmvOpPos(ticket);
|
|
return(true);
|
|
}
|
|
|
|
MqlTradeRequest req;MqlTradeResult res;
|
|
ZeroMemory(req);ZeroMemory(res);
|
|
|
|
req.symbol = PositionGetString(POSITION_SYMBOL);
|
|
if ( ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) ) {
|
|
req.type = ORDER_TYPE_SELL;
|
|
req.price = SymbolInfoDouble(req.symbol,SYMBOL_BID);
|
|
} else {
|
|
req.type = ORDER_TYPE_BUY;
|
|
req.price = SymbolInfoDouble(req.symbol,SYMBOL_ASK);
|
|
}
|
|
req.action = TRADE_ACTION_DEAL;
|
|
req.position = ticket;
|
|
req.volume = PositionGetDouble(POSITION_VOLUME);
|
|
req.magic = PositionGetInteger(POSITION_MAGIC);
|
|
req.deviation = deviation>0 ? deviation : 10;
|
|
Print("\n",__FUNCTION__,"[",__LINE__,"] ####################### OK: POS Close 1st TRY 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);
|
|
|
|
if(OrderSendAsync(req,res)) {
|
|
//DebugBreak();
|
|
chkREQ(FunLine,req,res.order);
|
|
DeBugORDER = res.order;
|
|
Print(__FUNCTION__,"[",__LINE__,"] check started DeBugORDER: ",DeBugORDER);
|
|
ResetLastError(); // err: 4756=ERR_TRADE_SEND_FAILED, 10013=TRADE_RETCODE_INVALID,
|
|
return(true);
|
|
} else {
|
|
Print("\n",__FUNCTION__,"[",__LINE__,"] ################ FAIL: POS Close 1st TRY ########\n ORDER_TYPE_CLOSE OrderSendAsync error ",err(_LastError)," res.order ",res.retcode,
|
|
"\ntC ",_t2All(TimeCurrent())," ask: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_ASK))
|
|
);
|
|
Print(FunLine,prtRequ(req));
|
|
Print(FunLine,prtResult(res));
|
|
bool ok = chkFail(FunLine,req,res);
|
|
if (ok) return(true);
|
|
Print(FunLine,prtRequ(req));
|
|
Print(FunLine,prtResult(res));
|
|
ok = chkFail(FunLine,req,res);
|
|
if (ok) return(true);
|
|
Print(FunLine,prtRequ(req));
|
|
Print(FunLine,prtResult(res));
|
|
ok = chkFail(FunLine,req,res);
|
|
if (ok) return(true);
|
|
Print(FunLine,prtRequ(req));
|
|
Print(FunLine,prtResult(res));
|
|
return(chkFail(FunLine,req,res));
|
|
//ExpertRemove();
|
|
}
|
|
return(false);
|
|
|
|
}
|
|
|
|
|
|
//use: if(!tradeClosePartPos(tckt, 0.01);
|
|
bool tradeClosePartPos(_opTrd &ord, const double volCls) {
|
|
|
|
// first check position
|
|
if (!PositionSelectByTicket(ord.uID)) return(false);
|
|
|
|
MqlTradeRequest req={};
|
|
MqlTradeResult res={};
|
|
|
|
req.type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
|
|
|
|
req.action = TRADE_ACTION_DEAL; // Typ der Transaktion
|
|
req.position = ord.uID;
|
|
req.price = PositionGetDouble(POSITION_PRICE_CURRENT);
|
|
req.volume = volCls;
|
|
req.symbol = PositionGetString(POSITION_SYMBOL);
|
|
req.deviation = 10;
|
|
req.comment = "cls Pos partially ("+_d22(PositionGetDouble(POSITION_VOLUME))+") Mag: "+(string)(ord.uMag%100000);
|
|
Print("\n",FunLine," ####################### OK: Close Partially Position",
|
|
"\n Pos tckt: ",ord.uID," mag:",ord.uMag," ",TimeToString(TimeCurrent(),TIME_SECONDS)," ",req.comment,
|
|
"\n vol: ",PositionGetDouble(POSITION_VOLUME)," => clsVol: ",_d22(volCls)," => newVol ",_d22(PositionGetDouble(POSITION_VOLUME) - volCls));
|
|
|
|
if(!OrderSendAsync(req,res)) {
|
|
Print(__FUNCTION__,"[",__LINE__,"] OrderSendAsync error ",err(_LastError)," res.order ",res.retcode," ",err(res.retcode)," r.D: ",res.deal," r.O: ",res.order,
|
|
"\ntC ",_t2All(TimeCurrent())," ask: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_ASK))," bid: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_BID))," pCurr:",_d2D(req.price)
|
|
);
|
|
Print(FunLine,prtRequ(req));
|
|
Print(FunLine,prtResult(res));
|
|
return( chkFail(FunLine,req,res) );
|
|
ResetLastError(); // err: 4756=ERR_TRADE_SEND_FAILED, 10013=TRADE_RETCODE_INVALID,
|
|
} else {
|
|
chkREQ(FunLine,req,res.order);
|
|
return(true);
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
//use: tradeCloseTcktByPos(t1, t2, mag);
|
|
bool tradeCloseTcktByPos(const ulong t1, const ulong t2, const ulong m) {
|
|
|
|
//--- check position existence
|
|
if(!PositionSelectByTicket(t1)) return(false);
|
|
|
|
string symbol=PositionGetString(POSITION_SYMBOL);
|
|
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
if(!PositionSelectByTicket(t2))
|
|
return(false);
|
|
string symbol_by=PositionGetString(POSITION_SYMBOL);
|
|
ENUM_POSITION_TYPE type_by=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
|
|
//--- check positions
|
|
if(type==type_by) return(false);
|
|
if(symbol!=symbol_by) return(false);
|
|
|
|
MqlTradeRequest req={};
|
|
MqlTradeResult res={};
|
|
|
|
//--- setting request
|
|
req.action = TRADE_ACTION_CLOSE_BY;
|
|
req.position = t1;
|
|
req.position_by = t2;
|
|
req.magic = m;
|
|
//--- close position
|
|
Print("\n",__FUNCTION__,"[",__LINE__,"] ####################### OK: Close 1 by 1 \n t1:",t1," t2:",t2," m:",m," ",TimeToString(TimeCurrent(),TIME_SECONDS)," ",req.comment,"\n MODIF POS SL & TP r.ID: ",res.request_id," d.O: ",res.deal," r.O: ",res.order," r.ret: ",res.retcode);
|
|
if (!OrderSendAsync(req,res)) {
|
|
Print(__FUNCTION__,"[",__LINE__,"] OrderSendAsync Cls 1by1 error ",err(_LastError)," t1:",t1," t2:",t2," res.order ",res.retcode," ",err(res.retcode)," r.D: ",res.deal," r.O: ",res.order,
|
|
"\ntC ",_t2All(TimeCurrent())," ask: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_ASK))," bid: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_BID))," pCurr:",_d2D(req.price)
|
|
);
|
|
return( chkFail(FunLine,req,res) );
|
|
} else {
|
|
chkREQ(FunLine,req,res.order);
|
|
return(true);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// use tradeNewTPSLPos(tckt, nSL:ask|bid +/- 400.0*_Point, nTP:ask|bid -/+ 200.0*_Point);
|
|
bool tradeNewTPSLPos(const ulong tckt, const double nSL=0., const double nTP=0., const string from="") {
|
|
if (nSL + nTP < _Point) return(false);
|
|
if (!PositionSelectByTicket(tckt)) { Print(__FILE__,"[",__LINE__,"] tckt:",tckt," not found from: ",from," err:",err());return(false);} //DebugBreak();
|
|
MqlTradeRequest req={};
|
|
MqlTradeResult res={};
|
|
|
|
req.action = TRADE_ACTION_SLTP; // Typ der Transaktion
|
|
req.position = tckt;
|
|
req.price = PositionGetDouble(POSITION_PRICE_CURRENT);
|
|
req.symbol = PositionGetString(POSITION_SYMBOL);
|
|
req.magic = PositionGetInteger(POSITION_MAGIC); // MagicNumber der Position
|
|
req.sl = (nSL>0.) ? nSL : PositionGetDouble(POSITION_SL);
|
|
req.tp = (nTP>0.) ? nTP : PositionGetDouble(POSITION_TP);
|
|
req.comment = "chg Pos "+(string)tckt+" sl:"+_d2D(nSL)+" tp:"+_d2D(nTP);
|
|
if(false) prtRequ(req,__LINE__);
|
|
if(!OrderSendAsync(req,res)) {
|
|
Print(__FUNCTION__,"[",__LINE__,"] OrderSendAsync error ",err(_LastError)," from: ",from," res.order ",res.retcode," ",err(res.retcode)," tckt: ",tckt," r.D: ",res.deal," r.O: ",res.order,
|
|
"\ntC ",_t2All(TimeCurrent())," ask: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_ASK))," bid: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_BID))," pCurr:",_d2D(req.price),
|
|
" req.sl",_d2D(req.sl)," nSL",_d2D(nSL)," req.tp",_d2D(req.tp)," nTP",_d2D(nTP)
|
|
);
|
|
return( chkFail(FunLine,req,res) );
|
|
|
|
} else {
|
|
//Print("\n",__FUNCTION__,"[",__LINE__,"] ####################### OK:CHG SL/TP Position \n from: ",from," m:",req.magic," ",TimeToString(TimeCurrent(),TIME_SECONDS)," ",req.comment," MODIF POS SL & TP r.ID: ",res.request_id," d.O: ",res.deal," r.O: ",res.order," r.ret: ",res.retcode);
|
|
chkREQ(FunLine,req,res.order);
|
|
return(true);
|
|
}
|
|
return(false);
|
|
}
|
|
// use tradeMoveTPSLPos(tckt, 400.0*_Point, 200.0*_Point);
|
|
bool tradeMoveTPSLPos(_opTrd &ord, const double nSL=0., const double nTP=0.) {
|
|
if (!PositionSelectByTicket(ord.uID)) return(false);
|
|
MqlTradeRequest req={};
|
|
MqlTradeResult res={};
|
|
double dir = PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY ? 1.0 : -1.0;
|
|
|
|
req.action = TRADE_ACTION_SLTP; // Typ der Transaktion
|
|
req.position = ord.uID;
|
|
req.price = PositionGetDouble(POSITION_PRICE_CURRENT);
|
|
req.symbol = PositionGetString(POSITION_SYMBOL);
|
|
req.magic = PositionGetInteger(POSITION_MAGIC); // MagicNumber der Position
|
|
if(nSL>0.) req.sl = req.price - dir*nSL;
|
|
if(nTP>0.) req.tp = req.price + dir*nTP;
|
|
req.comment = "chg Pos "+(string)ord.uID+" sl:"+_d2D(nSL)+" tp:"+_d2D(nTP);
|
|
if(!OrderSendAsync(req,res)) {
|
|
Print(FunLine," OrderSendAsync error ",err(_LastError)," res.order ",res.retcode," ",err(res.retcode)," r.D: ",res.deal," r.O: ",res.order,
|
|
"\ntC ",_t2All(TimeCurrent())," ask: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_ASK))," bid: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_BID))," pCurr:",_d2D(req.price)
|
|
);
|
|
Print(FunLine,prtRequ(req)); Print(FunLine,prtResult(res));
|
|
return( chkFail(FunLine,req,res) );
|
|
ResetLastError(); // err: 4756=ERR_TRADE_SEND_FAILED, 10013=TRADE_RETCODE_INVALID,
|
|
} else {
|
|
Print("\n",__FUNCTION__,"[",__LINE__,"] ####################### OK: CHG SL/TP Position \n mag:",req.magic," ",TimeToString(TimeCurrent(),TIME_SECONDS)," ",req.comment,"\n MODIF POS SL & TP r.ID: ",res.request_id," d.O: ",res.deal," r.O: ",res.order," r.ret: ",res.retcode);
|
|
chkREQ(FunLine,req,req.position);
|
|
return(true);
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
// use tradeMoveTPSLPos(tckt, 400.0*_Point, 200.0*_Point);
|
|
bool tradeTrailTPSLPos(const ulong tckt, const int nSL=0, const int nTP=0, const €SetMoveTpSl newTpSl=€MoveTpSl) {
|
|
if (!PositionSelectByTicket(tckt) || nSL+nTP==0) return(false);
|
|
MqlTradeRequest req={};
|
|
MqlTradeResult res={};
|
|
double dir = PositionGetInteger(POSITION_TYPE)%2 == 0 ? 1.0 : -1.0; // Type % 2 == all BUYs
|
|
double pnt = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_POINT);
|
|
|
|
req.price = PositionGetDouble(POSITION_PRICE_CURRENT);
|
|
if (newTpSl==€MoveTpSl) {
|
|
if(nSL>0.) req.sl = PositionGetDouble(POSITION_SL) - dir*nSL*pnt;
|
|
if(nTP>0.) req.tp = PositionGetDouble(POSITION_TP) + dir*nTP*pnt;
|
|
} else {
|
|
if(nSL>0.) req.sl = req.price - dir*nSL*pnt;
|
|
if(nTP>0.) req.tp = req.price + dir*nTP*pnt;
|
|
}
|
|
|
|
req.action = TRADE_ACTION_SLTP; // Typ der Transaktion
|
|
req.position = tckt;
|
|
req.symbol = PositionGetString(POSITION_SYMBOL);
|
|
req.magic = PositionGetInteger(POSITION_MAGIC); // MagicNumber der Position
|
|
req.comment = "chg Pos "+(string)tckt+" sl:"+_d21(nSL)+" tp:"+_d21(nTP);
|
|
if(!OrderSendAsync(req,res)) {
|
|
Print(__FUNCTION__,"[",__LINE__,"] OrderSendAsync error ",err(_LastError)," res.order ",res.retcode," ",err(res.retcode)," r.D: ",res.deal," r.O: ",res.order,
|
|
"\ntC ",_t2All(TimeCurrent())," ask: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_ASK))," bid: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_BID))," pCurr:",_d2D(req.price)
|
|
);
|
|
Print(FunLine,prtRequ(req));
|
|
Print(FunLine,prtResult(res));
|
|
return( chkFail(FunLine,req,res) );
|
|
|
|
ResetLastError(); // err: 4756=ERR_TRADE_SEND_FAILED, 10013=TRADE_RETCODE_INVALID,
|
|
} else {
|
|
Print("\n",__FUNCTION__,"[",__LINE__,"] ####################### OK: Set SL, TP of Position \n ",req.magic," ",TimeToString(TimeCurrent(),TIME_SECONDS)," ",req.comment," MODIF POS SL & TP r.ID: ",res.request_id," d.O: ",res.deal," r.O: ",res.order," r.ret: ",res.retcode);
|
|
chkREQ(FunLine,req,res.order);
|
|
return(true);
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
// use tradeNewTPSLOrd(tradeNewTPSLOrd, 400.0*_Point);
|
|
bool tradeNewTPSLOrd(_opTrd &ord, const double nSL=0., const double nTP=0.) {
|
|
if (!OrderSelect(ord.uID)) return(false);
|
|
|
|
MqlTradeRequest req={};
|
|
MqlTradeResult res={};
|
|
|
|
|
|
req.symbol = OrderGetString(ORDER_SYMBOL);
|
|
req.action = TRADE_ACTION_MODIFY; // Typ der Transaktion
|
|
req.magic = OrderGetInteger(ORDER_MAGIC); // MagicNumber der Order
|
|
req.order = ord.uID;
|
|
req.stoplimit = OrderGetDouble(ORDER_PRICE_STOPLIMIT);
|
|
req.price = OrderGetDouble(ORDER_PRICE_OPEN); // use of ORDER_PRICE_CURRENT will trigger the pend.order. immediately ;)
|
|
req.sl = nSL>0. ? nSL : OrderGetDouble(ORDER_SL);
|
|
req.tp = nTP>0. ? nTP : OrderGetDouble(ORDER_TP);
|
|
req.type_time = (ENUM_ORDER_TYPE_TIME)OrderGetInteger(ORDER_TYPE_TIME);
|
|
req.expiration = (datetime)OrderGetInteger(ORDER_TIME_EXPIRATION);
|
|
req.comment = "chg Ord "+(string)(ord.uID%100000)+" sl:"+_d2D(nSL)+" tp:"+_d2D(nTP);
|
|
if(!OrderSendAsync(req,res)) {
|
|
Print(__FUNCTION__,"[",__LINE__,"] OrderSendAsync error ",err(_LastError)," res.order ",res.retcode," ",err(res.retcode)," r.D: ",res.deal," r.O: ",res.order,
|
|
"\ntC ",_t2All(TimeCurrent())," ask: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_ASK))," bid: ",_d2D(SymbolInfoDouble(_Symbol,SYMBOL_BID))," pCurr:",_d2D(req.price)
|
|
);
|
|
Print(FunLine,prtRequ(req));
|
|
Print(FunLine,prtResult(res));
|
|
return( chkFail(FunLine,req,res) );
|
|
ResetLastError(); // err: 4756=ERR_TRADE_SEND_FAILED, 10013=TRADE_RETCODE_INVALID,
|
|
} else {
|
|
Print("\n",__FUNCTION__,"[",__LINE__,"] ####################### OK: chg OpnOrd SL, TP \n ",req.magic," ",TimeToString(TimeCurrent(),TIME_SECONDS)," ",req.comment," MODIF POS SL & TP r.ID: ",res.request_id," d.O: ",res.deal," r.O: ",res.order," r.ret: ",res.retcode);
|
|
chkREQ(FunLine,req,res.order);
|
|
return(true);
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
// Kochbuch OnTradeTransaction: OnTradeTransaction 1.1316999999999999
|
|
void OnTradeTransaction(const MqlTradeTransaction& trans,
|
|
const MqlTradeRequest& request,
|
|
const MqlTradeResult& result) {
|
|
ulong p = fmax(trans.position,request.position), // ticket number of a position
|
|
o = fmax3(trans.order,request.order,result.order), // ticket number of an order
|
|
d = fmax(trans.deal,result.deal), // ticket number of a deal
|
|
pB = fmax(trans.position_by,request.position_by), // ticket number of a conjugated position
|
|
m = request.magic, mP=0,mO=0,mD=0; // magic number
|
|
string sym = fmax(trans.symbol,request.symbol), // symbol
|
|
sQts = "";
|
|
if (StringLen(sym)<4) DebugBreak();
|
|
ResetLastError();
|
|
|
|
|
|
if (false && ( m%1000 == 55 && TimeCurrent() > D'2022.02.03 02:23:00')) { // 2023.01.09 15:16:15 take profit triggered #16 buy 1 EURUSD 1.06942 sl: 1.06488 tp: 1.07017 [#17 sell 1 EURUSD at 1.07017]
|
|
//if ( TimeCurrent()>D'2022.02.03 14:40:59' && OrdersTotal() == 0 ) {
|
|
//if ( true && (TimeCurrent()>D'2022.02.03 01:59:58' || (DeBugORDER>0 && (DeBugORDER == o || DeBugORDER == p)) )) {
|
|
if(p>0 && PositionSelectByTicket(p)) mP = (ulong)PositionGetInteger(POSITION_MAGIC); else mP=1;
|
|
if(o>0 && OrderSelect(o)) mO = (ulong)OrderGetInteger(ORDER_MAGIC); else mO=1;
|
|
if(d>0 && HistoryDealSelect(d)) mD = (ulong)HistoryDealGetInteger(d,DEAL_MAGIC); else mD=1;
|
|
MqlTick lT; SymbolInfoTick(_Symbol,lT); sQts=StringFormat("ask:%s bid:%s",_d2D(lT.ask),_d2D(lT.bid));
|
|
Print(__FUNCTION__,"[",__LINE__,"] mag:",m," nOrd:",OrdersTotal(),", nPos:",PositionsTotal(),", ",sQts);
|
|
prtListOpnOrdr();
|
|
prtListOpnPos();
|
|
prtOneOpnPos(p, FunLine);
|
|
listOpMatch(FunLine);
|
|
ArrayPrint(ReqCHCK);
|
|
Print(__FUNCTION__,"[",__LINE__,"] DEBUG res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mD:",mD," mP:",mP," mO:",mO," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type)," res.ret;",result.retcode);
|
|
//Print(FunLine,prtTrans(trans));
|
|
//Print(FunLine,prtRequ(request));
|
|
//Print(FunLine,prtResult(result));
|
|
DebugBreak();
|
|
}
|
|
|
|
|
|
int iConf = -2147483648;
|
|
|
|
//--- first case result returns success == 10009
|
|
if (result.retcode==10009) {
|
|
switch (request.action) {
|
|
case TRADE_ACTION_DEAL:
|
|
if(p>0 && o>p) {
|
|
if(false)Print(__FUNCTION__,"[",__LINE__,"] TRIG (Part.) CLS res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
iConf = confReq(sym, m, trans, request);
|
|
if (iConf==-1) Print(__FUNCTION__,"[",__LINE__,"] szReq: ",ArraySize(ReqCHCK)," ",prtRequ(request,__LINE__ ));
|
|
return;
|
|
|
|
} else if (p>0 && o==p) {
|
|
if (m==0) {
|
|
if(d>0 && HistoryDealSelect(d)) mD = (ulong)HistoryDealGetInteger(d,DEAL_MAGIC); else mD=1;
|
|
if(p>0 && PositionSelectByTicket(p)) mP = (ulong)PositionGetInteger(POSITION_MAGIC); else mP=1;
|
|
m = fmax(mD,mP);
|
|
}
|
|
if(false)Print(__FUNCTION__,"[",__LINE__,"] TRIG OPN new MKT-POS a) res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
iConf = confReq(sym, m, trans, request);
|
|
if (iConf==-1) Print(__FUNCTION__,"[",__LINE__,"] szReq: ",ArraySize(ReqCHCK)," ",prtRequ(request,__LINE__ ));
|
|
return;
|
|
|
|
} else if (d>0 && o>0 && m>0) {
|
|
if (HistoryDealSelect(d)) if(false)Print(FunLine,__LINE__,prtHistDeal(d));
|
|
if(true)
|
|
iConf = confReq(sym, m, trans, request);
|
|
if (iConf==-1) Print(__FUNCTION__,"[",__LINE__,"] already confirmed new MKT-POS b) res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
else Print(__FUNCTION__,"[",__LINE__,"] TRIG OPN new MKT-POS b) res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
return;
|
|
|
|
} else {
|
|
if(true)Print(__FUNCTION__,"[",__LINE__,"] ???? TRADE_ACTION_DEAL res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
}
|
|
return;
|
|
case TRADE_ACTION_PENDING:
|
|
if(OrderSelect(o)) m = (ulong)OrderGetInteger(ORDER_MAGIC); else m=1;
|
|
if(true)Print(__FUNCTION__,"[",__LINE__,"] TRIG Pend:Accpt res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
iConf = confReq(sym, m, trans, request, result);
|
|
if (iConf==-1) Print(FunLine," szReq: ",ArraySize(ReqCHCK));//," ",prtRequ(request,__LINE__ ));
|
|
return;
|
|
|
|
case TRADE_ACTION_SLTP:
|
|
if(false)Print(FunLine," TRIG CHG SL,TP res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
iConf = confReq(sym, request.magic, trans, request);
|
|
if (iConf==-1) Print(FunLine," szReq: ",ArraySize(ReqCHCK)," ",prtRequ(request,__LINE__ ));
|
|
else Print(FunLine," ADMIN openPos Arrays");
|
|
return;
|
|
|
|
case TRADE_ACTION_MODIFY:
|
|
if(OrderSelect(o)) m = (ulong)OrderGetInteger(ORDER_MAGIC); else { m=1;
|
|
if(true) Print(FunLine," TRIG CHG SL, TP res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
}
|
|
if (m>1) {
|
|
iConf = confReq(sym, m, trans, request);
|
|
if (iConf==-1) Print(FunLine," szReq: ",ArraySize(ReqCHCK)," ",prtRequ(request,__LINE__ ));
|
|
else Print(FunLine," ADMIN openPos Arrays"); // order not fpund => already processed
|
|
}
|
|
return;
|
|
|
|
|
|
/* default:
|
|
if(p>0 && PositionSelectByTicket(p)) mP = (ulong)PositionGetInteger(POSITION_MAGIC); else mP=1;
|
|
if(o>0 && OrderSelect(o)) mO = (ulong)OrderGetInteger(ORDER_MAGIC); else mO=1;
|
|
if(d>0 && HistoryDealSelect(d)) mD = (ulong)HistoryDealGetInteger(d,DEAL_MAGIC); else mD=1;
|
|
if (mP>1 || mO>1)
|
|
if(false)Print(__FUNCTION__,"[",__LINE__,"] SKIP trans.type==TRADE_TRANSACTION_HISTORY_ADD res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mD:",mD," mP:",mP," mO:",mO," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
*/ }
|
|
|
|
|
|
//--- second case the type of trans is needed HISTORY_ADD:
|
|
} else if (trans.type==TRADE_TRANSACTION_HISTORY_ADD) {
|
|
|
|
// #p > 0 && #po == #p
|
|
if (p==o && p>0 && trans.order_type> ORDER_TYPE_SELL ) { // pending order send?
|
|
if(PositionSelectByTicket(p)) m = (ulong)PositionGetInteger(POSITION_MAGIC); else m=1;
|
|
iConf = confReq(sym, m, trans, request);
|
|
if (iConf==-1) Print(__FUNCTION__,"[",__LINE__,"] szReq: ",ArraySize(ReqCHCK));//," ",prtRequ(request,__LINE__ ));
|
|
int i = getOpMatch(m,p);
|
|
if(true)Print(__FUNCTION__,"[",__LINE__,"] TRIG Pend:POS res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n match:",i," iConf:",iConf," tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
//listOpMatch();//int i = getOpMatch(mag,
|
|
//prtListOpnOrdr();
|
|
//prtListOpnPos();
|
|
//ArrayPrint(ReqCHCK);
|
|
|
|
return;
|
|
|
|
// #p > 0 && #o > #p
|
|
} else if (p>0 && o>p && d>0) {
|
|
if(d>0 && HistoryDealSelect(d)) mD = (ulong)HistoryDealGetInteger(d,DEAL_MAGIC); else mD=1;
|
|
ENUM_DEAL_ENTRY how = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(d,DEAL_ENTRY); // DEAL_ENTRY_OUT
|
|
ENUM_DEAL_REASON why = (ENUM_DEAL_REASON)HistoryDealGetInteger(d,DEAL_REASON); // DEAL_REASON_EXPERT
|
|
if(false)Print(__FUNCTION__,"[",__LINE__,"] TRIG CLS POS by SL or TP res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
if ( how == DEAL_ENTRY_OUT_BY || how == DEAL_ENTRY_OUT ) {
|
|
//if(false)Print(FunLine,prtHistDeal(d));Print(FunLine,prtTrans(trans));
|
|
//Print(FunLine,prtRequ(request));Print(FunLine,prtResult(result));
|
|
int i = getOpMatch(m,p);
|
|
iConf = confReq(sym, mD, p, how);
|
|
if (iConf==-1) Print(FunLine," szReq: ",ArraySize(ReqCHCK)," match:",i," iConf:",iConf);
|
|
listOpMatch(FunLine,"TRADE_TRANSACTION_HISTORY_ADD");
|
|
} else if ( mP!=1) {
|
|
if(true)Print(FunLine," SL,TP TRIGG res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mD:",mD," mP:",mP," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
} else if (p>0 && mP==1 ) {
|
|
if(true)Print(FunLine," SL,TP TRIGG POS CLSD res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mD:",mD," mP:",mP," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
} else {
|
|
if(true)Print(FunLine," SL,TP ??? res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mD:",mD," mP:",mP," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
}
|
|
return;
|
|
|
|
|
|
}
|
|
/* else {
|
|
if(p>0 && PositionSelectByTicket(p)) mP = (ulong)PositionGetInteger(POSITION_MAGIC); else mP=1;
|
|
if(o>0 && OrderSelect(o)) mO = (ulong)OrderGetInteger(ORDER_MAGIC); else mO=1;
|
|
if(d>0 && HistoryDealSelect(d)) mD = (ulong)HistoryDealGetInteger(d,DEAL_MAGIC); else mD=1;
|
|
if (mP>1 || mO>1)
|
|
if(false)Print(__FUNCTION__,"[",__LINE__,"] SKIP trans.type==TRADE_TRANSACTION_HISTORY_ADD res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mD:",mD," mP:",mP," mO:",mO," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
}
|
|
*/
|
|
|
|
|
|
//--- third case the type of trans is needed DEAL_ADD with #deal !=0:
|
|
} else if (p>0 && o==p && d>0 && trans.type==TRADE_TRANSACTION_DEAL_ADD) {
|
|
if(false) Print(__FUNCTION__,"[",__LINE__,"] SKIP res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mD:",mD," mP:",mP," mO:",mO," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type)," res.ret;",result.retcode);
|
|
|
|
if(p>0 && PositionSelectByTicket(p)) mP = (ulong)PositionGetInteger(POSITION_MAGIC); else mP=1;
|
|
if(HistoryDealSelect(d)) mD = (ulong)HistoryDealGetInteger(d,DEAL_MAGIC); else mD=1;
|
|
if( mD>1 ) {
|
|
ENUM_DEAL_ENTRY how = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(d,DEAL_ENTRY); // DEAL_ENTRY_OUT
|
|
ENUM_DEAL_REASON why = (ENUM_DEAL_REASON)HistoryDealGetInteger(d,DEAL_REASON); // DEAL_REASON_EXPERT
|
|
int i = getOpMatch(mD,p);
|
|
if(false)Print(__FUNCTION__,"[",__LINE__,"] TRIG SellStop CLS POS by SL or TP res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n match[:",i,"] how:",_e2s(how)," why:",_e2s(why),"tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
if ( how == DEAL_ENTRY_IN ) {
|
|
if ( i<0 ) { // no match
|
|
iConf = confReq(sym, mD, trans, request);
|
|
if(true)Print(__FUNCTION__,"[",__LINE__,"] TRIG SellStop CLS POS by SL or TP res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n match[:",i,"] confREQ:",iConf," how:",_e2s(how)," why:",_e2s(why),"tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
//if (iConf==-1)
|
|
} else {
|
|
//Print(FunLine,prtHistDeal(d));Print(FunLine,prtTrans(trans));
|
|
//Print(FunLine,prtRequ(request));Print(FunLine,prtResult(result));
|
|
iConf = confReq(sym, mD, p, how);
|
|
if (iConf==-1) Print(__FUNCTION__,"[",__LINE__,"] szReq: ",ArraySize(ReqCHCK));//," ",prtRequ(request,__LINE__ ));
|
|
if(false) listOpMatch(FunLine,"TRADE_TRANSACTION_DEAL_ADD, DEAL_ENTRY_IN");
|
|
i = getOpMatch(mD,p);
|
|
if (tradeCloseTcktByPos(match[i][matchPOS],match[i][matchCLS],match[i][matchMAG])) {
|
|
if(rmvOpMatch(i)) if(true)Print(__FUNCTION__,"[",__LINE__,"] OK DEAL_ENTRY_IN rmv err: ",err());
|
|
} else if(false)Print(__FUNCTION__,"[",__LINE__,"] FAIL DEAL_ENTRY_IN rmv err: ",err());
|
|
}
|
|
|
|
|
|
} else if ( how == DEAL_ENTRY_OUT_BY || how == DEAL_ENTRY_OUT ) {
|
|
//Print(FunLine,prtHistDeal(d));Print(FunLine,prtTrans(trans));
|
|
//Print(FunLine,prtRequ(request));Print(FunLine,prtResult(result));
|
|
iConf = confReq(sym, mD, p, how);
|
|
if (iConf==-1) Print(__FUNCTION__,"[",__LINE__,"] szReq: ",ArraySize(ReqCHCK)," ",prtRequ(request,__LINE__ ));
|
|
listOpMatch(FunLine,"TRADE_TRANSACTION_DEAL_ADD, DEAL_ENTRY_IN");
|
|
i = getOpMatch(mD,p);
|
|
if (tradeCloseTcktByPos(match[i][matchPOS],match[i][matchCLS],match[i][matchMAG])) {
|
|
if(rmvOpMatch(i)) if(true)Print(__FUNCTION__,"[",__LINE__,"] OK DEAL_ENTRY_OUT_BY rmv err: ",err());
|
|
} else if(false)Print(__FUNCTION__,"[",__LINE__,"] FAIL DEAL_ENTRY_OUT_BY rmv err: ",err());
|
|
|
|
|
|
} else if ( why == DEAL_REASON_TP || why == DEAL_REASON_SL ) {
|
|
if(true)Print(__FUNCTION__,"[",__LINE__,"] TRIG CLS POS by SL or TP res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
} else {
|
|
if(true)Print(__FUNCTION__,"[",__LINE__,"] TRIG TRADE_TRANSACTION_DEAL_ADD res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
}
|
|
}
|
|
|
|
else {
|
|
if(p>0 && PositionSelectByTicket(p)) mP = (ulong)PositionGetInteger(POSITION_MAGIC); else mP=1;
|
|
if(o>0 && OrderSelect(o)) mO = (ulong)OrderGetInteger(ORDER_MAGIC); else mO=1;
|
|
if(d>0 && HistoryDealSelect(d)) mD = (ulong)HistoryDealGetInteger(d,DEAL_MAGIC); else mD=1;
|
|
if (mP>1 || mO>1)
|
|
if(true)Print(__FUNCTION__,"[",__LINE__,"] SKIP trans.type==TRADE_TRANSACTION_DEAL_ADD res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mD:",mD," mP:",mP," mO:",mO," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
}
|
|
|
|
|
|
|
|
} else if (p>0 && o>p && trans.type==TRADE_TRANSACTION_DEAL_ADD) {
|
|
if(HistoryDealSelect(d)) mD = (ulong)HistoryDealGetInteger(d,DEAL_MAGIC); else mD=1;
|
|
if( mD>1 ) {
|
|
ENUM_DEAL_ENTRY how = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(d,DEAL_ENTRY); // DEAL_ENTRY_OUT
|
|
ENUM_DEAL_REASON why = (ENUM_DEAL_REASON)HistoryDealGetInteger(d,DEAL_REASON); // DEAL_REASON_EXPERT
|
|
//Print(__FUNCTION__,"[",__LINE__,"] TRIG CLS POS by SL or TP res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",mD," ",err(),
|
|
// "\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
if ( why == DEAL_REASON_TP ) {
|
|
ulong idCls = adminRmvOpPos(p,trans.price);
|
|
if(true)Print(__FUNCTION__,"[",__LINE__,"] TRIG CLS POS by SL or TP res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",mD," CLOSE id:",idCls," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
} else if (why == DEAL_REASON_SL ) {
|
|
ulong idCls = adminRmvOpPos(p,trans.price);
|
|
if(true)Print(__FUNCTION__,"[",__LINE__,"] TRIG CLS POS by SL or TP res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",mD," CLOSE id:",idCls," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
} else if ( how == DEAL_ENTRY_OUT_BY || how == DEAL_ENTRY_OUT ) {
|
|
//if(false)Print(FunLine,prtHistDeal(d));Print(FunLine,prtTrans(trans));
|
|
//Print(FunLine,prtRequ(request));Print(FunLine,prtResult(result));
|
|
if(true)Print(__FUNCTION__,"[",__LINE__,"] TRIG CLS POS by SL or TP res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",mD," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
iConf = confReq(sym, mD, p, how);
|
|
if (iConf==-1) Print(__FUNCTION__,"[",__LINE__,"] szReq: ",ArraySize(ReqCHCK)," ",prtRequ(request,__LINE__ ));
|
|
} else {
|
|
if(true)Print(__FUNCTION__,"[",__LINE__,"] TRIG TRADE_TRANSACTION_DEAL_ADD res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",mD," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
}
|
|
}
|
|
|
|
else {
|
|
if(p>0 && PositionSelectByTicket(p)) mP = (ulong)PositionGetInteger(POSITION_MAGIC); else mP=1;
|
|
if(o>0 && OrderSelect(o)) mO = (ulong)OrderGetInteger(ORDER_MAGIC); else mO=1;
|
|
if(d>0 && HistoryDealSelect(d)) mD = (ulong)HistoryDealGetInteger(d,DEAL_MAGIC); else mD=1;
|
|
if (mP>1 || mO>1)
|
|
Print(__FUNCTION__,"[",__LINE__,"] partial Close (Market) res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mD:",mD," mP:",mP," mO:",mO," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
}
|
|
|
|
} else if (o>0 && trans.type==TRADE_TRANSACTION_ORDER_UPDATE && (trans.order_type==ORDER_TYPE_BUY_LIMIT || trans.order_type==ORDER_TYPE_SELL_LIMIT)) {
|
|
if(OrderSelect(o)) m = (ulong)OrderGetInteger(ORDER_MAGIC); else m=1;
|
|
if(true)Print(__FUNCTION__,"[",__LINE__,"] StpLim => LIM res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mag:",m," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
iConf = confReq(sym, m, trans, request);
|
|
if (iConf==-1) Print(__FUNCTION__,"[",__LINE__,"] szReq: ",ArraySize(ReqCHCK) );//," ",prtRequ(request,__LINE__ ));
|
|
|
|
} else if (false) {
|
|
if(p>0 && PositionSelectByTicket(p)) mP = (ulong)PositionGetInteger(POSITION_MAGIC); else mP=1;
|
|
if(o>0 && OrderSelect(o)) mO = (ulong)OrderGetInteger(ORDER_MAGIC); else mO=1;
|
|
if(d>0 && HistoryDealSelect(d)) mD = (ulong)HistoryDealGetInteger(d,DEAL_MAGIC); else mD=1;
|
|
if (mP>1 || mO>1)
|
|
Print(__FUNCTION__,"[",__LINE__,"] SKIP res:",result.retcode," d:",d," p:",p," o:",o," pB:",pB," rO:",result.order," mD:",mD," mP:",mP," mO:",mO," ",err(),
|
|
"\n tr.type:",_e2s(trans.type)," tr.orT:",_e2s(trans.order_type)," rq.act:",_e2s(request.action)," rq.typ:",_e2s(request.type));
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|