diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 855f2353b..ab8eb9f98 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -750,7 +750,7 @@ class DigDeeperStrategy(IStrategy): # Hope you have a deep wallet! try: # This returns first order stake size - stake_amount = filled_entries[0].cost + stake_amount = filled_entries[0].stake_amount # This then calculates current safety order size stake_amount = stake_amount * (1 + (count_of_entries * 0.25)) return stake_amount diff --git a/docs/trade-object.md b/docs/trade-object.md index 7e0db1e3b..15a8b1938 100644 --- a/docs/trade-object.md +++ b/docs/trade-object.md @@ -141,7 +141,8 @@ Most properties here can be None as they are dependant on the exchange response. `amount` | float | Amount in base currency `filled` | float | Filled amount (in base currency) `remaining` | float | Remaining amount -`cost` | float | Cost of the order - usually average * filled +`cost` | float | Cost of the order - usually average * filled (*Exchange dependant on futures, may contain the cost with or without leverage and may be in contracts.*) +`stake_amount` | float | Stake amount used for this order. *Added in 2023.7.* `order_date` | datetime | Order creation date **use `order_date_utc` instead** `order_date_utc` | datetime | Order creation date (in UTC) `order_fill_date` | datetime | Order fill date **use `order_fill_utc` instead** diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 4a5536e84..6756f10b7 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -679,6 +679,7 @@ class Backtesting: remaining=amount, cost=amount * close_rate, ) + order._trade_bt = trade trade.orders.append(order) return trade @@ -901,8 +902,9 @@ class Backtesting: amount=amount, filled=0, remaining=amount, - cost=stake_amount + trade.fee_open, + cost=amount * propose_rate + trade.fee_open, ) + order._trade_bt = trade trade.orders.append(order) if pos_adjust and self._get_order_filled(order.ft_price, row): order.close_bt_order(current_time, trade) diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py index d1b9c5a3b..f686e4f8c 100644 --- a/freqtrade/persistence/trade_model.py +++ b/freqtrade/persistence/trade_model.py @@ -38,6 +38,7 @@ class Order(ModelBase): Mirrors CCXT Order structure """ __tablename__ = 'orders' + __allow_unmapped__ = True session: ClassVar[SessionType] # Uniqueness should be ensured over pair, order_id @@ -47,7 +48,8 @@ class Order(ModelBase): id: Mapped[int] = mapped_column(Integer, primary_key=True) ft_trade_id: Mapped[int] = mapped_column(Integer, ForeignKey('trades.id'), index=True) - trade: Mapped["Trade"] = relationship("Trade", back_populates="orders") + _trade_live: Mapped["Trade"] = relationship("Trade", back_populates="orders") + _trade_bt: "LocalTrade" = None # type: ignore # order_side can only be 'buy', 'sell' or 'stoploss' ft_order_side: Mapped[str] = mapped_column(String(25), nullable=False) @@ -119,6 +121,15 @@ class Order(ModelBase): def safe_amount_after_fee(self) -> float: return self.safe_filled - self.safe_fee_base + @property + def trade(self) -> "LocalTrade": + return self._trade_bt or self._trade_live + + @property + def stake_amount(self) -> float: + """ Amount in stake currency used for this order""" + return self.safe_amount * self.safe_price / self.trade.leverage + def __repr__(self): return (f"Order(id={self.id}, trade={self.ft_trade_id}, order_id={self.order_id}, " diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py index a333cda9d..cc1d9e95b 100644 --- a/tests/optimize/test_backtesting.py +++ b/tests/optimize/test_backtesting.py @@ -601,6 +601,9 @@ def test_backtest__enter_trade_futures(default_conf_usdt, fee, mocker) -> None: trade = backtesting._enter_trade(pair, row=row, direction='short') assert pytest.approx(trade.liquidation_price) == 0.11787191 + assert pytest.approx(trade.orders[0].cost) == ( + trade.stake_amount * trade.leverage + trade.fee_open) + assert pytest.approx(trade.orders[-1].stake_amount) == trade.stake_amount # Stake-amount too high! mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=600.0) diff --git a/tests/persistence/test_persistence.py b/tests/persistence/test_persistence.py index 4aa3b1e96..958db8c72 100644 --- a/tests/persistence/test_persistence.py +++ b/tests/persistence/test_persistence.py @@ -563,14 +563,14 @@ def test_calc_open_close_trade_price( trade.open_order_id = f'something-{is_short}-{lev}-{exchange}' oobj = Order.parse_from_ccxt_object(entry_order, 'ADA/USDT', trade.entry_side) - oobj.trade = trade + oobj._trade_live = trade oobj.update_from_ccxt_object(entry_order) trade.update_trade(oobj) trade.funding_fees = funding_fees oobj = Order.parse_from_ccxt_object(exit_order, 'ADA/USDT', trade.exit_side) - oobj.trade = trade + oobj._trade_live = trade oobj.update_from_ccxt_object(exit_order) trade.update_trade(oobj) diff --git a/tests/test_integration.py b/tests/test_integration.py index 0d3fd419a..945585448 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -429,6 +429,7 @@ def test_dca_order_adjust(default_conf_usdt, ticker_usdt, leverage, fee, mocker) assert pytest.approx(trade.stop_loss) == 1.99 * (1 - 0.1 / leverage) assert pytest.approx(trade.initial_stop_loss) == 1.96 * (1 - 0.1 / leverage) assert trade.initial_stop_loss_pct == -0.1 + assert pytest.approx(trade.orders[-1].stake_amount) == trade.stake_amount # 2nd order - not filling freqtrade.strategy.adjust_trade_position = MagicMock(return_value=120)