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

[GridTrading] add test and log #1426

Merged
merged 1 commit into from
Jan 26, 2025
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
13 changes: 11 additions & 2 deletions Trading/Mode/grid_trading_mode/grid_trading.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ async def _generate_staggered_orders(self, current_price, ignore_available_funds
highest_buy = current_price
lowest_sell = current_price
origin_created_buy_orders_count, origin_created_sell_orders_count = self._get_origin_orders_count(
sorted_orders, recently_closed_trades
recently_closed_trades, sorted_orders
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😮

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it has not consequence but i prefer fixing it ^^

)

min_max_total_order_price_delta = (
Expand Down Expand Up @@ -485,6 +485,12 @@ async def _generate_staggered_orders(self, current_price, ignore_available_funds
self.logger.info(
f"{len(missing_orders)} missing {self.symbol} orders on {self.exchange_name}: {missing_orders}"
)
else:
self.logger.info(
f"All {len(sorted_orders)} out of {self.buy_orders_count + self.sell_orders_count} {self.symbol} "
f"target orders are in place on {self.exchange_name}"
)

await self._handle_missed_mirror_orders_fills(recently_closed_trades, missing_orders, current_price)
try:
# apply state and (re)create missing orders
Expand Down Expand Up @@ -515,10 +521,13 @@ def _get_origin_orders_count(self, recent_trades, open_orders):
origin_created_buy_orders_count = self.buy_orders_count
origin_created_sell_orders_count = self.sell_orders_count
if recent_trades:
# in case all initial orders didn't get created, try to infer the original value from open orders and trades
buy_orders_count = len([order for order in open_orders if order.side is trading_enums.TradeOrderSide.BUY])
buy_trades_count = len([trade for trade in recent_trades if trade.side is trading_enums.TradeOrderSide.BUY])
origin_created_buy_orders_count = buy_orders_count + buy_trades_count
origin_created_sell_orders_count = len(open_orders) + len(recent_trades) - origin_created_buy_orders_count
origin_created_sell_orders_count = (
len(open_orders) + len(recent_trades) - origin_created_buy_orders_count
)
return origin_created_buy_orders_count, origin_created_sell_orders_count

def _get_grid_trades_or_orders(self, trades_or_orders):
Expand Down
73 changes: 73 additions & 0 deletions Trading/Mode/grid_trading_mode/tests/test_grid_trading_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,79 @@ async def test_start_after_offline_x_filled_and_price_back_should_buy_to_recreat
_check_created_orders(producer, trading_api.get_open_orders(exchange_manager), 200)


async def test_start_after_offline_x_filled_and_missing_should_recreate_sell():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

symbol = "BTC/USDT"
async with _get_tools(symbol) as (producer, _, exchange_manager):
# forced config
producer.buy_funds = producer.sell_funds = 0
producer.allow_order_funds_redispatch = True
producer.buy_orders_count = producer.sell_orders_count = 5
producer.compensate_for_missed_mirror_order = True
producer.enable_trailing_down = False
producer.enable_trailing_up = True
producer.flat_increment = decimal.Decimal(100)
producer.flat_spread = decimal.Decimal(300)
producer.reinvest_profits = False
producer.sell_volume_per_order = producer.buy_volume_per_order = False
producer.starting_price = 0
producer.use_existing_orders_only = False
producer.use_fixed_volume_for_mirror_orders = False

orders_count = producer.buy_orders_count + producer.sell_orders_count


initial_price = decimal.Decimal("105278.1")
trading_api.force_set_mark_price(exchange_manager, producer.symbol, initial_price)
btc_pf = trading_api.get_portfolio_currency(exchange_manager, "BTC")
usdt_pf = trading_api.get_portfolio_currency(exchange_manager, "USDT")
btc_pf.available = decimal.Decimal("0.00141858")
btc_pf.total = decimal.Decimal("0.00141858")
usdt_pf.available = decimal.Decimal("150.505098")
usdt_pf.total = decimal.Decimal("150.505098")

await producer._ensure_staggered_orders()
await asyncio.create_task(_check_open_orders_count(exchange_manager, orders_count))
original_orders = copy.copy(trading_api.get_open_orders(exchange_manager))
assert len(original_orders) == orders_count
assert sorted([
order.origin_price for order in original_orders
]) == [
# buy orders
decimal.Decimal('104728.1'), decimal.Decimal('104828.1'), decimal.Decimal('104928.1'),
decimal.Decimal('105028.1'), decimal.Decimal('105128.1'),
# sell orders
decimal.Decimal('105428.1'), decimal.Decimal('105528.1'), decimal.Decimal('105628.1'),
decimal.Decimal('105728.1'), decimal.Decimal('105828.1')
]

# price goes down to 105120, 105128.1 order gets filled
price = decimal.Decimal("105120")
# offline simulation: price goes down to 105120, 105128.1 order gets filled
offline_filled = [order for order in original_orders if order.origin_price == decimal.Decimal('105128.1')]
assert len(offline_filled) == 1
assert offline_filled[0].side == trading_enums.TradeOrderSide.BUY
for order in offline_filled:
await _fill_order(order, exchange_manager, trigger_update_callback=False, producer=producer)
assert len(trading_api.get_open_orders(exchange_manager)) == orders_count - len(offline_filled)
assert btc_pf.available == decimal.Decimal('0.00028861409')
assert btc_pf.total == decimal.Decimal('0.00170420409')
assert usdt_pf.available == decimal.Decimal('0.247225519')
assert usdt_pf.total == decimal.Decimal('120.447922929')

# back online: restore orders according to current price
trading_api.force_set_mark_price(exchange_manager, producer.symbol, price)
with _assert_missing_orders_count(producer, len(offline_filled)):
await producer._ensure_staggered_orders()
# restored orders
await asyncio.create_task(_check_open_orders_count(exchange_manager, orders_count))
open_orders = trading_api.get_open_orders(exchange_manager)
# there is now 6 sell orders
assert len([order for order in open_orders if order.side is trading_enums.TradeOrderSide.SELL]) == 6
# there is now 4 buy orders
assert len([order for order in open_orders if order.side is trading_enums.TradeOrderSide.BUY]) == 4
_check_created_orders(producer, trading_api.get_open_orders(exchange_manager), initial_price)


async def test_start_after_offline_1_filled_should_create_buy():
symbol = "BTC/USDT"
async with _get_tools(symbol) as (producer, _, exchange_manager):
Expand Down
Loading