def order_target_value(id_or_ins, cash_amount, style=MarketOrder()): """ 买入/卖出并且自动调整该证券的仓位到一个目标价值。如果还没有任何该证券的仓位,那么会买入全部目标价值的证券。如果已经有了该证券的仓位,则会买入/卖出调整该证券的现在仓位和目标仓位的价值差值的数目的证券。需要注意,如果资金不足,该API将不会创建发送订单。 :param id_or_ins: 下单标的物 :type id_or_ins: :class:`~Instrument` object | `str` | List[:class:`~Instrument`] | List[`str`] :param float cash_amount: 最终的该证券的仓位目标价值。 :param style: 下单类型, 默认是市价单。目前支持的订单类型有 :class:`~LimitOrder` 和 :class:`~MarketOrder` :type style: `OrderStyle` object :return: :class:`~Order` object :example: .. code-block:: python #如果现在的投资组合中持有价值¥3000的平安银行股票的仓位并且设置其目标价值为¥10000,以下代码范例会发送价值¥7000的平安银行的买单到市场。(向下调整到最接近每手股数即100的倍数的股数): order_target_value('000001.XSHE', 10000) """ order_book_id = assure_stock_order_book_id(id_or_ins) account = Environment.get_instance().portfolio.accounts[ACCOUNT_TYPE.STOCK] position = account.positions[order_book_id] if cash_amount == 0: return _sell_all_stock(order_book_id, position.quantity, style) return order_value(order_book_id, cash_amount - position.market_value, style)
def order_percent(id_or_ins, percent, style=MarketOrder()): """ 发送一个等于目前投资组合价值(市场价值和目前现金的总和)一定百分比的买/卖单,正数代表买,负数代表卖。股票的股数总是会被调整成对应的一手的股票数的倍数(1手是100股)。百分比是一个小数,并且小于或等于1(<=100%),0.5表示的是50%.需要注意,如果资金不足,该API将不会创建发送订单。 :param id_or_ins: 下单标的物 :type id_or_ins: :class:`~Instrument` object | `str` :param float percent: 占有现有的投资组合价值的百分比。正数表示买入,负数表示卖出。 :param style: 下单类型, 默认是市价单。目前支持的订单类型有 :class:`~LimitOrder` 和 :class:`~MarketOrder` :type style: `OrderStyle` object :return: :class:`~Order` object :example: .. code-block:: python #买入等于现有投资组合50%价值的平安银行股票。如果现在平安银行的股价是¥10/股并且现在的投资组合总价值是¥2000,那么将会买入200股的平安银行股票。(不包含交易成本和滑点的损失): order_percent('000001.XSHG', 0.5) """ if percent < -1 or percent > 1: raise RQInvalidArgument(_(u"percent should between -1 and 1")) account = Environment.get_instance().portfolio.accounts[ACCOUNT_TYPE.STOCK] return order_value(id_or_ins, account.total_value * percent, style)
def order_lots(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 #买入20手的平安银行股票,并且发送市价单: order_lots('000001.XSHE', 20) #买入10手平安银行股票,并且发送限价单,价格为¥10: order_lots('000001.XSHE', 10, style=LimitOrder(10)) """ order_book_id = assure_stock_order_book_id(id_or_ins) round_lot = int( Environment.get_instance().get_instrument(order_book_id).round_lot) return order_shares(id_or_ins, amount * round_lot, style)
def order_to(order_book_id, quantity, price=None): """ 全品种通用智能调仓函数 如果不指定 price, 则相当于 MarketOrder 如果 order_book_id 是股票,则表示仓位调整到多少股 如果 order_book_id 是期货,则进行智能调仓: * quantity 表示调整至某个仓位 * quantity 如果为正数,则先平 SELL 方向仓位,再 BUY 方向开仓 quantity 手 * quantity 如果为负数,则先平 BUY 方向仓位,再 SELL 方向开仓 -quantity 手 :param order_book_id: 下单标的物 :type order_book_id: :class:`~Instrument` object | `str` :param int quantity: 调仓量 :param float price: 下单价格 :return: list[:class:`~Order`] :example: .. code-block:: python # 当前仓位为0 # RB1710 调仓至 BUY 2手 order_to('RB1710', 2) # RB1710 调仓至 SELL 1手 order_to('RB1710', -1) """ order_style = MarketOrder() if price is None else LimitOrder(price) position = Environment.get_instance().portfolio.positions[order_book_id] if position.type == ACCOUNT_TYPE.STOCK: orders = order_stock(order_book_id, quantity - position.quantity, order_style) elif position.type == ACCOUNT_TYPE.FUTURE: orders = order_future( order_book_id, quantity - position.buy_quantity + position.sell_quantity, order_style) else: raise NotImplementedError if isinstance(orders, Order): return [orders] return orders
def sell_close(id_or_ins, amount, style=MarketOrder()): """ 平买仓 :param id_or_ins: 下单标的物 :type id_or_ins: :class:`~Instrument` object | `str` | List[:class:`~Instrument`] | List[`str`] :param int amount: 下单手数 :param style: 下单类型, 默认是市价单。目前支持的订单类型有 :class:`~LimitOrder` 和 :class:`~MarketOrder` :type style: `OrderStyle` object :return: :class:`~Order` object """ return order(id_or_ins, amount, SIDE.SELL, POSITION_EFFECT.CLOSE, style)
def order(order_book_id, quantity, price=None): """ 全品种通用智能调仓函数 如果不指定 price, 则相当于下 MarketOrder 如果 order_book_id 是股票,等同于调用 order_shares 如果 order_book_id 是期货,则进行智能下单: * quantity 表示调仓量 * 如果 quantity 为正数,则先平 Sell 方向仓位,再开 Buy 方向仓位 * 如果 quantity 为负数,则先平 Buy 反向仓位,再开 Sell 方向仓位 :param order_book_id: 下单标的物 :type order_book_id: :class:`~Instrument` object | `str` :param int quantity: 调仓量 :param float price: 下单价格 :return: list[:class:`~Order`] :example: .. code-block:: python # 当前仓位为0 # RB1710 多方向调仓2手:调整后变为 BUY 2手 order('RB1710', 2) # RB1710 空方向调仓3手:先平多方向2手 在开空方向1手,调整后变为 SELL 1手 order('RB1710', -3) """ order_style = MarketOrder() if price is None else LimitOrder(price) position = Environment.get_instance().portfolio.positions[order_book_id] if position.type == ACCOUNT_TYPE.STOCK: orders = order_stock(order_book_id, quantity, order_style) elif position.type == ACCOUNT_TYPE.FUTURE: orders = order_future(order_book_id, quantity, order_style) else: raise NotImplementedError if isinstance(orders, Order): return [orders] return orders
def order_target_percent(id_or_ins, percent, style=MarketOrder()): """ 买入/卖出证券以自动调整该证券的仓位到占有一个指定的投资组合的目标百分比。 * 如果投资组合中没有任何该证券的仓位,那么会买入等于现在投资组合总价值的目标百分比的数目的证券。 * 如果投资组合中已经拥有该证券的仓位,那么会买入/卖出目标百分比和现有百分比的差额数目的证券,最终调整该证券的仓位占据投资组合的比例至目标百分比。 其实我们需要计算一个position_to_adjust (即应该调整的仓位) `position_to_adjust = target_position - current_position` 投资组合价值等于所有已有仓位的价值和剩余现金的总和。买/卖单会被下舍入一手股数(A股是100的倍数)的倍数。目标百分比应该是一个小数,并且最大值应该<=1,比如0.5表示50%。 如果position_to_adjust 计算之后是正的,那么会买入该证券,否则会卖出该证券。 需要注意,如果资金不足,该API将不会创建发送订单。 :param id_or_ins: 下单标的物 :type id_or_ins: :class:`~Instrument` object | `str` | List[:class:`~Instrument`] | List[`str`] :param float percent: 仓位最终所占投资组合总价值的目标百分比。 :param style: 下单类型, 默认是市价单。目前支持的订单类型有 :class:`~LimitOrder` 和 :class:`~MarketOrder` :type style: `OrderStyle` object :return: :class:`~Order` object :example: .. code-block:: python #如果投资组合中已经有了平安银行股票的仓位,并且占据目前投资组合的10%的价值,那么以下代码会买入平安银行股票最终使其占据投资组合价值的15%: order_target_percent('000001.XSHE', 0.15) """ if percent < 0 or percent > 1: raise RQInvalidArgument(_(u"percent should between 0 and 1")) order_book_id = assure_stock_order_book_id(id_or_ins) account = Environment.get_instance().portfolio.accounts[ACCOUNT_TYPE.STOCK] position = account.positions[order_book_id] if percent == 0: return _sell_all_stock(order_book_id, position.quantity, style) return order_value(order_book_id, account.total_value * percent - position.market_value, style)
def buy_close(id_or_ins, amount, style=MarketOrder()): """ 平卖仓 :param id_or_ins: 下单标的物 :type id_or_ins: :class:`~Instrument` object | `str` | List[:class:`~Instrument`] | List[`str`] :param int amount: 下单手数 :param style: 下单类型, 默认是市价单。目前支持的订单类型有 :class:`~LimitOrder` 和 :class:`~MarketOrder` :type style: `OrderStyle` object :return: :class:`~Order` object :example: .. code-block:: python #市价单将现有IF1603空仓买入平仓2张: buy_close('IF1603', 2) """ return order(id_or_ins, amount, SIDE.BUY, POSITION_EFFECT.CLOSE, style)
def buy_open(id_or_ins, amount, style=MarketOrder()): """ 买入开仓。 :param id_or_ins: 下单标的物 :type id_or_ins: :class:`~Instrument` object | `str` | List[:class:`~Instrument`] | List[`str`] :param int amount: 下单手数 :param style: 下单类型, 默认是市价单。目前支持的订单类型有 :class:`~LimitOrder` 和 :class:`~MarketOrder` :type style: `OrderStyle` object :return: :class:`~Order` object :example: .. code-block:: python #以价格为3500的限价单开仓买入2张上期所AG1607合约: buy_open('AG1607', amount=2, style=LimitOrder(3500)) """ return order(id_or_ins, amount, SIDE.BUY, POSITION_EFFECT.OPEN, style)
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 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)