通过一段有趣的AFL, 解读被广泛误用的kelly公式

Discussion in 'AmiBroker' started by oldwain, Mar 3, 2010.

  1. 前天刚安装上AmiBroker, 为了练手到网上搜罗了一堆代码学习。


    下面这个代码来源于:http://www.amibroker.com/library/detail.php?id=1199
    它不是任何指标,也不是系统, 而是一个小工具,用来演示给定盈亏比/盈亏额后,各种不同投资比例带来的收益。


    我在其基础上,稍微做了一些加工: 加入了我们常见的kelly公式计算结果,及从路晨光的"投资组合的熵理论和信息价值"中的结算结果。


    为了试验, 我用了一个某个时间段有正收益的交易系统的结果来做了下测试:
    该系统的测试报告摘要:
    测试品种数: 63
    净利润: 33,680,474.94 净利润率: 53.46%
    总盈利: 146,649,920.00 总亏损: -106,887,912.00

    交易次数: 1440次 胜率: 39.38%
    年均交易次数: 178.96(2.84/品种) 盈/亏次数: 567/873

    多头交易次数: 1440 空头交易次数: 0
    多头盈利次数: 567 空头盈利次数: 0
    多头胜率: 39.38% 空头胜率: 0.00%
    多头盈亏比: 0.65 空头盈亏比: 0.00



    把以上数据替换公式中相应的变量,最后给出kelly公式的结果是10.68%, 而鲁氏公式则给出了87.21%

    而实际演示则可以看出kelly公式给出的结果远不是最优的结果, 而鲁氏公式则基本没问题。

    那么问题出在哪儿呢?

    常见的kelly公式:
    kelly = ((盈亏比 +1)*赢的几率 -1)/ (盈亏比);

    这个公式有各种不同的变体, 不过都是一些等式变换的结果。

    路晨光公式:

    Lu = (赢的几率*赢的收益率 + 赔的几率*赔的收益率)/ (赢的收益率* -赔的收益率)


    通过上面的公式可以看出: 在kelly公式中只关心盈亏比,但并不关心盈利和亏损的绝对值, 而我们凭直觉也能知道盈利和亏损的绝对值对于最优头寸是有影响的。 对于一个抛硬币的游戏: 输的时候输10个币,赢的时候赢11个币, 和输的时候输0.1个币,赢的时候赢011个币, 我们投注的额度是一定要有区分的。



    那么是kelly公式错了吗? 不是! 是很多引用kelly公式的人没有注意kelly公式的一个基本假设, 那就是输的时候收益永远是-1(输100%). 实际上把老鲁的公式中"赔的收益率"固定为-1后,两个公式才是等价的。
     
    ciceron likes this.
  2. 代码:

    PHP:
    _SECTION_BEGIN("ct1");
    /*
        Coin Toss model , it has nothing to do with Technical OR Fundamental Analysis
        
        It has nothing to do with entry or exit rules.
        Here One books profits and losses at a predefined percent.
        

        This Model was Inspired by many authors
        ---------------------------------------
        a)Victor Sperandeo    :- Methods of Wall Street Master
        b)Nasim Taleb            :-    Fooled by Randomness
        c)Ed Thorp                :-    #Beat the Market         #Beat the Dealer
        d)William Poundstone    :-    Fortune's Formula

        thanks for AB codes and concepts by
        a)Dimitris Tsokakis
        b)Herman van den Bergen
        c)Anthony Faragasso
        d)Graham Kavanagh    
        and countless good souls.

        Hearty thanks to
        
        "Tomasz Janeczko" for AB Platform.


        Disclaimer : any error in code or concept here belongs to me.
        This Amibroker Script is for educational purposes only. I cannot guarantee 
    it's accuracy nor take any responsibility for your use of it.  Use at your own
    risk.


    */
    SetOption("InitialEquity"100000);
    SetOption("CommissionMode"1);       //% per trade
    SetOption("CommissionAmount"0.00); // commission in BPS per leg
    SetOption("MarginRequirement"10);
    SetOption("UsePrevBarEquityForPosSizing"1);
    SetOption("AllowSameBarExit",1);                                    // Sq off Daily
    SetOption("PriceBoundChecking",0);
    SetTradeDelays000);
    RoundLotSize=1;                                                      //Change this according to your needs [i did it for Nifty].

    posSizeX Param("posSizeX"1011001);

    winloss Param("winloss"39.37510902);                     // Assumed probability of winning, higher the better

    winPercent Param("winPercent"25.8640.2520.25);          // higher the better
    lossPercent 12.243;   // winPercent*0.9;                                         //Optimize("lossPercent", 0.5, 0.25, 10,0.25);     // lower the better

    iterations Optimize("iterations",1,1,20,1);                     // to test randomness at different levels, NOT used in any equation.

    HitRatio mtRandomA() < (winloss/100);                             //hit ratio

    //FK = ((WL + 1) * Pw - 1 ) / WL

    kelly = ((winPercent/lossPercent +1)*winloss/100  -1)/ (winPercent/lossPercent)*100;

    //LU=(Pw*Rw+ Pl * Rl)/abs(Rw*Rl)

    Lu=100*(winloss/100 winPercent/100 + (1-winloss/100) * (-LossPercent)/100)/abs(winPercent/100*LossPercent/100);




    PositionSize = -(posSizeX);                                         //exposure of capital

    Buy Day() != Ref(Day(), -);                                    // trade daily
    Sell Buy;                                                            // Sq off Daily

    Short=Cover=0;

    BuyPrice=1;  // to make it generic from EURUSD to Hangseng to Bovespa

    //if you win you get winPercent, if you loose you loose lossPercent
    SellPrice=IIf(HitRatio,BuyPrice*(1+(winPercent/100)),BuyPrice*(1-(lossPercent/100))
     ); 


    Plot(posSizeX ,"posSize : " 1,256+2048);

    Plot(Equity(),"Equity : " 1,1);
    Plot(Equity()/100000*100-100 ,"Profit : " 3,256+2048 );
    Plot(kelly"Kelly: "1256+2048);
    Plot(Lu"LuChenGuang: "1256+2048);



    RequestTimedRefresh(3);

    SetChartBkGradientFillParamColor("BgTop"colorWhite),ParamColor("BgBottom",colorViolet));
    _SECTION_END();

     
  3. Very good, thanks.
     
  4. 谢谢分享
     
  5. 学习了 数理公式的灵活应用是我最头痛的地方
     
  6. 写了一段小代码,给大家share一下:

    PHP:
    //  Kelly Optimal position
    //    kelly.afl
    //  
    SetCustomBacktestProc("");
    if (
    Status("action") == actionPortfolio)
    {
        
    bo GetBacktesterObject();
        
    bo.backtest();
        
    st bo.getperformancestats(0);
        
    Pw st.getvalue("WinnersPercent");
        
    PL st.getvalue("LosersPercent");
        
    Rw st.getvalue("WinnersAvgProfitPercent");
        
    RL st.getvalue("LosersAvgLossPercent");

        
    Optpos = (Pw*Rw Pl*Rl)/abs(Rw*Rl)*100;
        
    bo.addcustommetric("Optimal Position %"OptPos);    
    }
    把这个代码存放到formulas\include目录下, 然后在任何一个交易系统afl的开头加入:
    #include <kelly.afl>
    就可以在该交易系统的backtester report里面看到该系统的最佳position.

    注意: 使用它确定最佳头寸时,最好系统本身不设定头寸(即100%头寸模式)进行测试。
    另外这个指标,也可以作为揭示回报风险比的一个指标。
     
  7. 奇怪的是,假如亏损收益=-10%,按鲁氏公式算出的仓位基本上大于满仓。靠!这怎么解释?
     
  8. Very good, thanks.
     
  9. LZ既然已经知道了这么个假设,那么你应该知道,像你这种方法进行凯利公式的计算是完全不对的