Kaur
Руслан Каюмов

 
Уровень 47

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

  Моя торговля


График торгового счета Kaur


Группа "Программирование на MQL"

Рейтинг 280



(mql4) Функция расчета лота в зависимости от величины просадки

Недавно я писал о методе увеличения прибыли с помощью введения зависимости лота от величины просадки. Читать подробнее о методе

Идею (которую раньше проверял в Excel) удалось воплотить в код MQL4. В этой заметке выкладываю получившийся код.

Внимание! Функция предназначена для стратегий, по которым одновременно открыто не более одной сделки.


Используемые переменные (оптимальные параметры зависят от Вашей стратегии):
extern bool ddLot=true; //если вкл, используется увеличение лота при просадке ниже ddX и восстановление лота при просадке выше ddY
extern double ddX = 0.12; // при превышении данного уровня просадки лот будет увеличиваться в k раз (указывается в долях, т.е. ddX=0.10 означает 10% просадку)
extern double ddY = 0.06; // после достижения ddX лот будет оставаться повышенным, пока просадка не восстановится выше уровня ddY (указывается в долях)
extern double k = 2.00; // коэффициент изменения лота в зависимости от уровня просадки

double MaxEquity = 0; // переменная для хранения максимального эквити
bool k_use = false; // хранит информацию, использовался ли в последней сделке k (коэффициент изменения лота в зависимости от уровня просадки)


Код функции расчета лота в зависимости от величины просадки:
//+-------------------------------------------------------------------------------------------------------------------+
   //| увеличение лота при просадке |
   void ddLot(){
      double DrawDawn = 0; // переменная для текущей просадки
      
      // расчет текущей просадки
      if (AccountEquity() > MaxEquity){
         MaxEquity = AccountEquity();
      }
      
      DrawDawn=NormalizeDouble(((MaxEquity - AccountEquity())/MaxEquity),2);
      
      //проверка на условие повышение лота при достижении порога просадки ddX
      if (DrawDawn >= ddX) {
         Lots = NormalizeDouble((Lots * k),2);
         k_use = true;
      }
      // если просадка меньше ddX, то проверить, больше ли она ddY и не повышался ли лот от просадки в последней сделке
      else {
         // если да, то продолжаем торговать повышенным лотом
         if (k_use == true && DrawDawn >= ddY){
            Lots = NormalizeDouble((Lots * k),2);   
         }
         // если нет, то k_use присваиваем false
         else {
            k_use = false;
         }
      }
   }


Запуск функции осуществляется с помощью вставки в основную часть
if (ddLot==true){ddLot();}


Lots рассчитывается предварительно в другом блоке расчета зависимости лота от эквити (для реализации реинвестирования).
  • +3
  • Просмотров: 40645
  • 2 мая 2012, 15:49
  • Kaur
Понравилcя материал? Не забудьте поставить плюс и поделиться в социальной сети!

Вступите в группу "Программирование на MQL", чтобы следить за обновлениями
ПРИСОЕДИНИТЬСЯ К ГРУППЕ
присоединиться
06 января 2012
28 февраля 2013

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

+
0
Скажите, а индикатор готовый есть по размеру лота? А то я в mql полный 0!!!
avatar

  0  iceburg Сообщений: 3

  • 5 мая 2012, 00:56
+
0
Вас интересует индикатор именно по данному методу? Или классический индикатор, показывающий размер лота в зависимости от принятых рисков на сделку и стопа?
avatar

  47  Kaur Автор Сообщений: 1327 - Руслан Каюмов

  • 5 мая 2012, 12:54
+
0
Да, по данному методу. Насколько я понимаю, этот метод по формуле DDSM?
avatar

  0  iceburg Сообщений: 3

  • 5 мая 2012, 13:10
+
0
Нет, DDSM, как я понимаю, сложнее. У меня все просто. Вот здесь подробности описаны — kaur.opentraders.ru/2737.html
avatar

  47  Kaur Автор Сообщений: 1327 - Руслан Каюмов

  • 5 мая 2012, 13:13
+
0
Я уже все это перечитал)) Дайте, пожалуйста, ваш индикатор попробовать.И еще вопрос реально ли сделать индюк по формуле ddsmm. Вот она поломаная.
avatar

  0  iceburg Сообщений: 3

  • 5 мая 2012, 13:21
+
0
Дайте, пожалуйста, ваш индикатор попробовать

У меня весь расчет в виде блока mql, который вставляется в советник. А весь блок выше приведен. Т.е. отдельного индикатора под это нет. Его еще надо делать.

И еще вопрос реально ли сделать индюк по формуле ddsmm. Вот она поломаная.

Думаю, что реально.
avatar

  47  Kaur Автор Сообщений: 1327 - Руслан Каюмов

  • 5 мая 2012, 14:11
+
0
Здравствуйте! Подскажите, пожалуйста, а как увеличивать лот вдвое если, например, профит увеличился на N пунктов? Благодарю!
avatar

  0  bhairava Сообщений: 5

  • 15 июня 2014, 03:08
+
0
avatar

  0  guest111 Сообщений: 180

  • 15 июня 2014, 10:45
+
0
Советую почитать эту статью
После прочтения, в том числе допов по ссылкам, станет понятно почему надо увеличить лот при просадке, чтобы выйти в плюс. Кратко: просадка была сделана лотом от еквити, а следующая ставка лотом от еквити минус убыток. В итоге наблюдаем нисходящую кривую. Всё просто.
И да, на тему удвоений лота и других на первый взгляд очевидных вещей там есть что покурить вдумчиво.
avatar

  0  guest111 Сообщений: 180

  • 15 июня 2014, 10:47
+
0
Благодарю за ссылку!

Но мне нужно именно в зависимости от баланса, или даже не баланса, а от эквити при увеличении допустим эквити на каждые int n_profit раз, увеличивать лот на double k
Пока реализовал примерно так, но понимаю, что есть какой-то более динамичный способ, но еще только осваеваю mql, и понять пока не получается как это сделать иначе.


double  Lot_Size        = 0.01;

void agressive_mode()
{
   int ii = 0;
   int eq = (int)round(AccountEquity());
   if(eq > 200 && ii == 0 )
   {
   Lot_Size = 0.02;
   ii+=1;
   }
   if(eq > 300 && ii == 1)
   {
   Lot_Size = 0.03;
   ii+=1;
   }
   if(eq > 400 && ii == 2)
   {
   Lot_Size = 0.03;
   ii+=1;
   }
}


пробовал другой вариант, что-то типа этого:

double Lot_Size = 0.01;
double k = 0.01;
int n_profit = 100;


void agress_mode()
{
   int ii = 0;
   int eq = (int)round(AccountEquity());
   
   if(eq > eq+n_profit && ii == 0 )
   {
   Lot_Size += k;
   ii+=1;
   }
   if(eq > eq+n_profit && ii == 1)
   {
   Lot_Size += k;
   ii+=1;
   }
   if(eq > eq+n_profit && ii == 2)
   {
   Lot_Size += k;
   ii+=1;
   }
}


Первый вариант работает, а этот ни в какую не хочет.(
avatar

  0  bhairava Сообщений: 5

  • 15 июня 2014, 12:52
+
+1
выдрал со своего робота:
extern int    DynamicLot = 1;        // 0=BaseLot, 1=FreeMargin, 2=Equity, 3=Balance
extern double RiskFactor = 0.003;    // риск от средств счёта для динамического лота

............................................
   // динамический лот рассчитывается исходя из текущего размера собственных средств
   // эмпирика: каждые 100$ свободных средств = 0.1 лота при EquityRisk = 0.1
   // без динамики hi/lo по барам и учёта максимального количества ордеров
   // внешняя переменная DynamicLot определяет источник (в порядке убывания агрессивности):
   // 1) свободные для открытия ордера, 2) средства без учёта маржи, 3) баланс (практики не имеет)

   double lot, lot_sell, lot_buy;

   switch(DynamicLot)
   {
      case 1:  lot = AccountFreeMargin() / 100 * RiskFactor; break;
      case 2:  lot = AccountEquity()     / 100 * RiskFactor; break;
      case 3:  lot = AccountBalance()    / 100 * RiskFactor; break;
      default: lot = BaseLot; break;
   }

   if (EquLot)
   {
      lot_buy = NormalizeDouble(lot * MathPow(LotExp, MathMax(count_buy, count_sell)), LotDec);
      lot_sell = lot_buy = MathMin(MathMax(lot_buy, BaseLot), MaxiLot);
   }
   else
   {
      lot_buy  = NormalizeDouble(lot * MathPow(LotExp, count_buy),  LotDec);
      lot_buy  = MathMin(MathMax(lot_buy, BaseLot), MaxiLot);
      lot_sell = NormalizeDouble(lot * MathPow(LotExp, count_sell), LotDec);
      lot_sell = MathMin(MathMax(lot_buy, BaseLot), MaxiLot);
   }


avatar

  0  guest111 Сообщений: 180

  • 16 июня 2014, 07:33
+
0
О!!! Благодарю Вас!!! Очень рад!) Попробую теперь прикрутить к своему!) Удачи Вам и вечного профита! :) ;) 
avatar

  0  bhairava Сообщений: 5

  • 16 июня 2014, 11:09
+
0
Здравствуйте!

А подскажите, пожалуйста, какие значения должны быть в переменных EquLot, LotExp, count_buy, count_sell, LotDec и MaxiLot.
count_buy и count_sell подсчитывает лоты в открытых позициях? А если у меня нет открытых, можно просто на 0 заменить?
avatar

  0  bhairava Сообщений: 5

  • 17 июня 2014, 18:57
+
+1
Как я уже говорил, этот кусок кода выдран из моего робота, поэтому напрямую вставить и собрать не получится. Я хотел только привести пример. Что касается переменных, то LotExp это мартингейл в зависимости от количества открытых ордеров в серии, EquLot открывает одинаковый лот в оба направления (робот торгует и бай и селл) по наибольшему из серии, count_buy, count_sell соответственно количество открытых ордеров, MaxiLot — максимально допустимый размер лота, LotDec — количество цифр после запятой для лота.
LotDec = log10(1 / MarketInfo(Symbol(), MODE_LOTSTEP));


Если нет открытых, размер лота принимает значение переменной BaseLot — начальный лот серии. Он же, если явно не задан, берётся из размера минимального лота у брокера (переменная MinLot в коде инициализации init() совы):
MinLot = MarketInfo(Symbol(), MODE_MINLOT);

Редактирован: 17 июня 2014, 20:19
avatar

  0  guest111 Сообщений: 180

  • 17 июня 2014, 20:15
+
0
Благодарю Вас! Теперь более-менее понятно!
avatar

  0  bhairava Сообщений: 5

  • 17 июня 2014, 20:30
+
0
Немного неверно написал: если количество ордеров = 0, функция MathPow(LotExp, 0) принимает значение «1» (при LotExp != 0) и в итоге расчитанная ранее в конструкции «switch(DynamicLot)» переменная lot умножается на единицу.
avatar

  0  guest111 Сообщений: 180

  • 18 июня 2014, 07:42

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