def _validate_benchmark(config, data_proxy): benchmark = config.base.benchmark if benchmark is None: return instrument = data_proxy.instruments(benchmark) if instrument is None: raise patch_user_exc( ValueError(_(u"invalid benchmark {}").format(benchmark))) if instrument.order_book_id == "000300.XSHG": # 000300.XSHG 数据进行了补齐,因此认为只要benchmark设置了000300.XSHG,就存在数据,不受限于上市日期。 return config = Environment.get_instance().config start_date = config.base.start_date end_date = config.base.end_date if instrument.listed_date.date() > start_date: raise patch_user_exc( ValueError( _(u"benchmark {benchmark} has not been listed on {start_date}" ).format(benchmark=benchmark, start_date=start_date))) if instrument.de_listed_date.date() < end_date: raise patch_user_exc( ValueError( _(u"benchmark {benchmark} has been de_listed on {end_date}"). format(benchmark=benchmark, end_date=end_date)))
def run_monthly(self, func, tradingday=None, time_rule=None, **kwargs): _verify_function('run_monthly', func) if tradingday is None and 'monthday' in kwargs: tradingday = kwargs.pop('monthday') if kwargs: raise patch_user_exc( ValueError('unknown argument: {}'.format(kwargs))) if tradingday is None: raise patch_user_exc(ValueError('tradingday is required')) if not isinstance(tradingday, int): raise patch_user_exc( ValueError('tradingday: <int> excpected, {} got'.format( repr(tradingday)))) if tradingday > 23 or tradingday < -23 or tradingday == 0: raise patch_user_exc( ValueError( 'invalid tradingday, should be in [-23, 0), (0, 23]')) if tradingday > 0: tradingday -= 1 time_checker = self._time_rule_for(time_rule) self._registry.append( (lambda: self._is_nth_trading_day_in_month(tradingday), time_checker, func))
def run_weekly(self, func, weekday=None, tradingday=None, time_rule=None): _verify_function('run_weekly', func) if (weekday is not None and tradingday is not None) or (weekday is None and tradingday is None): raise patch_user_exc( ValueError('select one of weekday/tradingday')) if weekday is not None: if weekday < 1 or weekday > 7: raise patch_user_exc( ValueError('invalid weekday, should be in [1, 7]')) day_checker = lambda: self._is_weekday(weekday - 1) else: if tradingday > 5 or tradingday < -5 or tradingday == 0: raise patch_user_exc( ValueError( 'invalid trading day, should be in [-5, 0), (0, 5]')) if tradingday > 0: tradingday -= 1 day_checker = lambda: self._is_nth_trading_day_in_week(tradingday) time_checker = self._time_rule_for(time_rule) self._registry.append((day_checker, time_checker, func))
def _verify_function(name, func): if not callable(func): raise patch_user_exc( ValueError('scheduler.{}: func should be callable'.format(name))) sig = signature(func) if len(sig.parameters) != 2: raise patch_user_exc( TypeError( 'scheduler.{}: func should take exactly 2 arguments (context, bar_dict)' .format(name)))
def compile_strategy(source_code, strategy, scope): try: code = compile(source_code, strategy, 'exec') six.exec_(code, scope) return scope except Exception as e: exc_type, exc_val, exc_tb = sys.exc_info() exc_val = patch_user_exc(exc_val, force=True) try: msg = str(exc_val) except Exception as e1: msg = "" six.print_(e1) error = CustomError() error.set_msg(msg) error.set_exc(exc_type, exc_val, exc_tb) stackinfos = list(traceback.extract_tb(exc_tb)) if isinstance(e, (SyntaxError, IndentationError)): error.add_stack_info(exc_val.filename, exc_val.lineno, "", exc_val.text) else: for item in stackinfos: filename, lineno, func_name, code = item if strategy == filename: error.add_stack_info(*item) # avoid empty stack if error.stacks_length == 0: error.add_stack_info(*item) raise CustomException(error)
def start_up(self, env, mod_config): if env.config.base.run_type == RUN_TYPE.LIVE_TRADING: return mod_config.matching_type = self.parse_matching_type(mod_config.matching_type) if env.config.base.margin_multiplier <= 0: raise patch_user_exc(ValueError(_(u"invalid margin multiplier value: value range is (0, +∞]"))) if env.config.base.frequency == "tick": mod_config.volume_limit = False if mod_config.matching_type not in [ MATCHING_TYPE.NEXT_TICK_LAST, MATCHING_TYPE.NEXT_TICK_BEST_OWN, MATCHING_TYPE.NEXT_TICK_BEST_COUNTERPARTY, ]: raise RuntimeError(_("Not supported matching type {}").format(mod_config.matching_type)) else: if mod_config.matching_type not in [ MATCHING_TYPE.NEXT_BAR_OPEN, MATCHING_TYPE.CURRENT_BAR_CLOSE, ]: raise RuntimeError(_("Not supported matching type {}").format(mod_config.matching_type)) if mod_config.signal: env.set_broker(SignalBroker(env, mod_config)) else: env.set_broker(SimulationBroker(env, mod_config)) event_source = SimulationEventSource(env) env.set_event_source(event_source)
def start_up(self, env, mod_config): if mod_config.commission_multiplier < 0: raise patch_user_exc( ValueError( _(u"invalid commission multiplier value: value range is [0, +∞)" ))) if env.config.base.market == MARKET.CN: env.set_transaction_cost_decider( DEFAULT_ACCOUNT_TYPE.STOCK, CNStockTransactionCostDecider( mod_config.commission_multiplier, mod_config.cn_stock_min_commission)) env.set_transaction_cost_decider( DEFAULT_ACCOUNT_TYPE.FUTURE, CNFutureTransactionCostDecider( mod_config.commission_multiplier)) elif env.config.base.market == MARKET.HK: env.set_transaction_cost_decider( DEFAULT_ACCOUNT_TYPE.STOCK, HKStockTransactionCostDecider( mod_config.commission_multiplier, mod_config.hk_stock_min_commission))
def __init__(self, rate=0.): if 0 <= rate: self.rate = rate else: raise patch_user_exc( ValueError( _(u"invalid slippage rate value: value range is greater than 0" )))
def __init__(self, rate=0.): # Rate必须在0~1之间 if 0 <= rate < 1: self.rate = rate else: raise patch_user_exc( ValueError( _(u"invalid slippage rate value: value range is [0, 1)")))
def wrapper(*args, **kwargs): phase = cls.stack.top.phase if phase not in phases: raise patch_user_exc( RuntimeError( _(u"You cannot call %s when executing %s") % (func.__name__, phase.value))) return func(*args, **kwargs)
def _get_universe(self): universe = self._env.get_universe() if len( universe ) == 0 and DEFAULT_ACCOUNT_TYPE.STOCK.name not in self._config.base.accounts: raise patch_user_exc(RuntimeError( _("Current universe is empty. Please use subscribe function before trade" )), force=True) return universe
def __getitem__(self, key): if not isinstance(key, six.string_types): raise patch_user_exc(ValueError('invalid key {} (use order_book_id please)'.format(key))) instrument = self._data_proxy.instruments(key) if instrument is None: raise patch_user_exc(ValueError('invalid order book id or symbol: {}'.format(key))) order_book_id = instrument.order_book_id try: return self._cache[order_book_id] except KeyError: try: bar = self._data_proxy.get_bar(order_book_id, self._dt, self._frequency) except Exception as e: system_log.exception(e) raise patch_user_exc(KeyError(_(u"id_or_symbols {} does not exist").format(key))) if bar is None: return BarObject(instrument, NANDict, self._dt) else: self._cache[order_book_id] = bar return bar
def _time_rule_for(self, time_rule): if time_rule == 'before_trading': return lambda: self._is_before_trading() if time_rule is not None and not isinstance(time_rule, int): raise patch_user_exc( ValueError( 'invalid time_rule, "before_trading" or int expected, got {}' .format(repr(time_rule)))) time_rule = time_rule if time_rule else self._minutes_since_midnight( 9, 31) return lambda: self._should_trigger(time_rule)
def get_trade_price(self, order, price): side = order.side tick_size = Environment.get_instance().data_proxy.instruments( order.order_book_id).tick_size() price = price + tick_size * self.rate * (1 if side == SIDE.BUY else -1) if price <= 0: raise patch_user_exc( ValueError( _(u"invalid slippage rate value {} which cause price <= 0" ).format(self.rate))) return price
def deco(*args, **kwargs): try: return func(*args, **kwargs) except RQInvalidArgument: raise except Exception as e: if isinstance(e, TypeError): exc_info = sys.exc_info() try: ret = inspect.getcallargs(unwrapper(func), *args, **kwargs) except TypeError: t, v, tb = exc_info raise patch_user_exc(v.with_traceback(tb)) if getattr(e, EXC_EXT_NAME, EXC_TYPE.NOTSET) == EXC_TYPE.NOTSET: patch_system_exc(e) raise
def _adjust_start_date(config, data_proxy): origin_start_date, origin_end_date = config.base.start_date, config.base.end_date start, end = data_proxy.available_data_range(config.base.frequency) config.base.start_date = max(start, config.base.start_date) config.base.end_date = min(end, config.base.end_date) # for annualized risk indicator calculation config.base.natural_start_date = config.base.start_date config.base.natural_end_date = config.base.end_date config.base.trading_calendar = data_proxy.get_trading_dates( config.base.start_date, config.base.end_date) if len(config.base.trading_calendar) == 0: raise patch_user_exc( ValueError( _(u"There is no data between {start_date} and {end_date}. Please check your" u" data bundle or select other backtest period.").format( start_date=origin_start_date, end_date=origin_end_date))) config.base.start_date = config.base.trading_calendar[0].date() config.base.end_date = config.base.trading_calendar[-1].date() config.base.timezone = pytz.utc