Replace open_order_id property by open_orders in Trade model, first test update
This commit is contained in:
@@ -281,6 +281,7 @@ def fix_old_dry_orders(engine):
|
|||||||
).values(ft_is_open=False)
|
).values(ft_is_open=False)
|
||||||
connection.execute(stmt)
|
connection.execute(stmt)
|
||||||
|
|
||||||
|
# OLD
|
||||||
stmt = update(Order).where(
|
stmt = update(Order).where(
|
||||||
Order.ft_is_open.is_(True),
|
Order.ft_is_open.is_(True),
|
||||||
tuple_(Order.ft_trade_id, Order.order_id).not_in(
|
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)
|
).values(ft_is_open=False)
|
||||||
connection.execute(stmt)
|
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:
|
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.")
|
"start with a fresh database.")
|
||||||
|
|
||||||
set_sqlite_to_wal(engine)
|
set_sqlite_to_wal(engine)
|
||||||
fix_old_dry_orders(engine)
|
# fix_old_dry_orders(engine) # TODO Fix that
|
||||||
|
|
||||||
if migrating:
|
if migrating:
|
||||||
logger.info("Database migration finished.")
|
logger.info("Database migration finished.")
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from typing import Any, ClassVar, Dict, List, Optional, Sequence, cast
|
|||||||
|
|
||||||
from sqlalchemy import (Enum, Float, ForeignKey, Integer, ScalarResult, Select, String,
|
from sqlalchemy import (Enum, Float, ForeignKey, Integer, ScalarResult, Select, String,
|
||||||
UniqueConstraint, desc, func, select)
|
UniqueConstraint, desc, func, select)
|
||||||
|
from sqlalchemy.ext.hybrid import hybrid_property
|
||||||
from sqlalchemy.orm import Mapped, lazyload, mapped_column, relationship, validates
|
from sqlalchemy.orm import Mapped, lazyload, mapped_column, relationship, validates
|
||||||
|
|
||||||
from freqtrade.constants import (CUSTOM_TAG_MAX_LENGTH, DATETIME_PRINT_FORMAT, MATH_CLOSE_PREC,
|
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
|
amount_requested: Optional[float] = None
|
||||||
open_date: datetime
|
open_date: datetime
|
||||||
close_date: Optional[datetime] = None
|
close_date: Optional[datetime] = None
|
||||||
open_order_id: Optional[str] = None
|
open_orders: List[Order] = []
|
||||||
# absolute value of the stop loss
|
# absolute value of the stop loss
|
||||||
stop_loss: float = 0.0
|
stop_loss: float = 0.0
|
||||||
# percentage value of the stop loss
|
# percentage value of the stop loss
|
||||||
@@ -468,6 +469,14 @@ class LocalTrade():
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
return ''
|
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):
|
def __init__(self, **kwargs):
|
||||||
for key in kwargs:
|
for key in kwargs:
|
||||||
setattr(self, key, kwargs[key])
|
setattr(self, key, kwargs[key])
|
||||||
@@ -680,12 +689,21 @@ class LocalTrade():
|
|||||||
if self.is_open:
|
if self.is_open:
|
||||||
payment = "SELL" if self.is_short else "BUY"
|
payment = "SELL" if self.is_short else "BUY"
|
||||||
logger.info(f'{order.order_type.upper()}_{payment} has been fulfilled for {self}.')
|
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
|
# condition to avoid reset value when updating fees
|
||||||
if self.open_order_id == order.order_id:
|
# if self.open_order_id == order.order_id:
|
||||||
self.open_order_id = None
|
# self.open_order_id = None
|
||||||
else:
|
# else:
|
||||||
logger.warning(
|
# logger.warning(
|
||||||
f'Got different open_order_id {self.open_order_id} != {order.order_id}')
|
# f'Got different open_order_id {self.open_order_id} != {order.order_id}')
|
||||||
self.recalc_trade_from_orders()
|
self.recalc_trade_from_orders()
|
||||||
elif order.ft_order_side == self.exit_side:
|
elif order.ft_order_side == self.exit_side:
|
||||||
if self.is_open:
|
if self.is_open:
|
||||||
@@ -693,11 +711,11 @@ class LocalTrade():
|
|||||||
# * On margin shorts, you buy a little bit more than the amount (amount + interest)
|
# * 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}.')
|
logger.info(f'{order.order_type.upper()}_{payment} has been fulfilled for {self}.')
|
||||||
# condition to avoid reset value when updating fees
|
# condition to avoid reset value when updating fees
|
||||||
if self.open_order_id == order.order_id:
|
# if self.open_order_id == order.order_id:
|
||||||
self.open_order_id = None
|
# self.open_order_id = None
|
||||||
else:
|
# else:
|
||||||
logger.warning(
|
# logger.warning(
|
||||||
f'Got different open_order_id {self.open_order_id} != {order.order_id}')
|
# 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', ):
|
elif order.ft_order_side == 'stoploss' and order.status not in ('open', ):
|
||||||
self.stoploss_order_id = None
|
self.stoploss_order_id = None
|
||||||
@@ -1244,7 +1262,6 @@ class Trade(ModelBase, LocalTrade):
|
|||||||
open_date: Mapped[datetime] = mapped_column(
|
open_date: Mapped[datetime] = mapped_column(
|
||||||
nullable=False, default=datetime.utcnow) # type: ignore
|
nullable=False, default=datetime.utcnow) # type: ignore
|
||||||
close_date: Mapped[Optional[datetime]] = mapped_column() # 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
|
# absolute value of the stop loss
|
||||||
stop_loss: Mapped[float] = mapped_column(Float(), nullable=True, default=0.0) # type: ignore
|
stop_loss: Mapped[float] = mapped_column(Float(), nullable=True, default=0.0) # type: ignore
|
||||||
# percentage value of the stop loss
|
# percentage value of the stop loss
|
||||||
@@ -1296,6 +1313,10 @@ class Trade(ModelBase, LocalTrade):
|
|||||||
funding_fees: Mapped[Optional[float]] = mapped_column(
|
funding_fees: Mapped[Optional[float]] = mapped_column(
|
||||||
Float(), nullable=True, default=None) # type: ignore
|
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):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.realized_profit = 0
|
self.realized_profit = 0
|
||||||
|
|||||||
@@ -437,15 +437,15 @@ def test_update_limit_order(fee, caplog, limit_buy_order_usdt, limit_sell_order_
|
|||||||
leverage=lev,
|
leverage=lev,
|
||||||
trading_mode=trading_mode
|
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_profit is None
|
||||||
assert trade.close_date 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)
|
oobj = Order.parse_from_ccxt_object(enter_order, 'ADA/USDT', entry_side)
|
||||||
trade.orders.append(oobj)
|
trade.orders.append(oobj)
|
||||||
trade.update_trade(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.open_rate == open_rate
|
||||||
assert trade.close_profit is None
|
assert trade.close_profit is None
|
||||||
assert trade.close_date 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)
|
||||||
|
|
||||||
caplog.clear()
|
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")
|
time_machine.move_to("2022-03-31 21:45:05 +00:00")
|
||||||
oobj = Order.parse_from_ccxt_object(exit_order, 'ADA/USDT', exit_side)
|
oobj = Order.parse_from_ccxt_object(exit_order, 'ADA/USDT', exit_side)
|
||||||
trade.orders.append(oobj)
|
trade.orders.append(oobj)
|
||||||
trade.update_trade(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 trade.close_rate == close_rate
|
||||||
assert pytest.approx(trade.close_profit) == profit
|
assert pytest.approx(trade.close_profit) == profit
|
||||||
assert trade.close_date is not None
|
assert trade.close_date is not None
|
||||||
|
|||||||
Reference in New Issue
Block a user