Merge pull request #1674 from freqtrade/feat/stopbuy

Telegram `/stopbuy`
This commit is contained in:
Misagh 2019-03-18 09:00:47 +01:00 committed by GitHub
commit ff08416b12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 90 additions and 11 deletions

View File

@ -16,6 +16,7 @@ official commands. You can ask at any moment for help with `/help`.
|----------|---------|-------------| |----------|---------|-------------|
| `/start` | | Starts the trader | `/start` | | Starts the trader
| `/stop` | | Stops the trader | `/stop` | | Stops the trader
| `/stopbuy` | | Stops the trader from opening new trades. Gracefully closes open trades according to their rules.
| `/reload_conf` | | Reloads the configuration file | `/reload_conf` | | Reloads the configuration file
| `/status` | | Lists all open trades | `/status` | | Lists all open trades
| `/status table` | | List all open trades in a table format | `/status table` | | List all open trades in a table format
@ -43,7 +44,21 @@ Below, example of Telegram message you will receive for each command.
> `Stopping trader ...` > `Stopping trader ...`
> **Status:** `stopped` > **Status:** `stopped`
## /status ### /stopbuy
> **status:** `Setting max_open_trades to 0. Run /reload_conf to reset.`
Prevents the bot from opening new trades by temporarily setting "max_open_trades" to 0. Open trades will be handled via their regular rules (ROI / Sell-signal, stoploss, ...).
After this, give the bot time to close off open trades (can be checked via `/status table`).
Once all positions are sold, run `/stop` to completely stop the bot.
`/reload_conf` resets "max_open_trades" to the value set in the configuration and resets this command.
!!! warning:
The stop-buy signal is ONLY active while the bot is running, and is not persisted anyway, so restarting the bot will cause this to reset.
### /status
For each open trade, the bot will send you the following message. For each open trade, the bot will send you the following message.
@ -58,7 +73,7 @@ For each open trade, the bot will send you the following message.
> **Current Profit:** `12.95%` > **Current Profit:** `12.95%`
> **Open Order:** `None` > **Open Order:** `None`
## /status table ### /status table
Return the status of all open trades in a table format. Return the status of all open trades in a table format.
``` ```
@ -68,7 +83,7 @@ Return the status of all open trades in a table format.
123 CVC/BTC 1 h 12.95% 123 CVC/BTC 1 h 12.95%
``` ```
## /count ### /count
Return the number of trades used and available. Return the number of trades used and available.
``` ```
@ -77,7 +92,7 @@ current max
2 10 2 10
``` ```
## /profit ### /profit
Return a summary of your profit/loss and performance. Return a summary of your profit/loss and performance.
@ -94,11 +109,11 @@ Return a summary of your profit/loss and performance.
> **Avg. Duration:** `2:33:45` > **Avg. Duration:** `2:33:45`
> **Best Performing:** `PAY/BTC: 50.23%` > **Best Performing:** `PAY/BTC: 50.23%`
## /forcesell <trade_id> ### /forcesell <trade_id>
> **BITTREX:** Selling BTC/LTC with limit `0.01650000 (profit: ~-4.07%, -0.00008168)` > **BITTREX:** Selling BTC/LTC with limit `0.01650000 (profit: ~-4.07%, -0.00008168)`
## /forcebuy <pair> ### /forcebuy <pair>
> **BITTREX**: Buying ETH/BTC with limit `0.03400000` (`1.000000 ETH`, `225.290 USD`) > **BITTREX**: Buying ETH/BTC with limit `0.03400000` (`1.000000 ETH`, `225.290 USD`)
@ -106,7 +121,7 @@ Note that for this to work, `forcebuy_enable` needs to be set to true.
[More details](configuration.md/#understand-forcebuy_enable) [More details](configuration.md/#understand-forcebuy_enable)
## /performance ### /performance
Return the performance of each crypto-currency the bot has sold. Return the performance of each crypto-currency the bot has sold.
> Performance: > Performance:
@ -117,7 +132,7 @@ Return the performance of each crypto-currency the bot has sold.
> 5. `STORJ/BTC 27.24%` > 5. `STORJ/BTC 27.24%`
> ... > ...
## /balance ### /balance
Return the balance of all crypto-currency your have on the exchange. Return the balance of all crypto-currency your have on the exchange.
@ -131,7 +146,7 @@ Return the balance of all crypto-currency your have on the exchange.
> **Balance:** 86.64180098 > **Balance:** 86.64180098
> **Pending:** 0.0 > **Pending:** 0.0
## /daily <n> ### /daily <n>
Per default `/daily` will return the 7 last days. Per default `/daily` will return the 7 last days.
The example below if for `/daily 3`: The example below if for `/daily 3`:
@ -145,6 +160,6 @@ Day Profit BTC Profit USD
2018-01-01 0.00269130 BTC 34.986 USD 2018-01-01 0.00269130 BTC 34.986 USD
``` ```
## /version ### /version
> **Version:** `0.14.3` > **Version:** `0.14.3`

View File

@ -328,6 +328,16 @@ class RPC(object):
self._freqtrade.state = State.RELOAD_CONF self._freqtrade.state = State.RELOAD_CONF
return {'status': 'reloading config ...'} return {'status': 'reloading config ...'}
def _rpc_stopbuy(self) -> Dict[str, str]:
"""
Handler to stop buying, but handle open trades gracefully.
"""
if self._freqtrade.state == State.RUNNING:
# Set 'max_open_trades' to 0
self._freqtrade.config['max_open_trades'] = 0
return {'status': 'No more buy will occur from now. Run /reload_conf to reset.'}
def _rpc_forcesell(self, trade_id) -> None: def _rpc_forcesell(self, trade_id) -> None:
""" """
Handler for forcesell <id>. Handler for forcesell <id>.

View File

@ -91,6 +91,7 @@ class Telegram(RPC):
CommandHandler('daily', self._daily), CommandHandler('daily', self._daily),
CommandHandler('count', self._count), CommandHandler('count', self._count),
CommandHandler('reload_conf', self._reload_conf), CommandHandler('reload_conf', self._reload_conf),
CommandHandler('stopbuy', self._stopbuy),
CommandHandler('whitelist', self._whitelist), CommandHandler('whitelist', self._whitelist),
CommandHandler('help', self._help), CommandHandler('help', self._help),
CommandHandler('version', self._version), CommandHandler('version', self._version),
@ -362,6 +363,18 @@ class Telegram(RPC):
msg = self._rpc_reload_conf() msg = self._rpc_reload_conf()
self._send_msg('Status: `{status}`'.format(**msg), bot=bot) self._send_msg('Status: `{status}`'.format(**msg), bot=bot)
@authorized_only
def _stopbuy(self, bot: Bot, update: Update) -> None:
"""
Handler for /stop_buy.
Sets max_open_trades to 0 and gracefully sells all open trades
:param bot: telegram bot
:param update: message update
:return: None
"""
msg = self._rpc_stopbuy()
self._send_msg('Status: `{status}`'.format(**msg), bot=bot)
@authorized_only @authorized_only
def _forcesell(self, bot: Bot, update: Update) -> None: def _forcesell(self, bot: Bot, update: Update) -> None:
""" """
@ -481,6 +494,7 @@ class Telegram(RPC):
"*/count:* `Show number of trades running compared to allowed number of trades`" \ "*/count:* `Show number of trades running compared to allowed number of trades`" \
"\n" \ "\n" \
"*/balance:* `Show account balance per currency`\n" \ "*/balance:* `Show account balance per currency`\n" \
"*/stopbuy:* `Stops buying, but handles open trades gracefully` \n" \
"*/reload_conf:* `Reload configuration file` \n" \ "*/reload_conf:* `Reload configuration file` \n" \
"*/whitelist:* `Show current whitelist` \n" \ "*/whitelist:* `Show current whitelist` \n" \
"*/help:* `This help message`\n" \ "*/help:* `This help message`\n" \

View File

@ -406,6 +406,26 @@ def test_rpc_stop(mocker, default_conf) -> None:
assert freqtradebot.state == State.STOPPED assert freqtradebot.state == State.STOPPED
def test_rpc_stopbuy(mocker, default_conf) -> None:
patch_coinmarketcap(mocker)
patch_exchange(mocker)
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_ticker=MagicMock()
)
freqtradebot = FreqtradeBot(default_conf)
patch_get_signal(freqtradebot, (True, False))
rpc = RPC(freqtradebot)
freqtradebot.state = State.RUNNING
assert freqtradebot.config['max_open_trades'] != 0
result = rpc._rpc_stopbuy()
assert {'status': 'No more buy will occur from now. Run /reload_conf to reset.'} == result
assert freqtradebot.config['max_open_trades'] == 0
def test_rpc_forcesell(default_conf, ticker, fee, mocker, markets) -> None: def test_rpc_forcesell(default_conf, ticker, fee, mocker, markets) -> None:
patch_coinmarketcap(mocker) patch_coinmarketcap(mocker)
patch_exchange(mocker) patch_exchange(mocker)

View File

@ -74,7 +74,7 @@ def test_init(default_conf, mocker, caplog) -> None:
message_str = "rpc.telegram is listening for following commands: [['status'], ['profit'], " \ message_str = "rpc.telegram is listening for following commands: [['status'], ['profit'], " \
"['balance'], ['start'], ['stop'], ['forcesell'], ['forcebuy'], " \ "['balance'], ['start'], ['stop'], ['forcesell'], ['forcebuy'], " \
"['performance'], ['daily'], ['count'], ['reload_conf'], " \ "['performance'], ['daily'], ['count'], ['reload_conf'], " \
"['whitelist'], ['help'], ['version']]" "['stopbuy'], ['whitelist'], ['help'], ['version']]"
assert log_has(message_str, caplog.record_tuples) assert log_has(message_str, caplog.record_tuples)
@ -662,6 +662,26 @@ def test_stop_handle_already_stopped(default_conf, update, mocker) -> None:
assert 'already stopped' in msg_mock.call_args_list[0][0][0] assert 'already stopped' in msg_mock.call_args_list[0][0][0]
def test_stopbuy_handle(default_conf, update, mocker) -> None:
patch_coinmarketcap(mocker)
msg_mock = MagicMock()
mocker.patch.multiple(
'freqtrade.rpc.telegram.Telegram',
_init=MagicMock(),
_send_msg=msg_mock
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
telegram = Telegram(freqtradebot)
assert freqtradebot.config['max_open_trades'] != 0
telegram._stopbuy(bot=MagicMock(), update=update)
assert freqtradebot.config['max_open_trades'] == 0
assert msg_mock.call_count == 1
assert 'No more buy will occur from now. Run /reload_conf to reset.' \
in msg_mock.call_args_list[0][0][0]
def test_reload_conf_handle(default_conf, update, mocker) -> None: def test_reload_conf_handle(default_conf, update, mocker) -> None:
patch_coinmarketcap(mocker) patch_coinmarketcap(mocker)
msg_mock = MagicMock() msg_mock = MagicMock()