精华帖子

量化策略框架封装用法

由anthony_wan创建,最终由anthony_wan 被浏览 104 用户

\

本文将介绍

1.如何封装量化策略框架

2.提供多个预先封装好的量化策略框架

\

什么是策略框架?

说到量化,自然少不了策略。可能会有很多人认为A股中有很多不同的量化策略,实际上恰恰相反。就A股而言,可用的量化策略非常少。目前A股主流的量化策略只有2种,分别为筛选策略和多因子策略。值得注意的是,不同的因子构成的多因子策略其实仅是因子不同,但是依然使用相同的策略框架,所以我们依然认为这是一种策略。


就好像一个人出行,无论是开宝马汽车还是劳斯莱斯,无论汽车的动力来自电还是汽油,他的出行方式统称为驾车出行。


基于这个思想,我们就可以用固定的策略框架 + 不同的因子组合的方法实现快速完成复杂策略的目的。

以A股为例,目前可用的主流策略框架仅有以下两种:

1.筛选策略框架


筛选策略框架是量化爱好者最常用的策略框架。


例如最经典的小市值策略,往往就是获取基础数据以后,通过筛选条件,最终在剩下的股池通过市值因子排序而成的策略。

筛选策略框架的优点是简单,容易完成。

缺点也很明显,筛选策略很容易过拟合,所以当筛选条件过多时策略的泛化能力降低,实盘效果往往不如回测。







\

  1. 多因子策略框架

多因子策略框架是目前私募最常用的策略框架。


值得注意的是在因子合成的部分成熟机构往往会用多模型融合。


多因子策略的优点是稳定,且具有较强的泛化能力。通过滚动训练+机器学习的策略信号不太会过拟合,最终实盘和回测会更加接近。

多因子策略的缺点是维护起来相对复杂,且非常依赖有好的因子。








\

封装策略框架方法

1.点击资源管理器,点击新建文件。


2.建立一个以.py结尾的文件





这是一个简单的筛选策略框架。

将以下代码复制到py文件内

\

def mod1(*args, **kwargs):
    import dai
    from bigmodule import M
    import pandas as pd
    import numpy as np
    sql = kwargs['sql']
    holding_date = kwargs['holding_date']
    num_stock = kwargs['num_stock']
    df = dai.query(sql).df()



    def m5_initialize_bigquant_run(context):
        from bigtrader.finance.commission import PerOrder

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

        # 持有期/调仓周期,1天,3天,5天等
        context.holding_days = holding_date
        # 设置买入股票数量
        context.target_hold_count = num_stock
        # 每只股票的目标权重
        context.target_percent_per_instrument = 1.0 / context.target_hold_count
    def m5_before_trading_start_bigquant_run(context, data):
        # 盘前处理,订阅行情等
        pass

    # @param(id="m5", name="handle_tick")
    # 交易引擎:tick数据处理函数,每个tick执行一次
    def m5_handle_tick_bigquant_run(context, tick):
        pass

# @param(id="m5", name="handle_data")
    def m5_handle_data_bigquant_run(context, data):
        # 每 context.holding_days 个交易日调仓一次
        if context.trading_day_index % context.holding_days != 0:
            return

        # 获取当前日期
        current_date = data.current_dt.strftime("%Y-%m-%d")
        # 获取当日数据
        current_day_data = context.data[context.data["date"] == current_date]
        # 取前10只
        current_day_data.sort_values(by='factor',inplace=True,ascending=False)
        current_day_data = current_day_data.head(context.target_hold_count)
        len_ = len(current_day_data)
        # 获取当日目标持有股票
        target_hold_instruments = set(current_day_data["instrument"])
        # 获取当前已持有股票
        current_hold_instruments = set(context.get_account_positions().keys())

        # 卖出不在目标持有列表中的股票
        for instrument in current_hold_instruments - target_hold_instruments:
            context.order_target_percent(instrument, 0)
            
        # 买入目标持有列表中的股票
        for instrument in target_hold_instruments - current_hold_instruments:
            context.order_target_percent(instrument, 1/len_)

    # @param(id="m5", name="handle_trade")
    # 交易引擎:成交回报处理函数,每个成交发生时执行一次
    def m5_handle_trade_bigquant_run(context, trade):
        pass

    # @param(id="m5", name="handle_order")
    # 交易引擎:委托回报处理函数,每个委托变化时执行一次
    def m5_handle_order_bigquant_run(context, order):
        pass

    # @param(id="m5", name="after_trading")
    # 交易引擎:盘后处理函数,每日盘后执行一次
    def m5_after_trading_bigquant_run(context, data):
        pass

    m5 = M.bigtrader.v22(
        data=df,
        start_date="""""",
        end_date="""""",
        initialize=m5_initialize_bigquant_run,
        before_trading_start=m5_before_trading_start_bigquant_run,
        handle_tick=m5_handle_tick_bigquant_run,
        handle_data=m5_handle_data_bigquant_run,
        handle_trade=m5_handle_trade_bigquant_run,
        handle_order=m5_handle_order_bigquant_run,
        after_trading=m5_after_trading_bigquant_run,
        capital_base=999999,
        frequency="""daily""",
        product_type="""股票""",
        rebalance_period_type="""月度交易日""",
        rebalance_period_days="""1""",
        rebalance_period_roll_forward=True,
        backtest_engine_mode="""标准模式""",
        before_start_days=0,
        volume_limit=1,
        order_price_field_buy="""open""",
        order_price_field_sell="""open""",
        benchmark="""沪深300指数""",
        plot_charts=True,
        debug=False,
        backtest_only=False,
        m_name="""m5""",
        m_cached=False
    )
    
    return


\

使用方法



从py文件内import 函数


配置config文件,输入变量。


运行函数直接回测。





\

策略框架封装的好处


1.固定策略框架,尽量用代码方式实现,避免环境升级带来的bug

2.专注因子本身,专注可解释性收益。

3.固定框架,方便使用,仅需要配置config文件便可以开始回测,使用方式更加简洁。

\

本文评论过 30 会提供机器学习+滚动训练策略框架。


\

评论
  • 万老师您好,看了您封装策略框架感觉受益匪浅,能不能帮忙扩展个小功能呢,就是我嫌bigtrader的log输出有点麻烦,有啥办法能让bigtrader不显示log信息呢?
  • 这个应该是写在源码里的,似乎不太行
{link}