Update websocket/follower docs

This commit is contained in:
Matthias 2022-09-22 19:58:38 +02:00
parent 6a6ae809f4
commit e6c5c22ea0
4 changed files with 38 additions and 18 deletions

View File

@ -1,15 +1,17 @@
FreqTrade provides a mechanism whereby an instance may listen to messages from an upstream FreqTrade instance using the message websocket. Mainly, `analyzed_df` and `whitelist` messages. This allows the reuse of computed indicators (and signals) for pairs in multiple bots without needing to compute them multiple times. # External Signals
freqtrade provides a mechanism whereby an instance may listen to messages from an upstream freqtrade instance using the message websocket. Mainly, `analyzed_df` and `whitelist` messages. This allows the reuse of computed indicators (and signals) for pairs in multiple bots without needing to compute them multiple times.
See [Message Websocket](rest-api.md#message-websocket) in the Rest API docs for setting up the `api_server` configuration for your message websocket. See [Message Websocket](rest-api.md#message-websocket) in the Rest API docs for setting up the `api_server` configuration for your message websocket.
!!! Note !!! Note
We strongly recommend to also set `ws_token` to something random and known only to yourself to avoid unauthorized access to your bot. We strongly recommend to also set `ws_token` to something random and known only to yourself to avoid unauthorized access to your bot.
### Configuration ## Configuration
Enable subscribing to an instance by adding the `external_message_consumer` section to the follower's config file. Enable subscribing to an instance by adding the `external_message_consumer` section to the follower's config file.
```jsonc ```json
{ {
//... //...
"external_message_consumer": { "external_message_consumer": {
@ -22,17 +24,38 @@ Enable subscribing to an instance by adding the `external_message_consumer` sect
"ws_token": "mysecretapitoken" // The ws_token from your leader's api_server config "ws_token": "mysecretapitoken" // The ws_token from your leader's api_server config
} }
], ],
// The following configurations are optional, and usually not required
// "wait_timeout": 300,
// "ping_timeout": 10,
// "sleep_time": 10,
// "remove_entry_exit_signals": false,
// "message_size_limit": 8
} }
//... //...
} }
``` ```
See [`config_examples/config_full.example.json`](https://github.com/freqtrade/freqtrade/blob/develop/config_examples/config_full.example.json) for all of the parameters you can set. | Parameter | Description |
|------------|-------------|
| `enabled` | **Required.** Enable follower mode. If set to false, all other settings in this section are ignored.<br>*Defaults to `false`.*<br> **Datatype:** boolean .
| `producers` | **Required.** List of producers <br> **Datatype:** Array.
| `producers.name` | **Required.** Name of this producer. This name must be used in calls to `get_producer_pairs()` and `get_external_df()` if more than one producer is used.<br> **Datatype:** string
| `producers.host` | **Required.** The hostname or IP address from your leader.<br> **Datatype:** string
| `producers.port` | **Required.** The port matching the above host.<br> **Datatype:** string
| `producers.ws_token` | **Required.** `ws_token` as configured on the leader.<br> **Datatype:** string
| | **Optional settings**
| `wait_timeout` | Timeout until we ping again if no message is received. <br>*Defaults to `300`.*<br> **Datatype:** Integer - in seconds.
| `wait_timeout` | Ping timeout <br>*Defaults to `10`.*<br> **Datatype:** Integer - in seconds.
| `sleep_time` | Sleep time before retrying to connect.<br>*Defaults to `10`.*<br> **Datatype:** Integer - in seconds.
| `remove_entry_exit_signals` | Remove signal columns from the dataframe (set them to 0) on dataframe receipt.<br>*Defaults to `10`.*<br> **Datatype:** Integer - in seconds.
| `message_size_limit` | Size limit per message<br>*Defaults to `8`.*<br> **Datatype:** Integer - Megabytes.
Instead of (or as well as) calculating indicators in `populate_indicators()` the follower instance listens on the connection to a leader instance's message websocket (or multiple leader instances in advanced configurations) and requests the leader's most recently analyzed dataframes for each pair in the active whitelist. Instead of (or as well as) calculating indicators in `populate_indicators()` the follower instance listens on the connection to a leader instance's messages (or multiple leader instances in advanced configurations) and requests the leader's most recently analyzed dataframes for each pair in the active whitelist.
A follower instance will then have a full copy of the analyzed dataframes without the need to calculate them itself. A follower instance will then have a full copy of the analyzed dataframes without the need to calculate them itself.
## Examples
### Example - Leader Strategy ### Example - Leader Strategy
A simple strategy with multiple indicators. No special considerations are required in the strategy itself. A simple strategy with multiple indicators. No special considerations are required in the strategy itself.
@ -71,7 +94,7 @@ class LeaderStrategy(IStrategy):
### Example - Follower Strategy ### Example - Follower Strategy
A logically equivalent strategy which calculates no indicators itself, but will have the same analyzed dataframes to make trading decisions from as the leader. In this example the follower has the same entry criteria, however this is not necessary. The follower may use different logic to enter/exit trades. A logically equivalent strategy which calculates no indicators itself, but will have the same analyzed dataframes available to make trading decisions based on the indicators calculated in the leader. In this example the follower has the same entry criteria, however this is not necessary. The follower may use different logic to enter/exit trades, and only use the indicators as specified.
```py ```py
class FollowerStrategy(IStrategy): class FollowerStrategy(IStrategy):
@ -82,7 +105,7 @@ class FollowerStrategy(IStrategy):
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
""" """
Use the websocket api to get pre-populated indicators from another FreqTrade instance. Use the websocket api to get pre-populated indicators from another freqtrade instance.
Use `self.dp.get_external_df(pair)` to get the dataframe Use `self.dp.get_external_df(pair)` to get the dataframe
""" """
pair = metadata['pair'] pair = metadata['pair']

View File

@ -234,7 +234,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `api_server.password` | Password for API server. See the [API Server documentation](rest-api.md) for more details. <br>**Keep it in secret, do not disclose publicly.**<br> **Datatype:** String | `api_server.password` | Password for API server. See the [API Server documentation](rest-api.md) for more details. <br>**Keep it in secret, do not disclose publicly.**<br> **Datatype:** String
| `api_server.ws_token` | API token for the Message WebSocket. See the [API Server documentation](rest-api.md) for more details. <br>**Keep it in secret, do not disclose publicly.** <br> **Datatype:** String | `api_server.ws_token` | API token for the Message WebSocket. See the [API Server documentation](rest-api.md) for more details. <br>**Keep it in secret, do not disclose publicly.** <br> **Datatype:** String
| `bot_name` | Name of the bot. Passed via API to a client - can be shown to distinguish / name bots.<br> *Defaults to `freqtrade`*<br> **Datatype:** String | `bot_name` | Name of the bot. Passed via API to a client - can be shown to distinguish / name bots.<br> *Defaults to `freqtrade`*<br> **Datatype:** String
| `external_message_consumer` | Enable consuming of external signals. See the [API Server documentation](rest-api.md) for more details. <br> **Datatype:** Dict | `external_message_consumer` | Enable consuming of external signals. See the [External signals](advanced-external-signals.md) for more details. <br> **Datatype:** Dict
| | **Other** | | **Other**
| `initial_state` | Defines the initial application state. If set to stopped, then the bot has to be explicitly started via `/start` RPC command. <br>*Defaults to `stopped`.* <br> **Datatype:** Enum, either `stopped` or `running` | `initial_state` | Defines the initial application state. If set to stopped, then the bot has to be explicitly started via `/start` RPC command. <br>*Defaults to `stopped`.* <br> **Datatype:** Enum, either `stopped` or `running`
| `force_entry_enable` | Enables the RPC Commands to force a Trade entry. More information below. <br> **Datatype:** Boolean | `force_entry_enable` | Enables the RPC Commands to force a Trade entry. More information below. <br> **Datatype:** Boolean

View File

@ -1,4 +1,4 @@
# REST API, FreqUI & External Signals # REST API & FreqUI
## FreqUI ## FreqUI
@ -325,15 +325,14 @@ whitelist
### Message WebSocket ### Message WebSocket
The API Server makes available a websocket endpoint for subscribing to RPC messages The API Server includes a websocket endpoint for subscribing to RPC messages
from the FreqTrade Bot. This can be used to consume real-time data from your bot, such as entry/exit fill messages, whitelist changes, populated indicators for pairs, and more. from the freqtrade Bot. This can be used to consume real-time data from your bot, such as entry/exit fill messages, whitelist changes, populated indicators for pairs, and more.
Assuming your rest API is set to `127.0.0.1` on port `8080`, the endpoint is available at `http://localhost:8080/api/v1/message/ws`. Assuming your rest API is set to `127.0.0.1` on port `8080`, the endpoint is available at `http://localhost:8080/api/v1/message/ws`.
To access the websocket endpoint, the `ws_token` is required as a query parameter in the endpoint URL. To access the websocket endpoint, the `ws_token` is required as a query parameter in the endpoint URL.
To generate a safe `ws_token` you can run the following code:
To generate a safe `ws_token` you can run the following code:
``` python ``` python
>>> import secrets >>> import secrets
@ -341,7 +340,6 @@ To access the websocket endpoint, the `ws_token` is required as a query paramete
'hZ-y58LXyX_HZ8O1cJzVyN6ePWrLpNQv4Q' 'hZ-y58LXyX_HZ8O1cJzVyN6ePWrLpNQv4Q'
``` ```
You would then add that token under `ws_token` in your `api_server` config. Like so: You would then add that token under `ws_token` in your `api_server` config. Like so:
``` json ``` json
@ -361,11 +359,9 @@ You would then add that token under `ws_token` in your `api_server` config. Like
You can now connect to the endpoint at `http://localhost:8080/api/v1/message/ws?token=hZ-y58LXyX_HZ8O1cJzVyN6ePWrLpNQv4Q`. You can now connect to the endpoint at `http://localhost:8080/api/v1/message/ws?token=hZ-y58LXyX_HZ8O1cJzVyN6ePWrLpNQv4Q`.
!!! warning "Warning" !!! Danger "Reuse of example tokens"
Please do not use the above example token. To make sure you are secure, generate a completely new token. Please do not use the above example token. To make sure you are secure, generate a completely new token.
#### Using the WebSocket #### Using the WebSocket
Once connected to the WebSocket, the bot will broadcast RPC messages to anyone who is subscribed to them. To subscribe to a list of messages, you must send a JSON request through the WebSocket like the one below. The `data` key must be a list of message type strings. Once connected to the WebSocket, the bot will broadcast RPC messages to anyone who is subscribed to them. To subscribe to a list of messages, you must send a JSON request through the WebSocket like the one below. The `data` key must be a list of message type strings.
@ -376,6 +372,7 @@ Once connected to the WebSocket, the bot will broadcast RPC messages to anyone w
"data": ["whitelist", "analyzed_df"] // A list of string message types "data": ["whitelist", "analyzed_df"] // A list of string message types
} }
``` ```
For a list of message types, please refer to the RPCMessageType enum in `freqtrade/enums/rpcmessagetype.py` For a list of message types, please refer to the RPCMessageType enum in `freqtrade/enums/rpcmessagetype.py`
Now anytime those types of RPC messages are sent in the bot, you will receive them through the WebSocket as long as the connection is active. They typically take the same form as the request: Now anytime those types of RPC messages are sent in the bot, you will receive them through the WebSocket as long as the connection is active. They typically take the same form as the request:

View File

@ -35,7 +35,7 @@ logger = logging.getLogger(__name__)
class ExternalMessageConsumer: class ExternalMessageConsumer:
""" """
The main controller class for consuming external messages from The main controller class for consuming external messages from
other FreqTrade bot's other freqtrade bot's
""" """
def __init__( def __init__(