Replace open_order_id property by open_orders in Trade model, first test update

This commit is contained in:
axel 2023-06-13 02:11:34 -04:00
parent 502090c199
commit 4874d10455
3 changed files with 62 additions and 18 deletions

View File

@ -281,6 +281,7 @@ def fix_old_dry_orders(engine):
).values(ft_is_open=False)
connection.execute(stmt)
# OLD
stmt = update(Order).where(
Order.ft_is_open.is_(True),
tuple_(Order.ft_trade_id, Order.order_id).not_in(
@ -294,6 +295,28 @@ def fix_old_dry_orders(engine):
).values(ft_is_open=False)
connection.execute(stmt)
# Update current Order where
# -current Order is open
# -current Order trade_id not equal to current Trade.id
# -current Order not stoploss
# -order_id not equal to current Trade.stoploss_order_id
# -current Order is dry
# NEW WIP
stmt = update(Order).where(
Order.ft_is_open.is_(True),
Order.ft_trade_id.not_in(
select(Trade.id).where(Trade.open_orders_count.is_not(0))
),
Order.order_id.not_in(
select(Trade.open_orders).filter(Order.order_id).first()
),
Order.ft_order_side != 'stoploss',
Order.order_id.like('dry%')
).values(ft_is_open=False)
connection.execute(stmt)
def check_migrate(engine, decl_base, previous_tables) -> None:
"""
@ -340,7 +363,7 @@ def check_migrate(engine, decl_base, previous_tables) -> None:
"start with a fresh database.")
set_sqlite_to_wal(engine)
fix_old_dry_orders(engine)
# fix_old_dry_orders(engine) # TODO Fix that
if migrating:
logger.info("Database migration finished.")

View File

@ -9,6 +9,7 @@ from typing import Any, ClassVar, Dict, List, Optional, Sequence, cast
from sqlalchemy import (Enum, Float, ForeignKey, Integer, ScalarResult, Select, String,
UniqueConstraint, desc, func, select)
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import Mapped, lazyload, mapped_column, relationship, validates
from freqtrade.constants import (CUSTOM_TAG_MAX_LENGTH, DATETIME_PRINT_FORMAT, MATH_CLOSE_PREC,
@ -327,7 +328,7 @@ class LocalTrade():
amount_requested: Optional[float] = None
open_date: datetime
close_date: Optional[datetime] = None
open_order_id: Optional[str] = None
open_orders: List[Order] = []
# absolute value of the stop loss
stop_loss: float = 0.0
# percentage value of the stop loss
@ -468,6 +469,14 @@ class LocalTrade():
except IndexError:
return ''
@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):
for key in kwargs:
setattr(self, key, kwargs[key])
@ -680,12 +689,21 @@ class LocalTrade():
if self.is_open:
payment = "SELL" if self.is_short else "BUY"
logger.info(f'{order.order_type.upper()}_{payment} has been fulfilled for {self}.')
# TODO WIP but to rm if useless
# condition to avoid reset value when updating fees (new)
# if order.order_id in self.open_orders_ids:
# self.open_order_id = None
# else:
# logger.warning(
# f'Got different open_order_id {self.open_order_id} != {order.order_id}')
# TODO validate if this is still relevant
# condition to avoid reset value when updating fees
if self.open_order_id == order.order_id:
self.open_order_id = None
else:
logger.warning(
f'Got different open_order_id {self.open_order_id} != {order.order_id}')
# if self.open_order_id == order.order_id:
# self.open_order_id = None
# else:
# logger.warning(
# f'Got different open_order_id {self.open_order_id} != {order.order_id}')
self.recalc_trade_from_orders()
elif order.ft_order_side == self.exit_side:
if self.is_open:
@ -693,11 +711,11 @@ class LocalTrade():
# * On margin shorts, you buy a little bit more than the amount (amount + interest)
logger.info(f'{order.order_type.upper()}_{payment} has been fulfilled for {self}.')
# condition to avoid reset value when updating fees
if self.open_order_id == order.order_id:
self.open_order_id = None
else:
logger.warning(
f'Got different open_order_id {self.open_order_id} != {order.order_id}')
# if self.open_order_id == order.order_id:
# self.open_order_id = None
# else:
# logger.warning(
# f'Got different open_order_id {self.open_order_id} != {order.order_id}')
elif order.ft_order_side == 'stoploss' and order.status not in ('open', ):
self.stoploss_order_id = None
@ -1244,7 +1262,6 @@ class Trade(ModelBase, LocalTrade):
open_date: Mapped[datetime] = mapped_column(
nullable=False, default=datetime.utcnow) # type: ignore
close_date: Mapped[Optional[datetime]] = mapped_column() # type: ignore
open_order_id: Mapped[Optional[str]] = mapped_column(String(255), nullable=True) # type: ignore
# absolute value of the stop loss
stop_loss: Mapped[float] = mapped_column(Float(), nullable=True, default=0.0) # type: ignore
# percentage value of the stop loss
@ -1296,6 +1313,10 @@ class Trade(ModelBase, LocalTrade):
funding_fees: Mapped[Optional[float]] = mapped_column(
Float(), nullable=True, default=None) # type: ignore
@hybrid_property
def open_orders(self):
return [order for order in self.orders if order.ft_is_open]
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.realized_profit = 0

View File

@ -437,15 +437,15 @@ def test_update_limit_order(fee, caplog, limit_buy_order_usdt, limit_sell_order_
leverage=lev,
trading_mode=trading_mode
)
assert trade.open_order_id is None
assert trade.open_orders_count == 0
assert trade.close_profit is None
assert trade.close_date is None
trade.open_order_id = enter_order['id']
trade.open_orders.append(enter_order)
oobj = Order.parse_from_ccxt_object(enter_order, 'ADA/USDT', entry_side)
trade.orders.append(oobj)
trade.update_trade(oobj)
assert trade.open_order_id is None
assert trade.open_orders_count == 0
assert trade.open_rate == open_rate
assert trade.close_profit is None
assert trade.close_date is None
@ -456,13 +456,13 @@ def test_update_limit_order(fee, caplog, limit_buy_order_usdt, limit_sell_order_
caplog)
caplog.clear()
trade.open_order_id = enter_order['id']
trade.open_orders.append(enter_order)
time_machine.move_to("2022-03-31 21:45:05 +00:00")
oobj = Order.parse_from_ccxt_object(exit_order, 'ADA/USDT', exit_side)
trade.orders.append(oobj)
trade.update_trade(oobj)
assert trade.open_order_id is None
assert trade.open_orders_count == 0
assert trade.close_rate == close_rate
assert pytest.approx(trade.close_profit) == profit
assert trade.close_date is not None