создал советника по пересечению 2 EMA, нужен совет

 

Привет!

Я новичок в mql 4 и я сделал простой 2 EMA кросс-советник, который я тестировал на демо-счете, но немного боюсь получить его на реальном.

Тестирование его на малых лотах в масштабе 1h займет слишком много времени, а тестировать его на минутных масштабах дорого, потому что минимальный лот у моего брокера составляет около 7 usd.

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

Этот советник предназначен для торговли на рынке Bitcoin/USD, который чрезвычайно волатилен (цена может колебаться на + - 30% в день), поэтому стоп-лосс и тейк-профит выставляются не в пунктах, а в процентах от бида или аск.

Переменные и прочее:

#property copyright "me"
#property link      "killnosock.net"
extern int SlowEma = 21;
extern int FastEma = 10;
extern int MaxRisk = 100;// % of Depo to be traded per order
extern int  TakeProfit=100;
extern int  StopLoss=100;
extern int Slippage = 10;

int LastBars = 0;

int init(){return(0);}
int deinit() {return(0);}

Эта функция определяет размер лота, в соответствии с % от депо, который разрешено использовать на ордер (int Risk).

double GetLot(int Risk)
{double Free    =AccountFreeMargin();
 double One_Lot =MarketInfo(Symbol(),MODE_MARGINREQUIRED);
 double Min_Lot =MarketInfo(Symbol(),MODE_MINLOT);
 double Max_Lot =MarketInfo(Symbol(),MODE_MAXLOT);
 double Step    =MarketInfo(Symbol(),MODE_LOTSTEP);
 double Lot     =MathFloor(Free*Risk/100/One_Lot/Step)*Step;
 if(Lot<Min_Lot) Lot=Min_Lot;
 if(Lot>Max_Lot) Lot=Max_Lot;
 if(Lot*One_Lot>Free) {
 Alert(" free= ", AccountFreeMargin()," for one lot= ", MarketInfo(Symbol(),MODE_MARGINREQUIRED)," lot= ", Lot);
 return(0.0);}
return(Lot);}

Это функция, которая открывает новый ордер, Cmd - buy или sell.

int NewOrder(int Cmd,double Lot)
{double TP=0; //takeprofit
 double SL=0; //stoploss
 double PR=0; //price
 color clr = CLR_NONE;
 while(!IsTradeAllowed()) Sleep(10);
 RefreshRates();
 if(Cmd==OP_BUY)
   {PR=Ask;
    if(TakeProfit>0) TP=Ask + Ask*TakeProfit/100;
    if(StopLoss>0) SL=Ask - Ask*StopLoss/100;
    if(SL<0) SL = 0;
    if(TP<0) TP = 0;
    clr = Green;}
 if(Cmd==OP_SELL)
   {PR=Bid;
    if(TakeProfit>0) TP=Bid - Bid*TakeProfit/100;
    if(StopLoss>0) SL=Bid + Bid*StopLoss/100;
    if(SL<0) SL = 0;
    if(TP<0) TP = 0;
    clr = Red;}
 int tic=OrderSend(Symbol(),Cmd,Lot,PR,Slippage,SL,TP,"",0,0,clr);
 if(tic<0) Print("Open order error: ",GetLastError());
return(tic);}

Здесь я закрываю 1 ордер или закрываю все ордера:

//CloseOrder
void CloseOrder()
{double PR=0;
 while(!IsTradeAllowed()) Sleep(10);
 RefreshRates();
 if(OrderType()==OP_BUY)  PR=Bid;
 if(OrderType()==OP_SELL) PR=Ask;
 if(!OrderClose(OrderTicket(),OrderLots(),PR,Slippage,CLR_NONE))
   Print("Order close error: ",GetLastError());
return;}
//Close all Orders
void CloseAllOrders()
{
  for(int i=OrdersTotal()-1;i>=0;i--)
   if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
     {
      CloseOrder();
     }
return;}

Эта функция используется для расчета разницы быстрой и медленной ЕМА (быстрая ЕМА - медленная ЕМА):

double EmaDiff(int shift)
   {
      double difference;
      difference = iMA(Symbol(),0,FastEma,0,MODE_EMA,PRICE_CLOSE,shift)
                 - iMA(Symbol(),0,SlowEma,0,MODE_EMA,PRICE_CLOSE,shift);
      return(difference);
   }

А вот и основная часть:

int start()
  {
double Lot;
    // check if new bar opened
    if (LastBars == Bars) return(0);
    else LastBars = Bars;
      {         
         if ((EmaDiff(1) > 0) && (EmaDiff(2) < 0))
            {
               CloseAllOrders();
               Lot = GetLot(MaxRisk);
               NewOrder(OP_BUY,Lot);
            }
            
         if ((EmaDiff(2) > 0) && (EmaDiff(1) < 0))
            {
               CloseAllOrders();
               Lot = GetLot(MaxRisk);
               NewOrder(OP_SELL,Lot);
            }                    
      }
   return(0);
  }

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

 
 //CloseOrder
void CloseOrder()
{double PR=0;
 while(!IsTradeAllowed()) Sleep(10);
 RefreshRates();
 if(OrderType()==OP_BUY)  PR=Bid;
 if(OrderType()==OP_SELL) PR=Ask;
 if(!OrderClose(OrderTicket(),OrderLots(),PR,Slippage,CLR_NONE))
   Print("Order close error: ",GetLastError());
return;}



//Close all Orders
void CloseAllOrders()
{
  for(int i=OrdersTotal()-1;i>=0;i--)
   if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
     {
      CloseOrder();
     }
return;}

не проверяет символ не проверяет magicnumber....

тогда что произойдет, если использовать его в реальном времени с разными советниками на нем?

 
deVries:

не проверяет символ не проверяет magicnumber....

тогда что произойдет, если использовать его в реальном времени с разными советниками на нем?


Вы имеете в виду запуск двух советников с одного счета?
 
prupru:

Вы имеете в виду запуск двух советников с одного счета?
Два советника или один советник и сделки, выставляемые вручную ... или просто сделки, выставляемые вручную.
 
prupru:

Привет!

Я новичок в mql 4 и я сделал простой кросс-советник 2 EMA, который я тестировал на демо-счете, но немного боюсь получить его на реальном счете.

Тестирование его на малых лотах в масштабе 1h займет слишком много времени, а тестировать его на минутных масштабах дорого, потому что минимальный лот у моего брокера составляет около 7 usd.

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

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

if(tic < 0) Print("Open order error: ", GetLastError());

... это хорошо, но вам нужно больше, какие переменные вам нужно распечатать, чтобы вы могли определить причину любой ошибки, которую вы получите? Когда вы определите, что вам может понадобиться, добавьте их все в вызов Print(), убедившись, что вы используете правильное количество десятичных дробей (DoubeToStr(value, digits)) для любых двойных переменных, таких как Ask, Bid и т.д.

 
RaptorUK:

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

Извините, но я не понял эту часть. Единственное, что я понял, это то, что мне нужно добавить как можно больше переменных к вызову Print(). Понял, спасибо.

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

Есть ли еще что-нибудь, что нужно исправить?

 

конечно, есть

    // check if new bar opened
    if (LastBars == Bars) return(0);
    else LastBars = Bars;

предположим, что у вас уже есть максимум баров (есть предел).....

 
deVries:

конечно, есть

предположим, что у вас уже есть максимум баров (есть предел).....


Хорошо, тогда как мне лучше поймать момент, когда открывается новая свеча?
 
prupru:

Хорошо, так как же мне лучше поймать момент, когда открывается новая свеча?


проверить время последнего бара Time[0]

найдите NewBar и вы найдете несколько примеров

 
deVries:


проверить время последнего бара Time[0]

выполните поиск по NewBar и вы найдете несколько примеров


Спасибо, я нашел это https://www.mql5.com/en/code/10370

 
 if(Cmd==OP_BUY)
   {PR=Ask;
    if(TakeProfit>0) TP=Ask + Ask*TakeProfit/100;
    if(StopLoss>0) SL=Ask - Ask*StopLoss/100;
    if(SL<0) SL = 0;
    if(TP<0) TP = 0;
    clr = Green;}

Я не думаю, что это правильно

как вы получаете 100 пунктов тейкпрофита и 150 пунктов стоплосса?

обновить смотрите " так стоп лосс и тейк профит не в пунктах, а в процентах от бида или аска."

все равно, как вы получаете действительную цену таким образом... если ваш символ имеет 5 цифр, результат будет часто на 2 цифры больше.

Причина обращения: