Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(backtes mode):1 minute candles multiple orders #454

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 38 additions & 8 deletions jesse/modes/backtest_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,17 +396,20 @@ def _get_fixed_jumped_candle(previous_candle: np.ndarray, candle: np.ndarray) ->


def _simulate_price_change_effect(real_candle: np.ndarray, exchange: str, symbol: str) -> None:
orders = store.orders.get_orders(exchange, symbol)

current_temp_candle = real_candle.copy()
executed_order = False

executing_orders = _get_executing_orders(exchange, symbol, real_candle)
if len(executing_orders) > 1:
# extend the candle shape from (6,) to (1,6)
executing_orders = _sort_execution_orders(executing_orders, current_temp_candle[None, :])

while True:
if len(orders) == 0:
if len(executing_orders) == 0:
executed_order = False
else:
for index, order in enumerate(orders):
if index == len(orders) - 1 and not order.is_active:
for index, order in enumerate(executing_orders):
if index == len(executing_orders) - 1 and not order.is_active:
executed_order = False

if not order.is_active:
Expand All @@ -425,6 +428,7 @@ def _simulate_price_change_effect(real_candle: np.ndarray, exchange: str, symbol
executed_order = True

order.execute()
executing_orders = _get_executing_orders(exchange, symbol, real_candle)

# break from the for loop, we'll try again inside the while
# loop with the new current_temp_candle
Expand Down Expand Up @@ -695,6 +699,9 @@ def _simulate_price_change_effect_multiple_candles(
)
executing_orders = _get_executing_orders(exchange, symbol, real_candle)
if len(executing_orders) > 0:
if len(executing_orders) > 1:
executing_orders = _sort_execution_orders(executing_orders, short_timeframes_candles)

for i in range(len(short_timeframes_candles)):
current_temp_candle = short_timeframes_candles[i].copy()
is_executed_order = False
Expand Down Expand Up @@ -768,9 +775,32 @@ def _simulate_price_change_effect_multiple_candles(

def _get_executing_orders(exchange, symbol, real_candle):
orders = store.orders.get_orders(exchange, symbol)
active_orders = [order for order in orders if order.is_active]
return [
order
for order in active_orders
if candle_includes_price(real_candle, order.price)
for order in orders
if order.is_active and candle_includes_price(real_candle, order.price)
]


def _sort_execution_orders(orders: List[Order], short_candles: np.ndarray):
sorted_orders = []
for i in range(len(short_candles)):
included_orders = [
order
for order in orders
if candle_includes_price(short_candles[i], order.price)
]
if len(included_orders) == 1:
sorted_orders.append(included_orders[0])
elif len(included_orders) > 1:
# in case that the orders are above

# note: check the first is enough because I can assume all the orders in the same direction of the price,
# in case it doesn't than i cant really know how the price react in this 1 minute candle..
if short_candles[i, 3] > included_orders[0].price > short_candles[i, 1]:
sorted_orders += sorted(included_orders, key=lambda o: o.price)
else:
sorted_orders += sorted(included_orders, key=lambda o: o.price, reverse=True)
if len(sorted_orders) == len(orders):
break
return sorted_orders
24 changes: 24 additions & 0 deletions jesse/strategies/TestOrdersAreSortedBeforeExecution/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from jesse.strategies import Strategy


class TestOrdersAreSortedBeforeExecution(Strategy):
def should_long(self):
return self.price == 10

def go_long(self):
self.buy = [
(1, 10.2),
(1, 10.3),
(1, 10.1)
]

def on_open_position(self, order) -> None:
# the order with the lowest price should be executed first
assert order.price == 10.1

def update_position(self):
if self.price == 20:
self.liquidate()

def should_cancel_entry(self):
return False
4 changes: 4 additions & 0 deletions tests/test_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ def test_order_is_take_profit_property():

def test_order_value_property():
single_route_backtest('TestOrderValueProperty')


def test_orders_are_sorted():
single_route_backtest('TestOrdersAreSortedBeforeExecution')
Loading