diff --git a/freqtrade/persistence.py b/freqtrade/persistence.py index ea34fd5bf..3f7f4e0e9 100644 --- a/freqtrade/persistence.py +++ b/freqtrade/persistence.py @@ -86,7 +86,7 @@ def check_migrate(engine) -> None: logger.debug(f'trying {table_back_name}') # Check for latest column - if not has_column(cols, 'fee_close_cost'): + if not has_column(cols, 'sell_order_status'): logger.info(f'Running database migration - backup available as {table_back_name}') fee_open = get_column_def(cols, 'fee_open', 'fee') @@ -113,6 +113,7 @@ def check_migrate(engine) -> None: close_profit_abs = get_column_def( cols, 'close_profit_abs', f"(amount * close_rate * (1 - {fee_close})) - {open_trade_price}") + sell_order_status = get_column_def(cols, 'sell_order_status', 'null') # Schema migration necessary engine.execute(f"alter table trades rename to {table_back_name}") @@ -131,7 +132,7 @@ def check_migrate(engine) -> None: stake_amount, amount, open_date, close_date, open_order_id, stop_loss, stop_loss_pct, initial_stop_loss, initial_stop_loss_pct, stoploss_order_id, stoploss_last_update, - max_rate, min_rate, sell_reason, strategy, + max_rate, min_rate, sell_reason, sell_order_status, strategy, ticker_interval, open_trade_price, close_profit_abs ) select id, lower(exchange), @@ -153,6 +154,7 @@ def check_migrate(engine) -> None: {initial_stop_loss_pct} initial_stop_loss_pct, {stoploss_order_id} stoploss_order_id, {stoploss_last_update} stoploss_last_update, {max_rate} max_rate, {min_rate} min_rate, {sell_reason} sell_reason, + {sell_order_status} sell_order_status, {strategy} strategy, {ticker_interval} ticker_interval, {open_trade_price} open_trade_price, {close_profit_abs} close_profit_abs from {table_back_name} @@ -228,6 +230,7 @@ class Trade(_DECL_BASE): # Lowest price reached min_rate = Column(Float, nullable=True) sell_reason = Column(String, nullable=True) + sell_order_status = Column(String, nullable=True) strategy = Column(String, nullable=True) ticker_interval = Column(Integer, nullable=True) @@ -267,6 +270,7 @@ class Trade(_DECL_BASE): 'stake_amount': round(self.stake_amount, 8), 'close_profit': self.close_profit, 'sell_reason': self.sell_reason, + 'sell_order_status': self.sell_order_status, 'stop_loss': self.stop_loss, 'stop_loss_pct': (self.stop_loss_pct * 100) if self.stop_loss_pct else None, 'initial_stop_loss': self.initial_stop_loss, @@ -370,6 +374,7 @@ class Trade(_DECL_BASE): self.close_profit_abs = self.calc_profit() self.close_date = datetime.utcnow() self.is_open = False + self.sell_order_status = 'closed' self.open_order_id = None logger.info( 'Marking %s as closed as the trade is fulfilled and found no open orders for it.', diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 856b8f138..19307253c 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -226,9 +226,13 @@ class Telegram(RPC): # Adding stoploss and stoploss percentage only if it is not None "*Stoploss:* `{stop_loss:.8f}` " + ("`({stop_loss_pct:.2f}%)`" if r['stop_loss_pct'] else ""), - - "*Open Order:* `{open_order}`" if r['open_order'] else "" ] + if r['open_order']: + if r['sell_order_status']: + lines.append("*Open Order:* `{open_order}` - `{sell_order_status}`") + else: + lines.append("*Open Order:* `{open_order}`") + # Filter empty lines using list-comprehension messages.append("\n".join([l for l in lines if l]).format(**r)) diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index a1e6d9f26..8a4c812a7 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -60,6 +60,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: 'open_trade_price': ANY, 'close_rate_requested': ANY, 'sell_reason': ANY, + 'sell_order_status': ANY, 'min_rate': ANY, 'max_rate': ANY, 'strategy': ANY, @@ -103,6 +104,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: 'open_trade_price': ANY, 'close_rate_requested': ANY, 'sell_reason': ANY, + 'sell_order_status': ANY, 'min_rate': ANY, 'max_rate': ANY, 'strategy': ANY, diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index b953097d5..a0e8e0c9e 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -520,6 +520,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets): 'open_rate_requested': 1.098e-05, 'open_trade_price': 0.0010025, 'sell_reason': None, + 'sell_order_status': None, 'strategy': 'DefaultStrategy', 'ticker_interval': 5}] @@ -626,6 +627,7 @@ def test_api_forcebuy(botclient, mocker, fee): 'open_rate_requested': None, 'open_trade_price': 0.2460546025, 'sell_reason': None, + 'sell_order_status': None, 'strategy': None, 'ticker_interval': None } diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index bbc961763..b84073dcc 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -170,6 +170,7 @@ def test_status(default_conf, update, mocker, fee, ticker,) -> None: 'current_profit': -0.59, 'initial_stop_loss': 1.098e-05, 'stop_loss': 1.099e-05, + 'sell_order_status': None, 'initial_stop_loss_pct': -0.05, 'stop_loss_pct': -0.01, 'open_order': '(limit buy rem=0.00000000)' diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 5c7686e28..25afed397 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -477,6 +477,7 @@ def test_migrate_old(mocker, default_conf, fee): assert trade.close_rate_requested is None assert trade.close_rate is not None assert pytest.approx(trade.close_profit_abs) == trade.calc_profit() + assert trade.sell_order_status is None def test_migrate_new(mocker, default_conf, fee, caplog): @@ -756,6 +757,7 @@ def test_to_json(default_conf, fee): 'stake_amount': 0.001, 'close_profit': None, 'sell_reason': None, + 'sell_order_status': None, 'stop_loss': None, 'stop_loss_pct': None, 'initial_stop_loss': None, @@ -810,6 +812,7 @@ def test_to_json(default_conf, fee): 'open_rate_requested': None, 'open_trade_price': 12.33075, 'sell_reason': None, + 'sell_order_status': None, 'strategy': None, 'ticker_interval': None}