克隆策略

    {"description":"实验创建于2019/4/24","graph":{"edges":[{"to_node_id":"-93:input_1","from_node_id":"-578:data"},{"to_node_id":"-40:input_data","from_node_id":"-632:data_1"},{"to_node_id":"-47:input_1","from_node_id":"-40:data"},{"to_node_id":"-199:input_1","from_node_id":"-47:data_1"},{"to_node_id":"-43:options_data","from_node_id":"-47:data_1"},{"to_node_id":"-43:history_ds","from_node_id":"-47:data_1"},{"to_node_id":"-43:benchmark_ds","from_node_id":"-47:data_1"},{"to_node_id":"-1128:input_1","from_node_id":"-47:data_1"},{"to_node_id":"-43:instruments","from_node_id":"-199:data_1"},{"to_node_id":"-43:trading_calendar","from_node_id":"-1128:data_1"},{"to_node_id":"-93:input_2","from_node_id":"-81:data"},{"to_node_id":"-100:input_1","from_node_id":"-93:data_1"},{"to_node_id":"-632:input_1","from_node_id":"-103:data"}],"nodes":[{"node_id":"-43","module_id":"BigQuantSpace.trade.trade-v4","parameters":[{"name":"start_date","value":"","type":"Literal","bound_global_parameter":null},{"name":"end_date","value":"","type":"Literal","bound_global_parameter":null},{"name":"initialize","value":"# 回测引擎:初始化函数,只执行一次\ndef bigquant_run(context):\n \n # 加载股票指标数据,数据继承自m4模块\n context.indicator_data = context.options['data'].read_df().set_index('date')\n print('indicator_data:', context.indicator_data.head()) \n # 设置交易费用,买入是万三,卖出是千分之1.3,如果不足5元按5元算\n context.set_commission(PerOrder(buy_cost=0.002, sell_cost=0.002, min_cost=5))\n # 设置股票数量\n context.stock_num = 1\n \n # 调仓天数,1个交易日换仓一次\n context.rebalance_days = 1\n \n # 如果策略运行中,需要将数据进行保存,可以借用extension这个对象,类型为dict\n # 比如当前运行的k线的索引,比如个股持仓天数、买入均价\n if 'index' not in context.extension:\n context.extension['index'] = 0\n \n","type":"Literal","bound_global_parameter":null},{"name":"handle_data","value":"# 回测引擎:每日数据处理函数,每天执行一次\ndef bigquant_run(context, data):\n \n # 按每个K线递增\n context.extension['index'] += 1\n \n # 每隔1个交易日进行换仓\n if context.extension['index'] % context.rebalance_days != 0:\n return \n \n # 日期\n date = data.current_dt.strftime('%Y-%m-%d')\n \n print('debug:', date)\n # 买入股票列表\n \n stock_to_buy = context.indicator_data.loc[date]['instrument'][- context.stock_num:]\n print('stock_to_buy:', stock_to_buy)\n \n # 目前持仓列表 \n stock_hold_now = [equity.symbol for equity in context.portfolio.positions]\n print('stock_hold_now:', stock_hold_now)\n \n # 继续持有股票列表\n no_need_to_sell = [i for i in stock_hold_now if i in stock_to_buy]\n print('no_need_to_sell:', no_need_to_sell)\n\n # 卖出股票列表 \n stock_to_sell = [i for i in stock_hold_now if i not in no_need_to_sell]\n print('stock_to_sell:', stock_to_sell)\n\n # 执行卖出\n for stock in stock_to_sell:\n if data.can_trade(context.symbol(stock)):\n context.order_target_percent(context.symbol(stock), 0)\n \n # 如果当天没有买入就返回\n if len(stock_to_buy) == 0:\n return\n \n # 等权重\n weight = 1 / len(stock_to_buy)\n # 执行买入\n for cp in stock_to_buy:\n if data.can_trade(context.symbol(cp)):\n context.order_target_percent(context.symbol(cp), weight)","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.025,"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":"close","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":"btcusdt","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"instruments","node_id":"-43"},{"name":"options_data","node_id":"-43"},{"name":"history_ds","node_id":"-43"},{"name":"benchmark_ds","node_id":"-43"},{"name":"trading_calendar","node_id":"-43"}],"output_ports":[{"name":"raw_perf","node_id":"-43"}],"cacheable":false,"seq_num":2,"comment":"","comment_collapsed":true},{"node_id":"-578","module_id":"BigQuantSpace.input_csv.input_csv-v5","parameters":[{"name":"file","value":"price_symbol_full.csv","type":"Literal","bound_global_parameter":null},{"name":"coding","value":"GBK","type":"Literal","bound_global_parameter":null},{"name":"dtypes","value":"{}","type":"Literal","bound_global_parameter":null},{"name":"date_type","value":"%Y-%m-%d %H:%M:%S","type":"Literal","bound_global_parameter":null},{"name":"date_cols","value":"['datetime']","type":"Literal","bound_global_parameter":null}],"input_ports":[],"output_ports":[{"name":"data","node_id":"-578"}],"cacheable":true,"seq_num":1,"comment":"","comment_collapsed":true},{"node_id":"-632","module_id":"BigQuantSpace.cached.cached-v3","parameters":[{"name":"run","value":"# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端\nimport datetime\ndef bigquant_run(input_1, input_2, input_3):\n df = input_1.read_df()\n df.rename(columns={'datetime': 'date'}, inplace = True)\n df = df.sort_values(by = ['instrument', 'date'],ascending=True)\n df['high_low_diff'] = df['high'] - df['low']\n df['swing'] = df['high_low_diff'] / df['open']\n for name, group in df.groupby('instrument'):\n group['swing_volatility_2'] = group['swing'].rolling(2).std()\n if name == '1.HBI':\n group_all = group\n else:\n group_all = pd.concat([group_all, group])\n group_all = group_all.sort_values(by = ['date', 'instrument'], ascending=True)\n \n return Outputs(data_1=DataSource.write_df(group_all),data_2=None,data_3=None)\n","type":"Literal","bound_global_parameter":null},{"name":"post_run","value":"# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。\ndef bigquant_run(outputs):\n return outputs\n","type":"Literal","bound_global_parameter":null},{"name":"input_ports","value":"","type":"Literal","bound_global_parameter":null},{"name":"params","value":"{}","type":"Literal","bound_global_parameter":null},{"name":"output_ports","value":"","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"input_1","node_id":"-632"},{"name":"input_2","node_id":"-632"},{"name":"input_3","node_id":"-632"}],"output_ports":[{"name":"data_1","node_id":"-632"},{"name":"data_2","node_id":"-632"},{"name":"data_3","node_id":"-632"}],"cacheable":true,"seq_num":4,"comment":"计算振幅、振幅的2日波动率","comment_collapsed":false},{"node_id":"-40","module_id":"BigQuantSpace.dropnan.dropnan-v2","parameters":[],"input_ports":[{"name":"input_data","node_id":"-40"},{"name":"features","node_id":"-40"}],"output_ports":[{"name":"data","node_id":"-40"}],"cacheable":true,"seq_num":6,"comment":"","comment_collapsed":true},{"node_id":"-47","module_id":"BigQuantSpace.cached.cached-v3","parameters":[{"name":"run","value":"# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端\nimport datetime\ndef bigquant_run(input_1, input_2, input_3):\n df = input_1.read_df()\n for name, group in df.groupby('date'): \n group['rank_swing_volatility_2'] = group['swing_volatility_2'].rank()\n group = group.sort_values('swing_volatility_2') \n if datetime.datetime.strftime(name, '%Y-%m-%d') == '2017-10-27':\n group_all = group\n else:\n group_all = pd.concat([group_all, group])\n #group_all = group_all.rename({'instrument_full': 'instrument'}, axis = 1)\n group_all = group_all.reset_index(drop = True)\n return Outputs(data_1=DataSource.write_df(group_all),data_2=None,data_3=None)\n","type":"Literal","bound_global_parameter":null},{"name":"post_run","value":"# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。\ndef bigquant_run(outputs):\n return outputs\n","type":"Literal","bound_global_parameter":null},{"name":"input_ports","value":"","type":"Literal","bound_global_parameter":null},{"name":"params","value":"{}","type":"Literal","bound_global_parameter":null},{"name":"output_ports","value":"","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"input_1","node_id":"-47"},{"name":"input_2","node_id":"-47"},{"name":"input_3","node_id":"-47"}],"output_ports":[{"name":"data_1","node_id":"-47"},{"name":"data_2","node_id":"-47"},{"name":"data_3","node_id":"-47"}],"cacheable":true,"seq_num":7,"comment":"计算振幅的2日波动率的排名","comment_collapsed":false},{"node_id":"-199","module_id":"BigQuantSpace.cached.cached-v3","parameters":[{"name":"run","value":"# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端\ndef bigquant_run(input_1, input_2, input_3, start_date, end_date, market):\n # 示例代码如下。在这里编写您的代码\n df = input_1.read_df()\n instrument = df['instrument']\n instrument = instrument.drop_duplicates()\n list_1 = instrument.to_list()\n \n dict_1 = {'instruments': list_1, 'start_date': start_date, 'end_date': end_date, 'market': market}\n data_1 = DataSource.write_pickle(dict_1)\n return Outputs(data_1=data_1, data_2=None, data_3=None)\n","type":"Literal","bound_global_parameter":null},{"name":"post_run","value":"# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。\ndef bigquant_run(outputs):\n return outputs\n","type":"Literal","bound_global_parameter":null},{"name":"input_ports","value":"","type":"Literal","bound_global_parameter":null},{"name":"params","value":"{'start_date':'2017-10-27', 'end_date':'2021-07-18', 'market':'DCC'}","type":"Literal","bound_global_parameter":null},{"name":"output_ports","value":"data_1","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"input_1","node_id":"-199"},{"name":"input_2","node_id":"-199"},{"name":"input_3","node_id":"-199"}],"output_ports":[{"name":"data_1","node_id":"-199"},{"name":"data_2","node_id":"-199"},{"name":"data_3","node_id":"-199"}],"cacheable":true,"seq_num":8,"comment":"将insturment转为列表","comment_collapsed":false},{"node_id":"-1128","module_id":"BigQuantSpace.cached.cached-v3","parameters":[{"name":"run","value":"# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端\ndef bigquant_run(input_1, input_2, input_3):\n # 示例代码如下。在这里编写您的代码\n #df = pd.DataFrame({'data': [1, 2, 3]})\n #data_1 = DataSource.write_df(df)\n from datetime import time\n df = input_1.read()\n # 直接根据回测数据的DataFrame的date来生成交易日历对象\n trading_date =df['date'] # 交易日历的日期\n trading_date = trading_date.drop_duplicates()\n trading_date = trading_date.reset_index(drop = True)\n trading_sections = [(time(00,00), time(00,00))]#23,59 # 交易日历的开、收盘时间\n # 生成交易日历\n trading_calendar = get_extend_calendar_with_tradingdays('CryptoCurrencyCalendar', tradingdays=trading_date, trading_sections=trading_sections)\n data_1 = DataSource.write_pickle(trading_calendar)\n return Outputs(data_1=data_1)\n","type":"Literal","bound_global_parameter":null},{"name":"post_run","value":"# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。\ndef bigquant_run(outputs):\n return outputs\n","type":"Literal","bound_global_parameter":null},{"name":"input_ports","value":"","type":"Literal","bound_global_parameter":null},{"name":"params","value":"{}","type":"Literal","bound_global_parameter":null},{"name":"output_ports","value":"","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"input_1","node_id":"-1128"},{"name":"input_2","node_id":"-1128"},{"name":"input_3","node_id":"-1128"}],"output_ports":[{"name":"data_1","node_id":"-1128"},{"name":"data_2","node_id":"-1128"},{"name":"data_3","node_id":"-1128"}],"cacheable":true,"seq_num":3,"comment":"定义数字货币交易日历","comment_collapsed":false},{"node_id":"-81","module_id":"BigQuantSpace.input_csv.input_csv-v5","parameters":[{"name":"file","value":"instruments1.csv","type":"Literal","bound_global_parameter":null},{"name":"coding","value":"GBK","type":"Literal","bound_global_parameter":null},{"name":"dtypes","value":"{}","type":"Literal","bound_global_parameter":null},{"name":"date_type","value":"False","type":"Literal","bound_global_parameter":null},{"name":"date_cols","value":"False","type":"Literal","bound_global_parameter":null}],"input_ports":[],"output_ports":[{"name":"data","node_id":"-81"}],"cacheable":false,"seq_num":5,"comment":"","comment_collapsed":true},{"node_id":"-93","module_id":"BigQuantSpace.cached.cached-v3","parameters":[{"name":"run","value":"# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端\ndef bigquant_run(input_1, input_2, input_3):\n # 示例代码如下。在这里编写您的代码\n global df2\n df1 = input_1.read_df()\n df2 = input_2.read_df()\n def transform_instrument(instrument_full):\n print('instrument_full: ', instrument_full)\n for index, row in df2.iterrows():\n #print('row[instrument_full]: ', row['instrument_full'])\n if instrument_full == row['instrument_full']:\n result = row['instrument_simple']\n #print('result: ', result)\n break\n return result\n df1['instrument'] = df1['symbol'].apply(lambda x: transform_instrument(x))\n data_1 = DataSource.write_df(df1)\n #data_2 = DataSource.write_pickle(df)\n return Outputs(data_1=data_1, data_2=None, data_3=None)\n","type":"Literal","bound_global_parameter":null},{"name":"post_run","value":"# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。\ndef bigquant_run(outputs):\n return outputs\n","type":"Literal","bound_global_parameter":null},{"name":"input_ports","value":"","type":"Literal","bound_global_parameter":null},{"name":"params","value":"{}","type":"Literal","bound_global_parameter":null},{"name":"output_ports","value":"","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"input_1","node_id":"-93"},{"name":"input_2","node_id":"-93"},{"name":"input_3","node_id":"-93"}],"output_ports":[{"name":"data_1","node_id":"-93"},{"name":"data_2","node_id":"-93"},{"name":"data_3","node_id":"-93"}],"cacheable":true,"seq_num":9,"comment":"转换数字货币代码为数字代码","comment_collapsed":false},{"node_id":"-100","module_id":"BigQuantSpace.df_to_csv.df_to_csv-v2","parameters":[{"name":"name","value":"instrument2.csv","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"input_1","node_id":"-100"}],"output_ports":[],"cacheable":true,"seq_num":10,"comment":"","comment_collapsed":true},{"node_id":"-103","module_id":"BigQuantSpace.input_csv.input_csv-v5","parameters":[{"name":"file","value":"instrument2.csv","type":"Literal","bound_global_parameter":null},{"name":"coding","value":"GBK","type":"Literal","bound_global_parameter":null},{"name":"dtypes","value":"{}","type":"Literal","bound_global_parameter":null},{"name":"date_type","value":"%Y-%m-%d","type":"Literal","bound_global_parameter":null},{"name":"date_cols","value":"['datetime']","type":"Literal","bound_global_parameter":null}],"input_ports":[],"output_ports":[{"name":"data","node_id":"-103"}],"cacheable":true,"seq_num":11,"comment":"","comment_collapsed":true}],"node_layout":"<node_postions><node_position Node='-43' Position='197,571,200,200'/><node_position Node='-578' Position='256.79559326171875,-132.41354322433472,200,200'/><node_position Node='-632' Position='220.07101440429688,177.87129974365234,200,200'/><node_position Node='-40' Position='197.39541625976562,273.87129974365234,200,200'/><node_position Node='-47' Position='263.91552734375,352.44905853271484,200,200'/><node_position Node='-199' Position='20,469,200,200'/><node_position Node='-1128' Position='466.45782470703125,460.457763671875,200,200'/><node_position Node='-81' Position='591.3733520507812,-131.18299865722656,200,200'/><node_position Node='-93' Position='436.39141845703125,-57.485239028930664,200,200'/><node_position Node='-100' Position='365.3261413574219,33.71915054321289,200,200'/><node_position Node='-103' Position='152.4041290283203,102.32907915115356,200,200'/></node_postions>"},"nodes_readonly":false,"studio_version":"v2"}
    In [2]:
    # 本代码由可视化策略环境自动生成 2021年8月9日 19:41
    # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
    
    
    # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
    def m9_run_bigquant_run(input_1, input_2, input_3):
        # 示例代码如下。在这里编写您的代码
        global df2
        df1 = input_1.read_df()
        df2 = input_2.read_df()
        def transform_instrument(instrument_full):
            print('instrument_full: ', instrument_full)
            for index, row in df2.iterrows():
                #print('row[instrument_full]: ', row['instrument_full'])
                if instrument_full == row['instrument_full']:
                    result = row['instrument_simple']
                    #print('result: ', result)
                    break
            return result
        df1['instrument'] = df1['symbol'].apply(lambda x: transform_instrument(x))
        data_1 = DataSource.write_df(df1)
        #data_2 = DataSource.write_pickle(df)
        return Outputs(data_1=data_1, data_2=None, data_3=None)
    
    # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    def m9_post_run_bigquant_run(outputs):
        return outputs
    
    # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
    import datetime
    def m4_run_bigquant_run(input_1, input_2, input_3):
        df = input_1.read_df()
        df.rename(columns={'datetime': 'date'}, inplace = True)
        df = df.sort_values(by = ['instrument', 'date'],ascending=True)
        df['high_low_diff'] = df['high'] - df['low']
        df['swing'] = df['high_low_diff'] / df['open']
        for name, group in df.groupby('instrument'):
            group['swing_volatility_2'] = group['swing'].rolling(2).std()
            if name == '1.HBI':
                group_all = group
            else:
                group_all = pd.concat([group_all, group])
        group_all = group_all.sort_values(by = ['date', 'instrument'], ascending=True)
        
        return Outputs(data_1=DataSource.write_df(group_all),data_2=None,data_3=None)
    
    # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    def m4_post_run_bigquant_run(outputs):
        return outputs
    
    # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
    import datetime
    def m7_run_bigquant_run(input_1, input_2, input_3):
        df = input_1.read_df()
        for name, group in df.groupby('date'): 
            group['rank_swing_volatility_2'] = group['swing_volatility_2'].rank()
            group = group.sort_values('swing_volatility_2')    
            if datetime.datetime.strftime(name, '%Y-%m-%d') == '2017-10-27':
                group_all = group
            else:
                group_all = pd.concat([group_all, group])
        #group_all = group_all.rename({'instrument_full': 'instrument'}, axis = 1)
        group_all = group_all.reset_index(drop = True)
        return Outputs(data_1=DataSource.write_df(group_all),data_2=None,data_3=None)
    
    # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    def m7_post_run_bigquant_run(outputs):
        return outputs
    
    # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
    def m8_run_bigquant_run(input_1, input_2, input_3, start_date, end_date, market):
        # 示例代码如下。在这里编写您的代码
        df = input_1.read_df()
        instrument = df['instrument']
        instrument = instrument.drop_duplicates()
        list_1 = instrument.to_list()
        
        dict_1 = {'instruments': list_1, 'start_date': start_date, 'end_date': end_date, 'market': market}
        data_1 = DataSource.write_pickle(dict_1)
        return Outputs(data_1=data_1, data_2=None, data_3=None)
    
    # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    def m8_post_run_bigquant_run(outputs):
        return outputs
    
    # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
    def m3_run_bigquant_run(input_1, input_2, input_3):
        # 示例代码如下。在这里编写您的代码
        #df = pd.DataFrame({'data': [1, 2, 3]})
        #data_1 = DataSource.write_df(df)
        from datetime import time
        df = input_1.read()
        # 直接根据回测数据的DataFrame的date来生成交易日历对象
        trading_date =df['date']  # 交易日历的日期
        trading_date = trading_date.drop_duplicates()
        trading_date = trading_date.reset_index(drop = True)
        trading_sections = [(time(00,00), time(00,00))]#23,59  # 交易日历的开、收盘时间
        # 生成交易日历
        trading_calendar = get_extend_calendar_with_tradingdays('CryptoCurrencyCalendar', tradingdays=trading_date, trading_sections=trading_sections)
        data_1 = DataSource.write_pickle(trading_calendar)
        return Outputs(data_1=data_1)
    
    # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    def m3_post_run_bigquant_run(outputs):
        return outputs
    
    # 回测引擎:初始化函数,只执行一次
    def m2_initialize_bigquant_run(context):
        
        # 加载股票指标数据,数据继承自m4模块
        context.indicator_data = context.options['data'].read_df().set_index('date')
        print('indicator_data:', context.indicator_data.head()) 
        # 设置交易费用,买入是万三,卖出是千分之1.3,如果不足5元按5元算
        context.set_commission(PerOrder(buy_cost=0.002, sell_cost=0.002, min_cost=5))
         # 设置股票数量
        context.stock_num = 1
        
        # 调仓天数,1个交易日换仓一次
        context.rebalance_days = 1
        
        # 如果策略运行中,需要将数据进行保存,可以借用extension这个对象,类型为dict
        # 比如当前运行的k线的索引,比如个股持仓天数、买入均价
        if 'index' not in context.extension:
            context.extension['index'] = 0
            
    
    # 回测引擎:每日数据处理函数,每天执行一次
    def m2_handle_data_bigquant_run(context, data):
        
        # 按每个K线递增
        context.extension['index']  += 1
        
        # 每隔1个交易日进行换仓
        if context.extension['index'] % context.rebalance_days != 0:
            return 
            
        # 日期
        date = data.current_dt.strftime('%Y-%m-%d')
        
        print('debug:', date)
        # 买入股票列表
        
        stock_to_buy = context.indicator_data.loc[date]['instrument'][- context.stock_num:]
        print('stock_to_buy:', stock_to_buy)
            
        # 目前持仓列表    
        stock_hold_now = [equity.symbol for equity in context.portfolio.positions]
        print('stock_hold_now:', stock_hold_now)
        
        # 继续持有股票列表
        no_need_to_sell = [i for i in stock_hold_now  if i in stock_to_buy]
        print('no_need_to_sell:', no_need_to_sell)
    
        # 卖出股票列表 
        stock_to_sell = [i for i in stock_hold_now if i not in no_need_to_sell]
        print('stock_to_sell:', stock_to_sell)
    
        # 执行卖出
        for stock in stock_to_sell:
            if data.can_trade(context.symbol(stock)):
                context.order_target_percent(context.symbol(stock), 0)
                
        # 如果当天没有买入就返回
        if len(stock_to_buy) == 0:
            return
        
        # 等权重
        weight = 1 / len(stock_to_buy)
        # 执行买入
        for  cp in stock_to_buy:
            if data.can_trade(context.symbol(cp)):
                context.order_target_percent(context.symbol(cp), weight)
    # 回测引擎:准备数据,只执行一次
    def m2_prepare_bigquant_run(context):
        pass
    
    # 回测引擎:每个单位时间开始前调用一次,即每日开盘前调用一次。
    def m2_before_trading_start_bigquant_run(context, data):
        pass
    
    
    m1 = M.input_csv.v5(
        file='price_symbol_full.csv',
        coding='GBK',
        dtypes={},
        date_type='%Y-%m-%d %H:%M:%S',
        date_cols=['datetime']
    )
    
    m5 = M.input_csv.v5(
        file='instruments1.csv',
        coding='GBK',
        dtypes={},
        date_type='False',
        date_cols=False,
        m_cached=False
    )
    
    m9 = M.cached.v3(
        input_1=m1.data,
        input_2=m5.data,
        run=m9_run_bigquant_run,
        post_run=m9_post_run_bigquant_run,
        input_ports='',
        params='{}',
        output_ports=''
    )
    
    m10 = M.df_to_csv.v2(
        input_1=m9.data_1,
        name='instrument2.csv'
    )
    
    m11 = M.input_csv.v5(
        file='instrument2.csv',
        coding='GBK',
        dtypes={},
        date_type='%Y-%m-%d',
        date_cols=['datetime']
    )
    
    m4 = M.cached.v3(
        input_1=m11.data,
        run=m4_run_bigquant_run,
        post_run=m4_post_run_bigquant_run,
        input_ports='',
        params='{}',
        output_ports=''
    )
    
    m6 = M.dropnan.v2(
        input_data=m4.data_1
    )
    
    m7 = M.cached.v3(
        input_1=m6.data,
        run=m7_run_bigquant_run,
        post_run=m7_post_run_bigquant_run,
        input_ports='',
        params='{}',
        output_ports=''
    )
    
    m8 = M.cached.v3(
        input_1=m7.data_1,
        run=m8_run_bigquant_run,
        post_run=m8_post_run_bigquant_run,
        input_ports='',
        params='{\'start_date\':\'2017-10-27\', \'end_date\':\'2021-07-18\', \'market\':\'DCC\'}',
        output_ports='data_1'
    )
    
    m3 = M.cached.v3(
        input_1=m7.data_1,
        run=m3_run_bigquant_run,
        post_run=m3_post_run_bigquant_run,
        input_ports='',
        params='{}',
        output_ports=''
    )
    
    m2 = M.trade.v4(
        instruments=m8.data_1,
        options_data=m7.data_1,
        history_ds=m7.data_1,
        benchmark_ds=m7.data_1,
        trading_calendar=m3.data_1,
        start_date='',
        end_date='',
        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.025,
        order_price_field_buy='open',
        order_price_field_sell='close',
        capital_base=1000000,
        auto_cancel_non_tradable_orders=True,
        data_frequency='daily',
        price_type='后复权',
        product_type='期货',
        plot_charts=True,
        backtest_only=False,
        benchmark='btcusdt'
    )
    
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    ValueError: month must be in 1..12
    
    The above exception was the direct cause of the following exception:
    
    ParserError                               Traceback (most recent call last)
    ParserError: month must be in 1..12: 2021-62-15
    
    During handling of the above exception, another exception occurred:
    
    ValueError                                Traceback (most recent call last)
    <ipython-input-2-8d46e512a221> in <module>
        204 )
        205 
    --> 206 m2 = M.trade.v4(
        207     instruments=m8.data_1,
        208     options_data=m7.data_1,
    
    ValueError: could not convert string to Timestamp
    In [21]:
    m11.data.read_df().head()
    
    Out[21]:
    Unnamed: 0 symbol exchange datetime open high low close volume open_interest instrument
    0 0 1inchusdt HUOBI 2020-12-25 0.100000 2.950000 0.100000 1.881843 6.150297e+07 0.0 185.HBI
    1 1 1inchusdt HUOBI 2020-12-26 1.881848 2.500000 1.571439 1.642000 2.843130e+07 0.0 185.HBI
    2 2 1inchusdt HUOBI 2020-12-27 1.642000 1.795363 1.165110 1.358303 1.917566e+07 0.0 185.HBI
    3 3 1inchusdt HUOBI 2020-12-28 1.358303 1.461002 1.040542 1.170001 1.228542e+07 0.0 185.HBI
    4 4 1inchusdt HUOBI 2020-12-29 1.170000 1.170001 0.771123 0.799691 1.165732e+07 0.0 185.HBI
    In [31]:
    df = m7.data_1.read_df()
    trading_date =df['date']  # 交易日历的日期
    trading_date = trading_date.drop_duplicates()
    trading_date = trading_date.reset_index(drop = True)
    trading_date
    
    Out[31]:
    0      2017-10-27
    1      2017-10-28
    2      2017-10-29
    3      2017-10-30
    4      2017-10-31
              ...    
    1356   2021-07-14
    1357   2021-07-15
    1358   2021-07-16
    1359   2021-07-17
    1360   2021-07-18
    Name: date, Length: 1361, dtype: datetime64[ns]
    In [5]:
    trading_date = m7.data_1.read_df()['date']
    trading_date = trading_date.drop_duplicates()
    trading_date = trading_date.reset_index(drop = True)
    trading_date = trading_date.set_index('date')
    trading_date['2021-07']
    
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-5-e5ee519dea0b> in <module>
          2 trading_date = trading_date.drop_duplicates()
          3 trading_date = trading_date.reset_index(drop = True)
    ----> 4 trading_date = trading_date.set_index('date')
          5 trading_date['2021-07']
    
    AttributeError: 'Series' object has no attribute 'set_index'
    In [26]:
    m8.data_1.read_pickle()
    
    Out[26]:
    {'instruments': ['1.HBI',
      '2.HBI',
      '3.HBI',
      '4.HBI',
      '5.HBI',
      '6.HBI',
      '7.HBI',
      '8.HBI',
      '9.HBI',
      '10.HBI',
      '11.HBI',
      '12.HBI',
      '13.HBI',
      '14.HBI',
      '15.HBI',
      '16.HBI',
      '17.HBI',
      '18.HBI',
      '19.HBI',
      '20.HBI',
      '21.HBI',
      '22.HBI',
      '23.HBI',
      '24.HBI',
      '25.HBI',
      '26.HBI',
      '27.HBI',
      '28.HBI',
      '29.HBI',
      '30.HBI',
      '31.HBI',
      '32.HBI',
      '33.HBI',
      '34.HBI',
      '35.HBI',
      '36.HBI',
      '37.HBI',
      '38.HBI',
      '39.HBI',
      '40.HBI',
      '41.HBI',
      '42.HBI',
      '43.HBI',
      '44.HBI',
      '45.HBI',
      '46.HBI',
      '47.HBI',
      '48.HBI',
      '49.HBI',
      '50.HBI',
      '51.HBI',
      '52.HBI',
      '53.HBI',
      '54.HBI',
      '55.HBI',
      '56.HBI',
      '57.HBI',
      '58.HBI',
      '59.HBI',
      '60.HBI',
      '61.HBI',
      '62.HBI',
      '63.HBI',
      '64.HBI',
      '65.HBI',
      '66.HBI',
      '67.HBI',
      '68.HBI',
      '69.HBI',
      '70.HBI',
      '71.HBI',
      '72.HBI',
      '73.HBI',
      '74.HBI',
      '75.HBI',
      '76.HBI',
      '77.HBI',
      '78.HBI',
      '79.HBI',
      '80.HBI',
      '81.HBI',
      '82.HBI',
      '83.HBI',
      '84.HBI',
      '85.HBI',
      '86.HBI',
      '87.HBI',
      '88.HBI',
      '89.HBI',
      '90.HBI',
      '91.HBI',
      '92.HBI',
      '93.HBI',
      '94.HBI',
      '95.HBI',
      '96.HBI',
      '97.HBI',
      '98.HBI',
      '99.HBI',
      '100.HBI',
      '101.HBI',
      '102.HBI',
      '103.HBI',
      '104.HBI',
      '105.HBI',
      '106.HBI',
      '107.HBI',
      '108.HBI',
      '109.HBI',
      '110.HBI',
      '111.HBI',
      '112.HBI',
      '113.HBI',
      '114.HBI',
      '115.HBI',
      '116.HBI',
      '117.HBI',
      '118.HBI',
      '119.HBI',
      '120.HBI',
      '121.HBI',
      '122.HBI',
      '123.HBI',
      '124.HBI',
      '125.HBI',
      '126.HBI',
      '127.HBI',
      '128.HBI',
      '129.HBI',
      '130.HBI',
      '131.HBI',
      '132.HBI',
      '133.HBI',
      '134.HBI',
      '135.HBI',
      '136.HBI',
      '137.HBI',
      '138.HBI',
      '139.HBI',
      '140.HBI',
      '141.HBI',
      '142.HBI',
      '143.HBI',
      '144.HBI',
      '145.HBI',
      '146.HBI',
      '147.HBI',
      '148.HBI',
      '149.HBI',
      '150.HBI',
      '151.HBI',
      '152.HBI',
      '153.HBI',
      '154.HBI',
      '155.HBI',
      '156.HBI',
      '157.HBI',
      '158.HBI',
      '159.HBI',
      '160.HBI',
      '161.HBI',
      '162.HBI',
      '163.HBI',
      '164.HBI',
      '165.HBI',
      '166.HBI',
      '167.HBI',
      '168.HBI',
      '169.HBI',
      '170.HBI',
      '171.HBI',
      '172.HBI',
      '173.HBI',
      '174.HBI',
      '175.HBI',
      '176.HBI',
      '177.HBI',
      '178.HBI',
      '179.HBI',
      '180.HBI',
      '181.HBI',
      '182.HBI',
      '183.HBI',
      '184.HBI',
      '185.HBI',
      '186.HBI',
      '187.HBI',
      '188.HBI',
      '189.HBI',
      '190.HBI',
      '191.HBI',
      '192.HBI',
      '193.HBI',
      '194.HBI',
      '195.HBI',
      '196.HBI',
      '197.HBI',
      '198.HBI',
      '199.HBI',
      '200.HBI',
      '201.HBI',
      '202.HBI',
      '203.HBI',
      '204.HBI',
      '205.HBI',
      '206.HBI',
      '207.HBI',
      '208.HBI',
      '209.HBI',
      '210.HBI',
      '211.HBI',
      '212.HBI',
      '213.HBI',
      '214.HBI',
      '215.HBI',
      '216.HBI',
      '217.HBI',
      '218.HBI',
      '219.HBI',
      '220.HBI',
      '221.HBI',
      '222.HBI',
      '223.HBI',
      '224.HBI',
      '225.HBI',
      '226.HBI',
      '227.HBI',
      '228.HBI'],
     'start_date': '2017-10-27',
     'end_date': '2021-07-18',
     'market': 'DCC'}
    In [19]:
    df = m7.data_1.read_df()
    df = df.set_index('date')
    df['2021-07-1'].tail(30)
    
    ---------------------------------------------------------------------------
    KeyError                                  Traceback (most recent call last)
    KeyError: '2021-07-1'
    
    The above exception was the direct cause of the following exception:
    
    KeyError                                  Traceback (most recent call last)
    <ipython-input-19-08efd9dcd821> in <module>
          1 df = m7.data_1.read_df()
          2 df = df.set_index('date')
    ----> 3 df['2021-07-1'].tail(30)
    
    KeyError: '2021-07-1'