Расчет уровня БУ (методы, формулы и примеры кода)
•
• Программирование на MQL
В нескольких топиках довелось участвовать в сраче обсуждении того, как рассчитывать уровень без убытка…
И вроде бы не сложный вопрос, вызывает порой серьезные затруднения и буйный полет фантазии в решениях
На самом деле все очень просто. Расскажу как это делаю я
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) одного типа и вычитая объемы противоположных ордеров, определим — не является ли сумма ордеров равновесной?
Ведь если объем ордеров на покупку, равен объему ордеров на продажу, то уровня без убытка просто не существует.
Теперь рассмотрим, как подсчитывается «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 на момент достижения этого уровня БУ.
И как же в таком случае быть?
Лично я пришел к выводу, что в практике расчета уровня БУ в советниках, не требуется совершенно точно вычислять уровень БУ.
Если цена находится далеко от предполагаемого уровня, то погрешность вычисления может быть достаточно большой.
Все равно, так как в процессе удержания позиции величина накопленных комиссий и свопов изменяется, то уровень БУ требуется пересчитывать.
И по мере приближения к этому уровню, уточняются значения курсов влияющих на стоимость одного пункта.
А значит и расчет уровня БУ становится точнее.
Общая идея (алгоритм) расчета уровня БУ с учетом комиссий и свопов в следующем:
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 достаточно в теле цикла закоментировать строки относящиеся к ненужным типам ордеров.