Ошибка в функции CalculateVolume() для участников чемпионата.

 
Функция описана здесь

https://championship.mql5.com/2012/ru/news

Вообще-то мне нужно было оставить комментарий на этой странице. Но я не участник чемпионата и время регистрации прошло. Поэтому пишу здесь. Функция выглядит таким образом

//--- extern variables
extern double ExtMaximumRisk=0.05;             // 5% by default
 
//--- calculate current volume
double CalculateVolume()
  {
   double lot_min =MarketInfo(Symbol(),MODE_MINLOT);
   double lot_max =MarketInfo(Symbol(),MODE_MAXLOT);
   double lot_step=MarketInfo(Symbol(),MODE_LOTSTEP);
   double vol;
//--- check data
   if(lot_min<0 || lot_max<=0.0 || lot_step<=0.0) 
     {
      Print("CalculateVolume: invalid MarketInfo() results [",lot_min,",",lot_max,",",lot_step,"]");
      return(0);
     }
   if(AccountLeverage()<=0)
     {
      Print("CalculateVolume: invalid AccountLeverage() [",AccountLeverage(),"]");
      return(0);
     }
//--- basic formula
   vol=NormalizeDouble(AccountFreeMargin()*ExtMaximumRisk/AccountLeverage()/10.0,2);
//--- additional calculation
//   ...
//--- check min, max and step
   vol=NormalizeDouble(vol/lot_step,0)*lot_step;
   if(vol<lot_min) vol=lot_min;
   if(vol>lot_max) vol=lot_max;
//---
   return(vol);
  }



Ошибка здесь

vol=NormalizeDouble(AccountFreeMargin()*ExtMaximumRisk/AccountLeverage()/10.0,2);



Эта формула работает только для AccountLeverage()=100. Правильная формула должна быть такой

string symbol="USDJPY" // should be passed as a function entry
double contract=MarketInfo(symbol,MODE_LOTSIZE);  // size of 1 lot, for example 100,000 for EURUSD
vol=NormalizeDouble(AccountFreeMargin()*ExtMaximumRisk*AccountLeverage()/contract,2);



Опять же для AccountLeverage()=100 и contract=100000 обе формулы для vol дают один и тот же результат. Но вторая формула правильна для всех ситуаций в которых первой волютой в торгуемой паре является валюта депозита (то есть счёт открыт в USD и торговля происходит в USDxxx). Авторы сайта championship.mql4.com, пожалуйста исправьте ошибку так как ваша страница видна всем МТ пользователям и они могут использовать этот код в своих экспертах предназначенных для более широкого использования.

 
Спасибо за поправку - я внес изменения в пример.
 
Спасибо за поправку - я внес изменения в пример.


Если уж быть точнее, то правильная формула такая :

vol=NormalizeDouble(AccountFreeMargin()*ExtMaximumRisk*AccountLeverage()/contract,nLotsDigits);



величину nLotsDigits можно вычислить, например так :

int nLotsDigits    = MathCeil(MathAbs(MathLog(MarketInfo(Symbol(),MODE_MINLOT))/MathLog(10)));



;).

Удачи и попутных трендов.

 
величину nLotsDigits можно вычислить, например так :
int nLotsDigits = MathCeil(MathAbs(MathLog(MarketInfo(Symbol(),MODE_MINLOT))/MathLog(10)));



а может вместо MODE_MINLOT в вашей формуле использовать MODE_LOTSTEP?
Хотя, для моего брокера эти величины совпадают.

А можно, я думаю использовать и такую формулу:
double nLotStep = MarketInfo(Symbol(),MODE_LOTSTEP);
vol=MathFloor(AccountFreeMargin()*ExtMaximumRisk*AccountLeverage()/contract/nLotStep)*nLotStep ;


 

а может вместо MODE_MINLOT в вашей формуле использовать MODE_LOTSTEP?
Хотя, для моего брокера эти величины совпадают.


Вообще было бы странно, если они не совпадали бы. Одна величина показывает размер минимально возможного лота, вторая минимально возможной "доливки". Но когда ордера выставлены, то доливка и расчитывается как количество ордеров, которое можно выставить и его минимальное значение не может быть меньше, правда может быть больше, но с какой стати то ?
Думаю, значения иметь не будет что там использовать - главное принцип: получить количество знаков мантиссы в ордере.

С уважением, Владислав.
Удачи и попутных трендов.