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

Рейтинг 280


Рейтинг
280
avatar

Программирование на MQL  

Описание группы

Обсуждаем здесь вопросы разработки экспертов, делимся опытом, выкладываем уроки.

Внимание! Если Вы хотите заказать советник, то Вам в группу «Заказы на разработку советников»

Координаторы (1)

Соавторы (7)

Участники (198)

Открытая группа

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

создавать новые топики в группе смогут только назначенные соавторы.

Как написать советник автомат, торгующий по новостям.

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

Реализовать подобный эксперт оказывается не так уж и сложно, как может показаться на первый взгляд. Чтобы нам

( Читать дальше )


Советник "Gerchik Trader Bot"

Советник написан по мотивам вебинара А.М.Герчика «Уровни на FOREX».

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

( Читать дальше )


Простейший сеточный советник "Hello!"

Простейший сеточный советник «Hello!» на одном индикаторе.

Рабочий тайм фрейм Н1. Хорошо карабкается по тренду и усредняется во флете. Не любит резкой смены тренда. При уходе позиции в минус добавляет усредняющие ордера и пересчитывает стопы. Оптимизирован на 2000-2013 годах. Дает хороший форвард тест.

«Hello!» потому что работает по хаям и лоу :) 



( Читать дальше )


Обучение MQL5. Бесплатный видеокурс из 8 уроков

Обнаружил бесплатный курс обучения MQL5 в формате вебинаров.

Автор: Денис Кириченко, ведущий вебинаров от компании Roboforex

Для обучения понадобится: MetaTrader5 (скачать)

Необходимый минимум знаний перед началом обучения:
начальный уровень работы с терминалом MetaTrader
-

( Читать дальше )


Простейший скрипт - советник для анализа статистики.

Подобный анализ статистики рынка с сайта www.statlist.net можно сделать с помощью простейшего скрипта.



С 2000-го года на D1, паттерн — свеча черная, свеча белая — следующая белая.
Вероятность 48.2%, в пятницу 65.2%.





( Читать дальше )


Как написать простейший советник, торгующий отложенными ордерами.

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

Перво наперво определимся со стратегией по которой наш эксперт будет торговать. За основу я взял первую пришедшую на ум стратегию. Составим небольшое техзадание для нашей импровизации.



( Читать дальше )


(mql4) Функция расчета лота в зависимости от величины просадки

Недавно я писал о методе увеличения прибыли с помощью введения зависимости лота от величины просадки. Читать подробнее о методе

Идею (которую раньше проверял в Excel) удалось воплотить в код MQL4. В этой заметке выкладываю получившийся код.

( Читать дальше )


Приемы MQL: открытие только одной сделки за один бар

По мере изучения MQL и перевода своих стратегий на код сталкиваюсь с некоторыми типовыми задачами, решение которых планирую выкладывать в данной группе.

Итак, первое, с чем я столкнулся — это необходимость открытия только одной сделки в текущем баре. Т.е. получили сигнал в текущем баре и после открытия сделки больше в этом баре новых сделок не открываем.

Есть разные способы решения задачи. От использования предопределенной переменной Bars в данном случае предостерегают, т.к. Bars может изменяться, например, при докачке истории.

Выбрал следующий способ.

1.Добавляем функцию IfOrderYetOpen

( Читать дальше )


По просьбе wizzard... Инфосоветник. (Часть 2)

Официальное продолжение решение вопроса моего друга wizzard-а...

… необходимо получить график зависимости суммы прибыли(убытка) по текущим открытым сделкам от времени. То есть если открыто три сделки +5, -12, +15 то значение +8.
Интересна зависимость этого параметра от времени. Можно каждую минуту вычислять этот параметр и складывать в файл.


Часть 1 состоит в том, чтобы получать значения об открытых ордерах всех валютных пар, полностью, их сумму в общем отображении.
Часть 2 состоит в том, чтобы задавая периодичность времени в настройках, эксперт мог сохранять в файл значение Прибыль_Убыток каждый раз с периодичностью n минут и записывать время в которое это произошло.

Часть 1 находится вот здесь
Ниже представлена реализация второй части *улыбается*

( Читать дальше )


По просьбе wizzard... Инфосоветник. (Часть 1)

Пару дней назад, мой друг wizzard попросил меня о помощи:

… необходимо получить график зависимости суммы прибыли(убытка) по текущим открытым сделкам от времени. То есть если открыто три сделки +5, -12, +15 то значение +8.
Интересна зависимость этого параметра от времени. Можно каждую минуту вычислять этот параметр и складывать в файл.


Часть 1 состоит в том, чтобы получать значения об открытых ордерах всех валютных пар, полностью, их сумму в общем отображении.
Часть 2 состоит в том, чтобы задавая периодичность времени в настройках, эксперт мог сохранять в файл значение Прибыль_Убыток каждый раз с периодичностью n минут и записывать время в которое это произошло.

Реализация в коде первой части предоставлено ниже *улыбается*
//+------------------------------------------------------------------+
//|                                      InfoEXPERT#1-amyrgan145.mq4 |
//|                                                          amyrgan |
//|                                                amyrgan@yandex.ru |
//+------------------------------------------------------------------+
#property copyright "amyrgan"
#property link      "amyrgan@yandex.ru"
//+------------------------------------------------------------------+
// Инит!
//+------------------------------------------------------------------+
void init(){
}
//+------------------------------------------------------------------+
// Деинит!
//+------------------------------------------------------------------+
void deinit(){
}
//+------------------------------------------------------------------+
// Старт!
//+------------------------------------------------------------------+
void start(){
   Comment("\n",
   "Прибыль_Убыток = ", ВычислениеПрибылиИлиУбытка());
}
//+------------------------------------------------------------------+
// Сумма открытых ордеров                                   
//+------------------------------------------------------------------+
double ВычислениеПрибылиИлиУбытка(){
   double buys=0,sells=0;

   for(int i=0;i<OrdersTotal();i++)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) continue;
      if(OrderType()==OP_BUY) buys += OrderProfit();
      if(OrderType()==OP_SELL) sells += OrderProfit();
   }
   return(buys+sells);
}
//+------------------------------------------------------------------+



Тоесть советник будет отображать на графике текстом значение суммарных открытых ордеров *улыбается*


Будут вопросы, пишите внизу в комментариях *улыбается*
Кому понравился пост, жмите «Мне нравится»

Продолжение в Части 2… *улыбается*


Пишем усреднитель.

Воспользуемся для нашего усреднителя готовой торговой системой одного из успешных управляющих на рынке FOREX.

Суть системы в следующем:

1) В ноль-ноль по терминальному времени открывается две сделки по GBPUSD, одна на север, вторая на юг. Тейк короткий — 10-15 пп. Лот — 0,01 на 100$ депозита.
2) Дальше, одна из сделок закрывается по тейку. На втором направлении начинается усреднение. Пипстеп рассчитывается из следующих соображений:
а) исторически сложившееся максимальное бескоррекционное движение GBPUSD,
б) максимально допустимая просадка в 50% на N-ное количество колен.
На сегодня этот диапазон составляет 2-2,5 фигуры.
3) Далее, если этого расстояния оказывается недостаточно для закрытия серии, тогда срабатывает отложенный локирующий ордер. Сова отключается и разруливание лока производится вручную.

За основу возьмем код эксперта Ilan 1.4.

Далее достаточно немного изменить блок сигнала для первой сделки:


      if (TradeNow && total<1){
         double PrevCl = iClose(Symbol(),0,2);
         double CurrCl = iClose(Symbol(),0,1);
         SellLimit = Bid;   
         BuyLimit = Ask;
   
            if(!ShortTrade && !LongTrade){
               NumOfTrades = total;
                  if(PrevCl > CurrCl){
                     iLots = fGetLots(OP_SELL);
                        if(iLots>0){//#
                           ticket = OpenPendingOrder(OP_SELL,iLots,SellLimit,slip,SellLimit,0,0,EAName+"-"+NumOfTrades,MagicNumber,0,HotPink);
                           if(ticket<0){Print(iLots,"Error: ",GetLastError()); return(0);}
                           LastBuyPrice = FindLastBuyPrice();
                           NewOrdersPlaced = true;
                        }//#
                  }   
                  else{
                     iLots = fGetLots(OP_BUY);
                        if(iLots>0){//#      
                           ticket = OpenPendingOrder(OP_BUY,iLots,BuyLimit,slip,BuyLimit,0,0,EAName+"-"+NumOfTrades,MagicNumber,0,Lime);
                              if(ticket<0){Print(iLots,"Error: ",GetLastError()); return(0);}
                                 LastSellPrice = FindLastSellPrice();
                                 NewOrdersPlaced = true;
                              }//#
                        }
                  }      
               if(ticket>0) expiration = CurTime()+MaxTradeOpenHours*60*60;
               TradeNow = false;
            }



Новый вариант у нас будет иметь вид:


      if (TradeNow && total<1){

         SellLimit = Bid;   
         BuyLimit = Ask;
   
            if(!ShortTrade && !LongTrade && Hour()==0)
            {
               NumOfTrades = total;
                  {
                     iLots = fGetLots(OP_SELL);
                        if(iLots>0){//#
                           ticket = OpenPendingOrder(OP_SELL,iLots,SellLimit,slip,SellLimit,0,Bid-TakeProfit*Point,EAName+"-"+NumOfTrades,MagicNumber,0,HotPink);
                           if(ticket<0){Print(iLots,"Error: ",GetLastError()); return(0);}
                           LastBuyPrice = FindLastBuyPrice();
                           NewOrdersPlaced = true;
                        }//#
                  }   
                        {
                     iLots = fGetLots(OP_BUY);
                        if(iLots>0){//#      
                           ticket = OpenPendingOrder(OP_BUY,iLots,BuyLimit,slip,BuyLimit,0,Ask+TakeProfit*Point,EAName+"-"+NumOfTrades,MagicNumber,0,Lime);
                              if(ticket<0){Print(iLots,"Error: ",GetLastError()); return(0);}
                                 LastSellPrice = FindLastSellPrice();
                                 NewOrdersPlaced = true;
                              }//#
                        }
                  }      
               if(ticket>0) expiration = CurTime()+MaxTradeOpenHours*60*60;
               TradeNow = false;
            }



И наш усреднитель уже может выставлять две разнонаправленные сделки в ноль часов, затем выводить в плюс убыточную сделку.



Рис.1. Схема работы усреднителя.

И вот новый код готов!


//+------------------------------------------------------------------+
//|                                   2008                   Ilan1.4 |
//+------------------------------------------------------------------+


#property copyright "Nikisaki@yandex.ru"

extern int     MMType=1; // Тип ММ: 0-Lots, 1-как было в 1.2, 2-мартингейл (коэффициент LotExponent)
extern bool    UseClose=false; // закрытие по убытку PipStep. рекомендутся false 
extern bool    UseAdd=true; // переоткрытие с новым лотом. лот для переоткрытия считается по LotExponent независимо от MMType рекомендутся = true
extern double  LotExponent = 1.667; // умножение лотов в серии по експоненте для вывода в безубыток. первый лот 0.1, серия: 0.16, 0.26, 0.43 ...
extern double  slip = 3; // допустимое проскальзывание цены в пипсах
extern double  Lots = 0.1; // теперь можно и микролоты 0.01 при этом если стоит 0.1 то следующий лот в серии будет 0.16
extern double  LotsDigits=2; // 2 - микролоты 0.01, 1 - мини лоты 0.1, 0 - нормальные лоты 1.0
extern double  TakeProfit = 10; // Уровень прибыли в пипсаз от цены открытия.
 double  Stoploss = 500; // эти три параметра не работают
 double  TrailStart = 10;
 double  TrailStop = 10;
extern double  PipStep = 30; // растоянию в пипсах убытка на котором открываеться следующий ордер колена.
extern int     MaxTrades = 10;
extern bool    UseEquityStop = false;
extern double  TotalEquityRisk = 20; //loss as a percentage of equity
extern bool    UseTrailingStop = false;
extern bool    UseTimeOut = false;
extern double  MaxTradeOpenHours = 48;

int MagicNumber = 12324;
double PriceTarget, StartEquity, BuyTarget, SellTarget;
double AveragePrice, SellLimit, BuyLimit;
double LastBuyPrice, LastSellPrice, ClosePrice, Spread;
int flag;
string EAName = "CostAvg-Pyramid";
datetime timeprev=0, expiration;
int NumOfTrades=0;
double iLots;
int cnt=0, total;
double Stopper=0;  
bool TradeNow = false, LongTrade=false, ShortTrade=false;
int ticket;
bool NewOrdersPlaced = false;

int init()
{
 Spread = MarketInfo(Symbol(), MODE_SPREAD)*Point;
 return(0);
}

int deinit()
{
 return(0);
}

int start(){

  
  
   if (UseTrailingStop){
      TrailingAlls(TrailStart, TrailStop, AveragePrice); 
   }
   if (UseTimeOut){
      if(CurTime() >= expiration){
         CloseThisSymbolAll();
         Print("Closed All due to TimeOut");
      }
   }
  
   if(timeprev==Time[0]){
      return(0);
   }
 
   timeprev=Time[0];
 
   double CurrentPairProfit = CalculateProfit();
      if(UseEquityStop){
         if(CurrentPairProfit<0 && MathAbs(CurrentPairProfit)>(TotalEquityRisk/100)*AccountEquityHigh()){
            CloseThisSymbolAll();
            Print("Closed All due to Stop Out");
            NewOrdersPlaced = false;
         }
      }

 
   total=CountTrades();
   
      if (total == 0){
         flag = 0;
      }
      
   double LastBuyLots;
   double LastSellLots;
      
      for(cnt=OrdersTotal()-1;cnt>=0;cnt--){// поиск последнего направления
         OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);
            if(OrderSymbol()!=Symbol()||OrderMagicNumber()!=MagicNumber)continue;
               if(OrderSymbol()==Symbol()&&OrderMagicNumber()==MagicNumber)
                  if(OrderType()==OP_BUY){
                     LongTrade = true;
                     ShortTrade = false;
                     LastBuyLots=OrderLots();
                     break;
                  }
               if(OrderSymbol()==Symbol()&&OrderMagicNumber()==MagicNumber)
                  if(OrderType()==OP_SELL){
                     LongTrade = false;
                     ShortTrade = true;
                     LastSellLots=OrderLots();
                     break;
               }
      }
  
      if(total>0 && total <= MaxTrades){
         RefreshRates();
         LastBuyPrice = FindLastBuyPrice();
         LastSellPrice = FindLastSellPrice();
            if(LongTrade && (LastBuyPrice - Ask) >= (PipStep*Point)){
               TradeNow = true;
            }
            if(ShortTrade && (Bid - LastSellPrice) >= (PipStep*Point)){
               TradeNow = true;
            }
      } 
  
      if (total < 1){
         ShortTrade = false;
         LongTrade = false;
         TradeNow = true;
         StartEquity = AccountEquity();
      }

      if (TradeNow){
         LastBuyPrice = FindLastBuyPrice();
         LastSellPrice = FindLastSellPrice();
            if(ShortTrade){
                  if(UseClose){
                     fOrderCloseMarket(false,true);
                     iLots = NormalizeDouble(LotExponent*LastSellLots,LotsDigits);
                  }
                  else{
                     iLots = fGetLots(OP_SELL);
                  }
                  if(UseAdd){
                     NumOfTrades = total;               
                        if(iLots>0){//#
                           RefreshRates();
                           ticket = OpenPendingOrder(OP_SELL,iLots,Bid,slip,Ask,0,0,EAName+"-"+NumOfTrades,MagicNumber,0,HotPink);
                           if(ticket<0){Print("Error: ",GetLastError()); return(0);}
                           LastSellPrice = FindLastSellPrice();
                           TradeNow = false;
                           NewOrdersPlaced = true;
                        }//#
                  }
            }
            else if (LongTrade){   
                  if(UseClose){
                     fOrderCloseMarket(true,false);
                     iLots = NormalizeDouble(LotExponent*LastBuyLots,LotsDigits);
                  }           
                  else{
                     iLots = fGetLots(OP_BUY);
                  } 
                  if(UseAdd){
                     NumOfTrades = total;
                        if(iLots>0){//#
                           ticket = OpenPendingOrder(OP_BUY,iLots,Ask,slip,Bid,0,0,EAName+"-"+NumOfTrades,MagicNumber,0,Lime);
                           if(ticket<0){Print("Error: ",GetLastError()); return(0);}
                           LastBuyPrice = FindLastBuyPrice();
                           TradeNow = false;
                           NewOrdersPlaced = true;
                        }//#
                  }
            }
      }
  
      if (TradeNow && total<1){

         SellLimit = Bid;   
         BuyLimit = Ask;
   
            if(!ShortTrade && !LongTrade && Hour()==0)
            {
               NumOfTrades = total;
                  {
                     iLots = fGetLots(OP_SELL);
                        if(iLots>0){//#
                           ticket = OpenPendingOrder(OP_SELL,iLots,SellLimit,slip,SellLimit,0,Bid-TakeProfit*Point,EAName+"-"+NumOfTrades,MagicNumber,0,HotPink);
                           if(ticket<0){Print(iLots,"Error: ",GetLastError()); return(0);}
                           LastBuyPrice = FindLastBuyPrice();
                           NewOrdersPlaced = true;
                        }//#
                  }   
                        {
                     iLots = fGetLots(OP_BUY);
                        if(iLots>0){//#      
                           ticket = OpenPendingOrder(OP_BUY,iLots,BuyLimit,slip,BuyLimit,0,Ask+TakeProfit*Point,EAName+"-"+NumOfTrades,MagicNumber,0,Lime);
                              if(ticket<0){Print(iLots,"Error: ",GetLastError()); return(0);}
                                 LastSellPrice = FindLastSellPrice();
                                 NewOrdersPlaced = true;
                              }//#
                        }
                  }      
               if(ticket>0) expiration = CurTime()+MaxTradeOpenHours*60*60;
               TradeNow = false;
            }

//----------------------- CALCULATE AVERAGE OPENING PRICE
   total=CountTrades();
   AveragePrice=0;
   double Count = 0;
   for(cnt=OrdersTotal()-1;cnt>=0;cnt--)
   {
    OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
    if(OrderSymbol()!=Symbol()||OrderMagicNumber()!=MagicNumber)
     continue;
    if(OrderSymbol()==Symbol()&&OrderMagicNumber()==MagicNumber)
     if(OrderType()==OP_BUY || OrderType()==OP_SELL)  
      {
       AveragePrice=AveragePrice+OrderOpenPrice()*OrderLots();
       Count = Count + OrderLots();
      }
   }
   if(total > 0)
    AveragePrice=NormalizeDouble(AveragePrice/Count, Digits);

   
//----------------------- RECALCULATE STOPLOSS & PROFIT TARGET BASED ON AVERAGE OPENING PRICE
   if(NewOrdersPlaced)
   for(cnt=OrdersTotal()-1;cnt>=0;cnt--)
   {
    OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
    if(OrderSymbol()!=Symbol()||OrderMagicNumber()!=MagicNumber)
     continue;
    if(OrderSymbol()==Symbol()&&OrderMagicNumber()==MagicNumber)
     if(OrderType()==OP_BUY) // Calculate profit/stop target for long 
     {
      PriceTarget=AveragePrice+(TakeProfit*Point);
      BuyTarget = PriceTarget;
      Stopper=AveragePrice-(Stoploss*Point); 
//      Stopper=0; 
      flag = 1;
     }
    if(OrderSymbol()==Symbol()&&OrderMagicNumber()==MagicNumber)
     if(OrderType()==OP_SELL) // Calculate profit/stop target for short
     {
      PriceTarget=AveragePrice-(TakeProfit*Point);
      SellTarget = PriceTarget;
      Stopper=AveragePrice+(Stoploss*Point);  
//      Stopper=0; 
      flag = 1; 
     }
   }
//----------------------- IF NEEDED CHANGE ALL OPEN ORDERS TO NEWLY CALCULATED PROFIT TARGET    
  if(NewOrdersPlaced)
  if(flag==1)// check if average has really changed
  {   
   for(cnt=OrdersTotal()-1;cnt>=0;cnt--)
    {
//     PriceTarget=total;
     OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);            
     if(OrderSymbol()!=Symbol()||OrderMagicNumber()!=MagicNumber)
      continue;
     if(OrderSymbol()==Symbol()&&OrderMagicNumber()==MagicNumber)
//      OrderModify(OrderTicket(),0,Stopper,PriceTarget,0,Yellow);// set all positions to averaged levels
      OrderModify(OrderTicket(),AveragePrice,OrderStopLoss(),PriceTarget,0,Yellow);// set all positions to averaged levels
     NewOrdersPlaced = false;
    }
  }
}
double ND(double v){return(NormalizeDouble(v,Digits));}

int fOrderCloseMarket(bool aCloseBuy=true,bool aCloseSell=true){
   int tErr=0;
      for(int i=OrdersTotal()-1;i>=0;i--){
         if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){
            if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber){
               if(OrderType()==OP_BUY && aCloseBuy){
                  RefreshRates();
                     if(!IsTradeContextBusy()){
                        if(!OrderClose(OrderTicket(),OrderLots(),ND(Bid),5,CLR_NONE)){
                           Print("Error close BUY "+OrderTicket());//+" "+fMyErDesc(GetLastError())); 
                           tErr=-1;
                        }
                     }
                     else{
                        static int lt1=0;
                           if(lt1!=iTime(NULL,0,0)){
                              lt1=iTime(NULL,0,0);
                              Print("Need close BUY "+OrderTicket()+". Trade Context Busy");
                           }            
                        return(-2);
                     }   
               }
               if(OrderType()==OP_SELL && aCloseSell){
                  RefreshRates();
                     if(!IsTradeContextBusy()){                        
                        if(!OrderClose(OrderTicket(),OrderLots(),ND(Ask),5,CLR_NONE)){
                           Print("Error close SELL "+OrderTicket());//+" "+fMyErDesc(GetLastError())); 
                           tErr=-1;
                        }  
                     }
                     else{
                        static int lt2=0;
                           if(lt2!=iTime(NULL,0,0)){
                              lt2=iTime(NULL,0,0);
                              Print("Need close SELL "+OrderTicket()+". Trade Context Busy");
                           }            
                        return(-2);
                     }          
               }
            }
         }
      }
   return(tErr);
}  


double fGetLots(int aTradeType){
   double tLots;
      switch(MMType){
         case 0:
            tLots=Lots;
         break;
         case 1:
            tLots=NormalizeDouble(Lots*MathPow(LotExponent,NumOfTrades),LotsDigits);
         break;
         case 2:
            int LastClosedTime=0;
            tLots=Lots;
               for(int i=OrdersHistoryTotal()-1;i>=0;i--){
                  if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)){
                     if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber){
                        if(LastClosedTime<OrderCloseTime()){
                           LastClosedTime=OrderCloseTime();
                              if(OrderProfit()<0){
                                 tLots=NormalizeDouble(OrderLots()*LotExponent,LotsDigits);
                              }
                              else{
                                 tLots=Lots;
                              }
                        }
                     }
                  }
                  else{
                     return(-3);
                  }
               }
         break;
      }
      
      if(AccountFreeMarginCheck(Symbol(),aTradeType,tLots)<=0){
         return(-1);
      }
      if(GetLastError()==134){
         return(-2);
      }
   return(tLots);     
} 

int CountTrades()
{
 int count=0;
 int trade;
 for(trade=OrdersTotal()-1;trade>=0;trade--)
 {
  OrderSelect(trade,SELECT_BY_POS,MODE_TRADES);
  
  if(OrderSymbol()!=Symbol()||OrderMagicNumber()!=MagicNumber)
   continue;
   
  if(OrderSymbol()==Symbol()&&OrderMagicNumber()==MagicNumber)
  if(OrderType()==OP_SELL || OrderType()==OP_BUY)
   count++;
 }//for
 return(count);
}


void CloseThisSymbolAll()
{
 int trade;
 for(trade=OrdersTotal()-1;trade>=0;trade--)
 {
  OrderSelect(trade,SELECT_BY_POS,MODE_TRADES);

  if(OrderSymbol()!=Symbol())
   continue;
  if(OrderSymbol()==Symbol() && OrderMagicNumber()== MagicNumber)
  {
   if(OrderType()==OP_BUY)
    OrderClose(OrderTicket(),OrderLots(),Bid,slip,Blue);

   if(OrderType()==OP_SELL)
    OrderClose(OrderTicket(),OrderLots(),Ask,slip,Red);
  }
  Sleep(1000);
 }
}

int OpenPendingOrder(int pType,double pLots,double pLevel,int sp, double pr, int sl, int tp,string pComment,int pMagic,datetime pExpiration,color pColor)
{
  int ticket=0;
  int err=0;
  int c = 0;
  int NumberOfTries = 100;
  switch (pType)
  {
      case OP_BUYLIMIT:
         for(c = 0 ; c < NumberOfTries ; c++)
         {
            ticket=OrderSend(Symbol(),OP_BUYLIMIT,pLots,pLevel,sp,StopLong(pr,sl),TakeLong(pLevel,tp),pComment,pMagic,pExpiration,pColor);
            err=GetLastError();
            if(err==0)
            { 
               break;
            }
            else
            {
               if(err==4 || err==137 ||err==146 || err==136) //Busy errors
               {
                  Sleep(1000);
                  continue;
               }
               else //normal error
               {
                  break;
               }  
            }
         }   
         break;
      case OP_BUYSTOP:
         for(c = 0 ; c < NumberOfTries ; c++)
         {
            ticket=OrderSend(Symbol(),OP_BUYSTOP,pLots,pLevel,sp,StopLong(pr,sl),TakeLong(pLevel,tp),pComment,pMagic,pExpiration,pColor);
            err=GetLastError();
            if(err==0)
            { 
               break;
            }
            else
            {
               if(err==4 || err==137 ||err==146 || err==136) //Busy errors
               {
                  Sleep(5000);
                  continue;
               }
               else //normal error
               {
                  break;
               }  
            }
         } 
         break;
      case OP_BUY:
         for(c = 0 ; c < NumberOfTries ; c++)
         {  
            RefreshRates();
            ticket=OrderSend(Symbol(),OP_BUY,pLots,Ask,sp,StopLong(Bid,sl),TakeLong(Ask,tp),pComment,pMagic,pExpiration,pColor);
            err=GetLastError();
            if(err==0)
            { 
               break;
            }
            else
            {
               if(err==4 || err==137 ||err==146 || err==136) //Busy errors
               {
                  Sleep(5000);
                  continue;
               }
               else //normal error
               {
                  break;
               }  
            }
         } 
         break;
      case OP_SELLLIMIT:
         for(c = 0 ; c < NumberOfTries ; c++)
         {
            ticket=OrderSend(Symbol(),OP_SELLLIMIT,pLots,pLevel,sp,StopShort(pr,sl),TakeShort(pLevel,tp),pComment,pMagic,pExpiration,pColor);
            err=GetLastError();
            if(err==0)
            { 
               break;
            }
            else
            {
               if(err==4 || err==137 ||err==146 || err==136) //Busy errors
               {
                  Sleep(5000);
                  continue;
               }
               else //normal error
               {
                  break;
               }  
            }
         } 
         break;
      case OP_SELLSTOP:
         for(c = 0 ; c < NumberOfTries ; c++)
         {
            ticket=OrderSend(Symbol(),OP_SELLSTOP,pLots,pLevel,sp,StopShort(pr,sl),TakeShort(pLevel,tp),pComment,pMagic,pExpiration,pColor);
            err=GetLastError();
            if(err==0)
            { 
               break;
            }
            else
            {
               if(err==4 || err==137 ||err==146 || err==136) //Busy errors
               {
                  Sleep(5000);
                  continue;
               }
               else //normal error
               {
                  break;
               }  
            }
         } 
         break;
      case OP_SELL:
         for(c = 0 ; c < NumberOfTries ; c++)
         {
            ticket=OrderSend(Symbol(),OP_SELL,pLots,Bid,sp,StopShort(Ask,sl),TakeShort(Bid,tp),pComment,pMagic,pExpiration,pColor);
            err=GetLastError();
            if(err==0)
            { 
               break;
            }
            else
            {
               if(err==4 || err==137 ||err==146 || err==136) //Busy errors
               {
                  Sleep(5000);
                  continue;
               }
               else //normal error
               {
                  break;
               }  
            }
         } 
         break;
  } 
  
  return(ticket);
}  

double StopLong(double price,int stop)
{
 if(stop==0)
  return(0);
 else
  return(price-(stop*Point));
}

double StopShort(double price,int stop)
{
 if(stop==0)
  return(0);
 else
  return(price+(stop*Point));
}

double TakeLong(double price,int take)
{
 if(take==0)
  return(0);
 else
  return(price+(take*Point));
}

double TakeShort(double price,int take)
{
 if(take==0)
  return(0);
 else
  return(price-(take*Point));
}


double CalculateProfit()
{

   double Profit=0;
   for(cnt=OrdersTotal()-1;cnt>=0;cnt--)
   {
    OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
    if(OrderSymbol()!=Symbol()||OrderMagicNumber()!=MagicNumber)
     continue;
    if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber)
     if(OrderType()==OP_BUY || OrderType()==OP_SELL)  
      {
       Profit=Profit+OrderProfit();
      }
   }

  return(Profit);
}

void TrailingAlls(int start,int stop, double AvgPrice)
{
 int profit;
 double stoptrade;
 double stopcal;
 
 if(stop==0)
  return;
 
 int trade;
 for(trade=OrdersTotal()-1;trade>=0;trade--)
 {
  if(!OrderSelect(trade,SELECT_BY_POS,MODE_TRADES))
   continue;

  if(OrderSymbol()!=Symbol()||OrderMagicNumber()!=MagicNumber)
   continue;

  if(OrderSymbol()==Symbol()||OrderMagicNumber()==MagicNumber)
  {
   if(OrderType()==OP_BUY)
   {
    profit=NormalizeDouble((Bid-AvgPrice)/Point,0);
    if(profit<start)
     continue;
    stoptrade=OrderStopLoss();
    stopcal=Bid-(stop*Point);
    if(stoptrade==0||(stoptrade!=0&&stopcal>stoptrade))
//     OrderModify(OrderTicket(),OrderOpenPrice(),stopcal,OrderTakeProfit(),0,Blue);
     OrderModify(OrderTicket(),AvgPrice,stopcal,OrderTakeProfit(),0,Aqua);
   }//Long
  
   if(OrderType()==OP_SELL)
   {
    profit=NormalizeDouble((AvgPrice-Ask)/Point,0);
    if(profit<start)
     continue;
    stoptrade=OrderStopLoss();
    stopcal=Ask+(stop*Point);
    if(stoptrade==0||(stoptrade!=0&&stopcal<stoptrade))
//     OrderModify(OrderTicket(),OrderOpenPrice(),stopcal,OrderTakeProfit(),0,Red);
     OrderModify(OrderTicket(),AvgPrice,stopcal,OrderTakeProfit(),0,Red);
   }//Shrt
  }
  Sleep(1000);
 }//for
}




double AccountEquityHigh()
{
 static double AccountEquityHighAmt,PrevEquity;
  if(CountTrades()==0) AccountEquityHighAmt=AccountEquity();
   if(AccountEquityHighAmt < PrevEquity) AccountEquityHighAmt=PrevEquity;
   else AccountEquityHighAmt=AccountEquity();
  PrevEquity = AccountEquity();
 return(AccountEquityHighAmt);
}


double FindLastBuyPrice()
{
 double oldorderopenprice = 0, orderprice;
 int cnt, oldticketnumber = 0, ticketnumber;
 
 for(cnt=OrdersTotal()-1;cnt>=0;cnt--)
 {
  OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
  if(OrderSymbol()!=Symbol()||OrderMagicNumber()!=MagicNumber)
   continue;
  if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber && OrderType()==OP_BUY)  
  {
     ticketnumber = OrderTicket();
     if(ticketnumber>oldticketnumber)
     {
      orderprice=OrderOpenPrice();
      oldorderopenprice=orderprice;
      oldticketnumber=ticketnumber;
     }
  }
 }
 
  return(orderprice);
}

double FindLastSellPrice()
{
 double oldorderopenprice = 0, orderprice;
 int cnt, oldticketnumber = 0, ticketnumber;
 
 for(cnt=OrdersTotal()-1;cnt>=0;cnt--)
 {
  OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
  if(OrderSymbol()!=Symbol()||OrderMagicNumber()!=MagicNumber)
   continue;
  if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber && OrderType()==OP_SELL)  
  {
     ticketnumber = OrderTicket();
     if(ticketnumber>oldticketnumber)
     {
      orderprice=OrderOpenPrice();
      oldorderopenprice=orderprice;
      oldticketnumber=ticketnumber;
     }
  }
 }
 
  return(orderprice);
}



В результате получаем вот такую картинку:


Рис.2. Один из результатов оптимизации эксперта с начала 2009 года.

Догоним и перегоним господина Таниса!


Добавим функцию Мартингейла к советнику.

Возьмем простейший советник торгующий с фиксированными значениями стопов.


//+------------------------------------------------------------------+
//|                                                        WellX.mq4 |
//|                                            Copyright © 2011, AM2 |
//|                                      http://www.forexsystems.biz |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2011, AM2"
#property link      "http://www.forexsystems.biz"

#define MAGIC 20111010

extern double StopLoss   = 400;
extern double TakeProfit = 800;
extern double ADXPeriod  = 14;
extern double BBPeriod   = 20;
extern double BBDev      = 2;
extern int Level         = 30;
extern double Lots       = 1;

bool b=true, s=true;  

//+------------------------------------------------------------------+
int start()
  {
//---- go trading only for first tiks of new bar
   if(Volume[0]>1) return;  
//----   
   int p=0;    
//---- get Indicatorrs 
   double bbh=iBands(NULL,0,BBPeriod,BBDev,0,PRICE_CLOSE,MODE_UPPER,0);
   double bbl=iBands(NULL,0,BBPeriod,BBDev,0,PRICE_CLOSE,MODE_LOWER,0);
   double adx=iADX(NULL,0,ADXPeriod,PRICE_CLOSE,MODE_MAIN,0);
  
//----

   for (int i=0; i<OrdersTotal(); i++)
   {
     if (OrderSelect(i, SELECT_BY_POS)==true)
      {  
         if (OrderSymbol()!=Symbol() || OrderMagicNumber()!=MAGIC) continue;
         if (OrderType()==OP_BUY || OrderType()==OP_SELL) p++;       
      }   
   }  
//---- buy 
   if(adx<Level && Ask<bbl && b && p<1)  
     {
      OrderSend(Symbol(),OP_BUY,Lots,Ask,30,Ask-StopLoss*Point,Ask+TakeProfit*Point,"",MAGIC,0,Blue);
      b=false;
      s=true;  
     }        
//---- sell   
   if(adx<Level && Bid>bbh && s && p<1)  
     {
      OrderSend(Symbol(),OP_SELL,Lots,Bid,30,Bid+StopLoss*Point,Bid-TakeProfit*Point,"",MAGIC,0,Red );
      b=true; 
      s=false;
     }       
//----
   return(0);
  }
//+------------------------------------------------------------------+



Результат оптимизации эксперта с 2000-го года ниже:



Функция Мартингейла может иметь следующий вид:


//+------------------------------------------------------------------+
int LossCount = 0;
double LotsArray[]={0.1,0.2,0.4,0.8,1.6,3.2};

...

double Lots()
 {
   double Lot = Lots;
   int total = OrdersHistoryTotal();
   for (int i = 0; i < total; i++)
    {
      OrderSelect(i, SELECT_BY_POS, MODE_HISTORY);
      if (OrderSymbol() == Symbol() && OrderMagicNumber() == MAGIC)
       {
         if (OrderProfit() > 0)
          {
            Lot=LotsArray[0];
            LossCount = 0;    
          }         
          else
           {
            Lot=LotsArray[LossCount+1];
            LossCount++;
           }
       }
    }
   return(Lot);
}
//+------------------------------------------------------------------+


Остается только собрать все воедино:


//+------------------------------------------------------------------+
//|                                                        WellX.mq4 |
//|                                            Copyright © 2011, AM2 |
//|                                      http://www.forexsystems.biz |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2011, AM2"
#property link      "http://www.forexsystems.biz"

#define MAGIC 20111010

extern double StopLoss   = 400;
extern double TakeProfit = 800;
extern double ADXPeriod  = 14;
extern double BBPeriod   = 20;
extern double BBDev      = 2;
extern int Level         = 30;
extern double Lots       = 0.1;

int LossCount = 0;
double LotsArray[]={0.1,0.2,0.4,0.8,1.6,3.2};
bool b=true, s=true;

//+------------------------------------------------------------------+
int start()
  {
//---- go trading only for first tiks of new bar
   if(Volume[0]>1) return;  
//----   
   int p=0;    
//---- get Indicatorrs 
   double bbh=iBands(NULL,0,BBPeriod,BBDev,0,PRICE_CLOSE,MODE_UPPER,0);
   double bbl=iBands(NULL,0,BBPeriod,BBDev,0,PRICE_CLOSE,MODE_LOWER,0);
   double adx=iADX(NULL,0,ADXPeriod,PRICE_CLOSE,MODE_MAIN,0);
  
//----

   for (int i=0; i<OrdersTotal(); i++)
   {
     if (OrderSelect(i, SELECT_BY_POS)==true)
      {  
         if (OrderSymbol()!=Symbol() || OrderMagicNumber()!=MAGIC) continue;
         if (OrderType()==OP_BUY || OrderType()==OP_SELL) p++;       
      }   
   }  
//---- buy 
   if(adx<Level && Ask<bbl && b && p<1)  
     {
      OrderSend(Symbol(),OP_BUY,Lots(),Ask,30,Ask-StopLoss*Point,Ask+TakeProfit*Point,"",MAGIC,0,Blue);
      b=false;
      s=true;  
     }        
//---- sell   
   if(adx<Level && Bid>bbh && s && p<1)  
     {
      OrderSend(Symbol(),OP_SELL,Lots(),Bid,30,Bid+StopLoss*Point,Bid-TakeProfit*Point,"",MAGIC,0,Red );
      b=true; 
      s=false;
     }       
//----
   return(0);
  }
//+------------------------------------------------------------------+
double Lots()
 {
   double Lot = Lots;
   int total = OrdersHistoryTotal();
   for (int i = 0; i < total; i++)
    {
      OrderSelect(i, SELECT_BY_POS, MODE_HISTORY);
      if (OrderSymbol() == Symbol() && OrderMagicNumber() == MAGIC)
       {
         if (OrderProfit() > 0)
          {
            Lot=LotsArray[0];
            LossCount = 0;    
          }         
          else
           {
            Lot=LotsArray[LossCount+1];
            LossCount++;
           }
       }
    }
   return(Lot);
}
//+------------------------------------------------------------------+


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



Результат с того же 2000-го года.

Дерзайте, юные умы!


Эффективное использование MagicNumber ордеров для упрощения анализа при торговле советниками.

Вступление

Итак, сегодня поговорим о том, как мы используем MagicNumber (далее — Magic) в анализе своих счетов. Для анализа используем Myfxbook.

При тестировании нескольких советников на одном счете важно не забывать использовать разные Magic у ордеров каждого отдельного эксперта и каждой его вариации. Мы решили пойти дальше, и сделать Magic более эффективными. Раньше, при потолочном выборе Magic надо было посмотреть, нет ли такого же Magic у одного из уже торгующих экспертов. А при пользовательском анализе на Myfxbook вообще приходилось то и дело глядеть в МетаТрейдер для понимания, какой Magic какому эксперту принадлежит. Теперь же каждая цифра MagicNumber имеет свой смысл*улыбается*

( Читать дальше )


Как прикрутить к советнику трейлингстоп и вывод в безубыток?

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

Чтобы проделать необходимые нам операции воспользуемся готовыми функциями трейлингстопа и БУ.

( Читать дальше )


Как написать простейший советник на MQL4?

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

Для начала сформулируем правила открытия и закрытия позиций.

( Читать дальше )