复制链接
克隆策略

    {"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":"-5320:input_2","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":"-5320: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"},{"to_node_id":"-113:features","from_node_id":"-294:data"},{"to_node_id":"-107:input_2","from_node_id":"-294:data"},{"to_node_id":"-113:factor_data","from_node_id":"-5320:data_1"}],"nodes":[{"node_id":"287d2cb0-f53c-4101-bdf8-104b137c8601-8","module_id":"BigQuantSpace.instruments.instruments-v2","parameters":[{"name":"start_date","value":"2010-01-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):\n from functools import reduce\n import pandas as pd \n import numpy as np \n \n df_raw = input_1.read()\n df_raw = df_raw[~(df_raw['instrument'].str.contains('IC|IF|IH|T|TF|TS'))]\n df_basic = input_2.read()[['product_code','instrument','delist_date']]\n df = df_raw[~(df_raw['instrument'].str.contains('0000|8888|9999'))]\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 #去掉成交量少的品种\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 def calc_t_mom(x,N):\n factor_name = 't_mom'\n x.sort_values(\"date\",inplace=True)\n x['returns'] = x['close'].pct_change()\n x[factor_name] = x['returns'].rolling(N).sum() * -1\n del x['product_code']\n x.set_index('date',inplace=True)\n return x\n\n def calc_t_cumstep(x,N):\n factor_name = 't_cum_step'\n x.sort_values('date',inplace=True)\n x[factor_name] = (2 * (x['high'] - x['low']) * np.sign(x['close'] - x['open']) - (x['close'] - x['open'])) / x['close']\n x[factor_name] = x[factor_name].rolling(N).mean() * -1\n del x['product_code']\n x.set_index('date',inplace=True)\n return x\n\n def calc_t_stds(x,N):\n factor_name = 't_stds'\n x.sort_values('date',inplace=True)\n x['h_hat'] = np.log(x['high']) - np.log(x['open'])\n x['l_hat'] = np.log(x['low']) - np.log(x['open'])\n x['c_hat'] = np.log(x['close']) - np.log(x['open'])\n x['gk'] = 0.5 * (x['h_hat'] - x['l_hat']) * (x['h_hat'] - x['l_hat']) - (2 * np.log(2) - 1) * x['c_hat'] * x['c_hat']\n x['gk'] = np.sqrt(x['gk'].rolling(5).sum() * 252 / 5)\n del x['product_code']\n del x['h_hat']\n del x['l_hat']\n del x['c_hat']\n x[factor_name] = (x['gk'] * (x['close'] - x['open']).apply(lambda x:np.sign(x)) ).rolling(N).mean() * -1\n x.set_index('date',inplace=True)\n return x\n \n df_result = pd.DataFrame(df_dom.groupby(\"product_code\").apply(calc_t_cumstep,N))\n df_result = df_result.reset_index()\n del df_result['instrument']\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,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.dropna(inplace=True)\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 'N':10\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()\n factor_name = input_2.read()[0]\n #signal \n def calc_signal(x,factor_name):\n x = x.sort_values(factor_name)\n length = x.shape[0]\n if length >= 10 :\n x['signal_'+factor_name] = [1]*5 + [0 for i in range(length-10)] + [-1]*5\n else :\n x['signal_' + factor_name] = [0] * length\n return x\n \n df_result = df.groupby(\"date\").apply(calc_signal,factor_name)\n df_result.reset_index(drop=True,inplace=True)\n #产生信号\n df_result = df_result[['date','instrument','signal_'+factor_name]] \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 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 \n if (context.trading_day_index % context.freq == 0) :\n print('date'*5, date)\n \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 stock_to_short = context.stock_to_short[context.stock_to_short['date'] == date]\n stock_to_short = stock_to_short[stock_to_short['signal'] < 0]['instrument']\n\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 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 for stock in short_pos.keys():\n pos = short_pos[stock]\n price = data.current(context.symbol(stock), \"close\")\n context.buy_close(context.symbol(stock), pos, price, order_type=OrderType.MARKET)\n \n \n # 开仓\n stock_num = len(stock_to_long) + len(stock_to_short)\n if stock_num != 0 :\n weight = 1 / stock_num\n portfolio_value = context.portfolio.portfolio_value\n book_value = portfolio_value * weight\n\n for i in range(len(stock_to_short)):\n stock_i = stock_to_short.iloc[i]\n stock = stock_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.sell_open(stock, lots, price, order_type=OrderType.MARKET)\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_id":"-113","module_id":"BigQuantSpace.factorlens_custom.factorlens_custom-v2","parameters":[{"name":"start_date","value":"2010-01-01","type":"Literal","bound_global_parameter":null},{"name":"end_date","value":"2022-06-30","type":"Literal","bound_global_parameter":null},{"name":"instrument_list","value":"","type":"Literal","bound_global_parameter":null},{"name":"expr","value":"","type":"Literal","bound_global_parameter":null},{"name":"rebalance_period","value":"5","type":"Literal","bound_global_parameter":null},{"name":"quantile_num","value":5,"type":"Literal","bound_global_parameter":null},{"name":"buy_commission_rate","value":0.0005,"type":"Literal","bound_global_parameter":null},{"name":"sell_commission_rate","value":0.0005,"type":"Literal","bound_global_parameter":null},{"name":"ic_method","value":"Rank_IC","type":"Literal","bound_global_parameter":null},{"name":"is_winsorize","value":"True","type":"Literal","bound_global_parameter":null},{"name":"is_standardlize","value":"False","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"features","node_id":"-113"},{"name":"factor_data","node_id":"-113"}],"output_ports":[{"name":"data_1","node_id":"-113"},{"name":"data_2","node_id":"-113"},{"name":"data_3","node_id":"-113"}],"cacheable":true,"seq_num":5,"comment":"","comment_collapsed":true},{"node_id":"-294","module_id":"BigQuantSpace.input_features.input_features-v1","parameters":[{"name":"features","value":"t_cum_step","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"features_ds","node_id":"-294"}],"output_ports":[{"name":"data","node_id":"-294"}],"cacheable":true,"seq_num":6,"comment":"","comment_collapsed":true},{"node_id":"-5320","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 df1 = input_1.read()\n data_1 = DataSource.write_pickle(df1)\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":"-5320"},{"name":"input_2","node_id":"-5320"},{"name":"input_3","node_id":"-5320"}],"output_ports":[{"name":"data_1","node_id":"-5320"},{"name":"data_2","node_id":"-5320"},{"name":"data_3","node_id":"-5320"}],"cacheable":true,"seq_num":7,"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='1528,-1655,200,200'/><node_position Node='-741' Position='1861,-1646,200,200'/><node_position Node='-32248' Position='1724,-1486,200,200'/><node_position Node='-17899' Position='1748,-1772,200,200'/><node_position Node='-107' Position='1723,-1376,200,200'/><node_position Node='-549' Position='1694,-1298,200,200'/><node_position Node='-113' Position='2144,-1345,200,200'/><node_position Node='-294' Position='2181,-1642,200,200'/><node_position Node='-5320' Position='2150,-1481,200,200'/></node_postions>"},"nodes_readonly":false,"studio_version":"v2"}
    In [3]:
    # 本代码由可视化策略环境自动生成 2022年9月23日 09:44
    # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
    
    
    # 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,N):
        from functools import reduce
        import pandas as pd 
        import numpy as np 
        
        df_raw = input_1.read()
        df_raw = df_raw[~(df_raw['instrument'].str.contains('IC|IF|IH|T|TF|TS'))]
        df_basic = input_2.read()[['product_code','instrument','delist_date']]
        df = df_raw[~(df_raw['instrument'].str.contains('0000|8888|9999'))]
        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)
        
        #去掉成交量少的品种
        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_t_mom(x,N):
            factor_name = 't_mom'
            x.sort_values("date",inplace=True)
            x['returns'] = x['close'].pct_change()
            x[factor_name] = x['returns'].rolling(N).sum() * -1
            del x['product_code']
            x.set_index('date',inplace=True)
            return x
    
        def calc_t_cumstep(x,N):
            factor_name = 't_cum_step'
            x.sort_values('date',inplace=True)
            x[factor_name] = (2 * (x['high'] - x['low']) * np.sign(x['close'] - x['open']) - (x['close'] - x['open'])) / x['close']
            x[factor_name] = x[factor_name].rolling(N).mean() * -1
            del x['product_code']
            x.set_index('date',inplace=True)
            return x
    
        def calc_t_stds(x,N):
            factor_name = 't_stds'
            x.sort_values('date',inplace=True)
            x['h_hat'] = np.log(x['high']) - np.log(x['open'])
            x['l_hat'] = np.log(x['low']) - np.log(x['open'])
            x['c_hat'] = np.log(x['close']) - np.log(x['open'])
            x['gk'] = 0.5 * (x['h_hat'] - x['l_hat']) * (x['h_hat'] - x['l_hat']) - (2 * np.log(2) - 1) * x['c_hat'] * x['c_hat']
            x['gk'] = np.sqrt(x['gk'].rolling(5).sum() * 252 / 5)
            del x['product_code']
            del x['h_hat']
            del x['l_hat']
            del x['c_hat']
            x[factor_name] = (x['gk'] * (x['close'] - x['open']).apply(lambda x:np.sign(x)) ).rolling(N).mean() * -1
            x.set_index('date',inplace=True)
            return x
        
        df_result = pd.DataFrame(df_dom.groupby("product_code").apply(calc_t_cumstep,N))
        df_result = df_result.reset_index()
        del df_result['instrument']
        
        #和样本空间
        df_result = pd.merge(df_universe,df_result,how='left',on=['date','product_code'])
        
        df_output = pd.merge(df_result,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.dropna(inplace=True)
        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 m7_run_bigquant_run(input_1, input_2, input_3):
        # 示例代码如下。在这里编写您的代码
        # 期限结构因子
        df1 = input_1.read()
        data_1 = DataSource.write_pickle(df1)
        return Outputs(data_1=data_1)
    
    # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    def m7_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()
        factor_name = input_2.read()[0]
        #signal 
        def calc_signal(x,factor_name):
            x = x.sort_values(factor_name)
            length = x.shape[0]
            if length >= 10 :
                x['signal_'+factor_name] = [1]*5 + [0 for i in range(length-10)] + [-1]*5
            else :
                x['signal_' + factor_name] = [0] * length
            return x
        
        df_result = df.groupby("date").apply(calc_signal,factor_name)
        df_result.reset_index(drop=True,inplace=True)
         #产生信号
        df_result =  df_result[['date','instrument','signal_'+factor_name]]  
        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):
        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')
            
        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']
            stock_to_short = context.stock_to_short[context.stock_to_short['date'] == date]
            stock_to_short = stock_to_short[stock_to_short['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():
                pos = long_pos[stock]
                price = data.current(context.symbol(stock), "close")
                context.sell_close(context.symbol(stock), pos, price, order_type=OrderType.MARKET)
            for stock in short_pos.keys():
                pos = short_pos[stock]
                price = data.current(context.symbol(stock), "close")
                context.buy_close(context.symbol(stock), pos, price, order_type=OrderType.MARKET)
                
     
            # 开仓
            stock_num = len(stock_to_long) + len(stock_to_short)
            if stock_num != 0 :
                weight =  1 / stock_num
                portfolio_value = context.portfolio.portfolio_value
                book_value = portfolio_value  * weight
    
                for i in range(len(stock_to_short)):
                    stock_i = stock_to_short.iloc[i]
                    stock = stock_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.sell_open(stock, lots, price, order_type=OrderType.MARKET)
    
                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='2010-01-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,
        'N':10
    }""",
        output_ports=''
    )
    
    m7 = M.cached.v3(
        input_1=m27.data_1,
        input_2=m2.data,
        run=m7_run_bigquant_run,
        post_run=m7_post_run_bigquant_run,
        input_ports='',
        params='{}',
        output_ports=''
    )
    
    m6 = M.input_features.v1(
        features='t_cum_step'
    )
    
    m5 = M.factorlens_custom.v2(
        features=m6.data,
        factor_data=m7.data_1,
        start_date='2010-01-01',
        end_date='2022-06-30',
        instrument_list='',
        expr='',
        rebalance_period=5,
        quantile_num=5,
        buy_commission_rate=0.0005,
        sell_commission_rate=0.0005,
        ic_method='Rank_IC',
        is_winsorize=True,
        is_standardlize=False
    )
    
    m3 = M.cached.v3(
        input_1=m27.data_1,
        input_2=m6.data,
        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
    )
    

    t_cum_step: IC分析

    • IC均值0.0032
    • IC标准差0.283
    • ICIR0.0113
    • IC正值次数298次
    • IC负值次数307次
    • IC偏度-0.0468
    • IC峰度-0.1976

    t_cum_step: 因子收益率分析

    • 因子收益均值-0.078
    • 因子收益标准差2.583
    • 因子收益为正比率49.830000000000005%
    • t值绝对值的均值1.2664
    • t值绝对值大于2的比率0.1997
    • 因子收益t检验p值小于0.05的比率0.1848

    t_cum_step: 因子绩效分析

    •   top0_ret top4_ret LS_ret
    • 收益率 -0.3307 -0.1429 -0.1416
    • 近1日收益率 -0.0011 0.001 -0.001
    • 近1周收益率 -0.0022 -0.0076 0.0026
    • 近1月收益率 -0.0754 -0.083 0.004
    • 年化收益率 -0.0328 -0.0127 -0.0126
    • 夏普比率 -0.2876 -0.1981 -0.5344
    • 收益波动率 0.1808 0.1691 0.0828
    • 最大回撤 -0.7022 -0.7704 -0.4288
    datedatedatedatedate 2010-01-04
    datedatedatedatedate 2010-02-01
    datedatedatedatedate 2010-03-08
    datedatedatedatedate 2010-04-06
    datedatedatedatedate 2010-05-05
    datedatedatedatedate 2010-06-02
    datedatedatedatedate 2010-07-05
    datedatedatedatedate 2010-08-02
    datedatedatedatedate 2010-08-30
    datedatedatedatedate 2010-09-30
    datedatedatedatedate 2010-11-04
    datedatedatedatedate 2010-12-02
    datedatedatedatedate 2010-12-30
    datedatedatedatedate 2011-01-28
    datedatedatedatedate 2011-03-04
    datedatedatedatedate 2011-04-01
    datedatedatedatedate 2011-05-04
    datedatedatedatedate 2011-06-01
    datedatedatedatedate 2011-06-30
    datedatedatedatedate 2011-07-28
    datedatedatedatedate 2011-08-25
    datedatedatedatedate 2011-09-23
    datedatedatedatedate 2011-10-28
    datedatedatedatedate 2011-11-25
    datedatedatedatedate 2011-12-23
    datedatedatedatedate 2012-01-31
    datedatedatedatedate 2012-02-28
    datedatedatedatedate 2012-03-27
    datedatedatedatedate 2012-04-27
    datedatedatedatedate 2012-05-29
    datedatedatedatedate 2012-06-27
    datedatedatedatedate 2012-07-25
    datedatedatedatedate 2012-08-22
    datedatedatedatedate 2012-09-19
    datedatedatedatedate 2012-10-24
    datedatedatedatedate 2012-11-21
    datedatedatedatedate 2012-12-19
    datedatedatedatedate 2013-01-21
    datedatedatedatedate 2013-02-25
    datedatedatedatedate 2013-03-25
    datedatedatedatedate 2013-04-24
    datedatedatedatedate 2013-05-27
    datedatedatedatedate 2013-06-27
    datedatedatedatedate 2013-07-25
    datedatedatedatedate 2013-08-22
    datedatedatedatedate 2013-09-23
    datedatedatedatedate 2013-10-28
    datedatedatedatedate 2013-11-25
    datedatedatedatedate 2013-12-23
    datedatedatedatedate 2014-01-21
    datedatedatedatedate 2014-02-25
    datedatedatedatedate 2014-03-25
    datedatedatedatedate 2014-04-23
    datedatedatedatedate 2014-05-23
    datedatedatedatedate 2014-06-23
    datedatedatedatedate 2014-07-21
    datedatedatedatedate 2014-08-18
    datedatedatedatedate 2014-09-16
    datedatedatedatedate 2014-10-21
    datedatedatedatedate 2014-11-18
    datedatedatedatedate 2014-12-16
    datedatedatedatedate 2015-01-15
    datedatedatedatedate 2015-02-12
    datedatedatedatedate 2015-03-19
    datedatedatedatedate 2015-04-17
    datedatedatedatedate 2015-05-18
    datedatedatedatedate 2015-06-15
    datedatedatedatedate 2015-07-14
    datedatedatedatedate 2015-08-11
    datedatedatedatedate 2015-09-10
    datedatedatedatedate 2015-10-15
    datedatedatedatedate 2015-11-12
    datedatedatedatedate 2015-12-10
    datedatedatedatedate 2016-01-08
    datedatedatedatedate 2016-02-05
    datedatedatedatedate 2016-03-11
    datedatedatedatedate 2016-04-11
    datedatedatedatedate 2016-05-10
    datedatedatedatedate 2016-06-07
    datedatedatedatedate 2016-07-07
    datedatedatedatedate 2016-08-04
    datedatedatedatedate 2016-09-01
    datedatedatedatedate 2016-10-10
    datedatedatedatedate 2016-11-07
    datedatedatedatedate 2016-12-05
    datedatedatedatedate 2017-01-03
    datedatedatedatedate 2017-02-07
    datedatedatedatedate 2017-03-07
    datedatedatedatedate 2017-04-06
    datedatedatedatedate 2017-05-05
    datedatedatedatedate 2017-06-06
    datedatedatedatedate 2017-07-04
    datedatedatedatedate 2017-08-01
    datedatedatedatedate 2017-08-29
    datedatedatedatedate 2017-09-26
    datedatedatedatedate 2017-10-31
    datedatedatedatedate 2017-11-28
    datedatedatedatedate 2017-12-26
    datedatedatedatedate 2018-01-24
    datedatedatedatedate 2018-02-28
    datedatedatedatedate 2018-03-28
    datedatedatedatedate 2018-04-27
    datedatedatedatedate 2018-05-29
    datedatedatedatedate 2018-06-27
    datedatedatedatedate 2018-07-25
    datedatedatedatedate 2018-08-22
    datedatedatedatedate 2018-09-19
    datedatedatedatedate 2018-10-25
    datedatedatedatedate 2018-11-22
    datedatedatedatedate 2018-12-20
    datedatedatedatedate 2019-01-21
    datedatedatedatedate 2019-02-25
    datedatedatedatedate 2019-03-25
    datedatedatedatedate 2019-04-23
    datedatedatedatedate 2019-05-24
    datedatedatedatedate 2019-06-24
    datedatedatedatedate 2019-07-22
    datedatedatedatedate 2019-08-19
    datedatedatedatedate 2019-09-17
    datedatedatedatedate 2019-10-22
    datedatedatedatedate 2019-11-19
    datedatedatedatedate 2019-12-17
    datedatedatedatedate 2020-01-15
    datedatedatedatedate 2020-02-20
    datedatedatedatedate 2020-03-19
    datedatedatedatedate 2020-04-17
    datedatedatedatedate 2020-05-20
    datedatedatedatedate 2020-06-17
    datedatedatedatedate 2020-07-17
    datedatedatedatedate 2020-08-14
    datedatedatedatedate 2020-09-11
    datedatedatedatedate 2020-10-19
    datedatedatedatedate 2020-11-16
    datedatedatedatedate 2020-12-14
    datedatedatedatedate 2021-01-12
    datedatedatedatedate 2021-02-09
    datedatedatedatedate 2021-03-16
    datedatedatedatedate 2021-04-14
    datedatedatedatedate 2021-05-17
    datedatedatedatedate 2021-06-15
    datedatedatedatedate 2021-07-13
    datedatedatedatedate 2021-08-10
    datedatedatedatedate 2021-09-07
    datedatedatedatedate 2021-10-14
    datedatedatedatedate 2021-11-11
    datedatedatedatedate 2021-12-09
    datedatedatedatedate 2022-01-07
    datedatedatedatedate 2022-02-11
    datedatedatedatedate 2022-03-11
    datedatedatedatedate 2022-04-12
    datedatedatedatedate 2022-05-13
    datedatedatedatedate 2022-06-13
    
    • 收益率26.88%
    • 年化收益率1.92%
    • 基准收益率26.87%
    • 阿尔法-0.01
    • 贝塔-0.01
    • 夏普比率-0.07
    • 胜率0.53
    • 盈亏比1.06
    • 收益波动率8.61%
    • 最大回撤23.27%
    bigcharts-data-start/{"__type":"tabs","__id":"bigchart-295869b43b17497c92213cce6ffd3c66"}/bigcharts-data-end
    In [5]:
    import empyrical
    start_date = ['2010-01-01', '2011-01-01', '2012-01-01', '2013-01-01', '2014-01-01', '2015-01-01', '2016-01-01', '2017-01-01', '2018-01-01', '2019-01-01', '2020-01-01', '2021-01-01', '2022-01-01']
    end_date = ['2010-12-31', '2011-12-31', '2012-12-31', '2013-12-31', '2014-12-31', '2015-12-31', '2016-12-31', '2017-12-31', '2018-12-31', '2019-12-31', '2020-12-31', '2021-12-31', '2022-08-31']
    raw_perf = m4.raw_perf.read()
    df_result = []
    for sd, ed in zip(start_date, end_date):
        df = raw_perf[raw_perf.date.between(sd, ed)]
        sharpe = empyrical.sharpe_ratio(df.returns)
        sortino = empyrical.sortino_ratio(df.returns)
        max_drawdown = empyrical.max_drawdown(df.returns)
        vol = empyrical.annual_volatility(df.returns)
        returns = empyrical.annual_return(df.returns)
        df_result.append({'start_date':sd,'end_date':ed,'returns':returns,'vol':vol,'max_drawdown':max_drawdown,'sharpe':sharpe,'sortino':sortino})
    #     print(f"date between {sd} and {ed}, the sharpe is {sharpe}, sortino is {sortino}")
    pd.DataFrame(df_result)[['returns','vol','max_drawdown','sharpe','sortino']]
    
    Out[5]:
    returns vol max_drawdown sharpe sortino
    0 -0.003174 0.078035 -0.076142 -0.001876 -0.002610
    1 0.145042 0.072891 -0.058363 1.894949 2.887791
    2 0.120870 0.077576 -0.038748 1.509760 2.476620
    3 0.079012 0.070575 -0.056094 1.112800 1.666135
    4 -0.036534 0.075730 -0.075938 -0.453740 -0.644220
    5 0.113790 0.078001 -0.064545 1.420765 2.145643
    6 0.153066 0.141398 -0.108166 1.077808 1.673547
    7 -0.066750 0.124550 -0.111116 -0.492476 -0.665048
    8 0.147776 0.097805 -0.067818 1.458223 2.286790
    9 0.101444 0.095580 -0.078425 1.058654 1.617385
    10 -0.049555 0.140734 -0.189198 -0.291059 -0.414395
    11 0.129588 0.171734 -0.141043 0.795118 1.197187
    12 -0.131828 0.144301 -0.081542 -0.907353 -1.134813
    In [26]:
     
    
    Out[26]:
    -0.013927574430000478
    In [ ]: