克隆策略

    {"Description":"实验创建于2017/8/26","Summary":"","Graph":{"EdgesInternal":[{"DestinationInputPortId":"-67:input_1","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"-1542:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62:data"},{"DestinationInputPortId":"-1559:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62:data"},{"DestinationInputPortId":"-1549:input_data","SourceOutputPortId":"-1542:data"},{"DestinationInputPortId":"-1559:options_data","SourceOutputPortId":"-1549:data"},{"DestinationInputPortId":"-1542:features","SourceOutputPortId":"-67:data"},{"DestinationInputPortId":"-1549:features","SourceOutputPortId":"-67:data"}],"ModuleNodes":[{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-24","ModuleId":"BigQuantSpace.input_features.input_features-v1","ModuleParameters":[{"Name":"features","Value":"# #号开始的表示注释\n# 多个特征,每行一个,可以包含基础特征和衍生特征\nbuy_condition=where(mean(close_0,p1)>mean(close_0,p2),1,0)\nsell_condition=where(mean(close_0,p1)<mean(close_0,p2),1,0)\nup_band=ts_max(close_0,p1)\ndown_band=ts_min(close_0,p2)\natr=ta_atr(high_0/adjust_factor_0, low_0/adjust_factor_0, close_0/adjust_factor_0, p3)\natr_p=atr/close_0\n\n","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features_ds","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24","OutputType":null}],"UsePreviousResults":false,"moduleIdForCode":1,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-62","ModuleId":"BigQuantSpace.instruments.instruments-v2","ModuleParameters":[{"Name":"start_date","Value":"2019-11-01","ValueType":"Literal","LinkedGlobalParameter":"交易日期"},{"Name":"end_date","Value":"2021-01-01","ValueType":"Literal","LinkedGlobalParameter":"交易日期"},{"Name":"market","Value":"CN_STOCK_A","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_list","Value":"300308.SZA\n300750.SZA\n002594.SZA\n002851.SZA\n600498.SHA\n002281.SZA","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"max_count","Value":"0","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"rolling_conf","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":2,"IsPartOfPartialRun":null,"Comment":"预测数据,用于回测和模拟","CommentCollapsed":false},{"Id":"-1542","ModuleId":"BigQuantSpace.general_feature_extractor.general_feature_extractor-v7","ModuleParameters":[{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"before_start_days","Value":"60","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"-1542"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-1542"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-1542","OutputType":null}],"UsePreviousResults":false,"moduleIdForCode":7,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-1549","ModuleId":"BigQuantSpace.derived_feature_extractor.derived_feature_extractor-v3","ModuleParameters":[{"Name":"date_col","Value":"date","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_col","Value":"instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"drop_na","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"remove_extra_columns","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"user_functions","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"-1549"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-1549"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-1549","OutputType":null}],"UsePreviousResults":false,"moduleIdForCode":8,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-1559","ModuleId":"BigQuantSpace.trade.trade-v4","ModuleParameters":[{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"initialize","Value":"# 回测引擎:初始化函数,只执行一次\ndef bigquant_run(context):\n \n #=====================================以下为一些变量,比如时间窗口、权重之类,可在后续进行优化=====================#\n # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数\n context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))\n \n #这两个日期控制变量,纯粹是为了回测模块真实价格的存储时用到\n context.entry_pos_period = 10\n context.exit_pos_period = 10\n \n #定义持仓中的股票数量上限-未用 \n context.stock_count = 5\n \n #设置每只股票占用的最大资金比例-未用\n context.stock_weights = 1 / context.stock_count\n \n #定义第一次购入的资金比例:每支股票的基础比例为cash_for_buy的5%,试探性购入\n context.weight_1 = 0.2\n \n #定义第一次购入的资金裕度,避免转天开盘大涨,买不进去,或者成交不了。这里暂时没有考虑创业板,所以只设定为10%的涨幅\n context.weight_2 = 1.11\n \n #定义加仓和第一次购入的金额比值,当然随着买入的动作增加,cash_for_buy会越来越少-未用\n context.weight_3 = 2\n \n #定义加仓价格的增幅与波动率之间的比值-未用\n context.weight_add = 1\n \n #定义加仓价格的增幅与上次购买价格之间的比值\n context.weight_add_1 = (1+0.05)\n \n #定义加仓仓位是第一次买入的几倍\n context.weight_add_cash = 1\n \n #定义加仓的次数\n context.addtime = 1\n \n #定义止损价格的减幅与波动率之间的比值-未用\n context.weight_loss = 2\n \n #定义止损价格的增幅与上次购买价格之间的比值\n context.weight_loss_1 = (1-0.1)\n \n #==========================================================================================================#\n \n #读取数据模块传来的数据\n context.op_data = context.options['data'].read_df()\n \n #print(context.op_data)\n #context.op_data.to_csv('op_data.csv')\n \n \n #=============================================================================================================================\n #datalog记录的是数据库出来的原始数据,由于回测模块可能除权时会造成差别,因此再定义一个datalog_0用来记录回测模块选择“真实价格”时的价格\n context.datalog = pd.DataFrame(columns=[\"date\",\"instrument\",\"atr_p\", \"close\", \"up_band\", \"down_band\", \"buy_condition\", \"sell_condition\", \"buy\", \"add\", \"loss\", \"sell\"])\n \n context.datalog['date'] = context.op_data['date']\n context.datalog['instrument'] = context.op_data['instrument']\n context.datalog['atr_p'] = context.op_data['atr_p']\n context.datalog['close'] = context.op_data['close_0']\n context.datalog['up_band'] = context.op_data['up_band']\n context.datalog['down_band'] = context.op_data['down_band']\n context.datalog['buy_condition'] = context.op_data['buy_condition']\n context.datalog['sell_condition'] = context.op_data['sell_condition']\n \n context.datalog = context.datalog.set_index(['date','instrument'])\n #print('---------1-context.datalog', context.datalog)\n \n #==============================================================================================================================\n #定义一个存储除权价格的datalog_0,仅当回测模块选择“真实价格”时,该模块输出与datalog不同。close、up_band、down_band这些价格都去主函数里面去读。\n context.datalog_0 = pd.DataFrame(columns=[\"date\",\"instrument\",\"atr_p\",\"close\", \"up_band\", \"down_band\", \"buy_condition\", \"sell_condition\", \"buy\", \"add\", \"loss\", \"sell\"])\n \n context.datalog_0['date'] = context.op_data['date']\n context.datalog_0['instrument'] = context.op_data['instrument']\n context.datalog_0['atr_p'] = context.op_data['atr_p']\n context.datalog_0['buy_condition'] = context.op_data['buy_condition']\n context.datalog_0['sell_condition'] = context.op_data['sell_condition']\n \n context.datalog_0 = context.datalog_0.set_index(['date','instrument'])\n #print('---------0-context.datalog', context.datalog_0)\n \n #===============================================================================================================================\n #定义一个用来存储最后一次购买(开仓or加仓)价格的df\n context.lastbuy = pd.DataFrame(columns=[\"instrument\",\"date\", \"buy\", \"add\", \"price\", \"atr_p\", \"lossprice\"])\n context.lastbuy['instrument'] = context.instruments\n context.lastbuy = context.lastbuy.set_index('instrument')\n #print('----------*-context.lastbuy', context.lastbuy)\n \n #===============================================================================================================================\n #必须在最后把date设为index,否则定义datalog时就会报错\n context.op_data = context.op_data.set_index('date')\n \n \n \n \n \n \n \n \n \n \n \n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"handle_data","Value":"# 回测引擎:每日数据处理函数,每天执行一次\n#本策略思路:1)只有当MA10在MA60上时,才进行买卖操作;2)满足条件1时,用唐其安的短周期系统判断;\n#加入通过乖离率决定唐其安通道的灵敏度\ndef bigquant_run(context, data):\n \n \n # 获取今日的日期\n today = data.current_dt.strftime('%Y-%m-%d') \n # 通过positions对象,使用列表生成式的方法获取目前持仓的股票列表\n stock_hold_now = {e.symbol: p.amount * p.last_sale_price\n for e, p in context.perf_tracker.position_tracker.positions.items()} \n \n \n #print('*****************************************************************************')\n #print('*****************************************************************************')\n #print('------------Today is: ', today)\n #print('------------持仓状况: ', stock_hold_now)\n #print('------------股池为: ', context.instruments)\n \n #==========================================================================================================\n #查看今日的Portfolio,如果发生了买单,更新context.lastbuy中的价格\n stockname_hold_now = [equity.symbol for equity in context.portfolio.positions]\n #print('------------stockname_hold_now: ', stockname_hold_now)\n \n for i in stockname_hold_now:\n #print('------------持仓中,更改价格', i)\n \n sid = context.symbol(i)\n \n amount_today = context.portfolio.positions[sid].today_amount\n amount = context.portfolio.positions[sid].amount\n #print('------------amount_today: ', amount_today)\n #print('------------amount: ', amount)\n \n \n if amount_today>0 and amount>0 and amount_today!=amount :\n #加仓的情况\n context.lastbuy.loc[i, 'date'] = today\n context.lastbuy.loc[i, 'add'] += 1\n context.lastbuy.loc[i, 'buy'] = \"add\"\n #这里存储的是data.current中的价格,后期止损、加仓判断都用真实价格,所以回测模块选择真实价格!!!!!!!!!!\n context.lastbuy.loc[i, 'price'] = data.current(sid, 'open')\n \n #context.lastbuy.loc[i, 'atr_p'] = context.datalog.loc[(today, i),'atr_p']\n \n if amount_today>0 and amount>0 and amount_today==amount:\n #今天刚开仓\n context.lastbuy.loc[i, 'date'] = today\n context.lastbuy.loc[i, 'add'] = 0\n context.lastbuy.loc[i, 'buy'] = \"buy\"\n #这里存储的是data.current中的价格,后期止损、加仓判断都用真实价格,所以回测模块选择真实价格!!!!!!!!!!\n context.lastbuy.loc[i, 'price'] = data.current(sid, 'open')\n \n #context.lastbuy.loc[i, 'atr_p'] = context.datalog.loc[(today, i),'atr_p']\n \n #========================================================================================================== \n #print('------------********最后购买记录: ', context.lastbuy) \n \n \n \n #================================存储回测模块输出的真实价格(仅当模块中勾选)=======================\n for i in context.instruments:\n \n sid = context.symbol(i)\n #收盘价-回测模块会处理成真实价格\n price_close = round( data.current(sid, 'price'), 2)\n #price_close = data.current(sid, 'price')\n #price_close_2 = data.history(sid, 'close', 1, '1d')\n \n #print('------------股票名称-', i)\n #print('------------current今日价格-', price_close)\n #print('------------history今日价格-', price_close_2)\n \n \n #上轨和下轨-回测模块会处理成真实价格\n high_point = round( data.history(sid, 'close', context.entry_pos_period, '1d').max(), 2)\n low_point = round( data.history(sid, 'close', context.exit_pos_period, '1d').min(), 2)\n \n #print('------------股票: ', i)\n #print('------------今日价格-', price_close)\n #print('------------上轨价格-', high_point)\n #print('------------下轨价格-', low_point)\n \n \n context.datalog_0.loc[(today, i),'close'] = price_close\n context.datalog_0.loc[(today, i),'up_band'] = high_point\n context.datalog_0.loc[(today, i),'down_band'] = low_point\n #============================================================================================\n \n \n \n #print('------------context.instruments', context.instruments)\n \n # 记录用于买入股票的可用现金,因为是尾盘卖股票尾盘买股票,需要记录卖出的股票市值并在买入下单前更新可用现金;\n # 如果是早盘买尾盘卖,则卖出时不需更新可用现金,因为尾盘卖出股票所得现金无法使用\n cash_for_buy = context.portfolio.cash \n #print('------------cash for buy: ', cash_for_buy)\n \n \n try:\n buy_stock = context.daily_stock_buy[today] # 当日符合买入条件的股票\n #print('------------buy_stock: ', buy_stock)\n \n except:\n buy_stock=[] # 如果没有符合条件的股票,就设置为空\n #print('------------buy_stock: ', buy_stock)\n \n try:\n sell_stock = context.daily_stock_sell[today] # 当日符合卖出条件的股票\n #print('------------sell_stock: ', sell_stock)\n \n except:\n sell_stock=[] # 如果没有符合条件的股票,就设置为空\n #print('------------sell_stock: ', sell_stock)\n \n \n # 需要卖出的股票:已有持仓中符合卖出条件的股票\n stock_to_sell = [ i for i in stock_hold_now if i in sell_stock ]\n # 需要买入的股票:没有持仓且符合买入条件的股票\n stock_to_buy = [ i for i in buy_stock if i not in stock_hold_now ] \n # 需要调仓的股票:已有持仓且不符合卖出条件的股票\n #stock_to_adjust=[ i for i in stock_hold_now if i not in sell_stock ]\n \n \n ####¥¥¥策略的顺序:1、是否止损;2、是否出场;3、是否加仓;4、是否开仓¥¥¥####\n \n \n \n #========================================================================================================================\n #止损信号+出场信号—————价格止损、破下轨、大趋势的出场信号整合到一起,为了避免cash_for_buy更新出问题。\n \n for i in stockname_hold_now:\n #print('------------判断是否需要止损、破下轨、出场', i)\n \n sid = context.symbol(i)\n \n price_now = round( data.current(sid, 'price'), 2) #用收盘价判断\n #price_now = data.history(sid, 'close', 1, '1d') #用收盘价判断\n \n price_lastbuy = context.lastbuy.loc[i, 'price'] #上一次买入(开仓or加仓)的价格\n #上轨和下轨-回测模块会处理成真实价格,精确到2位小数点\n high_point = round( data.history(sid, 'close', context.entry_pos_period, '1d').max(), 2)\n low_point = round( data.history(sid, 'close', context.exit_pos_period, '1d').min(), 2)+0.01 #!!!!!!!!!!!!!!!!!!!\n \n #high_point = data.history(sid, 'close', context.entry_pos_period, '1d')\n #low_point = data.history(sid, 'close', context.exit_pos_period, '1d')\n \n \n #print('------------股票现在价格: ', price_now)\n #print('------------上次购买价格: ', price_lastbuy)\n #print('------------下轨价格: ', low_point)\n \n #stock_to_sell 是通过均线系统判断的,如果在stock_to_sell中,代表均线走坏,需要出场\n #止损还有其他两个触发条件:1)跌破上次建仓成本的一定止损比例;2)唐其安通道下轨\n if (i in stock_to_sell) and data.can_trade(sid):\n \n context.order_target_value(sid,0)# 全部卖出\n # 因为是尾盘卖股票尾盘买股票,需要记录卖出的股票市值并在买入下单前更新可用现金;\n # 如果是早盘买尾盘卖,则卖出时不需更新可用现金,因为尾盘卖出股票所得现金无法使用\n cash_for_buy += stock_hold_now[i]\n context.datalog.loc[(today, i),'sell'] = \"出场\" \n context.datalog_0.loc[(today, i),'sell'] = \"出场\"\n #标记止盈\n #print('----------¥¥明日出场:', i)\n \n \n if (i not in stock_to_sell) and ((price_now < price_lastbuy * context.weight_loss_1) or (price_now < low_point))==True and data.can_trade(sid):\n \n context.order_target_value(sid,0)# 全部卖出\n # 因为是尾盘卖股票尾盘买股票,需要记录卖出的股票市值并在买入下单前更新可用现金;\n # 如果是早盘买尾盘卖,则卖出时不需更新可用现金,因为尾盘卖出股票所得现金无法使用\n cash_for_buy += stock_hold_now[i]\n context.datalog.loc[(today, i),'loss'] = \"止损\" #止损包括价格止损or破下轨 \n context.datalog_0.loc[(today, i),'loss'] = \"止损\"\n #标记止盈\n #print('----------¥¥明日止损:', i)\n \n \n \n #加仓信号\n #print('------------判断是否需要加仓', i)\n #print('------------股票现在价格: ', price_now)\n #print('------------上次购买价格: ', price_lastbuy)\n \n if (price_now >= (price_lastbuy * context.weight_add_1)) and (context.lastbuy.loc[i, 'add'] < context.addtime) :\n #加仓的金额要比第一次购入要多,与第一次购入的比例为context.weight_add_cash\n #加仓和开仓,都是从cash_for_buy中抽取一定的比例进行购买,所以只要cash_for_add>0,就不存在没钱买的情况\n cash_for_add = cash_for_buy * context.weight_1 *context.weight_add_cash\n #判断cash是否够用\n if data.can_trade(sid) and cash_for_add>0:\n amount = math.floor(cash_for_add / price_now / 100) * 100\n context.order(sid, amount)\n cash_for_buy -= price_now * amount\n #标记开仓\n #print('------------stock_to_add:', i)\n #print('----------¥¥明日加仓:', i)\n\n context.datalog.loc[(today, i),'add'] = \"加仓\"\n context.datalog_0.loc[(today, i),'add'] = \"加仓\"\n \n \n elif data.can_trade(sid) and cash_for_add<0:\n context.datalog.loc[(today, i),'add'] = \"加仓-但没钱\"\n context.datalog_0.loc[(today, i),'add'] = \"加仓-但没钱\"\n \n #=================================================================================================================== \n \n #开仓信号,第一次购入 \n if len(stock_to_buy) > 0:\n cash_for_first = cash_for_buy * context.weight_1\n \n for instrument in stock_to_buy:\n sid = context.symbol(instrument) # 将标的转化为equity格式\n \n #收盘价-回测模块会处理成真实价格,精确到2位小数点\n price_now = round( data.current(sid, 'price'), 2)\n \n #上轨和下轨-回测模块会处理成真实价格,精确到2位小数点\n high_point = round( data.history(sid, 'close', context.entry_pos_period, '1d').max(), 2)-0.01 #!!!!!!!!!!!!!!!!!\n low_point = round( data.history(sid, 'close', context.exit_pos_period, '1d').min(), 2)\n \n #判断cash是否够用\n if data.can_trade(sid) and cash_for_first>0 and price_now>=high_point :\n amount = math.floor(cash_for_first / price_now / 100) * 100\n context.order(sid, amount)\n cash_for_buy -= price_now * amount\n #标记开仓\n #print('----------¥¥明日买入:', instrument)\n\n context.datalog.loc[(today, instrument),'buy'] = \"开仓\"\n context.datalog_0.loc[(today, instrument),'buy'] = \"开仓\" \n \n elif data.can_trade(sid) and cash_for_first<0:\n context.datalog.loc[(today, instrument),'buy'] = \"开仓-但没钱\"\n context.datalog_0.loc[(today, instrument),'buy'] = \"开仓-但没钱\"\n \n \n \n context.datalog.to_csv('datalogV12_后复权.csv')\n context.datalog_0.to_csv('datalogV12_真实价格(模块中勾选).csv')\n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n ","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"prepare","Value":"# 回测引擎:准备数据,只执行一次\ndef bigquant_run(context):\n # 加载预测数据\n df = context.options['data'].read_df()\n\n # 函数:求满足开仓条件的股票列表\n def open_pos_con(df):\n return list(df[df['buy_condition']>0].instrument)\n\n # 函数:求满足平仓条件的股票列表\n def close_pos_con(df):\n return list(df[df['sell_condition']>0].instrument)\n\n # 每日买入股票的数据框\n context.daily_stock_buy= df.groupby('date').apply(open_pos_con)\n # 每日卖出股票的数据框\n context.daily_stock_sell= df.groupby('date').apply(close_pos_con)","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"before_trading_start","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"volume_limit","Value":0.025,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"order_price_field_buy","Value":"open","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"order_price_field_sell","Value":"open","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"capital_base","Value":"1000000","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"auto_cancel_non_tradable_orders","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"data_frequency","Value":"daily","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"price_type","Value":"真实价格","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"product_type","Value":"股票","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"plot_charts","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"backtest_only","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"benchmark","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"-1559"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"options_data","NodeId":"-1559"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"history_ds","NodeId":"-1559"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"benchmark_ds","NodeId":"-1559"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"trading_calendar","NodeId":"-1559"}],"OutputPortsInternal":[{"Name":"raw_perf","NodeId":"-1559","OutputType":null}],"UsePreviousResults":false,"moduleIdForCode":9,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-67","ModuleId":"BigQuantSpace.params_feature_list.params_feature_list-v12","ModuleParameters":[{"Name":"params","Value":"{0:\"10\", \"p2\":\"60\",\"p3\":\"5\"}","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_1","NodeId":"-67"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-67","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":5,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-154","ModuleId":"BigQuantSpace.hyper_run.hyper_run-v1","ModuleParameters":[{"Name":"run","Value":"def bigquant_run(bq_graph, inputs):\n p1_list = [\"5\",\"10\"]\n p2_list = [\"30\",\"60\"]\n p3_list = [\"5\",\"10\"]\n params = [{\"p1\":i, \"p2\":j,\"p3\":k} for i,j,k in zip(p1_list, p2_list, p3_list)]\n parameters_list = []\n \n for param in params:\n parameters = {'m5.params':param}\n parameters_list.append({'parameters': parameters})\n\n def run(parameters):\n try:\n print(parameters)\n return g.run(parameters)\n except Exception as e:\n print('ERROR --------', e)\n return None\n \n results = T.parallel_map(run, parameters_list, max_workers=1, remote_run=False, silent=False)\n\n return results","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"run_now","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"bq_graph","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"bq_graph_port","NodeId":"-154"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_1","NodeId":"-154"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_2","NodeId":"-154"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_3","NodeId":"-154"}],"OutputPortsInternal":[{"Name":"result","NodeId":"-154","OutputType":null}],"UsePreviousResults":false,"moduleIdForCode":4,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true}],"SerializedClientData":"<?xml version='1.0' encoding='utf-16'?><DataV1 xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'><Meta /><NodePositions><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-24' Position='494,10,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-62' Position='78,4,200,200'/><NodePosition Node='-1542' Position='258,224,200,200'/><NodePosition Node='-1549' Position='336,356,200,200'/><NodePosition Node='-1559' Position='273,500,200,200'/><NodePosition Node='-67' Position='489,133,200,200'/><NodePosition Node='-154' Position='764,401,200,200'/></NodePositions><NodeGroups /></DataV1>"},"IsDraft":true,"ParentExperimentId":null,"WebService":{"IsWebServiceExperiment":false,"Inputs":[],"Outputs":[],"Parameters":[{"Name":"交易日期","Value":"","ParameterDefinition":{"Name":"交易日期","FriendlyName":"交易日期","DefaultValue":"","ParameterType":"String","HasDefaultValue":true,"IsOptional":true,"ParameterRules":[],"HasRules":false,"MarkupType":0,"CredentialDescriptor":null}}],"WebServiceGroupId":null,"SerializedClientData":"<?xml version='1.0' encoding='utf-16'?><DataV1 xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'><Meta /><NodePositions></NodePositions><NodeGroups /></DataV1>"},"DisableNodesUpdate":false,"Category":"user","Tags":[],"IsPartialRun":true}
    In [1]:
    # 本代码由可视化策略环境自动生成 2021年3月25日14:48
    # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
    
    
    # 回测引擎:初始化函数,只执行一次
    def m9_initialize_bigquant_run(context):
        
        #=====================================以下为一些变量,比如时间窗口、权重之类,可在后续进行优化=====================#
        # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
        context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
        
        #这两个日期控制变量,纯粹是为了回测模块真实价格的存储时用到
        context.entry_pos_period = 10
        context.exit_pos_period = 10
        
        #定义持仓中的股票数量上限-未用  
        context.stock_count = 5
        
        #设置每只股票占用的最大资金比例-未用
        context.stock_weights = 1 / context.stock_count
        
        #定义第一次购入的资金比例:每支股票的基础比例为cash_for_buy的5%,试探性购入
        context.weight_1 = 0.2
        
        #定义第一次购入的资金裕度,避免转天开盘大涨,买不进去,或者成交不了。这里暂时没有考虑创业板,所以只设定为10%的涨幅
        context.weight_2 = 1.11
        
        #定义加仓和第一次购入的金额比值,当然随着买入的动作增加,cash_for_buy会越来越少-未用
        context.weight_3 = 2
        
        #定义加仓价格的增幅与波动率之间的比值-未用
        context.weight_add = 1
        
        #定义加仓价格的增幅与上次购买价格之间的比值
        context.weight_add_1 = (1+0.05)
        
        #定义加仓仓位是第一次买入的几倍
        context.weight_add_cash = 1
        
        #定义加仓的次数
        context.addtime = 1
        
        #定义止损价格的减幅与波动率之间的比值-未用
        context.weight_loss = 2
        
        #定义止损价格的增幅与上次购买价格之间的比值
        context.weight_loss_1 = (1-0.1)
        
        #==========================================================================================================#
        
        #读取数据模块传来的数据
        context.op_data = context.options['data'].read_df()
        
        #print(context.op_data)
        #context.op_data.to_csv('op_data.csv')
        
        
        #=============================================================================================================================
        #datalog记录的是数据库出来的原始数据,由于回测模块可能除权时会造成差别,因此再定义一个datalog_0用来记录回测模块选择“真实价格”时的价格
        context.datalog = pd.DataFrame(columns=["date","instrument","atr_p", "close", "up_band", "down_band", "buy_condition", "sell_condition", "buy", "add", "loss", "sell"])
         
        context.datalog['date'] = context.op_data['date']
        context.datalog['instrument'] = context.op_data['instrument']
        context.datalog['atr_p'] = context.op_data['atr_p']
        context.datalog['close'] = context.op_data['close_0']
        context.datalog['up_band'] = context.op_data['up_band']
        context.datalog['down_band'] = context.op_data['down_band']
        context.datalog['buy_condition'] = context.op_data['buy_condition']
        context.datalog['sell_condition'] = context.op_data['sell_condition']
        
        context.datalog = context.datalog.set_index(['date','instrument'])
        #print('---------1-context.datalog', context.datalog)
        
        #==============================================================================================================================
        #定义一个存储除权价格的datalog_0,仅当回测模块选择“真实价格”时,该模块输出与datalog不同。close、up_band、down_band这些价格都去主函数里面去读。
        context.datalog_0 = pd.DataFrame(columns=["date","instrument","atr_p","close", "up_band", "down_band", "buy_condition", "sell_condition", "buy", "add", "loss", "sell"])
        
        context.datalog_0['date'] = context.op_data['date']
        context.datalog_0['instrument'] = context.op_data['instrument']
        context.datalog_0['atr_p'] = context.op_data['atr_p']
        context.datalog_0['buy_condition'] = context.op_data['buy_condition']
        context.datalog_0['sell_condition'] = context.op_data['sell_condition']
        
        context.datalog_0 = context.datalog_0.set_index(['date','instrument'])
        #print('---------0-context.datalog', context.datalog_0)
        
        #===============================================================================================================================
        #定义一个用来存储最后一次购买(开仓or加仓)价格的df
        context.lastbuy = pd.DataFrame(columns=["instrument","date", "buy", "add", "price", "atr_p", "lossprice"])
        context.lastbuy['instrument'] = context.instruments
        context.lastbuy = context.lastbuy.set_index('instrument')
        #print('----------*-context.lastbuy', context.lastbuy)
        
        #===============================================================================================================================
        #必须在最后把date设为index,否则定义datalog时就会报错
        context.op_data = context.op_data.set_index('date')
        
        
        
        
        
        
        
        
        
        
        
    
    # 回测引擎:每日数据处理函数,每天执行一次
    #本策略思路:1)只有当MA10在MA60上时,才进行买卖操作;2)满足条件1时,用唐其安的短周期系统判断;
    #加入通过乖离率决定唐其安通道的灵敏度
    def m9_handle_data_bigquant_run(context, data):
        
        
        # 获取今日的日期
        today = data.current_dt.strftime('%Y-%m-%d')  
        # 通过positions对象,使用列表生成式的方法获取目前持仓的股票列表
        stock_hold_now = {e.symbol: p.amount * p.last_sale_price
                          for e, p in context.perf_tracker.position_tracker.positions.items()} 
        
        
        #print('*****************************************************************************')
        #print('*****************************************************************************')
        #print('------------Today is: ', today)
        #print('------------持仓状况: ', stock_hold_now)
        #print('------------股池为: ', context.instruments)
        
        #==========================================================================================================
        #查看今日的Portfolio,如果发生了买单,更新context.lastbuy中的价格
        stockname_hold_now = [equity.symbol for equity in context.portfolio.positions]
        #print('------------stockname_hold_now: ', stockname_hold_now)
        
        for i in stockname_hold_now:
            #print('------------持仓中,更改价格', i)
            
            sid = context.symbol(i)
            
            amount_today = context.portfolio.positions[sid].today_amount
            amount = context.portfolio.positions[sid].amount
            #print('------------amount_today: ', amount_today)
            #print('------------amount: ', amount)
            
            
            if amount_today>0 and amount>0 and amount_today!=amount :
                #加仓的情况
                context.lastbuy.loc[i, 'date'] = today
                context.lastbuy.loc[i, 'add'] += 1
                context.lastbuy.loc[i, 'buy'] = "add"
                #这里存储的是data.current中的价格,后期止损、加仓判断都用真实价格,所以回测模块选择真实价格!!!!!!!!!!
                context.lastbuy.loc[i, 'price'] = data.current(sid, 'open')
                
                #context.lastbuy.loc[i, 'atr_p'] = context.datalog.loc[(today, i),'atr_p']
                
            if amount_today>0 and amount>0 and amount_today==amount:
                #今天刚开仓
                context.lastbuy.loc[i, 'date'] = today
                context.lastbuy.loc[i, 'add'] = 0
                context.lastbuy.loc[i, 'buy'] = "buy"
                #这里存储的是data.current中的价格,后期止损、加仓判断都用真实价格,所以回测模块选择真实价格!!!!!!!!!!
                context.lastbuy.loc[i, 'price'] = data.current(sid, 'open')
                
                #context.lastbuy.loc[i, 'atr_p'] = context.datalog.loc[(today, i),'atr_p']
                
        #==========================================================================================================      
        #print('------------********最后购买记录: ', context.lastbuy)        
            
        
        
        #================================存储回测模块输出的真实价格(仅当模块中勾选)=======================
        for i in context.instruments:
            
            sid = context.symbol(i)
            #收盘价-回测模块会处理成真实价格
            price_close = round( data.current(sid, 'price'), 2)
            #price_close = data.current(sid, 'price')
            #price_close_2 = data.history(sid, 'close', 1, '1d')
            
            #print('------------股票名称-', i)
            #print('------------current今日价格-', price_close)
            #print('------------history今日价格-', price_close_2)
            
            
            #上轨和下轨-回测模块会处理成真实价格
            high_point = round( data.history(sid, 'close', context.entry_pos_period, '1d').max(), 2)
            low_point = round( data.history(sid, 'close', context.exit_pos_period, '1d').min(), 2)
            
            #print('------------股票: ', i)
            #print('------------今日价格-', price_close)
            #print('------------上轨价格-', high_point)
            #print('------------下轨价格-', low_point)
            
            
            context.datalog_0.loc[(today, i),'close'] = price_close
            context.datalog_0.loc[(today, i),'up_band'] = high_point
            context.datalog_0.loc[(today, i),'down_band'] = low_point
        #============================================================================================
       
            
        
        #print('------------context.instruments', context.instruments)
        
        # 记录用于买入股票的可用现金,因为是尾盘卖股票尾盘买股票,需要记录卖出的股票市值并在买入下单前更新可用现金;
        # 如果是早盘买尾盘卖,则卖出时不需更新可用现金,因为尾盘卖出股票所得现金无法使用
        cash_for_buy = context.portfolio.cash   
        #print('------------cash for buy: ', cash_for_buy)
        
        
        try:
            buy_stock = context.daily_stock_buy[today]  # 当日符合买入条件的股票
            #print('------------buy_stock: ', buy_stock)
            
        except:
            buy_stock=[]  # 如果没有符合条件的股票,就设置为空
            #print('------------buy_stock: ', buy_stock)
        
        try:
            sell_stock = context.daily_stock_sell[today]  # 当日符合卖出条件的股票
            #print('------------sell_stock: ', sell_stock)
            
        except:
            sell_stock=[] # 如果没有符合条件的股票,就设置为空
            #print('------------sell_stock: ', sell_stock)
            
        
        # 需要卖出的股票:已有持仓中符合卖出条件的股票
        stock_to_sell = [ i for i in stock_hold_now if i in sell_stock ]
        # 需要买入的股票:没有持仓且符合买入条件的股票
        stock_to_buy = [ i for i in buy_stock if i not in stock_hold_now ]  
        # 需要调仓的股票:已有持仓且不符合卖出条件的股票
        #stock_to_adjust=[ i for i in stock_hold_now if i not in sell_stock ]
        
        
        ####¥¥¥策略的顺序:1、是否止损;2、是否出场;3、是否加仓;4、是否开仓¥¥¥####
        
            
            
        #========================================================================================================================
        #止损信号+出场信号—————价格止损、破下轨、大趋势的出场信号整合到一起,为了避免cash_for_buy更新出问题。
        
        for i in stockname_hold_now:
            #print('------------判断是否需要止损、破下轨、出场', i)
            
            sid = context.symbol(i)
            
            price_now = round( data.current(sid, 'price'), 2) #用收盘价判断
            #price_now = data.history(sid, 'close', 1, '1d') #用收盘价判断
            
            price_lastbuy = context.lastbuy.loc[i, 'price'] #上一次买入(开仓or加仓)的价格
            #上轨和下轨-回测模块会处理成真实价格,精确到2位小数点
            high_point = round( data.history(sid, 'close', context.entry_pos_period, '1d').max(), 2)
            low_point = round( data.history(sid, 'close', context.exit_pos_period, '1d').min(), 2)+0.01 #!!!!!!!!!!!!!!!!!!!
            
            #high_point = data.history(sid, 'close', context.entry_pos_period, '1d')
            #low_point = data.history(sid, 'close', context.exit_pos_period, '1d')
            
            
            #print('------------股票现在价格: ', price_now)
            #print('------------上次购买价格: ', price_lastbuy)
            #print('------------下轨价格: ', low_point)
            
            #stock_to_sell 是通过均线系统判断的,如果在stock_to_sell中,代表均线走坏,需要出场
            #止损还有其他两个触发条件:1)跌破上次建仓成本的一定止损比例;2)唐其安通道下轨
            if (i in stock_to_sell) and data.can_trade(sid):
                 
                context.order_target_value(sid,0)# 全部卖出
                # 因为是尾盘卖股票尾盘买股票,需要记录卖出的股票市值并在买入下单前更新可用现金;
                # 如果是早盘买尾盘卖,则卖出时不需更新可用现金,因为尾盘卖出股票所得现金无法使用
                cash_for_buy += stock_hold_now[i]
                context.datalog.loc[(today, i),'sell'] = "出场"    
                context.datalog_0.loc[(today, i),'sell'] = "出场"
                #标记止盈
                #print('----------¥¥明日出场:', i)
                
             
            if (i not in stock_to_sell) and ((price_now < price_lastbuy * context.weight_loss_1) or (price_now < low_point))==True and data.can_trade(sid):
               
                context.order_target_value(sid,0)# 全部卖出
                # 因为是尾盘卖股票尾盘买股票,需要记录卖出的股票市值并在买入下单前更新可用现金;
                # 如果是早盘买尾盘卖,则卖出时不需更新可用现金,因为尾盘卖出股票所得现金无法使用
                cash_for_buy += stock_hold_now[i]
                context.datalog.loc[(today, i),'loss'] = "止损"      #止损包括价格止损or破下轨  
                context.datalog_0.loc[(today, i),'loss'] = "止损"
                #标记止盈
                #print('----------¥¥明日止损:', i)
            
                                     
              
            #加仓信号
            #print('------------判断是否需要加仓', i)
            #print('------------股票现在价格: ', price_now)
            #print('------------上次购买价格: ', price_lastbuy)
            
            if (price_now >= (price_lastbuy * context.weight_add_1)) and (context.lastbuy.loc[i, 'add'] < context.addtime) :
                #加仓的金额要比第一次购入要多,与第一次购入的比例为context.weight_add_cash
                #加仓和开仓,都是从cash_for_buy中抽取一定的比例进行购买,所以只要cash_for_add>0,就不存在没钱买的情况
                cash_for_add = cash_for_buy * context.weight_1 *context.weight_add_cash
                #判断cash是否够用
                if data.can_trade(sid) and cash_for_add>0:
                    amount = math.floor(cash_for_add / price_now / 100) * 100
                    context.order(sid, amount)
                    cash_for_buy -= price_now * amount
                    #标记开仓
                    #print('------------stock_to_add:', i)
                    #print('----------¥¥明日加仓:', i)
    
                    context.datalog.loc[(today, i),'add'] = "加仓"
                    context.datalog_0.loc[(today, i),'add'] = "加仓"
                    
                    
                elif data.can_trade(sid) and cash_for_add<0:
                    context.datalog.loc[(today, i),'add'] = "加仓-但没钱"
                    context.datalog_0.loc[(today, i),'add'] = "加仓-但没钱"
                    
        #===================================================================================================================                
                
        #开仓信号,第一次购入            
        if len(stock_to_buy) > 0:
            cash_for_first = cash_for_buy * context.weight_1
                    
            for instrument in stock_to_buy:
                sid = context.symbol(instrument) # 将标的转化为equity格式
                
                #收盘价-回测模块会处理成真实价格,精确到2位小数点
                price_now = round( data.current(sid, 'price'), 2)
                
                #上轨和下轨-回测模块会处理成真实价格,精确到2位小数点
                high_point = round( data.history(sid, 'close', context.entry_pos_period, '1d').max(), 2)-0.01  #!!!!!!!!!!!!!!!!!
                low_point = round( data.history(sid, 'close', context.exit_pos_period, '1d').min(), 2)
                
                #判断cash是否够用
                if data.can_trade(sid) and cash_for_first>0 and price_now>=high_point :
                    amount = math.floor(cash_for_first / price_now / 100) * 100
                    context.order(sid, amount)
                    cash_for_buy -= price_now * amount
                    #标记开仓
                    #print('----------¥¥明日买入:', instrument)
    
                    context.datalog.loc[(today, instrument),'buy'] = "开仓"
                    context.datalog_0.loc[(today, instrument),'buy'] = "开仓"      
                           
                elif data.can_trade(sid) and cash_for_first<0:
                    context.datalog.loc[(today, instrument),'buy'] = "开仓-但没钱"
                    context.datalog_0.loc[(today, instrument),'buy'] = "开仓-但没钱"
                    
        
        
        context.datalog.to_csv('datalogV12_后复权.csv')
        context.datalog_0.to_csv('datalogV12_真实价格(模块中勾选).csv')
            
                
            
    
        
        
         
                    
            
        
            
            
            
                    
                 
                
                
                
                
        
    # 回测引擎:准备数据,只执行一次
    def m9_prepare_bigquant_run(context):
        # 加载预测数据
        df = context.options['data'].read_df()
    
        # 函数:求满足开仓条件的股票列表
        def open_pos_con(df):
            return list(df[df['buy_condition']>0].instrument)
    
        # 函数:求满足平仓条件的股票列表
        def close_pos_con(df):
            return list(df[df['sell_condition']>0].instrument)
    
        # 每日买入股票的数据框
        context.daily_stock_buy= df.groupby('date').apply(open_pos_con)
        # 每日卖出股票的数据框
        context.daily_stock_sell= df.groupby('date').apply(close_pos_con)
    
    g = T.Graph({
    
        'm1': 'M.input_features.v1',
        'm1.features': """# #号开始的表示注释
    # 多个特征,每行一个,可以包含基础特征和衍生特征
    buy_condition=where(mean(close_0,p1)>mean(close_0,p2),1,0)
    sell_condition=where(mean(close_0,p1)<mean(close_0,p2),1,0)
    up_band=ts_max(close_0,p1)
    down_band=ts_min(close_0,p2)
    atr=ta_atr(high_0/adjust_factor_0, low_0/adjust_factor_0, close_0/adjust_factor_0, p3)
    atr_p=atr/close_0
    
    """,
        'm1.m_cached': False,
    
        'm5': 'M.params_feature_list.v12',
        'm5.input_1': T.Graph.OutputPort('m1.data'),
        'm5.params': {0:"10", "p2":"60","p3":"5"},
    
        'm2': 'M.instruments.v2',
        'm2.start_date': T.live_run_param('trading_date', '2019-11-01'),
        'm2.end_date': T.live_run_param('trading_date', '2021-01-01'),
        'm2.market': 'CN_STOCK_A',
        'm2.instrument_list': """300308.SZA
    300750.SZA
    002594.SZA
    002851.SZA
    600498.SHA
    002281.SZA""",
        'm2.max_count': 0,
    
        'm7': 'M.general_feature_extractor.v7',
        'm7.instruments': T.Graph.OutputPort('m2.data'),
        'm7.features': T.Graph.OutputPort('m5.data'),
        'm7.start_date': '',
        'm7.end_date': '',
        'm7.before_start_days': 60,
        'm7.m_cached': False,
    
        'm8': 'M.derived_feature_extractor.v3',
        'm8.input_data': T.Graph.OutputPort('m7.data'),
        'm8.features': T.Graph.OutputPort('m5.data'),
        'm8.date_col': 'date',
        'm8.instrument_col': 'instrument',
        'm8.drop_na': False,
        'm8.remove_extra_columns': False,
        'm8.m_cached': False,
    
        'm9': 'M.trade.v4',
        'm9.instruments': T.Graph.OutputPort('m2.data'),
        'm9.options_data': T.Graph.OutputPort('m8.data'),
        'm9.start_date': '',
        'm9.end_date': '',
        'm9.initialize': m9_initialize_bigquant_run,
        'm9.handle_data': m9_handle_data_bigquant_run,
        'm9.prepare': m9_prepare_bigquant_run,
        'm9.volume_limit': 0.025,
        'm9.order_price_field_buy': 'open',
        'm9.order_price_field_sell': 'open',
        'm9.capital_base': 1000000,
        'm9.auto_cancel_non_tradable_orders': True,
        'm9.data_frequency': 'daily',
        'm9.price_type': '真实价格',
        'm9.product_type': '股票',
        'm9.plot_charts': True,
        'm9.backtest_only': False,
        'm9.benchmark': '',
    })
    
    # g.run({})
    
    
    def m4_run_bigquant_run(bq_graph, inputs):
        p1_list = ["5","10"]
        p2_list = ["30","60"]
        p3_list = ["5","10"]
        params = [{"p1":i, "p2":j,"p3":k} for i,j,k in zip(p1_list, p2_list, p3_list)]
        parameters_list = []
         
        for param in params:
            parameters = {'m5.params':param}
            parameters_list.append({'parameters': parameters})
    
        def run(parameters):
            try:
                print(parameters)
                return g.run(parameters)
            except Exception as e:
                print('ERROR --------', e)
                return None
            
        results = T.parallel_map(run, parameters_list, max_workers=1, remote_run=False, silent=False)
    
        return results
    
    m4 = M.hyper_run.v1(
        run=m4_run_bigquant_run,
        run_now=True,
        bq_graph=g
    )
    
    {'m5.params': {'p1': '5', 'p2': '30', 'p3': '5'}}
    
    • 收益率41.62%
    • 年化收益率35.88%
    • 基准收益率34.08%
    • 阿尔法0.14
    • 贝塔0.68
    • 夏普比率1.16
    • 胜率0.25
    • 盈亏比5.42
    • 收益波动率27.18%
    • 信息比率0.02
    • 最大回撤18.26%
    bigcharts-data-start/{"__type":"tabs","__id":"bigchart-33f5ddcc3269480fb12678f5a2c5ad16"}/bigcharts-data-end
    {'m5.params': {'p1': '10', 'p2': '60', 'p3': '10'}}
    
    • 收益率35.68%
    • 年化收益率30.85%
    • 基准收益率34.08%
    • 阿尔法0.11
    • 贝塔0.67
    • 夏普比率1.05
    • 胜率0.25
    • 盈亏比5.39
    • 收益波动率26.08%
    • 信息比率0.01
    • 最大回撤18.85%
    bigcharts-data-start/{"__type":"tabs","__id":"bigchart-467c6aec4537483088f625147692bf15"}/bigcharts-data-end