mirror of
https://github.com/freqtrade/freqtrade.git
synced 2026-01-30 02:41:12 +00:00
Merge pull request #10687 from freqtrade/refactor/trade_init_0
Initialize Trade objects with amount=0
This commit is contained in:
@@ -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). |
|
| `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. |
|
| `close_rate` | float | Close rate - only set when is_open = False. |
|
||||||
| `stake_amount` | float | Amount in Stake (or Quote) currency. |
|
| `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` | datetime | Timestamp when trade was opened **use `open_date_utc` instead** |
|
||||||
| `open_date_utc` | datetime | Timestamp when trade was opened - in UTC. |
|
| `open_date_utc` | datetime | Timestamp when trade was opened - in UTC. |
|
||||||
| `close_date` | datetime | Timestamp when trade was closed **use `close_date_utc` instead** |
|
| `close_date` | datetime | Timestamp when trade was closed **use `close_date_utc` instead** |
|
||||||
|
|||||||
@@ -987,7 +987,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
base_currency=base_currency,
|
base_currency=base_currency,
|
||||||
stake_currency=self.config["stake_currency"],
|
stake_currency=self.config["stake_currency"],
|
||||||
stake_amount=stake_amount,
|
stake_amount=stake_amount,
|
||||||
amount=amount,
|
amount=0,
|
||||||
is_open=True,
|
is_open=True,
|
||||||
amount_requested=amount_requested,
|
amount_requested=amount_requested,
|
||||||
fee_open=fee,
|
fee_open=fee,
|
||||||
|
|||||||
@@ -1099,7 +1099,7 @@ class Backtesting:
|
|||||||
open_rate_requested=propose_rate,
|
open_rate_requested=propose_rate,
|
||||||
open_date=current_time,
|
open_date=current_time,
|
||||||
stake_amount=stake_amount,
|
stake_amount=stake_amount,
|
||||||
amount=amount,
|
amount=0,
|
||||||
amount_requested=amount,
|
amount_requested=amount,
|
||||||
fee_open=self.fee,
|
fee_open=self.fee,
|
||||||
fee_close=self.fee,
|
fee_close=self.fee,
|
||||||
|
|||||||
@@ -1161,10 +1161,7 @@ class LocalTrade:
|
|||||||
else:
|
else:
|
||||||
open_trade_value = self._calc_open_trade_value(amount, open_rate)
|
open_trade_value = self._calc_open_trade_value(amount, open_rate)
|
||||||
|
|
||||||
short_close_zero = self.is_short and close_trade_value == 0.0
|
if open_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:
|
|
||||||
return 0.0
|
return 0.0
|
||||||
else:
|
else:
|
||||||
if self.is_short:
|
if self.is_short:
|
||||||
|
|||||||
@@ -99,11 +99,21 @@ class Wallets:
|
|||||||
used_stake = 0.0
|
used_stake = 0.0
|
||||||
|
|
||||||
if self._config.get("trading_mode", "spot") != TradingMode.FUTURES:
|
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:
|
for trade in open_trades:
|
||||||
curr = self._exchange.get_pair_base_currency(trade.pair)
|
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:
|
else:
|
||||||
tot_in_trades = 0
|
tot_in_trades = 0
|
||||||
for position in open_trades:
|
for position in open_trades:
|
||||||
|
|||||||
@@ -689,13 +689,29 @@ def test_process_trade_creation(
|
|||||||
assert trade.open_date is not None
|
assert trade.open_date is not None
|
||||||
assert trade.exchange == "binance"
|
assert trade.exchange == "binance"
|
||||||
assert trade.open_rate == ticker_usdt.return_value[ticker_side]
|
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(
|
assert log_has(
|
||||||
f'{"Short" if is_short else "Long"} signal found: about create a new trade for ETH/USDT '
|
f'{"Short" if is_short else "Long"} signal found: about create a new trade for ETH/USDT '
|
||||||
"with stake_amount: 60.0 ...",
|
"with stake_amount: 60.0 ...",
|
||||||
caplog,
|
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:
|
def test_process_exchange_failures(default_conf_usdt, ticker_usdt, mocker) -> None:
|
||||||
@@ -1684,7 +1700,7 @@ def test_handle_trade_roi(
|
|||||||
create_order=MagicMock(
|
create_order=MagicMock(
|
||||||
side_effect=[
|
side_effect=[
|
||||||
open_order,
|
open_order,
|
||||||
{"id": 1234553382},
|
{"id": 1234553382, "amount": open_order["amount"]},
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
get_fee=fee,
|
get_fee=fee,
|
||||||
|
|||||||
@@ -149,7 +149,10 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
|
|||||||
# Different from "filled" response:
|
# Different from "filled" response:
|
||||||
response_unfilled.update(
|
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_ratio": 0.0,
|
||||||
"profit_pct": 0.0,
|
"profit_pct": 0.0,
|
||||||
"profit_abs": 0.0,
|
"profit_abs": 0.0,
|
||||||
@@ -762,7 +765,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
|
|||||||
freqtradebot.enter_positions()
|
freqtradebot.enter_positions()
|
||||||
# make an limit-buy open trade
|
# make an limit-buy open trade
|
||||||
trade = Trade.session.scalars(select(Trade).filter(Trade.id == "3")).first()
|
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.
|
# Fetch order - it's open first, and closed after cancel_order is called.
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
f"{EXMS}.fetch_order",
|
f"{EXMS}.fetch_order",
|
||||||
@@ -799,7 +802,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
|
|||||||
|
|
||||||
cancel_order_mock.reset_mock()
|
cancel_order_mock.reset_mock()
|
||||||
trade = Trade.session.scalars(select(Trade).filter(Trade.id == "3")).first()
|
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
|
# make an limit-sell open order trade
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
f"{EXMS}.fetch_order",
|
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
|
assert cancel_order_mock.call_count == 0
|
||||||
|
|
||||||
trade = Trade.session.scalars(select(Trade).filter(Trade.id == "4")).first()
|
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
|
# make an limit-buy open trade, if there is no 'filled', don't sell it
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
f"{EXMS}.fetch_order",
|
f"{EXMS}.fetch_order",
|
||||||
|
|||||||
@@ -365,13 +365,18 @@ def test_sync_wallet_dry(mocker, default_conf_usdt, fee):
|
|||||||
assert bal["NEO"].total == 10
|
assert bal["NEO"].total == 10
|
||||||
assert bal["XRP"].total == 10
|
assert bal["XRP"].total == 10
|
||||||
assert bal["LTC"].total == 2
|
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"]
|
assert freqtrade.wallets.get_starting_balance() == default_conf_usdt["dry_run_wallet"]
|
||||||
total = freqtrade.wallets.get_total("LTC")
|
total = freqtrade.wallets.get_total("LTC")
|
||||||
free = freqtrade.wallets.get_free("LTC")
|
free = freqtrade.wallets.get_free("LTC")
|
||||||
used = freqtrade.wallets.get_used("LTC")
|
used = freqtrade.wallets.get_used("LTC")
|
||||||
assert free != 0
|
assert used != 0
|
||||||
assert free + used == total
|
assert free + used == total
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user