hxgre的知识库

严格月初调仓示例

由hxgre创建,最终由hxgre 被浏览 33 用户

量化策略从角度上分为高频策略和低频侧率。高频策略基于分钟、快照等行情数据开发策略,持仓周期同样相对较短。低频策略一般基于基本面财务因子等低频,因为数据更新较长,调仓周期一般在月度或季度,甚至年度。

目前BigQuant平台上的模板策略一般是根据持仓周期进行调仓回测的,比如5日持仓、30日持仓等。这里,我们举一个简单的逻辑代码说明如何判断调仓周期为22个交易日:

1.在回测模块初始化中,设定调仓周期 rebalance_days = 22;并创建一个extension[‘index’]用于保存记录K线运行数量。

2.在handle_data模块中,每当新的一个K线即交易日来临后,extension[‘index’]会进行+1操作即记录一次交易日,然后对已有的交易日数量在调仓周期上进行取模操作,如果取模结果不为0,则直接返回,即跳过该交易日,不进行选股、买入卖出等操作。

def m6_initialize_bigquant_run(context):
    #周期为22个交易日
    context.rebalance_days = 22

    # 如果策略运行中,需要将数据进行保存,可以借用extension这个对象,类型为dict
    # 比如当前运行的k线的索引,比如个股持仓天数、买入均价
    if 'index' not in context.extension:
        context.extension['index'] = 0

def m6_handle_data_bigquant_run(context, data):
    context.extension['index'] += 1
    # 不在换仓日就return,相当于后面的代码只会一个月运行一次,买入的股票会持有1个月
    if  context.extension['index'] % context.rebalance_days != 0:
        return 

如果调仓周期为一个月,则设定rebalance_days参数为22即可,因为一个月一般有22个交易日。但是,如果某月存在假期比如春节、国庆节,或者交易所因某种原因未开市的话比如俄罗斯人为停市等,这种情况会导致该月交易日并不等于22,因此这种逻辑并非严格执行月度调仓策略。

如果需要严格按照“月末选股、月初调仓”的策略,则需要对回测引擎进行如下修改:

1.将输入的特征数据由日度数据改为月度数据

2.重新定义一个def month_handle_data(context, data)函数,在回测初始化函数中,通过schedule_function()方法调用上述函数,这样会每月调用一次handle_data函数进行回测处理。

3.在month_handle_data()函数中,在每月初获取上个月末的因子数据,并选股判断筛选出目标股票池,后续进行相应的调仓操作即可。

# 回测引擎:初始化函数,只执行一次
def m6_initialize_bigquant_run(context):
    #每月调仓:则需要将输入特征数据转换为月度数据
    context.month_data = context.indicator_data.groupby('instrument').resample(rule='M', on='date')
    context.month_data = context.month_data.agg({
                            'instrument': 'last',  
                            'date':'last',
                            'list_days_0': 'last',
                            'market_cap_0': 'last',
                            'pe_ttm_0': 'last',        
                        })
    context.month_data = context.month_data.reset_index(drop=True)
    
    #每月调仓,改用每月调用一次主处理函数
    schedule_function(func=month_handle_data,
        date_rule=date_rules.month_start(),   # 例如每周开始时执行一次
        time_rule=time_rules.market_open())   # 开盘执行

from datetime import timedelta
#每月初调用一次主处理函数,在本函数进行目标股票获取并进行买卖
def month_handle_data(context, data):
    # 当前的日期
    date = data.current_dt.strftime('%Y-%m-%d')
    #根据当前时间获取上一个月的时间。当前月初往前偏移28天一定是上个月
    last_month = str(pd.to_datetime(date) + timedelta(days=-28))[0:7]
    #获取上个月末的股票池
    tempdf = context.month_data[context.month_data['date'].astype(str).apply(lambda x:x[0:7])==last_month]
    #对股票池根据因子值列进行排序,并取前30只股票
    stocks = tempdf.sort_values('pe_ttm_0').iloc[:context.stock_num,:]
    #把股票id转换成需要购买的股票列表
    stock_to_buy = stocks['instrument'].values.tolist()
    print("选股日期:",date,',选股数量:',len(stock_to_buy))

下述策略是一个简单的因子选股策略,选股条件如下:

在每月月初等权重买入符合条件的股票,下月月初换仓
pe_ttm>0且最小的30只股票
总市值在50亿以下 
非ST股票
不买上市时间小于60天的新股
股票止损比率为-10%(即亏损10%就卖出)
手续费:买入万分之1  卖出千分之1

https://bigquant.com/experimentshare/8fa45b31260d455ca817a8ab0306776d

\

标签

量化策略调仓周期调仓
{link}