[神奇公式] 如何在 Ricequant 上实现策略( Python) - 1 从别人的经验和思路中实现 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
thinkingmind
V2EX    推广

[神奇公式] 如何在 Ricequant 上实现策略( Python) - 1 从别人的经验和思路中实现

  •  
  •   thinkingmind 2016-04-05 14:53:52 +08:00 5024 次点击
    这是一个创建于 3475 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原帖、更多讨论及代码: https://www.ricequant.com/community/topic/815

    我们提供了较为丰富的入门教学材料和视频,可能您还是会有疑问如何开始呢?我们就从一个简单的例子开始来看看吧,是非常流行的神奇公式

    我最开始是在网上浏览看到这个公式的,那么其作者是格林布拉特:

    乔尔格林布拉特简介 Gotham 资本公司的创始人和合伙经理人,自 1985 年这一私人投资公司成立以来,它的年均回报率达到了 40%。他不仅是哥伦比亚大学商学院的客座教授,一家《财富》 500 强公司的前董事长,价值投资者俱乐部网站( ValueInvestorsClub.com )的合作发起人,还是《你能成为股市天才》一书的作者。格林布拉特拥有理学学士学位,并从沃顿学院获得工商管理硕士学位。

    [《证券市场周刊》记者王存迎] 乔尔格林布拉特的投资理念是要找到物美价廉的公司,特别是在市场出现特殊情况的背景下低价买入好业务。    “便宜价格买好业务是神奇公式的核心理念。神奇公式能够帮助不懂估值的投资人战胜大盘,而对于精通估值的投资人,神奇公式则能给他们提供一个起点,他们的估值能力还能给神奇公式加分。”他如此评价他自己发明的神奇公式,认为神奇公式是戈坦资本投资流程的简化版。    在《股市稳赢》一书中,格林布拉特详细介绍了神奇公式的应用方法。其具体操作流程可以简化成两部分:一是寻找好的业务;二是寻找便宜的股票。好的业务是指有形资本回报率高的公司;便宜的股票则是指息税前盈余 /企业价值( EBIT/ EV )高的股票。

    利用神奇公式,在美国的历史回溯检验数据显示, 1988 年至 2004 年这 17 年间,该策略的年复合回报率为 30.8%,而同期标准普尔 500 指数的年复合回报率仅为 12.4%。

    接着我们开始找这个公式的真正原版是什么吧!经过一系列的 google 之后我还是比较相信 wikipedia : https://en.wikipedia.org/wiki/Magic_formula_investing

    Methodology[edit]

    Greenblatt suggests purchasing 30 "good companies": cheap stocks with a high earnings yield and a high return on capital. He touts the success of his magic formula in his book 'The Little Book that Beats the Market ', Joel Greenblatt ISBN 0-471-73306-7, citing that it does in fact beat the S&P 500 96% of the time, and has averaged a 17-year annual return of 30.8%[1]

    Formula[edit]

    • Establish a minimum market capitalization (usually greater than $50 million).
    • Exclude utility and financial stocks.
    • Exclude foreign companies (American Depositary Receipts).
    • Determine company's earnings yield = EBIT / enterprise value.
    • Determine company's return on capital = EBIT / (net fixed assets + working capital).
    • Rank all companies above chosen market capitalization by highest earnings yield and highest return on capital (ranked as percentages).
    • Invest in 20 30 highest ranked companies, accumulating 2 3 positions per month over a 12-month period.
    • Re-balance portfolio once per year, selling losers one week before the year-mark and winners one week after the year mark.
    • Continue over a long-term (5 10+ year) period.

    翻译一下就是:

    1. 排除掉公共事业和金融板块的股票。(为什么呢?这个可能需要从作者的那本书名很俗的书中寻找)
    2. 排除掉境外的公司( A 股基本没有)
    3. 选取公司的息税前盈余 /企业价值高的 = EBIT / Enterprise Value 《---- 便宜的股票是指税前盈余 /企业价值( EBIT/EV )高的股票。
    4. 选取公司的有形资本回报率( return on capital )= EBIT / (Net Fixed Assets + Working Capital) <--- 好的业务是指有形资本回报率高的公司
    5. 从所有市面上的股票中选取 3 和 4 最高的公司的股票
    6. 投资 20-30 个排名最高的股票,然后每个月持续加入 2-3 个持仓直到超过 12 个月
    7. 每年进行重新调整投资组合,年前剔除掉当年投资比较失败的,年后剔除掉当年投资比较成功的
    8. 长期继续以上的操作( 5-10 年+)

    在整个公式分析中如何一步一步在 Ricequant 上实现呢?我们先从比较简单的版本做起,剔除掉 6-8 的复杂操作,假设每个月调仓投资 20-30 个符合 3-4 点的股票。

    咱们来一个一个拆开分析,符合计算机的divide and conquer - 各个击破的思想吧!

    1. 排除掉公共事业和金融板块的股票。

    这个需要使用 Ricequant 提供的板块功能: https://www.ricequant.com/api/python/chn#other-methods-sector

    context.utlility_and_fin_stocks = sector('utilities') + sector('financials') logger.info(context.utlility_and_fin_stocks) 

    我们使用sector拿到utilitiesfinancials两个板块的股票,然后返回的是两个array相加得到一个包含两个板块的 array ,我也会习惯打印一句logger.info(xx)来把我们拿到的这俩板块的股票列表显示出来。


    2. 选取公司的息税前盈余 /企业价值高的 = EBIT / Enterprise Value 《---- 便宜的股票是指税前盈余 /企业价值( EBIT/EV )高的股票。

    比较赞的是 Ricequant 提供的财务数据表格查询是非常齐全和清洗的,也包含了专业的英文命名: https://www.ricequant.com/fundamentals

    我们需要首先寻找到 EBIT 和 Enterprise value ( EV )在 Ricequant 的命名: Screen Shot 2016-04-03 at 4.59.39 PM.png

    比较有意思的是我们直接找到了 EV/EBIT ,但是我们需要寻找的是 EBIT/EV 的最高的几名,因此从EV/EBIT这个指标我们只需要的排序是从低到高的前几名即可,那么转化为查询代码(对查询财务数据不熟悉,可以看我们的财务数据教程视频):

    我们首先要提前考虑的是我们需要查询两个指标:EBIT/EV资本回报率( return on capital ), 分别会拿到两组的公司列表,然后找两个列表中的共同股票就是最后的所得,由于财务数据的查询量会比较大,我们做一个 200 的查询限制,先查EV/EBIT的从低到高的排序:

    context.limit = 200 ebit_div_ev_df = get_fundamentals( query( fundamentals.eod_derivative_indicator.ev_to_ebit ).order_by( fundamentals.eod_derivative_indicator.ev_to_ebit.asc() ).limit( context.limit ) ) 

    PS:

    1. 这里有个命名的建议是,所有的dataframe数据类型我都建议您使用_df作为结尾,这样看到这个变量名,您就可以知道他是dataframe的数据类型了。
    2. fundamentals.eod_derivative_indicator.ev_to_ebit 就是我们在财务数据字典中查到的指标名。
    3. order_by(fundamentals.eod_derivative_indicator.ev_to_ebit.asc())是对该指标进行一个从小到大的排序,然后选取前context.limit个 - 即前 200 个

    3. 接着我们开始查询资本回报率( return on capital ),幸运的是我们强大的财务数据字典依然有:

    Screen Shot 2016-04-03 at 5.28.06 PM.png

    那么我们开始构建资本回报率的财务数据查询:

    return_on_cap_df = get_fundamentals( query( fundamentals.financial_indicator.return_on_invested_capital ).order_by( fundamentals.financial_indicator.return_on_invested_capital.desc() ).limit( context.limit ) ) 

    那么此时我们拿到了两个dataframe分别是ebit_div_ev_dfreturn_on_cap_df,但是我们要拿的是在这两个df中都存在的股票,因此做以下的代码操作:

    df_stocks = [stock for stock in ebit_div_ev_df if stock in return_on_cap_df] 

    但是我们仍旧需要去除掉属于公共事业和金融板块的股票代码:

    for stock in df_stocks: if stock in context.utlility_and_fin_stocks: df_stocks.remove(stock) 

    我们只需要前 30 个即可:

    context.total_amount = 30 context.stocks = df_stocks[0:context.total_amount] logger.info("选择好的神奇公式股票列表为:" + str(context.stocks)) 

    那么context.stocks就是最终我们需要的符合神奇公式的股票列表啦!

    原帖、更多讨论及代码: https://www.ricequant.com/community/topic/815

    4 条回复    2016-04-06 10:53:15 +08:00
    0x5010
        1
    0x5010  
       2016-04-05 15:48:41 +08:00
    很有想法.
    nilom
        2
    nilom  
       2016-04-05 16:17:22 +08:00
    先学习再收藏
    l6751902
        3
    l6751902  
       2016-04-06 09:21:50 +08:00
    最近怎么有种量化开始向“一般人”扩展的趋势?韭菜少了,机构开始想从码农这头扩展羊群么?
    thinkingmind
        4
    thinkingmind  
    OP
       2016-04-06 10:53:15 +08:00
    @l6751902 很多量化交易者出生就是码农,尤其是高频交易一块,当然在国内高频做不动了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5324 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 09:04 PVG 17:04 LAX 02:04 JFK 05:04
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86