fix localTrade and trade classe miroring, fix persistence tests

This commit is contained in:
axel
2023-06-14 11:40:30 -04:00
parent 4874d10455
commit 057f852e06
3 changed files with 46 additions and 26 deletions
+24 -4
View File
@@ -495,8 +495,10 @@ class LocalTrade():
) )
def to_json(self, minified: bool = False) -> Dict[str, Any]: def to_json(self, minified: bool = False) -> Dict[str, Any]:
filled_orders = self.select_filled_or_open_orders() filled_or_open_orders = self.select_filled_or_open_orders()
orders = [order.to_json(self.entry_side, minified) for order in filled_orders] orders_json = [order.to_json(self.entry_side, minified) for order in filled_or_open_orders]
open_orders = self.select_open_orders()
open_orders_json = [order.to_json(self.entry_side, minified) for order in open_orders]
return { return {
'trade_id': self.id, 'trade_id': self.id,
@@ -572,11 +574,11 @@ class LocalTrade():
'is_short': self.is_short, 'is_short': self.is_short,
'trading_mode': self.trading_mode, 'trading_mode': self.trading_mode,
'funding_fees': self.funding_fees, 'funding_fees': self.funding_fees,
'open_order_id': self.open_order_id,
'amount_precision': self.amount_precision, 'amount_precision': self.amount_precision,
'price_precision': self.price_precision, 'price_precision': self.price_precision,
'precision_mode': self.precision_mode, 'precision_mode': self.precision_mode,
'orders': orders, 'orders': orders_json,
'open_orders': open_orders_json
} }
@staticmethod @staticmethod
@@ -1064,6 +1066,16 @@ class LocalTrade():
or (o.ft_is_open is True and o.status is not None) or (o.ft_is_open is True and o.status is not None)
] ]
def select_open_orders(self) -> List['Order']:
"""
Finds open orders
:param order_side: Side of the order (either 'buy', 'sell', or None)
:return: array of Order objects
"""
return [o for o in self.orders if
(o.ft_is_open is True and o.status is not None)
]
@property @property
def nr_of_successful_entries(self) -> int: def nr_of_successful_entries(self) -> int:
""" """
@@ -1317,6 +1329,14 @@ class Trade(ModelBase, LocalTrade):
def open_orders(self): def open_orders(self):
return [order for order in self.orders if order.ft_is_open] return [order for order in self.orders if order.ft_is_open]
@hybrid_property
def open_orders_count(self) -> int:
return len(self.open_orders)
@hybrid_property
def open_orders_ids(self) -> list:
return [open_order.order_id for open_order in self.open_orders]
def __init__(self, **kwargs): def __init__(self, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
self.realized_profit = 0 self.realized_profit = 0
+6 -6
View File
@@ -46,7 +46,7 @@ def mock_trade_1(fee, is_short: bool):
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=17), open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=17),
open_rate=0.123, open_rate=0.123,
exchange='binance', exchange='binance',
open_order_id=f'dry_run_buy_{direc(is_short)}_12345', # open_order_id=f'dry_run_buy_{direc(is_short)}_12345',
strategy='StrategyTestV3', strategy='StrategyTestV3',
timeframe=5, timeframe=5,
is_short=is_short is_short=is_short
@@ -103,7 +103,7 @@ def mock_trade_2(fee, is_short: bool):
close_profit_abs=-0.005584127 if is_short else 0.000584127, close_profit_abs=-0.005584127 if is_short else 0.000584127,
exchange='binance', exchange='binance',
is_open=False, is_open=False,
open_order_id=f'dry_run_sell_{direc(is_short)}_12345', # open_order_id=f'dry_run_sell_{direc(is_short)}_12345',
strategy='StrategyTestV3', strategy='StrategyTestV3',
timeframe=5, timeframe=5,
enter_tag='TEST1', enter_tag='TEST1',
@@ -211,7 +211,7 @@ def mock_trade_4(fee, is_short: bool):
is_open=True, is_open=True,
open_rate=0.123, open_rate=0.123,
exchange='binance', exchange='binance',
open_order_id=f'prod_buy_{direc(is_short)}_12345', # open_order_id=f'prod_buy_{direc(is_short)}_12345',
strategy='StrategyTestV3', strategy='StrategyTestV3',
timeframe=5, timeframe=5,
is_short=is_short, is_short=is_short,
@@ -328,7 +328,7 @@ def mock_trade_6(fee, is_short: bool):
exchange='binance', exchange='binance',
strategy='SampleStrategy', strategy='SampleStrategy',
enter_tag='TEST2', enter_tag='TEST2',
open_order_id=f"prod_sell_{direc(is_short)}_6", # open_order_id=f"prod_sell_{direc(is_short)}_6",
timeframe=5, timeframe=5,
is_short=is_short is_short=is_short
) )
@@ -412,7 +412,7 @@ def short_trade(fee):
# close_profit_abs=-0.6925113200000013, # close_profit_abs=-0.6925113200000013,
exchange='binance', exchange='binance',
is_open=True, is_open=True,
open_order_id='dry_run_exit_short_12345', # open_order_id='dry_run_exit_short_12345',
strategy='DefaultStrategy', strategy='DefaultStrategy',
timeframe=5, timeframe=5,
exit_reason='sell_signal', exit_reason='sell_signal',
@@ -503,7 +503,7 @@ def leverage_trade(fee):
close_profit_abs=2.5983135000000175, close_profit_abs=2.5983135000000175,
exchange='kraken', exchange='kraken',
is_open=False, is_open=False,
open_order_id='dry_run_leverage_buy_12368', # open_order_id='dry_run_leverage_buy_12368',
strategy='DefaultStrategy', strategy='DefaultStrategy',
timeframe=5, timeframe=5,
exit_reason='sell_signal', exit_reason='sell_signal',
+16 -16
View File
@@ -491,11 +491,10 @@ def test_update_market_order(market_buy_order_usdt, market_sell_order_usdt, fee,
leverage=1.0, leverage=1.0,
) )
trade.open_order_id = 'mocked_market_buy'
oobj = Order.parse_from_ccxt_object(market_buy_order_usdt, 'ADA/USDT', 'buy') oobj = Order.parse_from_ccxt_object(market_buy_order_usdt, 'ADA/USDT', 'buy')
trade.orders.append(oobj) trade.orders.append(oobj)
trade.update_trade(oobj) trade.update_trade(oobj)
assert trade.open_order_id is None assert len(trade.open_orders) == 0
assert trade.open_rate == 2.0 assert trade.open_rate == 2.0
assert trade.close_profit is None assert trade.close_profit is None
assert trade.close_date is None assert trade.close_date is None
@@ -506,11 +505,10 @@ def test_update_market_order(market_buy_order_usdt, market_sell_order_usdt, fee,
caplog.clear() caplog.clear()
trade.is_open = True trade.is_open = True
trade.open_order_id = 'mocked_market_sell'
oobj = Order.parse_from_ccxt_object(market_sell_order_usdt, 'ADA/USDT', 'sell') oobj = Order.parse_from_ccxt_object(market_sell_order_usdt, 'ADA/USDT', 'sell')
trade.orders.append(oobj) trade.orders.append(oobj)
trade.update_trade(oobj) trade.update_trade(oobj)
assert trade.open_order_id is None assert len(trade.open_orders) == 0
assert trade.close_rate == 2.2 assert trade.close_rate == 2.2
assert pytest.approx(trade.close_profit) == 0.094513715710723 assert pytest.approx(trade.close_profit) == 0.094513715710723
assert trade.close_date is not None assert trade.close_date is not None
@@ -560,7 +558,7 @@ def test_calc_open_close_trade_price(
) )
entry_order = limit_order[trade.entry_side] entry_order = limit_order[trade.entry_side]
exit_order = limit_order[trade.exit_side] exit_order = limit_order[trade.exit_side]
trade.open_order_id = f'something-{is_short}-{lev}-{exchange}' # trade.open_order_id = f'something-{is_short}-{lev}-{exchange}'
oobj = Order.parse_from_ccxt_object(entry_order, 'ADA/USDT', trade.entry_side) oobj = Order.parse_from_ccxt_object(entry_order, 'ADA/USDT', trade.entry_side)
oobj.trade = trade oobj.trade = trade
@@ -658,7 +656,7 @@ def test_calc_close_trade_price_exception(limit_buy_order_usdt, fee):
leverage=1.0, leverage=1.0,
) )
trade.open_order_id = 'something' # trade.open_order_id = 'something'
oobj = Order.parse_from_ccxt_object(limit_buy_order_usdt, 'ADA/USDT', 'buy') oobj = Order.parse_from_ccxt_object(limit_buy_order_usdt, 'ADA/USDT', 'buy')
trade.update_trade(oobj) trade.update_trade(oobj)
assert trade.calc_close_trade_value(trade.close_rate) == 0.0 assert trade.calc_close_trade_value(trade.close_rate) == 0.0
@@ -677,7 +675,7 @@ def test_update_open_order(limit_buy_order_usdt):
trading_mode=margin trading_mode=margin
) )
assert trade.open_order_id is None assert len(trade.open_orders) == 0
assert trade.close_profit is None assert trade.close_profit is None
assert trade.close_date is None assert trade.close_date is None
@@ -685,7 +683,7 @@ def test_update_open_order(limit_buy_order_usdt):
oobj = Order.parse_from_ccxt_object(limit_buy_order_usdt, 'ADA/USDT', 'buy') oobj = Order.parse_from_ccxt_object(limit_buy_order_usdt, 'ADA/USDT', 'buy')
trade.update_trade(oobj) trade.update_trade(oobj)
assert trade.open_order_id is None assert len(trade.open_orders) == 0
assert trade.close_profit is None assert trade.close_profit is None
assert trade.close_date is None assert trade.close_date is None
@@ -758,7 +756,7 @@ def test_calc_open_trade_value(
is_short=is_short, is_short=is_short,
trading_mode=trading_mode trading_mode=trading_mode
) )
trade.open_order_id = 'open_trade' # trade.open_order_id = 'open_trade'
oobj = Order.parse_from_ccxt_object( oobj = Order.parse_from_ccxt_object(
limit_buy_order_usdt, 'ADA/USDT', 'sell' if is_short else 'buy') limit_buy_order_usdt, 'ADA/USDT', 'sell' if is_short else 'buy')
trade.update_trade(oobj) # Buy @ 2.0 trade.update_trade(oobj) # Buy @ 2.0
@@ -813,7 +811,7 @@ def test_calc_close_trade_price(
trading_mode=trading_mode, trading_mode=trading_mode,
funding_fees=funding_fees funding_fees=funding_fees
) )
trade.open_order_id = 'close_trade' # trade.open_order_id = 'close_trade'
assert round(trade.calc_close_trade_value(rate=close_rate), 8) == result assert round(trade.calc_close_trade_value(rate=close_rate), 8) == result
@@ -1135,7 +1133,7 @@ def test_calc_profit(
trading_mode=trading_mode, trading_mode=trading_mode,
funding_fees=funding_fees funding_fees=funding_fees
) )
trade.open_order_id = 'something' # trade.open_order_id = 'something'
assert pytest.approx(trade.calc_profit(rate=close_rate)) == round(profit, 8) assert pytest.approx(trade.calc_profit(rate=close_rate)) == round(profit, 8)
assert pytest.approx(trade.calc_profit_ratio(rate=close_rate)) == round(profit_ratio, 8) assert pytest.approx(trade.calc_profit_ratio(rate=close_rate)) == round(profit_ratio, 8)
@@ -1330,7 +1328,7 @@ def test_to_json(fee):
open_rate=0.123, open_rate=0.123,
exchange='binance', exchange='binance',
enter_tag=None, enter_tag=None,
open_order_id='dry_run_buy_12345', # open_order_id='dry_run_buy_12345',
precision_mode=1, precision_mode=1,
amount_precision=8.0, amount_precision=8.0,
price_precision=7.0, price_precision=7.0,
@@ -1346,7 +1344,7 @@ def test_to_json(fee):
'is_open': None, 'is_open': None,
'open_date': trade.open_date.strftime(DATETIME_PRINT_FORMAT), 'open_date': trade.open_date.strftime(DATETIME_PRINT_FORMAT),
'open_timestamp': int(trade.open_date.timestamp() * 1000), 'open_timestamp': int(trade.open_date.timestamp() * 1000),
'open_order_id': 'dry_run_buy_12345', # 'open_order_id': trade.open_orders_count,
'close_date': None, 'close_date': None,
'close_timestamp': None, 'close_timestamp': None,
'open_rate': 0.123, 'open_rate': 0.123,
@@ -1401,6 +1399,7 @@ def test_to_json(fee):
'price_precision': 7.0, 'price_precision': 7.0,
'precision_mode': 1, 'precision_mode': 1,
'orders': [], 'orders': [],
'open_orders': [],
} }
# Simulate dry_run entries # Simulate dry_run entries
@@ -1468,7 +1467,7 @@ def test_to_json(fee):
'is_open': None, 'is_open': None,
'max_rate': None, 'max_rate': None,
'min_rate': None, 'min_rate': None,
'open_order_id': None, # 'open_order_id': None,
'open_rate_requested': None, 'open_rate_requested': None,
'open_trade_value': 12.33075, 'open_trade_value': 12.33075,
'exit_reason': None, 'exit_reason': None,
@@ -1487,6 +1486,7 @@ def test_to_json(fee):
'price_precision': 8.0, 'price_precision': 8.0,
'precision_mode': 2, 'precision_mode': 2,
'orders': [], 'orders': [],
'open_orders': [],
} }
@@ -2638,7 +2638,7 @@ def test_recalc_trade_from_orders_dca(data) -> None:
assert len(trade.orders) == idx + 1 assert len(trade.orders) == idx + 1
if idx < len(data) - 1: if idx < len(data) - 1:
assert trade.is_open is True assert trade.is_open is True
assert trade.open_order_id is None assert len(trade.open_orders) == 0
assert trade.amount == result[0] assert trade.amount == result[0]
assert trade.open_rate == result[1] assert trade.open_rate == result[1]
assert trade.stake_amount == result[2] assert trade.stake_amount == result[2]
@@ -2652,4 +2652,4 @@ def test_recalc_trade_from_orders_dca(data) -> None:
assert not trade.is_open assert not trade.is_open
trade = Trade.session.scalars(select(Trade)).first() trade = Trade.session.scalars(select(Trade)).first()
assert trade assert trade
assert trade.open_order_id is None assert len(trade.open_orders) == 0