以下のコードを書いて、買いと売りのトレード(売り気配値の上下にある一定数のピップ)を特定の時間に開始します。
もう一方を開いたらすぐに閉じる/キャンセルするにはどうすればよいですか?
利益がXピップスである、または1分後に(最初に到達した条件に応じて)と表示されている場合、どのようにしてオープンしたトレードを閉じることができますか?
私は以下のコードで正しいことをしたかどうか確信が持てません。
double spread = Ask-Bid;
extern datetime time;
extern int pipGap = 7;
extern int lotSize = 0.01;
extern int closeTimeInSeconds = 60;
int start() {
if (TimeCurrent() >= StrToTime(time)){
OrderSend(Symbol(),OP_BUYSTOP,lotSize, Ask + Point*pipGap, 0,0,0);
OrderSend(Symbol(),OP_SELLSTOP,lotSize, Bid - Point*pipGap, 0,0,0);
}
for(int pos = OrdersTotal()-1; pos >= 0 ; pos--) if (
OrderSelect(pos, SELECT_BY_POS)
){
int duration = TimeCurrent() - OrderOpenTime();
if (duration >= closeTimeInSeconds)
OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(),
3*Point);
}
return(0);
}
#property strict
//---
input datetime InpTime1=D'2019.05.01 00:00'; //time to enter the trade, just as an example
input double InpPipsDist=10; //distance in pips to place BS&SS OCO-orders
input int InpCloseSeconds=60; //close time, seconds since main order is sent
input double InpProfitPips=1.; //profit in pips to close all.
input double InpLotSize=0.1; //lot size
input int InpMagicNumber=123456789; //magic number
// ---
#include <Arrays\ArrayObj.mqh>
bool firstOrderOpen;
double PIP;
CArrayObj *ordersList;
// ---
class C2Orders : public CObject
{
private:
int m_ticket1;
int m_ticket2;
datetime m_timeStart;//OrderOpenTime of the two tickets might be different,TimeCurrent() is used as time they are open.
bool m_activated;
void checkTicket(const int ticket) //if one order is open, another is deleted.
{
if(ticket>0 && OrderSelect(ticket,SELECT_BY_TICKET))
{
if(OrderType()<=OP_SELL)
{
if(ticket==m_ticket1)
{
if(OrderDelete(m_ticket2))
printf("%i: failed to delete#%d. error=%d",__LINE__,m_ticket2,_LastError);
m_ticket2=-1;
}
else
{
if(!OrderDelete(m_ticket1))
printf("%i: failed to delete#%d. error=%d",__LINE__,m_ticket1,_LastError);
m_ticket1=-1;
}
m_activated=true;
}
}
}
double getPnlPips(const int ticket)const
{
if(ticket>0 && OrderSelect(ticket,SELECT_BY_TICKET))
{
return (OrderProfit()>0 ? 1 : -1)*fabs(OrderOpenPrice()-OrderClosePrice());
}
return 0;
}
bool try2closeByPnl()const
{
const double pnl=getPnlPips(m_ticket1)+getPnlPips(m_ticket2);
if(pnl-InpProfitPips*PIP>0)
{
printf("%i : pnl=%.5f vs %.5f target. closing the tickets",__LINE__,pnl,InpProfitPips*PIP);
close(m_ticket1);
close(m_ticket2);
return(true);
}
return(false);
}
bool try2closeByTime()const
{
if(TimeCurrent()-m_timeStart-InpCloseSeconds>=0)
{
if(!OrderDelete(m_ticket1))printf("%i: failed to delete#%d. error=%d",__LINE__,m_ticket1,_LastError);
if(!OrderDelete(m_ticket2))printf("%i: failed to delete#%d. error=%d",__LINE__,m_ticket2,_LastError);
return(true);
}
return(false);
}
void close(const int ticket)const
{
if(ticket>0 && OrderSelect(ticket,SELECT_BY_TICKET))
{
RefreshRates();
if(OrderClose(ticket,OrderLots(),OrderClosePrice(),1))
printf("%i: failed to close#%d. error=%d",__LINE__,ticket,_LastError);
}
}
public:
C2Orders(const int ticket1,const int ticket2,const datetime time):
m_ticket1(ticket1),m_ticket2(ticket2),m_activated(false),m_timeStart(time){}
~C2Orders(){}
bool check() //returns FALSE if deleting the object
{
if(!m_activated)
{
checkTicket(m_ticket1);
checkTicket(m_ticket2);
}
if(m_activated)
{
if(try2closeByPnl())
return(false);
}
else
{
if(try2closeByTime())
return(false);
}
return true;
}
};
//+------------------------------------------------------------------+
int OnInit()
{
firstOrderOpen=false;
PIP=_Point*(_Digits%2==1 ? 10 : 1); //does not work for GOLD and indexes, good for FX.
ordersList=new CArrayObj();
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
delete(ordersList);
}
void OnTick()
{
if(!firstOrderOpen && TimeCurrent()>=InpTime1)
{
RefreshRates();
const int ticketBS=OrderSend(_Symbol,OP_BUYSTOP,InpLotSize,NormalizeDouble(Ask+InpPipsDist*PIP,_Digits),0,0,0,NULL,InpMagicNumber);
const int ticketSS=OrderSend(_Symbol,OP_SELLSTOP,InpLotSize,NormalizeDouble(Bid-InpPipsDist*PIP,_Digits),0,0,0,NULL,InpMagicNumber);
C2Orders *oco=new C2Orders(ticketBS,ticketSS,TimeCurrent());
ordersList.Add(oco);
firstOrderOpen=true;
}
if(firstOrderOpen)
{
C2Orders* oco;
for(int i=ordersList.Total()-1;i>=0;i--)//of course you have only one instance, but in real world you may need to loop over them.
{
oco=ordersList.At(i);
if(!oco.check())
ordersList.Delete(i);
}
if(ordersList.Total()==0)
ExpertRemove();//just to finish the test faster.
}
}