AM2
Андрей

 
Уровень 34

  Торгую в компаниях:


Группа "Программирование на MQL"

Рейтинг 280



Как переписать советник для реальной торговли

В объявлениях разработчиков советников часто можно встретить фразу «сделаю для реальной торговли». Для человека немного знакомого с MQL вполне под силу самостоятельно переписать советник для реальной торговли. Если у вас не имеется собственных наработок в этом направлении можно воспользоваться готовыми функциями опытных программистов.

Пусть у нас есть советник, торгующий по двум МА. При пересечении медленной МА быстрой снизу вверх покупаем, наоборот продаем.




//+------------------------------------------------------------------+
//|                                                         2MA .mq4 |
//|                                              Copyright 2015, AM2 |
//|                                      http://www.forexsystems.biz |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2015, AM2"
#property link      "http://www.forexsystems.biz"
#property description "Martin expert advisor"

extern int StopLoss     = 1200;
extern int TakeProfit   = 1400;
extern int Slip         = 50;
extern int MA1Period    = 9;
extern int MA2Period    = 22;
extern int Magic        = 123;
extern double Lots      = 0.1;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PutOrder(int type,double price)
  {
   int r=0;
   color clr=Green;
   double sl=0,tp=0;

   if(type==1 || type==3 || type==5)
     {
      clr=Red;
      if(StopLoss>0) sl=NormalizeDouble(price+StopLoss*Point,Digits);
      if(TakeProfit>0) tp=NormalizeDouble(price-TakeProfit*Point,Digits);
     }

   if(type==0 || type==2 || type==4)
     {
      clr=Blue;
      if(StopLoss>0) sl=NormalizeDouble(price-StopLoss*Point,Digits);
      if(TakeProfit>0) tp=NormalizeDouble(price+TakeProfit*Point,Digits);
     }

   r=OrderSend(NULL,type,Lots,NormalizeDouble(price,Digits),Slip,sl,tp,"",Magic,0,clr);
   return;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CountTrades()
  {
   int count=0;
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
           {
            if(OrderType()<2) count++;
           }
        }
     }
   return(count);
  }
//+------------------------------------------------------------------+
//| Check for open order conditions                                  |
//+------------------------------------------------------------------+
void OpenPos()
  {
   double ma11=iMA(NULL,0,MA1Period,0,MODE_EMA,PRICE_CLOSE,1);
   double ma21=iMA(NULL,0,MA2Period,0,MODE_EMA,PRICE_CLOSE,1);
   double ma12=iMA(NULL,0,MA1Period,0,MODE_EMA,PRICE_CLOSE,2);
   double ma22=iMA(NULL,0,MA2Period,0,MODE_EMA,PRICE_CLOSE,2);

//---- buy 
   if(ma11>ma21 && ma12<ma22)
     {
      PutOrder(0,Ask);
     }
//---- sell   
   if(ma11<ma21 && ma12>ma22)
     {
      PutOrder(1,Bid);
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ClosePos()
  {
   double ma11=iMA(NULL,0,MA1Period,0,MODE_EMA,PRICE_CLOSE,1);
   double ma21=iMA(NULL,0,MA2Period,0,MODE_EMA,PRICE_CLOSE,1);
   double ma12=iMA(NULL,0,MA1Period,0,MODE_EMA,PRICE_CLOSE,2);
   double ma22=iMA(NULL,0,MA2Period,0,MODE_EMA,PRICE_CLOSE,2);
//---
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
           {
            if(OrderType()==OP_BUY)
              {
               if(ma11<ma21 && ma12>ma22)
                 {
                  if(!OrderClose(OrderTicket(),OrderLots(),Bid,Slip,Red))
                     Print("OrderClose error ",GetLastError());
                 }
              }
            if(OrderType()==OP_SELL)
              {
               if(ma11>ma21 && ma12<ma22)
                 {
                  if(!OrderClose(OrderTicket(),OrderLots(),Ask,Slip,Blue))
                     Print("OrderClose error ",GetLastError());
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| Start function                                                   |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(CountTrades()<1)
     {
      OpenPos();
     }
   else ClosePos();
  }
//+------------------------------------------------------------------+



Для того, чтобы переписать советник воспользуемся библиотекой функций от Игоря Кима.


Нам понадобятся следующие функции:

Функция ExistPositions().
Предназначена для проверки наличия открытых покупок или продаж.


//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 06.03.2008                                                     |
//|  Описание : Возвращает флаг существования позиций                          |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любая позиция)                  |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//|    ot - время открытия             ( 0   - любое время открытия)           |
//+----------------------------------------------------------------------------+
bool ExistPositions(string sy="", int op=-1, int mn=-1, datetime ot=0) {
  int i, k=OrdersTotal();
 
  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==sy || sy=="") {
        if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
          if (op<0 || OrderType()==op) {
            if (mn<0 || OrderMagicNumber()==mn) {
              if (ot<=OrderOpenTime()) return(True);
            }
          }
        }
      }
    }
  }
  return(False);
}


Функция OpenPosition() для online.


//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 21.03.2008                                                     |
//|  Описание : Открывает позицию и возвращает её тикет.                       |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (NULL или "" - текущий символ)          |
//|    op - операция                                                           |
//|    ll - лот                                                                |
//|    sl - уровень стоп                                                       |
//|    tp - уровень тейк                                                       |
//|    mn - MagicNumber                                                        |
//+----------------------------------------------------------------------------+
int OpenPosition(string sy, int op, double ll, double sl=0, double tp=0, int mn=0) {
  color    clOpen;
  datetime ot;
  double   pp, pa, pb;
  int      dg, err, it, ticket=0;
  string   lsComm=WindowExpertName()+" "+GetNameTF(Period());
 
  if (sy=="" || sy=="0") sy=Symbol();
  if (op==OP_BUY) clOpen=clOpenBuy; else clOpen=clOpenSell;
  for (it=1; it<=NumberOfTry; it++) {
    if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) {
      Print("OpenPosition(): Остановка работы функции");
      break;
    }
    while (!IsTradeAllowed()) Sleep(5000);
    RefreshRates();
    dg=MarketInfo(sy, MODE_DIGITS);
    pa=MarketInfo(sy, MODE_ASK);
    pb=MarketInfo(sy, MODE_BID);
    if (op==OP_BUY) pp=pa; else pp=pb;
    pp=NormalizeDouble(pp, dg);
    ot=TimeCurrent();
    ticket=OrderSend(sy, op, ll, pp, Slippage, sl, tp, lsComm, mn, 0, clOpen);
    if (ticket>0) {
      if (UseSound) PlaySound(NameFileSound); break;
    } else {
      err=GetLastError();
      if (pa==0 && pb==0) Message("Проверьте в Обзоре рынка наличие символа "+sy);
      // Вывод сообщения об ошибке
      Print("Error(",err,") opening position: ",ErrorDescription(err),", try ",it);
      Print("Ask=",pa," Bid=",pb," sy=",sy," ll=",ll," op=",GetNameOP(op),
            " pp=",pp," sl=",sl," tp=",tp," mn=",mn);
      // Блокировка работы советника
      if (err==2 || err==64 || err==65 || err==133) {
        gbDisabled=True; break;
      }
      // Длительная пауза
      if (err==4 || err==131 || err==132) {
        Sleep(1000*300); break;
      }
      if (err==128 || err==142 || err==143) {
        Sleep(1000*66.666);
        if (ExistPositions(sy, op, mn, ot)) {
          if (UseSound) PlaySound(NameFileSound); break;
        }
      }
      if (err==140 || err==148 || err==4110 || err==4111) break;
      if (err==141) Sleep(1000*100);
      if (err==145) Sleep(1000*17);
      if (err==146) while (IsTradeContextBusy()) Sleep(1000*11);
      if (err!=135) Sleep(1000*7.7);
    }
  }
  return(ticket);
}


Функция ClosePositions().
Эта функция выполняет закрытие позиций, параметры которых удовлетворяют заданным значениям:


//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 19.02.2008                                                     |
//|  Описание : Закрытие позиций по рыночной цене                              |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любая позиция)                  |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//+----------------------------------------------------------------------------+
void ClosePositions(string sy="", int op=-1, int mn=-1) {
  int i, k=OrdersTotal();

  if (sy=="0") sy=Symbol();
  for (i=k-1; i>=0; i--) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if ((OrderSymbol()==sy || sy=="") && (op<0 || OrderType()==op)) {
        if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
          if (mn<0 || OrderMagicNumber()==mn) ClosePosBySelect();
        }
      }
    }
  }
}


Добавляем эти функции в советник. Вместо функции CountTrades() у нас будет кимовская
ExistPositions(string sy="", int op=-1, int mn=-1, datetime ot=0);

В блоке OnTick()

Изменяем строку

if(CountTrades()<1)


на

if(ExistPositions(Symbol(),-1,Magic,0)==false)


Далее функцию PutOrder() заменим на OpenPosition. Чтобы это сделать нам понадобятся еще дополнительные функции: GetNameTF, ErrorDescription,GetNameOP,Message. Добавим их также в код нашего эксперта.


//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 01.09.2005                                                     |
//|  Описание : Возвращает наименование таймфрейма                             |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    TimeFrame - таймфрейм (количество секунд)      (0 - текущий ТФ)         |
//+----------------------------------------------------------------------------+
string GetNameTF(int TimeFrame=0) {
  if (TimeFrame==0) TimeFrame=Period();
  switch (TimeFrame) {
    case PERIOD_M1:  return("M1");
    case PERIOD_M5:  return("M5");
    case PERIOD_M15: return("M15");
    case PERIOD_M30: return("M30");
    case PERIOD_H1:  return("H1");
    case PERIOD_H4:  return("H4");
    case PERIOD_D1:  return("Daily");
    case PERIOD_W1:  return("Weekly");
    case PERIOD_MN1: return("Monthly");
    default:         return("UnknownPeriod");
  }
}



//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 01.09.2005                                                     |
//|  Описание : Возвращает наименование торговой операции                      |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    op - идентификатор торговой операции                                    |
//+----------------------------------------------------------------------------+
string GetNameOP(int op) {
  switch (op) {
    case OP_BUY      : return("Buy");
    case OP_SELL     : return("Sell");
    case OP_BUYLIMIT : return("Buy Limit");
    case OP_SELLLIMIT: return("Sell Limit");
    case OP_BUYSTOP  : return("Buy Stop");
    case OP_SELLSTOP : return("Sell Stop");
    default          : return("Unknown Operation");
  }
}



   string Error(int error_code)
     {
      string error_string;
      //----
      switch(error_code)
        {
         //---- Коды ошибок, возвращаемые торговым сервером:
         case 0:   error_string="Нет ошибок";                                                     break;
         case 1:   error_string="Нет ошибки, но результат неизвестен";                            break;
         case 2:   error_string="Общая ошибка";                                                   break;
         case 3:   error_string="Неправильные параметры";                                         break;
         case 4:   error_string="Торговый сервер занят";                                          break;
         case 5:   error_string="Старая версия клиентского терминала";                            break;
         case 6:   error_string="Нет связи с торговым сервером";                                  break;
         case 7:   error_string="Недостаточно прав";                                              break;
         case 8:   error_string="Слишком частые запросы";                                         break;
         case 9:   error_string="Недопустимая операция нарушающая функционирование сервера";      break;
         case 64:  error_string="Счет заблокирован";                                              break;
         case 65:  error_string="Неправильный номер счета";                                       break;
         case 128: error_string="Истек срок ожидания совершения сделки";                          break;
         case 129: error_string="Неправильная цена";                                              break;
         case 130: error_string="Неправильные стопы";                                             break;
         case 131: error_string="Неправильный объем";                                             break;
         case 132: error_string="Рынок закрыт";                                                   break;
         case 133: error_string="Торговля запрещена";                                             break;
         case 134: error_string="Недостаточно денег для совершения операции";                     break;
         case 135: error_string="Цена изменилась";                                                break;
         case 136: error_string="Нет цен";                                                        break;
         case 137: error_string="Брокер занят";                                                   break;
         case 138: error_string="Новые цены";                                                     break;
         case 139: error_string="Ордер заблокирован и уже обрабатывается";                        break;
         case 140: error_string="Разрешена только покупка";                                       break;
         case 141: error_string="Слишком много запросов";                                         break;
         case 145: error_string="Модификация запрещена, так как ордер слишком близок к рынку";    break;
         case 146: error_string="Подсистема торговли занята";                                     break;
         case 147: error_string="Использование даты истечения ордера запрещено брокером";         break;
         case 148: error_string="Количество открытых и отложенных ордеров достигло предела, установленного брокером.";break;
         default:  error_string="Неизвестная ошибка.";
        }
      //----
      return(error_string);
     }
//+------------------------------------------------------------------+ 




//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 01.09.2005                                                     |
//|  Описание : Вывод сообщения в коммент и в журнал                           |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    m - текст сообщения                                                     |
//+----------------------------------------------------------------------------+
void Message(string m) {
  Comment(m);
  if (StringLen(m)>0 && PrintEnable) {
    if (AllMessages || prevMessage!=m) {
      prevMessage=m;
      Print(m);
    }
  }
}
//+----------------------------------------------------------------------------+



Также добавим необходимые глобальные переменные из библиотек


//------- Глобальные переменные для безошибочной компиляции -------------------+
bool   AllMessages, PrintEnable, gbDisabled;
string prevMessage;


Добавим дополнительные входные переменные:


extern int NumberOfTry      = 5;          // Количество попыток выставления и закрытия ордера
extern string NameFileSound = "News.wav"; // Имя файла для мелодии открытия закрытия ордера
extern bool UseSound        = True;       // Использовать мелодию при открытии закрытии ордера


для открытия позиции в функции OpenPos() заменим функцию PutOrder() на кимовскую OpenPosition

В результате OpenPos() будет выглядеть следующим образом:


void OpenPos()
  {
   double ma11=iMA(NULL,0,MA1Period,0,MODE_EMA,PRICE_CLOSE,1);
   double ma21=iMA(NULL,0,MA2Period,0,MODE_EMA,PRICE_CLOSE,1);
   double ma12=iMA(NULL,0,MA1Period,0,MODE_EMA,PRICE_CLOSE,2);
   double ma22=iMA(NULL,0,MA2Period,0,MODE_EMA,PRICE_CLOSE,2);

//---- buy 
   if(ma11>ma21 && ma12<ma22)
     {
      OpenPosition(Symbol(),OP_BUY,Lots,NormalizeDouble(Ask-StopLoss*Point,Digits),NormalizeDouble(Ask+TakeProfit*Point,Digits),Magic);
     }
//---- sell   
   if(ma11<ma21 && ma12>ma22)
     {
      OpenPosition(Symbol(),OP_SELL,Lots,NormalizeDouble(Ask+StopLoss*Point,Digits),NormalizeDouble(Ask-TakeProfit*Point,Digits),Magic);;
     }
  }


Закрытие позиций изменим таким же образом, подставив в функцию ClosePos() закрытие по киму ClosePositions(Symbol(),-1,Magic);
И получим:


void ClosePos()
  {
   double ma11=iMA(NULL,0,MA1Period,0,MODE_EMA,PRICE_CLOSE,1);
   double ma21=iMA(NULL,0,MA2Period,0,MODE_EMA,PRICE_CLOSE,1);
   double ma12=iMA(NULL,0,MA1Period,0,MODE_EMA,PRICE_CLOSE,2);
   double ma22=iMA(NULL,0,MA2Period,0,MODE_EMA,PRICE_CLOSE,2);
//---
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
           {
            if(OrderType()==OP_BUY)
              {
               if(ma11<ma21 && ma12>ma22)
                 {
                  ClosePositions(Symbol(),-1,Magic);
                 }
              }
            if(OrderType()==OP_SELL)
              {
               if(ma11>ma21 && ma12<ma22)
                 {
                  ClosePositions(Symbol(),-1,Magic);
                 }
              }
           }
        }
     }
  }


В результате таких манипуляций получаем, код для реальной торговли.


//+------------------------------------------------------------------+
//|                                                    2MAMartin.mq4 |
//|                                              Copyright 2015, AM2 |
//|                                      http://www.forexsystems.biz |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2015, AM2"
#property link      "http://www.forexsystems.biz"
#property description "Martin expert advisor"

extern int StopLoss     = 1200;
extern int TakeProfit   = 1400;
extern int Slip         = 50;
extern int MA1Period    = 9;
extern int MA2Period    = 22;
extern int Magic        = 123;
extern double Lots      = 0.1;

extern int NumberOfTry      = 5;          // Количество попыток выставления и закрытия ордера
extern string NameFileSound = "News.wav"; // Имя файла для мелодии открытия закрытия ордера
extern bool UseSound        = True;       // Использовать мелодию при открытии закрытии ордера


//------- Глобальные переменные для безошибочной компиляции -------------------+
bool   AllMessages,PrintEnable,gbDisabled;
string prevMessage;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 06.03.2008                                                     |
//|  Описание : Возвращает флаг существования позиций                          |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любая позиция)                  |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//|    ot - время открытия             ( 0   - любое время открытия)           |
//+----------------------------------------------------------------------------+
bool ExistPositions(string sy="",int op=-1,int mn=-1,datetime ot=0)
  {
   int i,k=OrdersTotal();

   if(sy=="0") sy=Symbol();
   for(i=0; i<k; i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==sy || sy=="")
           {
            if(OrderType()==OP_BUY || OrderType()==OP_SELL)
              {
               if(op<0 || OrderType()==op)
                 {
                  if(mn<0 || OrderMagicNumber()==mn)
                    {
                     if(ot<=OrderOpenTime()) return(True);
                    }
                 }
              }
           }
        }
     }
   return(False);
  }
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 21.03.2008                                                     |
//|  Описание : Открывает позицию и возвращает её тикет.                       |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (NULL или "" - текущий символ)          |
//|    op - операция                                                           |
//|    ll - лот                                                                |
//|    sl - уровень стоп                                                       |
//|    tp - уровень тейк                                                       |
//|    mn - MagicNumber                                                        |
//+----------------------------------------------------------------------------+
int OpenPosition(string sy,int op,double ll,double sl=0,double tp=0,int mn=0)
  {
   color    clOpen;
   datetime ot;
   double   pp,pa,pb;
   int      dg,err,it,ticket=0;
   string   lsComm=WindowExpertName()+" "+GetNameTF(Period());

   if(sy=="" || sy=="0") sy=Symbol();
   if(op==OP_BUY) clOpen=Blue; else clOpen=Red;
   for(it=1; it<=NumberOfTry; it++)
     {
      if(!IsTesting() && (!IsExpertEnabled() || IsStopped()))
        {
         Print("OpenPosition(): Остановка работы функции");
         break;
        }
      while(!IsTradeAllowed()) Sleep(5000);
      RefreshRates();
      dg=MarketInfo(sy, MODE_DIGITS);
      pa=MarketInfo(sy, MODE_ASK);
      pb=MarketInfo(sy, MODE_BID);
      if(op==OP_BUY) pp=pa; else pp=pb;
      pp=NormalizeDouble(pp, dg);
      ot=TimeCurrent();
      ticket=OrderSend(sy,op,ll,pp,Slip,sl,tp,lsComm,mn,0,clOpen);
      if(ticket>0)
        {
         if(UseSound) PlaySound(NameFileSound); break;
           } else {
         err=GetLastError();
         if(pa==0 && pb==0) Message("Проверьте в Обзоре рынка наличие символа "+sy);
         // Вывод сообщения об ошибке
         Print("Error(",err,") opening position: ",ErrorDescription(err),", try ",it);
         Print("Ask=",pa," Bid=",pb," sy=",sy," ll=",ll," op=",GetNameOP(op),
               " pp=",pp," sl=",sl," tp=",tp," mn=",mn);
         // Блокировка работы советника
         if(err==2 || err==64 || err==65 || err==133)
           {
            gbDisabled=True; break;
           }
         // Длительная пауза
         if(err==4 || err==131 || err==132)
           {
            Sleep(1000*300); break;
           }
         if(err==128 || err==142 || err==143)
           {
            Sleep(1000*66.666);
            if(ExistPositions(sy,op,mn,ot))
              {
               if(UseSound) PlaySound(NameFileSound); break;
              }
           }
         if(err==140 || err==148 || err==4110 || err==4111) break;
         if(err==141) Sleep(1000*100);
         if(err==145) Sleep(1000*17);
         if(err==146) while(IsTradeContextBusy()) Sleep(1000*11);
         if(err!=135) Sleep(1000*7.7);
        }
     }
   return(ticket);
  }
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 19.02.2008                                                     |
//|  Описание : Закрытие позиций по рыночной цене                              |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любая позиция)                  |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//+----------------------------------------------------------------------------+
void ClosePositions(string sy="",int op=-1,int mn=-1) 
  {
   int i,k=OrdersTotal();

   if(sy=="0") sy=Symbol();
   for(i=k-1; i>=0; i--) 
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) 
        {
         if((OrderSymbol()==sy || sy=="") && (op<0 || OrderType()==op)) 
           {
            if(OrderType()==OP_BUY || OrderType()==OP_SELL) 
              {
               if(mn<0 || OrderMagicNumber()==mn) ClosePosBySelect();
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ClosePosBySelect() 
  {
   bool   fc;
   color  clClose;
   double ll,pa,pb,pp;
   int    err,it;

   if(OrderType()==OP_BUY || OrderType()==OP_SELL) 
     {
      for(it=1; it<=NumberOfTry; it++) 
        {
         if(!IsTesting() && (!IsExpertEnabled() || IsStopped())) break;
         while(!IsTradeAllowed()) Sleep(5000);
         RefreshRates();
         pa=MarketInfo(OrderSymbol(), MODE_ASK);
         pb=MarketInfo(OrderSymbol(), MODE_BID);
         if(OrderType()==OP_BUY) 
           {
            pp=pb; clClose=White;
              } else {
            pp=pa; clClose=White;
           }
         ll=OrderLots();
         fc=OrderClose(OrderTicket(), ll, pp, Slip, clClose);
         if(fc) 
           {
            if(UseSound) PlaySound(NameFileSound); break;
              } else {
            err=GetLastError();
            if(err==146) while(IsTradeContextBusy()) Sleep(1000*11);
            Print("Error(",err,") Close ",GetNameOP(OrderType())," ",
                  ErrorDescription(err),", try ",it);
            Print(OrderTicket(),"  Ask=",pa,"  Bid=",pb,"  pp=",pp);
            Print("sy=",OrderSymbol(),"  ll=",ll,"  sl=",OrderStopLoss(),
                  "  tp=",OrderTakeProfit(),"  mn=",OrderMagicNumber());
            Sleep(1000*5);
           }
        }
     }
   else Print("Некорректная торговая операция. Close ",GetNameOP(OrderType()));
  }
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 01.09.2005                                                     |
//|  Описание : Возвращает наименование таймфрейма                             |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    TimeFrame - таймфрейм (количество секунд)      (0 - текущий ТФ)         |
//+----------------------------------------------------------------------------+
string GetNameTF(int TimeFrame=0)
  {
   if(TimeFrame==0) TimeFrame=Period();
   switch(TimeFrame)
     {
      case PERIOD_M1:  return("M1");
      case PERIOD_M5:  return("M5");
      case PERIOD_M15: return("M15");
      case PERIOD_M30: return("M30");
      case PERIOD_H1:  return("H1");
      case PERIOD_H4:  return("H4");
      case PERIOD_D1:  return("Daily");
      case PERIOD_W1:  return("Weekly");
      case PERIOD_MN1: return("Monthly");
      default:         return("UnknownPeriod");
     }
  }
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 01.09.2005                                                     |
//|  Описание : Возвращает наименование торговой операции                      |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    op - идентификатор торговой операции                                    |
//+----------------------------------------------------------------------------+
string GetNameOP(int op)
  {
   switch(op)
     {
      case OP_BUY      : return("Buy");
      case OP_SELL     : return("Sell");
      case OP_BUYLIMIT : return("Buy Limit");
      case OP_SELLLIMIT: return("Sell Limit");
      case OP_BUYSTOP  : return("Buy Stop");
      case OP_SELLSTOP : return("Sell Stop");
      default          : return("Unknown Operation");
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string ErrorDescription(int error_code)
  {
   string error_string;
//----
   switch(error_code)
     {
      //---- Коды ошибок, возвращаемые торговым сервером:
      case 0:   error_string="Нет ошибок";                                                     break;
      case 1:   error_string="Нет ошибки, но результат неизвестен";                            break;
      case 2:   error_string="Общая ошибка";                                                   break;
      case 3:   error_string="Неправильные параметры";                                         break;
      case 4:   error_string="Торговый сервер занят";                                          break;
      case 5:   error_string="Старая версия клиентского терминала";                            break;
      case 6:   error_string="Нет связи с торговым сервером";                                  break;
      case 7:   error_string="Недостаточно прав";                                              break;
      case 8:   error_string="Слишком частые запросы";                                         break;
      case 9:   error_string="Недопустимая операция нарушающая функционирование сервера";      break;
      case 64:  error_string="Счет заблокирован";                                              break;
      case 65:  error_string="Неправильный номер счета";                                       break;
      case 128: error_string="Истек срок ожидания совершения сделки";                          break;
      case 129: error_string="Неправильная цена";                                              break;
      case 130: error_string="Неправильные стопы";                                             break;
      case 131: error_string="Неправильный объем";                                             break;
      case 132: error_string="Рынок закрыт";                                                   break;
      case 133: error_string="Торговля запрещена";                                             break;
      case 134: error_string="Недостаточно денег для совершения операции";                     break;
      case 135: error_string="Цена изменилась";                                                break;
      case 136: error_string="Нет цен";                                                        break;
      case 137: error_string="Брокер занят";                                                   break;
      case 138: error_string="Новые цены";                                                     break;
      case 139: error_string="Ордер заблокирован и уже обрабатывается";                        break;
      case 140: error_string="Разрешена только покупка";                                       break;
      case 141: error_string="Слишком много запросов";                                         break;
      case 145: error_string="Модификация запрещена, так как ордер слишком близок к рынку";    break;
      case 146: error_string="Подсистема торговли занята";                                     break;
      case 147: error_string="Использование даты истечения ордера запрещено брокером";         break;
      case 148: error_string="Количество открытых и отложенных ордеров достигло предела, установленного брокером.";break;
      default:  error_string="Неизвестная ошибка.";
     }
//----
   return(error_string);
  }
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 01.09.2005                                                     |
//|  Описание : Вывод сообщения в коммент и в журнал                           |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    m - текст сообщения                                                     |
//+----------------------------------------------------------------------------+
void Message(string m) 
  {
   Comment(m);
   if(StringLen(m)>0  &&  PrintEnable) 
     {
      if(AllMessages || prevMessage!=m) 
        {
         prevMessage=m;
         Print(m);
        }
     }
  }
//+------------------------------------------------------------------+
//| Check for open order conditions                                  |
//+------------------------------------------------------------------+
void OpenPos()
  {
   double ma11=iMA(NULL,0,MA1Period,0,MODE_EMA,PRICE_CLOSE,1);
   double ma21=iMA(NULL,0,MA2Period,0,MODE_EMA,PRICE_CLOSE,1);
   double ma12=iMA(NULL,0,MA1Period,0,MODE_EMA,PRICE_CLOSE,2);
   double ma22=iMA(NULL,0,MA2Period,0,MODE_EMA,PRICE_CLOSE,2);

//---- buy 
   if(ma11>ma21 && ma12<ma22)
     {
      OpenPosition(Symbol(),OP_BUY,Lots,NormalizeDouble(Ask-StopLoss*Point,Digits),NormalizeDouble(Ask+TakeProfit*Point,Digits),Magic);
     }
//---- sell   
   if(ma11<ma21 && ma12>ma22)
     {
      OpenPosition(Symbol(),OP_SELL,Lots,NormalizeDouble(Ask+StopLoss*Point,Digits),NormalizeDouble(Ask-TakeProfit*Point,Digits),Magic);;
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ClosePos()
  {
   double ma11=iMA(NULL,0,MA1Period,0,MODE_EMA,PRICE_CLOSE,1);
   double ma21=iMA(NULL,0,MA2Period,0,MODE_EMA,PRICE_CLOSE,1);
   double ma12=iMA(NULL,0,MA1Period,0,MODE_EMA,PRICE_CLOSE,2);
   double ma22=iMA(NULL,0,MA2Period,0,MODE_EMA,PRICE_CLOSE,2);
//---
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
           {
            if(OrderType()==OP_BUY)
              {
               if(ma11<ma21 && ma12>ma22)
                 {
                  ClosePositions(Symbol(),-1,Magic);
                 }
              }
            if(OrderType()==OP_SELL)
              {
               if(ma11>ma21 && ma12<ma22)
                 {
                  ClosePositions(Symbol(),-1,Magic);
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| Start function                                                   |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(ExistPositions(Symbol(),-1,Magic,0)==false)
     {
      OpenPos();
     }
   else ClosePos();
  }
//+------------------------------------------------------------------+



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


#include <b-Positions_include.mqh>       // Библиотека функций для работы с позициями 
#include <b-KimIV_include.mqh>           // Библиотека дополнительных функций
#include <b-Orders_include.mqh>          // Библиотека функций для работы с ордерами


Все библиотеки и код эксперта можно скачать одним архивом. Также в архиве есть все функции в формате HTML.
Скачать советник и библиотеки функций: www.opentraders.ru/downloads/1093/
  • +10
  • Просмотров: 11763
  • 13 марта 2016, 16:12
  • AM2
Понравилcя материал? Не забудьте поставить плюс и поделиться в социальной сети!

Вступите в группу "Программирование на MQL", чтобы следить за обновлениями
ПРИСОЕДИНИТЬСЯ К ГРУППЕ
присоединиться
20 февраля 2016
21 марта 2016

Комментарии (5)

+
0
Ты забыл в OnInit() добавить кучу проверок. Да и этим тоже все не ограничивается.
avatar

  27  Oxy Сообщений: 3418 - ..ιllιlι.lι.ιllι.ιlι..

  • 14 марта 2016, 11:24
+
0
Еще есть мысль написать подобную статейку по написанию собственных функций, проверок на основе кодов Кима, Роша и Косицина. Может еще подскажешь чьи коды можно взять за образец или материалы на эту тему?
avatar

  34  AM2 Автор Сообщений: 15882 - Андрей

  • 14 марта 2016, 11:43
+
+1
Исключительно своими пользуюсь. Себе сама создала библиотеку.
avatar

  27  Oxy Сообщений: 3418 - ..ιllιlι.lι.ιllι.ιlι..

  • 14 марта 2016, 11:44
+
0
Вдогонку библиотеки функций: www.opentraders.ru/downloads/1095/

1. Торговые от TarasBY
2. Торговые от Andrey Shpilev
3. Трейлинг от TarasBY
4. Капитал от TarasBY
5. Ошибки от IURII TOKMAN
6. Капитал от Andrey Khatimlianskii
7. Тралы от Юрий Дзюбан
8. Торговые от Andrey Khatimlianskii
avatar

  34  AM2 Автор Сообщений: 15882 - Андрей

  • 14 марта 2016, 14:09
+
0
Простой шаблон для эксперта для реала с инструкцией: www.opentraders.ru/downloads/1096/


avatar

  34  AM2 Автор Сообщений: 15882 - Андрей

  • 14 марта 2016, 15:29

Зарегистрируйтесь или авторизуйтесь, чтобы оставить комментарий
Начать торговлю с Альпари