Andrju81
Андрей

 
Уровень 18

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


Группа "Стол заказов MQL"

Рейтинг 2081



РЕКОМЕНДУЮ



Написать функцию расчета (оптимизации) лота для советника МТ4...

Здравствуйте, Андрей!

Просьба написать функцию расчета (оптимизации) лота для советника МТ4.

Принцип расчета (оптимизации) лота заключается в следующем:

1) К примеру, при депозите 1000$ стартовый лот будет равен 0.10, далее депозит увеличивается до 2000$ — лот будет равен 0.20, до 3000$0.30 лота и так далее, т.е. на каждую полную 1000$ баланса лот увеличивается на 0.10.

2) Если баланс уменьшится хотя бы на одну единицу баланса от полной тысячи, то лот уменьшается до размера остатка полной тысячи. Пример: Баланс уменьшился с 3000$ до 2999$, лот соответственно меняется с 0.30 на 0.20 и так далее.

3) Если баланс становится меньше 1000$, то для расчета рабочего лота команда передается на другую функцию, которая рассчитывает лот процент от баланса, я предпочитаю такую:
double MMLot()
   {
    double LotSize=MarketInfo(Symbol(),MODE_LOTSIZE);
    double Min_Lot=MarketInfo(Symbol(),MODE_MINLOT);
    double Max_Lot=MaxLot;                        //Входной параметр советника "MaxLot"
    double MMlot=AccountBalance()*MM/LotSize;     //Входной параметр советника "MM", т.е. Мани-менеджмент (%) от баланса
    if(MMlot<=Min_Lot) MMlot=Min_Lot;
    if(MMlot>=Max_Lot) MMlot=Max_Lot;
    Print("Рабочий лот для ",Symbol()," (",MM,"%) = ",MMlot);
    return(MMlot);
   }

Входные параметры для советника и соответственно для работы функций можно обозначить следующим образом:

extern bool       MMonoff           = true;        //Мани-менеджмент вкл/выкл
extern double     MM                = 5;           //Мани-менеджмент (%) от баланса
extern double     Lot               = 0.10;        //Начальный лот
extern bool       ProgressiveLot    = true;        //Прогрессивный лот от баланса вкл/выкл
extern double     InitialLot        = 0.10;        //Прогрессия лота на каждые "ProgressiveBalans" +0.10 лот
extern double     ProgressiveBalans = 1000;        //Шаг баланса 
extern double     MaxLot            = 10;          //Максимальный лот

Или как Вам будет удобно.
  • 0
  • Просмотров: 5878
  • 23 января 2016, 04:33
  • Andrju81
Понравилcя материал? Не забудьте поставить плюс и поделиться в социальной сети!

Вступите в группу "Стол заказов MQL", чтобы следить за обновлениями
ПРИСОЕДИНИТЬСЯ К ГРУППЕ
присоединиться
  Предыдущая запись в группе
Советник М6
Следующая запись в группе  
Индикатор временных зон v.2
22 января 2016
23 января 2016

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

+
0
В понедельник займусь.
avatar

  34  AM2 Сообщений: 15869 - Андрей

  • 23 января 2016, 13:52
+
0
О.К. Благодарю!
avatar

  18  Andrju81 Автор Сообщений: 245 - Андрей

  • 23 января 2016, 14:34
+
0
Пункты 1 и 3 просто реализуются а вот 2 это нужно долго репу чесать. Вы составляли алгоритм для п.2, можно взглянуть?
avatar

  34  AM2 Сообщений: 15869 - Андрей

  • 24 января 2016, 05:48
+
0
Для отладки функции написал простой советник.
На рисунке видим предыдущий баланс 5220 сейчас 4942.
Лот уменьшился на 0.1



Вот функция:


double Lot()
  {
   double LotSize=MarketInfo(Symbol(),MODE_LOTSIZE);
   double MinLot=MarketInfo(Symbol(),MODE_MINLOT);
   double lot=Lots;
   lot=NormalizeDouble(AccountBalance()/10000,1);
   //баланс меньше 1000
   if(AccountBalance()<1000)
     {
      lot=NormalizeDouble(AccountBalance()*Risk/LotSize,2);
      if(lot<=MinLot) lot=MinLot;
      if(lot>=MaxLot) lot=MaxLot;
     }
   //  баланс уменьшился с 3100 до 2900
   if(AccountBalance()< PrevBalance && (int)AccountBalance()/1000<(int)PrevBalance/1000)lot=lot-0.1;
   
   return(lot);
  }


И советник:


//+------------------------------------------------------------------+
//|                                                          Lot.mq4 |
//|                                              Copyright 2016, AM2 |
//|                                      http://www.forexsystems.biz |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, AM2"
#property link      "http://www.forexsystems.biz"
#property version   "1.00"
#property strict

//--- Inputs
extern double Lots      = 0.1;      // лот
extern double MaxLot    = 10;       // максимальный лот
extern double Risk      = 5;        // риск
extern int StopLoss     = 500;      // лось
extern int TakeProfit   = 500;      // язь
extern int Slip         = 30;       // реквот
extern int Magic        = 123;      // магик

int Lock=0;
double PrevBalance=0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

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

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

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

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

   r=OrderSend(NULL,type,Lot(),NormalizeDouble(price,Digits),Slip,sl,tp,"",Magic,0,clr);
   return;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CountTrades()
  {
   int count=0;
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
           {
            if(OrderType()==OP_BUY || OrderType()==OP_SELL) count++;
           }
        }
     }
   return(count);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double Lot()
  {
   double LotSize=MarketInfo(Symbol(),MODE_LOTSIZE);
   double MinLot=MarketInfo(Symbol(),MODE_MINLOT);
   double lot=Lots;
   lot=NormalizeDouble(AccountBalance()/10000,1);
   //баланс меньше 1000
   if(AccountBalance()<1000)
     {
      lot=NormalizeDouble(AccountBalance()*Risk/LotSize,2);
      if(lot<=MinLot) lot=MinLot;
      if(lot>=MaxLot) lot=MaxLot;
     }
   //  баланс уменьшился с 3100 до 2900
   if(AccountBalance()< PrevBalance && (int)AccountBalance()/1000<(int)PrevBalance/1000)lot=lot-0.1;
   
   return(lot);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   double rsi=iRSI(NULL,0,14,PRICE_CLOSE,1);
   if(CountTrades()<1 && rsi<30)
     {
      PrevBalance=AccountBalance();
      PutOrder(0,Ask);
      //PutOrder(1,Bid);
     }

   Comment("\n Lot: ",Lot(),
           "\n Balance: ",NormalizeDouble(AccountBalance(),2),
           "\n PrevBalance: ",PrevBalance,
           "\n LotSize: ",MarketInfo(Symbol(),MODE_LOTSIZE),
           "\n Balance/1000: ",NormalizeDouble(AccountBalance()/1000,0),
           "\n int Balance/1000: ",(int)AccountBalance()/1000,            //
           "\n int PrevBalance/1000: ",(int)PrevBalance/1000);
  }
//+------------------------------------------------------------------+

avatar

  34  AM2 Сообщений: 15869 - Андрей

  • 24 января 2016, 06:43
+
0
Спасибо, Андрей.
В Вашем примере, я так понимаю, лот рассчитывается конкретно на 1000 депозита. Я немного подумал, и вот что я решил сделать, немного изменил Вашу функцию с возможностью выбора шага изменения баланса и выбора величины прогрессии лота:
<code>
input double  Lots              = 0.1;
input double  MaxLot            = 10;
input double  Risk              = 5;
extern double InitialLot        = 0.1;  //прогресcия лота на каждые "ProgressiveBalans"
extern double ProgressiveBalans = 1000; //шаг баланса 
//+-----------------------------------------------------------------+//

double Lot()
  {
   double LotSize=MarketInfo(Symbol(),MODE_LOTSIZE);
   double MinLot=MarketInfo(Symbol(),MODE_MINLOT);
   double lot=Lots;
   lot=NormalizeDouble(AccountBalance()*InitialLot/ProgressiveBalans,1);
   //баланс меньше 1000
   if(AccountBalance()<ProgressiveBalans)
     {
      lot=NormalizeDouble(AccountBalance()*Risk/LotSize,2);
      if(lot<=MinLot) lot=MinLot;
      if(lot>=MaxLot) lot=MaxLot;
     }
   //  баланс уменьшился с 3100 до 2900
   if(AccountBalance()< PrevBalance && (int)AccountBalance()/ProgressiveBalans<(int)PrevBalance/ProgressiveBalans) lot=lot-InitialLot;
   
   return(lot);
  }
//+-----------------------------------------------------------------+//
</code>

Но есть одна загвоздка!!! Лот начинает изменяться до того как баланс увеличивается (в данном случае) на 1000, т.е., допустим, начальный баланс 1000, как только баланс переваливает за 1501, лот уже начинает увеличивается!?.. А надо чтобы лот начинал увеличиваться на каждую полную (в данном случае) 1000!?.. Как это сделать, не могу понять?!..
Вот фрагмент отчета:

Редактирован: 24 января 2016, 16:11
avatar

  18  Andrju81 Автор Сообщений: 245 - Андрей

  • 24 января 2016, 15:48
+
0
Лот начинает изменяться до того как баланс увеличивается (в данном случае) на 1000, т.е., допустим, начальный баланс 1000, как только баланс переваливает за 1501, лот уже начинает увеличивается!?.. А надо чтобы лот начинал увеличиваться на каждую полную (в данном случае) 1000!?.. Как это сделать, не могу понять?!..


Также как с уменьшением.
//  баланс уменьшился с 3100 до 2900
   if(AccountBalance()< PrevBalance && (int)AccountBalance()/1000<(int)PrevBalance/1000)lot=lot-0.1;
   

Только наоборот.
avatar

  34  AM2 Сообщений: 15869 - Андрей

  • 24 января 2016, 17:36
+
0
Спасибо за подсказку. Сейчас попробую.
Редактирован: 24 января 2016, 18:39
avatar

  18  Andrju81 Автор Сообщений: 245 - Андрей

  • 24 января 2016, 17:40
+
0
К сожалению это не помогло, первый же лот сразу открылся увеличенным, и дальше все повторяется как я описывал выше!?..
avatar

  18  Andrju81 Автор Сообщений: 245 - Андрей

  • 24 января 2016, 18:40
+
0
Я пока Анатолию делаю, а потом уже ваш буду смотреть.
avatar

  34  AM2 Сообщений: 15869 - Андрей

  • 24 января 2016, 18:42
+
0
О.К.
avatar

  18  Andrju81 Автор Сообщений: 245 - Андрей

  • 24 января 2016, 18:44
+
0
На рисунке баланс 9649 лот 0.9. Считаем так:


   lot=(int)AccountBalance()/1000;
   lot=lot/10;




Функция:


double Lot()
  {
   double LotSize=MarketInfo(Symbol(),MODE_LOTSIZE);
   double MinLot=MarketInfo(Symbol(),MODE_MINLOT);
   double lot=Lots;
   
   lot=(int)AccountBalance()/1000;
   lot=lot/10;
   //баланс меньше 1000
   if(AccountBalance()<1000)
     {
      lot=NormalizeDouble(AccountBalance()*Risk/LotSize,2);
      if(lot<=MinLot) lot=MinLot;
      if(lot>=MaxLot) lot=MaxLot;
     }
   //  баланс уменьшился с 3100 до 2900
   if(AccountBalance()< PrevBalance && (int)AccountBalance()/1000<(int)PrevBalance/1000)lot=lot-0.1;
   
   return(lot);
  }

Редактирован: 25 января 2016, 08:48
avatar

  34  AM2 Сообщений: 15869 - Андрей

  • 25 января 2016, 08:47
+
0
Советник:


//+------------------------------------------------------------------+
//|                                                          Lot.mq4 |
//|                                              Copyright 2016, AM2 |
//|                                      http://www.forexsystems.biz |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, AM2"
#property link      "http://www.forexsystems.biz"
#property version   "1.00"
#property strict

//--- Inputs
extern double Lots      = 0.1;      // лот
extern double MaxLot    = 10;       // максимальный лот
extern double Risk      = 5;        // риск
extern int StopLoss     = 500;      // лось
extern int TakeProfit   = 500;      // язь
extern int Slip         = 30;       // реквот
extern int Magic        = 123;      // магик

int Lock=0;
double PrevBalance=0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

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

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

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

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

   r=OrderSend(NULL,type,Lot(),NormalizeDouble(price,Digits),Slip,sl,tp,"",Magic,0,clr);
   return;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CountTrades()
  {
   int count=0;
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
           {
            if(OrderType()==OP_BUY || OrderType()==OP_SELL) count++;
           }
        }
     }
   return(count);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double Lot()
  {
   double LotSize=MarketInfo(Symbol(),MODE_LOTSIZE);
   double MinLot=MarketInfo(Symbol(),MODE_MINLOT);
   double lot=Lots;
   
   lot=(int)AccountBalance()/1000;
   lot=lot/10;
   //баланс меньше 1000
   if(AccountBalance()<1000)
     {
      lot=NormalizeDouble(AccountBalance()*Risk/LotSize,2);
      if(lot<=MinLot) lot=MinLot;
      if(lot>=MaxLot) lot=MaxLot;
     }
   //  баланс уменьшился с 3100 до 2900
   if(AccountBalance()< PrevBalance && (int)AccountBalance()/1000<(int)PrevBalance/1000)lot=lot-0.1;
   
   return(lot);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   double rsi=iRSI(NULL,0,14,PRICE_CLOSE,1);
   if(CountTrades()<1 && rsi<30)
     {
      PrevBalance=AccountBalance();
      PutOrder(0,Ask);
      //PutOrder(1,Bid);
     }

   Comment("\n Lot: ",Lot(),
           "\n Balance: ",NormalizeDouble(AccountBalance(),2),
           "\n PrevBalance: ",PrevBalance,
           "\n LotSize: ",MarketInfo(Symbol(),MODE_LOTSIZE),
           "\n Balance/1000: ",NormalizeDouble(AccountBalance()/1000,0),
           "\n int Balance/1000: ",(int)AccountBalance()/1000,            //
           "\n int PrevBalance/1000: ",(int)PrevBalance/1000,
           "\n MathMod(AccountBalance(),1000: ",MathMod(AccountBalance(),1000));
  }
//+------------------------------------------------------------------+

avatar

  34  AM2 Сообщений: 15869 - Андрей

  • 25 января 2016, 08:49
+
0
Кстати и с уменьшением баланса тоже также просто можно считать:


lot=(int)AccountBalance()/1000;
   lot=lot/10;


Например баланс 3200 лот считает 0.3. Стал 2900 лот будет 0.2.
avatar

  34  AM2 Сообщений: 15869 - Андрей

  • 25 января 2016, 10:08
+
0
Спасибо Андрей за помощь! То что доктор прописал. Только, я думаю, надо сделать(дать) выбор шага изменения баланса и соответственно лота. В таком случае получается так:
extern double     Lot               = 0.1;  //Начальный лот
extern double     ShagLot           = 0.1;  //прогрессия лота на каждые "ShagBalans"
extern int        ShagBalans        = 1000; //шаг баланса кратный 1000
extern double     Risk              = 5;    //если баланс меньше "ShagBalans" рассчитывается(%) от баланса
extern double     MaxLot            = 10;   //Максимальный лот
//+-------------------------------------------------------------+//
double LotsOptimized()
  {
   double LotSize=MarketInfo(Symbol(),MODE_LOTSIZE);
   double MinLot=MarketInfo(Symbol(),MODE_MINLOT);
   double lot=Lot;
   lot=(int)AccountBalance()/ShagBalans;
   lot=lot*ShagLot;
   //баланс меньше 1000
   if(AccountBalance()<ShagBalans)
     {
      lot=NormalizeDouble(AccountBalance()*Risk/LotSize,2);
      if(lot<=MinLot) lot=MinLot;
      if(lot>=MaxLot) lot=MaxLot;
     }
return (lot);
  }

Вы со мной согласны?!.. Если да, то тогда вопрос исчерпан. Еще раз СПАСИБО за помощь.
Редактирован: 25 января 2016, 17:27
avatar

  18  Andrju81 Автор Сообщений: 245 - Андрей

  • 25 января 2016, 17:10
+
0
Вы со мной согласны?!.. Если да, то тогда вопрос исчерпан.

Согласен :) 
avatar

  34  AM2 Сообщений: 15869 - Андрей

  • 25 января 2016, 18:11

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