From e6c5c22ea08114d4ea1f5409d1afc4e3cd8d4ec3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 22 Sep 2022 19:58:38 +0200 Subject: [PATCH] Update websocket/follower docs --- docs/advanced-external-signals.md | 37 ++++++++++++++++++---- docs/configuration.md | 2 +- docs/rest-api.md | 15 ++++----- freqtrade/rpc/external_message_consumer.py | 2 +- 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/docs/advanced-external-signals.md b/docs/advanced-external-signals.md index caf708ee2..3fb3ce6ce 100644 --- a/docs/advanced-external-signals.md +++ b/docs/advanced-external-signals.md @@ -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. !!! Note 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. -```jsonc +```json { //... "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 } ], + // 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.
*Defaults to `false`.*
**Datatype:** boolean . +| `producers` | **Required.** List of producers
**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.
**Datatype:** string +| `producers.host` | **Required.** The hostname or IP address from your leader.
**Datatype:** string +| `producers.port` | **Required.** The port matching the above host.
**Datatype:** string +| `producers.ws_token` | **Required.** `ws_token` as configured on the leader.
**Datatype:** string +| | **Optional settings** +| `wait_timeout` | Timeout until we ping again if no message is received.
*Defaults to `300`.*
**Datatype:** Integer - in seconds. +| `wait_timeout` | Ping timeout
*Defaults to `10`.*
**Datatype:** Integer - in seconds. +| `sleep_time` | Sleep time before retrying to connect.
*Defaults to `10`.*
**Datatype:** Integer - in seconds. +| `remove_entry_exit_signals` | Remove signal columns from the dataframe (set them to 0) on dataframe receipt.
*Defaults to `10`.*
**Datatype:** Integer - in seconds. +| `message_size_limit` | Size limit per message
*Defaults to `8`.*
**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. +## Examples + ### Example - Leader Strategy 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 -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 class FollowerStrategy(IStrategy): @@ -82,7 +105,7 @@ class FollowerStrategy(IStrategy): 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 """ pair = metadata['pair'] diff --git a/docs/configuration.md b/docs/configuration.md index f4fb46707..211feef05 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -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.
**Keep it in secret, do not disclose publicly.**
**Datatype:** String | `api_server.ws_token` | API token for the Message WebSocket. See the [API Server documentation](rest-api.md) for more details.
**Keep it in secret, do not disclose publicly.**
**Datatype:** String | `bot_name` | Name of the bot. Passed via API to a client - can be shown to distinguish / name bots.
*Defaults to `freqtrade`*
**Datatype:** String -| `external_message_consumer` | Enable consuming of external signals. See the [API Server documentation](rest-api.md) for more details.
**Datatype:** Dict +| `external_message_consumer` | Enable consuming of external signals. See the [External signals](advanced-external-signals.md) for more details.
**Datatype:** Dict | | **Other** | `initial_state` | Defines the initial application state. If set to stopped, then the bot has to be explicitly started via `/start` RPC command.
*Defaults to `stopped`.*
**Datatype:** Enum, either `stopped` or `running` | `force_entry_enable` | Enables the RPC Commands to force a Trade entry. More information below.
**Datatype:** Boolean diff --git a/docs/rest-api.md b/docs/rest-api.md index e1ba1e889..1f09704b7 100644 --- a/docs/rest-api.md +++ b/docs/rest-api.md @@ -1,4 +1,4 @@ -# REST API, FreqUI & External Signals +# REST API & FreqUI ## FreqUI @@ -325,15 +325,14 @@ whitelist ### Message WebSocket -The API Server makes available 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. +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. 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 generate a safe `ws_token` you can run the following code: +To generate a safe `ws_token` you can run the following code: ``` python >>> import secrets @@ -341,7 +340,6 @@ To access the websocket endpoint, the `ws_token` is required as a query paramete 'hZ-y58LXyX_HZ8O1cJzVyN6ePWrLpNQv4Q' ``` - You would then add that token under `ws_token` in your `api_server` config. Like so: ``` 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`. -!!! 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. - #### 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. @@ -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 } ``` + 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: diff --git a/freqtrade/rpc/external_message_consumer.py b/freqtrade/rpc/external_message_consumer.py index 61b8ac2db..a57fac144 100644 --- a/freqtrade/rpc/external_message_consumer.py +++ b/freqtrade/rpc/external_message_consumer.py @@ -35,7 +35,7 @@ logger = logging.getLogger(__name__) class ExternalMessageConsumer: """ The main controller class for consuming external messages from - other FreqTrade bot's + other freqtrade bot's """ def __init__(