fix issue where market orders are not detected as reduce_only

This commit is contained in:
Saleh Mir
2021-03-08 17:08:34 +01:00
parent 34001e860d
commit 816bdf0aea
4 changed files with 64 additions and 85 deletions

View File

@@ -37,14 +37,6 @@ class Broker:
if price < 0:
raise ValueError('price cannot be negative.')
# if price <= self.position.current_price:
# raise OrderNotAllowed(
# 'Cannot LIMIT sell at ${} when current_price is ${}'.format(
# price,
# self.position.current_price
# )
# )
return self.api.limit_order(
self.exchange,
self.symbol,
@@ -74,14 +66,6 @@ class Broker:
if price < 0:
raise ValueError('price cannot be negative.')
# if price >= self.position.current_price:
# raise OrderNotAllowed(
# 'Cannot LIMIT buy at ${} when current_price is ${}'.format(
# price,
# self.position.current_price
# )
# )
return self.api.limit_order(
self.exchange,
self.symbol,
@@ -109,23 +93,6 @@ class Broker:
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
)
)
if price == self.position.current_price:
return self.api.market_order(
self.exchange,
@@ -137,15 +104,28 @@ class Broker:
[order_flags.REDUCE_ONLY]
)
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.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 start_profit_at(self, side: str, qty: float, price: float, role: str = None) -> Order:
self._validate_qty(qty)

View File

@@ -522,33 +522,13 @@ class Strategy(ABC):
for o in self._take_profit:
self._log_take_profit.append(o)
if o[1] == self.price:
if self.is_long:
self._take_profit_orders.append(
self.broker.sell_at_market(o[0], role=order_roles.CLOSE_POSITION)
)
elif self.is_short:
self._take_profit_orders.append(
self.broker.buy_at_market(o[0], role=order_roles.CLOSE_POSITION)
)
else:
if (self.is_long and o[1] > self.price) or (self.is_short and o[1] < self.price):
self._take_profit_orders.append(
self.broker.reduce_position_at(
o[0],
o[1],
order_roles.CLOSE_POSITION
)
)
elif (self.is_long and o[1] < self.price) or (self.is_short and o[1] > self.price):
self._take_profit_orders.append(
self.broker.stop_loss_at(
o[0],
o[1],
order_roles.CLOSE_POSITION
)
)
self._take_profit_orders.append(
self.broker.reduce_position_at(
o[0],
o[1],
order_roles.CLOSE_POSITION
)
)
if self.position.is_open and self.stop_loss is not None:
self._validate_stop_loss()
@@ -574,23 +554,13 @@ class Strategy(ABC):
for o in self._stop_loss:
self._log_stop_loss.append(o)
if o[1] == self.price:
if self.is_long:
self._stop_loss_orders.append(
self.broker.sell_at_market(o[0], role=order_roles.CLOSE_POSITION)
)
elif self.is_short:
self._stop_loss_orders.append(
self.broker.buy_at_market(o[0], role=order_roles.CLOSE_POSITION)
)
else:
self._stop_loss_orders.append(
self.broker.stop_loss_at(
o[0],
o[1],
order_roles.CLOSE_POSITION
)
self._stop_loss_orders.append(
self.broker.reduce_position_at(
o[0],
o[1],
order_roles.CLOSE_POSITION
)
)
except TypeError:
raise exceptions.InvalidStrategy(
'Something odd is going on with your strategy. '

View File

@@ -0,0 +1,25 @@
from jesse.strategies import Strategy
from jesse import utils
class TestReduceOnlyMarketOrders(Strategy):
def should_long(self) -> bool:
return self.price == 10
def should_short(self) -> bool:
return False
def go_long(self):
entry = self.price
qty = utils.size_to_qty(self.capital, entry, fee_rate=self.fee_rate)
self.buy = qty, entry
def go_short(self):
pass
def should_cancel(self):
return False
def update_position(self):
if self.price == 20:
self.liquidate()

View File

@@ -891,6 +891,10 @@ def test_leverage_property():
single_route_backtest('TestLeverageProperty2', is_futures_trading=True, leverage=2)
def test_reduce_only_market_orders():
single_route_backtest('TestReduceOnlyMarketOrders', is_futures_trading=True, leverage=1)
# def test_route_capital_isolation():
# set_up(
# [