Skip to content

Commit 18f12ce

Browse files
committed
[Orders] handle MissingMinimalExchangeTradeVolume
1 parent b215c32 commit 18f12ce

File tree

3 files changed

+63
-43
lines changed

3 files changed

+63
-43
lines changed

octobot_trading/exchanges/traders/trader.py

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -488,17 +488,22 @@ async def _sell_everything(self, symbol, inverted, timeout=None):
488488
quantity = 0
489489
else:
490490
quantity = current_symbol_holding
491-
for order_quantity, order_price in decimal_order_adapter.decimal_check_and_adapt_order_details_if_necessary(
492-
quantity, price,
493-
symbol_market):
494-
current_order = order_factory.create_order_instance(trader=self,
495-
order_type=order_type,
496-
symbol=symbol,
497-
current_price=order_price,
498-
quantity=order_quantity,
499-
price=order_price)
500-
created_orders.append(
501-
await self.create_order(current_order))
491+
try:
492+
for order_quantity, order_price in decimal_order_adapter.decimal_check_and_adapt_order_details_if_necessary(
493+
quantity, price,
494+
symbol_market):
495+
current_order = order_factory.create_order_instance(trader=self,
496+
order_type=order_type,
497+
symbol=symbol,
498+
current_price=order_price,
499+
quantity=order_quantity,
500+
price=order_price)
501+
created_orders.append(
502+
await self.create_order(current_order))
503+
except errors.MissingMinimalExchangeTradeVolume as error:
504+
self.logger.exception(
505+
error, True,
506+
f"Failed to sell everything - error: {error}")
502507
return created_orders
503508

504509
async def sell_all(self, currencies_to_sell=None, timeout=None):
@@ -558,35 +563,42 @@ async def close_position(self, position, limit_price=None, timeout=1, emit_tradi
558563
_, _, _, price, symbol_market = await order_util.get_pre_order_data(self.exchange_manager,
559564
position.symbol,
560565
timeout=timeout)
561-
for order_quantity, order_price in decimal_order_adapter.decimal_check_and_adapt_order_details_if_necessary(
562-
position.get_quantity_to_close().copy_abs(), price, symbol_market):
563-
564-
if limit_price is not None:
565-
order_type = enums.TraderOrderType.SELL_LIMIT \
566-
if position.is_long() else enums.TraderOrderType.BUY_LIMIT
567-
else:
568-
order_type = enums.TraderOrderType.SELL_MARKET \
569-
if position.is_long() else enums.TraderOrderType.BUY_MARKET
570-
571-
current_order = order_factory.create_order_instance(trader=self,
572-
order_type=order_type,
573-
symbol=position.symbol,
574-
current_price=order_price,
575-
quantity=order_quantity,
576-
price=limit_price
577-
if limit_price is not None else order_price,
578-
reduce_only=True,
579-
close_position=True)
580-
async with signals.remote_signal_publisher(self.exchange_manager, current_order.symbol,
581-
emit_trading_signals):
582-
order = await signals.create_order(
583-
self.exchange_manager,
584-
emit_trading_signals and signals.should_emit_trading_signal(self.exchange_manager),
585-
current_order,
586-
wait_for_creation=wait_for_creation,
587-
creation_timeout=creation_timeout
588-
)
589-
created_orders.append(order)
566+
try:
567+
for order_quantity, order_price in decimal_order_adapter.decimal_check_and_adapt_order_details_if_necessary(
568+
position.get_quantity_to_close().copy_abs(), price, symbol_market):
569+
570+
if limit_price is not None:
571+
order_type = enums.TraderOrderType.SELL_LIMIT \
572+
if position.is_long() else enums.TraderOrderType.BUY_LIMIT
573+
else:
574+
order_type = enums.TraderOrderType.SELL_MARKET \
575+
if position.is_long() else enums.TraderOrderType.BUY_MARKET
576+
577+
current_order = order_factory.create_order_instance(trader=self,
578+
order_type=order_type,
579+
symbol=position.symbol,
580+
current_price=order_price,
581+
quantity=order_quantity,
582+
price=limit_price
583+
if limit_price is not None else order_price,
584+
reduce_only=True,
585+
close_position=True)
586+
async with signals.remote_signal_publisher(self.exchange_manager, current_order.symbol,
587+
emit_trading_signals):
588+
order = await signals.create_order(
589+
self.exchange_manager,
590+
emit_trading_signals and signals.should_emit_trading_signal(self.exchange_manager),
591+
current_order,
592+
wait_for_creation=wait_for_creation,
593+
creation_timeout=creation_timeout
594+
)
595+
created_orders.append(order)
596+
except errors.MissingMinimalExchangeTradeVolume as error:
597+
# this error should never happen as you are
598+
# able to always close a position
599+
self.logger.exception(
600+
error, True,
601+
f"Failed close position - error: {error}")
590602
return created_orders
591603

592604
async def withdraw(self, amount, currency):

octobot_trading/personal_data/orders/decimal_order_adapter.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,11 @@ def decimal_check_and_adapt_order_details_if_necessary(quantity, price, symbol_m
188188

189189
# check total_order_price not < min_cost
190190
if not personal_data.check_cost(float(total_order_price), min_cost):
191-
return []
191+
symbol = f"{symbol_market['symbol']} - " if 'symbol' in symbol_market else ""
192+
raise errors.MissingMinimalExchangeTradeVolume(
193+
f"Order value ({symbol}value: "
194+
f"{total_order_price}) must be at least {min_cost} to open a order "
195+
)
192196

193197
# check total_order_price not > max_cost and valid_quantity not > max_quantity
194198
elif (max_cost is not None and total_order_price > max_cost) or \

tests/personal_data/orders/test_decimal_order_adapter.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from octobot_trading.enums import ExchangeConstantsMarketStatusColumns as Ecmsc
2121
import octobot_trading.personal_data as personal_data
2222
import octobot_trading.constants as constants
23+
import octobot_trading.errors as errors
2324
from tests import event_loop
2425

2526
# All test coroutines will be treated as marked.
@@ -170,8 +171,11 @@ async def test_decimal_check_and_adapt_order_details_if_necessary():
170171
# invalid cost <
171172
quantity = decimal.Decimal(str(0.5))
172173
price = decimal.Decimal(str(1))
173-
assert personal_data.decimal_check_and_adapt_order_details_if_necessary(quantity, price, symbol_market) == []
174-
174+
try:
175+
personal_data.decimal_check_and_adapt_order_details_if_necessary(quantity, price, symbol_market)
176+
assert False
177+
except errors.MissingMinimalExchangeTradeVolume:
178+
assert True
175179
# invalid cost >
176180
quantity = decimal.Decimal(str(10))
177181
price = decimal.Decimal(str(49))

0 commit comments

Comments
 (0)