Осциллятор стохастик: пишем код советника и разбираем его

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

Наш код советника будет содержать следующие параметры:

  • Размер позиции.
  • Использовать противоположный сигнал на вход для закрытия сделки или закрывать позицию по тейк-профиту.
  • Стоп лосс в пунктах.
  • Тейк профит в пунктах.
  • Размер допустимого проскальзывания в пунктах.
  • Возможность включить или отключить торговлю советника.
  • Осциллятор стохастик – К период.
  • Осциллятор стохастик – D период.
  • Замедление стохастика.
  • Осциллятор стохастик – нижний порог.
  • Осциллятор стохастик – верхний порог.
  • Тип скользящей средней, используемый для сигнальной линии.

Сигналы на вход:

  • Сигнал на покупку, когда осциллятор стохастик пересекает нижний порог снизу.
  • Сигнал на продажу, когда осциллятор стохастика пересекает верхний порог сверху.

Сигналы на выход:

  • Фиксированный тейк-профит или стоп-лосс.
  • Закрыть ордер на покупку, когда осциллятор стохастик достигает верхнего порога.
  • Закрыть ордер на продажу, когда осциллятор стохастик достигает нижнего порога.

осциллятор стохастик

Результаты тестирования на EURUSD M15 показывает, что советник сразу же уходит в просадку. Так как советник ограничен использованием только одного индикатора, этого недостаточно, чтобы установить четкие точки входа. Ситуация не становится прибыльной на других таймфреймах, и не стоит использовать этот советник на реальном счете.

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

осциллятор стохастик - результаты тестирования

Код советника:

#property copyright     "Александр Паркер"
#property link          "https://traderblog.net/"
#property version       "1.00"
#property strict

extern double LotSize=0.1;             //Размер позиции.
extern double StopLoss=20;             //Стоп-лосс в пунктах.
extern double TakeProfit=100;          //Тейк-профит в пунктах.
extern int Slippage=2;                 //Проскальзывание в пунктах.
extern bool TradeEnabled=true;         //Разрешена ли торговля.
extern int StochK=5;                   //Стохастик K период, по умолчанию 5.
extern int StochD=3;                   //Стохастик D период, по умолчанию 3
extern int StochSlowing=3;             //Замедление стохастика, по умолчанию 3.
extern int UpperThreshold=80;          //Верхний порог, по умолчанию 80.
extern int LowerThreShold=20;          //Нижний порог, по умолчанию 20.

//Глобальные переменные.
double ePoint;                         //Нормализованные пункты.
bool CanOrder;                         //Риск-менеджмент.
bool CanOpenBuy;                       //Флаг для проверки открытых ордеров на покупку.
bool CanOpenSell;                      //Флаг для проверки открытых ордеров на продажу.
int OrderOpRetry=10;                   //Количество попыток открытия ордера.
int SleepSecs=3;                       //Пауза.
int MinBars=60;                        //Минимальное количество баров на графике.

//Глобальные переменные для цены.
double MinSL;
double MaxSL;
double TP;
double SL;
double Spread;
int Slip; 


//Функция инициализации.
void Initialize(){          
   RefreshRates();
   ePoint=Point;
   Slip=Slippage;
   if (MathMod(Digits,2)==1){
      ePoint*=10;
      Slip*=10;
   }
   TP=TakeProfit*ePoint;
   SL=StopLoss*ePoint;
   CanOrder=TradeEnabled;
   CanOpenBuy=true;
   CanOpenSell=true;
}


//Проверка возможности открытия ордеров.
void CheckCanOrder(){            
   if( Bars<MinBars ){
      Print("Недостаточно баров на графике");
      CanOrder=false;
   }
   OrdersOpen();
   return;
}


//Проверка, какие ордера открыты и какого типа.
void OrdersOpen(){
   for(int i = 0; i<OrdersTotal(); i++) {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) {
         Print("Ошибка - ",GetLastError());
         break;
      } 
      if(OrderSymbol()==Symbol() && OrderType() == OP_BUY) CanOpenBuy=false;
      if(OrderSymbol()==Symbol() && OrderType() == OP_SELL) CanOpenSell=false;
   }
   return;
}


//Закрытие ордеров.
void CloseAll(int Command){
   double ClosePrice=0;
   for(int i = 0; i<OrdersTotal(); i++) {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) {
         Print("Ошибка - ",GetLastError());
         break;
      }
      if(OrderSymbol()==Symbol() && OrderType()==Command) {
         if(Command==OP_BUY) ClosePrice=Bid;
         if(Command==OP_SELL) ClosePrice=Ask;
         double Lots=OrderLots();
         int Ticket=OrderTicket();
         for(int j=1; j<OrderOpRetry; j++){
            bool res=OrderClose(Ticket,Lots,ClosePrice,Slip,Red);
            if(res){
               Print("Ордер закрыт ",Ticket," по цене ",ClosePrice);
               break;
            }
            else Print("Ошибка закрытия ордера ",Ticket," ошибка: ",GetLastError());
         }
      }
   }
   return;
}


//Открываем новые ордера.
void OpenNew(int Command){
   RefreshRates();
   double OpenPrice=0;
   double SLPrice;
   double TPPrice;
   if(Command==OP_BUY){
      OpenPrice=Ask;
      SLPrice=OpenPrice-SL;
      TPPrice=OpenPrice+TP;
   }
   if(Command==OP_SELL){
      OpenPrice=Bid;
      SLPrice=OpenPrice+SL;
      TPPrice=OpenPrice-TP;
   }
   for(int i=1; i<OrderOpRetry; i++){
      int res=OrderSend(Symbol(),Command,LotSize,OpenPrice,Slip,NormalizeDouble(SLPrice,Digits),NormalizeDouble(TPPrice,Digits),"",0,0,Green);
      if(res){
         Print("Новый ордер ",res," открыт ",Command," Объем ",LotSize," Цена открытия ",OpenPrice," Проскальзывание ",Slip," Стоп-лосс ",SLPrice," Тейк-профит ",TPPrice);
         break;
      }
      else Print("Ошибка: ",GetLastError());
   }
   return;
}


//Технический анализ.
bool CrossToOpenBuy=false;
bool CrossToOpenSell=false;
bool CrossToCloseBuy=false;
bool CrossToCloseSell=false;


void CheckStochCross(){
   CrossToOpenBuy=false;
   CrossToOpenSell=false;
   CrossToCloseBuy=false;
   CrossToCloseSell=false;
   double StochPrev=iStochastic(Symbol(),0,StochK,StochD,StochSlowing,MODE_SMA,STO_LOWHIGH,MODE_BASE,1);
   double StochCurr=iStochastic(Symbol(),0,StochK,StochD,StochSlowing,MODE_SMA,STO_LOWHIGH,MODE_BASE,0);
   if(StochPrev<LowerThreShold && StochCurr>LowerThreShold){
      CrossToOpenBuy=true;
   }
   if(StochPrev>UpperThreshold && StochCurr<UpperThreshold){
      CrossToOpenSell=true;
   }
   if(StochCurr>UpperThreshold){
      CrossToCloseBuy=true;
   }
   if(StochCurr<LowerThreShold){
      CrossToCloseSell=true;
   }
}

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   //Выполняем все функции.
   Initialize();
   CheckCanOrder();
   CheckStochCross();
   //Проверка сигналов на открытие позиции.
   if(CrossToCloseBuy) CloseAll(OP_BUY);
   if(CrossToCloseSell) CloseAll(OP_SELL);
   if(CrossToOpenBuy){
      if(CanOpenBuy && CanOrder) OpenNew(OP_BUY);
   }
   if(CrossToOpenSell){
      if(CanOpenSell && CanOrder) OpenNew(OP_SELL);
   }
  }
Добавить комментарий

Ваш e-mail не будет опубликован.