Золотое правило трейдера

Genkov | 6 марта, 2012


Введение

Основная задача трейдера - не только найти правильную точку входа в рынок, но и немаловажную роль играет выбор момента выхода из рынка. Золотое правило трейдера гласит: "Основное правило успешной торговли (или, как его называют, золотое правило трейдинга) - фиксировать убытки на низком уровне, и позволять прибыли расти".

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

  1. Знай свой риск, когда входишь в рынок (это первоначальное значение Stop Loss);
  2. Делай свою прибыль кратной первоначальному риску, давая расти прибыли (не закрывай позицию раньше, чем предусматривает система);
  3. Знай мат. ожидание своей системы – периодически тестируй и вноси коррективы.

Поэтапный метод отслеживания позиций, позволяющий прибыли расти

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

Выбор момента входа в рынок можно определять многими условиями, например по моделям японских свечей, по волновым моделям и т.д. В тоже время следует учитывать профит фактор (отношение величин выигрыша к проигрышу).

Основа этого метода заключается в том, что при открытии позиции трейдер выбирает минимально возможную величину Stop Loss. Метод выбора этой величины может быть, например 1,5% от депозита или любой другой. Когда рынок достигает профита равного величине Stop Loss, закрывается половина лота, но Stop Loss не переносится!

Таким образом, происходит некоторая подстраховка на случай, если рынок развернется в другую сторону. Т.е. уменьшаем риск, фиксируя минимальные убытки. Если после открытия позиции рынок пошел в направлении открытия позиции, а потом развернулся в противоположном направлении, то сработает установленный Stop Loss (рис. 1-3).

Рис. 1. Открываем позицию

Рис. 2. Ставим Stop Loss

если рынок развернулся:

Рис. 3. Если рынок развернулся – вы в безубытке

Программный код отслеживания позиции

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

Если рынок продолжает движение в направлении открытия позиции, и достигает заранее определенного значения, например 100 pip, - производим перенос Stop Loss в "безубыток". Дальнейшие переносы производим при достижении профита через заранее определенные промежутки, например через 50 pip. Можно переносить Stop Loss на каждом следующем баре, но частые переносы не нравятся брокерам, особенно, если торговля ведется на младших таймфреймах. По этому поводу в папке библиотек (libraries) в файле ошибок (stdlib.mq4) есть ошибка № 8 error="too frequent requests" (слишком частые запросы).

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

Вычисления уровней Фибоначчи производится функцией построения уровней LevelFibo():

//+------------------------------------------------------------------+
   void LevelFibo()
   {
   double Fb1,Fb2,Fb3,Fb4,Fb5,Fb6,Fb7,Fb8,Fb9,Fb10,Fb11,Fb12,Fb13;
   // канал "Vegas"
   double Ma144_1 = iMA(NULL,0,144,0,MODE_EMA,PRICE_CLOSE,1);
   double Ma169_1 = iMA(NULL,0,169,0,MODE_EMA,PRICE_CLOSE,1);
   // медиана канала "Vegas"
   double MedVegas=NormalizeDouble((Ma144_1+Ma169_1)/2,Digits); 
   // вычислим значения уровней Fibo по методике "Vegas"
   Fb1=MedVegas-377*Point;     Fb12=MedVegas+377*Point;
   Fb2=MedVegas-233*Point;     Fb11=MedVegas+233*Point;
   Fb3=MedVegas-144*Point;     Fb10=MedVegas+144*Point;
   Fb4=MedVegas-89*Point;      Fb9=MedVegas+89*Point;
   Fb5=MedVegas-55*Point;      Fb8=MedVegas+55*Point;
   Fb6=MedVegas-34*Point;      Fb7=MedVegas+34*Point;
   }
//+------------------------------------------------------------------+

При расчете Stop Loss для позиций BUY за профит принимается разность между Max ценой первого бара High[1] и уровнем открытия позиции OrderOpenPrice(). Уровень Stop Loss определяется как "ближайший" уровень Фибоначчи относительно Min значения первого бара Low[1] (рис. 4).

Рис. 4. Расчет Stop Loss для позиции BUY

При расчете Stop Loss для позиций SELL за профит принимается разность между уровнем открытия позиции OrderOpenPrice() и уровнем Max ценой первого бара High[1] (рис 5).

Рис. 5. Расчет Stop Loss для позиции SELL

Для позиций Buy, значения уровней StopLoss ориентированы на уровни Fibo, в зависимости от минимального значения первой свечи, представлена отдельной функцией.

Код функции приведен ниже:

//+---------------------------------------------------------------------+
//| Функция (таблица) определения значений Stop Loss для позиции BUY    |
//| по уровням Fibo в зависимости от минимального значения первой свечи |
//+---------------------------------------------------------------------+
 void StopLevelFiboBuy()
   {
   if(Low[1]>Fb12)                                newSL_B=Fb12-100*Point;
   if(Low[1]<=Fb12 && Low[1]>(Fb12+Fb11)/2)       newSL_B=(Fb12+Fb11)/2;
   if(Low[1]<=(Fb12+Fb11)/2 && Low[1]>Fb11)       newSL_B=Fb11;
   if(Low[1]<=Fb11 && Low[1]>(Fb11+Fb10)/2)       newSL_B=(Fb11+Fb10)/2;
   if(Low[1]<=(Fb10+Fb11)/2 && Low[1]>Fb10)       newSL_B=Fb10;
   if(Low[1]<=Fb10 && Low[1]>(Fb10+Fb9)/2)        newSL_B=Fb9;
   if(Low[1]<=(Fb10+Fb9)/2 && Low[1]>Fb9)         newSL_B=Fb8;
   if(Low[1]<=Fb9  && Low[1]>Fb8)                 newSL_B=Fb7;
   if(Low[1]<=Fb8  && Low[1]>Fb7)                 newSL_B=(Fb7+MedVegas)/2;
   if(Low[1]<=Fb7  && Low[1]>MedVegas)            newSL_B=Fb6;
   if(Low[1]<=MedVegas && Low[1]>(MedVegas+Fb6)/2)newSL_B=Fb6;
   if(Low[1]<=(MedVegas+Fb6)/2 && Low[1]>Fb6)     newSL_B=Fb5;
   if(Low[1]<=Fb6  && Low[1]>Fb5)                 newSL_B=Fb4;
   if(Low[1]<=Fb5  && Low[1]>Fb4)                 newSL_B=(Fb3+Fb4)/2;
   if(Low[1]<=Fb4  && Low[1]>Fb3)                 newSL_B=Fb3;
   if(Low[1]<=Fb3  && Low[1]>(Fb3+Fb2)/2)         newSL_B=(Fb3+Fb2)/2;
   if(Low[1]<=(Fb3+Fb2)/2  && Low[1]>Fb2)         newSL_B=Fb2;
   if(Low[1]<=Fb2  && Low[1]>(Fb2+Fb1)/2)         newSL_B=(Fb1+Fb2)/2;
   if(Low[1]<=(Fb2+Fb1)/2 && Low[1]>Fb1)          newSL_B=Fb1;
   if(Low[1]<=Fb1)                                newSL_B=Fb1-100*Point;
   }
//+------------------------------------------------------------------+

Таблица значений уровней Stop Loss по уровням Fibo в зависимости от максимальных значения первой свечи функцией StopLevelFiboSell() для позиций Sell представлена следующим кодом:

//+----------------------------------------------------------------------+
//| Функция (таблица) определения значений StopLoss для позиции SELL     |
//| по уровням Fibo в зависимости от максимального значения первой свечи |
//+----------------------------------------------------------------------+
 void StopLevelFiboSell()
   {
   if(High[1]<=Fb12 && High[1]>(Fb12+Fb11)/2)        newSL_S=Fb12+100*Point;
   if(High[1]<=Fb12 && High[1]>Fb11)                 newSL_S=Fb12;
   if(High[1]<=Fb11 && High[1]>Fb11+Fb10)            newSL_S=Fb11;
   if(High[1]<=Fb10 && High[1]>(Fb10+Fb9)/2)         newSL_S=(Fb11+Fb10)/2;
   if(High[1]<=Fb9  && High[1]>Fb8)                  newSL_S=(Fb10+Fb9)/2;
   if(High[1]<=Fb8  && High[1]>Fb7)                  newSL_S=Fb9;
   if(High[1]<=Fb7  && High[1]>MedVegas)             newSL_S=Fb8;
   if(High[1]<=MedVegas && High[1]>MedVegas)         newSL_S=Fb7;
   if(High[1]<=(MedVegas+Fb6)/2 && High[1]>Fb6)      newSL_S=MedVegas;
   if(High[1]<=Fb6  && High[1]>Fb5)                  newSL_S=MedVegas;
   if(High[1]<=Fb5  && High[1]>Fb4)                  newSL_S=Fb6;
   if(High[1]<=Fb4  && High[1]>Fb3)                  newSL_S=Fb5;
   if(High[1]<=Fb3  && High[1]>Fb2)                  newSL_S=Fb4;
   if(High[1]<=Fb2  && High[1]>(Fb2+Fb1)/2)          newSL_S=(Fb2+Fb3)/2;
   if(High[1]<(Fb2+Fb1)/2   && High[1]>Fb1)          newSL_S=Fb2;
   if(High[1]<Fb1)                                   newSL_S=(Fb2+Fb1)/2;
   }
//+------------------------------------------------------------------+

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

По поводу совмещения двух функций, точнее включения функции вычисления уровней LevelFibo() в функции определения уровней Stop Loss, ориентированных на эти уровни. Это объединение имеет смысл т.к. они работают совместно. Поэтому сократится количество вызовов функций при отслеживании - вместо двух вызовов будет только один.

После объединения они будут иметь вид:

//+----------------------------------------------------------------------+
//| Функция (таблица) определения значений Stop Loss для позиции BUY     |
//| по уровням Fibo в зависимости от минимального значения первой свечи  |
//+----------------------------------------------------------------------+
   void StoplevelFiboBuy()
   {
   double Fb1,Fb2,Fb3,Fb4,Fb5,Fb6,Fb7,Fb8,Fb9,Fb10,Fb11,Fb12,Fb13;
   double Ma144_1 = iMA(NULL,0,144,0,MODE_EMA,PRICE_CLOSE,1);
   double Ma169_1 = iMA(NULL,0,169,0,MODE_EMA,PRICE_CLOSE,1);
   double MedVegas=NormalizeDouble((Ma144_1+Ma169_1)/2,Digits); 
   Fb1=MedVegas-377*Point;     Fb12=MedVegas+377*Point;
   Fb2=MedVegas-233*Point;     Fb11=MedVegas+233*Point;
   Fb3=MedVegas-144*Point;     Fb10=MedVegas+144*Point;
   Fb4=MedVegas-89*Point;      Fb9=MedVegas+89*Point;
   Fb5=MedVegas-55*Point;      Fb8=MedVegas+55*Point;
   Fb6=MedVegas-34*Point;      Fb7=MedVegas+34*Point;
   if(Low[1]>Fb12)                                newSL_B=Fb12-100*Point;
   if(Low[1]<=Fb12 && Low[1]>(Fb12+Fb11)/2)       newSL_B=(Fb12+Fb11)/2;
   if(Low[1]<=(Fb12+Fb11)/2 && Low[1]>Fb11)       newSL_B=Fb11;
   if(Low[1]<=Fb11 && Low[1]>(Fb11+Fb10)/2)       newSL_B=(Fb11+Fb10)/2;
   if(Low[1]<=(Fb10+Fb11)/2 && Low[1]>Fb10)       newSL_B=Fb10;
   if(Low[1]<=Fb10 && Low[1]>(Fb10+Fb9)/2)        newSL_B=Fb9;
   if(Low[1]<=(Fb10+Fb9)/2 && Low[1]>Fb9)         newSL_B=Fb8;
   if(Low[1]<=Fb9  && Low[1]>Fb8)                 newSL_B=Fb7;
   if(Low[1]<=Fb8  && Low[1]>Fb7)                 newSL_B=(Fb7+MedVegas)/2;
   if(Low[1]<=Fb7  && Low[1]>MedVegas)            newSL_B=Fb6;
   if(Low[1]<=MedVegas && Low[1]>(MedVegas+Fb6)/2)newSL_B=Fb6;
   if(Low[1]<=(MedVegas+Fb6)/2 && Low[1]>Fb6)     newSL_B=Fb5;
   if(Low[1]<=Fb6  && Low[1]>Fb5)                 newSL_B=Fb4;
   if(Low[1]<=Fb5  && Low[1]>Fb4)                 newSL_B=(Fb3+Fb4)/2;
   if(Low[1]<=Fb4  && Low[1]>Fb3)                 newSL_B=Fb3;
   if(Low[1]<=Fb3  && Low[1]>(Fb3+Fb2)/2)         newSL_B=(Fb3+Fb2)/2;
   if(Low[1]<=(Fb3+Fb2)/2  && Low[1]>Fb2)         newSL_B=Fb2;
   if(Low[1]<=Fb2  && Low[1]>(Fb2+Fb1)/2)         newSL_B=(Fb1+Fb2)/2;
   if(Low[1]<=(Fb2+Fb1)/2 && Low[1]>Fb1)          newSL_B=Fb1;
   if(Low[1]<=Fb1)                                newSL_B=Fb1-100*Point;
   }
// ----------------------------------------------------------------------+

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

Ниже приведен небольшой фрагмент кода отслеживания:

//+------------------------------------------------------------------+
//| ОТСЛЕЖИВАНИЕ ОТКРЫТЫХ ПОЗИЦИЙ                                    |
//+------------------------------------------------------------------+
for(int i=OrdersTotal()-1; i>=0; i--)
  {
   if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
     {Print("Ошибка выбора ордера = ",GetLastError());}
   if(OrderSymbol()==Symbol())
     {
      if(OrderType()==OP_BUY)
        {
         if(OrderMagicNumber()==Magic)
           {
            // ----------------------------------------------------------------------+
            if((High[1]-OrderOpenPrice())>=SL_B*Point && OrderLots()==0.2)Close_B_lot();
            // ----------------------------------------------------------------------+
            if((High[1]-OrderOpenPrice())/Point>=100 && OrderLots()==0.1 && OrderStopLoss()<OrderOpenPrice())
              {
               Print(" 1 - перенос StopLoss");
               if(!OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+2*Point,OrderTakeProfit(),0,Aqua))
                 {
                  Print(" при Модиф.орд.# ",OrderTicket()," Ошибка # ",GetLastError());
                 }
               return;
              }
            // ----------------------------------------------------------------------+
            if((High[1]-OrderOpenPrice())>=120*Point && OrderOpenPrice()>Ma144_1-144*Point)
              {
               StoplevelFiboBuy();
               newSL_B=newSL_B+21*Point;
               if((Bid-newSL_B)/Point<StopLevel)newSL_B=Bid-StopLevel*Point;
               if(newSL_B>OrderStopLoss() && (Bid-newSL_B)/Point>StopLevel)
                 {
                  Print("2-ой перенос StopLoss ");
                  Modyf_B_lot();
                 }
              }
            // ----------------------------------------------------------------------+
            if((High[1]-OrderOpenPrice())>=200*Point && (High[1]-OrderOpenPrice())<=250*Point)
              {
               StoplevelFiboBuy();
               if((Bid-newSL_B)/Point<StopLevel)newSL_B=Bid-StopLevel*Point;
               if(newSL_B>OrderStopLoss() && (Bid-newSL_B)/Point>StopLevel)
                 {
                  Print(" 3-ий перенос на уровень ордер # ",OrderTicket());
                  Modyf_B_lot();
                 }
              }
            // ----------------------------------------------------------------------+
            if((High[1]-OrderOpenPrice())>=250*Point && OrderOpenPrice()>Ma144_1-144*Point)
              {
               StoplevelFiboBuy();
               newSL_B=newSL_B+10*Point;
               if((Bid-newSL_B)/Point<StopLevel) newSL_B=Bid-StopLevel*Point;
               if(newSL_B>OrderStopLoss() && (Bid-newSL_B)/Point>StopLevel)
                 {
                  Print(" 4 перенос на новый уровень ордер # ",OrderTicket());
                  Modyf_B_lot();
                 }
              }
            // ----------------------------------------------------------------------+
            if((High[1]-OrderOpenPrice())>=300*Point && (High[1]-OrderOpenPrice())<=350*Point)
              {
               StoplevelFiboBuy();
               newSL_B=newSL_B+20*Point;
               if((Bid-newSL_B)/Point<StopLevel) newSL_B=Bid-StopLevel*Point;
               if(newSL_B>OrderStopLoss() && (Bid-newSL_B)/Point>StopLevel)
                 {
                  Print(" 5-й перенос на уровень ордер # ",OrderTicket());
                  Modyf_B_lot();
                 }
              }
            // ----------------------------------------------------------------------+
            ...
           }
        }
     }
  }

В прикрепленном варианте демонстрационного советника последовательность поэтапного отслеживания состоит из 8 этапов.

Ниже скриншот отражающий этапы работы Демо советника по отслеживанию позиции Buy. Позиция открыта в связи с возникшим сигналом о том, что сформировалась свечная модель "поглощение трех свечей", кроме того в числе поглощенных свечей есть свеча "перевернутый молот", что усиливает значение сигнала на открытие позиции на покупку.

Рис. 6. Пример сопровождения Buy позиции

Чтобы видеть линии Fibo, как на светлом скриншоте, надо использовать индикатор "Vegas". Его можно посмотреть на сайте MQL4: https://www.mql5.com/ru/code/7148

Тот же скриншот с "темного" экрана монитора и немного растянут:

Рис. 7. Скриншот с экрана монитора (демо версия для Buy)

Рис. 8. Пример сопровождения позиции Sell

Для просмотра на мониторе работу демонстрационных советников надо установить временные параметры тестирования, как показано на приведенных ниже рис. 9-10:

Рис. 9. Параметры тестирования советника Demo_traill_Buy.mql

Рис. 10. Параметры тестирования советника Demo_traill_Sell.mql

Примечание: К статье файлы прилагаются файлы демонстрационных советников, как мини-роботы по отслеживанию позиций при покупке и продаже. Здесь позиции открываются двойным лотом. Однако, когда Stop Loss перенесен на безубыток, возникает уверенность в дальнейшем движении цены в нужном направлении, и можно добавить еще позицию.


Заключение

Краткий вывод таков: приведенные здесь результаты по отслеживанию ордеров показывают, что метод передвижения ордеров Stop Loss, ориентированных на динамические уровни Fibo, дает положительные результаты. Описанный метод может быть рекомендован для практического применения в трейдинге.

Функции определения динамических уровней Fibo: