-
In this trading mehtod, you are essentially betting that two trading pairs are going to revert to the mean. LTCM likely used the same trading method. Refer to this link. Below is an introduction of how it works:
- identify cointegrated pairs Cointegration is the difference between two trading pairs prices converging and diverging. Two trading pairs that are cointegrated are generally correlated. However, being correlated doesn't mean that the two prices will cross (aka mean revert). If this is the case, the two trading pairs doon't meet the requirements to be cointegrated.
- Below is an example of cointegrated pairs.
- Below is an example of correlated but not cointegrated pairs
- Cointegrated pairs with in
python
can be represented withstatsmodel
from statsmodels.tsa.stattools import coint coint_res = coint(series_1, series_2)
- Spread is used as a indication that there is a chance for mean reversion. The larger the spread the higher the possibility of mean reversion
- But what is the likelihood of mean reversion when the spread is wide? The answer is the Z-score spread.
- From the image above, you can see that the spread sometimes has a z-score or standard deviation of 4. At 4 standard deviations, it means the current number has a chance of 0.01% outside the mean, giving it a high probability that it will revert back to the mean. Refer to magnitudes in standard deviation for more information.
-
Important concepts used for this code:
- z-score: (x - mean) / std
- Spread: series_1 - (hedge_ratio * series_2)
- Hedge Ratio: How much of one trading pair would I need to buy relative to another trading pair. i.e. 16 ETH equals to 1 BTC
- Half-Life: How long will it take for our spread to revert. It can be argued that this is one of the reasons that LCTM failed.
- Kelly Criterion: position sizing for risk management. It can be argued that this is another reason that LCTM failed.
- Have Metamask wallet, change to Goerli Network
- Go to Goerli Faucet to send ETH
- Head to DYDX exchange to connect wallet with Goerli test network, remember to click on "remember me"
- Then inspect element -> Application -> Local Storage -> "trade.stage.dydx.exchange" -> find "STARK_KEY_PAIRS" and "API_KEY_PAIRS"
- Information to collect for DYDX to add to
.env
:- ETHEREUM ADDRESS
- ETH PRIVATE KEY
- STARK PRIVATE KEY
- DYDX API KEY
- DYDX API SECRET
- DYDX API PASSPHRASE
- HOST = API_HOST_GOERLI
- check python version with
python3 --version
- create a python virtual environment with
python3 -m venv venv
- run
source venv/bin/activate
- run
pip3 install -r requirements.txt
. requirements.txt is found in the course resources - then initialize git,
git init
- in
.gitignore
add.env
andvenv
to ignore these files and folders
- in root, run
source venv/bin/activate
to activate venv environment - go to
cd program
- run
python3 main.py
- there should be output below:
Connection Successful
Account ID: <ID>
Quote Balance: <Amount>
- run
deactive
to exit venv environment
- Connect to DYDX
- Place Market Order
- Abort All Open Orders
- Construct Market Prices & Store Cointegrated Pairs: Find all market prices pairs, put them in table and find, based on the prices, which one is cointegrated.
- Get ISO times: refer to DYDX
fromISO
andtoISO
, withlimit
- Get historical candles
- Construct market prices
- Write conintegration functions
- Find and store cointegration pairs
- Get ISO times: refer to DYDX
- While True
- Manage Existing Trades & Open Positions
- Create bot agent class
- Open Trades
- Check Validity of Order Status by ID
- Get recent candles
- Check if exit and exit open trades
- Check open positions
- Place and save trades
- Create bot agent class
- Manage Existing Trades & Open Positions
- Steps to setup AWS EC2:
- Upload code and venv
- add environment variable
- add cron job
- Create security groups with preferred name with description on the permissions like
Allows SSH for developers
- Add rule of SSH type and allow all IP addresses. Then create security group.
- Go to EC2, launch instances, Amazon aws and ubuntu are normally free tier. Select ubuntu
- For architecture, might want to select ARM if using ARM, else, select Intel x86
- Create key pair is recommended
- Click on "Actions", click on "Connect" and "Connect"
- Go into ubuntu terminal
sudo apt-get update
python --version
then installsudo apt-get install python3.10
- In local repo,
pip3 freeze > requirements.txt
then commit to github - Go to github repo -> code -> get https url to add the file in ubuntu
git clone https://github.com/chickensmitten/dydx-bot.git dydx_bot
- in ubuntu terminal enter into the
dydx_bot
folder and runpip3 install -r requirements.txt
touch .env
thensudo nano .env
, then put it all your env variables, then ctrl + x to exit, with y then enter.cd program
then runpython3 main.py
- When code is updated in local repo, in ubuntu cli, have to run
git reset --hard HEAD
then rungit pull origin --rebase
- refer to
crontab.guru
- How to read cron job
crontab -e
CRON item - Daily
0 12 * * * /bin/timeout -s 2 86330 python3 dydx_bot/program/main.py > output.txt 2>&1
CRON item - 5 Mins
*/5 * * * * /bin/timeout -s 2 290 python3 dydx_bot/program/main.py > output.txt 2>&1
crontab -l
- Then below is the anatomy to the command:
*/5 * * * * /bin/timeout
tells it when to run-s 2 290
tells it to kill it after 290 seconds- when it runs, tells it to execute
python3 dydx_bot/program/main.py
- then print output to
> output.txt
with2>&1
at the end. Refer to this link crontab -l
sees what cronjob is listed
- Setting up cronbjob in ubuntu
- in ubuntu cli, start with
crontab -e
to edit. - select nano editor
- then paste one of the cron items
- ctrl + x to save
- type
top
to see if the cronjob is running, you should see python3 running after your determined period
- in ubuntu cli, start with
- to close all positions manually, go to ubuntu cli, program directory, then run the main.py file to close all positions before shutting it down.
__pycache__
is a folder for compiled python 3 bytecodeconstants.py
contains all the constants. It also functions as on-off switch for specific functionsfunc_connections.py
contains connection to DYDX.func_private.py
contains execution functions that requires private keysfunc_public.py
contains execution functions that are publicfunc_utils.py
contains commonly shared functionsfunc_cointegration.py
contains code to caculate and store cointegration.calculate_zscore
,calculate_half_life
,calculate_cointegration
contains battle tested code, suitable for production.func_bot_agent.py
builds bot agents. Inopen_trades
, two orders will be opened because for the cointegration to work, you need two opposing trades to converge.func_open_positions.py
will open trading positionsfunc_messaging.py
will send messages to telegram
f-string
is a new string formatting mechanism known as Literal String Interpolation or more commonly as F-strings (because of the leading f character preceding the string literal). The idea behind f-strings is to make string interpolation simpler.
val = 'Geeks'
print(f"{val}for{val} is a portal for {val}.")
name = 'Tushar'
age = 23
print(f"Hello, My name is {name} and I'm {age} years old.")
- use
breakpoint()
to debug - testnet data is not as accurate as mainnet data. To do backtesting, use mainnet data without real trading.
- Order expiration less than 1 minute
Got the following error
Error closing all positions: DydxApiError(status_code=400, response={'errors': [{'msg': 'Order expiration cannot be less than 1 minute(s) in the future'}]})
. It is likely related to this code.expiration = datetime.fromisoformat(server_time.data["iso"].replace("Z", "")) + timedelta(seconds=70)
It is likely a GMT error, have to added moreseconds