【神奇公式】 故事不夠價值來湊

這是一個看臉的時代,好身材的童鞋們?yōu)榱俗C明自己是在三個標準差之外的存在,發(fā)明了一系列簡單的神奇公式:
反手摸肚臍,鎖骨放硬幣,A4腰,Iphone腿

只要簡單的一個測試就知道身材好不好!
那么大家都知道,A股是個喜歡講故事的市場,可是故事看不見摸不著,有沒有簡單神奇的公式,可以一步測試出A股的“身材”呢?
今天我們就來介紹一下如何使用Ricequant一步步實現(xiàn)一個簡單的“神奇公式’策略
雖然知道joe神奇公式的人很多,但是我們還是做一個簡單的介紹~
喬爾?格林布拉特:
Gotham資本公司的創(chuàng)始人和合伙經(jīng)理人,自1985年這一私人投資公司成立以來,它的年均回報率達到了40%。他不僅是哥倫比亞大學商學院的客座教授,一家《財富》500強公司的前董事長,價值投資者俱樂部網(wǎng)站(http://ValueInvestorsClub.com)的合作發(fā)起人,還是《你能成為股市天才》一書的作者。格林布拉特擁有理學學士學位,并從沃頓學院獲得工商管理碩士學位。
喬爾·格林布拉特的投資理念是要找到物美價廉的公司,特別是在市場出現(xiàn)特殊情況的背景下低價買入好業(yè)務?!氨阋藘r格買好業(yè)務是神奇公式的核心理念。神奇公式能夠幫助不懂估值的投資人戰(zhàn)勝大盤,而對于精通估值的投資人,神奇公式則能給他們提供一個起點,他們的估值能力還能給神奇公式加分?!彼绱嗽u價他自己發(fā)明的神奇公式,認為神奇公式是戈坦資本投資流程的簡化版。在《股市穩(wěn)贏》一書中,格林布拉特詳細介紹了神奇公式的應用方法。其具體操作流程可以簡化成兩部分:一是尋找好的業(yè)務;二是尋找便宜的股票。好的業(yè)務是指有形資本回報率高的公司;便宜的股票則是指息稅前盈余/企業(yè)價值(EBIT/ EV)高的股票。
利用神奇公式,在美國的歷史回溯檢驗數(shù)據(jù)顯示,1988年至2004年這17年間,該策略的年復合回報率為30.8%,而同期標準普爾500指數(shù)的年復合回報率僅為12.4%。
接著我們開始找這個公式的真正原版是什么吧!經(jīng)過一系列的google之后我還是比較相信wikipedia: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.

翻譯一下就是:
排除掉公共事業(yè)和金融板塊的股票。(為什么呢?這個可能需要從作者的那本書名很俗的書中尋找)
排除掉境外的公司(A股基本沒有)
選取公司的息稅前盈余/企業(yè)價值高的 = EBIT / Enterprise Value 《---- 便宜的股票是指稅前盈余/企業(yè)價值(EBIT/EV)高的股票。
選取公司的有形資本回報率(return on capital)= EBIT / (Net Fixed Assets + Working Capital) <--- 好的業(yè)務是指有形資本回報率高的公司
從所有市面上的股票中選取3和4最高的公司的股票
投資20-30個排名最高的股票,然后每個月持續(xù)加入2-3個持倉直到超過12個月
每年進行重新調(diào)整投資組合,年前剔除掉當年投資比較失敗的,年后剔除掉當年投資比較成功的
長期繼續(xù)以上的操作(5-10年+)

在整個公式分析中如何一步一步在Ricequant上實現(xiàn)呢?我們先從比較簡單的版本做起,剔除掉6-8的復雜操作,假設每個月調(diào)倉投資20-30個符合3-4點的股票。
咱們來一個一個拆開分析,符合計算機的divide and conquer - 各個擊破的思想吧!

  1. 排除掉公共事業(yè)和金融板塊的股票。
    這個需要使用Ricequant提供的板塊功能:Ricequant - Beta
context.utlility_and_fin_stocks = sector('utilities') + sector('financials')
logger.info(context.utlility_and_fin_stocks)

我們使用sector拿到utilities和financials兩個板塊的股票,然后返回的是兩個array相加得到一個包含兩個板塊的array,我也會習慣打印一句logger.info(xx)來把我們拿到的這倆板塊的股票列表顯示出來。

  1. 選取公司的息稅前盈余/企業(yè)價值高的 = EBIT / Enterprise Value 《---- 便宜的股票是指稅前盈余/企業(yè)價值(EBIT/EV)高的股票。
    比較贊的是Ricequant提供的財務數(shù)據(jù)表格查詢是非常齊全和清洗的,也包含了專業(yè)的英文命名:Ricequant - Beta
    我們需要首先尋找到EBIT和Enterprise value(EV)在Ricequant的命名:
    比較有意思的是我們直接找到了 EV/EBIT ,但是我們需要尋找的是EBIT/EV的最高的幾名,因此從EV/EBIT這個指標我們只需要的排序是從低到高的前幾名即可,那么轉(zhuǎn)化為查詢代碼(對查詢財務數(shù)據(jù)不熟悉,可以看我們的財務數(shù)據(jù)教程視頻):
    我們首先要提前考慮的是我們需要查詢兩個指標:EBIT/EV和資本回報率(return on capital), 分別會拿到兩組的公司列表,然后找兩個列表中的共同股票就是最后的所得,由于財務數(shù)據(jù)的查詢量會比較大,我們做一個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:
這里有個命名的建議是,所有的dataframe數(shù)據(jù)類型我都建議您使用_df作為結尾,這樣看到這個變量名,您就可以知道他是dataframe的數(shù)據(jù)類型了。
fundamentals.eod_derivative_indicator.ev_to_ebit就是我們在財務數(shù)據(jù)字典中查到的指標名。
order_by(fundamentals.eod_derivative_indicator.ev_to_ebit.asc())是對該指標進行一個從小到大的排序,然后選取前context.limit個 - 即前200個

  1. 接著我們開始查詢資本回報率(return on capital),幸運的是我們強大的財務數(shù)據(jù)字典依然有:
    那么我們開始構建資本回報率的財務數(shù)據(jù)查詢:
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_df和return_on_cap_df,但是我們要拿的是在這兩個df中都存在的股票,因此做以下的代碼操作:

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

但是我們?nèi)耘f需要去除掉屬于公共事業(yè)和金融板塊的股票代碼:

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就是最終我們需要的符合神奇公式的股票列表啦!
4.輪動的利器 - scheduler
接著繼續(xù),那么我們已經(jīng)知道了如何進行財務數(shù)據(jù)查詢了,但是如何實現(xiàn)每個月的輪動呢? 這就要用到了Ricequant API的另外一個大殺器了 - scheduler:Ricequant - Beta
scheduler可以讓一段邏輯(代碼)每天、每周和每月定期觸發(fā)一次,使用方法很簡單,就是:

scheduler.run_monthly(function, tradingday=t)

其中function就是我們想定期觸發(fā)的邏輯,在此處就是我們想定期調(diào)倉的邏輯,我也把上面的代碼總結一下如下:
在這個方法中編寫任何的初始化邏輯。context對象將會在你的算法策略的任何方法之間做傳遞。

def init(context): 
  context.utlility_and_fin_stocks = sector('utilities') + sector('financials')    
  logger.info(context.utlility_and_fin_stocks) 
  context.limit = 200# before_trading

此函數(shù)會在每天交易開始前被調(diào)用,當天只會被調(diào)用一次

def before_trading(context, bar_dict): 
  passdef rebalance(context, bar_dict): #挑選 ev/ebit 最高的,即ebit/ev 最低的 
  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
                        ) 
                     )
 #挑選 return_on_invested_capital 最高的頭context.limit個 
  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 
                         )
                 ) 
#拿到在兩者列表中共同的: df_stocks = [stock for stock in ebit_div_ev_df if stock in return_on_cap_df]

那么聰明的你可能已經(jīng)發(fā)現(xiàn)了我們只需要在init中注冊一下我們的scheduler事件,讓他每個月調(diào)用一次rebalance函數(shù)就行了!一行代碼就可以做到了每月輪動啦:

def init(context): 
 #每月第一個交易日調(diào)用rebalance邏輯 
   scheduler.run_monthly(rebalance, 1)

加入這一行之后你就可以試試看了,是不是很神奇的每個月第一個交易日就能幫你自動選股了呢?
5.調(diào)整某個股票在投資組合中所占倉位的利器 - order_target_percent
終于到了最后的關鍵點了 - 落單和調(diào)整倉位,不過我們有一個非常容易使用的Ricequant提供的和倉位管理融為一體的落單接口:order_target_percent
在上面的過程中我們在每個月初的調(diào)倉中已經(jīng)拿到了最新的想要投資的股票列表: context.stocks,那么我們需要計算一下每個股票即將買入建倉以后在投資組合中的比重 - avergae_weight:

average_weight = 0 
#計算比重
 if len(context.stocks) != 0: 
    average_weight = 0.999 / len(context.stocks)

接著我們對已有的持倉的股票但是卻不存在于新的篩選出來的股票列表context.stocks的股票進行清倉,使用order_target_percent('xxx', 0)即可對某個股票xxx進行清倉了,非常簡單:

#開始進行調(diào)倉 #先清倉持倉的股票不在新的列表中 
for stock in context.portfolio.positions: 
    if stock not in context.stocks: 
        order_target_percent(stock, 0)

然后對于新的篩選出來的股票列表進行建倉,我們知道想要建倉的每個股票占最終投資組合的比重為average_weight,那么就很簡單了,我們只需要對每個新的篩選出來的股票使用

order_target_percent('xxx', average_weight):
#買入新的選擇出來的股票 
if average_weight != 0: 
    for stock in context.stocks: 
        order_target_percent(stock, average_weight)

不知不覺這個策略就出來了!下面我們也一起來看下這個策略的最終結果:

快來ricequant自己動手寫起來吧~
公號id:Ricequant

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 名稱 libev - 一個 C 編寫的功能全面的高性能事件循環(huán)。 概要 示例程序 關于 libev Libev 是...
    hanpfei閱讀 15,551評論 0 5
  • https://guorn.com/ 果仁網(wǎng)~ 大家不妨打開看看 這次主要想看看計算機在量化里面的應用,然后白天自...
    芊小璇閱讀 787評論 2 1
  • 投資,其實就像是買白菜,追求的是物美價廉,追求的是優(yōu)質(zhì)低價。 這種買白菜的理念,其實就是喬爾·格林布拉特(Joel...
    李虎翼HugoLi閱讀 1,257評論 1 1
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,695評論 19 139
  • 1、安裝JDK(開發(fā)工具包)。JDK下載:網(wǎng)站http://java.sun.com。安裝JDK。配置JDK*配置...
    NEVER_LONELY閱讀 717評論 0 1

友情鏈接更多精彩內(nèi)容