设置选股策略,为什么程序不按条件运行呢?

用户成长系列
标签: #<Tag:0x00007fcc0baa6a70>

(imledger) #1
克隆策略

    {"Description":"实验创建于2017/8/26","Summary":"","Graph":{"EdgesInternal":[{"DestinationInputPortId":"-228:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"-234:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"-123:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"-550:input_1","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"-575:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"-228:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"-235:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"-235:input_data","SourceOutputPortId":"-228:data"},{"DestinationInputPortId":"-253:data1","SourceOutputPortId":"-234:data"},{"DestinationInputPortId":"-582:data1","SourceOutputPortId":"-253:data"},{"DestinationInputPortId":"-253:data2","SourceOutputPortId":"-235:data"},{"DestinationInputPortId":"-234:features","SourceOutputPortId":"-270:data"},{"DestinationInputPortId":"-123:options_data","SourceOutputPortId":"-185:data_1"},{"DestinationInputPortId":"-123:benchmark","SourceOutputPortId":"-550:data_1"},{"DestinationInputPortId":"-575:features","SourceOutputPortId":"-570:data"},{"DestinationInputPortId":"-582:data2","SourceOutputPortId":"-575:data"},{"DestinationInputPortId":"-121:input_1","SourceOutputPortId":"-582:data"},{"DestinationInputPortId":"-185:input_1","SourceOutputPortId":"-297:data_1"},{"DestinationInputPortId":"-185:input_2","SourceOutputPortId":"-297:data_2"},{"DestinationInputPortId":"-185:input_3","SourceOutputPortId":"-297:data_3"},{"DestinationInputPortId":"-297:input_1","SourceOutputPortId":"-121:data"}],"ModuleNodes":[{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-8","ModuleId":"BigQuantSpace.instruments.instruments-v2","ModuleParameters":[{"Name":"start_date","Value":"2014-01-01","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"2019-01-01","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"market","Value":"CN_STOCK_A","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_list","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"max_count","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"rolling_conf","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":1,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-24","ModuleId":"BigQuantSpace.input_features.input_features-v1","ModuleParameters":[{"Name":"features","Value":"\nin_csi300_0\nin_csi500_0\nin_sse50_0\nindustry_sw_level1_0\nst_status_0\n\n# 选股条件\ncond1=(pb_lf_0<200)&\\\n(fs_roe_ttm_0>20)\n\n# 排序选股\ncond2=1\n\n# 进场条件\ncond3=1\n \n# 卖出条件\ncond4=(pb_lf_0>700)\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":true,"moduleIdForCode":3,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-228","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":"300","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"-228"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-228"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-228","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":15,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-234","ModuleId":"BigQuantSpace.use_datasource.use_datasource-v1","ModuleParameters":[{"Name":"datasource_id","Value":"industry_CN_STOCK_A","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"-234"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-234"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-234","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":5,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-253","ModuleId":"BigQuantSpace.join.join-v3","ModuleParameters":[{"Name":"on","Value":"date,instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"how","Value":"inner","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"sort","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data1","NodeId":"-253"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data2","NodeId":"-253"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-253","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":7,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-235","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":"user_functions","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"-235"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-235"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-235","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":16,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-270","ModuleId":"BigQuantSpace.input_features.input_features-v1","ModuleParameters":[{"Name":"features","Value":"concept\n","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features_ds","NodeId":"-270"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-270","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":10,"IsPartOfPartialRun":null,"Comment":"获取股票概念,并匹配选中的概念","CommentCollapsed":false},{"Id":"-123","ModuleId":"BigQuantSpace.trade.trade-v4","ModuleParameters":[{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"handle_data","Value":"#--------------------------------------------------------------------\n# 卖出条件\n#-------------------------------------------------------------------- \ndef sell_action(context, data):\n date = data.current_dt.strftime('%Y-%m-%d')\n hit_stop_stock = context.stock_hit_stop \n \n try:\n today_enter_stock = context.enter_daily_df.ix[date] \n except KeyError as e:\n today_enter_stock = []\n try:\n today_exit_stock = context.exit_daily_df.ix[date] \n except KeyError as e:\n today_exit_stock = []\n \n target_stock_to_buy = [i for i in context.selected_stock if i in today_enter_stock ] \n stock_hold_now = [equity.symbol for equity in context.portfolio.positions] # 当前持仓股票\n \n if context.trading_day_index % context.sell_frequency == 0:\n stock_to_sell = [i for i in stock_hold_now if i in today_exit_stock] # 要卖出的股票\n stock_buy_and_sell = [i for i in stock_to_sell if i in target_stock_to_buy]\n if context.is_sell_willbuy_stock == False: # 要买入的股票不卖出,但该票也不再买入\n stock_to_sell.extend(hit_stop_stock) # 将触发个股风控的股票融入到卖出票池\n stock_to_sell = [i for i in stock_to_sell if i not in stock_buy_and_sell] # 进行更新而已\n elif context.is_sell_willbuy_stock == True: # 要买入的股票依然要卖出,该票不再买入\n stock_to_sell.extend(hit_stop_stock)\n \n # 买入时需要过滤的股票\n context.cannot_buy_stock = stock_buy_and_sell\n \n for stock in stock_to_sell:\n if data.can_trade(context.symbol(stock)):\n context.order_target_percent(context.symbol(stock), 0) \n\n\n#--------------------------------------------------------------------\n# 买入条件\n#-------------------------------------------------------------------- \ndef buy_action(context, data):\n date = data.current_dt.strftime('%Y-%m-%d')\n \n try:\n today_enter_stock = context.enter_daily_df.ix[date] \n except KeyError as e:\n today_enter_stock = []\n try:\n today_exit_stock = context.exit_daily_df.ix[date] \n except KeyError as e:\n today_exit_stock = []\n \n target_stock_to_buy = [i for i in context.selected_stock if i in today_enter_stock] \n target_stock_to_buy = [s for s in target_stock_to_buy if s not in context.cannot_buy_stock] # 进行更新,不能买入的股票要过滤\n \n stock_hold_now = [equity.symbol for equity in context.portfolio.positions] # 当前持仓股票\n \n # 确定股票权重\n if context.order_weight_method == 'equal_weight':\n equal_weight = 1 / context.max_stock_count\n \n portfolio_value = context.portfolio.portfolio_value\n position_current_value = {pos.sid: pos.amount* pos.last_sale_price for i,pos in context.portfolio.positions.items()}\n \n # 买入\n if context.trading_day_index % context.buy_frequency == 0:\n if len(stock_hold_now) >= context.max_stock_count:\n return \n \n today_buy_count = 0\n if context.trade_mode == '轮动':\n for s in target_stock_to_buy:\n if today_buy_count + len(stock_hold_now) >= context.max_stock_count: # 超出最大持仓数量\n break\n if data.can_trade(context.symbol(s)):\n order_target_percent(context.symbol(s), equal_weight)\n today_buy_count += 1\n else:\n if context.can_duplication_buy == True: # 可以重复买入,多一份买入\n for s in target_stock_to_buy:\n if today_buy_count + len(stock_hold_now) >= context.max_stock_count: # 超出最大持仓数量\n break\n \n if data.can_trade(context.symbol(s)):\n if context.symbol(s) in position_current_weight:\n curr_value = position_current_value.get(context.symbol(s)) \n order_value(context.symbol(s), min(context.max_stock_weight * portfolio_value - curr_value, equal_weight*portfolio_value))\n else:\n order_value(context.symbol(s), equal_weight*portfolio_value)\n today_buy_count += 1\n\n elif context.can_duplication_buy == False: # 不可以重复买入,不买\n for s in target_stock_to_buy:\n if today_buy_count + len(stock_hold_now) >= context.max_stock_count: # 超出最大持仓数量\n break\n if s in stock_hold_now:\n continue\n else:\n if data.can_trade(context.symbol(s)):\n order_target_percent(context.symbol(s), equal_weight)\n today_buy_count += 1\n\n \n#--------------------------------------------------------------------\n# 风控体系\n#-------------------------------------------------------------------- \ndef market_risk_manage(context, data):\n \"\"\"大盘风控\"\"\"\n date = data.current_dt.strftime('%Y-%m-%d')\n if type(context.index_signal_data) == pd.DataFrame:\n current_signal = context.index_signal_data.ix[date]['signal']\n if current_signal == 'short': \n stock_hold_now = [equity.symbol for equity in context.portfolio.positions] \n # 平掉所有股票\n for stock in stock_hold_now:\n if data.can_trade(context.symbol(stock)):\n context.order_target_percent(context.symbol(stock), 0) \n print('大盘出现止损信号, 平掉全部仓位,并关闭交易!')\n context.market_risk_signal = 'short'\n else:\n context.market_risk_signal = 'long'\n\n \n \ndef strategy_risk_manage(context, data):\n \"\"\"策略风控\"\"\"\n if context.strategy_risk_conf == []: # 没有设置策略风控\n context.strategy_risk_signal = 'long'\n \n else:\n for rm in context.strategy_risk_conf:\n if rm['method'] == 'strategy_percent_stopwin':\n pct = rm['params']['percent']\n portfolio_value = context.portfolio.portfolio_value \n if portfolio_value / context.capital_base - 1 > pct: \n stock_hold_now = [equity.symbol for equity in context.portfolio.positions] \n # 平掉所有股票\n for stock in stock_hold_now:\n if data.can_trade(context.symbol(stock)):\n context.order_target_percent(context.symbol(stock), 0) \n print('策略出现止盈信号, 平掉全部仓位,并关闭交易!')\n context.strategy_risk_signal = 'short' \n \n \n if rm['method'] == 'strategy_percent_stoploss':\n pct = rm['params']['percent']\n portfolio_value = context.portfolio.portfolio_value \n if portfolio_value / context.capital_base -1 < pct:\n stock_hold_now = [equity.symbol for equity in context.portfolio.positions] \n # 平掉所有股票\n for stock in stock_hold_now:\n if data.can_trade(context.symbol(stock)):\n context.order_target_percent(context.symbol(stock), 0) \n print('策略出现止损信号, 平掉全部仓位,并关闭交易!')\n context.strategy_risk_signal = 'short'\n\n \ndef stock_risk_manage(context, data):\n \"\"\"个股风控\"\"\"\n position_current_pnl = {pos.sid: (pos.last_sale_price-pos.cost_basis)/pos.cost_basis for i,pos in context.portfolio.positions.items()}\n \n for rm in context.stock_risk_conf:\n params_pct = rm['params']['percent']\n if rm['method'] == 'stock_percent_stopwin':\n for sid,pnl_pct in position_current_pnl.items(): \n if pnl_pct > params_pct:\n context.stock_hit_stop.append(sid.symbol)\n \n if rm['method'] == 'stock_percent_stoploss':\n for sid,pnl_pct in position_current_pnl.items():\n if pnl_pct < params_pct:\n context.stock_hit_stop.append(sid.symbol)\n\n\n\n\n# 回测引擎:每日数据处理函数,每天执行一次\ndef bigquant_run(context, data):\n \"\"\"每日运行策略逻辑\"\"\"\n market_risk_manage(context, data)\n strategy_risk_manage(context, data)\n \n if context.market_risk_signal == 'short': return\n if context.strategy_risk_signal == 'short': return\n\n stock_risk_manage(context, data)\n \n sell_action(context, data)\n buy_action(context, data)\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"prepare","Value":"# 回测引擎:准备数据,只执行一次\ndef bigquant_run(context):\n \n load_data = context.options['data'].read_pickle()\n context.signal_daily_stock = load_data['df1'].groupby('date').apply(lambda x:list(x.instrument))\n context.enter_daily_df = load_data['df2'].groupby('date').apply(lambda x:list(x.instrument))\n context.exit_daily_df = load_data['df3'].groupby('date').apply(lambda x:list(x.instrument))\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"initialize","Value":"\ndef prepare_index_data(context):\n \"\"\"准备指数数据\"\"\"\n if context.market_risk_conf != []:\n if len(context.market_risk_conf) == 1:\n index_code = context.market_risk_conf[0]['params']['index_code']\n start_date = '2005-01-01'\n end_date = context.end_date\n index_data = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code], start_date=start_date, end_date=end_date).set_index('date')\n \n if context.market_risk_conf[0]['method'] == 'market_ma_stoploss':\n ma_periods = int(context.market_risk_conf[0]['params']['ma_periods'])\n index_data['ma_%s'%ma_periods] = index_data['close'].rolling(ma_periods).mean()\n index_data['signal'] = np.where(index_data['close'] > index_data['ma_%s'%ma_periods], 'long', 'short')\n\n elif context.market_risk_conf[0]['method'] == 'market_fallrange_stoploss':\n days = context.market_risk_conf[0]['params']['days']\n fallrange = context.market_risk_conf[0]['params']['fallrange']\n index_data['signal'] = np.where(index_data['close']/index_data['close'].shift(days)-1 <= fallrange, 'long', 'short')\n context.index_signal_data = index_data \n \n if len(context.market_risk_conf) == 2:\n start_date = '2005-01-01'\n end_date = context.end_date \n if context.market_risk_conf[0]['method'] == 'market_ma_stoploss': \n index_code_1 = context.market_risk_conf[0]['params']['index_code']\n index_data_1 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_1], start_date=start_date, end_date=end_date).set_index('date')\n ma_periods = int(context.market_risk_conf[0]['params']['ma_periods'])\n \n index_code_2 = context.market_risk_conf[1]['params']['index_code']\n index_data_2 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_2], start_date=start_date, end_date=end_date).set_index('date')\n days = context.market_risk_conf[1]['params']['days']\n fallrange = context.market_risk_conf[1]['params']['fallrange']\n else:\n index_code_1 = context.market_risk_conf[1]['params']['index_code']\n index_data_1 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_1], start_date=start_date, end_date=end_date).set_index('date')\n ma_periods = int(context.market_risk_conf[1]['params']['ma_periods'])\n \n index_code_2 = context.market_risk_conf[0]['params']['index_code']\n index_data_2 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_2], start_date=start_date, end_date=end_date).set_index('date')\n days = context.market_risk_conf[0]['params']['days']\n fallrange = context.market_risk_conf[0]['params']['fallrange'] \n \n index_data_1['ma_%s'%ma_periods] = index_data_1['close'].rolling(ma_periods).mean()\n index_data_1['signal_1'] = np.where(index_data_1['close'] > index_data_1['ma_%s'%ma_periods], 1, 0)\n signal_1 = index_data_1[['signal_1']].reset_index() \n index_data_2['signal_2'] = np.where(index_data_2['close']/index_data_2['close'].shift(days)-1 <= fallrange, 1, 0)\n signal_2 = index_data_2[['signal_2']].reset_index()\n signal = pd.merge(signal_1,signal_2).set_index('date')\n signal['signal_sum'] = signal['signal_1'] + signal['signal_2']\n signal['signal'] = np.where(signal['signal_sum']>0,'long','short') \n context.index_signal_data = signal\n else:\n context.index_signal_data = None \n\ndef bigquant_run(context):\n context.set_commission(PerOrder(buy_cost=0.003, sell_cost=0.004, min_cost=5))\n \n context.trade_mode = '择时'\n\n if context.trade_mode == '轮动':\n context.buy_frequency = 1\n context.sell_frequency = 1\n context.rebalance_periods = 1 # 调仓周期\n context.max_stock_count = 5 # 最大持仓股票数量\n context.order_weight_method = 'equal_weight' # 买入方式\n context.is_sell_willbuy_stock = False # 卖出欲买进股票 \n else:\n # 买入条件参数\n context.stock_select_frequency = 1 # 选股频率\n context.order_weight_method = 'equal_weight' # 买入方式\n context.buy_frequency = 2 # 买入频率\n context.can_duplication_buy = False # 是否可重复买入\n context.max_stock_count = 5 # 最大持仓股票数量\n context.max_stock_weight = 1 # 个股最大持仓比重\n\n # 卖出条件参数\n context.sell_frequency = 10 # 卖出频率\n context.is_sell_willbuy_stock = False # 卖出欲买进股票 \n\n # 风控参数 \n context.stock_risk_conf = [{'method':'stock_percent_stopwin', 'params':{'percent': 0.2}}] # 支持多选 无:[]\n context.strategy_risk_conf = [] # 支持多选 无:[]\n context.market_risk_conf = [] # 支持多选, 无: []\n \n prepare_index_data(context)\n slippage_type = 'price'\n from zipline.finance.slippage import SlippageModel\n class FixedPriceSlippage(SlippageModel):\n # 指定初始化函数\n def __init__(self, spreads, price_field_buy, price_field_sell):\n # 存储spread的字典,用股票代码作为key\n self.spreads = spreads\n self._price_field_buy = price_field_buy\n self._price_field_sell = price_field_sell\n def process_order(self, data, order, bar_volume=0, trigger_check_price=0):\n if order.limit is None:\n price_field = self._price_field_buy if order.amount > 0 else self._price_field_sell\n price_base = data.current(order.asset, price_field)\n if slippage_type == 'price':\n price = price_base + (self.spreads / 2) if order.amount > 0 else price_base - (self.spreads / 2)\n else:\n price = price_base * (1.0 + self.spreads / 2) if order.amount > 0 else price_base * (1.0 - self.spreads / 2)\n else:\n price = order.limit\n # 返回希望成交的价格和数量\n return (price, order.amount)\n # 设置price_field\n fix_slippage = FixedPriceSlippage(price_field_buy='open', price_field_sell='open', spreads=0.02)\n context.set_slippage(us_equities=fix_slippage)","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"before_trading_start","Value":"# 回测引擎:每个单位时间开始前调用一次,即每日开盘前调用一次。\ndef bigquant_run(context, data):\n \n \"\"\"每日盘前更新股票池\"\"\"\n frequency = context.rebalance_periods if context.trade_mode == '轮动' else context.stock_select_frequency\n if context.trading_day_index % frequency == 0:\n date = data.current_dt.strftime('%Y-%m-%d')\n try:\n context.selected_stock = context.signal_daily_stock[date] \n except KeyError as e:\n context.selected_stock = []\n \n \"\"\"初始化风控参数\"\"\"\n context.strategy_risk_signal = 'long'\n context.market_risk_signal = 'long' \n context.stock_hit_stop = []\n context.cannot_buy_stock = []\n","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":"100000","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}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"-123"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"options_data","NodeId":"-123"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"history_ds","NodeId":"-123"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"benchmark","NodeId":"-123"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"trading_calendar","NodeId":"-123"}],"OutputPortsInternal":[{"Name":"raw_perf","NodeId":"-123","OutputType":null}],"UsePreviousResults":false,"moduleIdForCode":4,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-185","ModuleId":"BigQuantSpace.cached.cached-v3","ModuleParameters":[{"Name":"run","Value":"# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端\ndef bigquant_run(input_1, input_2, input_3):\n df1 = input_1.read_df()\n df2 = input_2.read_df()\n df3 = input_3.read_df()\n \n df = {'df1':df1,'df2':df2,'df3':df3}\n ds = DataSource.write_pickle(df)\n return Outputs(data_1=ds)\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"post_run","Value":"# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。\ndef bigquant_run(outputs):\n return outputs\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_ports","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"params","Value":"{}","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"output_ports","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_1","NodeId":"-185"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_2","NodeId":"-185"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_3","NodeId":"-185"}],"OutputPortsInternal":[{"Name":"data_1","NodeId":"-185","OutputType":null},{"Name":"data_2","NodeId":"-185","OutputType":null},{"Name":"data_3","NodeId":"-185","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":17,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-550","ModuleId":"BigQuantSpace.cached.cached-v3","ModuleParameters":[{"Name":"run","Value":"# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端\ndef bigquant_run(input_1, input_index):\n # 示例代码如下。在这里编写您的代码\n start_date=input_1.read_pickle()['start_date']\n end_date=input_1.read_pickle()['end_date']\n df = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[input_index],start_date=start_date,end_date=end_date,fields=['close'])\n data_1 = DataSource.write_df(df)\n return Outputs(data_1=data_1, data_2=None, data_3=None)\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"post_run","Value":"# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。\ndef bigquant_run(outputs):\n return outputs\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_ports","Value":"input_1","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"params","Value":"{'input_index':'000300.HIX'}","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"output_ports","Value":"data_1","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_1","NodeId":"-550"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_2","NodeId":"-550"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_3","NodeId":"-550"}],"OutputPortsInternal":[{"Name":"data_1","NodeId":"-550","OutputType":null},{"Name":"data_2","NodeId":"-550","OutputType":null},{"Name":"data_3","NodeId":"-550","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":8,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-570","ModuleId":"BigQuantSpace.input_features.input_features-v1","ModuleParameters":[{"Name":"features","Value":"suspended","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features_ds","NodeId":"-570"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-570","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":6,"IsPartOfPartialRun":null,"Comment":"获取股票停牌数据","CommentCollapsed":false},{"Id":"-575","ModuleId":"BigQuantSpace.use_datasource.use_datasource-v1","ModuleParameters":[{"Name":"datasource_id","Value":"stock_status_CN_STOCK_A","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"-575"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-575"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-575","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":19,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-582","ModuleId":"BigQuantSpace.join.join-v3","ModuleParameters":[{"Name":"on","Value":"date,instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"how","Value":"inner","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"sort","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data1","NodeId":"-582"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data2","NodeId":"-582"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-582","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":20,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-297","ModuleId":"BigQuantSpace.cached.cached-v3","ModuleParameters":[{"Name":"run","Value":"# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端\ndef bigquant_run(input_1, input_2, input_3):\n # 示例代码如下。在这里编写您的代码\n df = input_1.read_df()\n # 缺失值处理\n # if len(df)!=0:\n # df.dropna(inplace=True)\n \n # 选股条件\n if len(df)!=0:\n df_filter1 = df[df['cond1']>0]\n else:\n df_filter1 = df\n \n # 指标排序\n if len(df_filter1)!=0:\n df_filter2 = df_filter1.groupby('date').apply(lambda x:x.sort_values(by=['cond2'],ascending=True))\n else:\n df_filter2 = df_filter1\n \n #输出条件过滤股票池\n data_1 = DataSource.write_df(df_filter2)\n\n \n # 进场条件\n if len(df)!=0:\n df_buy = df[df['cond3']>0]\n else:\n df_buy = df\n # 输出满足进场条件的股票池\n data_2 = DataSource.write_df(df_buy)\n\n \n # 出场条件\n if len(df)!=0:\n df_sell = df[df['cond4']>0]\n else:\n df_sell = df\n # 输出满足出场条件的股票池\n data_3 = DataSource.write_df(df_sell) \n \n return Outputs(data_1=data_1, data_2=data_2, data_3=data_3)\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"post_run","Value":"# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。\ndef bigquant_run(outputs):\n return outputs\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_ports","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"params","Value":"{}","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"output_ports","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_1","NodeId":"-297"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_2","NodeId":"-297"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_3","NodeId":"-297"}],"OutputPortsInternal":[{"Name":"data_1","NodeId":"-297","OutputType":null},{"Name":"data_2","NodeId":"-297","OutputType":null},{"Name":"data_3","NodeId":"-297","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":22,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-121","ModuleId":"BigQuantSpace.stockpool_select.stockpool_select-v6","ModuleParameters":[{"Name":"self_instruments","Value":"[]","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_concepts","Value":"[]","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_industrys","Value":"[360000,710000,220000,460000,370000,330000,340000,720000,240000,630000,280000,420000,510000,640000,610000,620000,650000,230000,410000,350000,490000,110000,210000,480000,730000,450000,270000,430000]","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_indexs","Value":"['沪深300']","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_st","Value":"过滤","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_suspend","Value":"过滤","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_1","NodeId":"-121"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-121","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":2,"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-8' Position='473,-148,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-24' Position='697,-231,200,200'/><NodePosition Node='-228' Position='479,-22,200,200'/><NodePosition Node='-234' Position='145,-30,200,200'/><NodePosition Node='-253' Position='341,161,200,200'/><NodePosition Node='-235' Position='483,70,200,200'/><NodePosition Node='-270' Position='124,-149,200,200'/><NodePosition Node='-123' Position='563,687,200,200'/><NodePosition Node='-185' Position='454,575,200,200'/><NodePosition Node='-550' Position='878,511,200,200'/><NodePosition Node='-570' Position='960,-137,200,200'/><NodePosition Node='-575' Position='840,-16,200,200'/><NodePosition Node='-582' Position='557,241,200,200'/><NodePosition Node='-297' Position='453,455,200,200'/><NodePosition Node='-121' Position='457.305419921875,355.8680725097656,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 [ ]:
    # 本代码由可视化策略环境自动生成 2019年1月27日 19:01
    # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
    
    
    # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
    def m8_run_bigquant_run(input_1, input_index):
        # 示例代码如下。在这里编写您的代码
        start_date=input_1.read_pickle()['start_date']
        end_date=input_1.read_pickle()['end_date']
        df = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[input_index],start_date=start_date,end_date=end_date,fields=['close'])
        data_1 = DataSource.write_df(df)
        return Outputs(data_1=data_1, data_2=None, data_3=None)
    
    # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    def m8_post_run_bigquant_run(outputs):
        return outputs
    
    # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
    def m22_run_bigquant_run(input_1, input_2, input_3):
        # 示例代码如下。在这里编写您的代码
        df = input_1.read_df()
        # 缺失值处理
        # if len(df)!=0:
        #     df.dropna(inplace=True)
            
        # 选股条件
        if len(df)!=0:
            df_filter1 = df[df['cond1']>0]
        else:
            df_filter1 = df
        
        # 指标排序
        if len(df_filter1)!=0:
            df_filter2 = df_filter1.groupby('date').apply(lambda x:x.sort_values(by=['cond2'],ascending=True))
        else:
            df_filter2 = df_filter1
        
        #输出条件过滤股票池
        data_1 = DataSource.write_df(df_filter2)
    
        
        # 进场条件
        if len(df)!=0:
            df_buy = df[df['cond3']>0]
        else:
            df_buy = df
        # 输出满足进场条件的股票池
        data_2 = DataSource.write_df(df_buy)
    
        
        # 出场条件
        if len(df)!=0:
            df_sell = df[df['cond4']>0]
        else:
            df_sell = df
        # 输出满足出场条件的股票池
        data_3 = DataSource.write_df(df_sell)    
        
        return Outputs(data_1=data_1, data_2=data_2, data_3=data_3)
    
    # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    def m22_post_run_bigquant_run(outputs):
        return outputs
    
    # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
    def m17_run_bigquant_run(input_1, input_2, input_3):
        df1 = input_1.read_df()
        df2 = input_2.read_df()
        df3 = input_3.read_df()
        
        df = {'df1':df1,'df2':df2,'df3':df3}
        ds = DataSource.write_pickle(df)
        return Outputs(data_1=ds)
    
    # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    def m17_post_run_bigquant_run(outputs):
        return outputs
    
    #--------------------------------------------------------------------
    # 卖出条件
    #--------------------------------------------------------------------     
    def sell_action(context, data):
        date = data.current_dt.strftime('%Y-%m-%d')
        hit_stop_stock = context.stock_hit_stop 
        
        try:
            today_enter_stock = context.enter_daily_df.ix[date] 
        except KeyError as e:
            today_enter_stock = []
        try:
            today_exit_stock = context.exit_daily_df.ix[date] 
        except KeyError as e:
            today_exit_stock = []
            
        target_stock_to_buy = [i for i in  context.selected_stock  if i in today_enter_stock ]   
        stock_hold_now = [equity.symbol for equity in context.portfolio.positions] # 当前持仓股票
        
        if  context.trading_day_index % context.sell_frequency == 0:
            stock_to_sell = [i for i in stock_hold_now if i in today_exit_stock] # 要卖出的股票
            stock_buy_and_sell = [i for i in stock_to_sell if i in target_stock_to_buy]
            if context.is_sell_willbuy_stock == False: # 要买入的股票不卖出,但该票也不再买入
                stock_to_sell.extend(hit_stop_stock) # 将触发个股风控的股票融入到卖出票池
                stock_to_sell = [i for i in stock_to_sell if i not in stock_buy_and_sell] # 进行更新而已
            elif context.is_sell_willbuy_stock == True: # 要买入的股票依然要卖出,该票不再买入
                stock_to_sell.extend(hit_stop_stock)
            
            # 买入时需要过滤的股票
            context.cannot_buy_stock = stock_buy_and_sell
                
            for stock in stock_to_sell:
                if data.can_trade(context.symbol(stock)):
                    context.order_target_percent(context.symbol(stock), 0) 
    
    
    #--------------------------------------------------------------------
    # 买入条件
    #--------------------------------------------------------------------     
    def buy_action(context, data):
        date = data.current_dt.strftime('%Y-%m-%d')
        
        try:
            today_enter_stock = context.enter_daily_df.ix[date] 
        except KeyError as e:
            today_enter_stock = []
        try:
            today_exit_stock = context.exit_daily_df.ix[date] 
        except KeyError as e:
            today_exit_stock = []
        
        target_stock_to_buy = [i for i in  context.selected_stock if i in today_enter_stock]  
        target_stock_to_buy = [s for s in target_stock_to_buy if s not in context.cannot_buy_stock] # 进行更新,不能买入的股票要过滤
        
        stock_hold_now = [equity.symbol for equity in context.portfolio.positions] # 当前持仓股票
        
        # 确定股票权重
        if context.order_weight_method == 'equal_weight':
            equal_weight =  1 / context.max_stock_count
            
        portfolio_value = context.portfolio.portfolio_value
        position_current_value = {pos.sid: pos.amount* pos.last_sale_price for i,pos in context.portfolio.positions.items()}
        
        # 买入
        if  context.trading_day_index % context.buy_frequency == 0:
            if len(stock_hold_now) >= context.max_stock_count:
                return 
            
            today_buy_count = 0
            if context.trade_mode == '轮动':
                for s in target_stock_to_buy:
                    if today_buy_count + len(stock_hold_now) >= context.max_stock_count: # 超出最大持仓数量
                        break
                    if data.can_trade(context.symbol(s)):
                        order_target_percent(context.symbol(s), equal_weight)
                        today_buy_count += 1
            else:
                if  context.can_duplication_buy == True: # 可以重复买入,多一份买入
                    for s in target_stock_to_buy:
                        if today_buy_count + len(stock_hold_now) >= context.max_stock_count: # 超出最大持仓数量
                            break
                            
                        if data.can_trade(context.symbol(s)):
                            if context.symbol(s) in position_current_weight:
                                curr_value = position_current_value.get(context.symbol(s)) 
                                order_value(context.symbol(s), min(context.max_stock_weight * portfolio_value - curr_value, equal_weight*portfolio_value))
                            else:
                                order_value(context.symbol(s), equal_weight*portfolio_value)
                            today_buy_count += 1
    
                elif  context.can_duplication_buy == False: # 不可以重复买入,不买
                  for s in target_stock_to_buy:
                    if today_buy_count + len(stock_hold_now) >= context.max_stock_count: # 超出最大持仓数量
                        break
                    if s in stock_hold_now:
                        continue
                    else:
                        if data.can_trade(context.symbol(s)):
                            order_target_percent(context.symbol(s), equal_weight)
                            today_buy_count += 1
    
                            
    #--------------------------------------------------------------------
    # 风控体系
    #--------------------------------------------------------------------                         
    def market_risk_manage(context, data):
        """大盘风控"""
        date = data.current_dt.strftime('%Y-%m-%d')
        if type(context.index_signal_data) == pd.DataFrame:
            current_signal = context.index_signal_data.ix[date]['signal']
            if current_signal == 'short': 
                stock_hold_now = [equity.symbol for equity in context.portfolio.positions]  
                # 平掉所有股票
                for stock in stock_hold_now:
                    if data.can_trade(context.symbol(stock)):
                        context.order_target_percent(context.symbol(stock), 0) 
                print('大盘出现止损信号, 平掉全部仓位,并关闭交易!')
                context.market_risk_signal = 'short'
        else:
            context.market_risk_signal = 'long'
    
            
            
    def strategy_risk_manage(context, data):
        """策略风控"""
        if context.strategy_risk_conf == []: # 没有设置策略风控
            context.strategy_risk_signal = 'long'
        
        else:
            for rm in context.strategy_risk_conf:
                if rm['method'] == 'strategy_percent_stopwin':
                    pct = rm['params']['percent']
                    portfolio_value = context.portfolio.portfolio_value 
                    if  portfolio_value / context.capital_base - 1 > pct: 
                        stock_hold_now = [equity.symbol for equity in context.portfolio.positions]  
                        # 平掉所有股票
                        for stock in stock_hold_now:
                            if data.can_trade(context.symbol(stock)):
                                context.order_target_percent(context.symbol(stock), 0) 
                        print('策略出现止盈信号, 平掉全部仓位,并关闭交易!')
                        context.strategy_risk_signal = 'short'  
                    
                
                if rm['method'] == 'strategy_percent_stoploss':
                    pct = rm['params']['percent']
                    portfolio_value = context.portfolio.portfolio_value 
                    if  portfolio_value / context.capital_base -1 < pct:
                        stock_hold_now = [equity.symbol for equity in context.portfolio.positions]  
                        # 平掉所有股票
                        for stock in stock_hold_now:
                            if data.can_trade(context.symbol(stock)):
                                context.order_target_percent(context.symbol(stock), 0) 
                        print('策略出现止损信号, 平掉全部仓位,并关闭交易!')
                        context.strategy_risk_signal = 'short'
    
            
    def stock_risk_manage(context, data):
        """个股风控"""
        position_current_pnl = {pos.sid: (pos.last_sale_price-pos.cost_basis)/pos.cost_basis for i,pos in context.portfolio.positions.items()}
        
        for rm in context.stock_risk_conf:
            params_pct = rm['params']['percent']
            if rm['method'] == 'stock_percent_stopwin':
                for sid,pnl_pct in position_current_pnl.items():  
                    if pnl_pct > params_pct:
                        context.stock_hit_stop.append(sid.symbol)
              
            if rm['method'] == 'stock_percent_stoploss':
                for sid,pnl_pct in position_current_pnl.items():
                    if pnl_pct < params_pct:
                        context.stock_hit_stop.append(sid.symbol)
    
    
    
    
    # 回测引擎:每日数据处理函数,每天执行一次
    def m4_handle_data_bigquant_run(context, data):
        """每日运行策略逻辑"""
        market_risk_manage(context, data)
        strategy_risk_manage(context, data)
        
        if context.market_risk_signal == 'short': return
        if context.strategy_risk_signal == 'short': return
    
        stock_risk_manage(context, data)
        
        sell_action(context, data)
        buy_action(context, data)
    
    # 回测引擎:准备数据,只执行一次
    def m4_prepare_bigquant_run(context):
          
        load_data = context.options['data'].read_pickle()
        context.signal_daily_stock = load_data['df1'].groupby('date').apply(lambda x:list(x.instrument))
        context.enter_daily_df = load_data['df2'].groupby('date').apply(lambda x:list(x.instrument))
        context.exit_daily_df = load_data['df3'].groupby('date').apply(lambda x:list(x.instrument))
    
    
    def prepare_index_data(context):
        """准备指数数据"""
        if context.market_risk_conf != []:
            if len(context.market_risk_conf) == 1:
                index_code =  context.market_risk_conf[0]['params']['index_code']
                start_date = '2005-01-01'
                end_date = context.end_date
                index_data = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code], start_date=start_date, end_date=end_date).set_index('date')
                
                if  context.market_risk_conf[0]['method'] == 'market_ma_stoploss':
                    ma_periods = int(context.market_risk_conf[0]['params']['ma_periods'])
                    index_data['ma_%s'%ma_periods] = index_data['close'].rolling(ma_periods).mean()
                    index_data['signal'] = np.where(index_data['close'] > index_data['ma_%s'%ma_periods], 'long', 'short')
    
                elif context.market_risk_conf[0]['method'] == 'market_fallrange_stoploss':
                    days = context.market_risk_conf[0]['params']['days']
                    fallrange = context.market_risk_conf[0]['params']['fallrange']
                    index_data['signal'] = np.where(index_data['close']/index_data['close'].shift(days)-1 <= fallrange, 'long', 'short')
                context.index_signal_data = index_data 
                
            if  len(context.market_risk_conf) == 2:
                start_date = '2005-01-01'
                end_date = context.end_date 
                if context.market_risk_conf[0]['method'] == 'market_ma_stoploss':              
                    index_code_1 = context.market_risk_conf[0]['params']['index_code']
                    index_data_1 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_1], start_date=start_date, end_date=end_date).set_index('date')
                    ma_periods = int(context.market_risk_conf[0]['params']['ma_periods'])
                    
                    index_code_2 =  context.market_risk_conf[1]['params']['index_code']
                    index_data_2 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_2], start_date=start_date, end_date=end_date).set_index('date')
                    days = context.market_risk_conf[1]['params']['days']
                    fallrange = context.market_risk_conf[1]['params']['fallrange']
                else:
                    index_code_1 = context.market_risk_conf[1]['params']['index_code']
                    index_data_1 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_1], start_date=start_date, end_date=end_date).set_index('date')
                    ma_periods = int(context.market_risk_conf[1]['params']['ma_periods'])
                    
                    index_code_2 =  context.market_risk_conf[0]['params']['index_code']
                    index_data_2 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_2], start_date=start_date, end_date=end_date).set_index('date')
                    days = context.market_risk_conf[0]['params']['days']
                    fallrange = context.market_risk_conf[0]['params']['fallrange'] 
                    
                index_data_1['ma_%s'%ma_periods] = index_data_1['close'].rolling(ma_periods).mean()
                index_data_1['signal_1'] = np.where(index_data_1['close'] > index_data_1['ma_%s'%ma_periods], 1, 0)
                signal_1 = index_data_1[['signal_1']].reset_index()                
                index_data_2['signal_2'] = np.where(index_data_2['close']/index_data_2['close'].shift(days)-1 <= fallrange, 1, 0)
                signal_2 = index_data_2[['signal_2']].reset_index()
                signal = pd.merge(signal_1,signal_2).set_index('date')
                signal['signal_sum'] = signal['signal_1'] + signal['signal_2']
                signal['signal'] = np.where(signal['signal_sum']>0,'long','short')     
                context.index_signal_data = signal
        else:
            context.index_signal_data = None  
    
    def m4_initialize_bigquant_run(context):
        context.set_commission(PerOrder(buy_cost=0.003, sell_cost=0.004, min_cost=5))
        
        context.trade_mode = '择时'
    
        if context.trade_mode == '轮动':
            context.buy_frequency = 1
            context.sell_frequency = 1
            context.rebalance_periods = 1 # 调仓周期
            context.max_stock_count = 5 # 最大持仓股票数量
            context.order_weight_method = 'equal_weight' # 买入方式
            context.is_sell_willbuy_stock = False  # 卖出欲买进股票 
        else:
            # 买入条件参数
            context.stock_select_frequency = 1 # 选股频率
            context.order_weight_method = 'equal_weight' # 买入方式
            context.buy_frequency = 2 # 买入频率
            context.can_duplication_buy = False  # 是否可重复买入
            context.max_stock_count = 5 # 最大持仓股票数量
            context.max_stock_weight = 1 # 个股最大持仓比重
    
            # 卖出条件参数
            context.sell_frequency = 10 # 卖出频率
            context.is_sell_willbuy_stock = False  # 卖出欲买进股票 
    
        # 风控参数 
        context.stock_risk_conf = [{'method':'stock_percent_stopwin', 'params':{'percent': 0.2}}] # 支持多选  无:[]
        context.strategy_risk_conf = []  # 支持多选 无:[]
        context.market_risk_conf = [] # 支持多选, 无: []
        
        prepare_index_data(context)
        slippage_type = 'price'
        from zipline.finance.slippage import SlippageModel
        class FixedPriceSlippage(SlippageModel):
            # 指定初始化函数
            def __init__(self, spreads, price_field_buy, price_field_sell):
                # 存储spread的字典,用股票代码作为key
                self.spreads = spreads
                self._price_field_buy = price_field_buy
                self._price_field_sell = price_field_sell
            def process_order(self, data, order, bar_volume=0, trigger_check_price=0):
                if order.limit is None:
                    price_field = self._price_field_buy if order.amount > 0 else self._price_field_sell
                    price_base = data.current(order.asset, price_field)
                    if slippage_type == 'price':
                        price = price_base + (self.spreads / 2) if order.amount > 0 else price_base - (self.spreads / 2)
                    else:
                        price = price_base * (1.0 + self.spreads / 2) if order.amount > 0 else price_base * (1.0 - self.spreads / 2)
                else:
                    price = order.limit
                    # 返回希望成交的价格和数量
                return (price, order.amount)
        # 设置price_field
        fix_slippage = FixedPriceSlippage(price_field_buy='open', price_field_sell='open', spreads=0.02)
        context.set_slippage(us_equities=fix_slippage)
    # 回测引擎:每个单位时间开始前调用一次,即每日开盘前调用一次。
    def m4_before_trading_start_bigquant_run(context, data):
        
        """每日盘前更新股票池"""
        frequency = context.rebalance_periods if context.trade_mode == '轮动' else context.stock_select_frequency
        if context.trading_day_index % frequency == 0:
            date = data.current_dt.strftime('%Y-%m-%d')
            try:
                context.selected_stock = context.signal_daily_stock[date] 
            except KeyError as e:
                context.selected_stock = []
        
        """初始化风控参数"""
        context.strategy_risk_signal = 'long'
        context.market_risk_signal = 'long' 
        context.stock_hit_stop = []
        context.cannot_buy_stock = []
    
    
    m1 = M.instruments.v2(
        start_date='2014-01-01',
        end_date='2019-01-01',
        market='CN_STOCK_A',
        instrument_list=''
    )
    
    m8 = M.cached.v3(
        input_1=m1.data,
        run=m8_run_bigquant_run,
        post_run=m8_post_run_bigquant_run,
        input_ports='input_1',
        params='{\'input_index\':\'000300.HIX\'}',
        output_ports='data_1'
    )
    
    m3 = M.input_features.v1(
        features="""
    in_csi300_0
    in_csi500_0
    in_sse50_0
    industry_sw_level1_0
    st_status_0
    
    # 选股条件
    cond1=(pb_lf_0<200)&\
    (fs_roe_ttm_0>20)
    
    # 排序选股
    cond2=1
    
    # 进场条件
    cond3=1
                  
    # 卖出条件
    cond4=(pb_lf_0>700)
    """
    )
    
    m15 = M.general_feature_extractor.v7(
        instruments=m1.data,
        features=m3.data,
        start_date='',
        end_date='',
        before_start_days=300
    )
    
    m16 = M.derived_feature_extractor.v3(
        input_data=m15.data,
        features=m3.data,
        date_col='date',
        instrument_col='instrument'
    )
    
    m10 = M.input_features.v1(
        features="""concept
    """
    )
    
    m5 = M.use_datasource.v1(
        instruments=m1.data,
        features=m10.data,
        datasource_id='industry_CN_STOCK_A',
        start_date='',
        end_date=''
    )
    
    m7 = M.join.v3(
        data1=m5.data,
        data2=m16.data,
        on='date,instrument',
        how='inner',
        sort=False
    )
    
    m6 = M.input_features.v1(
        features='suspended'
    )
    
    m19 = M.use_datasource.v1(
        instruments=m1.data,
        features=m6.data,
        datasource_id='stock_status_CN_STOCK_A',
        start_date='',
        end_date=''
    )
    
    m20 = M.join.v3(
        data1=m7.data,
        data2=m19.data,
        on='date,instrument',
        how='inner',
        sort=False
    )
    
    m2 = M.stockpool_select.v6(
        input_1=m20.data,
        self_instruments=[],
        input_concepts=[],
        input_industrys=[360000,710000,220000,460000,370000,330000,340000,720000,240000,630000,280000,420000,510000,640000,610000,620000,650000,230000,410000,350000,490000,110000,210000,480000,730000,450000,270000,430000],
        input_indexs=['沪深300'],
        input_st='过滤',
        input_suspend='过滤'
    )
    
    m22 = M.cached.v3(
        input_1=m2.data,
        run=m22_run_bigquant_run,
        post_run=m22_post_run_bigquant_run,
        input_ports='',
        params='{}',
        output_ports=''
    )
    
    m17 = M.cached.v3(
        input_1=m22.data_1,
        input_2=m22.data_2,
        input_3=m22.data_3,
        run=m17_run_bigquant_run,
        post_run=m17_post_run_bigquant_run,
        input_ports='',
        params='{}',
        output_ports=''
    )
    
    m4 = M.trade.v4(
        instruments=m1.data,
        options_data=m17.data_1,
        benchmark=m8.data_1,
        start_date='',
        end_date='',
        handle_data=m4_handle_data_bigquant_run,
        prepare=m4_prepare_bigquant_run,
        initialize=m4_initialize_bigquant_run,
        before_trading_start=m4_before_trading_start_bigquant_run,
        volume_limit=0.025,
        order_price_field_buy='open',
        order_price_field_sell='open',
        capital_base=100000,
        auto_cancel_non_tradable_orders=True,
        data_frequency='daily',
        price_type='后复权',
        product_type='股票',
        plot_charts=True,
        backtest_only=False
    )
    

    (iQuant) #2

    您好,收到您的提问,已将问题分配给策略工程师,策略工程师会尽快为您解答的。


    (iQuant) #3

    image
    这里应该设置为2
    同理,卖出应该设置为7 而不是700


    (iQuant) #4

    从群内您提问来看,是条件设置有些问题,您修改后再试一下。


    (iQuant) #5

    您看一下这个是否满足您的需求呢?

    克隆策略

      {"Description":"实验创建于2017/8/26","Summary":"","Graph":{"EdgesInternal":[{"DestinationInputPortId":"-228:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"-234:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"-123:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"-550:input_1","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"-575:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"-228:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"-235:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"-235:input_data","SourceOutputPortId":"-228:data"},{"DestinationInputPortId":"-253:data1","SourceOutputPortId":"-234:data"},{"DestinationInputPortId":"-582:data1","SourceOutputPortId":"-253:data"},{"DestinationInputPortId":"-253:data2","SourceOutputPortId":"-235:data"},{"DestinationInputPortId":"-234:features","SourceOutputPortId":"-270:data"},{"DestinationInputPortId":"-123:options_data","SourceOutputPortId":"-185:data_1"},{"DestinationInputPortId":"-575:features","SourceOutputPortId":"-570:data"},{"DestinationInputPortId":"-582:data2","SourceOutputPortId":"-575:data"},{"DestinationInputPortId":"-121:input_1","SourceOutputPortId":"-582:data"},{"DestinationInputPortId":"-185:input_1","SourceOutputPortId":"-297:data_1"},{"DestinationInputPortId":"-185:input_2","SourceOutputPortId":"-297:data_2"},{"DestinationInputPortId":"-185:input_3","SourceOutputPortId":"-297:data_3"},{"DestinationInputPortId":"-297:input_1","SourceOutputPortId":"-121:data"}],"ModuleNodes":[{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-8","ModuleId":"BigQuantSpace.instruments.instruments-v2","ModuleParameters":[{"Name":"start_date","Value":"2014-01-01","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"2019-01-01","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"market","Value":"CN_STOCK_A","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_list","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"max_count","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"rolling_conf","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":1,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-24","ModuleId":"BigQuantSpace.input_features.input_features-v1","ModuleParameters":[{"Name":"features","Value":"\nin_csi300_0\nin_csi500_0\nin_sse50_0\nindustry_sw_level1_0\nst_status_0\n\n# 选股条件\ncond1=(pb_lf_0<2)&\\\n(fs_roe_ttm_0>20)\n\n# 排序选股\ncond2=1\n\n# 进场条件\ncond3=1\n \n# 卖出条件\ncond4=(pb_lf_0>7)\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":true,"moduleIdForCode":3,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-228","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":"300","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"-228"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-228"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-228","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":15,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-234","ModuleId":"BigQuantSpace.use_datasource.use_datasource-v1","ModuleParameters":[{"Name":"datasource_id","Value":"industry_CN_STOCK_A","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"-234"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-234"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-234","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":5,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-253","ModuleId":"BigQuantSpace.join.join-v3","ModuleParameters":[{"Name":"on","Value":"date,instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"how","Value":"inner","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"sort","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data1","NodeId":"-253"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data2","NodeId":"-253"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-253","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":7,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-235","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":"-235"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-235"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-235","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":16,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-270","ModuleId":"BigQuantSpace.input_features.input_features-v1","ModuleParameters":[{"Name":"features","Value":"concept\n","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features_ds","NodeId":"-270"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-270","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":10,"IsPartOfPartialRun":null,"Comment":"获取股票概念,并匹配选中的概念","CommentCollapsed":false},{"Id":"-123","ModuleId":"BigQuantSpace.trade.trade-v4","ModuleParameters":[{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"handle_data","Value":"#--------------------------------------------------------------------\n# 卖出条件\n#-------------------------------------------------------------------- \ndef sell_action(context, data):\n date = data.current_dt.strftime('%Y-%m-%d')\n hit_stop_stock = context.stock_hit_stop \n \n try:\n today_enter_stock = context.enter_daily_df.ix[date] \n except KeyError as e:\n today_enter_stock = []\n try:\n today_exit_stock = context.exit_daily_df.ix[date] \n except KeyError as e:\n today_exit_stock = []\n \n target_stock_to_buy = [i for i in context.selected_stock if i in today_enter_stock ] \n stock_hold_now = [equity.symbol for equity in context.portfolio.positions] # 当前持仓股票\n \n if context.trading_day_index % context.sell_frequency == 0:\n stock_to_sell = [i for i in stock_hold_now if i in today_exit_stock] # 要卖出的股票\n stock_buy_and_sell = [i for i in stock_to_sell if i in target_stock_to_buy]\n if context.is_sell_willbuy_stock == False: # 要买入的股票不卖出,但该票也不再买入\n stock_to_sell.extend(hit_stop_stock) # 将触发个股风控的股票融入到卖出票池\n stock_to_sell = [i for i in stock_to_sell if i not in stock_buy_and_sell] # 进行更新而已\n elif context.is_sell_willbuy_stock == True: # 要买入的股票依然要卖出,该票不再买入\n stock_to_sell.extend(hit_stop_stock)\n \n # 买入时需要过滤的股票\n context.cannot_buy_stock = stock_buy_and_sell\n \n for stock in stock_to_sell:\n if data.can_trade(context.symbol(stock)):\n context.order_target_percent(context.symbol(stock), 0) \n\n\n#--------------------------------------------------------------------\n# 买入条件\n#-------------------------------------------------------------------- \ndef buy_action(context, data):\n date = data.current_dt.strftime('%Y-%m-%d')\n \n try:\n today_enter_stock = context.enter_daily_df.ix[date] \n except KeyError as e:\n today_enter_stock = []\n try:\n today_exit_stock = context.exit_daily_df.ix[date] \n except KeyError as e:\n today_exit_stock = []\n \n target_stock_to_buy = [i for i in context.selected_stock if i in today_enter_stock] \n target_stock_to_buy = [s for s in target_stock_to_buy if s not in context.cannot_buy_stock] # 进行更新,不能买入的股票要过滤\n \n stock_hold_now = [equity.symbol for equity in context.portfolio.positions] # 当前持仓股票\n \n # 确定股票权重\n if context.order_weight_method == 'equal_weight':\n equal_weight = 1 / context.max_stock_count\n \n portfolio_value = context.portfolio.portfolio_value\n position_current_value = {pos.sid: pos.amount* pos.last_sale_price for i,pos in context.portfolio.positions.items()}\n \n # 买入\n if context.trading_day_index % context.buy_frequency == 0:\n if len(stock_hold_now) >= context.max_stock_count:\n return \n \n today_buy_count = 0\n if context.trade_mode == '轮动':\n for s in target_stock_to_buy:\n if today_buy_count + len(stock_hold_now) >= context.max_stock_count: # 超出最大持仓数量\n break\n if data.can_trade(context.symbol(s)):\n order_target_percent(context.symbol(s), equal_weight)\n today_buy_count += 1\n else:\n if context.can_duplication_buy == True: # 可以重复买入,多一份买入\n for s in target_stock_to_buy:\n if today_buy_count + len(stock_hold_now) >= context.max_stock_count: # 超出最大持仓数量\n break\n \n if data.can_trade(context.symbol(s)):\n if context.symbol(s) in position_current_weight:\n curr_value = position_current_value.get(context.symbol(s)) \n order_value(context.symbol(s), min(context.max_stock_weight * portfolio_value - curr_value, equal_weight*portfolio_value))\n else:\n order_value(context.symbol(s), equal_weight*portfolio_value)\n today_buy_count += 1\n\n elif context.can_duplication_buy == False: # 不可以重复买入,不买\n for s in target_stock_to_buy:\n if today_buy_count + len(stock_hold_now) >= context.max_stock_count: # 超出最大持仓数量\n break\n if s in stock_hold_now:\n continue\n else:\n if data.can_trade(context.symbol(s)):\n order_target_percent(context.symbol(s), equal_weight)\n today_buy_count += 1\n\n \n#--------------------------------------------------------------------\n# 风控体系\n#-------------------------------------------------------------------- \ndef market_risk_manage(context, data):\n \"\"\"大盘风控\"\"\"\n date = data.current_dt.strftime('%Y-%m-%d')\n if type(context.index_signal_data) == pd.DataFrame:\n current_signal = context.index_signal_data.ix[date]['signal']\n if current_signal == 'short': \n stock_hold_now = [equity.symbol for equity in context.portfolio.positions] \n # 平掉所有股票\n for stock in stock_hold_now:\n if data.can_trade(context.symbol(stock)):\n context.order_target_percent(context.symbol(stock), 0) \n print('大盘出现止损信号, 平掉全部仓位,并关闭交易!')\n context.market_risk_signal = 'short'\n else:\n context.market_risk_signal = 'long'\n\n \n \ndef strategy_risk_manage(context, data):\n \"\"\"策略风控\"\"\"\n if context.strategy_risk_conf == []: # 没有设置策略风控\n context.strategy_risk_signal = 'long'\n \n else:\n for rm in context.strategy_risk_conf:\n if rm['method'] == 'strategy_percent_stopwin':\n pct = rm['params']['percent']\n portfolio_value = context.portfolio.portfolio_value \n if portfolio_value / context.capital_base - 1 > pct: \n stock_hold_now = [equity.symbol for equity in context.portfolio.positions] \n # 平掉所有股票\n for stock in stock_hold_now:\n if data.can_trade(context.symbol(stock)):\n context.order_target_percent(context.symbol(stock), 0) \n print('策略出现止盈信号, 平掉全部仓位,并关闭交易!')\n context.strategy_risk_signal = 'short' \n \n \n if rm['method'] == 'strategy_percent_stoploss':\n pct = rm['params']['percent']\n portfolio_value = context.portfolio.portfolio_value \n if portfolio_value / context.capital_base -1 < pct:\n stock_hold_now = [equity.symbol for equity in context.portfolio.positions] \n # 平掉所有股票\n for stock in stock_hold_now:\n if data.can_trade(context.symbol(stock)):\n context.order_target_percent(context.symbol(stock), 0) \n print('策略出现止损信号, 平掉全部仓位,并关闭交易!')\n context.strategy_risk_signal = 'short'\n\n \ndef stock_risk_manage(context, data):\n \"\"\"个股风控\"\"\"\n position_current_pnl = {pos.sid: (pos.last_sale_price-pos.cost_basis)/pos.cost_basis for i,pos in context.portfolio.positions.items()}\n \n for rm in context.stock_risk_conf:\n params_pct = rm['params']['percent']\n if rm['method'] == 'stock_percent_stopwin':\n for sid,pnl_pct in position_current_pnl.items(): \n if pnl_pct > params_pct:\n context.stock_hit_stop.append(sid.symbol)\n \n if rm['method'] == 'stock_percent_stoploss':\n for sid,pnl_pct in position_current_pnl.items():\n if pnl_pct < params_pct:\n context.stock_hit_stop.append(sid.symbol)\n\n\n\n\n# 回测引擎:每日数据处理函数,每天执行一次\ndef bigquant_run(context, data):\n \"\"\"每日运行策略逻辑\"\"\"\n market_risk_manage(context, data)\n strategy_risk_manage(context, data)\n \n if context.market_risk_signal == 'short': return\n if context.strategy_risk_signal == 'short': return\n\n stock_risk_manage(context, data)\n \n sell_action(context, data)\n buy_action(context, data)\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"prepare","Value":"# 回测引擎:准备数据,只执行一次\ndef bigquant_run(context):\n \n load_data = context.options['data'].read_pickle()\n context.signal_daily_stock = load_data['df1'].groupby('date').apply(lambda x:list(x.instrument))\n context.enter_daily_df = load_data['df2'].groupby('date').apply(lambda x:list(x.instrument))\n context.exit_daily_df = load_data['df3'].groupby('date').apply(lambda x:list(x.instrument))\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"initialize","Value":"\ndef prepare_index_data(context):\n \"\"\"准备指数数据\"\"\"\n if context.market_risk_conf != []:\n if len(context.market_risk_conf) == 1:\n index_code = context.market_risk_conf[0]['params']['index_code']\n start_date = '2005-01-01'\n end_date = context.end_date\n index_data = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code], start_date=start_date, end_date=end_date).set_index('date')\n \n if context.market_risk_conf[0]['method'] == 'market_ma_stoploss':\n ma_periods = int(context.market_risk_conf[0]['params']['ma_periods'])\n index_data['ma_%s'%ma_periods] = index_data['close'].rolling(ma_periods).mean()\n index_data['signal'] = np.where(index_data['close'] > index_data['ma_%s'%ma_periods], 'long', 'short')\n\n elif context.market_risk_conf[0]['method'] == 'market_fallrange_stoploss':\n days = context.market_risk_conf[0]['params']['days']\n fallrange = context.market_risk_conf[0]['params']['fallrange']\n index_data['signal'] = np.where(index_data['close']/index_data['close'].shift(days)-1 <= fallrange, 'long', 'short')\n context.index_signal_data = index_data \n \n if len(context.market_risk_conf) == 2:\n start_date = '2005-01-01'\n end_date = context.end_date \n if context.market_risk_conf[0]['method'] == 'market_ma_stoploss': \n index_code_1 = context.market_risk_conf[0]['params']['index_code']\n index_data_1 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_1], start_date=start_date, end_date=end_date).set_index('date')\n ma_periods = int(context.market_risk_conf[0]['params']['ma_periods'])\n \n index_code_2 = context.market_risk_conf[1]['params']['index_code']\n index_data_2 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_2], start_date=start_date, end_date=end_date).set_index('date')\n days = context.market_risk_conf[1]['params']['days']\n fallrange = context.market_risk_conf[1]['params']['fallrange']\n else:\n index_code_1 = context.market_risk_conf[1]['params']['index_code']\n index_data_1 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_1], start_date=start_date, end_date=end_date).set_index('date')\n ma_periods = int(context.market_risk_conf[1]['params']['ma_periods'])\n \n index_code_2 = context.market_risk_conf[0]['params']['index_code']\n index_data_2 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_2], start_date=start_date, end_date=end_date).set_index('date')\n days = context.market_risk_conf[0]['params']['days']\n fallrange = context.market_risk_conf[0]['params']['fallrange'] \n \n index_data_1['ma_%s'%ma_periods] = index_data_1['close'].rolling(ma_periods).mean()\n index_data_1['signal_1'] = np.where(index_data_1['close'] > index_data_1['ma_%s'%ma_periods], 1, 0)\n signal_1 = index_data_1[['signal_1']].reset_index() \n index_data_2['signal_2'] = np.where(index_data_2['close']/index_data_2['close'].shift(days)-1 <= fallrange, 1, 0)\n signal_2 = index_data_2[['signal_2']].reset_index()\n signal = pd.merge(signal_1,signal_2).set_index('date')\n signal['signal_sum'] = signal['signal_1'] + signal['signal_2']\n signal['signal'] = np.where(signal['signal_sum']>0,'long','short') \n context.index_signal_data = signal\n else:\n context.index_signal_data = None \n\ndef bigquant_run(context):\n context.set_commission(PerOrder(buy_cost=0.003, sell_cost=0.004, min_cost=5))\n \n context.trade_mode = '择时'\n\n if context.trade_mode == '轮动':\n context.buy_frequency = 1\n context.sell_frequency = 1\n context.rebalance_periods = 1 # 调仓周期\n context.max_stock_count = 5 # 最大持仓股票数量\n context.order_weight_method = 'equal_weight' # 买入方式\n context.is_sell_willbuy_stock = False # 卖出欲买进股票 \n else:\n # 买入条件参数\n context.stock_select_frequency = 1 # 选股频率\n context.order_weight_method = 'equal_weight' # 买入方式\n context.buy_frequency = 2 # 买入频率\n context.can_duplication_buy = False # 是否可重复买入\n context.max_stock_count = 5 # 最大持仓股票数量\n context.max_stock_weight = 1 # 个股最大持仓比重\n\n # 卖出条件参数\n context.sell_frequency = 5 # 卖出频率\n context.is_sell_willbuy_stock = False # 卖出欲买进股票 \n\n # 风控参数 \n context.stock_risk_conf = [{'method':'stock_percent_stopwin', 'params':{'percent': 0.2}}] # 支持多选 无:[]\n context.strategy_risk_conf = [] # 支持多选 无:[]\n context.market_risk_conf = [] # 支持多选, 无: []\n \n prepare_index_data(context)\n slippage_type = 'price'\n from zipline.finance.slippage import SlippageModel\n class FixedPriceSlippage(SlippageModel):\n # 指定初始化函数\n def __init__(self, spreads, price_field_buy, price_field_sell):\n # 存储spread的字典,用股票代码作为key\n self.spreads = spreads\n self._price_field_buy = price_field_buy\n self._price_field_sell = price_field_sell\n def process_order(self, data, order, bar_volume=0, trigger_check_price=0):\n if order.limit is None:\n price_field = self._price_field_buy if order.amount > 0 else self._price_field_sell\n price_base = data.current(order.asset, price_field)\n if slippage_type == 'price':\n price = price_base + (self.spreads / 2) if order.amount > 0 else price_base - (self.spreads / 2)\n else:\n price = price_base * (1.0 + self.spreads / 2) if order.amount > 0 else price_base * (1.0 - self.spreads / 2)\n else:\n price = order.limit\n # 返回希望成交的价格和数量\n return (price, order.amount)\n # 设置price_field\n fix_slippage = FixedPriceSlippage(price_field_buy='open', price_field_sell='open', spreads=0.02)\n context.set_slippage(us_equities=fix_slippage)","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"before_trading_start","Value":"# 回测引擎:每个单位时间开始前调用一次,即每日开盘前调用一次。\ndef bigquant_run(context, data):\n \n \"\"\"每日盘前更新股票池\"\"\"\n frequency = context.rebalance_periods if context.trade_mode == '轮动' else context.stock_select_frequency\n if context.trading_day_index % frequency == 0:\n date = data.current_dt.strftime('%Y-%m-%d')\n try:\n context.selected_stock = context.signal_daily_stock[date] \n except KeyError as e:\n context.selected_stock = []\n \n \"\"\"初始化风控参数\"\"\"\n context.strategy_risk_signal = 'long'\n context.market_risk_signal = 'long' \n context.stock_hit_stop = []\n context.cannot_buy_stock = []\n","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":"100000","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":"-123"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"options_data","NodeId":"-123"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"history_ds","NodeId":"-123"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"benchmark_ds","NodeId":"-123"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"trading_calendar","NodeId":"-123"}],"OutputPortsInternal":[{"Name":"raw_perf","NodeId":"-123","OutputType":null}],"UsePreviousResults":false,"moduleIdForCode":4,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-185","ModuleId":"BigQuantSpace.cached.cached-v3","ModuleParameters":[{"Name":"run","Value":"# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端\ndef bigquant_run(input_1, input_2, input_3):\n df1 = input_1.read_df()\n df2 = input_2.read_df()\n df3 = input_3.read_df()\n \n df = {'df1':df1,'df2':df2,'df3':df3}\n ds = DataSource.write_pickle(df)\n return Outputs(data_1=ds)\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"post_run","Value":"# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。\ndef bigquant_run(outputs):\n return outputs\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_ports","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"params","Value":"{}","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"output_ports","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_1","NodeId":"-185"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_2","NodeId":"-185"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_3","NodeId":"-185"}],"OutputPortsInternal":[{"Name":"data_1","NodeId":"-185","OutputType":null},{"Name":"data_2","NodeId":"-185","OutputType":null},{"Name":"data_3","NodeId":"-185","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":17,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-550","ModuleId":"BigQuantSpace.cached.cached-v3","ModuleParameters":[{"Name":"run","Value":"# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端\ndef bigquant_run(input_1, input_index):\n # 示例代码如下。在这里编写您的代码\n start_date=input_1.read_pickle()['start_date']\n end_date=input_1.read_pickle()['end_date']\n df = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[input_index],start_date=start_date,end_date=end_date,fields=['close'])\n data_1 = DataSource.write_df(df)\n return Outputs(data_1=data_1, data_2=None, data_3=None)\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"post_run","Value":"# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。\ndef bigquant_run(outputs):\n return outputs\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_ports","Value":"input_1","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"params","Value":"{'input_index':'000300.HIX'}","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"output_ports","Value":"data_1","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_1","NodeId":"-550"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_2","NodeId":"-550"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_3","NodeId":"-550"}],"OutputPortsInternal":[{"Name":"data_1","NodeId":"-550","OutputType":null},{"Name":"data_2","NodeId":"-550","OutputType":null},{"Name":"data_3","NodeId":"-550","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":8,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-570","ModuleId":"BigQuantSpace.input_features.input_features-v1","ModuleParameters":[{"Name":"features","Value":"suspended","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features_ds","NodeId":"-570"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-570","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":6,"IsPartOfPartialRun":null,"Comment":"获取股票停牌数据","CommentCollapsed":false},{"Id":"-575","ModuleId":"BigQuantSpace.use_datasource.use_datasource-v1","ModuleParameters":[{"Name":"datasource_id","Value":"stock_status_CN_STOCK_A","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"-575"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-575"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-575","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":19,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-582","ModuleId":"BigQuantSpace.join.join-v3","ModuleParameters":[{"Name":"on","Value":"date,instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"how","Value":"inner","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"sort","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data1","NodeId":"-582"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data2","NodeId":"-582"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-582","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":20,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-297","ModuleId":"BigQuantSpace.cached.cached-v3","ModuleParameters":[{"Name":"run","Value":"# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端\ndef bigquant_run(input_1, input_2, input_3):\n # 示例代码如下。在这里编写您的代码\n df = input_1.read_df()\n # 缺失值处理\n # if len(df)!=0:\n # df.dropna(inplace=True)\n \n # 选股条件\n if len(df)!=0:\n df_filter1 = df[df['cond1']>0]\n else:\n df_filter1 = df\n \n # 指标排序\n if len(df_filter1)!=0:\n df_filter2 = df_filter1.groupby('date').apply(lambda x:x.sort_values(by=['cond2'],ascending=True))\n else:\n df_filter2 = df_filter1\n \n #输出条件过滤股票池\n data_1 = DataSource.write_df(df_filter2)\n\n \n # 进场条件\n if len(df)!=0:\n df_buy = df[df['cond3']>0]\n else:\n df_buy = df\n # 输出满足进场条件的股票池\n data_2 = DataSource.write_df(df_buy)\n\n \n # 出场条件\n if len(df)!=0:\n df_sell = df[df['cond4']>0]\n else:\n df_sell = df\n # 输出满足出场条件的股票池\n data_3 = DataSource.write_df(df_sell) \n \n return Outputs(data_1=data_1, data_2=data_2, data_3=data_3)\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"post_run","Value":"# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。\ndef bigquant_run(outputs):\n return outputs\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_ports","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"params","Value":"{}","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"output_ports","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_1","NodeId":"-297"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_2","NodeId":"-297"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_3","NodeId":"-297"}],"OutputPortsInternal":[{"Name":"data_1","NodeId":"-297","OutputType":null},{"Name":"data_2","NodeId":"-297","OutputType":null},{"Name":"data_3","NodeId":"-297","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":22,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-121","ModuleId":"BigQuantSpace.stockpool_select.stockpool_select-v6","ModuleParameters":[{"Name":"self_instruments","Value":"[]","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_concepts","Value":"[]","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_industrys","Value":"[360000,710000,220000,460000,370000,330000,340000,720000,240000,630000,280000,420000,510000,640000,610000,620000,650000,230000,410000,350000,490000,110000,210000,480000,730000,450000,270000,430000]","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_indexs","Value":"['沪深300']","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_st","Value":"过滤","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_suspend","Value":"过滤","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_1","NodeId":"-121"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-121","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":2,"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-8' Position='473,-148,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-24' Position='697,-231,200,200'/><NodePosition Node='-228' Position='479,-22,200,200'/><NodePosition Node='-234' Position='145,-30,200,200'/><NodePosition Node='-253' Position='341,161,200,200'/><NodePosition Node='-235' Position='483,70,200,200'/><NodePosition Node='-270' Position='124,-149,200,200'/><NodePosition Node='-123' Position='563,688.329345703125,200,200'/><NodePosition Node='-185' Position='452.670654296875,575,200,200'/><NodePosition Node='-550' Position='878,511,200,200'/><NodePosition Node='-570' Position='960,-137,200,200'/><NodePosition Node='-575' Position='840,-16,200,200'/><NodePosition Node='-582' Position='555.670654296875,241,200,200'/><NodePosition Node='-297' Position='453,455,200,200'/><NodePosition Node='-121' Position='457,355,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]:
      # 本代码由可视化策略环境自动生成 2019年1月28日 12:06
      # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
      
      
      # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
      def m8_run_bigquant_run(input_1, input_index):
          # 示例代码如下。在这里编写您的代码
          start_date=input_1.read_pickle()['start_date']
          end_date=input_1.read_pickle()['end_date']
          df = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[input_index],start_date=start_date,end_date=end_date,fields=['close'])
          data_1 = DataSource.write_df(df)
          return Outputs(data_1=data_1, data_2=None, data_3=None)
      
      # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
      def m8_post_run_bigquant_run(outputs):
          return outputs
      
      # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
      def m22_run_bigquant_run(input_1, input_2, input_3):
          # 示例代码如下。在这里编写您的代码
          df = input_1.read_df()
          # 缺失值处理
          # if len(df)!=0:
          #     df.dropna(inplace=True)
              
          # 选股条件
          if len(df)!=0:
              df_filter1 = df[df['cond1']>0]
          else:
              df_filter1 = df
          
          # 指标排序
          if len(df_filter1)!=0:
              df_filter2 = df_filter1.groupby('date').apply(lambda x:x.sort_values(by=['cond2'],ascending=True))
          else:
              df_filter2 = df_filter1
          
          #输出条件过滤股票池
          data_1 = DataSource.write_df(df_filter2)
      
          
          # 进场条件
          if len(df)!=0:
              df_buy = df[df['cond3']>0]
          else:
              df_buy = df
          # 输出满足进场条件的股票池
          data_2 = DataSource.write_df(df_buy)
      
          
          # 出场条件
          if len(df)!=0:
              df_sell = df[df['cond4']>0]
          else:
              df_sell = df
          # 输出满足出场条件的股票池
          data_3 = DataSource.write_df(df_sell)    
          
          return Outputs(data_1=data_1, data_2=data_2, data_3=data_3)
      
      # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
      def m22_post_run_bigquant_run(outputs):
          return outputs
      
      # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
      def m17_run_bigquant_run(input_1, input_2, input_3):
          df1 = input_1.read_df()
          df2 = input_2.read_df()
          df3 = input_3.read_df()
          
          df = {'df1':df1,'df2':df2,'df3':df3}
          ds = DataSource.write_pickle(df)
          return Outputs(data_1=ds)
      
      # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
      def m17_post_run_bigquant_run(outputs):
          return outputs
      
      #--------------------------------------------------------------------
      # 卖出条件
      #--------------------------------------------------------------------     
      def sell_action(context, data):
          date = data.current_dt.strftime('%Y-%m-%d')
          hit_stop_stock = context.stock_hit_stop 
          
          try:
              today_enter_stock = context.enter_daily_df.ix[date] 
          except KeyError as e:
              today_enter_stock = []
          try:
              today_exit_stock = context.exit_daily_df.ix[date] 
          except KeyError as e:
              today_exit_stock = []
              
          target_stock_to_buy = [i for i in  context.selected_stock  if i in today_enter_stock ]   
          stock_hold_now = [equity.symbol for equity in context.portfolio.positions] # 当前持仓股票
          
          if  context.trading_day_index % context.sell_frequency == 0:
              stock_to_sell = [i for i in stock_hold_now if i in today_exit_stock] # 要卖出的股票
              stock_buy_and_sell = [i for i in stock_to_sell if i in target_stock_to_buy]
              if context.is_sell_willbuy_stock == False: # 要买入的股票不卖出,但该票也不再买入
                  stock_to_sell.extend(hit_stop_stock) # 将触发个股风控的股票融入到卖出票池
                  stock_to_sell = [i for i in stock_to_sell if i not in stock_buy_and_sell] # 进行更新而已
              elif context.is_sell_willbuy_stock == True: # 要买入的股票依然要卖出,该票不再买入
                  stock_to_sell.extend(hit_stop_stock)
              
              # 买入时需要过滤的股票
              context.cannot_buy_stock = stock_buy_and_sell
                  
              for stock in stock_to_sell:
                  if data.can_trade(context.symbol(stock)):
                      context.order_target_percent(context.symbol(stock), 0) 
      
      
      #--------------------------------------------------------------------
      # 买入条件
      #--------------------------------------------------------------------     
      def buy_action(context, data):
          date = data.current_dt.strftime('%Y-%m-%d')
          
          try:
              today_enter_stock = context.enter_daily_df.ix[date] 
          except KeyError as e:
              today_enter_stock = []
          try:
              today_exit_stock = context.exit_daily_df.ix[date] 
          except KeyError as e:
              today_exit_stock = []
          
          target_stock_to_buy = [i for i in  context.selected_stock if i in today_enter_stock]  
          target_stock_to_buy = [s for s in target_stock_to_buy if s not in context.cannot_buy_stock] # 进行更新,不能买入的股票要过滤
          
          stock_hold_now = [equity.symbol for equity in context.portfolio.positions] # 当前持仓股票
          
          # 确定股票权重
          if context.order_weight_method == 'equal_weight':
              equal_weight =  1 / context.max_stock_count
              
          portfolio_value = context.portfolio.portfolio_value
          position_current_value = {pos.sid: pos.amount* pos.last_sale_price for i,pos in context.portfolio.positions.items()}
          
          # 买入
          if  context.trading_day_index % context.buy_frequency == 0:
              if len(stock_hold_now) >= context.max_stock_count:
                  return 
              
              today_buy_count = 0
              if context.trade_mode == '轮动':
                  for s in target_stock_to_buy:
                      if today_buy_count + len(stock_hold_now) >= context.max_stock_count: # 超出最大持仓数量
                          break
                      if data.can_trade(context.symbol(s)):
                          order_target_percent(context.symbol(s), equal_weight)
                          today_buy_count += 1
              else:
                  if  context.can_duplication_buy == True: # 可以重复买入,多一份买入
                      for s in target_stock_to_buy:
                          if today_buy_count + len(stock_hold_now) >= context.max_stock_count: # 超出最大持仓数量
                              break
                              
                          if data.can_trade(context.symbol(s)):
                              if context.symbol(s) in position_current_weight:
                                  curr_value = position_current_value.get(context.symbol(s)) 
                                  order_value(context.symbol(s), min(context.max_stock_weight * portfolio_value - curr_value, equal_weight*portfolio_value))
                              else:
                                  order_value(context.symbol(s), equal_weight*portfolio_value)
                              today_buy_count += 1
      
                  elif  context.can_duplication_buy == False: # 不可以重复买入,不买
                    for s in target_stock_to_buy:
                      if today_buy_count + len(stock_hold_now) >= context.max_stock_count: # 超出最大持仓数量
                          break
                      if s in stock_hold_now:
                          continue
                      else:
                          if data.can_trade(context.symbol(s)):
                              order_target_percent(context.symbol(s), equal_weight)
                              today_buy_count += 1
      
                              
      #--------------------------------------------------------------------
      # 风控体系
      #--------------------------------------------------------------------                         
      def market_risk_manage(context, data):
          """大盘风控"""
          date = data.current_dt.strftime('%Y-%m-%d')
          if type(context.index_signal_data) == pd.DataFrame:
              current_signal = context.index_signal_data.ix[date]['signal']
              if current_signal == 'short': 
                  stock_hold_now = [equity.symbol for equity in context.portfolio.positions]  
                  # 平掉所有股票
                  for stock in stock_hold_now:
                      if data.can_trade(context.symbol(stock)):
                          context.order_target_percent(context.symbol(stock), 0) 
                  print('大盘出现止损信号, 平掉全部仓位,并关闭交易!')
                  context.market_risk_signal = 'short'
          else:
              context.market_risk_signal = 'long'
      
              
              
      def strategy_risk_manage(context, data):
          """策略风控"""
          if context.strategy_risk_conf == []: # 没有设置策略风控
              context.strategy_risk_signal = 'long'
          
          else:
              for rm in context.strategy_risk_conf:
                  if rm['method'] == 'strategy_percent_stopwin':
                      pct = rm['params']['percent']
                      portfolio_value = context.portfolio.portfolio_value 
                      if  portfolio_value / context.capital_base - 1 > pct: 
                          stock_hold_now = [equity.symbol for equity in context.portfolio.positions]  
                          # 平掉所有股票
                          for stock in stock_hold_now:
                              if data.can_trade(context.symbol(stock)):
                                  context.order_target_percent(context.symbol(stock), 0) 
                          print('策略出现止盈信号, 平掉全部仓位,并关闭交易!')
                          context.strategy_risk_signal = 'short'  
                      
                  
                  if rm['method'] == 'strategy_percent_stoploss':
                      pct = rm['params']['percent']
                      portfolio_value = context.portfolio.portfolio_value 
                      if  portfolio_value / context.capital_base -1 < pct:
                          stock_hold_now = [equity.symbol for equity in context.portfolio.positions]  
                          # 平掉所有股票
                          for stock in stock_hold_now:
                              if data.can_trade(context.symbol(stock)):
                                  context.order_target_percent(context.symbol(stock), 0) 
                          print('策略出现止损信号, 平掉全部仓位,并关闭交易!')
                          context.strategy_risk_signal = 'short'
      
              
      def stock_risk_manage(context, data):
          """个股风控"""
          position_current_pnl = {pos.sid: (pos.last_sale_price-pos.cost_basis)/pos.cost_basis for i,pos in context.portfolio.positions.items()}
          
          for rm in context.stock_risk_conf:
              params_pct = rm['params']['percent']
              if rm['method'] == 'stock_percent_stopwin':
                  for sid,pnl_pct in position_current_pnl.items():  
                      if pnl_pct > params_pct:
                          context.stock_hit_stop.append(sid.symbol)
                
              if rm['method'] == 'stock_percent_stoploss':
                  for sid,pnl_pct in position_current_pnl.items():
                      if pnl_pct < params_pct:
                          context.stock_hit_stop.append(sid.symbol)
      
      
      
      
      # 回测引擎:每日数据处理函数,每天执行一次
      def m4_handle_data_bigquant_run(context, data):
          """每日运行策略逻辑"""
          market_risk_manage(context, data)
          strategy_risk_manage(context, data)
          
          if context.market_risk_signal == 'short': return
          if context.strategy_risk_signal == 'short': return
      
          stock_risk_manage(context, data)
          
          sell_action(context, data)
          buy_action(context, data)
      
      # 回测引擎:准备数据,只执行一次
      def m4_prepare_bigquant_run(context):
            
          load_data = context.options['data'].read_pickle()
          context.signal_daily_stock = load_data['df1'].groupby('date').apply(lambda x:list(x.instrument))
          context.enter_daily_df = load_data['df2'].groupby('date').apply(lambda x:list(x.instrument))
          context.exit_daily_df = load_data['df3'].groupby('date').apply(lambda x:list(x.instrument))
      
      
      def prepare_index_data(context):
          """准备指数数据"""
          if context.market_risk_conf != []:
              if len(context.market_risk_conf) == 1:
                  index_code =  context.market_risk_conf[0]['params']['index_code']
                  start_date = '2005-01-01'
                  end_date = context.end_date
                  index_data = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code], start_date=start_date, end_date=end_date).set_index('date')
                  
                  if  context.market_risk_conf[0]['method'] == 'market_ma_stoploss':
                      ma_periods = int(context.market_risk_conf[0]['params']['ma_periods'])
                      index_data['ma_%s'%ma_periods] = index_data['close'].rolling(ma_periods).mean()
                      index_data['signal'] = np.where(index_data['close'] > index_data['ma_%s'%ma_periods], 'long', 'short')
      
                  elif context.market_risk_conf[0]['method'] == 'market_fallrange_stoploss':
                      days = context.market_risk_conf[0]['params']['days']
                      fallrange = context.market_risk_conf[0]['params']['fallrange']
                      index_data['signal'] = np.where(index_data['close']/index_data['close'].shift(days)-1 <= fallrange, 'long', 'short')
                  context.index_signal_data = index_data 
                  
              if  len(context.market_risk_conf) == 2:
                  start_date = '2005-01-01'
                  end_date = context.end_date 
                  if context.market_risk_conf[0]['method'] == 'market_ma_stoploss':              
                      index_code_1 = context.market_risk_conf[0]['params']['index_code']
                      index_data_1 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_1], start_date=start_date, end_date=end_date).set_index('date')
                      ma_periods = int(context.market_risk_conf[0]['params']['ma_periods'])
                      
                      index_code_2 =  context.market_risk_conf[1]['params']['index_code']
                      index_data_2 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_2], start_date=start_date, end_date=end_date).set_index('date')
                      days = context.market_risk_conf[1]['params']['days']
                      fallrange = context.market_risk_conf[1]['params']['fallrange']
                  else:
                      index_code_1 = context.market_risk_conf[1]['params']['index_code']
                      index_data_1 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_1], start_date=start_date, end_date=end_date).set_index('date')
                      ma_periods = int(context.market_risk_conf[1]['params']['ma_periods'])
                      
                      index_code_2 =  context.market_risk_conf[0]['params']['index_code']
                      index_data_2 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=[index_code_2], start_date=start_date, end_date=end_date).set_index('date')
                      days = context.market_risk_conf[0]['params']['days']
                      fallrange = context.market_risk_conf[0]['params']['fallrange'] 
                      
                  index_data_1['ma_%s'%ma_periods] = index_data_1['close'].rolling(ma_periods).mean()
                  index_data_1['signal_1'] = np.where(index_data_1['close'] > index_data_1['ma_%s'%ma_periods], 1, 0)
                  signal_1 = index_data_1[['signal_1']].reset_index()                
                  index_data_2['signal_2'] = np.where(index_data_2['close']/index_data_2['close'].shift(days)-1 <= fallrange, 1, 0)
                  signal_2 = index_data_2[['signal_2']].reset_index()
                  signal = pd.merge(signal_1,signal_2).set_index('date')
                  signal['signal_sum'] = signal['signal_1'] + signal['signal_2']
                  signal['signal'] = np.where(signal['signal_sum']>0,'long','short')     
                  context.index_signal_data = signal
          else:
              context.index_signal_data = None  
      
      def m4_initialize_bigquant_run(context):
          context.set_commission(PerOrder(buy_cost=0.003, sell_cost=0.004, min_cost=5))
          
          context.trade_mode = '择时'
      
          if context.trade_mode == '轮动':
              context.buy_frequency = 1
              context.sell_frequency = 1
              context.rebalance_periods = 1 # 调仓周期
              context.max_stock_count = 5 # 最大持仓股票数量
              context.order_weight_method = 'equal_weight' # 买入方式
              context.is_sell_willbuy_stock = False  # 卖出欲买进股票 
          else:
              # 买入条件参数
              context.stock_select_frequency = 1 # 选股频率
              context.order_weight_method = 'equal_weight' # 买入方式
              context.buy_frequency = 2 # 买入频率
              context.can_duplication_buy = False  # 是否可重复买入
              context.max_stock_count = 5 # 最大持仓股票数量
              context.max_stock_weight = 1 # 个股最大持仓比重
      
              # 卖出条件参数
              context.sell_frequency = 5 # 卖出频率
              context.is_sell_willbuy_stock = False  # 卖出欲买进股票 
      
          # 风控参数 
          context.stock_risk_conf = [{'method':'stock_percent_stopwin', 'params':{'percent': 0.2}}] # 支持多选  无:[]
          context.strategy_risk_conf = []  # 支持多选 无:[]
          context.market_risk_conf = [] # 支持多选, 无: []
          
          prepare_index_data(context)
          slippage_type = 'price'
          from zipline.finance.slippage import SlippageModel
          class FixedPriceSlippage(SlippageModel):
              # 指定初始化函数
              def __init__(self, spreads, price_field_buy, price_field_sell):
                  # 存储spread的字典,用股票代码作为key
                  self.spreads = spreads
                  self._price_field_buy = price_field_buy
                  self._price_field_sell = price_field_sell
              def process_order(self, data, order, bar_volume=0, trigger_check_price=0):
                  if order.limit is None:
                      price_field = self._price_field_buy if order.amount > 0 else self._price_field_sell
                      price_base = data.current(order.asset, price_field)
                      if slippage_type == 'price':
                          price = price_base + (self.spreads / 2) if order.amount > 0 else price_base - (self.spreads / 2)
                      else:
                          price = price_base * (1.0 + self.spreads / 2) if order.amount > 0 else price_base * (1.0 - self.spreads / 2)
                  else:
                      price = order.limit
                      # 返回希望成交的价格和数量
                  return (price, order.amount)
          # 设置price_field
          fix_slippage = FixedPriceSlippage(price_field_buy='open', price_field_sell='open', spreads=0.02)
          context.set_slippage(us_equities=fix_slippage)
      # 回测引擎:每个单位时间开始前调用一次,即每日开盘前调用一次。
      def m4_before_trading_start_bigquant_run(context, data):
          
          """每日盘前更新股票池"""
          frequency = context.rebalance_periods if context.trade_mode == '轮动' else context.stock_select_frequency
          if context.trading_day_index % frequency == 0:
              date = data.current_dt.strftime('%Y-%m-%d')
              try:
                  context.selected_stock = context.signal_daily_stock[date] 
              except KeyError as e:
                  context.selected_stock = []
          
          """初始化风控参数"""
          context.strategy_risk_signal = 'long'
          context.market_risk_signal = 'long' 
          context.stock_hit_stop = []
          context.cannot_buy_stock = []
      
      
      m1 = M.instruments.v2(
          start_date='2014-01-01',
          end_date='2019-01-01',
          market='CN_STOCK_A',
          instrument_list=''
      )
      
      m8 = M.cached.v3(
          input_1=m1.data,
          run=m8_run_bigquant_run,
          post_run=m8_post_run_bigquant_run,
          input_ports='input_1',
          params='{\'input_index\':\'000300.HIX\'}',
          output_ports='data_1'
      )
      
      m3 = M.input_features.v1(
          features="""
      in_csi300_0
      in_csi500_0
      in_sse50_0
      industry_sw_level1_0
      st_status_0
      
      # 选股条件
      cond1=(pb_lf_0<2)&\
      (fs_roe_ttm_0>20)
      
      # 排序选股
      cond2=1
      
      # 进场条件
      cond3=1
                    
      # 卖出条件
      cond4=(pb_lf_0>7)
      """
      )
      
      m15 = M.general_feature_extractor.v7(
          instruments=m1.data,
          features=m3.data,
          start_date='',
          end_date='',
          before_start_days=300
      )
      
      m16 = M.derived_feature_extractor.v3(
          input_data=m15.data,
          features=m3.data,
          date_col='date',
          instrument_col='instrument',
          drop_na=False,
          remove_extra_columns=False
      )
      
      m10 = M.input_features.v1(
          features="""concept
      """
      )
      
      m5 = M.use_datasource.v1(
          instruments=m1.data,
          features=m10.data,
          datasource_id='industry_CN_STOCK_A',
          start_date='',
          end_date=''
      )
      
      m7 = M.join.v3(
          data1=m5.data,
          data2=m16.data,
          on='date,instrument',
          how='inner',
          sort=False
      )
      
      m6 = M.input_features.v1(
          features='suspended'
      )
      
      m19 = M.use_datasource.v1(
          instruments=m1.data,
          features=m6.data,
          datasource_id='stock_status_CN_STOCK_A',
          start_date='',
          end_date=''
      )
      
      m20 = M.join.v3(
          data1=m7.data,
          data2=m19.data,
          on='date,instrument',
          how='inner',
          sort=False
      )
      
      m2 = M.stockpool_select.v6(
          input_1=m20.data,
          self_instruments=[],
          input_concepts=[],
          input_industrys=[360000,710000,220000,460000,370000,330000,340000,720000,240000,630000,280000,420000,510000,640000,610000,620000,650000,230000,410000,350000,490000,110000,210000,480000,730000,450000,270000,430000],
          input_indexs=['沪深300'],
          input_st='过滤',
          input_suspend='过滤'
      )
      
      m22 = M.cached.v3(
          input_1=m2.data,
          run=m22_run_bigquant_run,
          post_run=m22_post_run_bigquant_run,
          input_ports='',
          params='{}',
          output_ports=''
      )
      
      m17 = M.cached.v3(
          input_1=m22.data_1,
          input_2=m22.data_2,
          input_3=m22.data_3,
          run=m17_run_bigquant_run,
          post_run=m17_post_run_bigquant_run,
          input_ports='',
          params='{}',
          output_ports=''
      )
      
      m4 = M.trade.v4(
          instruments=m1.data,
          options_data=m17.data_1,
          start_date='',
          end_date='',
          handle_data=m4_handle_data_bigquant_run,
          prepare=m4_prepare_bigquant_run,
          initialize=m4_initialize_bigquant_run,
          before_trading_start=m4_before_trading_start_bigquant_run,
          volume_limit=0.025,
          order_price_field_buy='open',
          order_price_field_sell='open',
          capital_base=100000,
          auto_cancel_non_tradable_orders=True,
          data_frequency='daily',
          price_type='后复权',
          product_type='股票',
          plot_charts=True,
          backtest_only=False,
          benchmark=''
      )
      
      [2019-01-28 11:52:55.824242] INFO: bigquant: instruments.v2 开始运行..
      [2019-01-28 11:52:55.965834] INFO: bigquant: 命中缓存
      [2019-01-28 11:52:55.967184] INFO: bigquant: instruments.v2 运行完成[0.143002s].
      [2019-01-28 11:52:55.973920] INFO: bigquant: cached.v3 开始运行..
      [2019-01-28 11:52:56.079416] INFO: bigquant: 命中缓存
      [2019-01-28 11:52:56.080661] INFO: bigquant: cached.v3 运行完成[0.10673s].
      [2019-01-28 11:52:56.085907] INFO: bigquant: input_features.v1 开始运行..
      [2019-01-28 11:52:56.167169] INFO: bigquant: input_features.v1 运行完成[0.08122s].
      [2019-01-28 11:52:56.194620] INFO: bigquant: general_feature_extractor.v7 开始运行..
      [2019-01-28 11:52:56.309790] INFO: bigquant: 命中缓存
      [2019-01-28 11:52:56.310814] INFO: bigquant: general_feature_extractor.v7 运行完成[0.116212s].
      [2019-01-28 11:52:56.315940] INFO: bigquant: derived_feature_extractor.v3 开始运行..
      [2019-01-28 11:52:59.820395] INFO: derived_feature_extractor: 提取完成 cond1=(pb_lf_0<2)&(fs_roe_ttm_0>20), 0.012s
      [2019-01-28 11:52:59.840407] INFO: derived_feature_extractor: 提取完成 cond2=1, 0.019s
      [2019-01-28 11:52:59.860258] INFO: derived_feature_extractor: 提取完成 cond3=1, 0.018s
      [2019-01-28 11:52:59.865721] INFO: derived_feature_extractor: 提取完成 cond4=(pb_lf_0>7), 0.004s
      [2019-01-28 11:53:00.460306] INFO: derived_feature_extractor: /y_2013, 470412
      [2019-01-28 11:53:00.983390] INFO: derived_feature_extractor: /y_2014, 569948
      [2019-01-28 11:53:01.403791] INFO: derived_feature_extractor: /y_2015, 569698
      [2019-01-28 11:53:01.842759] INFO: derived_feature_extractor: /y_2016, 641546
      [2019-01-28 11:53:02.339250] INFO: derived_feature_extractor: /y_2017, 743233
      [2019-01-28 11:53:02.979480] INFO: derived_feature_extractor: /y_2018, 816987
      [2019-01-28 11:53:03.492973] INFO: bigquant: derived_feature_extractor.v3 运行完成[7.176997s].
      [2019-01-28 11:53:03.495179] INFO: bigquant: input_features.v1 开始运行..
      [2019-01-28 11:53:03.715525] INFO: bigquant: 命中缓存
      [2019-01-28 11:53:03.716532] INFO: bigquant: input_features.v1 运行完成[0.221347s].
      [2019-01-28 11:53:03.780089] INFO: bigquant: use_datasource.v1 开始运行..
      [2019-01-28 11:53:03.912444] INFO: bigquant: 命中缓存
      [2019-01-28 11:53:03.913455] INFO: bigquant: use_datasource.v1 运行完成[0.13342s].
      [2019-01-28 11:53:03.918077] INFO: bigquant: join.v3 开始运行..
      [2019-01-28 11:53:11.522191] INFO: join: /y_2013, 行数=0/470412, 耗时=1.671924s
      [2019-01-28 11:53:14.073470] INFO: join: /y_2014, 行数=569948/569948, 耗时=2.5402s
      [2019-01-28 11:53:16.830421] INFO: join: /y_2015, 行数=569698/569698, 耗时=2.725071s
      [2019-01-28 11:53:22.076543] INFO: join: /y_2016, 行数=641546/641546, 耗时=5.211995s
      [2019-01-28 11:53:27.570708] INFO: join: /y_2017, 行数=743233/743233, 耗时=5.447221s
      [2019-01-28 11:53:31.156642] INFO: join: /y_2018, 行数=816987/816987, 耗时=3.548732s
      [2019-01-28 11:53:31.910744] INFO: join: 最终行数: 3341412
      [2019-01-28 11:53:31.913549] INFO: bigquant: join.v3 运行完成[27.995439s].
      [2019-01-28 11:53:31.916032] INFO: bigquant: input_features.v1 开始运行..
      [2019-01-28 11:53:32.140601] INFO: bigquant: 命中缓存
      [2019-01-28 11:53:32.142126] INFO: bigquant: input_features.v1 运行完成[0.226076s].
      [2019-01-28 11:53:32.144830] INFO: bigquant: use_datasource.v1 开始运行..
      [2019-01-28 11:53:32.263682] INFO: bigquant: 命中缓存
      [2019-01-28 11:53:32.265198] INFO: bigquant: use_datasource.v1 运行完成[0.120356s].
      [2019-01-28 11:53:32.268846] INFO: bigquant: join.v3 开始运行..
      [2019-01-28 11:53:37.026762] INFO: join: /y_2013, 行数=0/0, 耗时=1.347153s
      [2019-01-28 11:53:39.906649] INFO: join: /y_2014, 行数=569948/569948, 耗时=2.87819s
      [2019-01-28 11:53:42.923881] INFO: join: /y_2015, 行数=569698/569698, 耗时=2.967594s
      [2019-01-28 11:53:46.198893] INFO: join: /y_2016, 行数=641546/641546, 耗时=3.223604s
      [2019-01-28 11:53:49.886583] INFO: join: /y_2017, 行数=743233/743233, 耗时=3.611512s
      [2019-01-28 11:53:54.061223] INFO: join: /y_2018, 行数=816987/816987, 耗时=4.093184s
      [2019-01-28 11:53:54.305972] INFO: join: 最终行数: 3341412
      [2019-01-28 11:53:54.307986] INFO: bigquant: join.v3 运行完成[22.039143s].
      [2019-01-28 11:53:54.414553] INFO: bigquant: stockpool_select.v6 开始运行..
      [2019-01-28 12:03:05.081777] INFO: bigquant: stockpool_select.v6 运行完成[550.66718s].
      [2019-01-28 12:03:05.087136] INFO: bigquant: cached.v3 开始运行..
      [2019-01-28 12:03:07.811592] INFO: bigquant: cached.v3 运行完成[2.724433s].
      [2019-01-28 12:03:07.815108] INFO: bigquant: cached.v3 开始运行..
      [2019-01-28 12:03:08.751433] INFO: bigquant: cached.v3 运行完成[0.936307s].
      [2019-01-28 12:03:08.908095] INFO: bigquant: backtest.v8 开始运行..
      [2019-01-28 12:03:08.910505] INFO: bigquant: biglearning backtest:V8.1.7
      [2019-01-28 12:03:10.089203] INFO: bigquant: product_type:stock by specified
      [2019-01-28 12:03:38.987652] INFO: bigquant: 读取股票行情完成:4233612
      [2019-01-28 12:04:26.677325] INFO: algo: TradingAlgorithm V1.4.5
      [2019-01-28 12:04:38.627758] INFO: algo: trading transform...
      [2019-01-28 12:04:44.850438] INFO: Performance: Simulated 1220 trading days out of 1220.
      [2019-01-28 12:04:44.851789] INFO: Performance: first open: 2014-01-02 09:30:00+00:00
      [2019-01-28 12:04:44.853090] INFO: Performance: last close: 2018-12-28 15:00:00+00:00
      
      • 收益率101.09%
      • 年化收益率15.52%
      • 基准收益率29.21%
      • 阿尔法0.1
      • 贝塔0.61
      • 夏普比率0.66
      • 胜率1.0
      • 盈亏比0.0
      • 收益波动率20.52%
      • 信息比率0.03
      • 最大回撤27.95%
      [2019-01-28 12:04:49.952407] INFO: bigquant: backtest.v8 运行完成[101.044324s].