Советник форекс — шаблон

Шаблон советника форекс

Советник форекс — это просто. Терминал MT4 предоставляет платформу и программные средства для автоматизации торговых систем на языке MQL4.

Язык программирования MQL4 довольно не сложен для изучения, очень схож с языком C и содержит большое количество специальных функций ведения торговых операций, получения данных о счете, параметрах торгового инструмента и пр. В общем, написание советника сводится к реализации трех основных функций: формирование сигнала, открытие сделки, сопровождение сделки.

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

Собственно, вот он, код:

#property copyright "Copyright 2015, SergDeev"
#property description "Template Expert Advisor"
#property link      "http://fx-prog.ru"
#property version   "1.0"
#property strict

extern double startLot = 0.2,MaxRisk = 0,noLoss_factor = 1.0;
extern int stopLoss = 50,takeProfit = 500,trailStop = 30,trailStep = 2;
extern int ma_fast = 15,ma_slow = 80,timeStart = 10,timeEnd = 23;
extern int slippage = 5, MAGIC = 20161210;

int OnInit() { // функция инициализации
 if (Digits == 5) { // пересчет параметров сопровождения для 5-знака
  trailStop *= 10; trailStep *= 10; slippage *= 10; takeProfit *= 10; stopLoss *= 10;
 }
 return(INIT_SUCCEEDED);
}
double NormalizeLots(double v) { // функция нормализации объема торговли
 double max_lot = MarketInfo(Symbol(),MODE_MAXLOT);
 double min_lot = MarketInfo(Symbol(),MODE_MINLOT);
 double lot_step = MarketInfo(Symbol(),MODE_LOTSTEP);
 double x = NormalizeDouble((v/lot_step),0) * lot_step;
 if (v > max_lot) v = max_lot;
 if (x < min_lot) x = min_lot;
 return(x);
}

bool Signal_Buy() { // формирование сигнала на покупку
 if (iMA(NULL,0,ma_fast,0,MODE_EMA,PRICE_CLOSE,1) > iMA(NULL,0,ma_slow,0,MODE_EMA,PRICE_CLOSE,1))
 if (iMA(NULL,0,ma_fast,0,MODE_EMA,PRICE_CLOSE,2) < iMA(NULL,0,ma_slow,0,MODE_EMA,PRICE_CLOSE,2))
 return(true);
 return(false);
}

bool Signal_Sell() { // формирование сигнала на продажу
 if (iMA(NULL,0,ma_fast,0,MODE_EMA,PRICE_CLOSE,1) < iMA(NULL,0,ma_slow,0,MODE_EMA,PRICE_CLOSE,1))
 if (iMA(NULL,0,ma_fast,0,MODE_EMA,PRICE_CLOSE,2) > iMA(NULL,0,ma_slow,0,MODE_EMA,PRICE_CLOSE,2))
 return(true);
 return(false);
}

void CheckForOpen(int mode) { // проверка сигналов открытия сделок
   double SL,TP,lot;
   if (Volume[0] > 1) return; // выполняется только на открытии нового бара
   if (mode==OP_BUY && Signal_Buy()) { // покупка
    TP = SL = 0;
    if (stopLoss != 0) SL = Ask - stopLoss * Point;
    if (takeProfit != 0) TP = Bid + takeProfit * Point;
    if (SL != 0 && (Bid-SL)/Point < MarketInfo(NULL,MODE_STOPLEVEL)) SL = Bid - 1.1 * MarketInfo(NULL,MODE_STOPLEVEL) * Point;
    if (TP != 0 && (TP-Ask)/Point < MarketInfo(NULL,MODE_STOPLEVEL)) TP = Ask + 1.1 * MarketInfo(NULL,MODE_STOPLEVEL) * Point;
    if ((MaxRisk > 0) && (SL != 0)) lot = (AccountFreeMargin()*MaxRisk/100)/((Ask-SL)/Point*MarketInfo(Symbol(),MODE_TICKVALUE));
    else lot = startLot;
    if (AccountFreeMargin()<lot*MarketInfo(NULL,MODE_MARGINREQUIRED)) Print("No FreeMargin");
    else {
      if (OrderSend(Symbol(),OP_BUY,NormalizeLots(lot),Ask,slippage,NormalizeDouble(SL,Digits),NormalizeDouble(TP,Digits),MQLInfoString(MQL_PROGRAM_NAME),MAGIC,0,Blue)==-1)
      Print(__FUNCTION__," BUY_ORDER_SEND Ask:",Ask," SL:",SL," TP:",TP," lot:",lot,_LastError);
    }
   }
   if (mode==OP_SELL && Signal_Sell()) { // продажа
    TP = SL = 0;
    if (stopLoss != 0) SL = Bid + stopLoss * Point;
    if (takeProfit != 0) TP = Ask - takeProfit * Point;
    if (SL != 0 && (SL-Ask)/Point < MarketInfo(NULL,MODE_STOPLEVEL)) SL = Ask + 1.1 * MarketInfo(NULL,MODE_STOPLEVEL) * Point;
    if (TP != 0 && (Bid-TP)/Point < MarketInfo(NULL,MODE_STOPLEVEL)) TP = Bid - 1.1 * MarketInfo(NULL,MODE_STOPLEVEL) * Point;
    if ((MaxRisk > 0) && (SL != 0)) lot = (AccountFreeMargin()*MaxRisk/100)/((SL-Bid)/Point*MarketInfo(Symbol(),MODE_TICKVALUE));
    else lot = startLot;
    if (AccountFreeMargin()<lot*MarketInfo(NULL,MODE_MARGINREQUIRED)) Print("No FreeMargin");
    else {
     if (OrderSend(Symbol(),OP_SELL,NormalizeLots(lot),Bid,slippage,NormalizeDouble(SL,Digits),NormalizeDouble(TP,Digits),MQLInfoString(MQL_PROGRAM_NAME),MAGIC,0,Red)==-1)
     Print(__FUNCTION__," SELL_ORDER_SEND Bid:",Bid," SL:",SL," TP:",TP," lot:",lot," ",_LastError);
    }
   }
}

//+------------------------------------------------------------------+
void CheckForClose() { // сопровождение сделок
   double SL,x;
   
   for(int i=0;i<OrdersTotal();i++) { // цикл по всем ордерам терминала
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if ((OrderMagicNumber() != MAGIC) || (OrderSymbol() != Symbol())) continue;
      if (OrderType()==OP_BUY) { // ордер на покупку
        if (OrderStopLoss()<OrderOpenPrice() && noLoss_factor > 0) { // перевод в безубыток
         x = OrderOpenPrice() + noLoss_factor * (OrderOpenPrice()-OrderStopLoss());
         if (Ask > x) {
          SL = OrderOpenPrice() + MarketInfo(NULL,MODE_SPREAD)*Point;
          SL = NormalizeDouble(SL,Digits);
          if (!OrderModify(OrderTicket(),OrderOpenPrice(),SL,OrderTakeProfit(),0)) Print(__FUNCTION__," BUY_NOLOSS_ERROR SL:",SL," ",_LastError);
         }
        }
        if (OrderStopLoss() > OrderOpenPrice() && trailStop > 0) { // трейлинг-стоп
         SL = NormalizeDouble((Bid-trailStop*Point),Digits);
         if (((SL-OrderStopLoss())/Point) > trailStep) {
          if (!OrderModify(OrderTicket(),OrderOpenPrice(),SL,OrderTakeProfit(),0)) Print(__FUNCTION__," BUY_TRAIL_STOP_ERROR SL:",SL," ",_LastError);
          else continue;
         }
        }
      }
      if (OrderType()==OP_SELL) { // ордер на продажу
        if (OrderStopLoss() > OrderOpenPrice() && noLoss_factor > 0) { // перевод в безубыток
         x = OrderOpenPrice() - noLoss_factor * (OrderStopLoss()-OrderOpenPrice());
         if (Bid < x) {
          SL = OrderOpenPrice() - MarketInfo(NULL,MODE_SPREAD)*Point;
          SL = NormalizeDouble(SL,Digits);
          if (!OrderModify(OrderTicket(),OrderOpenPrice(),SL,OrderTakeProfit(),0,clrRed)) Print(__FUNCTION__," SELL_NOLOSS_ERROR SL:",SL," ",_LastError);
         }
        }
        if (OrderStopLoss() < OrderOpenPrice() && trailStop > 0) { // трейлинг-стоп
         SL = NormalizeDouble((Ask+trailStop*Point),Digits);
         if (((OrderStopLoss()-SL)/Point) > trailStep) {
          if (!OrderModify(OrderTicket(),OrderOpenPrice(),SL,OrderTakeProfit(),0,clrRed)) Print(__FUNCTION__," BUY_TRAIL_STOP_ERROR SL:",SL," ",_LastError);
          else continue;
         }
        }
      }
   }
}

int CalculateCurrentOrders(int mode) { // подсчет открытых ордеров
   int num=0;
   for(int i=0;i<OrdersTotal();i++) {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if (OrderMagicNumber() == MAGIC)
      if (OrderSymbol() == Symbol())
      if ((OrderType()==mode) || (mode==-1)) num++;
     }
   return(num);
}

void OnTick() { // выполняется на каждом тике
   if(Bars<100 || IsTradeAllowed()==false) return;
   if ((TimeHour(Time[0]) >= timeStart) && (TimeHour(Time[0]) <= timeEnd)) { // время торговли
     if (CalculateCurrentOrders(OP_BUY) == 0) CheckForOpen(OP_BUY); // проверка открытия BUY
     if (CalculateCurrentOrders(OP_SELL) == 0) CheckForOpen(OP_SELL); // проверка открытия SELL
   }
   if (CalculateCurrentOrders(-1) > 0) CheckForClose(); // сопровождение сделок
   Comment("\nProfit :",DoubleToString((AccountEquity()-AccountBalance()),2), // вывод сводной информации
           "\nAccountBalance: ",DoubleToString(AccountBalance(),2),
           "\nAccountEquity: ",DoubleToString(AccountEquity(),2),
           "\nAccountMargin: ",DoubleToString(AccountMargin(),2),
           "\nAccountFreeMargin: ",DoubleToString(AccountFreeMargin(),2),
           "\nMargeenLevel: ",DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_LEVEL),2));
  }
//+------------------------------------------------------------------+

В коде приведены основные функции:

  • Signal_Buy() — формирование сигнала на покупку;
  • Signal_Sell() — формирование сигнала на продажу;
  • CheckForOpen() — проверка сигналов и открытие сделок;
  • CheckForClose() — сопровождение сделок.

Данный код не в коем случае не претендует на эффективную стратегию форекс. Это всего лишь шаблон, который должен облегчить написание собственного эксперта форекс для начинающего программиста. Для включения в шаблон собственных сигналов необходимо лишь отредактировать функции Signal_Buy() и Signal_Sell().

Так выглядит прогон советника в тестере стратегий.

Вы можете оставить комментарий, или ссылку на Ваш сайт.

Оставить комментарий

Вы должны быть авторизованы, чтобы разместить комментарий.