Необычный трал стоп-лосса по заданному графику

 

Давно уже использую.

Трал включается после прохождения ценой в плюсовую сторону около 10 старых пунктов. Вначале стоп-лосс нарастает медленно, чтобы с большей вероятностью позиция "нагуляла жирок". Далее передвижка стоп-лосса идёт по заданному в двух массивах для X и Y графику. Хоть это и график в виде ломаной линии, тестирование показывает, что такой способ лучше, чем обычные алгоритмы. Можно придумать способ для оптимизации в тестере положения каждой точки ломаной линии поочерёдной подменой чисел в массиве из  изменяемой внешней переменной. Но для таких опытов нужен работоспособный прибыльный советник.

//размещать массивы возле глобалок
int Mass_Vpprof[9]= {-20,  0,10,20,30,40,60,80,500};//ломаный график в старых пунктах стоп-лосса от достигн. вершины пунктового профита
int Mass_SL[9]=     {-20,-19, 1, 4, 8,16,25,40,350}; //делается аппроксимация





//========================================================================================================//
//|          ----------------- SLT15__SL открытых позиций - трал через модификацию -------------------
//========================================================================================================//
void SLT15_Tral_SL_Tabl()//хорошо работает и на пятизнаке
  {
   double OOP=0,DRSL=0;
   int Mag=0,OT=0,PP=0,proekt_SL=0,im_SL=0;
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(OrderSelect(i,SELECT_BY_POS))
        {
         if(OrderSymbol()==Symbol())//либо все ордера с того графика, где стоит советник
           {
            Mag=OrderMagicNumber();
            ///////if(Mag!=222)
               ///////continue;//это когда надо брать в траление вручную (скриптом) поставленные
            PP=X17_Profit_v_Punktah(OrderTicket());
            if(PP>ppStart_SL) //трал СЛ начинается с некоторого плюсового значения (оно во внешних переменных, около 10)
              {
               proekt_SL=SLT16_Tangens_SL(PP);//подаётся пунктовый профит; на выходе имеющийся плюсовой пунктовый СЛ или 0
               //здесь в любом случае после постановки ставится стоп-лосс только для поставленных вручную
               if(proekt_SL==0)
                  continue;//при выдаче нуля обходим (стоп-лоссы ставятся только в плюсовой зоне)
               im_SL=SLT17_Im_ppSL();//имеющийся СЛ в старых пунктах
               if(proekt_SL>im_SL || im_SL==0)//и сравнение
                 {
                  OOP=OrderOpenPrice();//то модифи
                  OT=OrderType();
                  if(OT==0)
                     DRSL=ND(OOP+proekt_SL*Point*Faktor_ND);//в ините Faktor_ND надо определять, 10 при 5-знаке и 1 при 4-знаке
                  if(OT==1)
                     DRSL=ND(OOP-proekt_SL*Point*Faktor_ND);
                  while(!IsTradeAllowed())
                     Sleep(100);//пока сервер не будет готов
                  if(_IsTradeAllowed()==1)
                     OrderModify(OrderTicket(),ND(OOP),ND(DRSL),0,0,Red);//ставим СЛ
                  Z02_TradeIsNotBusy();
                 }
              }
           }
        }
     }//кц
   return;
  }
//=========================================================================================================//
//            ----------------- X17___ПОЛУЧЕНИЕ ПРОФИТА В ПУНКТАХ -------------------
//=========================================================================================================//
int X17_Profit_v_Punktah(int Tik)//ордер д.б. выделен, возвращается профит в пунктах
  {
   int mt;//ск. знаков в котировке
   double OL;
   if(MarketInfo(OrderSymbol(),MODE_DIGITS)==3 || MarketInfo(OrderSymbol(),MODE_DIGITS)==5)
      mt=10;
   else
      mt=1;
   int Profit_P=0;
   if(OrderSelect(Tik,SELECT_BY_TICKET))
     {
      OL=OrderLots();
      if(OL!=0)
        {
         Profit_P=(int)MathRound((OrderProfit()+OrderSwap())/MarketInfo(OrderSymbol(),MODE_TICKVALUE)/OL/mt);
        }
     }//своп тоже округлится в расчёте пунктов
   return (Profit_P);
  }
//=======================================================================================================//
//| ----- SLT16__вычисления стоп-лосса от пунктового профита по тангенсу - делается аппроксимация -----
//=======================================================================================================//
int SLT16_Tangens_SL(int Dei_PP_Prof)//исполняется график ломаной линии в двух массивах как трал
  {
//int Mass_Vpprof[8]= {0,10,20,30,40,60,80,500};//таблица зависимости пп стоп-лосса от достигн. вершины
//int Mass_SL[8]=     {0, 2, 8,15,20,38,55,400};//об"явление массивов в глобалках; делается аппроксимация
   int k=0;
   double zn_X=0,Katet_Pril=1,Katet_Prot=0,PP_SL=0;      //если профит более 8
   double Tang;
   for(int n=0; n<9; n++) //8 - это число элементов массива! должно соответствовать размеру массива!
     {
      zn_X=Mass_Vpprof[n];
      if(zn_X>Dei_PP_Prof)//значение очередной ячейки больше, чем Dei_PP_Prof (перевалило за значение Dei_PP_Prof)
        {
         k=n;//остановка перебора - нашли нужный треугольник
         break;//k -- это номер ячейки справа как правый край нижнего катета
        }
      else
         continue;//иначе далее перебор точек ломаного графика
     }
   if(k==0)
      return(0);
   Katet_Pril=1.00001*(Mass_Vpprof[k]-Mass_Vpprof[k-1]);
   Katet_Prot=1.00001*(Mass_SL[k]-Mass_SL[k-1]);
   Tang=ND(Katet_Prot/Katet_Pril,5);//тангенс получен
   PP_SL=(int)(ND(Tang*(Dei_PP_Prof-Mass_Vpprof[k-1]),0)+Mass_SL[k-1]); //вычисление сработки трала (в пунктах!)
   return(int)(PP_SL);//в этом варианте инт на выходе, но такой способ можно также переделать под расчёты с долл. профитом
  }
//========================================================================================================//
//|                   ----------------- SLT17__имеющийся уже поставленный SL в старых пунктах -------------------
//========================================================================================================//
int SLT17_Im_ppSL()
  {
   double OOP,DSL;
   int OT=0,SL=0;
   DSL=OrderStopLoss();
   if(DSL==0)
      return(0);
   OOP=OrderOpenPrice();
   OT=OrderType();
   if(OT==0)
     {
      SL=(int)ND((DSL-OOP)/Point/10,0);//10 -- это при 5-знаке, на 4-знаке 1 ()
     }
   if(OT==1)
     {
      SL=(int)ND((OOP-DSL)/Point/10,0);
     }
   return(SL);//когда делать ничeго не надо
  }
//###############################################################################################
double ND(double Znachenie,int H_Zn=10) //при отказе от ввода второго параметра возьмётся значение Digits    {if(H_Zn==10)        H_Zn=Digits;    return(NormalizeDouble(Znachenie,H_Zn));   }//и пятизнак учитывается