EA: eaBreakeven

 

eaBreakeven:

这个 EA 交易可以根据用户定义的盈亏平衡点来移动止损的位置。

作者: Alexey Lopatin

 

错误:

  1. 循环应颠倒。
  2. 应从代码中删除PositionSelect

 
fxsaber:

错误:

  1. 循环应颠倒。
  2. 应从代码中删除 PositionSelect。


工作室的参数。

 
Alexey Lopatin:

请提出论据。

解释循环需要很长时间。在 PositionGetSymbol 之后,PositionSelect 就没有必要了,因为如果 LastError 是确定的,选择就已经完成了。在对冲账户中,PositionSelect 也是邪恶的。

最好的选择是始终使用它,而不是上面提到的那些。

if (PositionGetTicket(i))


此外,可以通过POSITION_PRICE_CURRENT 获取任何仓位方向的最新价格。


而这一条件

if(latest_price.bid-price_open>=Breakeven*point && new_stoploss>stoploss && latest_price.bid-new_stoploss>stop_level)

即使在不需要修改的情况下(由于双重特殊性)也可以触发。


总的来说,您可以将其重写得更紧凑一些,而且不会出错。我会采用 MT4 风格。

#include <MT4Orders.mqh>     //https://www.mql5.com/zh/code/16006
#include <Price_Compare.mqh> //https://www.mql5.com/zh/code/16169

input int    Breakeven           = 15;           //盈亏平衡点
input int    Distance            = 5;            //从仓位开盘价算起的盈亏平衡点距离(点数
input int    MagicNumber         = 16112017;     //神奇数字
input bool   EnableSound         = true;         // 设置盈亏平衡时,启用/禁用播放声音
input string SoundFile           = "alert1.wav"; //声音文件名

void OnTick()
{
  DoBreakeven();
}

double GetNewStopLoss()
{
  const double point = SymbolInfoDouble(OrderSymbol(), SYMBOL_POINT);  
  const double stop_level = SymbolInfoInteger(OrderSymbol(), SYMBOL_TRADE_STOPS_LEVEL) * point;
  
  const double price_open = OrderOpenPrice();
  const double latest_price = OrderClosePrice();  
  const double stoploss = OrderStopLoss();

  double new_stoploss = 0;
  
  //-- 如果头寸利润大于盈亏平衡点,则将止损移至盈亏平衡点价格 + 距离 
  return(((OrderType() == OP_BUY)  && (CP(latest_price - price_open, point) >= Breakeven * point) &&
                                      (CP(new_stoploss = price_open + Distance * point, point) > stoploss) &&
                                      (CP(latest_price - new_stoploss, point) > stop_level)) ||
         ((OrderType() == OP_SELL) && (CP(price_open - latest_price, point) >= Breakeven * point) &&
                                      ((CP(new_stoploss = price_open - Distance * point, point) < stoploss) || !stoploss) &&
                                      (CP(new_stoploss - latest_price, point) > stop_level))
         ? NormalizeDouble(new_stoploss, (int)SymbolInfoInteger(OrderSymbol(), SYMBOL_DIGITS)) : 0);
}

void DoBreakeven()
{
//如果盈亏平衡为负值,则禁用盈亏平衡功能
  if (Breakeven >= 0)      
  //Loop for positions
    for (int i = OrdersTotal() - 1; i >= 0; i--)
      if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (!MagicNumber || (OrderMagicNumber() == MagicNumber)))
      {
        const double new_stoploss = GetNewStopLoss();
        
        if (new_stoploss)      
        {
          if (!OrderModify(OrderTicket(), OrderOpenPrice(), new_stoploss, OrderTakeProfit(), OrderExpiration()))
            Print(GetLastError());
          else if(EnableSound)
            PlaySound(SoundFile);
        }
      }
}
 

感谢您的回复和举例说明。我总是很高兴能学到新东西。

但在这里,我很想知道为什么PositionSelect 在对冲账户中是邪恶的?

 
Alexey Lopatin:

但在这里,我们很想知道为什么哈希计数上的 PositionSelect 是邪恶的?

因为符号并不能唯一定义位置。

 
caolyhuynh:
 
5000000
 
caolyhuynh: