Предлагаю написать советник по стратегии Anatoly74

Предлагаю написать советник по стратегии Anatoly74

anatoly74.opentraders.ru/14283.html#comment86256

Набросал небольшое ТЗ.

Идентификацию тренда будем производить по лентам Боллинджера. Так легче оптимизировать. При резкой смене тренда ленты раширяются на расстояние Delta, тогда покупаем или продаем с рынка в направлении тренда и набрасываем

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


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

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

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

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



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


MeasureFIBO - добавляем второй инидкатор Фибоначчи с предустановленными нестандартными значениями

Задача была поставлена от tibi: дать ему второй индикатор Фибо, в котором можно было бы предустановить значения, не меняющиеся после удаления инидкатора с графика.
Задача усложнилась тем, что значения Фибы у tibi секретные *ninja* , а значит надо научить его самостоятельно поставить нужные значения в индикатор так, чтобы они потом сохранялись.

Ок,

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


Обновление платформы MetaTrader 4
[*]



Уважаемые участники форума!

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

Большая часть изменений коснулась языка программирования MQL4. Это позволило в несколько раз увеличить скорость выполнения и повысить

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


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

Подобный анализ статистики рынка с сайта 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 находится вот здесь
Ниже представлена реализация второй части *улыбается*

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


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

Воспользуемся для нашего усреднителя готовой торговой системой одного из успешных управляющих на рынке 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-го года.

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


Решение: ошибка Cannot open file в MT

Иногда при попытке запустить даже стандартный скрипт из поставки MetaTrader (например, period_converter) пользователь сталкивается с ситуацией, что скрипт не работает. Неделю или месяц назад работал, а сегодня нет.

В таких случаях нужно посмотреть логи на закладке «Эксперты». Если там обнаружите ошибку:

2011.09.08 10:25:35	Cannot open file 'C:\Program Files\MetaTrader\experts\scripts\period_converter.ex4' on the EURUSD,H1


то проблема решается просто

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


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

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

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

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


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

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

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

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


Используйте RefreshRates()

Уважаемые разработчики!

Опыт Тестовой Лаборатории показал, что многие разработчики не используют в коде своих советников функцию RefreshRates(). Совершенно напрасно! Игнорирование этой функции может привести к пропуску сделок.

Эксперты работают с копией исторических данных. Когда вычисления производятся в течение долгого времени, эти данные могут устареть, в логах появляются записи «Old Tick».



В результате нарушается работа советника. В Лаборатории были случаи, когда советник перестает полностью функционировать до перезагрузки. Использование функции RefreshRates() в большинстве случаев решает проблему.


Тестирование советника, торгующего на основе средней скользящей "Diaspar"





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

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


Начать торговлю с Альпари