Прошу помочь с безубытком и ошибками

 

Доброго времени суток. Написал советника, хотел сделать для него "умный трейлинг", но что-то пошло не так, в сделках на покупку вроде как работает корректно (но это не точно),  а на продажу не выполняет вообще ничего. Суть советника в том, что по сигналу открывает два ордера:

1. Уникальный номер MAGIC: по дефолту установлен стоплосс. Надо чтобы при достижении прибыли в 200 пунктов, позиция переходила в безубыток на уровне цены открытия + 100 пунктов, до тех пор, пока линия канала дончиана (если бай - то нижняя линия, если селл - верхняя) не пересечет положение безубытка. После этого стоплосс должен двигаться вместе с линией дончиана.

2. Уникальный номер MAGIC1:  по дефолту установлен стоплосс и тейкпрофит.  Надо чтобы при достижении прибыли в 200 пунктов, позиция переходила в безубыток на уровне цены открытия +100пунктов.

Если установить трейлинг исключительно по дончиану, то все работает, но вот сначала перевести в безубыток, а потом следовать по каналу у меня не получилось. Можете объяснить, что я сделал не так? 

P.S.  Теперь в тестере выдаёт ошибку:

2020.11.22 06:37:09.503 EURUSD,H1: unknown ticket *** for OrderModify function

2020.11.22 06:37:09.503 EURUSD,H1: OrderModify error 4108

Параметры стопа

// Уровень стопа для длинной позиции.
double long_stoploss() {
  return(NormalizeDouble(
    iCustom(NULL, 0, DON_NAME, EXIT_CHANNEL, DON_LOWER, 1), Digits));
}

// Уровень стопа для короткой позици.
double short_stoploss() {
  return(NormalizeDouble((Ask - Bid) +
    iCustom(NULL, 0, DON_NAME, EXIT_CHANNEL, DON_UPPER, 1), Digits));
    }


Трейлинг

void Trailing ()
{
  int i=0;
  for(i=0; i<OrdersTotal(); i++)
  OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
  if (OrderType()==OP_BUY)
  {
    double CurrentPoint = (Bid-OrderOpenPrice())/(_Point);
    double CurrentPointDon = long_stoploss();
    if (OrderMagicNumber()==MAGIC)
    {
      if (CurrentPoint>=200 && (OrderOpenPrice()+200*Point>CurrentPointDon))
      {
        OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()+100*Point, OrderTakeProfit(), 0, CLR_NONE);
      }
      if (CurrentPoint>=200 && (OrderOpenPrice()+200*Point<CurrentPointDon))
      {
        OrderModify(OrderTicket(), OrderOpenPrice(), CurrentPointDon, OrderTakeProfit(), 0, CLR_NONE);
      }
    }
    if (OrderMagicNumber()==MAGIC1)
    {
      if (CurrentPoint>=200)
      {
        OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()+100*Point, OrderTakeProfit(), 0, CLR_NONE);
      }
    }
  }

  if (OrderType()==OP_SELL)
  {
    double CurrentPoint1 = (OrderOpenPrice()-Ask)/(_Point);
    double CurrentPointDon1 = short_stoploss();
    if (OrderMagicNumber()==MAGIC)
    {
      if (CurrentPoint1>=200 && (OrderOpenPrice()-100*Point)<CurrentPointDon1)
      {
        OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()-100*Point, OrderTakeProfit(), 0, CLR_NONE);
      }
      if (CurrentPoint1>=200 && (OrderOpenPrice()-100*Point)>CurrentPointDon1)
      {
        OrderModify(OrderTicket(), OrderOpenPrice(), CurrentPointDon1, OrderTakeProfit(), 0, CLR_NONE);
      }
      if (OrderMagicNumber()==MAGIC1)
      {
        if (CurrentPoint1>=200)
        {
          OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()-100*Point, OrderTakeProfit(), 0, CLR_NONE);
        }

      }
    }
  
  }
} 

Как самому создать советника или индикатор - Алгоритмический трейдинг, торговые роботы - Справка по MetaTrader 5
Как самому создать советника или индикатор - Алгоритмический трейдинг, торговые роботы - Справка по MetaTrader 5
  • www.metatrader5.com
Для разработки торговых систем в платформу встроен собственный язык программирования MetaQuotes Language 5 (MQL5), среда разработки MetaEditor и инструменты тестирования стратегий. Любую информацию о разработке торговых стратегий на языке MQL5 можно найти на официальном сайте MQL5.community. На этом же сайте в разделе Code Base могут быть...
 
почему не используете готовую функцию ?
 
Iurii Tokman:
почему не используете готовую функцию ?
Не нашёл подобных готовых версий, а как правильно сравнивать с показаниями индикатора не знаю.
 

Вот самый лучший вариант трейлинг-стопа из всех протестированных мной. Когда амплитуда цены начинает уменьшаться после сильного движения, стоп начинает подтягиваться ближе.

//трейлинг рыночных ордеров, стоплосс держится на расстоянии Distance от самой экстремальной тени из последних History баров 
int DoTrailOrder(int ePosition, int eMagicNumber, double eDistance, int eHistory, string eSymbol, int eTimeFrame)
   {
   if(!OrderSelect(ePosition,SELECT_BY_POS,MODE_TRADES)) return(1);
   int eType=OrderType();
   if(eType!=OP_BUY && eType!=OP_SELL) return(0);
   if(OrderMagicNumber()!=eMagicNumber) return(0);
   if(OrderSymbol()!=eSymbol) return(0);
   //наблюдаем начиная с бара следующим за баром открытия
   if(iBarShift(eSymbol,eTimeFrame,OrderOpenTime())==0) return(0);
   int eDigits=(int)MarketInfo(eSymbol,MODE_DIGITS);
   double ePoint=MarketInfo(eSymbol,MODE_POINT);
   double eSpread=MarketInfo(eSymbol,MODE_SPREAD);
   double eExtremum;
   if(eType==OP_BUY)
      {
      //стоп устанавливается на расстоянии eDistance от самой низкой тени бара из истории eHistory
      eExtremum=iLow(eSymbol,eTimeFrame,iLowest(eSymbol,eTimeFrame,MODE_LOW,eHistory,1));
      //расстояние от минимума до StopLoss должно превысить TrailingLevel
      if(NormalizeDouble(eExtremum-OrderStopLoss(),eDigits)<=eDistance*ePoint) return(0);
      //расстояние от минимума до цены открытия должно превысить TrailingLevel
      if(NormalizeDouble(eExtremum-OrderOpenPrice(),eDigits)<=eDistance*ePoint) return(0);
      //новый стоп должен быть не ближе к текущей цене, чем на два спреда
      if(NormalizeDouble(MarketInfo(eSymbol,MODE_BID)+eDistance*ePoint-eExtremum,eDigits)<=2*eSpread*ePoint) return(0);
      if(!OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(eExtremum-eDistance*ePoint,eDigits),OrderTakeProfit(),OrderExpiration(),clrBlue)) return(-1);
      }
   if(eType==OP_SELL)
      {
      //стоп устанавливается на расстоянии eDistance от самой высокой тени бара из истории eHistory
      eExtremum=iHigh(eSymbol,eTimeFrame,iHighest(eSymbol,eTimeFrame,MODE_HIGH,eHistory,1));
      if(NormalizeDouble(OrderStopLoss()-eExtremum,eDigits)<=(eDistance+eSpread)*ePoint && OrderStopLoss()!=0) return(0);
      if(NormalizeDouble(OrderOpenPrice()-eExtremum,eDigits)<=(eDistance+eSpread)*ePoint) return(0);
      //один спред между Ask и Bid сократился
      if(NormalizeDouble(eExtremum+eDistance*ePoint-MarketInfo(eSymbol,MODE_ASK),eDigits)<=eSpread*ePoint) return(0);
      if(!OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(eExtremum+(eDistance+eSpread)*ePoint,eDigits),OrderTakeProfit(),OrderExpiration(),clrRed)) return(-1);
      }
   return(0);
   }
 
LoG1TeCh:
Не нашёл подобных готовых версий, а как правильно сравнивать с показаниями индикатора не знаю.

вот здесь есть примеры - https://www.mql5.com/ru/forum/131859/page8#434275

Только "Полезные функции от KimIV".
Только "Полезные функции от KimIV".
  • 2011.02.18
  • www.mql5.com
Все функции взяты из этой ветки - http://forum.mql4...
 
Iurii Tokman:

вот здесь есть примеры - https://www.mql5.com/ru/forum/131859/page8#434275

Да, среди этих примеров наиболее подходящая функция - MovingInWL(). Но основную сложность вызывает именно сравнение с уровнями канала дончиана после уже проведенного безубытка. Как такое условие правильно описать?


Правильно ли будет выполнить подобное условие?

// Уровень стопа для длинной позиции.
double long_stoploss() {
  return(NormalizeDouble(
    iCustom(NULL, 0, DON_NAME, EXIT_CHANNEL, DON_LOWER, 1), Digits));
double CurrentPointDon = long_stoploss();

.............................

if (pp-OrderOpenPrice()>LevelProfit*po) {
            ModifyOrder(-1, OrderOpenPrice()+LevelWLoss*po, -1);
          }
if (OrderOpenPrice()+LevelWLoss*po<CurrentPointDon)
{
ModifyOrder(-1, CurrentPointDon, -1);
}

Мне кажется что в таком случае они будут конфликтовать между собой, т.к. если цена будет выше предполагаемого безубытка, а тот в свою очередь ниже канала, то будет соблюдаться сразу два условия..

Возможно все будет правильно, если сделать вот так:
if (pp-OrderOpenPrice()>LevelProfit*po) 
{
        if (OrderOpenPrice()+LevelWLoss*po<CurrentPointDon)
        {
                ModifyOrder(-1, CurrentPointDon, -1);
        } else {
ModifyOrder(-1, OrderOpenPrice()+LevelWLoss*po, -1);}
}
Верно ли такое условие?
 
LoG1TeCh:


в начале посмотрите что возвращает вызов индикатора ?
какие там значения? соответствует верх канала, низ канала ?

Причина обращения: