Fargo

 
Уровень 13

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


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

Рейтинг 280



Расчет уровня БУ (методы, формулы и примеры кода)

В нескольких топиках довелось участвовать в сраче обсуждении того, как рассчитывать уровень без убытка…
И вроде бы не сложный вопрос, вызывает порой серьезные затруднения и буйный полет фантазии в решениях
На самом деле все очень просто. Расскажу как это делаю я *stesnitelno* 

1. Расчет уровня БУ без учета комиссий, свопов и прочего. Чистое арифметическое среднее.

Из со школы все знают формулу

или простой наглядный пример


Применение этой формулы в коде:



   double lots=0;
   double sum=0;
   for (int i=0; i<OrdersTotal(); i++)
   {
      if (!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) break;
      if (OrderSymbol()!=Symbol()) continue;
      if (OrderType()==OP_BUY)
      {
         lots=lots+OrderLots();
         sum=sum+OrderLots()*OrderOpenPrice();
      }
 
      if (OrderType()==OP_SELL)
      {
         lots=lots-OrderLots();
      sum=sum-OrderLots()*OrderOpenPrice();
      }
   }
   double price=0;
   if (lots!=0) price=sum/lots;


Рассмотрим как это работает:

Сначала посмотрим в конец примера…
Искомый уровень БУ вычисляется здесь price=sum/lots;

А в переменных «lots» и «sum» содержатся данные по открытым ордерам, собираемые в цикле.
Причем для ордеров типа «Buy» данные ордеров берутся со знаком "+", а для «Sell» соответственно с "-".
Делается это из-за того, что ордера противоположного направления, компенсируют друг друга.

Сначала то, что касается переменной «lots»…
Прибавляя объем ордеров (OrderLots) одного типа и вычитая объемы противоположных ордеров, определим — не является ли сумма ордеров равновесной?
Ведь если объем ордеров на покупку, равен объему ордеров на продажу, то уровня без убытка просто не существует. *pardon* 

Теперь рассмотрим, как подсчитывается «sum»…
В ней суммируются произведения цены открытия ордера (OrderOpenPrice), на его объем (OrderLots). Т.е. цена ордера берется столько раз, сколько лотов в этом ордере.

Для примера, если взять два ордера Buy равного объема (пусть объем равен 1) с ценами открытия Pr1= 100 и Pr2=200, то сразу видно что среднее значение равно 150-ти.

А если их объемы будут равны Lot1=2, а Lot2=5? Ведь в таком случае второй ордер будет сильнее влиять на нашу прибыль/убыток.
Учтем это взяв цену первого ордера 2 раза, а цену второго соответственно 5 раз.
И для получения среднего, разделим на количество слагаемых.

(100+100+200+200+200+200+200)/2+5 = (2*100+5*200)/7 = 171,428571(428571)

Таким образом мы приходим в выражению price=sum/lots.
Для практического применения его нужно еще привести к нужному количеству знаков после запятой, но это уже другой вопрос.

2. Расчет уровня БУ с учетом свопов и комиссий.
(далее рассматриваются случаи для наиболее распространенных (в данный момент) долларовых депозитов)


Этот вопрос намного интереснее и не так прост.
Общая идея учета комиссий и свопов, в том, что бы определить, на каком уровне полученный профит компенсирует
начисленные суммы и общий результат сделок будет равен нулю.
Так как комиссии и свопы начисляются не в пунктах, а в валюте депозита, то тут начинает играть роль стоимость одного пункта.
А она зависит от торгуемой пары.

— Так для обратных котировок (EUR/USD, GBP/USD и всех других где доллар стоит в знаменателе) все просто:
Цена пункта = размер пункта * объем позиции

Для 1-го стандартного лота, стоимость одного (4зн) пункта всегда равна 10$.

— Для прямых котировок (USD/JPY, USD/CHF и других, где USD стоит в числителе) уже сложнее… Тут имеет значение текущий курс.
Формула расчета:
Цена пункта = размер пункта * объем позиции / текущий курс

Так как мы рассчитываем цену пункта не по текущему курсу, а по будущему, то расчет уровня БУ уже становится не таким простым.

— И наиболее сложный случай — кроссовые пары (GBP/CHF, EUR/JPY и др.)
Формула для расчета следующая:

Цена пункта = объем позиции * размер пункта * текущая котировка базовой валюты по отношению к USD / текущий курс валютной пары (кросс-курс)

Для примера возьмем GBP/CHF, по курсу 1.4400 франка за 1 фунт, при курсе GBP/USD= 1.5800.

Тогда 1-го лота цена пункта=100000 * 0.0001 * 1.5800 (курс GBP/USD) / 1.4400 = 11 $

В этом случае расчет уровеня БУ становится совершенно не тривиальной задачей,
т.к. требуется знать котировку базовой валюты по отношению к USD на момент достижения этого уровня БУ. *crazy* 

И как же в таком случае быть?
Лично я пришел к выводу, что в практике расчета уровня БУ в советниках, не требуется совершенно точно вычислять уровень БУ.
Если цена находится далеко от предполагаемого уровня, то погрешность вычисления может быть достаточно большой.
Все равно, так как в процессе удержания позиции величина накопленных комиссий и свопов изменяется, то уровень БУ требуется пересчитывать.
И по мере приближения к этому уровню, уточняются значения курсов влияющих на стоимость одного пункта.
А значит и расчет уровня БУ становится точнее.

Общая идея (алгоритм) расчета уровня БУ с учетом комиссий и свопов в следующем:
1. Сначала определяем уровень БУ методом арифметического среднего (см. выше)
2. Далее корректируем найденное значение, для компенсации накопленных начислений.
В этом нам поможет метод MarketInfo(Symbol(), MODE_TICKVALUE), возвращающий размер минимального изменения
цены инструмента в валюте депозита на один стандартный лот.

А вот так это воплощается в коде:



double _lost=0 ;
double _sum=0 ;
double _sumsvop=0;
double ZeroLevelAll=0;
double tickvalue = MarketInfo(Symbol(), MODE_TICKVALUE);

   for(int i=0; i<OrdersTotal(); i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
      if(OrderSymbol()!=Symbol()) continue;
      if(OrderType()==OP_BUY)
      {
            _lost+=OrderLots();
            _sum+=OrderLots()*OrderOpenPrice(); 
            _sumsvop+=OrderSwap( )+OrderCommission( );
      }
      
      if(OrderType()==OP_SELL)
      {
            _lost-=OrderLots();
            _sum-=OrderLots()*OrderOpenPrice(); 
            _sumsvop+=OrderSwap( )+OrderCommission( );
      }
     }


if (_lost>0)
{ZeroLevelAll=_sum/_lost - (_sumsvop / (tickvalue * (_lost)) * Point);   //уровень безубытка для открытых ордеров, перевес Buy
}

if (_lost<0)
{ZeroLevelAll=_sum/_lost + (_sumsvop/ (tickvalue * (_lost)) * Point);  //уровень безубытка для открытых ордеров, перевес Sell
}



Программный код отличается предыдущего:
— подсчетом суммы свопов и комиссий: _sumsvop+=OrderSwap( )+OrderCommission( )
— Формулой расчета уровня БУ:
ZeroLevelAll=_sum/_lost ± (_sumsvop / (tickvalue * (_lost)) * Point), в которой
первое слагаемое _sum/_lost — расчет арифметического среднего,
а второе (_sumsvop/ (tickvalue * (_lost)) * Point) — коррекция зависящая
от накопленной суммы и направления несбалансированной позиции.( Переведенная в пункты изменения цены)

ПС: В приведенных примерах рассчитывается БУ для всех ордеров (Buy и Sell) по паре.
Для расчета отодельно по Buy или Sell достаточно в теле цикла закоментировать строки относящиеся к ненужным типам ордеров.
  • +6
  • Просмотров: 27653
  • 17 мая 2015, 15:34
  • Fargo
Понравилcя материал? Не забудьте поставить плюс и поделиться в социальной сети!

Вступите в группу "Программирование на MQL", чтобы следить за обновлениями
ПРИСОЕДИНИТЬСЯ К ГРУППЕ
присоединиться
  Предыдущая запись в группе
Индикатор - ускоренная реальность, MT4
Следующая запись в группе  
"CME Loader" полуавтомат
13 мая 2015
16 августа 2015

Брокер для ваших роботов, 15 лет на рынке

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

+
0
Запуталась с последней частью, где деление.
Я использую формулу:
sum/lots - (sumSwapComm*Point)/(TICKVALUE*lots)

Это тоже или нет? *think* 
avatar

  27  Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..

  • 17 мая 2015, 16:45
+
0
*yes*  Тоже самое
А вот насчет знака
sum/lots — (sumSwapComm*Point)/(TICKVALUE*lots)
всегда со знаком минус?
avatar

  13  Fargo Автор Сообщений: 495

  • 17 мая 2015, 18:20
+
0
я со знаком заранее разбираюсь, когда лоты суммирую
avatar

  27  Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..

  • 17 мая 2015, 22:43
+
0
Уровень БУ (обозвала — zeroprice) давно использую в скрипте на паре EURUSD, еще не подводил. Также, если я хочу узнать, как вывести несколько сделок в общий Profit = 10$, то использую:
profitPrice=zeroprice + (Profit*Point)/(TICKVALUE*lots)

Мне вот никак не сочинить формулу:
у нас есть несколько однонаправленных сделок, когда у них наступит stop out? Fargo, может поможешь?
avatar

  27  Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..

  • 17 мая 2015, 16:51
+
0
Хелпе есть такой пример
int level=AccountStopoutLevel();
if(AccountStopoutMode()==0)
Print(«StopOut level = », level, "%");
else
Print(«StopOut level = », level, " ", AccountCurrency());
Если у нас первый случай (в процентах), тогда нужно воспользоватся AccountMargin()
и перевести проценты в деньги.
level= AccountMargin()*level/100;
Далее для текущего положения дел

if(lots > 0) LSO = Bid — ((AccountFreeMargin()+AccountMargin() -level) / (tickvalue * lots)) * Point;
if(lots < 0) LSO = Ask — ((AccountFreeMargin()+AccountMargin() -level) / (tickvalue * lots)) * Point;

Как то так

Ну это на вскидку, я не проверял
Редактирован: 17 мая 2015, 19:15
avatar

  13  Fargo Автор Сообщений: 495

  • 17 мая 2015, 19:13
+
0
спасибо! я проверю, отпишусь. Сама формулу создавала сложнее и она не получилась у меня. Эта проще.
avatar

  27  Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..

  • 17 мая 2015, 22:46
+
0
Вот смотри, у меня StopOut level = 60%
Открыта sell позиция лот 0,03
AccountMargin() => 6.69 — Сумма залоговых средств, она неизменна.
Почему мы эту сумму умножаем на проценты? *think* 

Может надо?: AccountBalance()*level/100

У меня на втором счете StopOut 10%, а на третьем 20%
Т.е. это сколько средств может остаться после StopOut? Т.е. на первом счете после StopOut у меня останется 60% средств?
Редактирован: 19 мая 2015, 16:16
avatar

  27  Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..

  • 19 мая 2015, 15:58
+
+1
Умножаем на проценты StopOut'а, что бы получить его в денежном выражении (зависит от залога по открытым позициям).

Вот хорошую картинку нашел

Структура средств на депозите наглядно
Редактирован: 19 мая 2015, 16:42
avatar

  13  Fargo Автор Сообщений: 495

  • 19 мая 2015, 16:38
+
0
Не согласна я с ней, у меня размер stop-out больше минимального залога.
Твоя формула:
level= AccountMargin()*level/100;

У меня: level= 6.69*60/100 = 4,014 — непонятно, что получилось
А если: AccountBalance()*level/100 => то получается, сколько останется средств после срабатывания stop-out
Так хотя бы понятно, что получилось.
avatar

  27  Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..

  • 19 мая 2015, 16:48
+
0
Хочешь сказать что если у тебя
-начальный баланс 1000$, то при SO 60%, то тебя принудительно закроют если получишь убыток в 400$, т.е. на счету останется 600$? Хорошо, <img src='http://opentraders.ru/templates/skin/g6h/images/smilies/002.gif' alt=' <img src='http://opentraders.ru/templates/skin/g6h/images/smilies/002.gif' alt=' <img src='http://opentraders.ru/templates/skin/g6h/images/smilies/002.gif' alt=' <img src='http://opentraders.ru/templates/skin/g6h/images/smilies/002.gif' alt=' :) '>&nbsp; '>&nbsp; '>&nbsp; '>&nbsp;  идем дальше…
— открыты два ордера с залогом пусть по 100$ за каждый,
— один из ордеров ты закрываешь с прибылью в 500$
— текущий баланс 1500$. Тогда тебя закроют если ты достигнешь по оставшемуся ордеру убытка (1500-(1500*60%)) 600$ и на счету останется 900$, т.е. еще раньше *pardon* 
Так? Ну это, извини, фигня получается

А вот 4.014 понятная цифра, тебе принудительно начнут закрывать убыточные ордера если средства твоего депозита будут <= 4.01$. И останется у тебя на спокойном рынке 4$, если будут проскальзывания на новостях или гэп, то и того меньше.
Редактирован: 20 мая 2015, 08:56
avatar

  13  Fargo Автор Сообщений: 495

  • 19 мая 2015, 17:04
+
0
*** запуталась, может ты и прав
Редактирован: 19 мая 2015, 17:30
avatar

  27  Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..

  • 19 мая 2015, 17:20
+
+1
Что за ДЦ? *think*  Я что то такого не встречал
Обычная схема это примерно как здесь написано smfanton.ru/forex/marzhin-koll-i-stop-aut.html
Редактирован: 19 мая 2015, 17:32
avatar

  13  Fargo Автор Сообщений: 495

  • 19 мая 2015, 17:30
+
0
спасибо
avatar

  27  Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..

  • 19 мая 2015, 17:33
+
+1
В итоге формула stop out для однонаправленных сделок (на паре EURUSD тестировала):
int level=AccountStopoutLevel();
double stopSumm, priceStopOut;
if(AccountStopoutMode()==0) stopSumm = AccountMargin()*(double)level/100;
else                        stopSumm = (double)level;
      
double pips = (AccountFreeMargin() + AccountMargin() - stopSumm)/(MarketInfo(Symb, MODE_TICKVALUE)*summLots);   
if (NamePos==SELL) {
   priceStopOut = Ask + pips*Point;
} else {
  priceStopOut = Bid - pips*Point;
}
priceStopOut = NormalizeDouble(priceStopOut, Digits);

такая же, как у тебя
Редактирован: 21 мая 2015, 17:33
avatar

  27  Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..

  • 19 мая 2015, 17:25
+
0
*yes*  *good* 
avatar

  13  Fargo Автор Сообщений: 495

  • 21 мая 2015, 18:39
+
0
Я не математик *rabota* 
Кто нибудь может обьяснить что тогда считает этот алгоритм?*help* 

gd_240 = 0;
double ld_56 = 0;
for (index = OrdersTotal() - 1; index >= 0; index--)
   {
   OrderSelect(index, SELECT_BY_POS, MODE_TRADES);
   if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber) continue;
   if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
      {
      if (OrderType() == OP_BUY || OrderType() == OP_SELL)
         {
         gd_240 += OrderOpenPrice() * OrderLots();
         ld_56 += OrderLots();
         }
      }
   }
gd_240 = NormalizeDouble(gd_240 / ld_56, Digits);


Мне говорили что высчитывает среднию цену*tipatogo* 
avatar

  8  Kudryashov Сообщений: 129

  • 13 октября 2016, 00:48
+
0
Кто нибудь может обьяснить что тогда считает этот алгоритм


Часть функции для усреднителя, считает среднюю цену открытых позиций одного направления с различным лотом.
avatar

  35  AM2 Сообщений: 16250 - Андрей

  • 13 октября 2016, 01:11
+
0
Ясненько… А чтобы в разных направлениях считал надо разделить if (OrderType() == OP_BUY || OrderType() == OP_SELL) на 2 отдельных ЕСЛИ и дописать их сложения?*pardon* 
avatar

  8  Kudryashov Сообщений: 129

  • 13 октября 2016, 19:16

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