Фиксированный процент от депозита

 
Здравствуйте. Есть у кого-то функция расчета лота исходя из фиксированного риска в процентах на сделку? 
 
Igor Knyazkov:
Здравствуйте. Есть у кого-то функция расчета лота исходя из фиксированного риска в процентах на сделку? 

Вот (риск задаётся в строке)

   m_money.Percent(10); // 10% risk

после расчёта объёма дополнительно проверяется, а хватит ли денег (маржи) на открытие позиции:
//+------------------------------------------------------------------+
//|                                          TestCMoneyFixedRisk.mq5 |
//|                              Copyright © 2016, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2016, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.00"
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>  
#include <Trade\AccountInfo.mqh>
#include <Expert\Money\MoneyFixedRisk.mqh>
CTrade         m_trade;                      // trading object
CSymbolInfo    m_symbol;                     // symbol info object
CAccountInfo   m_account;                    // account info wrapper
CMoneyFixedRisk m_money;
//---
input ushort   InpStopLoss=25;
//---
double ExtStopLoss=0.0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   m_symbol.Name(Symbol());
   m_symbol.Refresh();
   if(!RefreshRates())
     {
      Print("Error RefreshRates. Bid=",DoubleToString(m_symbol.Bid(),Digits()),
            ", Ask=",DoubleToString(m_symbol.Ask(),Digits()));
      return(INIT_FAILED);
     }
//--- tuning for 3 or 5 digits
   int digits_adjust=1;
   if(m_symbol.Digits()==3 || m_symbol.Digits()==5)
      digits_adjust=10;
   ExtStopLoss=InpStopLoss*m_symbol.Point()*digits_adjust;
//---
   if(!m_money.Init(GetPointer(m_symbol),Period(),m_symbol.Point()*digits_adjust))
      return(INIT_FAILED);
   m_money.Percent(10); // 10% risk
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   if(!RefreshRates())
      return;

   static long count=0;
   if(count%980==0) // we pass 980 tics
     {
      //--- getting lot size for open long position (CMoneyFixedRisk)
      double check_open_long_lot=m_money.CheckOpenLong(m_symbol.Ask(),m_symbol.Bid()-ExtStopLoss);
      Print("CheckOpenLong: ",DoubleToString(check_open_long_lot,2),
            ", Balance: ",    DoubleToString(m_account.Balance(),2),
            ", Equity: ",     DoubleToString(m_account.Equity(),2),
            ", FreeMargin: ", DoubleToString(m_account.FreeMargin(),2));
      if(check_open_long_lot==0.0)
         return;

      //--- check volume before OrderSend to avoid "not enough money" error (CTrade)
      double chek_volime_lot=m_trade.CheckVolume(m_symbol.Name(),check_open_long_lot,m_symbol.Ask(),ORDER_TYPE_BUY);

      if(chek_volime_lot!=0.0)
         if(chek_volime_lot>=check_open_long_lot)
            m_trade.Buy(chek_volime_lot,NULL,m_symbol.Ask(),m_symbol.Bid()-ExtStopLoss,m_symbol.Bid()+ExtStopLoss);
      else
         Print("CMoneyFixedRisk lot = ",DoubleToString(check_open_long_lot,2),
               ", CTrade lot = ",DoubleToString(chek_volime_lot,2));
      //---
     }
   count++;
  }
//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data                                 |
//+------------------------------------------------------------------+
bool RefreshRates()
  {
//--- refresh rates
   if(!m_symbol.RefreshRates())
      return(false);
//--- protection against the return value of "zero"
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
      return(false);
//---
   return(true);
  }
//+------------------------------------------------------------------+


Как это работает:

Первая сделка открыта (рассчитанный лот в процентах от депозита равен 1.14 и денег (маржи) для его открытия хватает):

Шаг первый

Шаг второй (рассчитанный лот в процентах от депозита равен 1.16 и денег (маржи) для его открытия хватает):

Шаг второй

А вот на третьем шаге неудача: (рассчитанный лот в процентах от депозита равен 1.08 но денег (маржи) для хватает только на открытие 0.24 лота):

Шаг три 

Файлы:
 
Вот еще вариант
double volume(string symbol,double risk,double sl)
  {
   double lot=0.0;
   double procent=0.0;
   double balans=0.0;
   double tc = SymbolInfoDouble(symbol,SYMBOL_TRADE_CONTRACT_SIZE);
   double tv = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE_LOSS);
   double ts=SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
   double LotStep=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
   if(Type_Balanse==Balance) balans=AccountInfoDouble(ACCOUNT_BALANCE);
   if(Type_Balanse==Equity) balans=AccountInfoDouble(ACCOUNT_EQUITY);
   if(Type_Balanse==FreeMargin) balans=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
   procent=(balans/100.0)*risk;

   switch((ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol,SYMBOL_TRADE_CALC_MODE))
     {
      case SYMBOL_CALC_MODE_FOREX:if(sl!=0 && tv!=0) lot=procent/(sl*tv);break;
      case SYMBOL_CALC_MODE_FUTURES:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
      case SYMBOL_CALC_MODE_CFD:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_CFDINDEX:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_CFDLEVERAGE:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_EXCH_STOCKS:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_EXCH_FUTURES:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
      case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
     }
   return(NormalizeVolume(symbol,lot));
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double NormalizeVolume(string symbol,double lot)
  {
   double MinLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
   double MaxLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
   double volume_step=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
   int volume_digits=(int)(MathLog(1.0/volume_step)/MathLog(10.0));

   if(lot<MinLot)lot=MinLot;
   if(lot>MaxLot)lot=MaxLot;

   return(NormalizeDouble(lot,volume_digits));
  }
...
 
Комментарии, не относящиеся к этой теме, были перенесены в "Фиксированный процент от депозита".
 
Всем спасибо!
 
Sergey Gritsay:
Вот еще вариант
double volume(string symbol,double risk,double sl)
  {
   double lot=0.0;
   double procent=0.0;
   double balans=0.0;
   double tc = SymbolInfoDouble(symbol,SYMBOL_TRADE_CONTRACT_SIZE);
   double tv = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE_LOSS);
   double ts=SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
   double LotStep=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
   if(Type_Balanse==Balance) balans=AccountInfoDouble(ACCOUNT_BALANCE);
   if(Type_Balanse==Equity) balans=AccountInfoDouble(ACCOUNT_EQUITY);
   if(Type_Balanse==FreeMargin) balans=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
   procent=(balans/100.0)*risk;

   switch((ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol,SYMBOL_TRADE_CALC_MODE))
     {
      case SYMBOL_CALC_MODE_FOREX:if(sl!=0 && tv!=0) lot=procent/(sl*tv);break;
      case SYMBOL_CALC_MODE_FUTURES:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
      case SYMBOL_CALC_MODE_CFD:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_CFDINDEX:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_CFDLEVERAGE:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_EXCH_STOCKS:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_EXCH_FUTURES:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
      case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
     }
   return(NormalizeVolume(symbol,lot));
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double NormalizeVolume(string symbol,double lot)
  {
   double MinLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
   double MaxLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
   double volume_step=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
   int volume_digits=(int)(MathLog(1.0/volume_step)/MathLog(10.0));

   if(lot<MinLot)lot=MinLot;
   if(lot>MaxLot)lot=MaxLot;

   return(NormalizeDouble(lot,volume_digits));
  }
...
А что это за переменные: Type_Balance, Balance, Equity, FreeMargin? Как их инициализировать.
 
Igor Knyazkov:
А что это за переменные: Type_Balance, Balance, Equity, FreeMargin? Как их инициализировать.
Так ясно по смыслу. Type_Balance - переменная, в которой указывается, по какому параметру проводим расчет, по балансу, средствам или свободной марже. Все, как в терминале нарисовано во вкладке Торговля
 
Igor Knyazkov:
А что это за переменные: Type_Balance, Balance, Equity, FreeMargin? Как их инициализировать.
Примерно так 
//+------------------------------------------------------------------+
//|                                                       test01.mq5 |
//|                                                   Sergey Gritsay |
//|                         https://www.mql5.com/ru/users/sergey1294 |
//+------------------------------------------------------------------+
#property copyright "Sergey Gritsay"
#property link      "https://www.mql5.com/ru/users/sergey1294"
#property version   "1.00"
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_TYPE_BALANS
  {
   Balance,
   Equity,
   FreeMargin
  };

input int Magic=5;//Identification number
input ENUM_TYPE_BALANS Type_Balanse=Balance;
input double Risk=1.0;
input double  Lot=0.01;
input int     StopLoss=100;    // Стоп-лосс
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick(void)
  {
   if(Risk!=0.0)Volume=volume(_Symbol,Risk,StopLoss);
   else Volume=NormalizeVolume(_Symbol,Lot);

  }
//+------------------------------------------------------------------+
double volume(string symbol,double risk,double sl)
  {
   double lot=0.0;
   double procent=0.0;
   double MinLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
   double MaxLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
   double balans=0.0;
   double tc = SymbolInfoDouble(symbol,SYMBOL_TRADE_CONTRACT_SIZE);
   double tv = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE_LOSS);
   double ts=SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
   double LotStep=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
   if(Type_Balanse==Balance) balans=AccountInfoDouble(ACCOUNT_BALANCE);
   if(Type_Balanse==Equity) balans=AccountInfoDouble(ACCOUNT_EQUITY);
   if(Type_Balanse==FreeMargin) balans=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
   procent=(balans/100.0)*risk;

   switch((ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol,SYMBOL_TRADE_CALC_MODE))
     {
      case SYMBOL_CALC_MODE_FOREX:if(sl!=0 && tv!=0) lot=procent/(sl*tv);break;
      case SYMBOL_CALC_MODE_FUTURES:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
      case SYMBOL_CALC_MODE_CFD:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_CFDINDEX:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_CFDLEVERAGE:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_EXCH_STOCKS:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_EXCH_FUTURES:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
      case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
     }
   return(NormalizeVolume(symbol,lot));
  }
//+------------------------------------------------------------------+
double NormalizeVolume(string symbol,double lot)
  {
   double MinLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
   double MaxLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
   double volume_step=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
   int volume_digits=(int)(MathLog(1.0/volume_step)/MathLog(10.0));

   if(lot<MinLot)lot=MinLot;
   if(lot>MaxLot)lot=MaxLot;

   return(NormalizeDouble(lot,volume_digits));
  }
//+------------------------------------------------------------------+
...
 
Sergey Gritsay:
Примерно так 
//+------------------------------------------------------------------+
//|                                                       test01.mq5 |
//|                                                   Sergey Gritsay |
//|                         https://www.mql5.com/ru/users/sergey1294 |
//+------------------------------------------------------------------+
#property copyright "Sergey Gritsay"
#property link      "https://www.mql5.com/ru/users/sergey1294"
#property version   "1.00"
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_TYPE_BALANS
  {
   Balance,
   Equity,
   FreeMargin
  };

input int Magic=5;//Identification number
input ENUM_TYPE_BALANS Type_Balanse=Balance;
input double Risk=1.0;
input double  Lot=0.01;
input int     StopLoss=100;    // Стоп-лосс
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick(void)
  {
   if(Risk!=0.0)Volume=volume(_Symbol,Risk,StopLoss);
   else Volume=NormalizeVolume(_Symbol,Lot);

  }
//+------------------------------------------------------------------+
double volume(string symbol,double risk,double sl)
  {
   double lot=0.0;
   double procent=0.0;
   double MinLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
   double MaxLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
   double balans=0.0;
   double tc = SymbolInfoDouble(symbol,SYMBOL_TRADE_CONTRACT_SIZE);
   double tv = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE_LOSS);
   double ts=SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
   double LotStep=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
   if(Type_Balanse==Balance) balans=AccountInfoDouble(ACCOUNT_BALANCE);
   if(Type_Balanse==Equity) balans=AccountInfoDouble(ACCOUNT_EQUITY);
   if(Type_Balanse==FreeMargin) balans=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
   procent=(balans/100.0)*risk;

   switch((ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol,SYMBOL_TRADE_CALC_MODE))
     {
      case SYMBOL_CALC_MODE_FOREX:if(sl!=0 && tv!=0) lot=procent/(sl*tv);break;
      case SYMBOL_CALC_MODE_FUTURES:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
      case SYMBOL_CALC_MODE_CFD:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_CFDINDEX:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_CFDLEVERAGE:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_EXCH_STOCKS:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_EXCH_FUTURES:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
      case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
     }
   return(NormalizeVolume(symbol,lot));
  }
//+------------------------------------------------------------------+
double NormalizeVolume(string symbol,double lot)
  {
   double MinLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
   double MaxLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
   double volume_step=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
   int volume_digits=(int)(MathLog(1.0/volume_step)/MathLog(10.0));

   if(lot<MinLot)lot=MinLot;
   if(lot>MaxLot)lot=MaxLot;

   return(NormalizeDouble(lot,volume_digits));
  }
//+------------------------------------------------------------------+
...
Спасибо.
 
Sergey Gritsay:
Вот еще вариант
double volume(string symbol,double risk,double sl)
  {
   double lot=0.0;
   double procent=0.0;
   double balans=0.0;
   double tc = SymbolInfoDouble(symbol,SYMBOL_TRADE_CONTRACT_SIZE);
   double tv = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE_LOSS);
   double ts=SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
   double LotStep=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
   if(Type_Balanse==Balance) balans=AccountInfoDouble(ACCOUNT_BALANCE);
   if(Type_Balanse==Equity) balans=AccountInfoDouble(ACCOUNT_EQUITY);
   if(Type_Balanse==FreeMargin) balans=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
   procent=(balans/100.0)*risk;

   switch((ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol,SYMBOL_TRADE_CALC_MODE))
     {
      case SYMBOL_CALC_MODE_FOREX:if(sl!=0 && tv!=0) lot=procent/(sl*tv);break;
      case SYMBOL_CALC_MODE_FUTURES:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
      case SYMBOL_CALC_MODE_CFD:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_CFDINDEX:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_CFDLEVERAGE:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_EXCH_STOCKS:if(sl!=0 && point!=0 && tc!=0) lot=procent/(sl*point*tc);break;
      case SYMBOL_CALC_MODE_EXCH_FUTURES:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
      case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:if(sl!=0 && point!=0 && tv!=0 && ts!=0) lot=procent/(sl*point*(tv/ts));break;
     }
   return(NormalizeVolume(symbol,lot));
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double NormalizeVolume(string symbol,double lot)
  {
   double MinLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
   double MaxLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
   double volume_step=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
   int volume_digits=(int)(MathLog(1.0/volume_step)/MathLog(10.0));

   if(lot<MinLot)lot=MinLot;
   if(lot>MaxLot)lot=MaxLot;

   return(NormalizeDouble(lot,volume_digits));
  }
...
Есть проблема...Почему-то, при установке риска в 1% загрузка депозита получается в районе 5%...Вы пользовались этой функцией?
 
Igor Knyazkov:
Есть проблема...Почему-то, при установке риска в 1% загрузка депозита получается в районе 5%...Вы пользовались этой функцией?
да, постоянно, и при чем тут загрузка?