def bought_value(self): """ [已弃用] """ user_system_log.warn( _(u"[abandon] {} is no longer valid.").format( 'stock_position.bought_value')) return self._quantity * self._avg_price
def average_cost(self): """ [已弃用] 请使用 avg_price 获取持仓买入均价 """ user_system_log.warn( _(u"[abandon] {} is no longer valid.").format( 'stock_position.average_cost')) return self._avg_price
def sold_value(self): """ [已弃用] """ user_system_log.warn( _(u"[abandon] {} is no longer valid.").format( 'stock_position.sold_value')) return 0
def set_state(self, state): dict_data = pickle.loads(state) for key, value in six.iteritems(dict_data): try: self.__dict__[key] = pickle.loads(value) system_log.debug("restore context.{} {}", key, type(self.__dict__[key])) except Exception as e: user_system_log.warn('context.{} can not restore', key)
def get_state(self): dict_data = {} for key, value in six.iteritems(self.__dict__): try: dict_data[key] = pickle.dumps(value) except Exception as e: user_detail_log.exception("g.{} can not pickle", key) user_system_log.warn("g.{} can not pickle", key) return pickle.dumps(dict_data)
def get_state(self): dict_data = {} for key, value in six.iteritems(self.__dict__): if key.startswith("_"): continue try: dict_data[key] = pickle.dumps(value) except Exception as e: user_system_log.warn("context.{} can not pickle", key) return pickle.dumps(dict_data)
def _on_settlement(self, event): for position in list(self._positions.values()): order_book_id = position.order_book_id if position.is_de_listed() and position.quantity != 0: if Environment.get_instance( ).config.validator.cash_return_by_stock_delisted: self._total_cash += position.market_value user_system_log.warn( _(u"{order_book_id} is expired, close all positions by system" ).format(order_book_id=order_book_id)) self._positions.pop(order_book_id, None) elif position.quantity == 0: self._positions.pop(order_book_id, None) else: position.apply_settlement() self._transaction_cost = 0 self._backward_trade_set.clear() self._handle_dividend_book_closure(event.trading_dt.date())
def __init__(self, event_bus, scope, ucontext): self._user_context = ucontext self._current_universe = set() self._init = scope.get('init', None) self._handle_bar = scope.get('handle_bar', None) self._handle_tick = scope.get('handle_tick', None) func_before_trading = scope.get('before_trading', None) if func_before_trading is not None and func_before_trading.__code__.co_argcount > 1: self._before_trading = lambda context: func_before_trading(context, None) user_system_log.warn(_(u"deprecated parameter[bar_dict] in before_trading function.")) else: self._before_trading = func_before_trading self._after_trading = scope.get('after_trading', None) if self._before_trading is not None: event_bus.add_listener(EVENT.BEFORE_TRADING, self.before_trading) if self._handle_bar is not None: event_bus.add_listener(EVENT.BAR, self.handle_bar) if self._handle_tick is not None: event_bus.add_listener(EVENT.TICK, self.handle_tick) if self._after_trading is not None: event_bus.add_listener(EVENT.AFTER_TRADING, self.after_trading) self._before_day_trading = scope.get('before_day_trading', None) self._before_night_trading = scope.get('before_night_trading', None) if self._before_day_trading is not None: user_system_log.warn(_(u"[deprecated] before_day_trading is no longer used. use before_trading instead.")) if self._before_night_trading is not None: user_system_log.warn(_(u"[deprecated] before_night_trading is no longer used. use before_trading instead."))
def _is_valid_instrument(self, func_name, value): config = Environment.get_instance().config global index_contract_warning_flag if isinstance(value, six.string_types): if config.base.run_type == RUN_TYPE.PAPER_TRADING: if "88" in value: raise RQInvalidArgument( _(u"Main Future contracts[88] are not supported in paper trading." )) if "99" in value: raise RQInvalidArgument( _(u"Index Future contracts[99] are not supported in paper trading." )) else: if "88" in value: global main_contract_warning_flag if main_contract_warning_flag: main_contract_warning_flag = False user_system_log.warn( _(u"Main Future contracts[88] are not supported in paper trading." )) if "99" in value: global index_contract_warning_flag if index_contract_warning_flag: index_contract_warning_flag = False user_system_log.warn( _(u"Index Future contracts[99] are not supported in paper trading." )) instrument = Environment.get_instance().get_instrument(value) if instrument is None: self.raise_not_valid_instrument_error(func_name, self._arg_name, value) return if isinstance(value, Instrument): return self.raise_not_valid_instrument_error(func_name, self._arg_name, value)
def order(id_or_ins, amount, side, position_effect, style): if not isinstance(style, OrderStyle): raise RuntimeError if amount <= 0: raise RuntimeError if isinstance(style, LimitOrder) and style.get_limit_price() <= 0: raise RQInvalidArgument(_(u"Limit order price should be positive")) order_book_id = assure_future_order_book_id(id_or_ins) env = Environment.get_instance() price = env.get_last_price(order_book_id) if np.isnan(price): user_system_log.warn( _(u"Order Creation Failed: [{order_book_id}] No market data"). format(order_book_id=order_book_id)) return amount = int(amount) r_order = Order.__from_create__(env.calendar_dt, env.trading_dt, order_book_id, amount, side, style, position_effect) if np.isnan(price) or price == 0: user_system_log.warn( _(u"Order Creation Failed: [{order_book_id}] No market data"). format(order_book_id=order_book_id)) r_order.mark_rejected( _(u"Order Creation Failed: [{order_book_id}] No market data"). format(order_book_id=order_book_id)) return r_order if r_order.type == ORDER_TYPE.MARKET: r_order.set_frozen_price(price) if env.can_submit_order(r_order): env.broker.submit_order(r_order) return r_order
def _settlement(self, event): old_margin = self.margin old_holding_pnl = self.holding_pnl for position in list(self._positions.values()): order_book_id = position.order_book_id if position.is_de_listed() and position.buy_quantity + position.sell_quantity != 0: self._total_cash += position.market_value * position.margin_rate user_system_log.warn( _(u"{order_book_id} is expired, close all positions by system").format(order_book_id=order_book_id)) del self._positions[order_book_id] elif position.buy_quantity == 0 and position.sell_quantity == 0: del self._positions[order_book_id] else: position.apply_settlement() self._total_cash = self._total_cash + (old_margin - self.margin) + old_holding_pnl self._transaction_cost = 0 # 如果 total_value <= 0 则认为已爆仓,清空仓位,资金归0 if self.total_value <= 0: self._positions.clear() self._total_cash = 0 self._backward_trade_set.clear()
def pnl(self): """ [已弃用] 请使用 total_value """ user_system_log.warn(_(u"[abandon] {} is no longer used.").format('account.pnl')) return 0
def starting_cash(self): """ [已弃用] 请使用 total_value """ user_system_log.warn(_(u"[abandon] {} is no longer used.").format('account.starting_cash')) return 0
def portfolio_value(self): """ [已弃用] 请使用 total_value """ user_system_log.warn(_(u"[abandon] {} is no longer used.").format('account.portfolio_value')) return self.total_value
def short_selling_allowed(self, value): user_system_log.warn(_(u"[abandon] {} is no longer used.").format('context.short_selling_allowed'))
def commission(self, value): user_system_log.warn(_(u"[abandon] {} is no longer used.").format('context.commission'))
def margin_rate(self, value): user_system_log.warn(_(u"[abandon] {} is no longer used.").format('context.margin_rate'))
def slippage(self, value): user_system_log.warn(_(u"[abandon] {} is no longer used.").format('context.slippage'))
def order_shares(id_or_ins, amount, style=MarketOrder()): """ 落指定股数的买/卖单,最常见的落单方式之一。如有需要落单类型当做一个参量传入,如果忽略掉落单类型,那么默认是市价单(market order)。 :param id_or_ins: 下单标的物 :type id_or_ins: :class:`~Instrument` object | `str` :param int amount: 下单量, 正数代表买入,负数代表卖出。将会根据一手xx股来向下调整到一手的倍数,比如中国A股就是调整成100股的倍数。 :param style: 下单类型, 默认是市价单。目前支持的订单类型有 :class:`~LimitOrder` 和 :class:`~MarketOrder` :type style: `OrderStyle` object :return: :class:`~Order` object :example: .. code-block:: python #购买Buy 2000 股的平安银行股票,并以市价单发送: order_shares('000001.XSHE', 2000) #卖出2000股的平安银行股票,并以市价单发送: order_shares('000001.XSHE', -2000) #购买1000股的平安银行股票,并以限价单发送,价格为¥10: order_shares('000001.XSHG', 1000, style=LimitOrder(10)) """ if amount is 0: # 如果下单量为0,则认为其并没有发单,则直接返回None return None if not isinstance(style, OrderStyle): raise RQInvalidArgument(_(u"style should be OrderStyle")) if isinstance(style, LimitOrder): if style.get_limit_price() <= 0: raise RQInvalidArgument(_(u"Limit order price should be positive")) order_book_id = assure_stock_order_book_id(id_or_ins) env = Environment.get_instance() price = env.get_last_price(order_book_id) if np.isnan(price): user_system_log.warn( _(u"Order Creation Failed: [{order_book_id}] No market data"). format(order_book_id=order_book_id)) return if amount > 0: side = SIDE.BUY else: amount = abs(amount) side = SIDE.SELL round_lot = int(env.get_instrument(order_book_id).round_lot) try: amount = int(Decimal(amount) / Decimal(round_lot)) * round_lot except ValueError: amount = 0 r_order = Order.__from_create__(env.calendar_dt, env.trading_dt, order_book_id, amount, side, style, None) if price == 0: user_system_log.warn( _(u"Order Creation Failed: [{order_book_id}] No market data"). format(order_book_id=order_book_id)) r_order.mark_rejected( _(u"Order Creation Failed: [{order_book_id}] No market data"). format(order_book_id=order_book_id)) return r_order if amount == 0: # 如果计算出来的下单量为0, 则不生成Order, 直接返回None # 因为很多策略会直接在handle_bar里面执行order_target_percent之类的函数,经常会出现下一个量为0的订单,如果这些订单都生成是没有意义的。 r_order.mark_rejected(_(u"Order Creation Failed: 0 order quantity")) return r_order if r_order.type == ORDER_TYPE.MARKET: r_order.set_frozen_price(price) if env.can_submit_order(r_order): env.broker.submit_order(r_order) return r_order
def mark_rejected(self, reject_reason): if not self.is_final(): self._message = reject_reason self._status = ORDER_STATUS.REJECTED user_system_log.warn(reject_reason)
def daily_realized_pnl(self): """ [已弃用] 请使用 realized_pnl """ user_system_log.warn(_(u"[abandon] {} is no longer used.").format('future_account.daily_realized_pnl')) return self.realized_pnl
def total_trades(self): """abandon""" user_system_log.warn( _(u"[abandon] {} is no longer valid.").format( 'position.total_trades')) return 0
def future_portfolio(self): user_system_log.warn(_(u"[abandon] {} is no longer used.").format('context.future_portfolio')) return self.future_account
def benchmark(self, value): user_system_log.warn(_(u"[abandon] {} is no longer used.").format('context.benchmark'))
def mark_cancelled(self, cancelled_reason, user_warn=True): if not self.is_final(): self._message = cancelled_reason self._status = ORDER_STATUS.CANCELLED if user_warn: user_system_log.warn(cancelled_reason)
def order_value(id_or_ins, cash_amount, style=MarketOrder()): """ 使用想要花费的金钱买入/卖出股票,而不是买入/卖出想要的股数,正数代表买入,负数代表卖出。股票的股数总是会被调整成对应的100的倍数(在A中国A股市场1手是100股)。当您提交一个卖单时,该方法代表的意义是您希望通过卖出该股票套现的金额。如果金额超出了您所持有股票的价值,那么您将卖出所有股票。需要注意,如果资金不足,该API将不会创建发送订单。 :param id_or_ins: 下单标的物 :type id_or_ins: :class:`~Instrument` object | `str` :param float cash_amount: 需要花费现金购买/卖出证券的数目。正数代表买入,负数代表卖出。 :param style: 下单类型, 默认是市价单。目前支持的订单类型有 :class:`~LimitOrder` 和 :class:`~MarketOrder` :type style: `OrderStyle` object :return: :class:`~Order` object :example: .. code-block:: python #买入价值¥10000的平安银行股票,并以市价单发送。如果现在平安银行股票的价格是¥7.5,那么下面的代码会买入1300股的平安银行,因为少于100股的数目将会被自动删除掉: order_value('000001.XSHE', 10000) #卖出价值¥10000的现在持有的平安银行: order_value('000001.XSHE', -10000) """ if not isinstance(style, OrderStyle): raise RQInvalidArgument(_(u"style should be OrderStyle")) if isinstance(style, LimitOrder): if style.get_limit_price() <= 0: raise RQInvalidArgument(_(u"Limit order price should be positive")) order_book_id = assure_stock_order_book_id(id_or_ins) env = Environment.get_instance() price = env.get_last_price(order_book_id) if np.isnan(price): user_system_log.warn( _(u"Order Creation Failed: [{order_book_id}] No market data"). format(order_book_id=order_book_id)) return if price == 0: return order_shares(order_book_id, 0, style) account = env.portfolio.accounts[ACCOUNT_TYPE.STOCK] round_lot = int(env.get_instrument(order_book_id).round_lot) if cash_amount > 0: cash_amount = min(cash_amount, account.cash) if isinstance(style, MarketOrder): amount = int( Decimal(cash_amount) / Decimal(price) / Decimal(round_lot)) * round_lot else: amount = int( Decimal(cash_amount) / Decimal(style.get_limit_price()) / Decimal(round_lot)) * round_lot # if the cash_amount is larger than you current security’s position, # then it will sell all shares of this security. position = account.positions[order_book_id] amount = downsize_amount(amount, position) return order_shares(order_book_id, amount, style)