Автоматический расчет размера лота для советника

 

Уважаемые знатоки.

Я не программист, но мне удалось разобраться в MQL-4 и создать работающего советника.

Судя по тому, что я вижу в сети и на форумах, проблема манименеджемента рано или поздно начинает волновать всех (лучше рано, чем поздно :)). Однако, ответа на мой вопрос я найти не смог, поэтому решил спросить у форумчан. 

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

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

В алгоритме предусмотрены два варианта умножения лота на коэффициент при срабатывании стопа:

1. только в одном направлении

2. в обоих направлениях

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

Сейчас код функции выглядит так:

 

void MyDEP_count()

   {

      RefreshRates();

      int level=AccountStopoutLevel();//уровень стоп аут%      

      double Margin=AccountFreeMargin();//свободные средства

      double Stop_Rest;//остаток после стоп аута

      double Free_Capital;//свободный капитал

      double Point_Price;//цена пункта

      double Lot_Size=MarketInfo(Symbol(), MODE_LOTSIZE);//стандартный лот

      double one_point = 0.0001;//пункт

      double max_lot;//максимальный лот      

      double margin_r = MarketInfo (Symbol(),MODE_MARGINREQUIRED); //маржа на 1 лот

      double drowdown_max;//максимальная просадка

      double margin_max;//максимальная маржа

      double max_lot_red;//скорректированный максимальный лот

      int lot_reduction;//процент снижения просадки для расчета скорректированного максимального лота

      int stop = SL;//стоп лосс в пунктах

      

      

       

      if  (Digits==5) 

            {

      one_point = 0.00001;//коррекция пункта при 5 значном терминале

      stop=stop/10;//коррекция стоп лосса при 5 значном терминале

      }


      

      

      if(AccountStopoutMode()==0) 

      

      {

      Alert("Stop Out = ", level, "%");  //расчет капитала (свободная маржа минус стоп аут)    

      Stop_Rest=level*Margin/100;

      Free_Capital= NormalizeDouble (Margin-Stop_Rest,2);

      }

      

      if(AccountStopoutMode()==1) 

      

      {

      Alert("Stop Out = ", level, "USD");//расчет капитала (свободная маржа минус стоп аут)

      Free_Capital= NormalizeDouble (Margin-level,2);

      }

      

      max_lot = NormalizeDouble (Free_Capital*0.95/stop/Lot_Size*10000/2,LotStep);           

      Point_Price = NormalizeDouble (max_lot*Lot_Size/10000,2);

      drowdown_max = NormalizeDouble (Point_Price*stop*1.2,2); 

      margin_max = NormalizeDouble (max_lot*margin_r,2);  

      

      

      Alert("max лот = ",max_lot); 

      Alert("свободная маржа =  ", Margin); 

      Alert("максимальная маржа с  max лотом =  ", margin_max);       

      Alert("максимальная просадка с max лотом =  ", drowdown_max); 

      Alert("необходимый капитал с max лотом =  ", drowdown_max + margin_max); 

      Alert("свободный капитал = ", Free_Capital, "USD");

       

      if (drowdown_max + margin_max > Free_Capital)

      { 

      lot_reduction = Free_Capital*100/(drowdown_max + margin_max);

      drowdown_max = NormalizeDouble (drowdown_max/100*lot_reduction,2);

      max_lot_red=NormalizeDouble (drowdown_max/stop/Lot_Size*10000/2,LotStep);

      Lot1 = NormalizeDouble (max_lot_red/k,LotStep);// рабочий лот 

        }

        else

      Lot1 = NormalizeDouble (max_lot/k,LotStep);// рабочий лот 

      

      margin_max= NormalizeDouble (Lot1*k*margin_r,2);

      drowdown_max= NormalizeDouble (Lot1*1.2*k*Lot_Size/10000*stop,2);   

      

        

    

    Alert("средства на 1 лот = ",margin_r); 

    Alert("максимальный лот скорректированный =  ", max_lot_red);  

    Alert("НЗ = ", Stop_Rest, "USD");

    Alert("цена пункта = ", Point_Price, "USD");

    Alert("рабочий лот = ", Lot1);

    Alert("максимальная маржа с рабочим лотом =  ", margin_max);       

    Alert("максимальная просадка с рабочим лотом =  ", drowdown_max); 

    Alert("необходимый капитал с рабочим лотом =  ", drowdown_max + margin_max); 

    Alert("свободный капитал = ", Free_Capital, "USD");   

    

      return;

   } 

 

Алерты писались для проверки результатов расчета в ручную.  У меня остается ощущение чрезмерной громоздкости и корявости расчета. Из-за того, что я уже

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

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

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

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

Заранее благодарен за помощь.

 
Внутри этого архива есть библиотека b-PSI@MM_Light.mqh - может найдёте для себя что-нибудь полезное.
 
TarasBY:
Внутри этого архива есть библиотека b-PSI@MM_Light.mqh - может найдёте для себя что-нибудь полезное.

Спасибо, изучу.