15.10 风险控制建模-动量类多因子之择时中选股

用户头像Reflecti0N
2023-08-07 发布

作为策略集锦压轴篇,向大家介绍完整的多因子选股策略,结合了光大证券多因子选股研报,希望能在多因子研究模块,给大家打好坚实基础。

import pandas as pd
import numpy as np
# 初始化函数,全局只运行一次
def init(context):
    g.n = 20 #设置最大持仓数量为20只股票
    run_monthly(handle_bar,date_rule=1) 
    #将trade交易函数设置为定时运行:每个月第一个交易日
    context.stock = []#储存上期的股票池
    g.stock='000300.SH'#设置指数获取其成分股
    g.kc=False #因子择时结果是够为空仓
## 开盘时运行函数
def handle_bar(context, bar_dict):
    date=get_last_datetime().strftime('%Y%m%d')
    #执行选股函数:alphastock(date),并将结果导入,该股票列表是需要买入的个股。
    needstock_list = alphastock(date)
    if g.kc ==True:
        context.stock=[]
        for i in list(context.portfolio.positions):
            order_target(i,0)
        pass
    else:
        #获取上期持仓个股
        holdstock_list = list(context.stock)
        #确定本期需要卖出的个股
        sell_list = list(set(holdstock_list)-set(needstock_list))
        #执行卖出操作,运用for循环,逐个操作。
        for s in sell_list:
            order_target(s,0)
        #确定本期需要买入的个股,其余即为继续持仓的个股
        buy_list=[]
        for i in needstock_list:
            if i in holdstock_list:
                pass
            else:
                buy_list.append(i)
        #确定可用资金,平分分配至需买入的个股
        n=len(buy_list)
        cash=context.portfolio.available_cash/n
        #执行买入操作
        for s in range(0,n,1):
            stock=list(buy_list)[s]
            order_value(stock,cash)
        #操作完毕,将选股结果放到上期股票池储存变量中,以备下次使用。
        context.stock = frozenset(needstock_list)
#===============以沪深300为股票池,除去ST和停牌=====  
def stock(date):  
    stk=list(get_index_stocks(g.stock,date))
    #2015年前上市的
    stk2=list(get_all_securities('stock','20150105').index)
    price=get_price(stk, None, date, '1d', ['is_paused', 'is_st'], False, None, 1, is_panel=1)
    stopstk=price['is_paused'].iloc[-1]
    ststk=price['is_st'].iloc[-1]
    startstk=(stopstk[stopstk==0].index)
    okstk=(ststk[ststk==0].index)
    tradestk=list(set(startstk)&set(okstk)&set(stk2))
    return tradestk  
def alphastock(date):
    stock_list=stock(date)
    quote_rate_all=get_price(stock_list, None, date, '1d', ['quote_rate'], False, 'pre', 273, is_panel=1)['quote_rate']
    nowmonth=quote_rate_all.iloc[-21:]
    quote_rate=quote_rate_all.iloc[:-21]
    PM_1M=quote_rate.iloc[-21:].sum()
    PM_3M=quote_rate.iloc[-63:].sum()
    PM_6M=quote_rate.iloc[-126:].sum()
    PM_9M=quote_rate.iloc[-189:].sum()
    PM_12M=quote_rate.iloc[:].sum()
    PM_12MC6M=quote_rate.iloc[:].sum()-quote_rate.iloc[-126:].sum()
    PM_12MC1M=quote_rate.iloc[:].sum()-quote_rate.iloc[-21:].sum()
    PM_6MC1M=quote_rate.iloc[-126:].sum()-quote_rate.iloc[-21:].sum()
    quote_rate=quote_rate.T
    quote_rate['PM_1M']=PM_1M
    quote_rate['PM_3M']=PM_3M
    quote_rate['PM_6M']=PM_6M
    quote_rate['PM_9M']=PM_9M
    quote_rate['PM_12M']=PM_12M
    quote_rate['PM_12MC6M']=PM_12MC6M
    quote_rate['PM_12MC1M']=PM_12MC1M
    quote_rate['PM_6MC1M']=PM_6MC1M
    yinzi_list=['PM_1M','PM_3M','PM_6M','PM_9M','PM_12M','PM_12MC6M','PM_12MC1M','PM_6MC1M']
    for i in quote_rate.columns:
        if i in yinzi_list:
            pass
        else:
            del quote_rate[i]
    nowmonth=nowmonth.sum()
    quote_rate['nowmonth']=nowmonth
    stocknum=int(len(quote_rate.index)*0.1)
    yinzi_IClist=[]
    zeshi=0
    for i in quote_rate.columns:
        if i in yinzi_list:
            quote_rate = pd.DataFrame(quote_rate).sort_values(by =i, ascending=False)
            d=quote_rate['nowmonth'].iloc[:stocknum].mean()-quote_rate['nowmonth'].iloc[-stocknum:].mean()
            if d <0:
                zeshi=zeshi+1
                yinzi_IClist.append(d)
            else:
                yinzi_IClist.append(d)
    if zeshi > 4:
        g.kc = True 
    else:
        g.kc = False
    quote_rate_all=quote_rate_all.iloc[-252:]
    PM_1M=quote_rate_all.iloc[-21:].sum()
    PM_3M=quote_rate_all.iloc[-63:].sum()
    PM_6M=quote_rate_all.iloc[-126:].sum()
    PM_9M=quote_rate_all.iloc[-189:].sum()
    PM_12M=quote_rate_all.iloc[:].sum()
    PM_12MC6M=quote_rate_all.iloc[:].sum()-quote_rate_all.iloc[-126:].sum()
    PM_12MC1M=quote_rate_all.iloc[:].sum()-quote_rate_all.iloc[-21:].sum()
    PM_6MC1M=quote_rate_all.iloc[-126:].sum()-quote_rate_all.iloc[-21:].sum()
    df=pd.DataFrame(columns=yinzi_list)
    df['PM_1M']=PM_1M
    df['PM_3M']=PM_3M
    df['PM_6M']=PM_6M
    df['PM_9M']=PM_9M
    df['PM_12M']=PM_12M
    df['PM_12MC6M']=PM_12MC6M
    df['PM_12MC1M']=PM_12MC1M
    df['PM_6MC1M']=PM_6MC1M
    for i in yinzi_list:
        df[i] = (df[i] - df[i].mean())/df[i].std()
    df=df.T
    df['IC']=yinzi_IClist
    df=df[df['IC']>0]
    for i in df.columns:
        if i =='IC':
            pass
        else:
            df[i]=df[i]*df['IC']
    del df['IC']
    alpha=df.sum()
    df=df.T
    df['alpha']=alpha
    df['syboml']=df.index
    df=pd.DataFrame(df).sort_values(by ='alpha', ascending=False)
    #获取前20只股票的代码
    needstock_list=[]
    for s in range(0,g.n,1):
        needstock_list.append(df.iloc[s]['syboml'])
    #完成函数,输入即为10只股票代码,作为策略的股票池
    return needstock_list
收益&风险
源码

评论

需要帮助?

试试AI小助手吧