def reduce_position_at(self, qty, price, role=None) -> Order: self._validate_qty(qty) qty = abs(qty) # validation if price < 0: raise ValueError('price cannot be negative.') # validation if self.position.is_close: raise OrderNotAllowed( 'Cannot submit a reduce_position order when there is not open position' ) side = jh.opposite_side(jh.type_to_side(self.position.type)) # validation if side == 'buy' and price >= self.position.current_price: raise OrderNotAllowed( 'Cannot reduce (via LIMIT) buy at ${} when current_price is ${}' .format(price, self.position.current_price)) # validation if side == 'sell' and price <= self.position.current_price: raise OrderNotAllowed( 'Cannot reduce (via LIMIT) sell at ${} when current_price is ${}' .format(price, self.position.current_price)) return self.api.limit_order(self.exchange, self.symbol, qty, price, side, role, [order_flags.REDUCE_ONLY])
def stop_loss_at(self, qty, price, role=None) -> Order: self._validate_qty(qty) # validation if self.position.is_close: raise OrderNotAllowed( 'Cannot submit a (reduce_only) stop_loss order when there is not open position' ) side = jh.opposite_side(jh.type_to_side(self.position.type)) if price < 0: raise ValueError('price cannot be negative.') if side == 'buy' and price < self.position.current_price: raise OrderNotAllowed( 'Cannot submit a buy stop at {} when current price is {}'. format(price, self.position.current_price)) if side == 'sell' and price > self.position.current_price: raise OrderNotAllowed( 'Cannot submit a sell stop at {} when current price is {}.'. format(price, self.position.current_price)) return self.api.stop_order(self.exchange, self.symbol, abs(qty), price, side, role, [order_flags.REDUCE_ONLY])
def reduce_position_at(self, qty: float, price: float, role: str = None) -> Union[Order, None]: self._validate_qty(qty) qty = abs(qty) # validation if price < 0: raise ValueError('price cannot be negative.') # validation if self.position.is_close: raise OrderNotAllowed( 'Cannot submit a reduce_position order when there is no open position' ) side = jh.opposite_side(jh.type_to_side(self.position.type)) if abs(price - self.position.current_price) < 0.0001: return self.api.market_order(self.exchange, self.symbol, qty, price, side, role, [order_flags.REDUCE_ONLY]) elif (side == 'sell' and self.position.type == 'long' and price > self.position.current_price) or ( side == 'buy' and self.position.type == 'short' and price < self.position.current_price): return self.api.limit_order(self.exchange, self.symbol, qty, price, side, role, [order_flags.REDUCE_ONLY]) elif (side == 'sell' and self.position.type == 'long' and price < self.position.current_price) or ( side == 'buy' and self.position.type == 'short' and price > self.position.current_price): return self.api.stop_order(self.exchange, self.symbol, abs(qty), price, side, role, [order_flags.REDUCE_ONLY]) else: raise OrderNotAllowed( "This order doesn't seem to be for reducing the position.")
def test_opposite_side(): assert jh.opposite_side('buy') == 'sell' assert jh.opposite_side('sell') == 'buy'