问题描述
我正在尝试开发一段MQL4代码,当在满足EA交易指定的条件时,由EA交易开立的头寸未能平仓/清算时,该代码会向您发送通知.
I'm trying to develop a piece of MQL4 code which sends you a notification when an position opened by an Expert Advisor fails to close/liquidate when the conditions specified by the Expert Advisor are met.
这是我到目前为止所拥有的.
ClosePosition()
成功关闭头寸后返回true
,而EA无法关闭头寸时返回false
.这是else if (ClosePosition == false)
插入的地方.
Here is what I have so far.
The ClosePosition()
returns true
when the position is closed successfully and returns false
when the EA fails to close the position. This is where the else if (ClosePosition == false)
kicks in.
//Order Close//
string sym = Symbol();
int ordersTotal = OrdersTotal();
for(int PosSel = ordersTotal-1; PosSel>=0; PosSel--)
{
if(OrderSelect(PosSel,SELECT_BY_POS,MODE_TRADES))
if(OrderTicket() > 0)
if(OrderMagicNumber() == Period())
if(OrderSymbol() == Symbol())
if(TimeCurrent() >=(OrderOpenTime() + 60 * Period()))
{
ClosePosition = OrderClose(OrderTicket(),8,MarketInfo(sym,MODE_BID) + MarketInfo(sym,MODE_SPREAD) * MarketInfo(sym,MODE_POINT),300,clrNONE);
if(ClosePosition == true)
{
Sleep(60000);
int PosSelHist = OrdersHistoryTotal()-1;
bool reshist = OrderSelect(PosSelHist,SELECT_BY_POS,MODE_HISTORY);
if(reshist == true && Digits == 5)
{
double ClosingPrice = OrderClosePrice();
double OpeningPrice = OrderOpenPrice();
double Profit = OrderProfit();
int Ticket = OrderTicket();
SendMail("Trade Notification Email (TNE)","Order# "+DoubleToStr(Ticket,0)+" has been closed on the account "+AccountName()+
"\n"+
"\nThe order exit price for this trade is "+DoubleToStr(ClosingPrice,5)+"with a profit/loss of"+DoubleToStr(Profit,2)+
"\n"+
"\nThe spread charge for this position is £"+DoubleToStr((spread*tickvalue)*LotSize,2)+
"\n"+
"\n-----------------------------------------------------------------------"+
"\n"+
SendNotification("Ticket # "+IntegerToString(Ticket,10)+"has closed with a profit/loss of "+DoubleToStr(Profit,2));
}
else if(reshist == true && Digits == 3)
{
double ClosingPrice = OrderClosePrice();
double OpeningPrice = OrderOpenPrice();
double Profit = OrderProfit();
int Ticket = OrderTicket();
SendMail("Trade Notification Email (TNE)","Order# "+DoubleToStr(Ticket,0)+" has been placed on the account "+AccountName()+
"\n"+
"\nThe order entry price for this trade is "+DoubleToStr(ClosingPrice,3)+"with a profit/loss of"+DoubleToStr(Profit,2)+
"\n"+
"\nThe spread charge for this position is £"+DoubleToStr((spread*tickvalue)*LotSize,2)+
"\n"+
"\n-----------------------------------------------------------------------"+
SendNotification("Ticket # "+IntegerToString(Ticket,10)+" has closed with a profit/loss of "+DoubleToStr(Profit,2));
}
}
else if(ClosePosition == false)
{
int failedClosePosition = OrdersTotal()-1;
bool fail = OrderSelect(failedClosePosition,SELECT_BY_POS,MODE_HISTORY);
if(fail == true)
{
SendNotification("Order Number #"+IntegerToString(OrderTicket(),10)+" has failed to close. Please refer to error code "+IntegerToString(GetLastError()));
}
}
}
}
首先,这是获得所需结果的正确方法,其次;这是对ClosePosition == true
的替代代码进行编码的正确方法,还是这是if
而不是else if
?
Firstly, is this the correct way in getting the desired result, and secondly; is this the correct way of coding the alternative for the ClosePosition == true
, or would this be an if
instead of an else if
?
推荐答案
不,抱歉.该代码很难被确认是正确的.
No, sorry. The code is hard to get confirmed to be correct.
当然可以解决一些语法错误.
Sure, a few syntax errors could be fixed.
重复的大部分处理可能会起作用,但很难长期维护,并且被认为是不良的软件工程实践/习惯.
您可能会受益于保留唯一的OrderTicket()
值先搜索db.POOL
,然后先搜索SELECT_BY_TICKET
,这对于db.POOL
的两个{ MODE_TRADES | MODE_HISTORY }
部分中的所有order_state/order_relative_position变化都是可靠的.
A big portion of processing is duplicated, which may work, but is hard to maintain in a longer run and is considered a poor software engineering practice/habit.
You may benefit from rather retaining a unique OrderTicket()
value once searching the db.POOL
and then straight SELECT_BY_TICKET
, which is robust against all order_state / order_relative_position changes in both of the { MODE_TRADES | MODE_HISTORY }
parts of the db.POOL
.
接下来是拟议的MQL4代码的最大敌人:
Next is the worse enemy for the proposed MQL4 code:
如果可以相信这一点,请不要阻止代码流. MQL4代码执行环境是基于事件的,由外部事件源(Market)触发,并且调用Sleep( 60000 )
比在EuroTunnel出口处睡一觉更糟糕.哎呀!
If one may believe this, never block the flow of the code. MQL4 code-execution environment is event-based, triggered by the external source of events ( The Market ) and calling Sleep( 60000 )
is worse than taking a sleep on the rails, right in the exit from the EuroTunnel. OUCH!!
您的代码被迫不能做出反应,更糟糕的是,不能让MQL4代码生态系统的其他部分与市场事件的流程保持同步.相信我,肯定有比Sleep()
更好的方法,如何几乎无所作为".
Your code is envictimed not to be able to react, and worse, not to be able to let other parts of the MQL4 code eco-system breathe in sync with the flow of The Market Events. There are sure better ways, how to do "almost nothing", than Sleep()
, believe me.
效率提示:
避免代码重复,而应使用特定于Digits
的格式,无论是通过设置为实际小数位数的变量还是通过StringFormat()
模式.
Avoid code-duplicates and rather use Digits
-specific formatting, be it via a variable set to actual number of decimal places, or via StringFormat()
patterns.
可能会有一些不同的代码布局,这将帮助您避免语法错误,括号等.
May enjoy a bit different layout of code, that will help you avoid syntax errors, missed parentheses et al.
首选使用全局唯一的,类似于直接指针的OrderTicket()
数字(如在OrderClose()
中求值的那样),并预先存储其值,因为您希望稍后在代码中重用它,但不要使用它随时可以从OrderClose()
时刻获得.
Prefer to use globally unique, direct-pointer-alike OrderTicket()
numbers, as evaluated in OrderClose()
and rather pre-store it's value, as you wish to re-use it later in the code, but not having it readily available from the OrderClose()
-moment.
可以享受另一个用于MQL4代码工作的IDE,其中折叠和列块变得非常方便(Geany,SciTe,JEdit,Notepad ++).
在这里,您很快就会从物理上看到if(){}else if(){}
代码块的效率低下,在else
部分重复了自然的相互{True|False}
-二分法.
May enjoy another IDE for MQL4 code-effort, where collapsing and columnar blocks become very handy ( Geany, SciTe, JEdit, Notepad++ ).
Here, you soon physically view the inefficiency in if(){}else if(){}
code-blocks, where the natural mutual {True|False}
-dichotomy was duplicated in the else
part.
无论如何,请享受MQL4的狂野世界
Anyway, enjoy the wild worlds of MQL4
//Order Close//
string sym = Symbol();
int ordersTotal = OrdersTotal();
for ( int PosSel = ordersTotal - 1; // loopVar .SET
PosSel >= 0; // loopVar .PRE-condition
PosSel-- // loopVar .DEC at loop-end
)
{
if ( OrderSelect( PosSel, SELECT_BY_POS, MODE_TRADES ) )
if ( OrderTicket() > 0 )
if ( OrderMagicNumber() == Period() )
if ( OrderSymbol() == Symbol() )
if ( OrderOpenTime() <= TimeCurrent() - ( 60 * Period() ) )
{
ClosePosition = OrderClose( OrderTicket(),
8,
MarketInfo( sym, MODE_BID )
+ MarketInfo( sym, MODE_SPREAD )
* MarketInfo( sym, MODE_POINT ),
300,
clrNONE
);
if ( ClosePosition == true )
{ // ===================||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||====================
Sleep( 60000 ); //|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| BLOCKS EA-EXECUTION
// ===================||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||====================
int PosSelHist = OrdersHistoryTotal() - 1;
bool reshist = OrderSelect( PosSelHist, SELECT_BY_POS, MODE_HISTORY );
if ( reshist == true
&& Digits == 5
)
{
double ClosingPrice = OrderClosePrice();
double OpeningPrice = OrderOpenPrice();
double Profit = OrderProfit();
int Ticket = OrderTicket();
SendMail( "Trade Notification Email (TNE)",
"Order# " + DoubleToStr( Ticket, 0 )
+ " has been closed on the account " + AccountName()
+ "\n"
+ "\nThe order exit price for this trade is " + DoubleToStr( ClosingPrice, 5 )
+ "with a profit/loss of" + DoubleToStr( Profit, 2 )
+ "\n"
+ "\nThe spread charge for this position is £" + DoubleToStr( ( spread
* tickvalue
)
* LotSize, 2 )
+ "\n"
+ "\n-----------------------------------------------------------------------"
+ "\n"
+ SendNotification( "Ticket # "
+ IntegerToString( Ticket, 10 )
+ "has closed with a profit/loss of "
+ DoubleToStr( Profit, 2 )
)
);
}
else if ( reshist == true
&& Digits == 3
)
{
double ClosingPrice = OrderClosePrice();
double OpeningPrice = OrderOpenPrice();
double Profit = OrderProfit();
int Ticket = OrderTicket();
SendMail( "Trade Notification Email (TNE)",
"Order# " + DoubleToStr( Ticket, 0 )
+ " has been placed on the account " + AccountName()
+ "\n"
+ "\nThe order entry price for this trade is " + DoubleToStr( ClosingPrice, 3 )
+ "with a profit/loss of" + DoubleToStr( Profit, 2 )
+ "\n"
+ "\nThe spread charge for this position is £" + DoubleToStr( ( spread
* tickvalue
)
* LotSize, 2 )
+ "\n"
+ "\n-----------------------------------------------------------------------"
+ SendNotification( "Ticket # "
+ IntegerToString( Ticket, 10 )
+ " has closed with a profit/loss of "
+ DoubleToStr( Profit, 2 )
)
);
}
}
else if ( ClosePosition == false )
{
int failedClosePosition = OrdersTotal() - 1;
bool fail = OrderSelect( failedClosePosition, SELECT_BY_POS, MODE_HISTORY );
if ( fail == true )
{
SendNotification( "Order Number #"
+ IntegerToString( OrderTicket(), 10 )
+ " has failed to close. Please refer to error code "
+ IntegerToString( GetLastError() )
);
}
}
}
}
这篇关于EA交易无法关闭交易头寸时发送电子邮件通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!