{"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"}
[2022-09-02 15:01:54.897220] INFO: moduleinvoker: instruments.v2 开始运行..
[2022-09-02 15:01:54.909073] INFO: moduleinvoker: 命中缓存
[2022-09-02 15:01:54.911160] INFO: moduleinvoker: instruments.v2 运行完成[0.013943s].
[2022-09-02 15:01:54.925675] INFO: moduleinvoker: cached.v3 开始运行..
[2022-09-02 15:01:54.939841] INFO: moduleinvoker: 命中缓存
[2022-09-02 15:01:54.941758] INFO: moduleinvoker: cached.v3 运行完成[0.016123s].
[2022-09-02 15:01:54.950630] INFO: moduleinvoker: use_datasource.v2 开始运行..
[2022-09-02 15:01:54.961254] INFO: moduleinvoker: 命中缓存
[2022-09-02 15:01:54.964070] INFO: moduleinvoker: use_datasource.v2 运行完成[0.013464s].
[2022-09-02 15:01:54.977348] INFO: moduleinvoker: use_datasource.v2 开始运行..
[2022-09-02 15:01:54.987191] INFO: moduleinvoker: 命中缓存
[2022-09-02 15:01:54.989434] INFO: moduleinvoker: use_datasource.v2 运行完成[0.01212s].
[2022-09-02 15:01:55.005592] INFO: moduleinvoker: cached.v3 开始运行..
[2022-09-02 15:01:55.018493] INFO: moduleinvoker: 命中缓存
[2022-09-02 15:01:55.020433] INFO: moduleinvoker: cached.v3 运行完成[0.014851s].
[2022-09-02 15:01:55.032969] INFO: moduleinvoker: cached.v3 开始运行..
[2022-09-02 15:01:55.047972] INFO: moduleinvoker: 命中缓存
[2022-09-02 15:01:55.050282] INFO: moduleinvoker: cached.v3 运行完成[0.017313s].
[2022-09-02 15:01:55.114336] INFO: moduleinvoker: hfbacktest.v1 开始运行..
[2022-09-02 15:01:55.166046] INFO: moduleinvoker: 命中缓存
[2022-09-02 15:01:58.189279] INFO: moduleinvoker: hfbacktest.v1 运行完成[3.074954s].
[2022-09-02 15:01:58.191694] INFO: moduleinvoker: hftrade.v2 运行完成[3.130567s].
- 收益率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