复制链接
克隆策略

    {"description":"实验创建于2021/11/25","graph":{"edges":[{"to_node_id":"-16:instruments","from_node_id":"287d2cb0-f53c-4101-bdf8-104b137c8601-62:data"}],"nodes":[{"node_id":"-16","module_id":"BigQuantSpace.trade.trade-v4","parameters":[{"name":"start_date","value":"2022-01-03","type":"Literal","bound_global_parameter":null},{"name":"end_date","value":"2022-04-28","type":"Literal","bound_global_parameter":null},{"name":"initialize","value":"# 回测引擎:初始化函数,只执行一次\ndef bigquant_run(context):\n # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数\n context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))","type":"Literal","bound_global_parameter":null},{"name":"handle_data","value":"# 回测引擎:每日数据处理函数,每天执行一次\ndef bigquant_run(context, data):\n # 获取今日的日期\n today = data.current_dt.strftime('%Y-%m-%d')\n # 通过positions对象,使用列表生成式的方法获取目前持仓的股票列表\n stock_hold_now = {e.symbol: p.amount * p.last_sale_price\n for e, p in context.perf_tracker.position_tracker.positions.items()}\n\n # //////////////////////////////////计算20日收益率动量拟合取斜率最大的标的\n rank = []\n for stock in context.instruments:\n # 标的为字符串格式\n stock_1 = context.symbol(stock) # 标的为字符串格\n data_1 = data.history(stock_1, ['close', 'open'], 20, '1d') # 获取前20天的历史收盘价\n score = np.polyfit(np.arange(len(data_1)), data_1.close / data_1.close[0], 1)[0]\n rank.append([stock, score])\n rank.sort(key=lambda x: x[-1], reverse=True) # 排序\n check_out_list = rank[0]\n print(data_1['close'].tail(3))\n # /////////////////////////////////计算20日收益率动量拟合取斜率最大的标的\n\n \n # /////////////////////////////////RSRS相关公式\n def get_ols(x, y):\n slope, intercept = np.polyfit(x, y, 1)\n r2 = 1 - (sum((y - (slope * x + intercept)) ** 2) / ((len(y) - 1) * np.var(y, ddof=1)))\n return intercept, slope, r2\n\n def initial_slope_series():\n data_1 = data.history(context.symbol('510300.HOF'), ['high', 'low'], 618, '1d') # 获取基准历史最高价 最低价\n return [get_ols(data_1.low[i:i + 18], data_1.high[i:i + 18])[1] for i in range(600)]\n\n # 因子标准化\n def get_zscore(slope_series):\n mean = np.mean(slope_series)\n std = np.std(slope_series)\n return (slope_series[-1] - mean) / std\n # /////////////////////////////////RSRS相关公式\n\n \n # /////////////////////////////////// 只看RSRS因子值作为买入、持有和清仓依据\n # 只看RSRS因子值作为买入、持有和清仓依据,前版本还加入了移动均线的上行作为条件\n def get_timing_signal(context, stock):\n slope_series = initial_slope_series()[:-1]\n high_low_data = data.history(context.symbol('510300.HOF'), ['high', 'low'], 18, '1d') # 获取基准历史最高价 最低价\n intercept, slope, r2 = get_ols(high_low_data.low, high_low_data.high)\n slope_series.append(slope)\n rsrs_score = get_zscore(slope_series[-600:]) * r2\n\n if rsrs_score > 0.7:\n return \"BUY\"\n elif rsrs_score < -0.7:\n return \"SELL\"\n else:\n return \"KEEP\"\n # /////////////////////////////////// 只看RSRS因子值作为买入、持有和清仓依据\n \n \n\n # ///////////////////////////////////买卖主函数\n # 交易主函数,先确定ETF最强的是谁,然后再根据择时信号判断是否需要切换或者清仓\n timing_signal = get_timing_signal(context, '510300.HOF') # 获取买\\卖\\持有信号\n print('今日自选及择时信号:{} {}'.format(check_out_list[0], timing_signal)) # 打印\n\n if timing_signal == 'SELL': # 如果信息为卖,执行卖出\n for stock in stock_hold_now: # 代码与标的代码循环对比\n context.order_target_percent(stock, 0) # 全部卖出\n elif timing_signal == 'BUY' or timing_signal == 'KEEP': # 如果信息为买或持有,买入或持有\n context.order_target_percent(check_out_list[0], 1)\n else:\n pass\n # ///////////////////////////////////买卖主函数\n\n\n\n\n\n","type":"Literal","bound_global_parameter":null},{"name":"prepare","value":"# 回测引擎:准备数据,只执行一次\ndef bigquant_run(context):\n pass\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":"volume_limit","value":"0","type":"Literal","bound_global_parameter":null},{"name":"order_price_field_buy","value":"open","type":"Literal","bound_global_parameter":null},{"name":"order_price_field_sell","value":"open","type":"Literal","bound_global_parameter":null},{"name":"capital_base","value":1000000,"type":"Literal","bound_global_parameter":null},{"name":"auto_cancel_non_tradable_orders","value":"True","type":"Literal","bound_global_parameter":null},{"name":"data_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":"plot_charts","value":"True","type":"Literal","bound_global_parameter":null},{"name":"backtest_only","value":"False","type":"Literal","bound_global_parameter":null},{"name":"benchmark","value":"","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"instruments","node_id":"-16"},{"name":"options_data","node_id":"-16"},{"name":"history_ds","node_id":"-16"},{"name":"benchmark_ds","node_id":"-16"},{"name":"trading_calendar","node_id":"-16"}],"output_ports":[{"name":"raw_perf","node_id":"-16"}],"cacheable":false,"seq_num":2,"comment":"","comment_collapsed":true},{"node_id":"287d2cb0-f53c-4101-bdf8-104b137c8601-62","module_id":"BigQuantSpace.instruments.instruments-v2","parameters":[{"name":"start_date","value":"2022-01-03","type":"Literal","bound_global_parameter":null},{"name":"end_date","value":"2022-04-28","type":"Literal","bound_global_parameter":null},{"name":"market","value":"CN_FUND","type":"Literal","bound_global_parameter":null},{"name":"instrument_list","value":"510050.HOF\n159928.ZOF\n510310.HOF\n510300.HOF\n\n","type":"Literal","bound_global_parameter":null},{"name":"max_count","value":"0","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"rolling_conf","node_id":"287d2cb0-f53c-4101-bdf8-104b137c8601-62"}],"output_ports":[{"name":"data","node_id":"287d2cb0-f53c-4101-bdf8-104b137c8601-62"}],"cacheable":false,"seq_num":7,"comment":"预测数据,用于回测和模拟","comment_collapsed":true}],"node_layout":"<node_postions><node_position Node='-16' Position='361.6514892578125,364.5211486816406,200,200'/><node_position Node='287d2cb0-f53c-4101-bdf8-104b137c8601-62' Position='79,-74,200,200'/></node_postions>"},"nodes_readonly":false,"studio_version":"v2"}
    In [92]:
    # 本代码由可视化策略环境自动生成 2022年5月1日 19:53
    # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
    
    
    # 回测引擎:初始化函数,只执行一次
    def m2_initialize_bigquant_run(context):
        # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
        context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
    # 回测引擎:每日数据处理函数,每天执行一次
    def m2_handle_data_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.perf_tracker.position_tracker.positions.items()}
    
        # //////////////////////////////////计算20日收益率动量拟合取斜率最大的标的
        rank = []
        for stock in context.instruments:
            # 标的为字符串格式
            stock_1 = context.symbol(stock)  # 标的为字符串格
            data_1 = data.history(stock_1, ['close', 'open'], 20, '1d')  # 获取前20天的历史收盘价
            score = np.polyfit(np.arange(len(data_1)), data_1.close / data_1.close[0], 1)[0]
            rank.append([stock, score])
        rank.sort(key=lambda x: x[-1], reverse=True)  # 排序
        check_out_list = rank[0]
        print(data_1['close'].tail(3))
        # /////////////////////////////////计算20日收益率动量拟合取斜率最大的标的
    
        
        # /////////////////////////////////RSRS相关公式
        def get_ols(x, y):
            slope, intercept = np.polyfit(x, y, 1)
            r2 = 1 - (sum((y - (slope * x + intercept)) ** 2) / ((len(y) - 1) * np.var(y, ddof=1)))
            return intercept, slope, r2
    
        def initial_slope_series():
            data_1 = data.history(context.symbol('510300.HOF'), ['high', 'low'], 618, '1d')  # 获取基准历史最高价 最低价
            return [get_ols(data_1.low[i:i + 18], data_1.high[i:i + 18])[1] for i in range(600)]
    
        # 因子标准化
        def get_zscore(slope_series):
            mean = np.mean(slope_series)
            std = np.std(slope_series)
            return (slope_series[-1] - mean) / std
        # /////////////////////////////////RSRS相关公式
    
        
        # /////////////////////////////////// 只看RSRS因子值作为买入、持有和清仓依据
        # 只看RSRS因子值作为买入、持有和清仓依据,前版本还加入了移动均线的上行作为条件
        def get_timing_signal(context, stock):
            slope_series = initial_slope_series()[:-1]
            high_low_data = data.history(context.symbol('510300.HOF'), ['high', 'low'], 18, '1d')  # 获取基准历史最高价 最低价
            intercept, slope, r2 = get_ols(high_low_data.low, high_low_data.high)
            slope_series.append(slope)
            rsrs_score = get_zscore(slope_series[-600:]) * r2
    
            if rsrs_score > 0.7:
                return "BUY"
            elif rsrs_score < -0.7:
                return "SELL"
            else:
                return "KEEP"
        # /////////////////////////////////// 只看RSRS因子值作为买入、持有和清仓依据
        
        
    
        # ///////////////////////////////////买卖主函数
        # 交易主函数,先确定ETF最强的是谁,然后再根据择时信号判断是否需要切换或者清仓
        timing_signal = get_timing_signal(context, '510300.HOF')  # 获取买\卖\持有信号
        print('今日自选及择时信号:{} {}'.format(check_out_list[0], timing_signal))  # 打印
    
        if timing_signal == 'SELL':  # 如果信息为卖,执行卖出
            for stock in stock_hold_now:  # 代码与标的代码循环对比
                context.order_target_percent(stock, 0)  # 全部卖出
        elif timing_signal == 'BUY' or timing_signal == 'KEEP':  # 如果信息为买或持有,买入或持有
            context.order_target_percent(check_out_list[0], 1)
        else:
            pass
        # ///////////////////////////////////买卖主函数
    
    
    
    
    
    
    # 回测引擎:准备数据,只执行一次
    def m2_prepare_bigquant_run(context):
        pass
    
    # 回测引擎:每个单位时间开始前调用一次,即每日开盘前调用一次。
    def m2_before_trading_start_bigquant_run(context, data):
        pass
    
    
    m7 = M.instruments.v2(
        start_date='2022-01-03',
        end_date='2022-04-28',
        market='CN_FUND',
        instrument_list="""510050.HOF
    159928.ZOF
    510310.HOF
    510300.HOF
    
    """,
        max_count=0,
        m_cached=False
    )
    
    m2 = M.trade.v4(
        instruments=m7.data,
        start_date='2022-01-03',
        end_date='2022-04-28',
        initialize=m2_initialize_bigquant_run,
        handle_data=m2_handle_data_bigquant_run,
        prepare=m2_prepare_bigquant_run,
        before_trading_start=m2_before_trading_start_bigquant_run,
        volume_limit=0,
        order_price_field_buy='open',
        order_price_field_sell='open',
        capital_base=1000000,
        auto_cancel_non_tradable_orders=True,
        data_frequency='daily',
        price_type='真实价格',
        product_type='股票',
        plot_charts=True,
        backtest_only=False,
        benchmark=''
    )
    
    2021-12-30 00:00:00+00:00    2.287
    2021-12-31 00:00:00+00:00    2.292
    2022-01-04 00:00:00+00:00    2.285
    Freq: C, Name: close, dtype: float64
    
    ---------------------------------------------------------------------------
    IndexError                                Traceback (most recent call last)
    <ipython-input-92-674cafdce305> in <module>
        108 )
        109 
    --> 110 m2 = M.trade.v4(
        111     instruments=m7.data,
        112     start_date='2022-01-03',
    
    <ipython-input-92-674cafdce305> in m2_handle_data_bigquant_run(context, data)
         68     # ///////////////////////////////////买卖主函数
         69     # 交易主函数,先确定ETF最强的是谁,然后再根据择时信号判断是否需要切换或者清仓
    ---> 70     timing_signal = get_timing_signal(context, '510300.HOF')  # 获取买\卖\持有信号
         71     print('今日自选及择时信号:{} {}'.format(check_out_list[0], timing_signal))  # 打印
         72 
    
    <ipython-input-92-674cafdce305> in get_timing_signal(context, stock)
         50     # 只看RSRS因子值作为买入、持有和清仓依据,前版本还加入了移动均线的上行作为条件
         51     def get_timing_signal(context, stock):
    ---> 52         slope_series = initial_slope_series()[:-1]
         53         high_low_data = data.history(context.symbol('510300.HOF'), ['high', 'low'], 18, '1d')  # 获取基准历史最高价 最低价
         54         intercept, slope, r2 = get_ols(high_low_data.low, high_low_data.high)
    
    <ipython-input-92-674cafdce305> in initial_slope_series()
         36 
         37     def initial_slope_series():
    ---> 38         data_1 = data.history(context.symbol('510300.HOF'), ['high', 'low'], 618, '1d')  # 获取基准历史最高价 最低价
         39         return [get_ols(data_1.low[i:i + 18], data_1.high[i:i + 18])[1] for i in range(600)]
         40 
    
    IndexError: index 4507 is out of bounds for axis 0 with size 4250