@@ -56,6 +56,7 @@ class AbstractAuthenticatedExchangeTester:
56
56
SYMBOL = f"{ ORDER_CURRENCY } /{ SETTLEMENT_CURRENCY } "
57
57
TIME_FRAME = "1h"
58
58
VALID_ORDER_ID = "8bb80a81-27f7-4415-aa50-911ea46d841c"
59
+ ALLOW_0_MAKER_FEES = False
59
60
SPECIAL_ORDER_TYPES_BY_EXCHANGE_ID : dict [
60
61
str , (
61
62
str , # symbol
@@ -76,6 +77,7 @@ class AbstractAuthenticatedExchangeTester:
76
77
# closed orders fees are taken from recent trades
77
78
EXPECT_MISSING_FEE_IN_CANCELLED_ORDERS = True # when get_cancelled_orders returns None in fee
78
79
EXPECT_POSSIBLE_ORDER_NOT_FOUND_DURING_ORDER_CREATION = False
80
+ CONVERTS_MARKET_INTO_LIMIT_ORDERS = False # when market orders are always converted into limit order by the exchange
79
81
OPEN_ORDERS_IN_CLOSED_ORDERS = False
80
82
CANCELLED_ORDERS_IN_CLOSED_ORDERS = False
81
83
EXPECT_FETCH_ORDER_TO_BE_AVAILABLE = True
@@ -357,6 +359,8 @@ def assert_has_at_least_one_authenticated_call(calls):
357
359
amount = self .get_order_size (
358
360
portfolio , price , symbol = self .SYMBOL , settlement_currency = self .SETTLEMENT_CURRENCY
359
361
) * 100000
362
+ if amount == 0 :
363
+ amount = 100000
360
364
if self .CHECK_EMPTY_ACCOUNT :
361
365
amount = 10
362
366
# (amount is too large, creating buy order will fail)
@@ -477,6 +481,7 @@ async def inner_test_get_special_orders(self):
477
481
# return
478
482
for exchange_id , order_details in self .SPECIAL_ORDER_TYPES_BY_EXCHANGE_ID .items ():
479
483
symbol , info_key , info_type , expected_type , expected_side , expected_trigger_above = order_details
484
+ print (order_details )
480
485
fetched_order = await self .exchange_manager .exchange .get_order (exchange_id , symbol = symbol )
481
486
assert fetched_order is not None
482
487
self ._check_fetched_order_dicts ([fetched_order ])
@@ -561,7 +566,7 @@ async def inner_test_create_and_cancel_limit_orders(self, symbol=None, settlemen
561
566
open_orders = await self .get_open_orders (exchange_data )
562
567
cancelled_orders = await self .get_cancelled_orders (exchange_data )
563
568
if self .CHECK_EMPTY_ACCOUNT :
564
- assert size == trading_constants .ZERO
569
+ assert size >= trading_constants . ZERO if enable_min_size_check else size == trading_constants .ZERO
565
570
assert open_orders == []
566
571
assert cancelled_orders == []
567
572
return
@@ -649,7 +654,9 @@ async def test_create_and_cancel_stop_orders(self):
649
654
async def inner_test_create_and_cancel_stop_orders (self ):
650
655
current_price = await self .get_price ()
651
656
price = self .get_order_price (current_price , False )
652
- size = self .get_order_size (await self .get_portfolio (), price )
657
+ portfolio = await self .get_portfolio ()
658
+ base = symbols .parse_symbol (self .SYMBOL ).base
659
+ size = self .get_order_size (portfolio , price , settlement_currency = base )
653
660
open_orders = await self .get_open_orders ()
654
661
assert self .exchange_manager .exchange .is_supported_order_type (
655
662
trading_enums .TraderOrderType .STOP_LOSS
@@ -1007,7 +1014,7 @@ def check_parsed_closed_order(
1007
1014
assert order .fee is None
1008
1015
else :
1009
1016
try :
1010
- assert order .fee
1017
+ assert order .fee , f"Unexpected missing fee: { order . to_dict () } "
1011
1018
assert isinstance (order .fee [trading_enums .FeePropertyColumns .COST .value ], decimal .Decimal )
1012
1019
has_paid_fees = order .fee [trading_enums .FeePropertyColumns .COST .value ] > trading_constants .ZERO
1013
1020
if has_paid_fees :
@@ -1024,7 +1031,12 @@ def check_parsed_closed_order(
1024
1031
else :
1025
1032
assert order .fee [trading_enums .FeePropertyColumns .IS_FROM_EXCHANGE .value ] is True
1026
1033
except AssertionError :
1027
- if allow_incomplete_fees and self .EXPECT_MISSING_ORDER_FEES_DUE_TO_ORDERS_TOO_OLD_FOR_RECENT_TRADES :
1034
+ if (
1035
+ not order .fee and self .ALLOW_0_MAKER_FEES and
1036
+ order .taker_or_maker == trading_enums .ExchangeConstantsOrderColumns .MAKER .value
1037
+ ):
1038
+ incomplete_fee_orders .append (order )
1039
+ elif allow_incomplete_fees and self .EXPECT_MISSING_ORDER_FEES_DUE_TO_ORDERS_TOO_OLD_FOR_RECENT_TRADES :
1028
1040
incomplete_fee_orders .append (order )
1029
1041
else :
1030
1042
raise
@@ -1059,7 +1071,7 @@ def check_raw_trades(self, trades):
1059
1071
1060
1072
def check_parsed_trade (self , trade : personal_data .Trade ):
1061
1073
assert trade .symbol
1062
- assert trade .total_cost
1074
+ assert trade .total_cost > 0
1063
1075
assert trade .trade_type
1064
1076
assert trade .trade_type is not trading_enums .TraderOrderType .UNKNOWN
1065
1077
assert trade .exchange_trade_type is not trading_enums .TradeOrderType .UNKNOWN
@@ -1198,8 +1210,10 @@ def get_order_size(self, portfolio, price, symbol=None, order_size=None, settlem
1198
1210
symbol = symbols .parse_symbol (symbol or self .SYMBOL )
1199
1211
if symbol .is_inverse ():
1200
1212
order_quantity = currency_quantity * price
1201
- else :
1213
+ elif settlement_currency == symbol . quote :
1202
1214
order_quantity = currency_quantity / price
1215
+ else :
1216
+ order_quantity = currency_quantity
1203
1217
return personal_data .decimal_adapt_quantity (
1204
1218
self .exchange_manager .exchange .get_market_status (str (symbol )),
1205
1219
order_quantity
@@ -1284,8 +1298,12 @@ def check_created_limit_order(self, order, price, size, side):
1284
1298
1285
1299
def check_created_market_order (self , order , size , side ):
1286
1300
self ._check_order (order , size , side )
1287
- expected_type = personal_data .BuyMarketOrder \
1288
- if side is trading_enums .TradeOrderSide .BUY else personal_data .SellMarketOrder
1301
+ if self .CONVERTS_MARKET_INTO_LIMIT_ORDERS :
1302
+ expected_type = personal_data .BuyLimitOrder \
1303
+ if side is trading_enums .TradeOrderSide .BUY else personal_data .SellLimitOrder
1304
+ else :
1305
+ expected_type = personal_data .BuyMarketOrder \
1306
+ if side is trading_enums .TradeOrderSide .BUY else personal_data .SellMarketOrder
1289
1307
assert isinstance (order , expected_type )
1290
1308
1291
1309
def check_created_stop_order (self , order , price , size , side ):
@@ -1310,10 +1328,13 @@ def check_portfolio_changed(self, previous_portfolio, updated_portfolio, has_inc
1310
1328
def _check_order (self , order , size , side ):
1311
1329
if self .CONVERTS_ORDER_SIZE_BEFORE_PUSHING_TO_EXCHANGES :
1312
1330
# actual origin_quantity may vary due to quantity conversion for market orders
1313
- assert size * decimal .Decimal ("0.8" ) <= order .origin_quantity <= size * decimal .Decimal ("1.2" )
1331
+ assert size * decimal .Decimal ("0.8" ) <= order .origin_quantity <= size * decimal .Decimal ("1.2" ), (
1332
+ f"FALSE: { size * decimal .Decimal ('0.8' )} <= { order .origin_quantity } <= { size * decimal .Decimal ('1.2' )} "
1333
+ )
1314
1334
else :
1315
1335
assert order .origin_quantity == size
1316
1336
assert order .side is side
1337
+ assert order .total_cost > trading_constants .ZERO
1317
1338
assert order .is_open ()
1318
1339
1319
1340
async def wait_for_order_exchange_id_in_trades (self , order_exchange_id ):
0 commit comments