Прошу помощи с советником!

 

Всем доброго время суток!


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



#property copyright "http://www.forexfactory.com/showthread.php?t=14073"
#property link      "http://www.gnu.org/copyleft/gpl.html"
// 
// This is a Metatrader 4 expert trying to follow the BAT method
// Copyright (C) 2007 fukinagashi
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details:
// "http://www.gnu.org/copyleft/gpl.html"
// 
// Link to method: http://www.forexfactory.com/showthread.php?t=12808
//
// Link to thread for this expert: http://www.forexfactory.com/showthread.php?t=14073
//
#define MaxTest 250
#define MagicNumber 666666
#define FractalOfLevel 2

#include <OrderReliable.mqh>

#define ExpertName "BAT expert v 1.5" 
extern int Slipage=3;
extern bool MultipleFibos=false;

extern bool debug=false;

extern double RiskPercent=0;
extern double Lot=1;

extern bool Use_BATATR_Indicator=true;
extern int ATRPeriod=5;
extern double Factor=4;

extern bool UseAlert=false;
extern bool UseMail=false;

extern int Timeout=900;

int LastSignal;

extern double Trade1VolumeFactor=1;
extern double Trade2VolumeFactor=1;
extern double Trade3VolumeFactor=2;


datetime bartime = 0;
datetime LastTrade;
double Upper, Lower, UpperPrevious, LowerPrevious;
int RecentLowPos, RecentHighPos, total;
double Recentlow, Recenthigh;
double Entry, Diff;
int reg=0;
bool NoLongLimitOrders=true;
bool NoShortLimitOrders=true;

int deinit() {
   for (int i=1;i<=100;i++) {
      ObjectDelete("Fibo_"+i);
   }
}

int init() {
  deinit();
}


int start() {
   string Message;
  
   UpperPrevious=Upper;
   LowerPrevious=Lower;
   if (!Use_BATATR_Indicator) {
     BATATR(ATRPeriod, Factor);
   } else {
    Upper=NormalizeDouble(iCustom(NULL,0,"BAT ATR v1",1000,ATRPeriod,Factor,1,1),Digits);
    Lower=NormalizeDouble(iCustom(NULL,0,"BAT ATR v1",1000,ATRPeriod,Factor,0,1),Digits);
   }
   if (Upper==0 && Lower==0) {
      Lower=LowerPrevious;
      Upper=UpperPrevious;
   }


   if (debug) {
      if (bartime != Time[0]) {
         Print ("Time since last Trade: " + (TimeCurrent()-LastTrade) + " Upper: " + Upper + " Lower: " + Lower + " Recenthigh: " + Recenthigh + " Recentlow: " + Recentlow + " Entry: " + Entry + " Diff: " + Diff);
         bartime = Time[0]; // a new bar, so record its open time.   
      }
   }

   for(int i=OrdersTotal(); i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) {
         if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol()) {
            if(OrderType()==OP_BUY  && (OrderStopLoss()<Lower || OrderStopLoss()==0) && Lower!=EMPTY_VALUE) {
               Print("Change Order: " + OrderTicket());
               OrderModifyReliable(OrderTicket(),OrderOpenPrice(),Lower,OrderTakeProfit(),0,Blue);
            } else if(OrderType()==OP_SELL && (OrderStopLoss()>Upper || OrderStopLoss()==0) && Upper!=EMPTY_VALUE) {
               Print("Change Order: " + OrderTicket());
               OrderModifyReliable(OrderTicket(),OrderOpenPrice(),Upper,OrderTakeProfit(),0,Blue);
            }
         }
      }
   }

  total=OrdersTotal();
   for(i=total; i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) {
         if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol()) {
            if(OrderType()==OP_BUYLIMIT) {
               if (Entry==0) {
                  Entry=OrderTakeProfit();
                  if (debug) Print("New value for entry: " + Entry);
               }
               if (Diff==0) {
                  Diff=Entry-OrderStopLoss()+10*Point;
                  if (debug) Print("New value for Diff: " + Diff);
               }
              if (Ask>=Entry+Diff*0.618) {
                Print("Price passed 61.8%, closing LimitOrder " + OrderTicket());
                NoLongLimitOrders=true;
                OrderDelete(OrderTicket());
                LastTrade=TimeCurrent();
              }
            }
         }
    }
   } 

   total=OrdersTotal();
   for(i=total; i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) {
         if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol()) {
            if(OrderType()==OP_SELLLIMIT) {
              if (Entry==0) {
               Entry=OrderTakeProfit();
               if (debug) Print("New value for entry: " + Entry);
             }
              if (Diff==0) {
               Diff=OrderStopLoss()-10*Point-Entry;
               if (debug) Print("New value for Diff: " + Diff);
              }
              if (Bid<=Entry-Diff*0.618) {
                Print("Price passed 61.8%, closing LimitOrder " + OrderTicket());
                NoShortLimitOrders=true;
                OrderDelete(OrderTicket());
                LastTrade=TimeCurrent();
              }
            }
         }
    }
   } 


   if (Realtotal(MagicNumber, OP_BUY)==0 && Ask>=Upper && High[1]<=Upper) {
      total=OrdersTotal();
      for(i=total; i>=0; i--) {
         if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) {
            if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol()) {
               if(OrderType()==OP_SELL)      {
                  OrderCloseReliable(OrderTicket(), OrderLots(), Ask, Slipage);
                  LastTrade=TimeCurrent();
               }
                  if(OrderType()==OP_SELLLIMIT) {
                  OrderDelete(OrderTicket());
                  LastTrade=TimeCurrent();
               }
               
            }
         }
      }
      Entry=Ask;
      RecentLowPos=Recent_Low(0, 2);
      Recentlow=Low[RecentLowPos];
      Diff=Entry-Recentlow;

      if (!IsTesting()) DrawFibo(Time[0], Entry, Time[RecentLowPos], Recentlow);

        Message="BAT ATR: LONG " + Symbol() + "@"+ Ask + " SL:" + Recentlow;
        if (LastSignal!=1) {
         if (debug) Print(Message);
         if (UseAlert) Alert(Message);
         if (UseMail) SendMail(Message, Message);
         LastSignal=1;
        }
        NoLongLimitOrders=false;
        NoShortLimitOrders=true;
        if (TimeCurrent()-LastTrade>Timeout) {
         OrderSendReliable(Symbol(),OP_BUY,       CalculateVolume()*Trade1VolumeFactor, Ask, Slipage,Entry-Diff*0.618*Point,0,ExpertName + "_T1",MagicNumber, 0,Green);
         LastTrade=TimeCurrent();         
        }
   }

   if (Realtotal(MagicNumber, OP_SELL)==0 && Bid<=Lower && Low[1]>=Lower) {
      total=OrdersTotal();
      for(i=total; i>=0; i--) {
         if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) {
            if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol()) {
               if(OrderType()==OP_BUY)      {
                  OrderCloseReliable(OrderTicket(), OrderLots(), Bid,Slipage);
                  LastTrade=TimeCurrent();
               }
               if(OrderType()==OP_BUYLIMIT)  {
                  OrderDelete(OrderTicket());
                  LastTrade=TimeCurrent();
               }
               
            }
         }
      }
      Entry=Bid;
      RecentHighPos=Recent_High(0, 2);
      Recenthigh=High[RecentHighPos];
      Diff=Recenthigh-Entry;

      if (!IsTesting()) DrawFibo(Time[0], Entry, Time[RecentHighPos], Recenthigh);
        Message="BAT ATR: SHORT " + Symbol() + "@"+ Bid + " SL:" + Recenthigh;
        if (LastSignal!=-1) {
         if (debug) Print(Message);
         if (UseAlert) Alert(Message);
         if (UseMail) SendMail(Message, Message);
         LastSignal=-1;
        }
        
        NoLongLimitOrders=true;
        NoShortLimitOrders=false;
        if (TimeCurrent()-LastTrade>Timeout) {
         OrderSendReliable(Symbol(),OP_SELL,      CalculateVolume()*Trade1VolumeFactor,  Bid, Slipage,Entry+Diff*0.618*Point,0,ExpertName + "_T1",MagicNumber,0,Red);
         LastTrade=TimeCurrent();
       }
   }
}

int Recent_Low(int von, int FoL) {
 for(int shift=von+FoL;shift<von+MaxTest;shift++) {
     int failed=0;
     for(int i=FoL;i>0;i--) {
        if(Low[shift+i]<=Low[shift]) failed=failed+1;
        if(Low[shift-i]<=Low[shift]) failed=failed+1;
     }
     if (failed==0) return(shift);
 }
 Print("failed to find recent low");
 return(-1);
}


int Recent_High(int von, int FoL) {
 for(int shift=von+FoL;shift<von+MaxTest;shift++) {
     int failed=0;
     for(int i=FoL;i>0;i--) {
        if(High[shift+i]>=High[shift]) failed=failed+1;
        if(High[shift-i]>=High[shift]) failed=failed+1;
     }
     if (failed==0) return(shift);
 }
 Print("failed to find recent high");
 return(-1);
}

bool DrawFibo(datetime T1, double P1, datetime T2, double P2) {
  if (MultipleFibos) {
    reg=reg+1;
   } else {
    ObjectDelete("Fibo"+reg);
   }

   ObjectCreate("Fibo_"+reg, OBJ_FIBO, 0, T1, P1, T2, P2);
   ObjectSet("Fibo_"+reg, OBJPROP_COLOR, Black);
   ObjectSet("Fibo_"+reg, OBJPROP_WIDTH, 2);

   ObjectSet ("Fibo_"+reg, OBJPROP_LEVELCOLOR, Black);
   //ObjectSet ("Fibo_"+reg, OBJPROP_LEVELCOLOR, Color2[n]);
   ObjectSet ("Fibo_"+reg, OBJPROP_STYLE, 2);
   ObjectSet ("Fibo_"+reg, OBJPROP_LEVELSTYLE, 2);
   ObjectSet ("Fibo_"+reg, OBJPROP_FIBOLEVELS, 7);
   ObjectSet ("Fibo_"+reg, OBJPROP_FIRSTLEVEL+0, 0);
   ObjectSet ("Fibo_"+reg, OBJPROP_FIRSTLEVEL+1, 0.236);
   ObjectSet ("Fibo_"+reg, OBJPROP_FIRSTLEVEL+2, 0.382);
   ObjectSet ("Fibo_"+reg, OBJPROP_FIRSTLEVEL+3, 0.618);
   ObjectSet ("Fibo_"+reg, OBJPROP_FIRSTLEVEL+4, 1.0);
   ObjectSet ("Fibo_"+reg, OBJPROP_FIRSTLEVEL+5, 1.236);
   ObjectSet ("Fibo_"+reg, OBJPROP_FIRSTLEVEL+6, 1.382);
   ObjectSet ("Fibo_"+reg, OBJPROP_FIRSTLEVEL+7, 1.618);
   ObjectSetFiboDescription ("Fibo_"+reg, 0, " Swing     %$");
   ObjectSetFiboDescription ("Fibo_"+reg, 1, "  23.6     %$");
   ObjectSetFiboDescription ("Fibo_"+reg, 2, "  38.2     %$");
   ObjectSetFiboDescription ("Fibo_"+reg, 3, "  61.8     %$");
   ObjectSetFiboDescription ("Fibo_"+reg, 4, " Enter     %$");
   ObjectSetFiboDescription ("Fibo_"+reg, 5, " 123.6     %$");
   ObjectSetFiboDescription ("Fibo_"+reg, 6, " 138.2     %$");
   ObjectSetFiboDescription ("Fibo_"+reg, 7, " 161.8     %$");
}

int Realtotal(int MN, int OType) {
  int realtotal=0;
  if(OrdersTotal()>0)  {
     for(int cnt=0;cnt<=OrdersTotal();cnt++) {
        OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
        if(OrderMagicNumber()==MN && OrderSymbol()==Symbol() &&
OrderType()==OType) realtotal=realtotal+1;
     }
  }
  return(realtotal);
}

int BATATR(int ATRP, double Fac) {
  int limit=MaxTest;
  double PrevUp, PrevDn;
  double CurrUp, CurrDn;
  double PriceLvl;
  double LvlUp = 0;
  double LvlDn = 1000;
  int Dir = 1;
  int InitDir=0;
  for(int i=limit; i>=0; i--) {
    PriceLvl = Close[i];
    if(InitDir == 0) {
      CurrUp=Close[i] - (iATR(NULL,0,ATRPeriod,i) * Factor);
      PrevUp=Close[i-1] - (iATR(NULL,0,ATRPeriod,i-1) * Factor);
      CurrDn=Close[i] + (iATR(NULL,0,ATRPeriod,i) * Factor);
      PrevDn=Close[i-1] + (iATR(NULL,0,ATRPeriod,i-1) * Factor);

      if (CurrUp > PrevUp) Dir = 1;
      LvlUp = CurrUp;
      if (CurrDn < PrevDn) Dir = -1;
      LvlDn = CurrDn;
      InitDir = 1;
    }

    CurrUp=PriceLvl - (iATR(NULL,0,ATRP,i) * Fac);
    CurrDn=PriceLvl + (iATR(NULL,0,ATRP,i) * Fac);

    if (Dir == 1) {
      if (CurrUp > LvlUp) {
        Lower = CurrUp;
        LvlUp = CurrUp;
      } else {
        Lower = LvlUp;
      }
      Upper = EMPTY_VALUE;

      if (Low[i] < Lower) {
        Dir = -1;
        LvlDn = 1000;
      }
    }

    if (Dir == -1) {
      if (CurrDn < LvlDn) {
        Upper = CurrDn;
        LvlDn = CurrDn;
      } else {
        Upper = LvlDn;
      }
      Lower = EMPTY_VALUE;

      if (High[i] > Upper) {
        Dir = 1;
        LvlUp = 0;
      }
    }
  }
}

double CalculateVolume() {
   if (RiskPercent==0) {
      return(Lot);
   } else {
      double lot_min =MarketInfo(Symbol(),MODE_MINLOT);
      double lot_max =MarketInfo(Symbol(),MODE_MAXLOT);
      double lot_step=MarketInfo(Symbol(),MODE_LOTSTEP);
      double vol=NormalizeDouble(AccountBalance()*RiskPercent/AccountLeverage()/1000.0,2);
      vol=NormalizeDouble(vol/lot_step,0)*lot_step;
      if(vol<lot_min) vol=lot_min;
      if(vol>lot_max) vol=lot_max;
      return(vol);
   }
}
Файлы:
1.png  14 kb
 

Нужно смотреть функцию OrderSendReliable(), которая находится во включаемом файле 

OrderReliable.mqh
 
Ihor Herasko #:

Нужно смотреть функцию OrderSendReliable(), которая находится во включаемом файле 

Благодарю за ответ, есть такой файл, нашёл такую функцию)) ещё бы разобраться что поменять нужно)

 
Код в сообщение не влез
Файлы:
 

Да, проблема в неправильном расчете Stop Loss при открытии ордера.

Так, в строках 195 и 234 (открытие Buy и Sell соответственно) главного  файла эксперта значение переменной Diff уже выражено в категории цены, а не в пунктах, но его все равно умножают на Point. Нужно убрать это умножение. Тогда советник начинает открывать ордера.

Но остается еще одна ошибка: лишние перемещения стопа, когда он по факту не изменился. Такие перемещения приводят к ошибке 1. Чтобы ее не было, нужно в файле OrderReliable.mqh блок кода, начинающийся со строки 486:

        if (false) {
                 // This section is 'nulled out', because
                 // it would have to involve an 'OrderSelect()' to obtain
                 // the symbol string, and that would change the global context of the
                 // existing OrderSelect, and hence would not be a drop-in replacement
                 // for OrderModify().
                 //
                 // See OrderModifyReliableSymbol() where the user passes in the Symbol 
                 // manually.
                 
                 OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES);
                 string symbol = OrderSymbol();
                 int digits = MarketInfo(symbol,MODE_DIGITS);
                 if (digits > 0) {
                         price = NormalizeDouble(price,digits);
                         stoploss = NormalizeDouble(stoploss,digits);
                         takeprofit = NormalizeDouble(takeprofit,digits); 
                 }
                 
                 if (stoploss != 0) OrderReliable_EnsureValidStop(symbol,price,stoploss); 
        }

заменить на такой:

                 OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES);
                 string symbol = OrderSymbol();
                 int digits = MarketInfo(symbol,MODE_DIGITS);
                 if (digits > 0) {
                         price = NormalizeDouble(price,digits);
                         stoploss = NormalizeDouble(stoploss,digits);
                         takeprofit = NormalizeDouble(takeprofit,digits); 
                 }
                 if (fabs(stoploss - OrderStopLoss()) < Point() / 10.0 && fabs(takeprofit - OrderTakeProfit()) < Point / 10.0)
                   return true;
                 
                 if (stoploss != 0) OrderReliable_EnsureValidStop(symbol,price,stoploss); 
        
 
Ihor Herasko #:

Да, проблема в неправильном расчете Stop Loss при открытии ордера.

Так, в строках 195 и 234 (открытие Buy и Sell соответственно) главного  файла эксперта значение переменной Diff уже выражено в категории цены, а не в пунктах, но его все равно умножают на Point. Нужно убрать это умножение. Тогда советник начинает открывать ордера.

Но остается еще одна ошибка: лишние перемещения стопа, когда он по факту не изменился. Такие перемещения приводят к ошибке 1. Чтобы ее не было, нужно в файле OrderReliable.mqh блок кода, начинающийся со строки 486:

заменить на такой:

Благодарю, всё заработало!!
 

Всем профита!

Надо к имеющемуся условию

if(mEquityNetto <= mLevelCloseRise)

добавить

 а так же mLevelCloseRise не меньше mMaxBalance

помогите правильно прописать

 
Shoker #:

Всем профита!

Надо к имеющемуся условию

добавить

помогите правильно прописать

Если только по имеющимся в Вашем посте данным, то так:

if (mEquityNetto <= mLevelCloseRise && mLevelCloseRise >= mMaxBalance)

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

 
Ihor Herasko #:

Если только по имеющимся в Вашем посте данным, то так:

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

спасибо, проверю.
Просто нюанс в том, что бы код работал только при дополнительном условии.
Причина обращения: