Нужна формула размера LOT для управления капиталом, основанная на SL и риске счета! - страница 3

 

Хорошо, ребята! Этот код был написан мной, и именно его я использую в своих советниках. Он довольно сложный, потому что, помимо Risk% и StopLoss, он также учитывает Margin Risk%, а также корректирует размер лота на основе Minimum, Maximum и Step Size. Он также всегда использует минимальное значение текущего баланса и капитала вместо того, чтобы использовать только одно из них. Я считаю, что так безопаснее.

Обратите внимание, однако, что она не использует в расчетах спред, потому что я рассчитываю его отдельно при расчете используемого StopLoss. Таким образом, приведенная ниже функция использует относительный размер стоп-лосса. В моих советниках аргумент dblStopLossPips рассчитывается заранее в зависимости от различных факторов, таких как стратегия, спред, ATR и т.д.; поэтому конечное значение, передаваемое в функцию dblLotsRisk(), уже является конечным значением для расчета используемого размера лота.

// Function to Determine Tick Point Value in Account Currency

        double dblTickValue( string strSymbol )
        {
                return( MarketInfo( strSymbol, MODE_TICKVALUE ) );
        }
        

// Function to Determine Pip Point Value in Account Currency

        double dblPipValue( string strSymbol )
        {
                double dblCalcPipValue = dblTickValue( strSymbol );
                switch ( MarketInfo( strSymbol, MODE_DIGITS ) )
                {
                        case 3:
                        case 5:
                                dblCalcPipValue *= 10;
                                break;
                }
                
                return( dblCalcPipValue );
        }
        

// Calculate Lot Size based on Maximum Risk & Margin

        double dblLotsRisk( string strSymbol, double dblStopLossPips,
                double dblRiskMaxPercent, double dblMarginMaxPercent,
                double dblLotsMin, double dblLotsMax, double dblLotsStep )
        {
                double
                        dblValueAccount = MathMin( AccountEquity(), AccountBalance() )
                ,       dblValueRisk    = dblValueAccount * dblRiskMaxPercent / 100.0
                ,       dblValueMargin  = AccountFreeMargin() * dblMarginMaxPercent / 100.0
                ,       dblLossOrder    = dblStopLossPips * dblPipValue( strSymbol )
                ,       dblMarginOrder  = MarketInfo( strSymbol, MODE_MARGINREQUIRED )
                ,       dblCalcLotMin
                                = MathMax( dblLotsMin, MarketInfo( strSymbol, MODE_MINLOT ) )
                ,       dblCalcLotMax
                                = MathMin( dblLotsMax, MarketInfo( strSymbol, MODE_MAXLOT ) )
                ,       dblModeLotStep  = MarketInfo( strSymbol, MODE_LOTSTEP )
                ,       dblCalcLotStep  = MathCeil( dblLotsStep / dblModeLotStep ) * dblModeLotStep
                ,       dblCalcLotLoss
                                = MathFloor( dblValueRisk / dblLossOrder / dblCalcLotStep ) * dblCalcLotStep
                ,       dblCalcLotMargin
                                = MathFloor( dblValueMargin / dblMarginOrder / dblCalcLotStep ) * dblCalcLotStep
                ,       dblCalcLot = MathMin( dblCalcLotLoss, dblCalcLotMargin )
                ;
                
                if ( dblCalcLot < dblCalcLotMin ) dblCalcLot = dblCalcLotMin;
                if ( dblCalcLot > dblCalcLotMax ) dblCalcLot = dblCalcLotMax;

                return ( dblCalcLot );
        }
 
GumRai:

У меня голова болит от одной только попытки разобраться со скобками!

Честно говоря, я совершенно не понимаю, чего вы пытаетесь добиться.

Я не вижу, как MODE_STOPLEVEL или SPREAD имеют отношение к делу, конечно, вы должны основывать свои расчеты на расстоянии стоп-лосса от текущей цены?

Не должно быть никакой разницы, какая валюта счета, расчеты должны быть одинаковыми, потому что TICKVALUE находится в валюте счета.

Обратите внимание, что благодаря тому, что вы разместили свою строку кода в 2 строки, пост не такой широкий и его легче читать без прокрутки вправо-влево :)

Я разместил несколько страниц назад картинку, на которой я проиллюстрировал свою формулу расчета лота. Но pipvalue или tickvalue или как там его, все время путается.Quote->базовая валюта и другие вещи, которые сбивают с толку, но пока моя формула хорошо работает, хотя я не уверен в ее правильности.

SPREAD может быть неважным, но stoplevel необходим. Я ставлю SL как можно ближе к цене открытия ордера, которая является стоп-уровнем, но из-за колебаний и скачков мне нужно иногда корректировать его вручную, поэтому я ввел переменную STOPSLIP, с помощью которой я могу корректировать SL в зависимости от волатильности или чего-то еще.

FMIC:

Хорошо, ребята! Этот код был написан мной, и именно его я использую в своих советниках. Он довольно сложный, потому что, помимо Risk% и StopLoss, он также учитывает Margin Risk%, а также корректирует размер лота на основе Minimum, Maximum и Step Size. Он также всегда использует минимальное значение текущего баланса и капитала вместо того, чтобы использовать только одно из них. Мне кажется, так безопаснее.

Обратите внимание, однако, что она не использует спред в расчете, потому что я рассчитываю его отдельно при расчете используемого StopLoss. Таким образом, приведенная ниже функция использует относительный размер стоп-лосса. В моих советниках аргумент dblStopLossPips рассчитывается заранее в зависимости от различных факторов, таких как стратегия, спред, ATR и т.д.; поэтому конечное значение, передаваемое в функцию dblLotsRisk(), уже является конечным значением для расчета используемого размера лота.

Спасибо, я протестирую его и сообщу свой отзыв!

Хотя я не понимаю, зачем вы поместили туда так много переменных, весь код можно уместить в 1 строку :)

 
Proximus:

Я разместил несколько страниц назад картинку, на которой я проиллюстрировал свою формулу расчета лота. Но pipvalue или tickvalue или как там его, все время путается. Quote->базовая валюта и другие вещи, которые сбивают с толку, но пока моя формула хорошо работает, хотя я не уверен в ее правильности.

SPREAD может быть неважным, но stoplevel необходим. Я ставлю SL как можно ближе к цене открытия ордера, которая является стоплоссом, но из-за колебаний и скачков, мне нужно иногда корректировать его вручную, поэтому я ввел переменную STOPSLIP, с помощью которой я могу корректировать SL в зависимости от волатильности или чего-то еще.

Спасибо, я протестирую это и сообщу свой отзыв!

Хотя я не понимаю, зачем вы поместили туда так много переменных, весь код можно уместить в 1 строку :)


Да, весь код может быть помещен в одну строку, но поверьте мне, это НИКОГДА не является хорошим способом кодирования, если только вы не пытаетесь выжать из своего кода все до последнего цикла процессора, чтобы быть самым быстрым на планете.

Вот почему "GumRai" жаловался на головную боль, пытаясь разобраться в другом коде. Он просто не был очень читабельным или легко понимаемым, и это делает его очень трудным для отладки.

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

Но не стесняйтесь сжать все это в одну строку. Только не жалуйтесь, если это не даст тех же результатов. Я оставлю на ваше усмотрение отладку этого.

 

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

double LOTUNITSTORISK()
{
double LOTS=((AccountBalance()*RISKPERCENT/100) / (  MarketInfo(Symbol(), MODE_TICKVALUE)*MarketInfo(Symbol(), MODE_TICKSIZE)*STOPSIZE     ));
return LOTS;
}


Эта функция должна возвращать единицы лота, основанные на риске счета, и рассчитанные через счет EUR, так как EUR всегда является базовой валютой.

Единица лота означает = фактический денежный размер позиции, поэтому для счета 100 € с риском 1% она должна возвращать 1 €, что на основе стоплосса, например, стоплосс в 100 пипсов должен составлять 1000 единиц лота (0.01 лота в эквиваленте MT4).

Критично, что валюта счета - евро, и ничего больше.

Вызвав функцию LOTUNITTORISK(), мы разделим результат на 100.000, чтобы получить фактический размер лота в формате MT4 (1000 денежных единиц 0.01 LOT в MT4).

RISKPERCENT = это int и это может быть 1,2,3,4 % риска, которым мы рискуем.

STOPSIZE = это int и это количество пипсов (пипсов/10 на 5-ти значном брокере), которое составляет размер нашего стоплосса, так например 60 пипсов SL это 6 пипсов SL

Я хочу знать, правильно ли функция вычисляет LOT UNITS, пожалуйста, протестируйте ее и если вы найдете какую-либо ошибку, пожалуйста, помогите мне :)

Тысяча благодарностей!

 
Proximus:
MarketInfo(Symbol(), MODE_TICKVALUE)* MarketInfo(Symbol(), MODE_TICKSIZE)*STOPSIZE

Risk  = lotsize * StopSize * TickValue /  TickSize
         1      *  0.0100  *  $10.00   / 0.0001
$1000 = one lot * 100 pips *  $10.00   / pip
  1. Вы размещаете стоп там, где он должен быть - там, где причина для торговли больше не актуальна. Например, при торговле на отскоке от поддержки стоп опускается ниже поддержки.
  2. Баланс счета * процент = RISK = (OrderOpenPrice - OrderStopLoss)*DIR * OrderLots * DeltaPerlot (Примечание OOP-OSL включает SPREAD).
  3. НЕ используйте TickValue само по себе - DeltaPerlot
  4. Вы также должны проверить FreeMargin, чтобы избежать стоп-аута
 
WHRoeder:
  1. Вы размещаете стоп там, где он должен быть - там, где причина для торговли больше не актуальна. Например, при торговле на отскоке от поддержки стоп опускается ниже поддержки.
  2. Баланс счета * процент = RISK = (OrderOpenPrice - OrderStopLoss)*DIR * OrderLots * DeltaPerlot (Примечание OOP-OSL включает SPREAD).
  3. НЕ используйте TickValue само по себе - DeltaPerlot
  4. Вы также должны проверить FreeMargin, чтобы избежать стоп-аута.

1) Функция возвращает только размер лота в денежных единицах, а не в единицах MT4, и ничего больше, когда я ставлю ордера, то соответственно STOPSIZE будет добавлен / вычтен из Bid в случае BUY и Ask в случае sell. Это так же, как MT4 обрабатывает TP и SL.

BUY открывается по ASK, закрывается по BID

SELL открыт по BID, закрыт по ASK.

2) Я не могу использовать OrderOpenprice man, потому что ордер не открывается до вычисления этой функции. Спреды не включены, спреды будут обработаны, когда я добавлю/субстрагирую STOPSIZE после открытия ордера.

Но перед этим нам нужно определить размер лота, это логично.

3) Я не понимаю этого.

4) Очевидно, но я еще раз подчеркиваю, что функция размещения ордеров выполняется после этого, и имеет мало общего с этой функцией.Единственная цель этой функции - определить размер лота, и ничего больше.


TickValue /  TickSize

Неправильно, если я делю их, то получаю неправильное число, возможно для USD счетов так и нужно делать, но это EUR счет. Их нужно перемножить.

 
Proximus:

BUY открыта по ASK, закрыта по BID SELL открыта по BID, закрыта по ASK

2) Я не могу использовать OrderOpenprice

3) Я не понимаю этого.

4)t, если я их разделю, то получу неправильное число, возможно для USD счетов так и нужно делать, но это EUR счет. Их нужно перемножить.

  1. Ask - это цена открытия ордера для покупки.
  2. Bid - это цена открытия ордера для продажи. Почему вы не можете использовать ее, вы должны знать ее, чтобы передать ее в OrderSend?
  3. Вы ДОЛЖНЫ использовать tickvalue/ticksize. Тиковое значение само по себе бессмысленно.
  4. Вы ДОЛЖНЫ разделить, чтобы получить правильные единицы (Изменение цены) * (tickValue) / (изменение цены) дает вам значение. $10 за пункт = $1 за пункт = стоимость/изменение. Помните, что результат в валюте счета, поэтому, когда вы делите его на ваш риск, вы получаете чистую цифру, а единицы измерения отменяют $risk(BAL%)/$risk(SL). Если вам приходится умножать, вы делаете что-то не так, или брокеры перепутали значения.
 
WHRoeder:
Proximus:

BUY открывается по ASK, закрывается по BID SELL открывается по BID, закрывается по ASK

2) Я не могу использовать OrderOpenprice

3) Я не понимаю этого.

4)t, если я их разделю, то получу неправильное число, возможно для USD счетов так и нужно делать, но это EUR счет. Их нужно перемножить.

  1. Ask - это цена открытия ордера для покупки.
  2. Bid - это цена открытия ордера для продажи. Почему вы не можете использовать ее, вы должны знать ее, чтобы передать ее в OrderSend?
  3. Вы ДОЛЖНЫ использовать tickvalue/ticksize. Tickvalue само по себе бессмысленно.
  4. Вы ДОЛЖНЫ разделить, чтобы получить правильные единицы (Изменение цены) * (tickValue) / (изменение цены) дает вам значение. $10 за пункт = $1 за пункт = стоимость/изменение. Помните, что результат в валюте счета, поэтому, когда вы делите его на ваш риск, вы получаете чистую цифру, а единицы измерения отменяют $risk(BAL%)/$risk(SL). Если вам приходится умножать, вы делаете что-то не так, или брокеры перепутали значения.


1,2 Я знаю это, но поймите меня, что это обрабатывается другой функцией, она не имеет ничего общего с этой.

3) Как я понимаю, tickvalue - это стоимость 1 пункта в базовой валюте, поэтому в зависимости от того, какую пару я использую, нужно будет либо делить, либо умножать на нее. В случае с EUR-счетом кажется, что нужно умножать, а не делить.

Вот картинка, которая лучше это иллюстрирует:


На EUR/USD для сделки с риском 3% нам нужно открыть 1798 единиц, округленно 0.02 LOTS в единицах MT4, чтобы достичь этого.

Размер STOPLOSS определяется другой функцией.

Это кажется правильным, поскольку я проверил это, но я не уверен, что формула действительно точна, это то, что я пытаюсь определить здесь, так что, пожалуйста, помогите в этом.

 

Я тоже пытался разобраться с расчетом размера лота на основе SL, риска счета и уровня Margin Call, особенно когда уровень Margin Call не 100%, а, например, 120%. Лучший ответ, который я нашел, это то, что WHRoeder поделился здесь в своем коде whrea.mq4. Код whrea.mq4 нуждается в некоторой коррекции, но WHRoeder уже дал эту коррекцию здесь в своем ответе на комментарий RaptorUK. Таким образом, полный ответ на вопрос о расчете размера лота существует, но для полного понимания того, чем поделился WHRoeder, необходимо приложить некоторые усилия.

Я приложил код, который я извлек и модифицировал из WHRoeder's whrea.mq4 для компиляции с последней новой сборкой MT4, чтобы рассчитать размер лота для длинной сделки, где уровень Margin Call составляет более 100%.

Однако я не уверен, что умножение на MarginCallLevel % правильно для учета Margin Call Level % во избежание маржин-колла. Если MarginCallLevel равен 100%, то обе строки кода будут правильными, но если MarginCallLevel равен 120%, будет ли умножение на MarginCallLevel % правильным тестом Margin Call? Если нет, то каков правильный способ сделать это? WHRoeder, вы можете помочь с этим? Уильям, я старался изо всех сил.

Вот код из раздела Margin Test для длинной сделки:

extern double MarginCallLevel = 120; //As a percentage

double MarginCallLevel1 = MarginCallLevel * 0.01; 

        double  AFMC    = AccountFreeMarginCheck(Symbol(), OP_BUY, tradesize),
                        eRisk   = equityatrisk + atrisknew;

        //Test for margin
        //Note: Not sure if multiplying by the MarginCallLevel % here is correct to 
        //take the Margin Call Level % into account for avoiding a margin call.
        //If the MarginCallLevel is 100% then both lines of code would be correct
        //but if the MarginCallLevel is 120% would multiplying by the MarginCallLevel %
        //be a correct Margin Call test? If not, then what is the correct way to do this?

        //if (AFMC*0.99 <= eRisk){
        if (AFMC*0.99 <= eRisk*MarginCallLevel1){
            tradesize *= 0.95;    // Must still round to lotStep.
            continue;   }   // Prevent margin call if new trade goes against us.
Файлы:
 

... в этой части кода есть проблема с новой компиляцией (ошибка ---> 'MarketInfo' - illegal switch expression type), возможно, все было в порядке до обновления до MT4 build 600+ ... но с тех пор это больше не работает.

// Function to Determine Pip Point Value in Account Currency

        double dblPipValue( string strSymbol )
        {
                double dblCalcPipValue = dblTickValue( strSymbol );
                switch ( MarketInfo( strSymbol, MODE_DIGITS ) )
                {
                        case 3:
                        case 5:
                                dblCalcPipValue *= 10;
                                break;
                }
                
                return( dblCalcPipValue );
        }
        

Поэтому, не могли бы вы выложить более новую версию... если, конечно, вы еще здесь.


Причина обращения: