Не могу сделать ее универсальной, чтобы и для прямой, обратной и кроссовой пары работало....
Может у кого уже есть готовый пример?
Что-то вроде:
Когда-то уже писал пример расчета размера лота по проценту риска. Искать долго, вот что-то в этом роде попробуйте (может будет полезно).
Набор функций для расчета размера лота:
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 не обрабатывается, таким образом эта ситуация может привести к проблемам (если нужно обработать то тут придется в параметры добавлять тип ордера и цену открытия)...
Для чего нужны:
SYMBOL_MARGIN_INITIAL |
Начальная (инициирующая) маржа обозначает размер необходимых залоговых средств в маржинальной валюте для открытия позиции объемом в один лот. Используется при проверке средств клиента при входе в рынок. |
double |
SYMBOL_MARGIN_MAINTENANCE |
Поддерживающая маржа по инструменту. В случае если задана – указывает размер маржи в маржинальной валюте инструмента, удерживаемой с одного лота. Используется при проверке средств клиента при изменении состояния счета клиента. Если поддерживающая маржа равна 0, то используется начальная маржа. |
В SymbolInfoDouble() они просто выдают ноль!
bool OrderCalcMargin( ENUM_ORDER_TYPE action // тип ордера string symbol // имя символа double volume // объем double price // цена открытия????????????????????????????? double& margin // переменная для получения значения маржи );Что за цена открытия????
- www.mql5.com
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Не могу сделать ее универсальной, чтобы и для прямой, обратной и кроссовой пары работало....
Может у кого уже есть готовый пример?
Что-то вроде:
И еще вопрос:
Для чего нужны:
SYMBOL_MARGIN_INITIAL
Начальная (инициирующая) маржа обозначает размер необходимых залоговых средств в маржинальной валюте для открытия позиции объемом в один лот. Используется при проверке средств клиента при входе в рынок.
double
SYMBOL_MARGIN_MAINTENANCE
Поддерживающая маржа по инструменту. В случае если задана – указывает размер маржи в маржинальной валюте инструмента, удерживаемой с одного лота. Используется при проверке средств клиента при изменении состояния счета клиента. Если поддерживающая маржа равна 0, то используется начальная маржа.
В SymbolInfoDouble() они просто выдают ноль!