自动计算批量大小的功能?

 

大家好,我又回来跟你们唠叨了:-)谁有一个方便的小MQL4功能,可以根据我的可用资产的多少%的风险,以及我想要的止损大小(点),自动计算手数大小(任何符号)?


谢谢。

肖恩

 


谢谢菲利普!虽然听起来代码在处理日元对时有一些问题。这个问题已经解决了吗?


谢谢

肖恩

 
shawnh:


谢谢菲利普!虽然听起来代码在处理日元对时有一些问题。这个问题已经解决了吗?


谢谢

肖恩




我不知道你指的是什么? 在日元对上运行良好。 就像你可能把钱交给任何代码一样,你应该对代码进行调查,并通过一些手工计算确认其正确性。 该代码是正确的,但它并不是万无一失的:)

 

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.
}
 

菲利普,我把你的代码放在我的EA中,它运行得非常好--非常感谢你。同时也感谢AIS和WHRoeder的回复!


谢谢

肖恩

 

很高兴听到这个消息,Shawn!

我一直在修改代码,如果你想要一个最新的版本(你所拥有的版本中没有错误),我很乐意分享它。

这些变化主要是围绕着使包含文件更容易与你现有的EA整合和使用。 既然你已经设法让另一个实现了,那么现在对你来说可能没有任何区别。

 

菲利普,我很喜欢那个新的 "更容易使用 "的包含文件,你能不能把它贴出来或寄给我,实际上我今天正在努力做这件事。

谢谢!

 

当然,等我回到有我的代码的电脑前,我会把它贴出来。

现在我想起来了,我也许也应该把它上传到代码库里。

 

第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);

第3步:假设你已经在你的EA中定义了MaxPercentEquityAtRisk,即在止损点被击中的情况下,每笔交易完全损失的最大允许权益,这部分代码将首先根据openprice和stoplossprice(不是点数而是实际市场价格,与你在订单中发送给经纪人的价格相同)确定最大手数,然后它将确定经纪人在不超过你预算的风险权益情况下接受的最大头寸大小。

第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