попробуйте такой вариант. Если задан стоплосс в пипсах то расчет по первой функции, если задан 0, то по второй.
//| test09.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=0,
Equity=1,
FreeMargin=2
};
input ENUM_TYPE_BALANS Type_Balanse=Balance;//Method calculation Volume
input double Risk=1.0;
input int StopLoss=300;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
double Volume = (StopLoss!=0)?volume(_Symbol,Risk,StopLoss):volume(_Symbol,ORDER_TYPE_BUY,Risk);
Comment("Volume = ",Volume);
}
//+------------------------------------------------------------------+
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 volume(string symbol,ENUM_ORDER_TYPE type,double risk)
{
double lot=0.0;
double balans=0.0;
double margin=0.0;
int digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
double bid=NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_BID),digits);
double ask=NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_ASK),digits);
double price=(type==ORDER_TYPE_BUY)?ask:bid;
if(!OrderCalcMargin(type,symbol,1.0,price,margin))return(NormalizeVolume(symbol,lot));
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);
if(margin!=0)lot=(balans*Risk)/(margin*100.0);
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));
}
//+------------------------------------------------------------------+
...
попробуйте такой вариант. Если задан стоплосс в пипсах то расчет по первой функции, если задан 0, то по второй.
...
Конечно, большое спасибо за такую функцию, но сейчас стоит вопрос чем гарантированно заменить эту функцию
double marg1lot=SymbolInfoDouble(symbol,SYMBOL_MARGIN_INITIAL);
чтобы всегда иметь правильный ответ по залогу.
Конечно, большое спасибо за такую функцию, но сейчас стоит вопрос чем гарантированно заменить эту функцию
double marg1lot=SymbolInfoDouble(symbol,SYMBOL_MARGIN_INITIAL);
чтобы всегда иметь правильный ответ по залогу.
Попробуйте OrderCalcMargin()
Т.Е. Вы предлагаете заменить типа на вот это
double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,margin1lot);
Т.Е. Вы предлагаете заменить типа на вот это
double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,margin1lot);
Да, но нужно знать конкретные задачи.
Потому как есть много "подводных камней" когда резервируешь залог.
Добавлено
Посмотрите здесь
Да, но нужно знать конкретные задачи.
Потому как есть много "подводных камней" когда резервируешь залог.
Согласен, сейчас стоит задача рассчитать объем ордера по проценту от депозита и получается функция такого вида,
даже если что то выдалось не так, размер будет равен минимальному контракту
{
double lot=0.0;
double margin1lot;
double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
double minlot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
double riskbalans=NormalizeDouble(AccountInfoDouble(ACCOUNT_BALANCE)*percent/100,2);
if(OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,margin1lot)) lot=NormalizeDouble(riskbalans/marg1lot,digitsfloatvolume);
if(lot<minlot) lot=minlot;
return(lot);
}
Согласен, сейчас стоит задача рассчитать объем ордера по проценту от депозита и получается функция такого вида,
даже если что то выдалось не так, размер будет равен минимальному контракту
{
double lot=0.0;
double margin1lot;
double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
double minlot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
double riskbalans=NormalizeDouble(AccountInfoDouble(ACCOUNT_BALANCE)*percent/100,2);
if(OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,margin1lot)) lot=NormalizeDouble(riskbalans/marg1lot,digitsfloatvolume);
if(lot<minlot) lot=minlot;
return(lot);
}
Вышло вот так
{
double lot=0.0;
double margin1lot;
double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
double minlot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
double maxlot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
double riskbalans=NormalizeDouble(AccountInfoDouble(ACCOUNT_BALANCE)*percent/100,2);
if(OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,margin1lot))
lot=NormalizeDouble(riskbalans/margin1lot,digitsfloatvolume);
if(lot<minlot) lot=minlot;
if(lot>maxlot) lot=maxlot;
return(lot);
}
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Есть множество подходов в этом отношении, но вопрос возник в принципе, почему часто невозможно от сервера получить ответ на запрос о маржинальном требовании средств на 1 лот или 1 контракт?
double marg1lot=SymbolInfoDouble(symbol,SYMBOL_MARGIN_INITIAL);
Особенно часто это возникает именно на биржевом рынке.
Вот пример функции, где на ответ сервера у некоторых брокеров не приходит ничего, а вернее чаще возвращается 0, в результате чего возникает ошибка деления на 0.
{
double lot=0.0;
double marg1lot=SymbolInfoDouble(symbol,SYMBOL_MARGIN_INITIAL);
double minlot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
double riskbalans=NormalizeDouble(AccountInfoDouble(ACCOUNT_BALANCE)*percent/100,2);
lot=NormalizeDouble(riskbalans/marg1lot,digitsfloatvolume);
if(lot<minlot) lot=minlot;
return(lot);
}
Как можно обойти это решение? Временно видоизменил эту функцию, если в результате запроса приходит 0, то присваиваю внешнее значение залога.
{
double lot=0.0;
double marg1lot=SymbolInfoDouble(symbol,SYMBOL_MARGIN_INITIAL);
if(marg1lot==0) marg1lot=marginlot;
double minlot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
double riskbalans=NormalizeDouble(AccountInfoDouble(ACCOUNT_BALANCE)*percent/100,2);
lot=NormalizeDouble(riskbalans/marg1lot,digitsfloatvolume);
if(lot<minlot) lot=minlot;
return(lot);
}
Но это только временный выход, да и можно забыть или неправильно указать этот залог, а как гарантированно получить эти данные для расчета?