https://github.com/tradingstrategy-ai/dex-live-algorithmic-trading-example
An example repository how to set up a TradingStrategy.ai trade-executor with a live trading strategy
https://github.com/tradingstrategy-ai/dex-live-algorithmic-trading-example
decentralized-exchange docker ethereum python trading-bot trading-strategies
Last synced: 6 months ago
JSON representation
An example repository how to set up a TradingStrategy.ai trade-executor with a live trading strategy
- Host: GitHub
- URL: https://github.com/tradingstrategy-ai/dex-live-algorithmic-trading-example
- Owner: tradingstrategy-ai
- Created: 2024-07-02T21:03:48.000Z (over 1 year ago)
- Default Branch: master
- Last Pushed: 2024-08-19T06:48:04.000Z (about 1 year ago)
- Last Synced: 2025-03-27T03:51:17.594Z (7 months ago)
- Topics: decentralized-exchange, docker, ethereum, python, trading-bot, trading-strategies
- Language: Jupyter Notebook
- Homepage: https://tradingstrategy.ai
- Size: 6.82 MB
- Stars: 6
- Watchers: 1
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# DEX live trading strategy deployment example
This is an example repository for setting up a `docker-compose.yml` for a minimal live [trade-executor](https://github.com/tradingstrategy-ai/trade-executor/).
- This repository comes with a preconfigured strategy `hotwallet-polygon-eth-usdc-breakout`
- This allows you to start a live trade execution on your computer using Docker
- It is a limited preproduction environment with devops and web frontend missing
- We use the Polygon blockchain as it is an easy and cost-friendly way to do some test trades
- The folder structure is set up in a manner you can run several trade executors under the same `docker-compose.yml` configuration* [Step 1: Develop a trading strategy](#step-1-develop-a-trading-strategy)
* [Step 2: Give the strategy id](#step-2-give-the-strategy-id)
* [Step 3: Extract strategy as a Python module](#step-3-extract-strategy-as-a-python-module)
* [Step 4: Set up docker-compose.yml entry](#step-4-set-up-docker-composeyml-entry)
* [Step 5: Set up an environment file](#step-5-set-up-an-environment-file)
* [Step 6: Launching Docker for the first time](#step-6-launching-docker-for-the-first-time)
* [Step 6a: Set Github container registry access](#step-6a-set-github-container-registry-access)
* [Step 6b: Test Docker container start](#step-6b-test-docker-container-start)
* [Step 7: Run backtest for the strategy module](#step-7-run-backtest-for-the-strategy-module)
* [Step 8: Set up a hot wallet](#step-8-set-up-a-hot-wallet)
* [Step 8a: Generate a private key](#step-8a-generate-a-private-key)
* [Step 8b: Add the private key environment variable file](#step-8b-add-the-private-key-environment-variable-file)
* [Step 8c Check the wallet](#step-8c-check-the-wallet)
* [Step 8d: Fund the account](#step-8d-fund-the-account)
* [Step 8e: Check the wallet again](#step-8e-check-the-wallet-again)
* [Step 9: Check the trading universe](#step-9-check-the-trading-universe)
* [Step 10: Init the strategy](#step-10-init-the-strategy)
* [Step 11: Perform test trade](#step-11-perform-test-trade)
* [Step 12: Launch the live trading strategy](#step-12-launch-the-live-trading-strategy)
* [Step 13: Configure additional RPC providers (optional)](#step-13-configure-additional-rpc-providers-optional)
* [Step 14: Set up Discord logging (optional)](#step-14-set-up-discord-logging-optional)
* [Support and social media](#support-and-social-media)# Preface
This is an example repository to do partial deployment for live trading strategies.
You need
- Basic experience in UNIX system administration
- Linux / macOS laptop
- On Windows, use Windows Subsystem for Linux (WSL)
- Docker installationThis preproduction set up can be more straightforward than the actual production deployment, as we shortcut a few things here:
- Security like managing the access to the private keys
- Web frontend
- Devops and diagnostics output: Only output is Docker process stdout# Step 1: Develop a trading strategy
See [Getting started](https://github.com/tradingstrategy-ai/getting-started) if you do not have a trading strategy yet.
The usual deliverables of developing a trading strategy include:
1. Initial backtest notebook
2. Optimiser that crunches through multiple parameters
2. Final backtest notebook with fixed parameters you are prepared to take to the live tradingThis repository comes with a simple example ETH-USDC strategy.
For this example we have
1. Initial backtest - somewhere in [Getting started repo](https://github.com/tradingstrategy-ai/getting-started)
2. Optimiser notebook. [See here](./notebooks/eth-breakout-optimiser.ipynb)
3. Final backtest. [See here](./notebooks/eth-breakout-dex-final.ipynb)**Note**: Github does not view notebooks fully - you need to open them locally.
**Note**: This strategy might be too simple and overfit for real-world trading.
# Step 2: Give the strategy id
You are going to have a lot of strategies. You need to have a systematic way to keep track of them.
This example uses id `hotwallet-polygon-eth-usdc-breakout`. It's a mouthful, but self-explanatory.
- Asset management mode (hot wallet)
- The target chain (Polygon)
- Pairs to be traded (ETH/USDC)
- Type of strategy (breakout)This id is used in
- URLs
- State file
- Log files
- etc.# Step 3: Extract strategy as a Python module
We convert the final backtest notebook to a Python module. We use (3) from the step above as the starting point.
Rules to convert
- Create a Python file
- Copy-paste the strategy from the notebook
- `Parameteters` class
- `decide_trades`
- `create_indicators`
- `create_strategy_universe`
- Autocomplete the imports for the Python file
- Usually a good editor like Visual Studio Code or PyCharm can do this for you with a keypress or two
- Modify `create_strategy_universe` to cater to both the backtesting and live trading
- Different options are available if you want to show DEX backtesting data (usually too short period)
- Add the following Python module variables```python
trading_strategy_engine_version = "0.5"
name = "ETH-BTC-USDC momentum" # Optional: Frontend metadata
tags = {StrategyTag.beta, StrategyTag.live} # Optional: Frontend metadata
icon = "" # Optional: Frontend metadata
short_description = "" # Optional: Frontend metadata
long_description = "" # Optional: Frontend metadata
```We also edit the strategy to dynamically decide which trading universe to use
- Binance for backtesting (longer history)
- DEX for live tradingExample modification here:
```python
def get_strategy_trading_pairs(execution_mode: ExecutionMode) -> list[HumanReadableTradingPairDescription]:
if execution_mode.is_backtesting():
# Need longer history
trading_pairs = [
(ChainId.centralised_exchange, "binance", "ETH", "USDT"),
]else:
# For live trading we do Uniswap v3 on Polygon
trading_pairs = [
(ChainId.polygon, "uniswap-v3", "WETH", "USDC", 0.0005),
]
return trading_pairsdef create_trading_universe(
timestamp: datetime.datetime,
client: Client,
execution_context: ExecutionContext,
universe_options: UniverseOptions,
) -> TradingStrategyUniverse:
"""Create the trading universe."""
trading_pairs = get_strategy_trading_pairs(execution_context.mode)if execution_context.mode.is_backtesting():
# Backtesting - load Binance data to get longer history
strategy_universe = create_binance_universe(
[f"{p[2]}{p[3]}" for p in trading_pairs],
candle_time_bucket=Parameters.candle_time_bucket,
stop_loss_time_bucket=Parameters.stop_loss_time_bucket,
start_at=universe_options.start_at,
end_at=universe_options.end_at,
forward_fill=True,
)else:
# How many bars of live trading data needed
required_history_period = Parameters.required_history_perioddataset = load_partial_data(
client=client,
time_bucket=Parameters.candle_time_bucket,
pairs=trading_pairs,
execution_context=execution_context,
universe_options=universe_options,
liquidity=False,
stop_loss_time_bucket=Parameters.stop_loss_time_bucket,
required_history_period=required_history_period,
)
# Construct a trading universe from the loaded data,
# and apply any data preprocessing needed before giving it
# to the strategy and indicators
strategy_universe = TradingStrategyUniverse.create_from_dataset(
dataset,
reserve_asset="USDC",
forward_fill=True,
)return strategy_universe
```- [See the full resulting Python file here](./strategies/hotwallet-polygon-eth-usdc-breakout.py)
# Step 4: Set up docker-compose.yml entry
- [See docker-compose.yml](./docker-compose.yml)
**Note**: We use new style `docker compose` commands in this README, instead of `docker-compose` legacy command (with dash). Make sure you have the latest version.
# Step 5: Set up an environment file
Each trade executor docker is configured using environment variable files using the normal Docker conventions.
**Note**: For the production deployment it is recommend against putting any highly sensitive material like private keys
directly to these files/- See [hotwallet-polygon-eth-usdc-breakout.env](./env/hotwallet-polygon-eth-usdc-breakout.env)
The file comes with
- No hot wallet set up
- No Trading Strategy API key set up
- Public low quality Polygon RPC endpoint (do not use for production - likely just keeps crashing)# Step 6: Launching Docker for the first time
## Step 6a: Set Github container registry access
Docker images are distributed on [Github Container Registry ghcr.io](https://github.com/features/packages).
The access is public, but you need to have an access token through your Github account.To enable docker login to Github see [how to set up Github access token to download Docker images from GHCR](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry>).
- [Create a personal access tokens in Developer settings of your Github account](https://github.com/settings/tokens) - classic token
- You need an access token to publish, install, and delete private, internal, and public packages:
`repo:*` and `read:packages`.When you find your token you can do:
```shell
GITHUB_USERNAME=miohtama
# Your Personal Access Token (classic)
CR_PAT=ghp_mmc...
# This will save a config file locally with your GHCR access key
echo $CR_PAT | docker login ghcr.io -u $GITHUB_USERNAME --password-stdin
```Docker login should reply:
```
Login Succeeded
```## Step 6b: Test Docker container start
We try to run and verify our Docker Compose launches.
First we need to choose the trade-executor release. The trade executor is under active development
and may see multiple releases per day. [You can find releases on Github](https://github.com/tradingstrategy-ai/trade-executor/pkgs/container/trade-executor)```shell
# Get the latest trade-executor version tag from Github to environment variable
source scripts/export-latest-trade-executor-version.sh# Launch to show the command line help
docker compose run hotwallet-polygon-eth-usdc-breakout --help
```You should see the command line help for [trade-executor command](https://tradingstrategy.ai/docs/deployment/trade-executor.html):
```
Usage: trade-executor [OPTIONS] COMMAND [ARGS]...Options:
--install-completion [bash|zsh|fish|powershell|pwsh]
Install completion for the specified shell.
--show-completion [bash|zsh|fish|powershell|pwsh]
Show completion for the specified shell, to copy it or customize the installation.
--help Show this message and exit.
...
```# Step 7: Run backtest for the strategy module
This will run the strategy backtest using `docker compose` command.
- This command will execute the same backtest as you would have run earlier in the final notebook
- Python errors when running this command will catch any mistakes made during the strategy module creation
- Backtest artifacts like HTML backtest report are written under `state/` folder
- The same artifacts will be served in the web frontend for the users who want to see the backtest resultsYou need to add your [Trading Strategy API key](https://tradingstrategy.ai/trading-view/api) in [./env/hotwallet-polygon-eth-usdc-breakout.env](./env/hotwallet-polygon-eth-usdc-breakout.env):
Now run the backtest:
```shell
docker compose run hotwallet-polygon-eth-usdc-breakout backtest
```**Note**: Currently macOS and Apple Silicon run Intel architecture Docker images, slowing down the execution 5x - 10x. [Github Actions do not support building macOS Docker images yet](https://stackoverflow.com/a/78202969/315168). When you run this command on macOS prepare to wait for ~20 minutes.
You are likely to encounter several Python bugs in this step, so keep fixing your Python strategy module.
The end of the output should look like:
```
Writing backtest data the state file: /usr/src/trade-executor/state/hotwallet-polygon-eth-usdc-breakout-backtest.json
Exporting report, notebook: state/hotwallet-polygon-eth-usdc-breakout-backtest.ipynb, HTML: state/hotwallet-polygon-eth-usdc-breakout-backtest.html
```After the backtest is complete, you can view the HTML report:
```shell
# macOS way to open a HTML file from the command line
open state/hotwallet-polygon-eth-usdc-breakout-backtest.html
```You should see the backtest results, as captured from the default backtest notebook template:

# Step 8: Set up a hot wallet
You need a hot wallet
- It costs ETH/MATIC/etc. to broadcast the transactions for your trades
- A hot wallet is just an EVM account with the associated private key## Step 8a: Generate a private key
To create a hot wallet for the executor you can [do it from the command line](https://ethereum.stackexchange.com/questions/82926/how-to-generate-a-new-ethereum-address-and-private-key-from-a-command-line):
```shell
head -c 32 /dev/urandom|xxd -ps -c 32
```This will give you a private key (example - do not use this private key):
```
68f4e1be83e2bd242d1a5a668574dd3b6b76a29f254b4ae662eba5381d1fc3a6
```Then
- Store the private key safely in your backup storage (password manager, or something stronger depending on the security level)
**Note**: Hot wallets cannot be shared across different `trade-executor` instances, because this will mess up accounting.
## Step 8b: Add the private key environment variable file
Private key will be needed in the trade execution configuration file
- Edit `hotwallet-polygon-eth-usdc-breakout.env`.
- Add `0x` prefix to the raw hex output from the step above
- Fill in `PRIVATE_KEY`.Example:
```shell
# Do not use this private key
PRIVATE_KEY=0x68f4e1be83e2bd242d1a5a668574dd3b6b76a29f254b4ae662eba5381d1fc3a6
```## Step 8c Check the wallet
`trade-executor` provides the subcommand `check-wallet` to check the hot wallet status.
This checks
- You are connected to the right blockchain
- Your hot wallet private key has been correctly set up
- You have native token for gas fees
- You have trading capital
- The last block number of the blockchain
- We know how to route trades for our strategy, using the current wallet
```shell
docker compose run hotwallet-polygon-eth-usdc-breakout check-wallet
```
Output:```
AssertionError: At least 0.1 native currency need, our wallet 0xABF10A4027B3e5D29c21292955DcC4ECCe05747A has 0.00000000
```This gives you the address for your private key.
## Step 8d: Fund the account
We need to fund the account on Polygon
- MATIC to cover the gas fees: get 25 MATIC.
- [USDC.e](https://tradingstrategy.ai/trading-view/polygon/tokens/0x2791bca1f2de4661ed88a30c99a7a9449aa84174), also known USD Coin PoS: get 25 USDC.e.You can use a service like [Transak](https://transak.com/) to get MATIC with a debit card. KYC needed.
You can get MATIC swapped to USDC.e e.g. on [KyberSwap](https://kyberswap.com/swap/polygon).Send MATIC and USDC.e to the address you saw above.
**Note**: Due to historical reasons we use USDC.e (bridged variant) over native USDC on Polygon,
because it has better liquidity. These two tokens are not fungible as the writing of this.## Step 8e: Check the wallet again
Now you should have some MATIC and USDC.e in your hot wallet.
```shell
docker compose run hotwallet-polygon-eth-usdc-breakout check-wallet
```
We see the account is funded now:```
Balance details
Hot wallet is 0xABF10A4027B3e5D29c21292955DcC4ECCe05747A
We have 10.000000 tokens left for gas
The gas error limit is 0.100000 tokens
Reserve asset: USDC
Reading token balances for 1 tokens at block 59193849, last
Balance of USD Coin (PoS) (0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174): 1.988353 USDC
```# Step 9: Check the trading universe
`trade-executor` provides the subcommand `check-universe` to ensure the market data feeds work correctly.
- This confirms your Trading Strategy oracle API keys are correctly set up
and your strategy can receive data.- The market data feed is up-to-date
You can run this with configured `docker-compose` as:
```shell
docker compose run hotwallet-polygon-eth-usdc-breakout check-universe
```This will print out the last available candle, based on the the strategy `Parameters.candle_time_bucket`:
```
Latest OHCLV candle is at: 2024-07-10 15:00:00, 0:19:41.794234 ago
```# Step 10: Init the strategy
This will write the initial state file for your trading strategy:
```shell
docker compose run hotwallet-polygon-eth-usdc-breakout init
```It should output something like:
```
Saved state to state/hotwallet-polygon-eth-usdc-breakout.json, total 1,108 chars
All done: State deployment info is
```# Step 11: Perform test trade
After you are sure that trading data and hot wallet are fine,
you can perform a test trade from the command line.- This will ensure trade routing and execution gas fee methods
are working by executing a live trade against live blockchain.- The test trade will buy and sell the "default" asset of the strategy
worth 1 USD. For a single pair strategies the asset is the default
base token.- This will open a position using the strategy's exchange and trade
pair routing.- The position and the trade will have notes field filled in that
this was a test trade.- Broadcasting a transaction through your JSON-RPC connection
works.Example:
```shell
docker compose run hotwallet-polygon-eth-usdc-breakout perform-test-trade
```This will print something like:
```
Test trade report
Gas spent: 0.016125835459386936
Trades done currently: 2
Reserves currently: 1.986876 USDC
Reserve currency spent: 0.0014769999999999506 USDC
Buy trade price, expected: 3113.8176546091504, actual: 3111.
Sell trade price, expected: 3108.3790383082533, actual: 3110.0700549742683 (WETH-USDC)
```# Step 12: Launch the live trading strategy
Now you are ready to start the strategy.
We first suggest start on the foreground.
```shell
docker compose up hotwallet-polygon-eth-usdc-breakout
```After the boot up dance you will see:
```
apscheduler.scheduler INFO Scheduler started
```This means the trade-executor is now running, with its scheduled tasks (decide trades, check stop losses, revalue the portfolio, etc.). Leave it running.
There is a lot of output (noisy). In some point you should catch the message about `decide_trades`:
```
2024-07-11 08:08:27 tradeexecutor.strategy.runner INFO No open
2024-07-11 08:08:27 tradeexecutor.strategy.runner INFO No frozen
2024-07-11 08:08:27 tradeexecutor.strategy.runner TRADE Portfolio
Total equity: $1.99, in cash: $1.99
Life-time positions: 1, trades: 2
…
Reserves:
1.99 USDC
2024-07-11 08:08:27 tradeexecutor.utils.timer INFO Starting task decide_trades at 2024-07-11 08:08:27.183694, context is {}
```The given strategy rebalances every 1h. So you should see something working or not working within 1h. The rebalance does not happen exactly at 00 minutes, but a bit past, as the candle data needs to be properly formed first.
For the long-term running, use daemon option:
```shell
docker compose up -d hotwallet-polygon-eth-usdc-breakout
```# Step 13: Configure additional RPC providers (optional)
- The configuration line `JSON_RPC_POLYGON` accepts multiple space separared provided URLs.
- The same feature can be used to add MEV protected RPC endpoints for your trade executor[See the multi-RPC configuration documentation here](https://web3-ethereum-defi.readthedocs.io/tutorials/multi-rpc-configuration.html).
# Step 14: Set up Discord logging (optional)
In this example, we only output trades in the docker console.
The trade-executor supports output to different team chat mediums. like Discord.
To configure Discord logging
- Create a private Discord channel
- In the channel settings, go to *Integrations*
- Press *Create Webhook*
- Add the webhook URL in the environment variable file as `DISCORD_WEBHOOK_URL````
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/12...
```
Now all trade-related logging messages will be displayed at the Discord channel as well.# Support and social media
Got any questions? Pop into our Discord.
- [Trading Strategy community Discord server](https://tradingstrategy.ai/community#discord)
- [Trading Strategy website](https://tradingstrategy.ai)
- [Blog](https://tradingstrategy.ai/blog)
- [Twitter](https://twitter.com/TradingProtocol)
- [Telegram channel](https://t.me/trading_protocol)
- [Newsletter](https://tradingstrategy.ai/newsletter)