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 too small new order issue and etc #784

Open
wants to merge 2 commits into
base: devel
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 29 additions & 2 deletions dexbot/strategies/staggered_orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ def remove_outside_orders(self, sell_orders, buy_orders):
success = self.cancel_orders_wrapper(orders_to_cancel, batch_only=True)
# Refresh orders to prevent orders outside boundaries being in the future comparisons
self.refresh_orders()
self.refresh_balances(use_cached_orders=True)
# Batch cancel failed, repeat cancelling only one order
if success:
return True
Expand Down Expand Up @@ -741,6 +742,7 @@ def allocate_asset(self, asset, asset_balance):
self.log.debug('Need to allocate {}: {}'.format(asset, asset_balance))
closest_opposite_order = None
closest_opposite_price = 0
closest_opposite_order2 = None # The 2nd closest opposite order
opposite_asset_limit = None
opposite_orders = []
order_type = ''
Expand Down Expand Up @@ -784,6 +786,10 @@ def allocate_asset(self, asset, asset_balance):
if opposite_orders:
closest_opposite_order = opposite_orders[0]
closest_opposite_price = closest_opposite_order['price'] ** -1
try:
closest_opposite_order2 = opposite_orders[1] # Get the 2nd order
except IndexError:
closest_opposite_order2 = opposite_orders[0] # Fall back: get the 1st order
elif asset == 'base':
# For one-sided start, calculate closest_opposite_price empirically
closest_opposite_price = self.market_center_price * (1 + self.target_spread / 2)
Expand Down Expand Up @@ -852,18 +858,32 @@ def allocate_asset(self, asset, asset_balance):
opposite_orders = self.filter_buy_orders(stored_orders, sort='DESC')

try:
opposite_order = opposite_orders[0]
# Note: The 1st opposite order may be a partial order due to
# a) the dust order handling logic (#486), or
# b) on the sell side where partial orders are allowed due to the fall back logic (#485), or
# c) placing max-sized closer order if only one order needed to reach target spread.
# Limiting by it may lead to a lot of small orders being placed, especially when a significant
# price drop or spike occurred on the market. Although they may be upsized later, but if some of
# them got filled before upsizing, it may lead to
# a) small orders being placed on the opposite side which can not be updated to the normal size
# in a relatively long period, and
# b) a lot of "exceeded" funds on the current side which will be used to upsize orders deep down
# in the order book later, which makes the situation worse and harder to recover.
# Using the 2nd closest opposite order mitigates the problem.
# Ideally still need logic to check whether the closest own order is partial and upsize it if so.
Copy link
Author

Choose a reason for hiding this comment

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

Not easy to check and can not always upsize, especially when orders on one side are significantly larger.

Copy link
Author

Choose a reason for hiding this comment

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

Done writing some code. Testing locally.

opposite_order = opposite_orders[1]
self.log.debug('Using stored opposite order')
except IndexError:
self.log.debug('Using real opposite order')
opposite_order = closest_opposite_order
opposite_order = closest_opposite_order2

if (
self.mode == 'mountain'
or (self.mode == 'buy_slope' and asset == 'base')
or (self.mode == 'sell_slope' and asset == 'quote')
):
opposite_asset_limit = None
# TODO The amount may need to be calculated due to the 2nd opposite order used
own_asset_limit = opposite_order['quote']['amount']
self.log.debug(
'Limiting {} order by opposite order: {:.{prec}f} {}'.format(
Expand All @@ -876,7 +896,10 @@ def allocate_asset(self, asset, asset_balance):
or (self.mode == 'buy_slope' and asset == 'quote')
or (self.mode == 'sell_slope' and asset == 'base')
):
# TODO The amount may need to be calculated due to the 2nd opposite order used
opposite_asset_limit = opposite_order['base']['amount']
abitmore marked this conversation as resolved.
Show resolved Hide resolved
if self.mode == 'neutral':
opposite_asset_limit = opposite_asset_limit * math.sqrt(1 + self.increment)
own_asset_limit = None
self.log.debug(
'Limiting {} order by opposite order: {:.{prec}f} {}'.format(
Expand Down Expand Up @@ -1560,6 +1583,10 @@ def replace_partially_filled_order(self, order):
order_type, asset_balance['amount'], needed, order['base']['symbol'], prec=precision
)
)
if order_type == 'sell':
self.quote_asset_threshold = needed
else: # order_type == 'buy'
self.base_asset_threshold = needed

def place_closer_order(
self, asset, order, place_order=True, allow_partial=False, own_asset_limit=None, opposite_asset_limit=None
Expand Down