复制链接
克隆策略

    {"description":"实验创建于2017/8/26","graph":{"edges":[{"to_node_id":"-17899:input_1","from_node_id":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"to_node_id":"-549:instruments","from_node_id":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"to_node_id":"-32248:input_1","from_node_id":"-896:data"},{"to_node_id":"-32248:input_2","from_node_id":"-741:data"},{"to_node_id":"-107:input_1","from_node_id":"-32248:data_1"},{"to_node_id":"-896:instruments","from_node_id":"-17899:data_1"},{"to_node_id":"-741:instruments","from_node_id":"-17899:data_1"},{"to_node_id":"-549:options_data","from_node_id":"-107:data_1"}],"nodes":[{"node_id":"287d2cb0-f53c-4101-bdf8-104b137c8601-8","module_id":"BigQuantSpace.instruments.instruments-v2","parameters":[{"name":"start_date","value":"2017-06-01","type":"Literal","bound_global_parameter":null},{"name":"end_date","value":"2022-06-30","type":"Literal","bound_global_parameter":null},{"name":"market","value":"CN_FUTURE","type":"Literal","bound_global_parameter":null},{"name":"instrument_list","value":"","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-8"}],"output_ports":[{"name":"data","node_id":"287d2cb0-f53c-4101-bdf8-104b137c8601-8"}],"cacheable":true,"seq_num":1,"comment":"","comment_collapsed":true},{"node_id":"-896","module_id":"BigQuantSpace.use_datasource.use_datasource-v2","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},{"name":"before_start_days","value":"0","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"instruments","node_id":"-896"},{"name":"features","node_id":"-896"}],"output_ports":[{"name":"data","node_id":"-896"}],"cacheable":true,"seq_num":2,"comment":"","comment_collapsed":true},{"node_id":"-741","module_id":"BigQuantSpace.use_datasource.use_datasource-v2","parameters":[{"name":"datasource_id","value":"basic_info_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},{"name":"before_start_days","value":"0","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"instruments","node_id":"-741"},{"name":"features","node_id":"-741"}],"output_ports":[{"name":"data","node_id":"-741"}],"cacheable":true,"seq_num":33,"comment":"","comment_collapsed":true},{"node_id":"-32248","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,min_volume):\n from functools import reduce\n \n df_raw = input_1.read()\n df_basic = input_2.read()[['product_code','instrument','delist_date']]\n df = df_raw[~(df_raw['instrument'].str.contains('0000|8888|9999|IC|IF|IH|T|TF|TS'))]\n df_index = df_raw[df_raw['instrument'].str.contains('0000')]\n df_dom = df_raw[df_raw['instrument'].str.contains('9999')]\n \n df = pd.merge(df,df_basic,how='left',on=['product_code','instrument'])\n df['maturity_days'] = (df['delist_date'] - df['date']).apply(lambda x:x.days)\n# 去掉了所有的农产品\n universe_codes = ['AG','AU','ZN','WR','BC','PB','NI','SS','SN','AL','CU','JM','RB','ZC','I','SF','J','SM','HC','BB','FU','EG','ME','PP','L','NR','PG','TA','SC','SA','','V','FG','RN','BU','PF','UR','EB','LU','MA']\n df = df[(df['product_code'].isin(universe_codes))]\n \n #去掉成交量少的品种\n def kill_min_volume_product(x):\n df_tp = x.groupby('product_code').sum()\n return df_tp[df_tp['volume'] >= min_volume]\n \n df_universe = df[['date','product_code','volume']].groupby('date').apply(kill_min_volume_product)\n df_universe.reset_index(inplace=True)\n df_universe = df_universe[['date','product_code']]\n \n #因子加工函数\n \n #计算期限结构因子\n def calc_ts(x):\n df_tp = x.sort_values(\"maturity_days\")\n if df_tp.shape[0] > 1:\n df_tp['ts'] = (df_tp['close'] - df_tp['close'].iloc[0])/df_tp['close'] * 365/(df_tp['maturity_days'] - df_tp['maturity_days'].iloc[0])\n df_tp['ts_skew'] = df_tp['ts'].skew()\n df_tp['ts_mean'] = df_tp['ts'].mean()\n return df_tp[['ts_mean','ts_skew']].iloc[1]\n \n #计算偏度因子\n def calc_skew(x,N):\n factor_name = 'skew_' + str(N)\n x.sort_values(\"date\",inplace=True)\n x['returns'] = x['close'].pct_change()\n x[factor_name] = x['returns'].rolling(N).skew()\n x.set_index('date',inplace=True)\n del x['product_code']\n return x\n \n \n df_result_ts = df.groupby([\"date\",\"product_code\"]).apply(calc_ts)\n df_result_ts.reset_index(inplace=True)\n\n df_result_skew = pd.DataFrame(df_index.groupby(\"product_code\").apply(calc_skew,90))\n df_result_skew = df_result_skew.reset_index()[['date','product_code','skew_90']]\n #因子合并\n df_factor_list = [df_result_ts,df_result_skew] \n df_result = reduce(lambda left,right:pd.merge(left,right,how='left',on=['date','product_code']),df_factor_list)\n \n #和样本空间\n df_result = pd.merge(df_universe,df_result,how='left',on=['date','product_code'])\n \n df_output = pd.merge(df_result[['date','product_code','ts_skew','ts_mean','skew_90']],df_index[['date','product_code','instrument']],how='left',on=['date','product_code'])\n del df_output['product_code']\n df_output['date'] = pd.to_datetime(df_output['date'])\n df_output.sort_values(\"date\",inplace=True)\n data_1 = DataSource.write_df(df_output)\n return Outputs(data_1=data_1)\n\n\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":"{\n 'min_volume': 100000\n}","type":"Literal","bound_global_parameter":null},{"name":"output_ports","value":"","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"input_1","node_id":"-32248"},{"name":"input_2","node_id":"-32248"},{"name":"input_3","node_id":"-32248"}],"output_ports":[{"name":"data_1","node_id":"-32248"},{"name":"data_2","node_id":"-32248"},{"name":"data_3","node_id":"-32248"}],"cacheable":true,"seq_num":27,"comment":"","comment_collapsed":true},{"node_id":"-17899","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 from datetime import datetime,timedelta\n df_data = input_1.read()\n df_data['start_date'] = (datetime.strptime(df_data['start_date'],'%Y-%m-%d') - timedelta(days=150)).strftime('%Y-%m-%d')\n return Outputs(data_1=df_data)\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":"-17899"},{"name":"input_2","node_id":"-17899"},{"name":"input_3","node_id":"-17899"}],"output_ports":[{"name":"data_1","node_id":"-17899"},{"name":"data_2","node_id":"-17899"},{"name":"data_3","node_id":"-17899"}],"cacheable":true,"seq_num":8,"comment":"","comment_collapsed":true},{"node_id":"-107","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 # 期限结构因子\n df = input_1.read()[['date','instrument','skew_90','ts_skew','ts_mean']]\n df = df[df['ts_skew'] < 0]\n df = df[['date','instrument','skew_90']]\n #signal \n def calc_signal(x,factor_name):\n x = x.sort_values(factor_name)\n length = x.shape[0]\n if length >= 3 :\n x['signal_'+factor_name] = [1]*3 + [0 for i in range(length-3)]\n else :\n x['signal_' + factor_name] = [0] * length\n return x\n \n factor_names = [i for i in df.columns if i not in ['date','instrument']]\n df_result = df\n for factor_ in factor_names:\n df_result = df_result.groupby(\"date\").apply(calc_signal,factor_)\n df_result.reset_index(drop=True,inplace=True)\n #产生信号\n df_result = df_result[['date','instrument','signal_skew_90']] \n df_result['signal'] = df_result.iloc[:,2:].apply(lambda x:x.sum(),axis=1)\n df_result = df_result[~(df_result['signal'] == 0)]\n \n data_1 = DataSource.write_pickle(df_result[['date','instrument','signal']])\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":"-107"},{"name":"input_2","node_id":"-107"},{"name":"input_3","node_id":"-107"}],"output_ports":[{"name":"data_1","node_id":"-107"},{"name":"data_2","node_id":"-107"},{"name":"data_3","node_id":"-107"}],"cacheable":true,"seq_num":3,"comment":"产生信号","comment_collapsed":true},{"node_id":"-549","module_id":"BigQuantSpace.hftrade.hftrade-v2","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 context.strategy_leverage = 3\n outer_data = context.options['data'].read()\n context.stock_to_long = outer_data[(outer_data['signal'] > 0)]\n context.stock_to_short = outer_data[(outer_data['signal'] < 0)]\n context.freq = 5\n \n\n ","type":"Literal","bound_global_parameter":null},{"name":"before_trading_start","value":"# 交易引擎:每个单位时间开盘前调用一次。\ndef bigquant_run(context, data):\n # 盘前处理,订阅行情等\n context.position_check = context.get_positions()\n","type":"Literal","bound_global_parameter":null},{"name":"handle_tick","value":"# 交易引擎:tick数据处理函数,每个tick执行一次\ndef bigquant_run(context, tick):\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"handle_data","value":"# 回测引擎:每日数据处理函数,每天执行一次\ndef bigquant_run(context, data):\n date = data.current_dt.strftime('%Y-%m-%d')\n import string \n current_stoploss_long = []\n current_stoploss_short = []\n \n if len(context.position_check) > 0:\n positions_cost_long = {e:p.long.cost_price for e,p in context.get_positions().items()}\n avail_positions_long = {e: p.long.avail_qty for e, p in context.get_positions().items()}\n #------------------------START:止赢止损模块(含建仓期)---------------\n stopline = -0.05\n for instrument in positions_cost_long.keys():\n stock_cost=positions_cost_long[instrument]\n if stock_cost != 0:\n stock_market_price=data.current(context.symbol(instrument),'price')\n if stock_market_price/stock_cost-1 <= stopline and avail_positions_long[instrument] != 0:\n context.order_target(instrument, 0, order_type=OrderType.MARKET)\n print('止损成功, 止损标的{}'.format(instrument))\n current_stoploss_long.append(instrument) \n #--------------------------END: 止赢止损模块--------------------------\n if (context.trading_day_index % context.freq == 0) :\n print('date'*5, date)\n stock_to_long = context.stock_to_long[context.stock_to_long['date'] == date]\n stock_to_long = stock_to_long[stock_to_long['signal'] > 0]['instrument']\n\n # 平仓\n hold_symbols = context.get_account_positions()\n long_pos = {}\n short_pos = {}\n\n for i in hold_symbols.keys():\n if hold_symbols[i].long.current_qty > 0:\n long_pos[i] = hold_symbols[i].long.current_qty\n if hold_symbols[i].short.current_qty> 0:\n short_pos[i] = hold_symbols[i].short.current_qty\n \n for stock in long_pos.keys():\n if stock not in current_stoploss_long:\n pos = long_pos[stock]\n price = data.current(context.symbol(stock), \"close\")\n context.sell_close(context.symbol(stock), pos, price, order_type=OrderType.MARKET)\n \n \n # 开仓\n stock_num = len(stock_to_long)\n if stock_num != 0 :\n weight = 1 / stock_num *0.5\n portfolio_value = context.portfolio.portfolio_value\n book_value = portfolio_value * context.strategy_leverage * weight\n\n for i in range(len(stock_to_long)):\n stock_i = stock_to_long.iloc[i]\n code = stock_i.split('.')[0][:-4]\n stock = context.get_dominant(code)\n if data.can_trade(stock):\n price = data.current(stock,\"close\")\n unit =context.get_contract(stock).multiplier\n lots = math.floor(book_value/(unit*price))\n if lots != 0:\n context.buy_open(stock, lots, price, order_type=OrderType.MARKET)\n \n\n \n ","type":"Literal","bound_global_parameter":null},{"name":"handle_trade","value":"# 交易引擎:成交回报处理函数,每个成交发生时执行一次\ndef bigquant_run(context, trade):\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"handle_order","value":"# 交易引擎:委托回报处理函数,每个委托变化时执行一次\ndef bigquant_run(context, order):\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":"100000000","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":"0","type":"Literal","bound_global_parameter":null},{"name":"volume_limit","value":1,"type":"Literal","bound_global_parameter":null},{"name":"order_price_field_buy","value":"close","type":"Literal","bound_global_parameter":null},{"name":"order_price_field_sell","value":"close","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":"replay_bdb","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":"-549"},{"name":"options_data","node_id":"-549"},{"name":"history_ds","node_id":"-549"},{"name":"benchmark_ds","node_id":"-549"}],"output_ports":[{"name":"raw_perf","node_id":"-549"}],"cacheable":false,"seq_num":4,"comment":"","comment_collapsed":true}],"node_layout":"<node_postions><node_position Node='287d2cb0-f53c-4101-bdf8-104b137c8601-8' Position='1751,-1869,200,200'/><node_position Node='-896' Position='1495,-1643,200,200'/><node_position Node='-741' Position='1846,-1654,200,200'/><node_position Node='-32248' Position='1489.9114990234375,-1565.796630859375,200,200'/><node_position Node='-17899' Position='1748,-1772,200,200'/><node_position Node='-107' Position='1483.88525390625,-1485.1705322265625,200,200'/><node_position Node='-549' Position='1474.026123046875,-1402.888427734375,200,200'/></node_postions>"},"nodes_readonly":false,"studio_version":"v2"}
    In [5]:
    # 本代码由可视化策略环境自动生成 2022年9月2日 18:27
    # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
    
    
    # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
    def m8_run_bigquant_run(input_1, input_2, input_3):
        # 示例代码如下。在这里编写您的代码
        from datetime import datetime,timedelta
        df_data = input_1.read()
        df_data['start_date'] = (datetime.strptime(df_data['start_date'],'%Y-%m-%d') - timedelta(days=150)).strftime('%Y-%m-%d')
        return Outputs(data_1=df_data)
    
    # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    def m8_post_run_bigquant_run(outputs):
        return outputs
    
    # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
    def m27_run_bigquant_run(input_1, input_2, input_3,min_volume):
        from functools import reduce
        
        df_raw = input_1.read()
        df_basic = input_2.read()[['product_code','instrument','delist_date']]
        df = df_raw[~(df_raw['instrument'].str.contains('0000|8888|9999|IC|IF|IH|T|TF|TS'))]
        df_index = df_raw[df_raw['instrument'].str.contains('0000')]
        df_dom = df_raw[df_raw['instrument'].str.contains('9999')]
        
        df = pd.merge(df,df_basic,how='left',on=['product_code','instrument'])
        df['maturity_days'] = (df['delist_date'] - df['date']).apply(lambda x:x.days)
    #     去掉了所有的农产品
        universe_codes = ['AG','AU','ZN','WR','BC','PB','NI','SS','SN','AL','CU','JM','RB','ZC','I','SF','J','SM','HC','BB','FU','EG','ME','PP','L','NR','PG','TA','SC','SA','','V','FG','RN','BU','PF','UR','EB','LU','MA']
        df = df[(df['product_code'].isin(universe_codes))]
        
        #去掉成交量少的品种
        def kill_min_volume_product(x):
            df_tp = x.groupby('product_code').sum()
            return df_tp[df_tp['volume'] >= min_volume]
        
        df_universe = df[['date','product_code','volume']].groupby('date').apply(kill_min_volume_product)
        df_universe.reset_index(inplace=True)
        df_universe = df_universe[['date','product_code']]
        
        #因子加工函数
        
        #计算期限结构因子
        def calc_ts(x):
            df_tp = x.sort_values("maturity_days")
            if df_tp.shape[0] > 1:
                df_tp['ts'] = (df_tp['close'] - df_tp['close'].iloc[0])/df_tp['close'] * 365/(df_tp['maturity_days'] - df_tp['maturity_days'].iloc[0])
                df_tp['ts_skew'] = df_tp['ts'].skew()
                df_tp['ts_mean'] = df_tp['ts'].mean()
                return df_tp[['ts_mean','ts_skew']].iloc[1]
          
        #计算偏度因子
        def calc_skew(x,N):
            factor_name = 'skew_' + str(N)
            x.sort_values("date",inplace=True)
            x['returns'] = x['close'].pct_change()
            x[factor_name] = x['returns'].rolling(N).skew()
            x.set_index('date',inplace=True)
            del x['product_code']
            return x
        
        
        df_result_ts = df.groupby(["date","product_code"]).apply(calc_ts)
        df_result_ts.reset_index(inplace=True)
    
        df_result_skew = pd.DataFrame(df_index.groupby("product_code").apply(calc_skew,90))
        df_result_skew = df_result_skew.reset_index()[['date','product_code','skew_90']]
        #因子合并
        df_factor_list = [df_result_ts,df_result_skew] 
        df_result = reduce(lambda left,right:pd.merge(left,right,how='left',on=['date','product_code']),df_factor_list)
        
        #和样本空间
        df_result = pd.merge(df_universe,df_result,how='left',on=['date','product_code'])
        
        df_output = pd.merge(df_result[['date','product_code','ts_skew','ts_mean','skew_90']],df_index[['date','product_code','instrument']],how='left',on=['date','product_code'])
        del df_output['product_code']
        df_output['date'] = pd.to_datetime(df_output['date'])
        df_output.sort_values("date",inplace=True)
        data_1 = DataSource.write_df(df_output)
        return Outputs(data_1=data_1)
    
    
    
    # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    def m27_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 = input_1.read()[['date','instrument','skew_90','ts_skew','ts_mean']]
        df = df[df['ts_skew'] < 0]
        df = df[['date','instrument','skew_90']]
        #signal 
        def calc_signal(x,factor_name):
            x = x.sort_values(factor_name)
            length = x.shape[0]
            if length >= 3 :
                x['signal_'+factor_name] = [1]*3 + [0 for i in range(length-3)]
            else :
                x['signal_' + factor_name] = [0] * length
            return x
        
        factor_names = [i for i in df.columns if i not in ['date','instrument']]
        df_result = df
        for factor_ in factor_names:
            df_result = df_result.groupby("date").apply(calc_signal,factor_)
            df_result.reset_index(drop=True,inplace=True)
         #产生信号
        df_result =  df_result[['date','instrument','signal_skew_90']]  
        df_result['signal'] = df_result.iloc[:,2:].apply(lambda x:x.sum(),axis=1)
        df_result = df_result[~(df_result['signal'] == 0)]
        
        data_1 = DataSource.write_pickle(df_result[['date','instrument','signal']])
        return Outputs(data_1=data_1)
    
    # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    def m3_post_run_bigquant_run(outputs):
        return outputs
    
    # 回测引擎:初始化函数,只执行一次
    def m4_initialize_bigquant_run(context):
        # 设置最大杠杆
        context.strategy_leverage = 3
        outer_data = context.options['data'].read()
        context.stock_to_long = outer_data[(outer_data['signal'] > 0)]
        context.stock_to_short = outer_data[(outer_data['signal'] < 0)]
        context.freq = 5
        
    
        
    # 交易引擎:每个单位时间开盘前调用一次。
    def m4_before_trading_start_bigquant_run(context, data):
        # 盘前处理,订阅行情等
        context.position_check = context.get_positions()
    
    # 交易引擎:tick数据处理函数,每个tick执行一次
    def m4_handle_tick_bigquant_run(context, tick):
        pass
    
    # 回测引擎:每日数据处理函数,每天执行一次
    def m4_handle_data_bigquant_run(context, data):
        date = data.current_dt.strftime('%Y-%m-%d')
        import string 
        current_stoploss_long = []
        current_stoploss_short = []
        
        if len(context.position_check) > 0:
            positions_cost_long = {e:p.long.cost_price for e,p in context.get_positions().items()}
            avail_positions_long = {e: p.long.avail_qty for e, p in context.get_positions().items()}
            #------------------------START:止赢止损模块(含建仓期)---------------
            stopline = -0.05
            for instrument in positions_cost_long.keys():
                stock_cost=positions_cost_long[instrument]
                if stock_cost != 0:
                    stock_market_price=data.current(context.symbol(instrument),'price')
                    if stock_market_price/stock_cost-1 <= stopline and avail_positions_long[instrument] != 0:
                        context.order_target(instrument, 0, order_type=OrderType.MARKET)
                        print('止损成功, 止损标的{}'.format(instrument))
                        current_stoploss_long.append(instrument)      
            #--------------------------END: 止赢止损模块--------------------------
        if (context.trading_day_index % context.freq == 0) :
            print('date'*5, date)
            stock_to_long = context.stock_to_long[context.stock_to_long['date'] == date]
            stock_to_long = stock_to_long[stock_to_long['signal'] > 0]['instrument']
    
            # 平仓
            hold_symbols = context.get_account_positions()
            long_pos = {}
            short_pos = {}
    
            for i in hold_symbols.keys():
                if  hold_symbols[i].long.current_qty > 0:
                    long_pos[i] = hold_symbols[i].long.current_qty
                if hold_symbols[i].short.current_qty> 0:
                    short_pos[i] = hold_symbols[i].short.current_qty
            
            for stock in long_pos.keys():
                if stock not in current_stoploss_long:
                    pos = long_pos[stock]
                    price = data.current(context.symbol(stock), "close")
                    context.sell_close(context.symbol(stock), pos, price, order_type=OrderType.MARKET)
                
     
            # 开仓
            stock_num = len(stock_to_long)
            if stock_num != 0 :
                weight =  1 / stock_num *0.5
                portfolio_value = context.portfolio.portfolio_value
                book_value = portfolio_value * context.strategy_leverage  * weight
    
                for i in range(len(stock_to_long)):
                    stock_i = stock_to_long.iloc[i]
                    code = stock_i.split('.')[0][:-4]
                    stock = context.get_dominant(code)
                    if data.can_trade(stock):
                        price = data.current(stock,"close")
                        unit =context.get_contract(stock).multiplier
                        lots = math.floor(book_value/(unit*price))
                        if lots != 0:
                            context.buy_open(stock, lots, price, order_type=OrderType.MARKET)
      
    
             
            
    # 交易引擎:成交回报处理函数,每个成交发生时执行一次
    def m4_handle_trade_bigquant_run(context, trade):
        pass
    
    # 交易引擎:委托回报处理函数,每个委托变化时执行一次
    def m4_handle_order_bigquant_run(context, order):
        pass
    
    # 交易引擎:盘后处理函数,每日盘后执行一次
    def m4_after_trading_bigquant_run(context, data):
        pass
    
    
    m1 = M.instruments.v2(
        start_date='2017-06-01',
        end_date='2022-06-30',
        market='CN_FUTURE',
        instrument_list='',
        max_count=0
    )
    
    m8 = M.cached.v3(
        input_1=m1.data,
        run=m8_run_bigquant_run,
        post_run=m8_post_run_bigquant_run,
        input_ports='',
        params='{}',
        output_ports=''
    )
    
    m2 = M.use_datasource.v2(
        instruments=m8.data_1,
        datasource_id='bar1d_CN_FUTURE',
        start_date='',
        end_date='',
        before_start_days=0
    )
    
    m33 = M.use_datasource.v2(
        instruments=m8.data_1,
        datasource_id='basic_info_CN_FUTURE',
        start_date='',
        end_date='',
        before_start_days=0
    )
    
    m27 = M.cached.v3(
        input_1=m2.data,
        input_2=m33.data,
        run=m27_run_bigquant_run,
        post_run=m27_post_run_bigquant_run,
        input_ports='',
        params="""{
        'min_volume': 100000
    }""",
        output_ports=''
    )
    
    m3 = M.cached.v3(
        input_1=m27.data_1,
        run=m3_run_bigquant_run,
        post_run=m3_post_run_bigquant_run,
        input_ports='',
        params='{}',
        output_ports=''
    )
    
    m4 = M.hftrade.v2(
        instruments=m1.data,
        options_data=m3.data_1,
        start_date='',
        end_date='',
        initialize=m4_initialize_bigquant_run,
        before_trading_start=m4_before_trading_start_bigquant_run,
        handle_tick=m4_handle_tick_bigquant_run,
        handle_data=m4_handle_data_bigquant_run,
        handle_trade=m4_handle_trade_bigquant_run,
        handle_order=m4_handle_order_bigquant_run,
        after_trading=m4_after_trading_bigquant_run,
        capital_base=100000000,
        frequency='daily',
        price_type='真实价格',
        product_type='期货',
        before_start_days='0',
        volume_limit=1,
        order_price_field_buy='close',
        order_price_field_sell='close',
        benchmark='000300.HIX',
        plot_charts=True,
        disable_cache=False,
        replay_bdb=False,
        show_debug_info=False,
        backtest_only=False
    )
    
    • 收益率1125.37%
    • 年化收益率63.27%
    • 基准收益率28.23%
    • 阿尔法0.66
    • 贝塔0.37
    • 夏普比率1.79
    • 胜率0.58
    • 盈亏比1.67
    • 收益波动率29.28%
    • 最大回撤22.54%
    bigcharts-data-start/{"__type":"tabs","__id":"bigchart-dfc7eaa35df34368a808c65f18f23e6b"}/bigcharts-data-end