Нужна функция, которая по определенной сумме выдает объем сделки для определенного символа.

 

Не могу сделать ее универсальной, чтобы и для прямой, обратной и кроссовой пары работало....

Может у кого уже есть готовый пример?

Что-то вроде:

double GetLot( string symbol, double allow_margin )


И еще вопрос:

Для чего нужны:

SYMBOL_MARGIN_INITIAL

Начальная (инициирующая) маржа обозначает размер необходимых залоговых средств в маржинальной валюте для открытия позиции объемом в один лот. Используется при проверке средств клиента при входе в рынок.

double

SYMBOL_MARGIN_MAINTENANCE

Поддерживающая маржа по инструменту. В случае если задана – указывает размер маржи в маржинальной валюте инструмента, удерживаемой с одного лота. Используется при проверке средств клиента при изменении состояния счета клиента. Если поддерживающая маржа равна 0, то используется начальная маржа.


В SymbolInfoDouble() они просто выдают ноль!

 
extern.fx:

Не могу сделать ее универсальной, чтобы и для прямой, обратной и кроссовой пары работало....

Может у кого уже есть готовый пример?

Что-то вроде:

double GetLot( string symbol, double allow_margin )



Когда-то уже писал пример расчета размера лота по проценту риска. Искать долго, вот что-то в этом роде попробуйте (может будет полезно).

Набор функций для расчета размера лота:

1. CalculateVolume - рассчитывает размер лота на основе типа ордера (ENUM_ORDER_TYPE), цены открытия, процента риска и размера свободных средств;

Основная функция

//Function CalculateVolume
double CalculateVolume(string symbol="",ENUM_ORDER_TYPE action=ORDER_TYPE_BUY,double OpenPrice=0.0,double Percent=10.0)
//Вычисляем размер лота
{
//----------------------------------------------------------------------------//
//Work variables
double FreeMargin, MarginSize, MarginStd;

int Laverage;

double Lots;
//----------------------------------------------------------------------------//
//Защита от дурака
  if(symbol==""){symbol=Symbol();}
//Текущий размер свободных средств
FreeMargin  = AccountInfoDouble(ACCOUNT_FREEMARGIN);
//Размер торгового плеча для счета
Laverage = (int)AccountInfoInteger(ACCOUNT_LEVERAGE);
//Расчет лота для открытия позиции
MarginSize = MarginOptimumSize(FreeMargin,Percent,Laverage);

OrderCalcMargin(action,symbol,1.0,OpenPrice,MarginStd);

Lots = LotOptimumSize(symbol,MarginSize,MarginStd);
//----------------------------------------------------------------------------//
return(Lots);
//----------------------------------------------------------------------------//
}

2. MarginOptimumSize - возвращает "Оптимальный" размер залога, на который можно открыть новую позицию (без учета торговых операций). Расчет ведется на основе свободных средств, процента риска и торгового плеча;

//Function MarginOptimumSize
double MarginOptimumSize(double FreeMargin=0.0,double Percent=10.0,long Leverage=100)
//Функция производит расчет оптимального размера залога для ордера или позиции
{
//----------------------------------------------------------------------------//
//Служебные переменные
double Margin; //Сумма залога
double Result; //Возвращаемое значение
//----------------------------------------------------------------------------//
//Защита от дурака!
  if(FreeMargin<=0.0)
  {
  FreeMargin = AccountInfoDouble(ACCOUNT_FREEMARGIN);
  }
//Произведем расчет залога исходя из Leverage = 100 (Плечо 100 как стандарт)
Margin = (FreeMargin/100)*Percent;
//Оптимизируем сумму залога под реальный Leverage (предпологаем что Leverage>=100)
  if(Leverage==100)
  //Счет со стандартным торговым плечом в 100
  {
  Result = Margin; //Раз плечо стандартно оптимизация не нужна!
  }
  else
  //Особые условия, выполним оптимизацию
  {

    if(Leverage>100)
    //Плечо больше 100
    {
    Result = Margin/NormalizeDouble(Leverage/100,0);
    }
    else
    //плечо меньше 100
    {
    Result = Margin/NormalizeDouble(100/Leverage,0);
    }

  }
//----------------------------------------------------------------------------//
return(Result);
//----------------------------------------------------------------------------//
}

3. LotOptimumSize - Функция производит расчет размера лота для ордеров и позиций на основе "оптимальной" маржи и залога необходимого для стандартного лота...

Расчет ведется с учетом характеристик символа

//Function LotOptimumSize
double LotOptimumSize(string WorkSymbol,double MarginOptimal=0.0,double MarginStd=0.0)
//Функция производит расчет оптимального размера лота для ордеров и позиций
{
//----------------------------------------------------------------------------//
//Служебные переменные
//Минимальный и максимальный размеры лотов, а также шаг
double SymbolLotMin,SymbolLotMax,SymbolLotStep;
double StepSumm,LotStepCount; //Необходимы для расчета лота
double LotSize; //Размер лота
double Result;  //Возвращаемое значение
//----------------------------------------------------------------------------//

//Защита от дурака!
  if(MarginOptimal<=0.0)
  {
  MarginOptimal = MarginOptimumSize(AccountInfoDouble(ACCOUNT_FREEMARGIN));
  }
//Получаем вилку по размерам лота
SymbolLotMin  = SymbolInfoDouble(WorkSymbol,SYMBOL_VOLUME_MIN);  //Минимальный лот
SymbolLotMax  = SymbolInfoDouble(WorkSymbol,SYMBOL_VOLUME_MAX);  //Максимальный лот
SymbolLotStep = SymbolInfoDouble(WorkSymbol,SYMBOL_VOLUME_STEP); //Шаг лотов
//Расчитываем размер лота
  if(MarginOptimal<MarginStd)
  //Указанной маржи не достаточно для открытия хотябы одного стандартного лота
  //Необходимо получить размер лота который мы можем открыть
  {
  LotSize = NormalizeDouble(MarginStd/MarginOptimal,2);
  }
  else
  //Достоточно маржи для открытия как минимум одного стандартного лота
  {
  LotSize = NormalizeDouble(MarginOptimal/MarginStd,2);
  }
//Оптимизируем размер лота под торговые условия
//Оптимизация. Шаг №1 - Проверка на мин и макс значения размера лота
  if(LotSize<SymbolLotMin){LotSize=SymbolLotMin;} //Лот меньше минимального
  if(LotSize>SymbolLotMax){LotSize=SymbolLotMax;} //Лот больше максимального
//Оптимизация. Шаг №2 - Перерасчет размера лота
  if(LotSize>SymbolLotMin)
  {
  StepSumm = LotSize-SymbolLotMin;
  LotStepCount = StepSumm/SymbolLotStep-NormalizeDouble(MathMod(StepSumm/SymbolLotStep,1.0),2);
  LotSize = SymbolLotMin+LotStepCount*SymbolLotStep;
  }
Result = LotSize;
//----------------------------------------------------------------------------//
return(Result);
//----------------------------------------------------------------------------//
}

PS

На счет счетов где торговое плечо меньше 100 я не уверен, но такой алгоритм расчета меня вполне устраивает.

MarginStd = 0.0 в LotOptimumSize не обрабатывается, таким образом эта ситуация может привести к проблемам (если нужно обработать то тут придется в параметры добавлять тип ордера и цену открытия)...


 
extern.fx:

Для чего нужны:

SYMBOL_MARGIN_INITIAL

Начальная (инициирующая) маржа обозначает размер необходимых залоговых средств в маржинальной валюте для открытия позиции объемом в один лот. Используется при проверке средств клиента при входе в рынок.

double

SYMBOL_MARGIN_MAINTENANCE

Поддерживающая маржа по инструменту. В случае если задана – указывает размер маржи в маржинальной валюте инструмента, удерживаемой с одного лота. Используется при проверке средств клиента при изменении состояния счета клиента. Если поддерживающая маржа равна 0, то используется начальная маржа.


В SymbolInfoDouble() они просто выдают ноль!


Они вроде и в MT4 выдавали 0, по крайней мере я так и не добился там иного результата...
 
bool  OrderCalcMargin(
   ENUM_ORDER_TYPE       action           // тип ордера
   string                symbol           // имя символа
   double                volume           // объем
   double                price            // цена открытия?????????????????????????????
   double&               margin           // переменная для получения значения маржи
   );
Что за цена открытия????
Документация по MQL5: Стандартные константы, перечисления и структуры / Константы индикаторов / Ценовые константы
Документация по MQL5: Стандартные константы, перечисления и структуры / Константы индикаторов / Ценовые константы
  • www.mql5.com
Стандартные константы, перечисления и структуры / Константы индикаторов / Ценовые константы - Документация по MQL5
 
extern.fx:
Что за цена открытия????

Почитайте статью Ограничения и проверки в экспертах, попробуйте запустить приложенный к ней скрипт Check_Money.mq5.
 
extern.fx:
Что за цена открытия????

Текущий бид/аск по ходу  (цена по которой будет открыта поза или на которую будет поставлен отложник). В зависимости от типа ордера, если Buy то Ask....
Причина обращения: