Crypto Quant profits with Supertrend Indicator
Tags: Crytocurrency, Binance, Bitcoin, Python, Quant

The so-called “Supertrend” indicator is generating a lot of interest lately, but is it profitable to trade with? Let’s get to the bottom of this.

Tradingview and Supertrend indicator/strategy

Supertrend strategy and indicators have grown in attention on charting sites such as Tradingview.com, here the leading public library indicator of this genre has 23,332 ‘followers’.

And video blogs have taken to this indicator, for example “Part Time Larry” who recently built a trading bot using this trigger.

The indicator itself is rather sexy when graphed…

Math matters.

But is the profitable? For one thing the math involved is non-trivial.

The point of this piece is not the revisit the math involved but rather to test its profitability in crypto quant trading. Shall we proceed?

The devil is in the details.

One small but crucial point before we continue, notice that this indicator is a “trend following indicator”, this is very important for 2 reasons:

roughly 80% of the time markets are NOT trending

trending the profits of a trending strategy must be compared with the profits of simply holding (or shorting) the same asset. This is very different from judging profits themselves (i.e. remaining in cash).

Outline

In this piece we will do the following:

Borrow some Python code for the Supertrend indicator math (why re-invent the wheel)

Collect Binance historical data

Backtest the strategy against an exchange (eg. ‘BTCUSDT’) over a period of time and review results

Brute-force difference indicator parameters to see what ‘fits’ profitably

Binance setup

As usual to work with the Binance API you will need to setup a Binance account (free) and get API keys. There are instructions on their site on how to do this.

Next you’ll create a config.py in the directory with the crypto quant code. This will be used to import your key and secret.

API_KEY = ‘your API key’

API_SECRET = ‘your API secret’

Supertrend math

The Supertrend indicator user the True Range (TR) and Average True Range (ATR) calculations:

True Range (TR): A True Range of an asset is calculated by taking the greatest values of three price differences which are: market high minus marker low, market high minus previous market close, previous market close minus market low.

A True Range of an asset is calculated by taking the greatest values of three price differences which are: market high minus marker low, market high minus previous market close, previous market close minus market low. Average True Rance (ATR): Average True Range is a smoothed average of the previously calculated True Range values for a specified number of periods.

For a deep-dive on the Supertrend calculations see here.

We’ll use a simplified set of calculations courtesy of ‘Part Time Larry’ and his video blog on this topic. He goes into great detail on the math here so no need to rehash all of that. Watch his video.

These videos are a lot of work and hat’s off to these authors for publishing content on these topics. Please buy him a ☕, or a whiskey!

Here are our imports and client setup. Nothing special here.

import ccxt

import config

import schedule

import pandas as pd

pd.set_option(‘display.max_rows’, None) import warnings

warnings.filterwarnings(‘ignore’) import numpy as np

from datetime import datetime

import time

from binance.client import Client

import random client = Client(config.API_KEY, config.API_SECRET)

We’ll need data, let’s use 15minute tick data for Etherium (ETH) in a trending period on early 2021

candlesticks = client.get_historical_klines(“ETHUSDT”, Client.KLINE_INTERVAL_15MINUTE, “22 Jan, 2021”, “21 Feb, 2021”)

# trim each candle

for candle in candlesticks:

del candle[-6:] # only need the first few columns

Let’s see our data in a dataframe:

Backtesting!

Now we’ll create the backtest code. The double-indentation is a place-holder we’ll revisit later on.

The strategy is simple: when the Supertrend indicator reverses from “Sell” to “Buy”, we take a long position IF the most recent close value is above the 200 period EMA (Exponential Moving Average) value. Here is the essence of the buy trigger:

if not df['in_uptrend'][previous_row_index] and df['in_uptrend'][last_row_index]:

print("*changed to uptrend")

if not in_position:

if df['close'][last_row_index] < df['ema200'][last_row_index]:

print("below EMA")

return # do not buy here



print(' ema200', df['ema200'][last_row_index])

print(" BUY!", df['timestamp'][last_row_index], df['close'][last_row_index])

The strategy sells when close price falls below EMA.

if df[‘close’][previous_row_index] < df[‘ema200’][previous_row_index]: # closed below ema

if in_position:

print(‘ ema200’, df[‘ema200’][previous_row_index])

print(“ SELL!”, df[‘timestamp’][last_row_index], df[‘close’][last_row_index])

The rest of the code is mostly to keep track of our trading ledger.

Trending markets

So in early 2021 the market was trending strongly for ETH…

Here are our Supertrend backtest results for this period with default parameters for the Supertrend indicator:

*changed to uptrend

ema200 1336.3416667585598

BUY! 2021-01-26 23:00:00 1365.57

ema200 1337.542530741581

SELL! 2021-01-27 01:15:00 1327.7

*changed to uptrend

ema200 1293.9199247860201

BUY! 2021-01-28 13:45:00 1343.0

ema200 1314.384770497579

SELL! 2021-01-29 03:45:00 1320.82

*changed to uptrend

ema200 1329.4749563894045

BUY! 2021-02-01 21:45:00 1350.12

ema200 1576.8033662124164

SELL! 2021-02-04 15:15:00 1566.06

*changed to uptrend

ema200 1615.0917589663093

BUY! 2021-02-05 13:30:00 1685.92

ema200 1657.0474199540897

SELL! 2021-02-06 05:15:00 1662.5

*changed to uptrend

ema200 1622.6337214761083

BUY! 2021-02-08 06:15:00 1634.53

ema200 1748.050539834764

SELL! 2021-02-10 12:45:00 1745.0

*changed to uptrend

ema200 1740.2712583651808

BUY! 2021-02-11 10:30:00 1783.51

ema200 1762.7249257898284

SELL! 2021-02-12 04:15:00 1750.14

*changed to uptrend

ema200 1790.4360684700155

BUY! 2021-02-15 12:45:00 1805.14

ema200 1790.2882902636748

SELL! 2021-02-15 12:45:00 1805.14

*changed to uptrend

ema200 1781.059323775294

BUY! 2021-02-17 09:30:00 1817.25

ema200 1961.7364660509322

SELL! 2021-02-20 22:15:00 1931.86

Period: 20 arm: 6

profit % 2.733345624999929

2.7% profit in a month, great! No, terrible. We cannot compare this with a non-position during this period, instead it should be compared with being in the market and holding long.

Be careful how you evaluate backtesting profit results.

In fact to have held ETH during this period would have resulted in >80% [paper] profit

Non trending markets

So what about a non-trending period? This is the case approximately 80% of the time.

Markets are trending only ~20% of the time. The other 80% of the time they are ‘moving sideways’.

In that case the hold profits would be negligible (or negative), how did Supertrend strategy do there? Very easy for us to see that by simply changing the date period of our backtest.

We had negative profits in this non-trending period with the default parameters:

Period: 20 arm: 6

profit % -0.49146142499997947

Indeed June was a classic non-trending period for ETH, in fact the Supertrend strategy outperformed (including commissions) a holding loss but not by much and this is still a net loss!

A net loss is still a net loss! Would have been better off being OUT of the market.

A trading strategy is only worthwhile if significantly better than staying in or out of the market during the period in question.

Brute forcing parameters

But the default parameters are unlikely to be ideal here, as we did in our prior crypto quant exploration let’s brute-force our way to more profitable parameters for our Supertrend indicator.

You need only to modify the header of our backtesting code:

verbose = False for p in range(20,40):

for arm in range(4, 9):

#if True:

# if True:

# p = 20

# arm = 6

Now we will see the most profitable parameters for this non-trending period, and we can compare these with being in (or out) of the market. The Supertrend parameters are period (ticks to look back) and atr_multiplier (an amplifier, see the math details above).

Being OUT of the ETH market in June yielded $0, and being IN it also yielded approximately $0.

The best Supertend parameters for this period:

Period: 21 arm: 5

in position True 2117.18 balance $ 10140.623120000004

profit % 1.4062312000000383

Of the 100 brute-force combinations (20..40)x(4..9) only 20% of them were profitable, so 80% of all possible combinations (within these practical ranges) would not have been better than our alternative positions (in or out).

Strategy during DOWN trend market

What about in a down trending period of the market? 2 weeks in May 2021 were brutal for ETH, as shown below:

Our Supertrend strategy outperformed the market in this period but still posting marginal gains with 13% of the parameter values producing profit.

Period: 36 arm: 4

profit % 0.6344214999999894

This is clearly superior to being IN the market during this period (a loss of ~60%!) but over the longer term it performed relatively poorly.

Conclusion

Run the backtests for yourself and try different crypto coins. See if you can find a reliable trading strategy using the Supertrend indicator. On it’s own it is somewhat less than ‘Super’, right?