Максимально возможный объем для депозита

 
Существует SYMBOL_VOLUME_MAX, а также  OrderCalcMargin(). Но при проверке SYMBOL_VOLUME_MAX с помощью данной функции, с депозитом в $10000, выясняется, что с данным объемом в рынок войти невозможно. Как узнать максимально возможный объем для входа в рынок с текущим депозитом?
 

Проверил код на демо счёте. 

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart() {
  string symbol = Symbol();
  double maxLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
  double margin;
  if(!OrderCalcMargin(ORDER_TYPE_BUY, symbol, maxLot, SymbolInfoDouble(symbol, SYMBOL_ASK), margin)) {
    Print("Not enough money to make a deal!");
    // Пересчёт максимального лота для текущего депозита
    // ...
  }
}
//+------------------------------------------------------------------+

Получается, на демо maxLot проходит проверку, но в советнике, на тестере, вылетает сообщение " Not enough money to make a deal!" и позиция с объемом maxLot не открывается, хоть, размер депозита, как на тестере так и на демо 10000. На демо даже меньше немного. Как можно вычислить максимально возможный лот, если  OrderCalcMargin дает фальш?

Файлы:
 

Читал и использую данные проверки в своих программах. Только не понимаю, из-за чего может быть такая ситуация. В логе журнала тестера пишет следующее:

2019.10.06 13:22:07.405 Core 1  2012.04.19 02:33:00   current account state: Balance: 47730.00, Credit: 0.00, Commission: 0.00, Accumulated: 0.00, Assets: 0.00, Liabilities: 0.00, Equity 47730.00, Margin: 0.00, FreeMargin: 47730.00
2019.10.06 13:22:07.405 Core 1  2012.04.19 02:33:00   calculated account state: Assets: 0.00, Liabilities: 0.00, Equity 47730.00, Margin: 655515.00, FreeMargin: -607785.00
2019.10.06 13:22:07.405 Core 1  2012.04.19 02:33:00   not enough money [instant sell 500.00 EURUSD at 1.31103 sl: 1.31603]
2019.10.06 13:22:07.405 Core 1  2012.04.19 02:33:00   failed instant sell 500.00 EURUSD at 1.31103 sl: 1.31603 [No money]

Из лога видно, что депозит у меня не 10000, а 47730. То есть взлетел до небес. Почему же при хорошем Equity и тем более марже продажа не открывается с лотом 500.0, если аналогичные сделки открываются с депозитом всего 10000? И свободная маржа с каким-то странным значением... -607785.00... Ничего не понимаю...

 

Поставил проверку CheckMoneyForTrade (https://www.mql5.com/ru/articles/2555#not_enough_money), которая у меня не допускает срабатывание функции OrderSend (если данные проверку не прошли) выдает сообщение о нехватке средств на депозите:

2019.10.06 17:15:02.028 Core 1  2012.05.03 14:53:00   Not enough money for ORDER_TYPE_BUY 500.0 EURUSD Error code: 0
Но депозит, повторюсь, вырос аж до  47730.00, с 10000 и тут терминал не пропускает объем в 500.0, что соответствует SYMBOL_VOLUME_MAX. Ошибок нет  - "Error code: 0", но на депозите недостаточно средств. Как такое может быть?
Какие проверки должен пройти торговый робот перед публикацией в Маркете
Какие проверки должен пройти торговый робот перед публикацией в Маркете
  • www.mql5.com
Все продукты Маркета перед публикацией проходят обязательную предварительную проверку, так как небольшая ошибка в логике советника или индикатора может привести к убыткам на торговом счете. Именно поэтому нами разработана серия базовых проверок, призванных обеспечить необходимый уровень качества продуктов Маркета. Если в процессе проверки...
 
Mihail Matkovskij:

Проверил код на демо счёте. 

Получается, на демо maxLot проходит проверку, но в советнике, на тестере, вылетает сообщение " Not enough money to make a deal!" и позиция с объемом maxLot не открывается, хоть, размер депозита, как на тестере так и на демо 10000. На демо даже меньше немного. Как можно вычислить максимально возможный лот, если  OrderCalcMargin дает фальш?

Кроме проверки

if(!OrderCalcMargin

нужно проверить, как минимум

if(margin>0.0


а ещё лучше (по крайней мере я тай делаю) - чтобы margin хватало на ещё одну такую-же позицию.


Пример кода: в OnInit распечатывает максимальный лот; если параметр Start поставить в "true" - то он выдаст сигнал на открытие позиции заданным лотом ( Money management: Lot OR Risk ставится в Constant lot, а The value for "Money management" в 500.0)

Файлы:
 
Vladimir Karputov:

Кроме проверки

нужно проверить, как минимум


а ещё лучше (по крайней мере я тай делаю) - чтобы margin хватало на ещё одну такую-же позицию.


Пример кода: в OnInit распечатывает максимальный лот; если параметр Start поставить в "true" - то он выдаст сигнал на открытие позиции заданным лотом ( Money management: Lot OR Risk ставится в Constant lot, а The value for "Money management" в 500.0)

Спасибо! Поэкспериментирую со свободной маржой...

 

Поэкспериментировал со свободной маржой:

  double volumeChecked;
  
  double cutVoluneByFreeMargin(string _symbol, double _volume, int _stopLoss, ENUM_ORDER_TYPE _type) {
    
    volumeChecked = false;
    
    double lotValue = SymbolInfoDouble(_symbol, SYMBOL_TRADE_TICK_VALUE);
    double freeMargin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
    
    double maxLot_ = (freeMargin * 0.3 / _stopLoss) / lotValue; // работает только начиная с 0.3 от freeMargin 
    
    double maxLot = SymbolInfoDouble(_symbol, SYMBOL_VOLUME_MAX);
     
    if(maxLot_ > maxLot)
      maxLot_ = maxLot;
    
    double lot = (_volume <= maxLot_) ? _volume : maxLot_;
    
    // проверка на достаток средств для входа в рынок  
    MqlTick mqltick;
    SymbolInfoTick(_symbol, mqltick);
    double price;
    switch(_type) {
    case ORDER_TYPE_BUY:
      price = mqltick.ask;
      break;
    case ORDER_TYPE_SELL:
      price = mqltick.bid;
      break;
    default:
      Print(__FUNCTION__," Error! Line:", __LINE__);
      return 0;
    }
    
    double margin;
    
    if(!OrderCalcMargin(_type, _symbol, lot, price, margin)) {
      //--- что-то пошло не так
      Print("Error in ",__FUNCTION__," code: ",GetLastError());
      return 0;
    }
    //--- если не хватает средств на проведение операции
    if(margin > freeMargin) {
      //--- сообщим об ошибке и вернем false
      Print("Not enough money for ",EnumToString(_type)," ", lot," ",_symbol," Error code: ",GetLastError());
      Print("margin: ", margin, " freeMargin: ", freeMargin, " lot: ", lot);
      return 0;
    }
    volumeChecked = true;
    return lot;
  }

Но функция пропускает объем рассчитанный со значением не  более чем 0.3 * freeMargin

double maxLot_ = (freeMargin * 0.3 / _stopLoss) / lotValue;

Почему получилась именно такая закономерность? Может быть, я неправильно рассчитываю максимально возможный лот?

 

А теперь попался мне случай, когда даже лот с 0.3 от свободной маржи не работает. Инструмент USDSEK. Срабатывает условие:

    //--- если не хватает средств на проведение операции
    if(margin > freeMargin) {
      //--- сообщим об ошибке и вернем false
      Print("Not enough money for ",EnumToString(_type)," ", lot," ",_symbol," Error code: ",GetLastError());
      Print("margin: ", margin, " freeMargin: ", freeMargin, " lot: ", lot);
      return 0;
    }

И функция cutVoluneByFreeMargin возвращает 0. Как вычислить правильный максимальный лот в случае срабатывания этого условия (когда  margin > freeMargin) или как лучше правильно рассчитать максимальный лот  maxLot_, чтобы данное условие не срабатывало?