干货分享来啦——动量因子选股策略


(夹心巧克力^_^) #1

我最近开发了一个策略,基本思想强者恒强,弱者恒弱的动量原理。大神勿拍:

克隆策略
In [7]:
instruments = D.instruments()
start_date = '2015-01-01' # 起始日期
end_date = '2017-02-13' # 结束日期
stock_num  = 30 # 股票数量
In [10]:
def initialize_0(context):
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
    context.date_index = 0
    context.schedule_function(rebalance,date_rule=date_rules.month_start(days_offset=0)) # 换仓规则


def handle_data_0(context,data):
    pass

# 换仓
def rebalance(context, data):
    context.date_index += 1
    
    # 目前持仓的股票列表
    pos_list = [i.symbol for i in context.portfolio.positions]
    
    # 数据获取和动量因子计算处理
    current_dt = data.current_dt.strftime('%Y-%m-%d')
    dic = {}
    for j in instruments:
        try:
            df = data.history(context.symbol(j),'close',30,'1d')
            momentum =  df[0] / df[-1]
            dic[j] = momentum     
        except Exception as e:
            continue
            
    # 获取换仓买入股票列表
    dic = {v:k for v,k in dic.items() if not np.isnan(k)}
    dic_sorted = sorted(dic.items(),key = lambda d:d[1],reverse = True)
    symbol_lst = [i[0] for i in dic_sorted]
    sym_top = symbol_lst[:stock_num] # 买入的股票列表
    
    to_sell = [k for k in pos_list if k not in sym_top] # 需要卖出的股票列表
      
    # 如果持有仓位 先把仓位平掉
    for j in to_sell:
        if data.can_trade(context.symbol(j)):
            context.order_target(context.symbol(j), 0)            
   
    # 落单买入
    weight = 1. / stock_num 
    for  cp in sym_top:
        if data.can_trade(context.symbol(cp)):
            context.order_target_percent(context.symbol(cp), weight)
            
    # 打印信息
    print('date = ', data.current_dt.strftime('%Y-%m-%d'),'该交易日已经结束')    
In [ ]:
m=M.backtest.v4( # 测试接口
    instruments=instruments,
    start_date=start_date,
    end_date=end_date,
    initialize=initialize_0,
    handle_data=handle_data_0,
    order_price_field='close',
    order_price_field_buy='open',
    order_price_field_sell='open',
    capital_base=float("1.0e6"),
    benchmark='000300.INDX',
)
[2017-02-17 11:07:45.933965] INFO: bigquant: backtest.v4 start ..
/var/app/enabled/pandas/tseries/index.py:817: PerformanceWarning: Non-vectorized DateOffset being applied to Series or DatetimeIndex
  "or DatetimeIndex", PerformanceWarning)
date =  2015-01-05 该交易日已经结束
/var/app/enabled/empyrical/stats.py:534: RuntimeWarning: invalid value encountered in double_scalars
  sortino = mu / dsr
date =  2015-02-02 该交易日已经结束
date =  2015-03-02 该交易日已经结束
In [ ]:
 

(会飞的鱼) #2

策略 收益风险怎么样?有图吗?


(江旭奇) #3

这个策略对计算动量因子的期限很敏感吧?因为虽然存在动量效应,但反转效应也存在啊,如果期限太长,可能出现反转效应。


(华尔街的猫) #4

回测已经是v5版本了,回测接口可以修改为:
m=M.backtest.v5( # 测试接口
instruments=instruments,
start_date=start_date,
end_date=end_date,
initialize=initialize_0,
handle_data=handle_data_0,
order_price_field='close',
order_price_field_buy='open',
order_price_field_sell='open',
capital_base=float("1.0e6"),
benchmark='000300.INDX',
)