Перенос в безубыток несколько позиций

 

Привет.

Есть функция переноса в безубыток BreakEvenPoint(). Открываю три позиции, при закрытии первой по тейку активируется эта функция. То есть осталось две позиции, но эта функция переносит в безубыток стоп только одной позиции, вторая остается со старым стопом. Вроде же все правильно написано, но работает не правильно. В чем ошибка. Буду признателен за подсказку.

void BreakEvenPoint()
{
   if(BreakEven == 0)
      return;
   for(int i=PositionsTotal()-1; i>=0; i--)  
      if(iPosition.SelectByIndex(i))      
         if(iPosition.Symbol() == iSymbol.Name() && iPosition.Magic() == MagicNumber)
         {
            if(PositionSelect(iSymbol.Name())==true) // есть открытая позиция
            {
               if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
               {
                  if(iSymbol.Bid() > (iPosition.PriceOpen() + iSprd * iSymbol.Point()))
                  {
                     double sl = NormalizeDouble(iPosition.PriceOpen() + iSprd, iSymbol.Digits());
                     double tp = iPosition.TakeProfit();
                     if(iPosition.StopLoss() < sl || iPosition.StopLoss()==0.0)
                     {
                        //--- modify position
                        if(iTrade.PositionModify(iSymbol.Name(), sl, tp))
                           printf("Long position by %s to be modified", iSymbol.Name());
                        else
                        {
                           printf("Error modifying position by %s : '%s'", iSymbol.Name(), iTrade.ResultComment());
                           printf("Modify parameters : SL=%f,TP=%f", sl, tp);
                        }
                        //--- modified and must exit from expert
                     }
                  }
               }
               if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
               {
                  if(iPosition.PriceOpen() > (iSymbol.Ask() - BreakEven * iSymbol.Point()))
                  {
                     double sl=NormalizeDouble(iPosition.PriceOpen() - iSprd, iSymbol.Digits());
                     double tp=iPosition.TakeProfit();
                     if(iPosition.StopLoss() > sl || iPosition.StopLoss()==0.0)
                     {
                        //--- modify position
                        if(iTrade.PositionModify(iSymbol.Name(),sl,tp))
                           printf("Short position by %s to be modified", iSymbol.Name());
                        else
                        {
                           printf("Error modifying position by %s : '%s'", iSymbol.Name(), iTrade.ResultComment());
                           printf("Modify parameters : SL=%f,TP=%f", sl, tp);
                        }
                        //--- modified and must exit from expert
                     }
                  }
               }
            }
         }    
}
 
Konstantin Ivanov:

Привет.

Есть функция переноса в безубыток BreakEvenPoint(). Открываю три позиции, при закрытии первой по тейку активируется эта функция. То есть осталось две позиции, но эта функция переносит в безубыток стоп только одной позиции, вторая остается со старым стопом. Вроде же все правильно написано, но работает не правильно. В чем ошибка. Буду признателен за подсказку.

Второй раз выделять позицию - это лишнее.

      if(iPosition.SelectByIndex(i))
         if(iPosition.Symbol() == iSymbol.Name() && iPosition.Magic() == MagicNumber)
           {
            if(PositionSelect(iSymbol.Name())==true) // есть открытая позиция
 

В букваре написано "Для гарантированного получения свежих данных о позиции рекомендуется вызывать функцию PositionSelect() непосредственно перед обращением за ними." Оставлю, хуже не будет.

В общем сам запутался в трех березах. Для счетов с хеджированием надо по пикетам перебирать. Правильный код ниже.

void BreakEvenPoint()
{
   if(BreakEven == 0)
      return;
   for(int i=PositionsTotal()-1; i>=0; i--)  // returns the number of current positions
      if(iPosition.SelectByIndex(i))         // selects the position by index for further access to its properties
         if(iPosition.Symbol() == iSymbol.Name() && iPosition.Magic() == MagicNumber)
         {
            if(PositionSelect(iSymbol.Name())==true) 
            {
               if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
               {
                  if(iSymbol.Bid() > (iPosition.PriceOpen() + BreakEven * iSymbol.Point()))
                  {
                     double sl = NormalizeDouble(iPosition.PriceOpen() + iSprd, iSymbol.Digits());
                     double tp = iPosition.TakeProfit();
                     ulong  iTicket = PositionGetTicket(i);
                     if(iPosition.StopLoss() < sl || iPosition.StopLoss()==0.0)
                     {
                        //--- modify position
                        if(iTrade.PositionModify(iTicket, sl, tp))
                           printf("Long position by %s to be modified", iSymbol.Name());
                        else
                        {
                           printf("Error modifying position by %s : '%s'", iSymbol.Name(), iTrade.ResultComment());
                           printf("Modify parameters : SL=%f,TP=%f", sl, tp);
                        }
                        //--- modified and must exit from expert
                     }
                  }
               }
               if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
               {
                  if(iPosition.PriceOpen() > (iSymbol.Ask() - BreakEven * iSymbol.Point()))
                  {
                     double sl=NormalizeDouble(iPosition.PriceOpen() - iSprd, iSymbol.Digits());
                     double tp=iPosition.TakeProfit();
                     ulong  iTicket = PositionGetTicket(i);
                     if(iPosition.StopLoss() > sl || iPosition.StopLoss()==0.0)
                     {
                        //--- modify position
                        if(iTrade.PositionModify(iTicket,sl,tp))
                           printf("Short position by %s to be modified", iSymbol.Name());
                        else
                        {
                           printf("Error modifying position by %s : '%s'", iSymbol.Name(), iTrade.ResultComment());
                           printf("Modify parameters : SL=%f,TP=%f", sl, tp);
                        }
                        //--- modified and must exit from expert
                     }
                  }
               }
            }
         }    
}
Документация по MQL5: Торговые функции / PositionSelect
Документация по MQL5: Торговые функции / PositionSelect
  • www.mql5.com
Выбирает открытую позицию для дальнейшей работы с ней. Возвращает true при успешном завершении функции. Возвращает false при неудачном завершении функции. Чтобы получить информацию об ошибке, необходимо вызвать функцию GetLastError(). При независимом представлении позиций (ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) по каждому символу одновременно...
 
Konstantin Ivanov:

В букваре написано "Для гарантированного получения свежих данных о позиции рекомендуется вызывать функцию PositionSelect() непосредственно перед обращением за ними." Оставлю, хуже не будет.

В общем сам запутался в трех березах. Для счетов с хеджированием надо по пикетам перебирать. Правильный код ниже.

Вы выбираете позицию в

      if(iPosition.SelectByIndex(i))         // selects the position by index for further access to its properties

этого достаточно. 

Уберите повторный выбор - он ошибочный по сути применения.

 
Понял. Спасибо.