历史文档

开发传统趋势策略

由clearyf创建,最终由small_q 被浏览 809 用户

更新

本文内容已经过期,不再适合平台最新版本,请查看如下最新内容:

https://bigquant.com/wiki/doc/5bya5yr5lyg57uf6lal5yq562w55wl-T5GmwSk63u

\

导语

本文以双均线策略为例,如何开发一个传统的趋势跟踪策略。

在BigQuant策略平台上,除了开发AI策略,还可以开发传统策略,比如趋势跟踪、套利、事件驱动策略、多因子选股策略。本文以双均线策略为例,帮助大家更好地理解BigQuant回测机制

双均线策略的策略思想是:当短期均线上穿长期均线时,形成金叉,此时买入股票。当短期均线下穿长期均线时,形成死叉,此时卖出股票。研究表明,双均线系统虽然简单,但只要严格执行,也能长期盈利。

策略的构建流程如下图所示:

构建策略流程

我们可以在BigStudio环境下构建如下流程

第一步,我们通过证券代码列表模m1块指定回测的股票和回测起止日期。

第二步,我们通过特征输入列表模块m2定义买入和卖出信号

  • 定义5日均线大于50日均线作为买入条件信号buy_condition,
  • 定义5日均线小于50日均线作为卖出条件信号sell_condition。

这里的等号表示将表达式重命名,以免表达式过长导致不方便后续的过滤操作。

buy_condition=where(mean(close_0,5)>mean(close_0,50),1,0)
sell_condition=where(mean(close_0,5)<mean(close_0,50),1,0)

上述代码中使用的close_0默认是后复权价格,如果想采用真实价格计算信号,那么可以改写为

buy_condition=where(mean(close_0/adjust_factor_0,5)>mean(close_0/adjust_factor_0, 50),1,0)
sell_condition=where(mean(close_0/adjust_factor_0,5,5)<mean(close_0/adjust_factor_0, 50),1,0)

第三步,通过基础特征抽取模块获取表达式中基础因子数据close_0,

第四步,通过衍生特征抽取m8获取buy_condition和sell_condition对应的因子表达式数据。

第五步,利用缺失值处理模块m6对含有缺失值的行进行删除处理。

第六步,我们将证券代买列表模块的输出和计算好的买卖条件信号输出给回测模块m3。

在回测模块中,首先我们在初始化函数里通过context.set_commission设置交易手续费

    # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))

本例中,我们设置股票的买入手续费按照成交额的0.0003收取,卖出手续费按成交额的0.0013收取,不足5元按照5元收取。

然后,我们在数据准备函数中我们定义全局变量context.daily_stock_buy和context.daily_stock_sell分别获取每日符合买卖条件的股票列表

# 回测引擎:准备数据,只执行一次
def bigquant_run(context):
    # 加载计算数据
    df = context.options['data'].read_df()

    # 函数:求满足开仓条件的股票列表
    def open_pos_con(df):
        return list(df[df['buy_condition']>0].instrument)

    # 函数:求满足平仓条件的股票列表
    def close_pos_con(df):
        return list(df[df['sell_condition']>0].instrument)

    # 逐日计算每日买入股票列表
    context.daily_stock_buy= df.groupby('date').apply(open_pos_con)
    # 逐日计算每日卖出股票列表
    context.daily_stock_sell= df.groupby('date').apply(close_pos_con)

最后,我们在主函数中进行每日交易逻辑的编写

# 回测引擎:每日数据处理函数,每天执行一次
def bigquant_run(context, data):
    # 获取今日的日期字符串
    today = data.current_dt.strftime('%Y-%m-%d')  
    # 通过positions对象,使用列表生成式的方法获取目前持仓的股票列表
    stock_hold_now = {e.symbol: p.amount * p.last_sale_price
                 for e, p in context.portfolio.positions.items()}
    
    try:
        buy_stock = context.daily_stock_buy[today]  # 当日符合买入条件的股票
    except:
        buy_stock=[]  # 如果没有符合条件的股票,就设置为空
    
    try:
        sell_stock = context.daily_stock_sell[today]  # 当日符合卖出条件的股票
    except:
        sell_stock=[] # 如果没有符合条件的股票,就设置为空
    
    # 需要卖出的股票:已有持仓中符合卖出条件的股票
    stock_to_sell = [ i for i in stock_hold_now if i in sell_stock ]
    
    # 如果有卖出信号
    if len(stock_to_sell)>0:
        for instrument in stock_to_sell:
            # 将标的转化为equity格式以便下单操作
            sid = context.symbol(instrument) 
            # 获取股票持仓
            cur_position = context.portfolio.positions[sid].amount
            # 如果有股票持仓并且处于可交易状态,则下单卖出
            if cur_position > 0 and data.can_trade(sid):
                # 通过order_target_percent下单至指定仓位比例(通常0到1之间)
                context.order_target_percent(sid, 0) 
   
    # 如果有买入信号/需要调整持仓
    if len(buy_stock )>0:
        # 每只股票的比重为等资金比例持有
        weight = 1/len(buy_stock )
        for instrument in buy_stock :
            # 将标的转化为equity格式以便下单操作
            sid = context.symbol(instrument)
            if  data.can_trade(sid):
                context.order_target_percent(sid, weight) # 买入

策略案例

https://bigquant.com/experimentshare/b342d0a1dfc04a10a2950352e5276ad1

小结: BigQuant不仅支持AI量化策略,同样也支持传统量化策略,大家可参考上述步骤,自行开发您所需的传统量化策略。

标签

双均线策略