白马股选股策略

本人对白马股的定义如下:

第一条件:筛选投资回报率ROIC五年以上都超过10%的公司
第二条件:自由资金流强劲,有息负债率低
第三条件:行业地位高、上下游议价能力强、运营资本低的的企业。这条量化起来有点儿“玄学”,暂时用“毛利率高”作为代理指标吧。

回测效果如下:
白马股选股策略_第1张图片
核心选股代码:

def select_stock(context):        
    start_date = dt.datetime.today().date()-dt.timedelta(days=1)
    stk = get_index_stocks('000300.XSHG')+get_index_stocks('000905.XSHG')+get_index_stocks('399006.XSHE')
    stk=list(set(stk))
    stk2= list(get_fundamentals(query(
        valuation.code,
        ).filter(
            valuation.code.in_(stk),
        balance.equities_parent_company_owners > 0,
        balance.retained_profit>0,
        valuation.pe_ratio>0,
        ), date=start_date).code.values)
    def delete_st(stocks,begin_date):
        st_data=get_extras('is_st',stocks, count = 1,end_date=begin_date)
        stockList = [stock for stock in stocks if not st_data[stock][0]]
        return stockList
    def delete_stop(stocks,beginDate,n=365*3):
        stockList=[]
        
        beginDate = datetime.datetime.strptime(beginDate, "%Y-%m-%d")
        for stock in stocks:
            start_date=get_security_info(stock).start_date
            if start_date<(beginDate-datetime.timedelta(days=n)).date():
                stockList.append(stock)
        return stockList
        
    def get_jq_factor(date,feasible_stocks,jqfactors_list):
        factor_data =  get_factor_values(securities=feasible_stocks, 
                            factors=jqfactors_list,count=1, end_date=date )
        df_jq_factor=pd.DataFrame(index=feasible_stocks)
        
        for i in factor_data.keys():
            df_jq_factor[i]=factor_data[i].iloc[0,:]
        
        return df_jq_factor
    stk = delete_st(stk2,start_date)
    one_year_ago = start_date - datetime.timedelta(days=365)
    two_year_ago = start_date - datetime.timedelta(days=365*2)
    three_year_ago = start_date - datetime.timedelta(days=365*3)
    four_year_ago = start_date - datetime.timedelta(days=365*4)
    #1、5年roic均值>0.1
    ikun_1= pd.DataFrame(index=stk)
    ikun_1['roic1']=get_jq_factor(start_date,stk,'roic_ttm').dropna()
    ikun_1['roic2']=get_jq_factor(one_year_ago,stk,'roic_ttm').dropna()
    ikun_1['roic3']=get_jq_factor(two_year_ago,stk,'roic_ttm').dropna()
    ikun_1['roic4']=get_jq_factor(three_year_ago,stk,'roic_ttm').dropna()
    ikun_1['roic5']=get_jq_factor(four_year_ago,stk,'roic_ttm').dropna()
    ikun_1=ikun_1.dropna()
    ikun_1['roic_mean']=ikun_1.mean(axis=1)
    ikun_11=list(ikun_1[ikun_1.roic_mean>=0.1].index)
    
    # 2、自由现金流强劲、有息负债率低(不喜欢大量负债、重资产)
    #free cash flow/total__assets高  非流动资产/总资产低, 有息负债率低
    # 3、排除行业地位不高,上下游议价能力差,运营资本高
    #用毛利率高借代 行业地位高(可能不准确??), 净运营资本低高
    ikun_f = get_history_fundamentals(ikun_11,
                                 [income.operating_revenue,
                                  income.operating_cost,
                                  balance.total_current_assets,
                                  balance.total_current_liability,
                                  cash_flow.net_operate_cash_flow,
                                  cash_flow.fix_intan_other_asset_acqui_cash,
                                  balance.total_assets,
                                  balance.total_non_current_assets,
                                  
                                  ],
                                 watch_date=start_date, count=4).dropna()  # 连续的6个季度
    ikun_f['fcf']=ikun_f['net_operate_cash_flow']-ikun_f['fix_intan_other_asset_acqui_cash']
    ikun_total_current_assets=ikun_f.groupby('code')['total_current_assets'].mean()
    ikun_total_current_liability=ikun_f.groupby('code')['total_current_liability'].mean()
    
    ikun_operating_revenue=ikun_f.groupby('code')['operating_revenue'].sum()
    ikun_operating_cost=ikun_f.groupby('code')['operating_cost'].sum()
    
    ikun_total_assets=ikun_f.groupby('code')['total_assets'].mean()
    ikun_total_non_current_assets=ikun_f.groupby('code')['total_non_current_assets'].mean()
    
    ikun_fcf=ikun_f.groupby('code')['fcf'].sum()
    
    ikun_2= pd.DataFrame(index=ikun_11)
    ikun_2['fcfsum']=ikun_fcf/ikun_total_assets
    ikun_2['f_l']=get_jq_factor(start_date,ikun_11,'financial_liability').dropna()
    ikun_2['a']=ikun_total_assets
    ikun_2['d_a']=-ikun_2['f_l']/ikun_2['a']
    del ikun_2['a']
    del ikun_2['f_l']
    ikun_2['fix_asset']=-ikun_total_non_current_assets/ikun_total_assets
    
    ikun_3= pd.DataFrame(index=ikun_11)
    ikun_3['gpm']=(ikun_operating_revenue-ikun_operating_cost)/ikun_operating_revenue
    ikun_3['net working capital']=(ikun_total_current_liability-ikun_total_current_assets)/ikun_total_assets
    
    ikun_2=ikun_2.dropna()
    ikun_2=ikun_2.rank(ascending=True)
    ikun_2_v = np.sum(preprocessing.scale(ikun_2),axis=1)
    ikun_2_v1=preprocessing.scale(ikun_2_v )
    ikun_2_i = ikun_2.index.tolist()
    ikun_end2 = pd.DataFrame({'code':ikun_2_i,'ikun2':ikun_2_v1}).set_index('code')

    ikun_3=ikun_3.dropna()
    ikun_3=ikun_3.rank(ascending=True)
    ikun_3_v = np.sum(preprocessing.scale(ikun_3),axis=1)
    ikun_3_v1=preprocessing.scale(ikun_3_v )
    ikun_3_i = ikun_3.index.tolist()
    ikun_end3 = pd.DataFrame({'code':ikun_3_i,'ikun3':ikun_3_v1}).set_index('code')

    ikun_score = pd.merge(ikun_end3,ikun_end2,on=['code'])    
    ikun_score_v = np.sum(ikun_score.dropna(),axis=1)
    ikun_score_v1=preprocessing.scale(ikun_score_v)
    ikun_score_i = ikun_score.dropna().index.tolist()
    ikun_score1= pd.DataFrame({'code':ikun_score_i,'score':ikun_score_v1}).set_index('code')    
    ikun_score1=ikun_score1.sort_values(by='score',ascending=False).head(2*g.buy_stock_count) 
    def get_pb(x):
        q = query( 
            valuation.pb_ratio,
        ).filter(
            valuation.code == x
        )
        return get_fundamentals(q,start_date)['pb_ratio'].item()
    
    def get_marketcap(x):
        q = query( 
            valuation.market_cap,

        ).filter(
            valuation.code == x
        )
        return get_fundamentals(q,start_date)['market_cap'].item()
    

    ikun_score1['value'] = ikun_score1.index.map(get_marketcap)
    result  = list(ikun_score1.sort_values(by ='value',ascending=False).head(g.buy_stock_count).index) 

    return result 

行业地位高、上下游议价能力强、运营资本低的的企业,这个条件可能需要找找别的更好的指标,纯毛利率其实是会选出白酒等高毛利的品类,但是白酒在这一两年表现并不佳,因此寻找更恰当的指标可以提高泛化性能。

如果你喜欢小木屋分享的内容,请关注小木屋哦。关注小木屋后回复【电子书】可获取小木屋入门量化的硬核书籍呢。

你可能感兴趣的:(策略,量化,python,人工智能)