Фиксированный риск на сделку в МТ4

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

Пока готовил ответ — написал небольшой мануальчик. Соответственно этот манульчик выкладываю тут в виде статьи, может быть кому либо пригодиться. А может быть кто-то предложит еще более простой или может быть более «корректное» решение описанной задачи.

Логика работы

Нам нужно рассчитать объем открываемой позиции для того, чтобы при срывании стоп-лосса получить заданную в процентах от депозита величину убытка.

Сначала рассмотрим теоретическую сторону вопроса, а затем покажу как можно реализовать решение данной задачи в коде.

Пример. Наше депо $10 000, мы открываемся по EURUSD в бай по цене 1,2 со стопом на уровне 1,15 и хотим, чтобы величина убытка составила 5% от депо в случае выбивания позиции по стопам.

  1. Сначала рассчитаем изменение стоимости eurusd после которого нас выбьет по стопу: 1-1,15/1,2= 0,0416667.
  2. Теперь рассчитаем величину убытка в абсолютной величине: $10 000*5%=$500.
  3. Таким образом изменение стоимости покупаемого актива должно составить 4.16667% и это должно привести к убытку в 500 баксов. Исходя из это посчитаем объем сделки: 500/0,0416667= ~ $12000.
    Итого мы должны купить eurusd на сумму в 12000 долларов США чтобы в случае выбивания стопа величина убытка составила 5% от нашего депозита.
  4. Теперь объем открываемой позиции из долларового выражения необходимо перевести в объем базовой валютной пары актива. В случае с EURUSD объем нужно переводить в EUR. Для этого необходимо воспользоваться величиной текущего курса EUR к USD, который, как мы знаем, равен 1.2: $12000*(1/1.2)= 10000 EUR.
  5. Далее полученный объем нужно перевести в лоты торгового терминала: 10000/100000=0,1.

Соответственно нам нужно открыться лотом 0,1.

Данный подход абсолютно универсален для всех торгуемых пар. Единственным более менее сложным моментом будет расчёт коэффициента для перевода объема открываемой позиции из валюты депозита в базовую валюту торгуемого инструмента. В этот теоретический пример не заложена комиссия, свопы и спред, но это уже частные случаи, которые принципиально не меняют задачу.

Ниже приведу микропримеры для валютных пар, которые можно называть «нестандартными». Базовое депо так же $10000 убыток который берем на себя 5%, то есть 500 баксов. Позиция бай.

  • USDJPY: Ask-120 sl-118: 500/(1-118/120)*(1/1)/100000= 0,3. Стоимость, в принципе, выражена в долларах США, поэтому корректирующий коэффициент равен единице, так как USD/USD всегда равно 1.
  • XAUUSD: Ask-1300 sl-1200: 500/(1-1200/1300)*(1/1200)/100= 0.054167. Делим на 100, потому что объем базового актива торгового инструмента равен 100 унций 1 лот золота= 100 унциям.
  • EURJPY: Ask-140 sl-130: 500/(1-130/140)*(1/1.2)/100000= 0,3. В расчёте используется котировка валютной пары EURUSD=1.2, которая не участвует в торговле
  • BTCUSD: Ask-9000 sl-5000: 500/(1-5000/9000)*(1/9000)/1=0.125. В паре btcusd объем базового актива равен единице.
  • XAGEUR: Ask-20 sl-18: 500/(1-18/20)*(1/17)/5000=0.058823. В расчёте используется курс котировки XAGUSD=17, 5000 унций это размер базового лота при торговле серебром.

Очевидно, что самым «гемором» в этом расчёте будет высчитывание коэффициента перевода стоимости актива в доллары США с поправкой на объем базового актива, так как для разных инструментов в 1 лоте находится разное количество объема актива: где-то 100 000 как для валютных пар, где-то 1 единица как для крипты, где то 100 или 5000 как для золота и серебра соответственно.

Вариант реализации

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

if(signal_open_buy ){  
   dist=(Close[1]-Open[1]);
   sl=Bid-dist*sl_koef;    // как либо рассчитываем цену где у нас будет стоять стоп лосс
   if (FixLossPrcn>0){     // если в настройках советника задан расчёт лота как фиксированный риск на сделку в процентах то считаем
      lot=(FixLossPrcn/100*MathMin(AccountEquity(),AccountBalance()))/(1-sl/Ask)*(1/GetLotKoefSymbolMN())/100000;   // собственно расчёт открываемого лота
      }

Соответственно функция GetLotKoefSymbolMN(); считает требуемый коэффициент. Изначально функция была написана под иную задачу, поэтому она несколько сложнее чем требуется. Я её тут в примере существенно упростил, чтобы она не сильно пугала, хотя все-равно функция остается избыточной и её в идеале можно упростить. Для экзотических пар я задаю объем лота вручную. Технически в МТ4 это можно делать и автоматически извлекая соответствующую информацию из спецификации символа, но у меня сразу как то не получилось. Я решил не заморачиваться и поставил все вручную.

double GetLotKoefSymbolMN()
   {
    string ValMarginSymbol=StringSubstr(Symbol(),0,3);
    double LotSizeMN=100000;    
    if (Symbol()=="XAUUSD") LotSizeMN=100;     
    if (Symbol()=="XAGUSD") LotSizeMN=5000;
    if (Symbol()=="BTCUSD") LotSizeMN=1;
    double MnojMN=1,MnojSymbol=1;
 
    if (ValMarginSymbol=="USD") MnojSymbol=1; 
    if (iClose(ValMarginSymbol+"USD",0,0)>0) MnojSymbol=iClose(ValMarginSymbol+"USD",0,0);
    if (iClose("USD"+ValMarginSymbol,0,0)>0) MnojSymbol=1/iClose("USD"+ValMarginSymbol,0,0);
 
    double ResultCoef=(MnojSymbol*LotSizeMN)/(MnojMN*100000);
    return(ResultCoef); 
   }

Собственно всё. Не претендую на полную корректность и тем более на эстетическую грамотность написанного кода. Но всё работает.

Ссылка на основную публикацию
Фиксированный риск на сделку в МТ4
Хиб.ру