克隆策略

择时策略——AR人气指标

版本 v1.0

目录

AR人气指标策略的交易规则

策略构建步骤

策略的实现

正文

一、AR人气指标策略的交易规则

  • AR = [N天所有(High-Open)的和/ N天所有(Open—Low)的和] * 100,其中:High=当日最高价;Low=当日最低价;Open=当日开市价N为公式中的设定参数,一般设定为26日。
  • MA:在上升行情进入稳定期,短周期、中周期、长周期移动平均线从上而下依次顺序排列,向右上方移动。在下跌行情中,短周期、中周期、长周期移动平均线自下而上依次顺序排列,向右下方移动,称为空头 排列,预示市价将大幅下跌。
  • 如果AR值 > 110,当MA(5)>MA(10)>MA(30),做多 。
  • 当MA(5)<MA(10)<MA(30),做空 ,并且此条件下,如果AR值 < 75,代表这波下跌动能趋于耗尽,这时候平掉空头。
  • 如果110 >= AR值 >= 90 ,代表市价走势比较平稳,不会出现剧烈波动,这时候保持空仓。

二、策略构建步骤

1、确定股票池和回测时间

  • 通过证券代码列表输入回测的起止日期

2、确定买卖原则

  • AR值 > 120,MA(5)>MA(10)>MA(30)做多 ,当MA(5)<MA(10)<MA(30)做空 ,并且此条件下,AR值 < 75,平掉空头,110 >= AR值 >= 90,保持空仓。

3、回测

  • 通过 trade 模块中的初始化函数定义交易手续费和滑点;
  • 通过 trade 模块中的主函数(handle函数)查看每日的买卖交易信号,按照买卖原则执行相应的买入/卖出/调仓操作。

三、策略的实现

可视化策略实现如下:

    {"description":"实验创建于2021/12/2","graph":{"edges":[{"to_node_id":"-71:instruments","from_node_id":"-5:data"},{"to_node_id":"-127:instruments","from_node_id":"-5:data"},{"to_node_id":"-62:features","from_node_id":"-13:data"},{"to_node_id":"-71:features","from_node_id":"-13:data"},{"to_node_id":"-97:input_data","from_node_id":"-62:data"},{"to_node_id":"-62:input_data","from_node_id":"-71:data"},{"to_node_id":"-127:options_data","from_node_id":"-97:data"}],"nodes":[{"node_id":"-5","module_id":"BigQuantSpace.instruments.instruments-v2","parameters":[{"name":"start_date","value":"2021-02-17","type":"Literal","bound_global_parameter":null},{"name":"end_date","value":"2021-11-26","type":"Literal","bound_global_parameter":null},{"name":"market","value":"CN_FUTURE","type":"Literal","bound_global_parameter":null},{"name":"instrument_list","value":"JM2201.DCE","type":"Literal","bound_global_parameter":null},{"name":"max_count","value":0,"type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"rolling_conf","node_id":"-5"}],"output_ports":[{"name":"data","node_id":"-5"}],"cacheable":true,"seq_num":1,"comment":"","comment_collapsed":true},{"node_id":"-13","module_id":"BigQuantSpace.input_features.input_features-v1","parameters":[{"name":"features","value":"# #号开始的表示注释,注释需单独一行\n# 多个特征,每行一个,可以包含基础特征和衍生特征,特征须为本平台特征\nAR = sum((high - open),26)/sum((open - low ),26)*100\nmean_5 = mean(close,5)\nmean_10 = mean(close,10)\nmean_30 = mean(close,30)","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"features_ds","node_id":"-13"}],"output_ports":[{"name":"data","node_id":"-13"}],"cacheable":true,"seq_num":2,"comment":"","comment_collapsed":true},{"node_id":"-62","module_id":"BigQuantSpace.derived_feature_extractor.derived_feature_extractor-v3","parameters":[{"name":"date_col","value":"date","type":"Literal","bound_global_parameter":null},{"name":"instrument_col","value":"instrument","type":"Literal","bound_global_parameter":null},{"name":"drop_na","value":"False","type":"Literal","bound_global_parameter":null},{"name":"remove_extra_columns","value":"False","type":"Literal","bound_global_parameter":null},{"name":"user_functions","value":"{}","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"input_data","node_id":"-62"},{"name":"features","node_id":"-62"}],"output_ports":[{"name":"data","node_id":"-62"}],"cacheable":true,"seq_num":4,"comment":"","comment_collapsed":true},{"node_id":"-71","module_id":"BigQuantSpace.use_datasource.use_datasource-v1","parameters":[{"name":"datasource_id","value":"bar1d_CN_FUTURE","type":"Literal","bound_global_parameter":null},{"name":"start_date","value":"","type":"Literal","bound_global_parameter":null},{"name":"end_date","value":"","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"instruments","node_id":"-71"},{"name":"features","node_id":"-71"}],"output_ports":[{"name":"data","node_id":"-71"}],"cacheable":true,"seq_num":5,"comment":"","comment_collapsed":true},{"node_id":"-97","module_id":"BigQuantSpace.dropnan.dropnan-v2","parameters":[],"input_ports":[{"name":"input_data","node_id":"-97"},{"name":"features","node_id":"-97"}],"output_ports":[{"name":"data","node_id":"-97"}],"cacheable":true,"seq_num":3,"comment":"","comment_collapsed":true},{"node_id":"-127","module_id":"BigQuantSpace.hftrade.hftrade-v1","parameters":[{"name":"start_date","value":"2021-02-14","type":"Literal","bound_global_parameter":null},{"name":"end_date","value":"2021-10-18","type":"Literal","bound_global_parameter":null},{"name":"initialize","value":"# 交易引擎:初始化函数,只执行一次\ndef bigquant_run(context):\n context.all_data = context.options[\"data\"].read()\n context.ar_upr=110\n context.ar_dwn=75\n \n","type":"Literal","bound_global_parameter":null},{"name":"before_trading_start","value":"# 交易引擎:每个单位时间开盘前调用一次。\ndef bigquant_run(context, data):\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"handle_tick","value":"# 交易引擎:tick数据处理函数,每个tick执行一次\ndef bigquant_run(context, data):\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"handle_data","value":"# 交易引擎:bar数据处理函数,每个时间单位执行一次\ndef bigquant_run(context, data):\n today = data.current_dt.strftime('%Y-%m-%d') # 当前交易日期\n all_data = context.all_data[context.all_data.date == today]\n if len(all_data) == 0:#过滤没有指标的数据\n return\n \n ar_value = all_data['AR'].iloc[0]\n ma_short = all_data['mean_5'].iloc[0]\n ma_medium = all_data['mean_10'].iloc[0]\n ma_long = all_data['mean_30'].iloc[0]\n price = all_data['close'].iloc[0]\n \n instrument = context.future_symbol(context.instruments[0]) # 交易标的\n long_position = context.get_account_position(instrument, direction=Direction.LONG).avail_qty#多头持仓\n short_position = context.get_account_position(instrument, direction=Direction.SHORT).avail_qty#空头持仓\n curr_position = short_position + long_position#总持仓\n if (ar_value > context.ar_upr) and (ma_short > ma_medium > ma_long): # 开多\n if short_position > 0:\n print(short_position)\n context.buy_close(instrument, short_position, price, order_type=OrderType.MARKET)\n context.buy_open(instrument, 4, price, order_type=OrderType.MARKET)\n print(today,'先平空再开多')\n elif curr_position == 0:\n context.buy_open(instrument, 4, price, order_type=OrderType.MARKET)\n print(today,'开多')\n if ar_value < context.ar_dwn and ma_short < ma_medium < ma_long :# 开空\n if long_position > 0:\n context.sell_close(instrument, long_position, price, order_type=OrderType.MARKET)\n context.sell_open(instrument, 4, price, order_type=OrderType.MARKET)\n print(today,'先平多再开空',curr_position)\n elif curr_position == 0:\n context.sell_open(instrument, 4, price, order_type=OrderType.MARKET)\n print(today,'开空')\n if 100 >= ar_value >= 90 :\n if long_position > 0:\n context.sell_close(instrument, long_position, price, order_type=OrderType.MARKET)\n print(today,'AR在90~100之间平多仓')\n elif short_position > 0:\n context.buy_close(instrument, short_position, price, order_type=OrderType.MARKET)\n print(today,'AR在90~100之间平空仓') \n ","type":"Literal","bound_global_parameter":null},{"name":"handle_trade","value":"# 交易引擎:成交回报处理函数,每个成交发生时执行一次\ndef bigquant_run(context, data):\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"handle_order","value":"# 交易引擎:委托回报处理函数,每个委托变化时执行一次\ndef bigquant_run(context, data):\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"after_trading","value":"# 交易引擎:盘后处理函数,每日盘后执行一次\ndef bigquant_run(context, data):\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"capital_base","value":1000000,"type":"Literal","bound_global_parameter":null},{"name":"frequency","value":"daily","type":"Literal","bound_global_parameter":null},{"name":"price_type","value":"真实价格","type":"Literal","bound_global_parameter":null},{"name":"product_type","value":"期货","type":"Literal","bound_global_parameter":null},{"name":"before_start_days","value":"","type":"Literal","bound_global_parameter":null},{"name":"benchmark","value":"000300.HIX","type":"Literal","bound_global_parameter":null},{"name":"plot_charts","value":"True","type":"Literal","bound_global_parameter":null},{"name":"disable_cache","value":"False","type":"Literal","bound_global_parameter":null},{"name":"show_debug_info","value":"False","type":"Literal","bound_global_parameter":null},{"name":"backtest_only","value":"False","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"instruments","node_id":"-127"},{"name":"history_ds","node_id":"-127"},{"name":"benchmark_ds","node_id":"-127"},{"name":"options_data","node_id":"-127"}],"output_ports":[{"name":"raw_perf","node_id":"-127"}],"cacheable":false,"seq_num":6,"comment":"","comment_collapsed":true}],"node_layout":"<node_postions><node_position Node='-5' Position='293,113,200,200'/><node_position Node='-13' Position='602,109,200,200'/><node_position Node='-62' Position='420,280,200,200'/><node_position Node='-71' Position='258,194,200,200'/><node_position Node='-97' Position='406,357,200,200'/><node_position Node='-127' Position='350,452,200,200'/></node_postions>"},"nodes_readonly":false,"studio_version":"v2"}
    In [199]:
    # 本代码由可视化策略环境自动生成 2021年12月6日 09:56
    # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
    
    
    # 交易引擎:初始化函数,只执行一次
    def m6_initialize_bigquant_run(context):
        context.all_data = context.options["data"].read()
        context.ar_upr=110
        context.ar_dwn=75
        
    
    # 交易引擎:每个单位时间开盘前调用一次。
    def m6_before_trading_start_bigquant_run(context, data):
        pass
    
    # 交易引擎:tick数据处理函数,每个tick执行一次
    def m6_handle_tick_bigquant_run(context, data):
        pass
    
    # 交易引擎:bar数据处理函数,每个时间单位执行一次
    def m6_handle_data_bigquant_run(context, data):
        today = data.current_dt.strftime('%Y-%m-%d') # 当前交易日期
        all_data = context.all_data[context.all_data.date == today]
        if len(all_data) == 0:#过滤没有指标的数据
            return
           
        ar_value = all_data['AR'].iloc[0]
        ma_short = all_data['mean_5'].iloc[0]
        ma_medium = all_data['mean_10'].iloc[0]
        ma_long = all_data['mean_30'].iloc[0]
        price = all_data['close'].iloc[0]
        
        instrument = context.future_symbol(context.instruments[0]) # 交易标的
        long_position = context.get_account_position(instrument, direction=Direction.LONG).avail_qty#多头持仓
        short_position = context.get_account_position(instrument, direction=Direction.SHORT).avail_qty#空头持仓
        curr_position = short_position + long_position#总持仓
        if (ar_value > context.ar_upr) and (ma_short > ma_medium > ma_long): # 开多
            if short_position > 0:
                print(short_position)
                context.buy_close(instrument, short_position, price, order_type=OrderType.MARKET)
                context.buy_open(instrument, 4, price, order_type=OrderType.MARKET)
                print(today,'先平空再开多')
            elif curr_position == 0:
                context.buy_open(instrument, 4, price, order_type=OrderType.MARKET)
                print(today,'开多')
        if ar_value < context.ar_dwn and ma_short < ma_medium < ma_long :# 开空
            if long_position > 0:
                context.sell_close(instrument, long_position, price, order_type=OrderType.MARKET)
                context.sell_open(instrument, 4, price, order_type=OrderType.MARKET)
                print(today,'先平多再开空',curr_position)
            elif curr_position == 0:
                context.sell_open(instrument, 4, price, order_type=OrderType.MARKET)
                print(today,'开空')
        if 100 >= ar_value >= 90 :
            if long_position > 0:
                context.sell_close(instrument, long_position, price, order_type=OrderType.MARKET)
                print(today,'AR在90~100之间平多仓')
            elif short_position > 0:
                context.buy_close(instrument, short_position, price, order_type=OrderType.MARKET)
                print(today,'AR在90~100之间平空仓')    
        
    # 交易引擎:成交回报处理函数,每个成交发生时执行一次
    def m6_handle_trade_bigquant_run(context, data):
        pass
    
    # 交易引擎:委托回报处理函数,每个委托变化时执行一次
    def m6_handle_order_bigquant_run(context, data):
        pass
    
    # 交易引擎:盘后处理函数,每日盘后执行一次
    def m6_after_trading_bigquant_run(context, data):
        pass
    
    
    m1 = M.instruments.v2(
        start_date='2021-02-17',
        end_date='2021-11-26',
        market='CN_FUTURE',
        instrument_list='JM2201.DCE',
        max_count=0
    )
    
    m2 = M.input_features.v1(
        features="""# #号开始的表示注释,注释需单独一行
    # 多个特征,每行一个,可以包含基础特征和衍生特征,特征须为本平台特征
    AR = sum((high - open),26)/sum((open - low ),26)*100
    mean_5 = mean(close,5)
    mean_10 = mean(close,10)
    mean_30 = mean(close,30)"""
    )
    
    m5 = M.use_datasource.v1(
        instruments=m1.data,
        features=m2.data,
        datasource_id='bar1d_CN_FUTURE',
        start_date='',
        end_date=''
    )
    
    m4 = M.derived_feature_extractor.v3(
        input_data=m5.data,
        features=m2.data,
        date_col='date',
        instrument_col='instrument',
        drop_na=False,
        remove_extra_columns=False,
        user_functions={}
    )
    
    m3 = M.dropnan.v2(
        input_data=m4.data
    )
    
    m6 = M.hftrade.v1(
        instruments=m1.data,
        options_data=m3.data,
        start_date='2021-02-14',
        end_date='2021-10-18',
        initialize=m6_initialize_bigquant_run,
        before_trading_start=m6_before_trading_start_bigquant_run,
        handle_tick=m6_handle_tick_bigquant_run,
        handle_data=m6_handle_data_bigquant_run,
        handle_trade=m6_handle_trade_bigquant_run,
        handle_order=m6_handle_order_bigquant_run,
        after_trading=m6_after_trading_bigquant_run,
        capital_base=1000000,
        frequency='daily',
        price_type='真实价格',
        product_type='期货',
        before_start_days='',
        benchmark='000300.HIX',
        plot_charts=True,
        disable_cache=False,
        show_debug_info=False,
        backtest_only=False
    )
    
    2021-12-02 17:47:29.777193 run trading v1.7.9 
    2021-12-02 17:47:29.777418 init history datas... 
    2021-12-02 17:47:29.788830 init trading env... 
    2021-04-06 开多
    2021-05-20 AR在90~100之间平多仓
    2021-06-28 开多
    2021-07-08 AR在90~100之间平多仓
    2021-07-21 开多
    2021-07-23 AR在90~100之间平多仓
    2021-07-26 开多
    
    • 收益率44.94%
    • 年化收益率78.76%
    • 基准收益率-15.49%
    • 阿尔法0.81
    • 贝塔0.07
    • 夏普比率2.66
    • 胜率0.29
    • 盈亏比1.55
    • 收益波动率21.58%
    • 最大回撤10.46%
    bigcharts-data-start/{"__type":"tabs","__id":"bigchart-7f9245d1661f416ebaa3ae8f96ca6c11"}/bigcharts-data-end