자동 로트 크기 계산 기능?

 

안녕하세요 여러분, 다시 잔소리를 하러 돌아왔습니다. :-) 내 가용 자산의 위험도(%)와 원하는 손절매 크기(핍)를 기반으로 로트 크기(모든 기호에 대해)를 자동으로 계산하는 편리한 작은 MQL4 기능 을 가진 사람이 있습니까?


감사해요!

 


감사합니다 필립! 코드에 JPY 쌍에 몇 가지 문제가 있는 것 같습니다. 해결되었나요?


감사해요

 
shawnh :


감사합니다 필립! 코드에 JPY 쌍에 몇 가지 문제가 있는 것 같습니다. 해결되었나요?


감사해요




나는 당신이 무엇을 언급하고 있는지 모르겠습니까? JPY 쌍과 잘 작동합니다. 돈을 맡길 수 있는 다른 코드와 마찬가지로 코드를 조사하고 몇 가지 수동 계산을 통해 정확성을 확인해야 합니다. 코드는 정확하지만 완벽하지는 않습니다. :)

 

1. 샘플: 로트 크기 계산 https://www.mql5.com/en/code/8583

2. AIS1 트레이딩 로봇 https://www.mql5.com/en/code/8700

//< 7.7.2. Risk Management > //<192>
//< 7.7.3. Operation Size Control > //<202>

 
shawnh :

가용 자산의 위험도(%)와 원하는 손절매 크기(핍)를 기반으로 로트 크기(모든 기호에 대해)를 자동으로 계산하는 간편하고 작은 MQL4 기능을 가진 사람이 있습니까?

 //+------------------------------------------------------------------+
//| Lot size computation.                                            |
//+------------------------------------------------------------------+
double   LotSize( double risk){
/*double    TEF.value,                          // Import from ComputeTEF
//double    at.risk;                            // Export to init/start
//bool      need2refresh;                       // Import from RelTradeContext
//int       op.code; // -1/OP_BUY/OP_SELL       // Import from setDIR */
     /* This function computes the lot size for a trade.
     * Explicit inputs are SL relative to bid/ask (E.G. SL=30*points,)
     * Implicit inputs are the MM mode, the MM multiplier, count currently
     * filled orders by all EA's vs this EA/pair/period count and history.
     * Implicit inputs are all used to reduce available balance the maximum
     * dollar risk allowed. StopLoss determines the maximum dollar risk possible
     * per lot. Lots=maxRisk/maxRiskPerLot
     **************************************************************************/
     if (need2refresh)   Refresh();
     /*++++ Compute lot size based on account balance and MM mode*/ {
     double   ab  = AccountBalance();
     switch (Money.Management.F0M1G2){
     case MMMODE_FIXED:
        at.risk = Money.Management.Multiplier;
         break ;
     case MMMODE_MODERATE:
         // See https://www.mql5.com/en/articles/1526 Fallacies, Part 1: Money
         // Management is Secondary and Not Very Important.       // %used/trade=
        at.risk = MathSqrt (Money.Management.Multiplier * ab)/ab; // ~const rate.
        at.risk = MathSqrt (Money.Management.Multiplier * ab
                            * MathPow ( 1 - at.risk, OrdersTotal () ));
         break ;
     case MMMODE_GEOMETRICAL:
        at.risk = Money.Management.Multiplier * ab *
                 MathPow ( 1 - Money.Management.Multiplier, OrdersTotal ());
         break ;
    }
     double   maxLossPerLot   = risk * PointValuePerLot(),
     /* Number of lots wanted = at.risk / maxLossPerLot rounded/truncated to
     * nearest lotStep size.
     *
     * However, the broker doesn't care about the at.risk/account balance. They
     * care about margin. Margin used=lots used*marginPerLot and that must be
     * less than free margin available. */
            marginFree      = AccountFreeMargin(),
            marginPerLot    = MarketInfo( Symbol (), MODE_MARGINREQUIRED ),
     // So I use, the lesser of either.
            size = MathMin (marginFree / marginPerLot, at.risk / maxLossPerLot),
            minLot  = MarketInfo( Symbol (), MODE_MINLOT),
            LotStep = MarketInfo( Symbol (), MODE_LOTSTEP);
     /*---- Compute lot size based on account balance and MM mode*/ }
     double   adjFact = IfD( MathMin ( 1 , TEF.value), 1 , TEF.Enable01);
     while (true){   // Adjust for broker, test for margin, combine with TEF
        size =   MathFloor (size/LotStep)*LotStep;
         if (size < minLot){ // Insufficient margin.
             Print (
             "LotSize(SL=" , DoubleToStr(risk/pips2dbl, Digits .pips), ")=" ,
            size, " [risk=" , at.risk, AccountCurrency(),     "/" , maxLossPerLot,
                     ", margin=" ,    marginFree,             "/" , marginPerLot,
                     ", MMM=" ,       Money.Management.F0M1G2, "x" ,
                    Money.Management.Multiplier,     ", OO=" ,   OrdersTotal (),
                 "]" );
            size= 0 ; break ;  }
         /* size<minLot should be sufficient, but the tester was generating error
         * 134 even when marginFree should have been OK. So I also use
         * AccountFreeMarginCheck which aggrees with the tester.
         * https://forum.mql4.com/35056 */
         double AFMC = AccountFreeMarginCheck( Symbol (), op.code, size);
         /**/ if (AFMC < 0 )      size *= 0.95 ;
         else if (adjFact < 1 ){  size  = MathMax (minLot,size*adjFact);adjFact= 1 ;}
         else break ; // We're good to go.
    }
    at.risk = size * maxLossPerLot;                     // Export for Comment
     return (size);
}   // LotSize
double PointValuePerLot() { // Value in account currency of a Point of Symbol.
     /* In tester I had a sale: open=1.35883 close=1.35736 (0.00147)
     * gain$=97.32/6.62 lots/147 points=$0.10/point or $1.00/pip.
     * IBFX demo/mini       EURUSD TICKVALUE=0.1 MAXLOT=50 LOTSIZE=10,000
     * IBFX demo/standard   EURUSD TICKVALUE=1.0 MAXLOT=50 LOTSIZE=100,000
     *                                  $1.00/point or $10.00/pip.
     *
     * https://forum.mql4.com/33975 CB: MODE_TICKSIZE will usually return the
     * same value as MODE_POINT (or Point for the current symbol), however, an
     * example of where to use MODE_TICKSIZE would be as part of a ratio with
     * MODE_TICKVALUE when performing money management calculations which need
     * to take account of the pair and the account currency. The reason I use
     * this ratio is that although TV and TS may constantly be returned as
     * something like 7.00 and 0.00001 respectively, I've seen this
     * (intermittently) change to 14.00 and 0.00002 respectively (just example
     * tick values to illustrate). */
     return (  MarketInfo( Symbol (), MODE_TICKVALUE)
           / MarketInfo( Symbol (), MODE_TICKSIZE) ); // Not Point.
}
 

Phillip, 귀하의 코드를 제 EA에 저장했는데 멋지게 작동합니다. 정말 감사합니다. 답변을 주신 AIS와 WHRoeder에게도 감사드립니다!


건배

 

숀을 듣게되어 기쁩니다!

나는 계속해서 코드를 수정하고 있습니다. 더 최신 버전을 원하신다면(당신이 가지고 있는 것에는 버그가 없습니다) 기꺼이 공유하겠습니다.

변경 사항은 주로 포함 파일을 기존 EA와 더 쉽게 통합하고 사용할 수 있도록 하는 데 중점을 둡니다. 이미 다른 하나를 구현하는 데 성공했으므로 지금은 별 차이가 없을 수 있습니다.

 

Phillip, 나는 새로운 "사용하기 쉬운" 포함 파일을 원합니다. 게시하거나 저에게 보내주실 수 있습니까? 저는 오늘 실제로 그렇게 하려고 합니다.

감사해요!

 

물론입니다. 내 코드가 있는 컴퓨터로 다시 돌아가면 게시하겠습니다.

지금 생각해보니 코드뱅크에도 올려야 할 것 같습니다.

 

1단계: 이 게시물의 모든 첨부 파일을 포함 경로(...\experts\include\*.mqh)에 넣습니다.

2단계: 첨부 파일에 포함된 호출 기능에 액세스할 수 있도록 EA 상단에 다음을 추가합니다.

#include < OrderReliable_2010.10.12.mqh >
#include < Trade_Position_Management_2010.10.29.mqh >

3단계: 계획된 위험 자본 금액을 기반으로 로트 크기를 계산하려면 다음을 추가합니다.

   // Determine position lotsize based on order direction and market prices
   double CurrentEquityAtRisk=(MaxPercentEquityAtRisk/100.)*AccountBalance();
   double CurrentLotSize=LotSize(CurrentEquityAtRisk,OpenPrice_ND,StopLossPrice_ND,CurrentOrderType); // Compute the max possible lotsize for the risk equity
   Print("Max allowed EquityAtRisk = $",DoubleToStr(CurrentEquityAtRisk,2)," and Max computed Lotsize = ",CurrentLotSize);
   CurrentLotSize=NormalizeLotSize(CurrentLotSize);   // Normalize the lotsize to conform with the Broker's specific quantized position allowances
   if(CurrentLotSize <MarketInfo(CurrentSymbol,MODE_MINLOT)) CurrentLotSize= MarketInfo (CurrentSymbol,MODE_MINLOT);
   if (CurrentLotSize> MarketInfo(CurrentSymbol,MODE_MAXLOT)) CurrentLotSize=MarketInfo(CurrentSymbol,MODE_MAXLOT);

EA의 어딘가에 MaxPercentEquityAtRisk를 최대 허용 자산으로 정의하여 중지가 발생한 경우 거래당 완전한 손실 위험에 처할 수 있다고 가정하면 코드의 이 부분은 먼저 오픈 가격 및 중지 손실 가격(핍이 아님)을 기반으로 최대 로트 크기를 결정합니다. 그러나 실제 시장 가격, 주문 시 브로커에게 보내는 것과 동일) 그러면 브로커가 예산 위험 자산을 초과하지 않으면서 수락할 최대 포지션 크기가 결정됩니다.

4단계: 계산 결과를 로그에 인쇄하거나 주문 주석으로 거래에 추가하려면 다음을 추가할 수도 있습니다.

   // Determine the actual equity at risk of total loss for the position's normalized lotsize
   CurrentEquityAtRisk=EquityAtRisk(CurrentLotSize,OpenPrice_ND,StopLossPrice_ND,CurrentOrderType);
   if (TakeProfitBidPrice> 0.01 )
      {
      CurrentProfitPotential=ProfitPotential(CurrentLotSize,OpenPrice_ND,TakeProfitPrice_ND,CurrentOrderType);
       Print ( "Current EquityAtRisk = $" ,DoubleToStr(CurrentEquityAtRisk, 2 ), " and Current Lotsize = " ,CurrentLotSize, " and Profit Target = $"
            ,DoubleToStr(CurrentProfitPotential, 2 ), " for a " ,DoubleToStr(CurrentProfitPotential/CurrentEquityAtRisk, 1 ), ":1 Profit:Loss ratio" );
      Order_Comment= StringConcatenate ( "EaR = $" ,DoubleToStr(CurrentEquityAtRisk, 2 ), " & Profit = $" ,DoubleToStr(CurrentProfitPotential, 2 ));
      }
   else
      {
       Print ( "Current EquityAtRisk = $" ,DoubleToStr(CurrentEquityAtRisk, 2 ), " and Current Lotsize = " ,CurrentLotSize);
      Order_Comment= StringConcatenate ( "EquityAtRisk = $" ,DoubleToStr(CurrentEquityAtRisk, 2 ));
      }

5단계: 주문하기(ordersendreliable 방법 사용)

   // Place the order
   ticket = OrderSendReliable(CurrentSymbol,CurrentOrderType,CurrentLotSize,OpenPrice_ND,MarketInfo(CurrentSymbol,MODE_SPREAD)
            ,StopLossPrice_ND,TakeProfitPrice_ND,Order_Comment, 0 , 0 , Aqua );

https://c.mql5.com/mql4/forum/2010/10/OrderReliable_2010.10.12.mqh