{"description":"实验创建于2021/12/2","graph":{"edges":[{"to_node_id":"-74:input_1","from_node_id":"-5:data"},{"to_node_id":"-62:features","from_node_id":"-13:data"},{"to_node_id":"-97:input_data","from_node_id":"-62:data"},{"to_node_id":"-2990:input_ds","from_node_id":"-71:data"},{"to_node_id":"-3809:options_data","from_node_id":"-97:data"},{"to_node_id":"-3809:instruments","from_node_id":"-74:data_1"},{"to_node_id":"-71:instruments","from_node_id":"-74:data_2"},{"to_node_id":"-62:input_data","from_node_id":"-2990:sorted_data"}],"nodes":[{"node_id":"-5","module_id":"BigQuantSpace.instruments.instruments-v2","parameters":[{"name":"start_date","value":"2010-01-01","type":"Literal","bound_global_parameter":"交易日期"},{"name":"end_date","value":"2022-08-31","type":"Literal","bound_global_parameter":"交易日期"},{"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":"-5"}],"output_ports":[{"name":"data","node_id":"-5"}],"cacheable":true,"seq_num":1,"comment":"","comment_collapsed":true},{"node_id":"-13","module_id":"BigQuantSpace.input_features.input_features-v1","parameters":[{"name":"features","value":"# #号开始的表示注释,注释需单独一行\n# 多个特征,每行一个,可以包含基础特征和衍生特征,特征须为本平台特征\n# bbands_up = ta_bbands_u(close, 20)\n# bbands = ta_bbands_m(close, 20)\n# bbands_low = ta_bbands_l(close, 20)\nbbands_std = std(close, 30)\nbbands = mean(close, 30)\nbbands_up = mean(close, 30) + 1 * bbands_std\nbbands_low = mean(close, 30) - 1 * bbands_std\n\nATR = ta_atr(high, low, close, 30)\nLev_ATR = clip(((0.05 / ATR) * close), 0.01, 5)\n\nOI_short = mean(open_intl, 10)\nOI_long = mean(open_intl, 20)\nOI_pct = OI_short / OI_long\n\nprice_diff = close - shift(close, 1)\ntrend_strength = (close - shift(close, 252)) / sum(abs(price_diff), 252)\n\n","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"features_ds","node_id":"-13"}],"output_ports":[{"name":"data","node_id":"-13"}],"cacheable":true,"seq_num":2,"comment":"","comment_collapsed":true},{"node_id":"-62","module_id":"BigQuantSpace.derived_feature_extractor.derived_feature_extractor-v3","parameters":[{"name":"date_col","value":"date","type":"Literal","bound_global_parameter":null},{"name":"instrument_col","value":"instrument","type":"Literal","bound_global_parameter":null},{"name":"drop_na","value":"False","type":"Literal","bound_global_parameter":null},{"name":"remove_extra_columns","value":"True","type":"Literal","bound_global_parameter":null},{"name":"user_functions","value":"{}","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"input_data","node_id":"-62"},{"name":"features","node_id":"-62"}],"output_ports":[{"name":"data","node_id":"-62"}],"cacheable":true,"seq_num":4,"comment":"","comment_collapsed":true},{"node_id":"-71","module_id":"BigQuantSpace.use_datasource.use_datasource-v1","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}],"input_ports":[{"name":"instruments","node_id":"-71"},{"name":"features","node_id":"-71"}],"output_ports":[{"name":"data","node_id":"-71"}],"cacheable":true,"seq_num":5,"comment":"","comment_collapsed":true},{"node_id":"-97","module_id":"BigQuantSpace.dropnan.dropnan-v2","parameters":[],"input_ports":[{"name":"input_data","node_id":"-97"},{"name":"features","node_id":"-97"}],"output_ports":[{"name":"data","node_id":"-97"}],"cacheable":true,"seq_num":3,"comment":"","comment_collapsed":true},{"node_id":"-3809","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":"def bigquant_run(context):\n msg = \"initialize:\" \n context.PRINT = 1\n context.write_log(msg, stdout=context.PRINT)\n print(\"initializing:\")\n context.all_data = context.options[\"data\"].read()\n context.all_data.set_index(\"instrument\", inplace=True)\n context.atr = pd.DataFrame()\n \n context.returns = []\n context.order_num = {}\n \n context.num_contract = 5 # 最终选取标的数量\n context.adjust_vol = False # 是否进行波动率调整\n context.oi_adjust = False # 是否进行持仓量调整\n context.expected_vol = 0.2 # 预期策略波动率(决定杠杆系数)\n context.adjust_volatility_period = 22 # 波动率调整周期\n context.vol_window = 126\n context.adjust_contract_period = 126 # 合约标的筛选周期\n\n# context.set_commission(equities_commission=PerOrder(buy_cost=0.0003, sell_cost=0.0003, min_cost=5.0))\n context.set_slippage_value(slippage_value=0.001)\n \n# context.cash_per_constract = context.portfolio.portfolio_value / context.num_contract\n# context.cash_per_constract = 10000000","type":"Literal","bound_global_parameter":null},{"name":"before_trading_start","value":"def bigquant_run(context, data):\n context.today = data.trading_day_dt.strftime('%Y-%m-%d')\n# print(\"check date, \", context.today)\n context.today_data = context.all_data[context.all_data.date==context.today]\n\n if context.trading_day_index % context.adjust_contract_period == 0:\n # print(f\"{context.today}进行合约筛选\")\n r1 = context.today_data\n r1.sort_values(by=[\"trend_strength\"], ascending=False, inplace=True)\n context.ins = sorted(r1.index[:context.num_contract].tolist())\n context.ins_dominant = sorted(context.get_dominant(context.ins))\n if context.trading_day_index == 0:\n context.extension.pre_ins_dominant = context.ins_dominant\n else:\n context.ins = sorted(context.extension.pre_ins) # 8888\n context.ins_dominant = sorted(context.get_dominant(context.ins))\n \n subscribe_list = list(set(context.ins_dominant).union(set(context.extension.pre_ins_dominant)))\n # print(context.today, context.ins, context.ins_dominant)\n context.subscribe(subscribe_list) # 订阅主力合约\n \n context.cash_per_constract = context.portfolio.portfolio_value / context.num_contract","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":"def bigquant_run(context, data):\n import pandas as pd\n import empyrical\n\n ##--------- 已实现波动率调整 ---------##\n if context.adjust_vol:\n if context.trading_day_index % context.adjust_volatility_period == 0 and context.trading_day_index != 0:\n raw_perf = context.get_perf_datas() # 读取累计策略绩效表现\n context.returns = []\n for d in raw_perf:\n context.returns.append(d[\"returns\"])\n if empyrical.annual_volatility(pd.Series(context.returns[-context.vol_window:])) != 0:\n context.extension.mul_vol = context.expected_vol / (empyrical.annual_volatility(pd.Series(context.returns[-context.vol_window:])))\n else:\n context.extension.mul_vol = 1\n elif context.trading_day_index == 0:\n context.extension.mul_vol = 1\n else:\n context.extension.mul_vol = 1\n ##--------- 已实现波动率调整 ---------##\n \n all_data = context.today_data\n atr_data = all_data[[\"Lev_ATR\", \"date\"]]\n atr_data[\"Lev_ATR\"] = atr_data[\"Lev_ATR\"] * context.extension.mul_vol\n all_data = pd.DataFrame(all_data)\n atr_data = pd.DataFrame(atr_data)\n \n if len(all_data) == 0:\n return\n \n ##--------- 对调整标的池之后未在标的池中的合约进行平仓处理 ---------##\n if len(context.get_account_positions()) > 0:\n ins_pc = [i.split(\".\")[0][:-4] for i in context.ins]\n for instrument, _ in context.get_account_positions().items():\n pc = instrument.split(\".\")[0][:-4]\n if pc not in ins_pc:\n price = data.current(instrument, \"close\")\n long_position = context.get_account_position(instrument, direction=Direction.LONG).avail_qty\n short_position = context.get_account_position(instrument, direction=Direction.SHORT).avail_qty\n if long_position > 0:\n # print(context.today, \"合约调整, 平多, for \", instrument)\n rv = context.order_target(instrument, 0, price, order_type=OrderType.MARKET)\n # msg = \"{} 合约调整 for {} 下单函数返回={}\".format(str(context.today), instrument, str(rv))\n # context.write_log(msg, stdout=1)\n if short_position > 0:\n # print(context.today, \"合约调整, 平空, for \", instrument)\n rv = context.order_target(instrument, 0, price, order_type=OrderType.MARKET)\n # msg = \"{} 合约调整 for {} 下单函数返回={}\".format(str(context.today), instrument, str(rv))\n # context.write_log(msg, stdout=1)\n ##--------- 对调整标的池之后未在标的池中的合约进行平仓处理: ---------##\n \n ## 遍历交易标的进行交易逻辑\n for instrument in context.ins:\n if instrument not in set(all_data.index):\n continue\n pc = instrument.split(\".\")[0][:-4]\n dominant_code = [i for i in context.ins_dominant if pc == i.split(\".\")[0][:-4]][0]\n\n pre_dominant_list = [i for i in context.extension.pre_ins_dominant if pc == i.split(\".\")[0][:-4]]\n if not len(pre_dominant_list):\n pre_dominant_code = dominant_code\n else:\n pre_dominant_code = pre_dominant_list[0]\n\n high_line = all_data['bbands_up'].loc[instrument]\n low_line = all_data['bbands_low'].loc[instrument]\n ma_line = all_data['bbands'].loc[instrument]\n OI_pct = all_data[\"OI_pct\"].loc[instrument]\n ma_std = all_data['bbands_std'].loc[instrument]\n n = 3 # 止盈通道线系数 n*std(close)\n Lev_ATR = atr_data[\"Lev_ATR\"].loc[instrument]\n context.long_stop_line = ma_line + n * ma_std\n context.short_stop_line = ma_line - n * ma_std\n \n price = data.current(instrument, \"close\") # 合约价格\n multiplier = context.get_contract(instrument).multiplier # 合约乘数\n long_position = context.get_account_position(pre_dominant_code, direction=Direction.LONG).avail_qty # 多头持仓\n short_position = context.get_account_position(pre_dominant_code, direction=Direction.SHORT).avail_qty # 空头持仓\n curr_position = short_position + long_position # 总持仓\n \n order_num = int(Lev_ATR * (context.cash_per_constract // (price * multiplier)))\n \n # 持仓量调整\n if context.oi_adjust:\n if order_num >= 2 and OI_pct < 1:\n order_num = math.ceil(0.5 * order_num)\n\n if curr_position==0:\n if price > high_line:\n # print(context.today, \"无仓位, 开多, for \", dominant_code)\n rv1 = context.order_target(dominant_code, order_num, price, order_type=OrderType.MARKET)\n # msg1 = \"{} 开多 for {} 下单函数返回={}\".format(str(context.today), dominant_code, str(rv1))\n # context.write_log(msg1, stdout=1)\n elif price < low_line:\n # print(context.today, \"无仓位, 开空, for \", dominant_code)\n rv1 = context.order_target(dominant_code, -order_num, price, order_type=OrderType.MARKET)\n # msg1 = \"{} 开空 for {} 下单函数返回={}\".format(str(context.today), dominant_code, str(rv1))\n # context.write_log(msg1, stdout=1)\n else:\n if short_position > 0:\n if price > ma_line:# or price <= context.short_stop_line:\n # print(context.today, \"平空, for \", pre_dominant_code)\n rv1 = context.order_target(pre_dominant_code, 0, price, order_type=OrderType.MARKET)\n # msg1 = \"{} 平空 for {} 下单函数返回={}\".format(str(context.today), pre_dominant_code, str(rv1))\n # context.write_log(msg1, stdout=1)\n else:\n if dominant_code != pre_dominant_code:\n # print(context.today, \"未触发平空仓信号, 但需移仓换月, for \", pre_dominant_code, dominant_code)\n rv1 = context.order_target(pre_dominant_code, 0, price, order_type=OrderType.MARKET)\n # msg1 = \"{} 平旧主力合约 for {} 下单函数返回={}\".format(str(context.today), pre_dominant_code, str(rv1))\n # context.write_log(msg1, stdout=1)\n rv2 = context.order_target(dominant_code, -short_position, price, order_type=OrderType.MARKET)\n # msg2 = \"{} 开新主力合约 for {} 下单函数返回={}\".format(str(context.today), dominant_code, str(rv2))\n # context.write_log(msg2, stdout=1)\n\n elif long_position > 0:\n if price < ma_line:# or price >= context.long_stop_line:\n # print(context.today, \"平多, for \", pre_dominant_code)\n rv1 = context.order_target(pre_dominant_code, 0, price, order_type=OrderType.MARKET)\n # msg1 = \"{} 平多 for {} 下单函数返回={}\".format(str(context.today), pre_dominant_code, str(rv1))\n # context.write_log(msg1, stdout=1)\n else:\n if dominant_code != pre_dominant_code:\n # print(context.today, \"未触发平多仓信号, 但需移仓换月, for \", pre_dominant_code, dominant_code)\n rv1 = context.order_target(pre_dominant_code, 0, price, order_type=OrderType.MARKET)\n # msg1 = \"{} 平旧主力合约 for {} 下单函数返回={}\".format(str(context.today), pre_dominant_code, str(rv1))\n # context.write_log(msg1, stdout=1)\n rv2 = context.order_target(dominant_code, long_position, price, order_type=OrderType.MARKET)\n # msg2 = \"{} 开新主力合约 for {} 下单函数返回={}\".format(str(context.today), dominant_code, str(rv2))\n # context.write_log(msg2, stdout=1)","type":"Literal","bound_global_parameter":null},{"name":"handle_trade","value":"# 交易引擎:成交回报处理函数,每个成交发生时执行一次\ndef bigquant_run(context, data):\n# msg = \"handle_trade data:{}\".format(data.log_str())\n# context.write_log(msg, stdout=context.PRINT)\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"handle_order","value":"# 交易引擎:委托回报处理函数,每个委托变化时执行一次\ndef bigquant_run(context, data):\n# msg = \"handle_order data:{}\".format(data.log_str())\n# context.write_log(msg, stdout=context.PRINT)\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"after_trading","value":"# 交易引擎:盘后处理函数,每日盘后执行一次\ndef bigquant_run(context, data):\n context.extension.pre_ins = context.ins\n context.extension.pre_ins_dominant = context.ins_dominant\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":"open","type":"Literal","bound_global_parameter":null},{"name":"order_price_field_sell","value":"open","type":"Literal","bound_global_parameter":null},{"name":"benchmark","value":"","type":"Literal","bound_global_parameter":null},{"name":"plot_charts","value":"True","type":"Literal","bound_global_parameter":null},{"name":"disable_cache","value":"True","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":"-3809"},{"name":"options_data","node_id":"-3809"},{"name":"history_ds","node_id":"-3809"},{"name":"benchmark_ds","node_id":"-3809"}],"output_ports":[{"name":"raw_perf","node_id":"-3809"}],"cacheable":false,"seq_num":8,"comment":"","comment_collapsed":true},{"node_id":"-74","module_id":"BigQuantSpace.futures_forward_extractor.futures_forward_extractor-v9","parameters":[{"name":"before_days","value":"252","type":"Literal","bound_global_parameter":null},{"name":"product_filter","value":"[\"BB\", \"LR\", \"JR\", \"FB\", \"RI\", \"WR\", \"RS\", \"PM\", \"WT\", \"TC\", \"RO\", \"ER\", \"WS\", \"B\", \"FU\", \"LU\", \"SC\", \"L\", \"ME\", \"WH\"]","type":"Literal","bound_global_parameter":null},{"name":"if_CFX","value":"True","type":"Literal","bound_global_parameter":null},{"name":"set_enable_trade","value":"False","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"input_1","node_id":"-74"}],"output_ports":[{"name":"data_1","node_id":"-74"},{"name":"data_2","node_id":"-74"},{"name":"data_3","node_id":"-74"}],"cacheable":true,"seq_num":7,"comment":"","comment_collapsed":true},{"node_id":"-2990","module_id":"BigQuantSpace.sort.sort-v5","parameters":[{"name":"sort_by","value":"date","type":"Literal","bound_global_parameter":null},{"name":"group_by","value":"--","type":"Literal","bound_global_parameter":null},{"name":"keep_columns","value":"--","type":"Literal","bound_global_parameter":null},{"name":"ascending","value":"True","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"input_ds","node_id":"-2990"},{"name":"sort_by_ds","node_id":"-2990"}],"output_ports":[{"name":"sorted_data","node_id":"-2990"}],"cacheable":true,"seq_num":6,"comment":"","comment_collapsed":true}],"node_layout":"<node_postions><node_position Node='-5' Position='206,-27,200,200'/><node_position Node='-13' Position='627.1610717773438,30,200,200'/><node_position Node='-62' Position='414,290,200,200'/><node_position Node='-71' Position='414,139,200,200'/><node_position Node='-97' Position='415,359,200,200'/><node_position Node='-3809' Position='341,433,200,200'/><node_position Node='-74' Position='210,35.16108703613281,200,200'/><node_position Node='-2990' Position='416,213,200,200'/></node_postions>"},"nodes_readonly":false,"studio_version":"v2"}
[2022-09-15 23:15:47.235829] INFO: moduleinvoker: instruments.v2 开始运行..
[2022-09-15 23:15:47.252905] INFO: moduleinvoker: 命中缓存
[2022-09-15 23:15:47.254530] INFO: moduleinvoker: instruments.v2 运行完成[0.018712s].
[2022-09-15 23:15:47.264340] INFO: moduleinvoker: futures_forward_extractor.v9 开始运行..
[2022-09-15 23:16:10.208560] INFO: moduleinvoker: futures_forward_extractor.v9 运行完成[22.944212s].
[2022-09-15 23:16:10.214569] INFO: moduleinvoker: use_datasource.v1 开始运行..
[2022-09-15 23:16:19.761552] INFO: moduleinvoker: use_datasource.v1 运行完成[9.546977s].
[2022-09-15 23:16:19.787076] INFO: moduleinvoker: sort.v5 开始运行..
[2022-09-15 23:16:20.101567] INFO: moduleinvoker: sort.v5 运行完成[0.31448s].
[2022-09-15 23:16:20.107870] INFO: moduleinvoker: input_features.v1 开始运行..
[2022-09-15 23:16:20.114176] INFO: moduleinvoker: 命中缓存
[2022-09-15 23:16:20.116262] INFO: moduleinvoker: input_features.v1 运行完成[0.008403s].
[2022-09-15 23:16:20.127362] INFO: moduleinvoker: derived_feature_extractor.v3 开始运行..
[2022-09-15 23:16:20.588163] INFO: derived_feature_extractor: 提取完成 bbands_std = std(close, 30), 0.065s
[2022-09-15 23:16:20.651186] INFO: derived_feature_extractor: 提取完成 bbands = mean(close, 30), 0.061s
[2022-09-15 23:16:20.717592] INFO: derived_feature_extractor: 提取完成 bbands_up = mean(close, 30) + 1 * bbands_std, 0.065s
[2022-09-15 23:16:20.780895] INFO: derived_feature_extractor: 提取完成 bbands_low = mean(close, 30) - 1 * bbands_std, 0.061s
[2022-09-15 23:16:20.870247] INFO: derived_feature_extractor: 提取完成 ATR = ta_atr(high, low, close, 30), 0.088s
[2022-09-15 23:16:20.873776] INFO: derived_feature_extractor: 提取完成 Lev_ATR = clip(((0.05 / ATR) * close), 0.01, 5), 0.002s
[2022-09-15 23:16:20.936296] INFO: derived_feature_extractor: 提取完成 OI_short = mean(open_intl, 10), 0.061s
[2022-09-15 23:16:21.003668] INFO: derived_feature_extractor: 提取完成 OI_long = mean(open_intl, 20), 0.066s
[2022-09-15 23:16:21.006953] INFO: derived_feature_extractor: 提取完成 OI_pct = OI_short / OI_long, 0.002s
[2022-09-15 23:16:21.023861] INFO: derived_feature_extractor: 提取完成 price_diff = close - shift(close, 1), 0.015s
[2022-09-15 23:16:21.104998] INFO: derived_feature_extractor: 提取完成 trend_strength = (close - shift(close, 252)) / sum(abs(price_diff), 252), 0.079s
[2022-09-15 23:16:21.516136] INFO: derived_feature_extractor: /data, 102712
[2022-09-15 23:16:21.676188] INFO: moduleinvoker: derived_feature_extractor.v3 运行完成[1.548823s].
[2022-09-15 23:16:21.686913] INFO: moduleinvoker: dropnan.v2 开始运行..
[2022-09-15 23:16:21.920833] INFO: dropnan: /data, 90080/102712
[2022-09-15 23:16:21.977431] INFO: dropnan: 行数: 90080/102712
[2022-09-15 23:16:21.982309] INFO: moduleinvoker: dropnan.v2 运行完成[0.29539s].
[2022-09-15 23:16:22.018511] INFO: moduleinvoker: hfbacktest.v1 开始运行..
[2022-09-15 23:16:22.024309] INFO: hfbacktest: biglearning V1.4.19
[2022-09-15 23:16:22.026545] INFO: hfbacktest: bigtrader v1.9.7_sp7 2022-09-15
[2022-09-15 23:18:11.106114] INFO: hfbacktest: backtest done, raw_perf_ds:DataSource(c0b8e8bf91a84cd1bfeeb52524d5df40T)
[2022-09-15 23:18:16.218149] INFO: moduleinvoker: hfbacktest.v1 运行完成[114.199645s].
[2022-09-15 23:18:16.219957] INFO: moduleinvoker: hftrade.v2 运行完成[114.230759s].
2022-09-15 23:16:51.102341 strategy(bktfut,): initialize:
initializing:
- 收益率867.7%
- 年化收益率19.54%
- 基准收益率0.0%
- 阿尔法nan
- 贝塔nan
- 夏普比率0.71
- 胜率0.42
- 盈亏比1.29
- 收益波动率27.52%
- 最大回撤38.43%
bigcharts-data-start/{"__type":"tabs","__id":"bigchart-54a0c891d3a741c6aef59d93871340e7"}/bigcharts-data-end