Merge pull request #10687 from freqtrade/refactor/trade_init_0
Some checks failed
Build Documentation / Deploy Docs through mike (push) Has been cancelled

Initialize Trade objects with amount=0
This commit is contained in:
Matthias 2024-09-24 06:30:24 +02:00 committed by GitHub
commit 5907de90c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 49 additions and 18 deletions

View File

@ -18,7 +18,7 @@ The following attributes / properties are available for each individual trade -
| `open_rate` | float | Rate this trade was entered at (Avg. entry rate in case of trade-adjustments). |
| `close_rate` | float | Close rate - only set when is_open = False. |
| `stake_amount` | float | Amount in Stake (or Quote) currency. |
| `amount` | float | Amount in Asset / Base currency that is currently owned. |
| `amount` | float | Amount in Asset / Base currency that is currently owned. Will be 0.0 until the initial order fills. |
| `open_date` | datetime | Timestamp when trade was opened **use `open_date_utc` instead** |
| `open_date_utc` | datetime | Timestamp when trade was opened - in UTC. |
| `close_date` | datetime | Timestamp when trade was closed **use `close_date_utc` instead** |

View File

@ -987,7 +987,7 @@ class FreqtradeBot(LoggingMixin):
base_currency=base_currency,
stake_currency=self.config["stake_currency"],
stake_amount=stake_amount,
amount=amount,
amount=0,
is_open=True,
amount_requested=amount_requested,
fee_open=fee,

View File

@ -1099,7 +1099,7 @@ class Backtesting:
open_rate_requested=propose_rate,
open_date=current_time,
stake_amount=stake_amount,
amount=amount,
amount=0,
amount_requested=amount,
fee_open=self.fee,
fee_close=self.fee,

View File

@ -1161,10 +1161,7 @@ class LocalTrade:
else:
open_trade_value = self._calc_open_trade_value(amount, open_rate)
short_close_zero = self.is_short and close_trade_value == 0.0
long_close_zero = not self.is_short and open_trade_value == 0.0
if short_close_zero or long_close_zero:
if open_trade_value == 0.0:
return 0.0
else:
if self.is_short:

View File

@ -99,11 +99,21 @@ class Wallets:
used_stake = 0.0
if self._config.get("trading_mode", "spot") != TradingMode.FUTURES:
current_stake = self.start_cap + tot_profit - tot_in_trades
total_stake = current_stake
for trade in open_trades:
curr = self._exchange.get_pair_base_currency(trade.pair)
_wallets[curr] = Wallet(curr, trade.amount, 0, trade.amount)
used_stake += sum(
o.stake_amount for o in trade.open_orders if o.ft_order_side == trade.entry_side
)
pending = sum(
o.amount
for o in trade.open_orders
if o.amount and o.ft_order_side == trade.exit_side
)
_wallets[curr] = Wallet(curr, trade.amount - pending, pending, trade.amount)
current_stake = self.start_cap + tot_profit - tot_in_trades
total_stake = current_stake + used_stake
else:
tot_in_trades = 0
for position in open_trades:

View File

@ -689,13 +689,29 @@ def test_process_trade_creation(
assert trade.open_date is not None
assert trade.exchange == "binance"
assert trade.open_rate == ticker_usdt.return_value[ticker_side]
assert pytest.approx(trade.amount) == 60 / ticker_usdt.return_value[ticker_side]
# Trade opens with 0 amount. Only trade filling will set the amount
assert pytest.approx(trade.amount) == 0
assert pytest.approx(trade.amount_requested) == 60 / ticker_usdt.return_value[ticker_side]
assert log_has(
f'{"Short" if is_short else "Long"} signal found: about create a new trade for ETH/USDT '
"with stake_amount: 60.0 ...",
caplog,
)
mocker.patch("freqtrade.freqtradebot.FreqtradeBot._check_and_execute_exit")
# Fill trade.
freqtrade.process()
trades = Trade.get_open_trades()
assert len(trades) == 1
trade = trades[0]
assert trade is not None
assert trade.is_open
assert trade.open_date is not None
assert trade.exchange == "binance"
assert trade.open_rate == limit_order[entry_side(is_short)]["price"]
# Filled trade has amount set to filled order amount
assert pytest.approx(trade.amount) == limit_order[entry_side(is_short)]["filled"]
def test_process_exchange_failures(default_conf_usdt, ticker_usdt, mocker) -> None:
@ -1684,7 +1700,7 @@ def test_handle_trade_roi(
create_order=MagicMock(
side_effect=[
open_order,
{"id": 1234553382},
{"id": 1234553382, "amount": open_order["amount"]},
]
),
get_fee=fee,

View File

@ -149,7 +149,10 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
# Different from "filled" response:
response_unfilled.update(
{
"amount": 91.07468124,
"amount": 0.0,
"open_trade_value": 0.0,
"stoploss_entry_dist": 0.0,
"stoploss_entry_dist_ratio": 0.0,
"profit_ratio": 0.0,
"profit_pct": 0.0,
"profit_abs": 0.0,
@ -762,7 +765,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
freqtradebot.enter_positions()
# make an limit-buy open trade
trade = Trade.session.scalars(select(Trade).filter(Trade.id == "3")).first()
filled_amount = trade.amount / 2
filled_amount = trade.amount_requested / 2
# Fetch order - it's open first, and closed after cancel_order is called.
mocker.patch(
f"{EXMS}.fetch_order",
@ -799,7 +802,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
cancel_order_mock.reset_mock()
trade = Trade.session.scalars(select(Trade).filter(Trade.id == "3")).first()
amount = trade.amount
amount = trade.amount_requested
# make an limit-sell open order trade
mocker.patch(
f"{EXMS}.fetch_order",
@ -832,7 +835,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
assert cancel_order_mock.call_count == 0
trade = Trade.session.scalars(select(Trade).filter(Trade.id == "4")).first()
amount = trade.amount
amount = trade.amount_requested
# make an limit-buy open trade, if there is no 'filled', don't sell it
mocker.patch(
f"{EXMS}.fetch_order",

View File

@ -365,13 +365,18 @@ def test_sync_wallet_dry(mocker, default_conf_usdt, fee):
assert bal["NEO"].total == 10
assert bal["XRP"].total == 10
assert bal["LTC"].total == 2
assert bal["USDT"].total == 922.74
usdt_bal = bal["USDT"]
assert usdt_bal.free == 922.74
assert usdt_bal.total == 942.74
assert usdt_bal.used == 20.0
# sum of used and free should be total.
assert usdt_bal.total == usdt_bal.free + usdt_bal.used
assert freqtrade.wallets.get_starting_balance() == default_conf_usdt["dry_run_wallet"]
total = freqtrade.wallets.get_total("LTC")
free = freqtrade.wallets.get_free("LTC")
used = freqtrade.wallets.get_used("LTC")
assert free != 0
assert used != 0
assert free + used == total