How to Build a Crypto Trading Algorithm With a Neural Network

What is Crypto Algorithmic Trading?

Crypto algorithmic trading, or crypto algo trading, is the use of automations to execute cryptocurrency trades to capitalize on market opportunities efficiently. Algorithms analyze market and historical data, blend statistical models and predefined criteria to trade cryptocurrencies.

Crypto algo trading may involve machine learning techniques, which trains the algorithm to evolve with the market and new data inputs. Some common machine learning techniques include decision trees, support vector machines and artificial neural networks (ANNs).

In today’s guide, we’ll be covering how to develop a crypto trading algorithm using an artificial neural network, using the Open High Low Close Volume (OHLCV) endpoint from the GeckoTerminal API.

Artificial Neural Networks in Crypto Algorithmic Trading

Artificial neural networks are computational models that simulate human decision-making, whereby it is capable of learning and adapting based on its environment and new data inputs. In the context of crypto trading, an ANN functions as a trader continuously monitoring asset prices 24/7, adapting trading positions based on historical and live data, among other metrics.

This can be achieved as ANNs comprise layers of interconnected nodes and process information through weighted connections – as such, it is able to learn and recognize complex data patterns.ANNs can therefore be employed for predictive analysis and decision-making in executing crypto trades. They analyze historical market data, identify patterns, and adjust trading strategies based on evolving market conditions.

Understanding Input, Hidden and Output Layers

It is important to understand how the ANN’s interconnected nodes are divided into three layers and its corresponding statistical representation, as these will be covered in scripts later on.

  1. Input layer – Independent variables
    The input layer, which corresponds to independent variables, serves as the entry point for data into the neural network.

  2. Hidden layer – Coefficient (weights)
    The hidden layer is associated with coefficients or weights. These weights are adjusted during the processing of input data to optimize the network’s performance.

  3. Output layer – Dependent variable
    The output layer is linked to the dependent variable, where the final result or prediction is produced, based on the information processed.

How it comes together: Inputs are fed into the model to be processed (i.e. summed). If the result of this summation is a value that exceeds the threshold, the node adjusts the weight matrices. The process of adjustment is known as ‘training’ a neural network, and the most common feedback method to perform these amendments is called backpropagation. Without this algorithm, we would have to identify the impact each weight has on the model’s error and update each individual coefficient. Instead, the error is fed back (back propagated) into the network, progressing one layer at a time until it is minimized in the model. This creates a trained ANN that can continue to analyze data.

Prerequisites: Python Libraries & Importing OHLC Data

Before we dive into the crypto trading algorithms, we will first need to import the following python libraries to extract our dataset from the GeckoTerminal API and build it into a legible dataframe. The pandas library is useful to visualize and manipulate our data in a legible dataframe. The numpy package is practical when dealing with arrays and different functions, and the matplotlib.pyplot library can be used to visualize our strategies results.

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

import requests
from datetime import datetime, timedelta

After this, we will import our data into our integrated development environment (IDE) – for this demo, I’ve used Visual Studio, and followed the same process outlined in my previous article on using Python to parse CoinGecko API.

We will now import Ethereum network data from the DAI-WETH pool, between the time period of August 23, 2023 to December 30, 2023.

# Import data from GeckoTerminal DEX API

network = 'eth'

pool_address = '0x60594a405d53811d3bc4766596efd80fd545a270' #DAI-WETH Pool

parameters = f'{network}/pools/{pool_address}'

specificity = f'{1}'

#URL with your specifications

url = f'{parameters}/ohlcv/day?aggregate={specificity}'

response = requests.get(url)

data = response.json()

#Turning into pandas dataframe, turning the date value into datetime format, making it the index

data = data['data']['attributes']['ohlcv_list']

df = pd.DataFrame(data, columns=['Date', 'Open', 'Close', 'High', 'Low', 'Volume'])

df['Date'] = pd.to_datetime(df['Date'], unit = 's')

df.set_index('Date', inplace = True)


This returns a clear and legible dataset that includes the DAI-WETH OHLC price on the UniSwap exchange, alongside its volume. Additionally, the ‘date’ each price was quoted is now the index.


100 rows × 5 columns

Specifically for developing artificial neural networks, we will also require the following two python libraries:

  1. Tensorflow: Tensorflow is a machine learning (ML) library that provides the core functionality for training neural networks. 
  2. Keras: Keras is a high-level python neural network API, which allows developers to exercise complex functionalities without having to deal with granularities. With pre-built functions and modules for common tasks, it enables developers to express their code in a more human-readable manner.

💡Pro-tip: Instead of manually defining the operations for each layer, Keras allows us to specify the design of our ANN in a clear and legible syntax. 

# Creating ANN Model


from tensorflow.keras.models import Sequential

from tensorflow.keras.layers import Dense, Dropout

layer_builder = Sequential()

The ‘Sequential’ class at the bottom of the above quote, initiated as ‘layer_builder’, is a part of the Keras API within Tensorflow. It allows us to add layers to our ANN one at a time, in a layer-by-layer fashion. The Dense layer is a fully connected layer that links each neuron in a layer to every neuron in the next layer. Lastly, the Dropout layer is used to prevent overfitting. During training, it randomly drops out a fraction of inputs, which helps prevent the network from overlying on certain nodes and encourages more robust learning. 

Training the ANN with Crypto Price Data

We will need to train our ANN in order to build our crypto algorithmic trading strategy. We’ll employ the following 3 basic technical analysis techniques to train our ANN:

  1. 3-month moving average (3MA)
  2. 10-month moving average (10MA)
  3. 15-month moving average (15MA)

The output value is binary (defined as 1 or 0), varying when the price rises or falls between periods (hence the new df[‘Price_Rise’] column). These measurements are stored in our dataframe as new columns. Our X data thus includes all rows and the 6th to N-1th column (i.e. ‘3MA’ to ‘15MA’). Our Y data is all the rows in the ‘Price_Rise’ column (which is the last column).

# Clean up and standardize data

df['3MA'] = df['Close'].shift(1).rolling(window = 3).mean()

df['10MA'] = df['Close'].shift(1).rolling(window = 10).mean()

df['15MA'] = df['Close'].shift(1).rolling(window = 15).mean()

df['Price_Rise'] = np.where(df['Close'].shift(-1) > df['Close'], 1, 0)

df = df.dropna()

X = df.iloc[:, 5:-1]

Y = df.iloc[:, -1]

The objective here is to split up our X data (i.e. 3MA, 10MA, and 15MA columns) and the Y dataset (i.e. price rise or fall) into training and testing sets.

The training set is used to arrive at the adjusted weights through backpropagation, while the test set is used to see how the model would perform on newly instituted data, which is our backtest. After using the test data set, we will employ several metrics to determine the efficiency of our model.

#Create X_train, X_test, Y_train, Y_test

split_data = int(len(df)*0.7)

X_train, X_test, Y_train, Y_test = X.iloc[:split_data, :], X.iloc[split_data:, :], Y.iloc[:split_data], Y.iloc[split_data:]

Standardizing the Dataset

Standardizing the dataset is a crucial step because it will ensure the mean of our inputs is 0 and the standard deviation is 1. This therefore confirms the data is unbiased, due to the varying scales of our inputs. 

💡Pro-tip: Neglecting this step of standardizing the dataset may result in the model “over-weighing” features with higher average returns, and is not recommended.

The StandardScaler class from sklearn facilitates this process, as it removes the mean and scales to unit (=1) variance. ‘Scaler’ is created as an instance of StandardScaler. The ‘fit_transform’ method fits to the training set data (X_train) and calculates its mean and standard deviation. The ‘transform’ method uses the mean and standard deviation calculated from the training set to standardize the test set (X_test). As the Y_train and Y_test are binary values—from price increasing or decreasing—we do not need to apply the same standardizing methods.

#Standardize Data

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()

X_train = scaler.fit_transform(X_train)

X_test = scaler.transform(X_test)

Adding Layers

We will now proceed with creating our linear stack of layers.

For our first densely connected layer, we create ‘128’ neurons for our hidden layer, which, as the name prescribes, is hidden.

The activation function ‘relu’ abbreviates Rectified Linear Unit. A popular choice for the activation function, ‘relu’ introduces non-linearity to the neural network. This causes the ANN to learn and represent more complex and non-linear relationships in the data.

Input_dim’ simply determines the dimensions of our inputs. We set this to be the exact shape of our X data by using the ‘shape()’ function in numpy.

After building several layers, we construct our output layer, which includes one node as we require one output.  Additionally, we use the ‘sigmoid’ function because it returns values between 0 and 1, as it represents the probability of the market moving favorably.

# First input layer

layer_builder.add(Dense(units = 128, kernel_initializer = 'uniform',

activation = 'relu', input_dim = X.shape[1]))

# Second input layer

layer_builder.add(Dense(units = 128, kernel_initializer = 'uniform'

, activation = 'relu'))

# Output layer

layer_builder.add(Dense(units = 1, kernel_initializer = 'uniform', activation = 'sigmoid'))

Improving Predictive Capabilities

Our goal is to improve the predictive capabilities of the ANN and minimize the difference (also known as ‘the residual’) between predicted and observed data. This is commonly done through a process called ‘gradient descent’. This method minimizes the ‘cost function’, which is a function of the cost of making a prediction using the neural network. It is a measure of how far off the predicted value, y^, is from the actual value, y. 

While there are many cost functions used in practice, we will aim to minimize the ‘mean_squared_error’ which is the squared sum of our residuals, divided by the number of observations:

  • SSR = Σᵢ(𝑦ᵢ − 𝑓(𝐱ᵢ))² for all observations 𝑖 = 1, …, 𝑛, where 𝑛 is the total number of observations. 

  • MSE = SSR / 𝑛

  • The measurement of our success (‘metrics’) is set to ‘accuracy’, which calculates how often our predictions were correct.

We will use ‘adam’ to optimize when compiling our layers, as it is computationally efficient and requires little memory usage. Adam is an optimization algorithm that we can use instead of the classical stochastic gradient descent procedure to update our neural network weights. It is straightforward to implement, making it a good starting point for building ANNs.

# Compile the layers

layer_builder.compile(optimizer = 'adam', loss = 'mean_squared_error', metrics = ['accuracy'])

We then fit our ANN to our training data, using a ‘batch size’ of 5, which is the number of data points used to compute the error before backpropagation, and 100 ‘epochs’, the number of times the training model will be used on the training set.

The keras ‘predict’ method generates output predictions given our input data ‘X_test’. We then obtain a binary variable by defining Y_pred as true when it is greater than 0.5, and false when it is less.

#Fit ANN to training set, Y_train, batch_size = 5, epochs = 100)

Y_pred = layer_builder.predict(X_test)

Y_pred = (Y_pred > 0.5)

#Store predictions back into dataframe

df['Y_Pred'] = np.NaN

df.iloc[(-len(Y_pred)):,-1:] = Y_pred.flatten()

#Fit ANN to training set, Y_train, batch_size = 5, epochs = 100)

Y_pred = layer_builder.predict(X_test)

Y_pred = (Y_pred > 0.5)

#Store predictions back into dataframe

df['Y_Pred'] = np.NaN

df.iloc[(-len(Y_pred)):,-1:] = Y_pred.flatten()

Visualizing the Returns

We can compute and visualize our price returns based on our crypto trading strategy, through the following code. This outputs a log-return visualization of our ANN, relative to the performance of simply holding Ethereum.

# Strategy Returns

df['Returns'] = 0

# Get the log returns

df['Returns'] = np.log(df['Close']/df['Close'].shift(1))

# Shift so that the returns are in line with the day they were achieved

df['Returns'] = df['Returns'].shift(-1)

df['Strategy Returns'] = 0

df['Strategy Returns'] = np.where(df['Y_Pred'] == True, df['Returns'], - df['Returns'])

df['Cumulative Market Returns'] = np.cumsum(df['Returns'])

df['Cumulative Strategy Returns'] = np.cumsum(df['Strategy Returns'])

# Visualize Returns


plt.plot(df['Cumulative Strategy Returns'], color = 'Blue', label = 'Strategy Returns')

plt.plot(df['Cumulative Market Returns'], color = 'Green', label = 'Market Returns')


plt.xticks(df.index[::5], rotation = 45)



As a result of the code, we see the following chart:

example of an ethereum price returns chart from crypto algo trading


Analyzing the data visualization, we can see that there are exorbitantly high returns in the first 15 days, followed by an interestingly negative relationship between the strategy and market returns share, over the next few months. This issue could stem from overfitting; excessive reliance on the training data set may lead to initially high returns. We should therefore acquire more data for the training and testing sets – as with all machine learning models, this crypto trading algorithm has the potential to be improved with more data points and larger data sizes, which would enhance the training and development of the ANN. 

To wrap up, in this demo we have created a crypto trading algorithm capable of forward feeding and back-propagating, creating predictions off 3-, 10- and 15-day moving averages. These predictions are then back-tested against monthly price data, allowing us to compare it to the performance of simply holding Ethereum.

For Advanced Traders: Build Your Own Crypto Trading Algorithm with Richer Crypto Data

GeckoTerminal’s DEX data API is currently publicly accessible in beta and will soon be integrated into CoinGecko API. Some of the most popular endpoints include:

  • OHLCV data, as covered in this guide
  • Trending liquidity pools on a network
  • Top liquidity pools for a token, and more!

To avoid getting rate limited, advanced traders can consider subscribing to our Analyst API plan and will be extended a GeckoTerminal API key upon request.

benefits of subscribing to CoinGecko API | GeckoTerminal API

Interested in more API or trading-related resources? This extensive DEX Data API guide will walk you through how to get market data for a liquidity pool, access on-chain data for DEX-traded tokens and more!

How to Get Decentralized Exchange Data with DEX Data API

What is a DEX Aggregator?

A decentralized exchange (DEX) aggregator is a platform that consolidates liquidity pools across multiple DEXs, so that traders can find the best available prices and pools to optimize their DeFi trades. DEX aggregators optimally match user swap orders from multiple DEXs, and help traders reach pools of deep liquidity, similar to how Google Maps finds the optimal route for drivers.

Having sufficient liquidity in a trading pool enables users to execute trades without fear of slippage. An exchange or marketplace becomes more efficient with higher liquidity. When liquidity is low, trader orders stall, sellers struggle to match buyers, and prices swing. During this time, the expected swap price diverges from the actual swap price, causing slippage. With cryptocurrencies’ inherent volatility, liquidity pools can be unpredictable. DEX aggregators therefore are used by traders to find the most liquidated pools, and swiftly execute a swap order from a single dashboard.

GeckoTerminal DEX Aggregator

GeckoTerminal is a popular DEX aggregator that tracks tokens trading on decentralized exchanges (DEXs), supplying information on price, trading volume, liquidity and more. It currently tracks cryptocurrencies across more than 100 chains and 700 decentralized exchanges (DEX), including Uniswap, Sushi, Pancakeswap, Curve, Balancer and more.

In today’s guide, we’ll explore how to leverage GeckoTerminal DEX data API to fetch token trade information through its RESTful JSON endpoints. With just one API call, developers and traders can fetch price, market data and historical OHLC charts. The endpoints we’ll be covering in this guide are mapped on the GeckoTerminal front-end, accordingly:

Let’s dive in!

How to Access On-Chain Data for Tokens Traded on DEXs

Access on-chain data for DEX-traded tokens through the GeckoTerminal DEX data API. Depending on what data you’re looking for, you can specify a contract address for specific pools, retrieve top or latest pools on a network, or get the latest pools across all networks.

More specifically, you can drill down and get data for:

  • A specific pool or multiple pools on a network, by specifying a given contract address in the query param.
  • The top 20 or latest 20 pools on a network, for specific networks.
  • The latest 20 pools across all networks.
  • The top 20 pools on a given network’s DEX.

Should we want to find the list of available networks from which we can pull data, we can use the /networks endpoints. This retrieves a full list of supported networks and their ids. Then, in narrowing our search, we can pull pool specific data with the /networks/{network}/tokens/{token_address}/pools endpoint to get a specific pool on a network.

💡 Pro-tip: If you are unsure how to set up your IDE, refer to this Python API Guide.

This endpoint would appear as:

        import requests
        url = ''
        parameters = {'accept': 'application/json'}
        response = requests.get(url, headers=parameters)
        if response.status_code == 200:
                # Successful response
                        data = response.json()
                        print(f"Request failed with status code: {response.status_code}")

Use the requests library to access the /networks/{network}/tokens/{token_address}/pools endpoint. We’ve included the ‘eth’ network in the request parameters, and the specific pool address ‘0x60594a405d53811d3bc4766596efd80fd545a270’. 

For error handling, should the request be unsuccessful, we print ‘Request failed with status code: {response.status_code}’. We can vary both parameters to specify other DEXs, using the vast amount of data housed by GeckoTerminal. To find other pool addresses on the Ethereum mainnet, simply go to GeckoTerminal, select a desired pool, and locate the address in the bottom left. 

Locate the pool address on GeckoTerminal - CoinGecko DEX Data API

The output from this endpoint includes trading volume, on-chain transactions for a specific token, along with buy and sell transactions.

How to Find the Liquidity Pool of a Coin

Use the /search/pools endpoint in GeckoTerminal’s DEX data API to find the liquidity pool of a coin, searching by pool address, token address or symbol. This returns a multitude of pools including the queried data. For example, to look for pools on the Ethereum network, our query would simply be ‘ETH’ and we would replace our url with the new request url:

        url = ''

This endpoint is extremely useful for crypto projects and developers as it segregates DEXs with immense liquidity, and locates market efficiency. Pools with high liquidity experience price stability and enable seamless transactions, resulting in more investor confidence, which. perpetuates into more developers establishing pools on the same DEX. Conversely, low liquidity can cause unsettling and unpredictable fluctuations for newly established projects. The request outputs the following JSON text:

        {'data': [{'id': 'eth_0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640',
                'type': 'pool',
                'attributes': {'base_token_price_usd': '1827.82349971122',
                'base_token_price_native_currency': '1.0',
                'quote_token_price_usd': '0.997985290842797',
                'quote_token_price_native_currency': '0.000545991457703024',
                'base_token_price_quote_token': '1831.53',
                'quote_token_price_base_token': '0.00054599',
                'address': '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640',
                'name': 'WETH / USDC 0.05%',
                'pool_created_at': None,
                'fdv_usd': '5911367354',
                'market_cap_usd': None,
                'price_change_percentage': {'h1': '-0.02', 'h24': '1.31'},
                'transactions': {'h1': {'buys': 76, 'sells': 88},
                'h24': {'buys': 2649, 'sells': 2746}},
                'volume_usd': {'h24': '366293316.2813256561009998'},
                'reserve_in_usd': '195144837.9232'},
               'relationships': {'base_token': {'data': {'id': 'eth_0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
                'type': 'token'}},
                'quote_token': {'data': {'id': 'eth_0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
               'type': 'token'}},
               'dex': {'data': {'id': 'uniswap_v3', 'type': 'dex'}}}},

And thereafter goes to show the next pool’s data, and so on.

        {'id': 'eth_0x4585fe77225b41b697c938b018e2ac67ac5a20c0', ….

How to Find Liquidity Pools on a Network

To find multiple liquidity pools on the network, use the /networks/{network}/pools/multi/{address} endpoint in GeckoTerminal’s DEX data API. For example, to pull data on all liquidity pools on Uniswap V3, simply include all pools’ addresses. The addresses will be separated by commas, like:

               The url, therefore, becomes:
               pool1 = '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640'
               pool2 = '0x11950d141ecb863f01007add7d1a342041227b58'
               pool3 = '0x60594a405d53811d3bc4766596efd80fd545a270'

               # Concatenate the pool addresses as a comma-separated string
               pools = f'{pool1},{pool2},{pool3}'

               url = f'{pools}'

By doing so, we are able to get data from the DAI/WETH, WETH/USDC, and PEPE/WETH pools simultaneously. Now our output includes data concerning specific pools:

               First: WETH/USDC Pool:
               {'data': [{'id': 'eth_0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640',
                      'type': 'pool',
                   'attributes': {'base_token_price_usd': '1828.45810660423',
                   'base_token_price_native_currency': '1.0',
                   'quote_token_price_usd': '0.997676722335158',
                   'quote_token_price_native_currency': '0.000545627354443188',
                   'base_token_price_quote_token': '1832.75',
                   'quote_token_price_base_token': '0.00054563',
                   'address': '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640',
                   'name': 'WETH / USDC 0.05%',
                    'pool_created_at': None,
                    'fdv_usd': '5913419738',
                 'market_cap_usd': None,
                 'price_change_percentage': {'h1': '0.03', 'h24': '1.31'},
                 'transactions': {'h1': {'buys': 61, 'sells': 87},
                 'h24': {'buys': 2645, 'sells': 2747}},
                  'volume_usd': {'h24': '366072244.7173006110111998'},
                  'reserve_in_usd': '195158456.8977'},
                   'relationships': {'base_token': {'data': {'id': 'eth_0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
                  'type': 'token'}},
                   'quote_token': {'data': {'id': 'eth_0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
                   'type': 'token'}},
                   'dex': {'data': {'id': 'uniswap_v3', 'type': 'dex'}}}},

After which, we see the data for the PEPE/WETH pool, and so on.

                       {'id': 'eth_0x11950d141ecb863f01007add7d1a342041227b58', ….

How to Get Market Data for a Liquidity Pool

Retrieve market data for a DEX liquidity pool by using the GeckoTerminal DEX data API endpoint /networks/{network}/pools/{address}. You can specify the query param to obtain data for the  top 20 pools on a network. 

For instance, to get market data for liquidity pools with the highest 24H trading volume on the Ethereum Mainnet we will use ‘eth’ for {network} and use the ‘volume_usd’ query param. This adjusts the API call to search for the top 20 pools befitting this criterion – an incredibly useful endpoint for developers! Additionally, we can improve the legibility of the JSON request by using a Pandas Dataframe:

        Import pandas as pd
        url = ''

        response = requests.get(url)
        data = response.json()

        # Extract the 'data' field from the JSON response which includes all of our desired attributes
        data_list = data['data'] 

        # Initialize empty lists to store the data we select to extract
        id_list = []
        type_list = []
        base_token_price_usd_list = []
        volume_usd_list = []
        # Add more empty lists for other attributes

        # Iterate through each data point in the created list to extract certain attributes
        for data_point in data_list:
                attributes = data_point['attributes']


        # Extract 'volume_usd' without '{', 'h24', and '}'
                volume_usd = attributes['volume_usd']['h24']
                volume_usd = volume_usd.replace('{', '').replace('}', '').replace('h24: ', '')
                # Append more attributes to their respective lists if you want

        # Create a DataFrame from the lists created
        df = pd.DataFrame({
                'id': id_list,
                'type': type_list,
                'base_token_price_usd': base_token_price_usd_list,
                '24_hour_volume': volume_usd_list,
               # Add more columns for other attributes


        # Now, 'df' contains the data in separate columns!

This creates an easily legible DataFrame that we can manipulate as we look for certain data points:

easily legible DataFrame

How to Get OHLCV Candlestick Data for DEXs

The easiest way to get OHLCV candlestick data for DEXs is to use the GeckoTerminal DEX data API endpoint /networks/{network}/pools/{pool_address}/ohlcv/{timeframe}, which pulls OHLCV data for desired pools for up to 6 months.

The data granularity of this endpoint covers daily, hourly and minutely data on differing aggregations. The resulting JSON response is incredibly difficult to decipher, prompting the use of pandas dataframe, like so:

        #Specifying network, desired pool, and time granularity
        network = 'eth'
        pool_address = '0x60594a405d53811d3bc4766596efd80fd545a270' #DAI-WETH Pool
        parameters = f'{network}/pools/{pool_address}'
        specificity = f'{1}'

        #URL with your specifications
        url = f'{parameters}/ohlcv/day?aggregate={specificity}' 

        response = requests.get(url)
        data = response.json()

        #Turning into pandas dataframe, turning the date value into datetime format, making it the index
        data = data['data']['attributes']['ohlcv_list']

        df = pd.DataFrame(data, columns=['Date', 'Open', 'Close', 'High', 'Low', 'Volume'])
        df['Date'] = pd.to_datetime(df['Date'], unit = 'ms')
        df.set_index('Date', inplace = True)

We can plot candlestick charts using matplotlibs.pyplot to visualize our newfound data. This would look like:

        import matplotlib.pyplot as plt

        plt.figure(figsize = (12,6))
        plt.plot(df['Open'], label = 'Open', alpha=0.5)
        plt.plot(df['Close'], label = 'CLose', alpha=0.5)
        plt.plot(df['High'], label = 'High', alpha=0.5)
        plt.plot(df['Low'], label ='Low', alpha=0.5)
        plt.title('OHLC Data')
        plt.xticks(rotation=45)  # Rotate x-axis labels for better readability

Now we can see the variation in price over the past few months in this one pool:

Build DeFi Apps with GeckoTerminal DEX Data API

DEX aggregators play a crucial role in crypto by offering a unified and consolidated platform for DeFi projects and traders to access liquidity pool data across decentralized exchanges. This allows users to optimize swap fees, reduce slippage, and identify fleeting or strong liquidity – and by extension, impacting investor confidence. New projects can leverage this data to influence L1 or L2 deployment decisions, forecasting how user sentiment and participation in a DEX will change overtime. DeFi Apps can utilize GeckoTerminal to access innumerable DEX data from the easily usable API.

GeckoTerminal’s DEX data API is currently in beta and will soon be integrated into CoinGecko API. Web3 developers and traders who want access to more crypto market data and avoid getting rate limited, may consider subscribing to our Analyst API plan. The CoinGecko API currently has 50+ endpoints, tracks 10,000+ coins across 900+ exchanges and 3,000+ NFT collections serving billions of API calls each month.

If you require a custom solution, fill in the form below to get in touch with our API sales team:

Disclaimer: This guide is for illustrative and informational purposes only, and does not constitute professional or financial advice. Always do your own research and be careful when putting your money into any crypto or financial asset.

Looking for further API resources? Check out this guide on 5 popular crypto trading strategies and how you can backtest using historical crypto data.

How to Conduct a Crypto Sentiment Analysis with Python

What is Crypto Sentiment Analysis? (Opinion Mining)

Crypto sentiment analysis, or opinion mining, involves evaluating public perceptions of cryptocurrencies through monitoring social media and news sentiment. It helps traders gauge market sentiment and understand how other investors are feeling about a particular coin or category. In the case of crypto, Twitter/X is the optimal platform for gauging social sentiment.

While the process typically involves machine learning and artificial intelligence to mine and process the data, we’ll be demonstrating how to conduct a crypto sentiment analysis with Twitter/X and CoinGecko API.

How to Develop a Sentiment-Based Crypto Trading Strategy

To conduct a market sentiment-based crypto trading strategy, follow the 4 steps outlined below:

  1. Generate Twitter/X and CoinGecko API keys.
  2. Open an IDE/code editor (like a Jupyter notebook), download Python and pip.
  3. Install Python packages that processes market sentiment data.
  4. Extract sentiment, synthesize the data set and generate polarity scores (sentiment scores).
  5. Develop crypto trading signals based on sentiment scores.

Essentially by synthetisizing crypto market sentiment data, you can utilize insights to inform potential entry and exit positions. Let’s dive in!

Generate Twitter and CoinGecko API Keys

Twitter/X API

The crypto community has nestled into Twitter/X, also known as ‘crypto Twitter’, where news often break faster than traditional media outlets. Given the volatile nature of crypto tied to perception shifts, monitoring market sentiment on Twitter/X can offer traders a valuable edge. On this basis, we will be developing a crypto trading strategy based on Twitter/X sentiment analysis, using the Twitter/X API.

To gain access to the Twitter/X API you will first need to create  developer account. After which, you will receive an API key, an API secret key, a Bearer token, an access token, and an access token secret.

As of February 9, 2023, Twitter/X launched their Basic and Pro plans. In this guide, we’ll be leveraging the ‘Search Tweets‘ endpoint found under their Basic plan. The Basic plan also allows you to fetch data for tweet counts and retweets, which can come in handy when analyzing sentiment.

CoinGecko API

Every CoinGecko user can generate 1 API key by signing up for the Demo Plan, and will enjoy a stable rate limit of 30 calls per minute and a monthly cap of 10,000 calls. We’ll be using the Open High Low Close (OHLC) /coins/{id}/ohlc endpoint for this guide, retrieving coins’ OHLC data where data granularity is automatic for Demo API users:

  • 30-minute data granularity for 1-2 days away from now
  • 4-hourly data for 3-30 days away from now
  • 4-daily data for >31 days away from now


Download Python and Pip

Before getting started, do also ensure that you have Python and pip downloaded. Python can be downloaded here, and you may follow these steps for pip installation:

  1. Press command + spacebar and type in ‘Terminal’
  2. Check your Python version by typing python3 --version
  3. Download pip by typing in: curl -o
  4. Then type: python3

Install Python Packages to Process Sentiment Data

We recommend using the following 3 Python packages to effectively process the market sentiment data:

  1. ReGex Python Package: To clean-up the tweets we search for, we will need the regular expression (regex) Python package. This will help wash the tweets of the sprawling characters attached to each call.

  2. Tweepy Package: The easiest and most convenient way to access the Twitter/X API through Python, is through the open-sourced Tweepy package. The Tweepy package will give us a convenient way to access the Twitter API through Python. It includes an assortment of methods that resemble Twitter/X’s or X’s, API endpoints, providing a variety of implementation aid and detail.

  3. NLTK Vader Lexicon Package: Text analysis is an integral part of a number of industries, and one of its most important subsections is sentiment analysis. The Natural Language Toolkit (NLTK) is a ubiquitous library in Python programming for natural language processing (NLP). Advances in NLP have made it possible to perform sentiment analysis on large volumes of data, accompanying our construction of a sentiment-based strategy. There are several ways to perform NLP, such as lexicon-based analysis, machine learning, or pre-trained transformer-based deep learning. For this strategy we will be utilizing a lexicon-based analysis.

    The NLTK Vader Sentiment Analyzer uses a set of predefined rules to determine the sentiment of a text. Hence, we can specify the degree of positive or negative polarity required in our compound score, to perform a trade.

Use pip to install the above packages, still in the terminal:

       pip install tweepy
       pip install nltk‘vader_lexicon’)

Next, access jupyter notebook, and import the required packages:

       import pandas as pd
       import tweepy
       import re
       from nltk.sentiment.vader import SentimentIntensityAnalyzer

Conduct a Crypto Sentiment Analysis using Python

Now that we have installed Python and Pip and imported the required packages, it’s time to finally collect Twitter/X sentiment data.

Apply our newly acquired Twitter/X API credentials in Jupyter notebook:

       API_key = ‘********************’
       API_secret = ‘***********************’
       Access_token = ‘*********************’
       Access_secret = ‘***********************’

Simply replace the stars with your personal developer details. We will then use Tweepy to authenticate, using our credentials, and access the API:

       # From Tweepy docs
       auth = tweepy.OAuthHandler(API_key, API_secret)
       auth.set_access_token(Access_token, Access_secret)
       api = tweepy.API(auth)

We can then define our parameters and create a function using regex to clean up our pulled tweets. We will pull tweets containing $ETHUSD as an example:

       # Define Variables
       count = 10
       coinid = ‘$ETHUSD’

       #Clean up collected tweets with regex
       def nice_tweet(tweet):
              return' '.join(re.sub("(@[A-Za-z0-9]+)|([^0-9A-Za-z t])|(w+://S+)", " ", tweet).split()) 

To apply the function on actual tweets, let’s next create a ‘get_tweets’ method. Starting with an empty set to contain our 10 tweets, we’ll then sift through it to determine if the tweet is already included, before leaving a lean list of recent tweets involving ‘$ETHUSD’:

       def get_tweets(coinid, count):
              tweets = set()
              collected_tweets = = coinid, count = count)
              for tweet in collected_tweets:
                     cleaned_tweet = clean_tweet(tweet.text)
                     if cleaned_tweet not in tweets:
              return tweets

After we have fetched data on the $ETHUSD tweets, let’s run them through a sentiment analyzer, to determine their polarity (i.e. how positive/negative/neutral they are).

       def polarity(tweets):
              scores = []
              for tweet in tweets:
                     score = SentimentIntensityAnalyzer().polarity_scores(tweet)
                     score[‘tweet’] = tweet
              return scores

With that, we have pulled tweets from the Twitter/X API, cleaned the data, and determined their sentiment score through the NLTK Vader Sentiment Intensity Analyzer.

Develop Crypto Trading Signals Based on Sentiment Scores

Let’s now pull in crypto price data using the CoinGecko API, to combine them with our previous sentiment analysis and create trades. Use the following code to import Ethereum (ETH)’s Open High Low Close (OHLC) data for the last 30 days:

       from pycoingecko import CoinGeckoAPI
       cg = CoinGeckoAPI()

       ohlc = cg.get_coin_ohlc_by_id(
          id="ethereum", vs_currency="usd", days="30"

       df = pd.DataFrame(ohlc)
       df.columns = ["date", "open", "high", "low", "close"]
       df["date"] = pd.to_datetime(df["date"], unit="ms")
       df.set_index('date', inplace=True)

With this data and our polarity scores we can construct a simple signal to enter long and short positions with ETH prices. The compound score produced from our polarity function combines negative, positive, and neutral scores, giving us a single consolidated value. Rules can be varied, and for a simple trading signal we can follow this logic:

  • If the compound score is greater than 0.06, buy 1 ETH at the spot price
  • If the compound score is below 0.04, sell our 1 ETH position
  • Otherwise, no action

This translates to the following python script:

       def Signal(scores):
          LongPrice = []
          ShortPrice = []
          Signal = 0
          SignalList = []
          tweets = get_tweets(coinid, count)
          scores = polarity(tweets)

          #Getting compound score
          df = pd.DataFrame.from_records(scores)
          mean = df.mean()
          compound_score = mean[‘compound’]

          for i in range(len(df)):
               if (compound_score> 0.06 and Signal != 1
               Signal = 1
            elif (compound_score <= 0.04 and Signal == 1
               Signal = -1
               if Signal == -1:
               Signal = 0


          return SignalList, LongPrice, ShortPrice

With that, we have created a signal using our pulled CoinGecko $ETHUSD price data and polarity scores.

💡 Pro-tip: Be sure to check out Shashank Vemuri’s Medium blog, covering articles concerning the Tweepy and NLTK libraries.

For Professional Traders: Unlock Daily OHLC Data

Incorporating sentiment analysis into crypto trading strategies offers valuable market insights for informed decision-making. Using the Tweepy and NLTK Vader Sentiment Analyzer packages, traders can extract sentiment data from platforms like crypto Twitter/X, generating polarity or sentiment scores. Trading signals can then be developed based on sentiment scores and coin OHLC data from CoinGecko API. However, it’s important to note that results may vary based on individual parameters and market circumstances.

Professional traders looking to maximize the OHLC endpoint with a daily candle interval data granularity may consider subscribing to our Analyst API plan. This is exclusively available to paid subscribers, along with endpoints like:

  • /coins/list/new – get the latest 200 coins as listed on CoinGecko
  • /coins/top_gainers_losers – get the top 30 coins with largest price gain and loss, within a specific time duration
  • /exchange/{exchange_id}/volume_chart/range – get the historical volume data of an exchange for a specified date range

If you require a custom solution, fill in the form below to get in touch with our API sales team:


Disclaimer: This guide is for illustrative and informational purposes only, and does not constitute professional or financial advice. Always do your own research and be careful when putting your money into any crypto or financial asset.

How to Use Python to Query CoinGecko API

Python is one of the most ubiquitous, general-purpose programming languages today, and can be used to create a wide range of varying programs. In this guide, we’ll explore how to leverage Python to query CoinGecko API, and retrieve coin price data from the various endpoints:

  • Crypto price /simple/price
  • OHLC /coins/{id}/ohlc
  • Trending /search/trending
  • NFTs /nft/{id}

Let’s dive in!

Navigating CoinGecko API Documentation & Setting Up

CoinGecko API has a total of 50+ endpoints, of which 30+ are publicly accessible via our Demo API plan. This provides access to independently aggregated crypto data, such as historical and live prices, volume, exchange volumes, contract data, and NFT floor prices – all comprehensively outlined in their API documentation.

If any endpoint is of particular interest to you, simply click the down arrow next to it to reveal the potential parameters associated with that function.

The /simple/price endpoint effectively illustrates the functionality of the API. We can input various parameters concerning the coin of interest, the currency to compare it with, whether to include volume/market cap/etc. in our output, and the precision of each price value.

Once we hit ‘execute’, we get a cURL response as follows:

cURL is a command-line tool and library for making HTTP requests. This code language is used to make a GET request to the CoinGecko API, retrieving information about Ethereum (ETH)’s price vs USD. You can perform the same HTTP GET request using Python!

Open a Jupyter notebook, PyCharm, or another favored IDE, by simply typing in the name into the Mac command line ‘Terminal’, such as ‘Jupyter Notebook’. Prior to this, ensure you have Python downloaded, and pip, which is a Python package manager. This process can be mirrored on Windows.

Once you are on your Python script, we will need to import the requests library, which is a commonly used tool for making HTTP requests in Python. By using it, we can facilitate a similar process to that shown before.

import requests
url = ‘
params = {  
         ‘ids’: ‘ethereum’,
         ‘vs_currencies’: ‘USD’

response = requests.get(url, params = params)

In the code example below, 200 refers to a status code, indicating a successful HTTP request. Other status codes might be more familiar, such as code 404 (Not Found), 500 (Internal Server Error), 401 (Unauthorized), and so on. 

To retrieve simple price data, we’d then write:

if response.status_code == 200:
         data = response.json()
         Ethereum_price = data[‘ethereum’][‘usd’]
         print(f’The price of Ethereum in USD is ${Ethereum_price}’)
         print(‘Failed to retrieve data from the API’)

💡 Pro-tip: Make sure you have the ‘requests’ library downloaded in your Python environment. You can install it using pip in your Terminal:

         pip install requests

How to Get Coin’s OHLC Data with an API

To pull Open, High, Low, Close (OHLC) data for a cryptocurrency, use the OHLC endpoint /coins/{id}/ohlc in CoinGecko API. The data pulled – the candle’s body – has an automatic data granularity for Demo plan users:

  • 1 – 2 days: 30 minutes
  • 3 – 30 days: 4 hours
  • 31 days and beyond: 4 days

Meanwhile, paid API users can enjoy the exclusive daily candle interval parameter, using the ‘interval=daily‘ parameter in your request. The ‘daily‘ interval is available for 1, 7, 14, 30, 90 and 180 days, updated on a 30 minute frequency.

We can utilize the pycoingecko library to pull from this endpoint as it initiates an API request distinct from the one made to the /simple/price endpoint and serves a unique purpose. 

The /coins/{id}/ohlc endpoint can utilize the cg.get_coin_ohlc_by_id method from the pycoingecko library. This method is specifically created to fetch OHLC price data for a given cryptocurrency, in this case Ethereum, over a specified number of days. As it is making a request to a different endpoint, we can use the pycoingecko library to facilitate this:

         from pycoingecko import CoinGeckoAPI
         cg = CoinGeckoAPI()
         ohlc = cg.get_coin_ohlc_by_id(id = “ethereum”, vs_currency = “usd”, days = “30”)
         print (ohlc)

Of course, the print method will, as designed, display JSON data returned by the API. 

In order to make it more palatable, we can utilize pandas DataFrames.

How to Turn Requests into Readable pandas DataFrame

To convert text data to a human-readable pandas DataFrame, first convert the response to a string and then extract key-value pairs as columns.

In the code below, the OHLC variable stores the JSON response data, which is essentially a list of OHLC data points. Each data point is represented as a dictionary. When you create a pandas DataFrame using pd.DataFrame(ohlc), pandas interprets each dictionary within the list as a row in the Dataframe, and extracts the key-value pairs as columns.

         import pandas as pd
         df = pd.DataFrame(ohlc)
As the output is still not properly legible, we will make a few further adjustments: labeling columns, converting the date to a pandas datetime object, and setting the date as the index.
         df.columns = [“date”, “open”, “high”, “low”, “close”]

💡Pro-tip: To reconfirm that these data points are accurate, we can return to the CoinGecko website and compare the information.

Let’s continue readjusting our DataFrame:

         df[“date”] = pd.to_datetime(df[“date”], unit = “ms”)
         df.set_index(‘date’, inplace = True)

The DataFrame is now complete, featuring OHLC data and accurate datetime stamps, which are all in accordance with the 4-hour automatic granularity for 30 day price history:

How to Fetch Cryptocurrency Price Data 

We can obtain all coins market data by using the /coins/markets CoinGecko API endpoint. The parameters allow us to specify:

  • The currency to compare it to (vs_currency – typically ‘usd’)
  • The ids of specific coins (if we want to narrow down our list)
  • The order
  • The number per page
  • The page number, etc.

Similarly to the /coins/{id}/ohlc endpoint, we can use the pycoingecko library, instead of the requests library (like we did with /simple/price).

parameters = {
         'vs_currency': 'usd',
         'order': 'market_cap_desc',
         'per_page': 100,
         'page': 1,
         'sparkline': False,
         'locale': 'en'
coin_market_data = cg.get_coins_markets(**parameters)

However, to avoid getting indigestible data, turn the output into a pandas DataFrame as we did before.

To overcome the undue number of columns, we can next employ pandas index slicing!

         df = pd.DataFrame(coin_market_data)
         df = df.drop(['id', 'symbol', 'image', 'high_24h', 'low_24h', 'price_change_24h', 'price_change_percentage_24h',
         'market_cap_change_24h','market_cap_change_percentage_24h', 'fully_diluted_valuation', 'ath_date', 'ath_change_percentage',
         'atl_change_percentage', 'atl_date', 'roi'],  axis = 1)

Continue to readjust the desired area of the DataFrame, dropping columns through ‘df.drop’, whittling it down to the state we want it in:

How to Get Trending Crypto Price Data via Python

Using the “requests” library, we will navigate to the /search/trending endpoint to retrieve data on the top 7 trending coins on CoinGecko, as searched by users in the last 24 hours, with the most popular being ordered first.

url = ‘’
headers = {
         ‘accept’: ‘application/json’
response = requests.get(url, headers = headers)

The ‘accept’ header here is set to ‘application/json’, indicating the client – your Python script – prefers to receive the response in JSON format, which is informed by the ‘header’ to the server. For example, if you prefer to receive the response in XML format, you can set the ‘accept’ header to ‘application/xml’. This can be mirrored for other formats like CSV, HTML, or other media (MIME) types.

Next, write a similar ‘if’ statement, depending on if the request was successful or not. However, as we cannot simply mold this request into a DataFrame, because the resultant arrays we are trying to convert have differing lengths.

Therefore, we need to initialize an empty list where we will store the data for each coin, create a for loop that iterates through the ‘coins’ section of our JSON data, defaulting to an empty list ([]) if the ‘coins’ does not exist. Thereafter, we’ll extract the ‘item’ dictionary for each coin, create an empty dictionary if it does not exist, and finally append a dictionary to our list for each coin. The dictionary then contains information regarding the coins ‘id’, ‘name’, ‘symbol’, ‘market_cap_rank’, and ‘score’. The ‘get’ method is used for each key to extract the corresponding value from the dictionary, assigning a default value ‘’ for empty strings or 0 for integers.

if response.status_code == 200:
         # Convert the JSON response to a Python dictionary
         data = response.json()

         # Extract relevant fields from the JSON data (coins section)
         coin_data = []
         for coin in data.get('coins', []):
         coin_item = coin.get('item', {})
         'id': coin_item.get('id', ''),
         'name': coin_item.get('name', ''),
         'symbol': coin_item.get('symbol', ''),
         'market_cap_rank': coin_item.get('market_cap_rank', 0),
         'score': coin_item.get('score', 0)

         # Create a DataFrame from the extracted data
         df = pd.DataFrame(coin_data)

         # Display the DataFrame


         print(f"API request failed with status code: {response.status_code}")

 Our constructed DataFrame should appear as follows:

How to Get NFT Price Data with API

The easiest way to get NFT price data is through the /nft/list and /nft/{id} CoinGecko API endpoints, where you can pull a list of NFT collections and respective data pertaining to that NFT collection.

This can be done with the following Python script:

# Request for list of NFTs
nfts_list = cg.get_nfts_list(per_page=100, page=1)
# View what NFTs are covered and choose one (e.g. Squiggly)
url = ''
response = requests.get(url)
if response.status_code == 200:
         squiggly_nft = response.json()
         synthesized_data = {
         'id': squiggly_nft['id'],
         'name': squiggly_nft['name'],
         'symbol': squiggly_nft['symbol'],
         'image': squiggly_nft['image'],
         'description': squiggly_nft['description'],
         'native_currency': squiggly_nft['native_currency'],
         'floor_price': squiggly_nft['floor_price'],
         'market_cap': squiggly_nft['market_cap'],
         'volume_24h': squiggly_nft['volume_24h']

         # Create a DataFrame from the synthesized data
         df = pd.DataFrame([synthesized_data])
         df = df.drop(['symbol', 'image', 'id'], axis = 1)


         print("Request failed with status code:", response.status_code)

Essentially, this requests for a list of NFT collections, allowing us to sift through and pick from the available JSON data. Once selected, we append the NFT name to the end of the url (i.e. ‘’). Once the response status is successful, simply construct a new flattened data dictionary, selecting desired data and pulling it from the JSON text, before creating a dataframe around our synthesized data!

Unlock Exclusive API Endpoints

Evidently from the above, CoinGecko API provides access to coin prices, NFT activity, trending coins, derivatives, and many others.  Although the data returned is in JSON format, one can easily employ the pandas data science library to convert the response into an easily legible structure. 

To unlock exclusive API endpoints and historical prices, developers, traders and project founders can consider subscribing to our Analyst API plan. The CoinGecko API currently has 50+ endpoints, tracks 10,000+ coins across 800+ exchanges and 3,000+ NFT collections serving billions of API calls each month. If you require a custom solution, fill in the form below to get in touch with our API sales team:

Looking for further API resources? Check out this tutorial that covers 5 popular crypto trading strategies and how you can backtest using historical crypto data.

Demystifying Price Charts with Elliott Wave Theory

What is the Elliott Wave Theory?

The Elliott Wave theory is the technical analysis of price patterns based on sequences, which are used to predict the path of the market over time.

Key Takeaways:

  • The Wave Principle by Ralph Nelson Elliott posits that crowd behavior trends and reverses happen in 13 patterns of price movements.

  • An impulsive or motive wave consists of five linked subwaves and moves in the same direction as the trend, where the even-numbered waves tend to be shorter than the other three.

  • A corrective or retracement wave comprises of three wubwaves and moves against the trend of the next larger size. 

The complexities that pervade every seasoned trader’s price charts leaves most neophytes discouraged. This is to say, traders use common terminology to describe charts but it can appear as an assortment of numbers and letters splattered at random around a graph. The nomenclature devised by Ralph Nelson Elliott is one of the main causes of this confusion.

Ralph Nelson Elliott discovered that crowd behavior trends and reverses in recognizable patterns — known as the Wave Principle. Using 75 years’ worth of stock market data, Elliott isolated 13 patterns of price movements. He described how these “waves” interlink to form larger versions of those same patterns, in an almost fractal manner. In expanding the time horizon, these basic structures form larger identical versions which, in turn, form larger versions of themselves, and so on. Essentially, the Wave Principle is a rolodex of price patterns that are used to predict the path of the market as time progresses. 

Elliott Wave Theory (EWT) Fundamentals

To say that market movements are patterned, especially in the frenzied realm of crypto, is largely controversial. But, consistent systems of punctuated growth, which show periods of bullish tendencies with phases of bearish undertones, is similar to the price patterns exhibited by most cryptocurrencies. This is the pattern Ralph Nelson Elliott described. The pattern consists of impulsive (a.k.a. motive) or correction (a.k.a. retracement) waves. The former is denoted by numbers on a price chart and the latter by letters.

A single impulsive (or motive) wave consists of five subwaves and moves in the same direction as the trend of the next larger size. In the figure below, the impulsive wave is clearly constructed by five smaller subwaves, all of which concatenate into an upward movement of one degree larger — ending at (1). With impulsive waves, the even-numbered waves (i.e. 2 and 4) are often shorter than the other three. 

Impulsive wave EWTThe end of this impulsive movement signals the start of a corrective wave. A singular corrective (or retracement) wave comprises three subwaves and moves — as expected — against the trend of the next larger size. As one can notice, the three subwaves that construct the corrective wave (from (1) to (2)) are labeled by letters, ending at (2) in the image below. Together with the previous impulse wave, this basic pattern forms structures of recurring five and three wave patterns of increasingly larger degree. Variations in corrective patterns revolve around repetitions of this three-wave pattern, but they create more complex structures that have a variety of names, like triangle, flat, or double three.

Corrective wave EWT

Elliott categorized these waves by relative size and distinguished nine degrees of waves — varying from a shudder on an hourly chart to the largest wave of an asset over a century. From smallest to largest these names consist of:

  1. Subminuette

  2. Minuette

  3. Minute

  4. Minor

  5. Intermediate

  6. Primary

  7. Cycle

  8. Supercycle

  9. Grand Supercycle

To reassert, these labels refer to identifiable degrees of waves, which refer to their size (or degree). One example, as described in A Capsule Summary of the Elliott Wave Principle, is the rise of the US stock market from 1932 to the present day. Often talked about as a Supercycle, it has the following subdivisions: 1932-1937, first wave of Cycle degree (i.e. one degree lower than a Supercycle); 1937-1942, second wave of Cycle degree; 1942-1966, third wave of Cycle degree; 1966-1974, fourth wave of Cycle degree; 1974-present, the fifth wave of Cycle degree. Fractally, Cycle waves subdivide into Primary waves which break down into Intermediate waves that are constructed of Minor waves, and so on. 

With this separation, each wave degree receives its own type of labels:

DegreeImpulse with the TrendCorrective Against the Trend
Subminuettei ii iii iv v a b c 
Minuette(i) (ii) (iii) (iv) (v)(a) (b) (c) 
Minute[i] [ii] [iii] [iv] [v] [a] [b] [c]
Minor1 2 3 4 5 A B C
Intermediate(1) (2) (3) (4) (5)(A) (B) (C)
Primary[1] [2] [3] [4] [5] [A] [B] [C] 
Supercycle(I) (II) (III) (IV) (V) (A) (B) (C)
Grand Supercycle[I] [II] [III] [IV] [V][A] [B] [C]

While seemingly convoluted, the alternative notation — preferred by most scientists — would be 11, 12, 13,14, etc. However, this further obfuscates a price chart, meaning the above table provides for easier readability. Alternatively, chartists also use color to discern wave degrees. One of the most difficult aspects of the Wave Principle is to decide what the initial smaller subdivision of a new wave in real time is. As waves are not based upon specific prices or time periods, they are dependent upon form, size, and position relative to adjacent, component, and overarching waves. Therefore, the Wave Principle is an intellectual challenge — permitting seasoned discretionary traders to establish a knowledge disparity. 

Expanding Elliott Wave Theory

Utilizing the nomenclature established by Elliott, analysts are able to accurately identify the position of a wave in time. This can be paralleled to using longitude and latitude over general location, or temperature over weather conditions. By saying Ethereum is in Intermediate wave [1] of Primary wave [2] of Cycle Wave III, etc., places a specific point along the price action of Ethereum in history. 

Reading the Elliott WaveSource: A Capsule Summary of the Elliott Wave Theory Principle

The above image expands upon the previously shown impulse and corrective waves to demonstrate this point. If you notice, wave 1 of impulse wave (1) consists of 5 subwaves, as does wave (1), suggesting that the first subwave of impulse wave (1) is also an impulse wave with its own subwaves — alluding to the “degrees” Elliott distinguished. The first subwave of impulse wave (1) is followed by three corrective subwaves that make up 2. This is the same makeup as the larger corrective wave (2).

Below is a pertinent example of the ‘geolocative’ capabilities of EWT. This specific image is taken from the Trading on the Mark Substack, which offers a regular newsletter discussing an assortment of assets, including bitcoin future prices. It perfectly illustrates the wavering nature that chartists display as they deliberate upon the correct degree of the wave under discussion when utilizing EWT. The author vacillates among the possibilities of the displayed waves, considering them as Subminuette impulse waves (iii, iv, v,…, a, b, c), Minuette waves ((iii)), or even Minute degree waves ([iii]). Nevertheless, through the use of EWT, they can accurately disclose and deliberate on the stage and movement of the Bitcoin futures market. For example, as written below, the newly generated price data causes their confidence in disclosing the most recently shown wave as a Minuette impulse wave ((iv)) to waver.

BTC Futures EWT

Source: Trading on the Mark Substack

Elliott Wave Theory in Crypto

Despite the onerous process of identifying a wave and its correct degree, GeckoTerminal simplifies this task. For example, in identifying the current state of WETH/USDC; simply select the pool in the search bar at the top, move to the graph displayed and select the “text” tool to begin jotting on the graph. The resultant chart can be seen below. WETH recently displayed a noticeable Minor impulse wave with an extended 5 subwave, constructed by 5 Minute waves as the price action reached for 1980, before featuring a corrective wave built by 3 Minor corrective subwaves that moved down to 1430, assembling the second wave (2) in the Intermediate impulse wave. Assuming a trader followed this pattern, they would have been able to trace the impending corrective waves that followed the 5 Minute Waves, and profited off of a short position once the support of 2000 was tested (as indicated by the (1), 5, and [v]).

Elliott Wave on GeckoTerminal

Elliott Wave Theory Technical Analysis

The contemporary overuse of the Elliott Wave Theory was a corollary of its precision. In essence, traders use it to define trends and timeframes with accuracy, simplifying price charts. Alternatively, some employ it as a form of technical analysis aimed at forecasting market movements by identifying recurring patterns.

Despite its applicability to various markets, including crypto, the theory fosters a number of pitfalls. This technical theory heavily relies on the analytical abilities of individual traders, leading to significant discrepancies in interpretation. Developed in the 1920s and 1930s, many consider its relevance today to be questionable, as it has not been updated to account for more recent market data.

Nevertheless, some traders still utilize the theory as a trading tool. One of the significant discoveries propagated by Elliott was the relation between the market and the sequences of five and three waves. The wave patterns resemble a Fibonacci sequence, as an additive sequence of 1, 1, 2, 3, 5, 8, 13, 21, 34, etc. is created throughout the theory. To clarify, 3 and 5 represent the three subwaves that construct a corrective wave, and the five subwaves that create an impulsive wave, resulting in a total of 8 waves — in correspondence with the Fibonacci sequence. This is continuously repeated as the successive waves are also constructed by this same pattern.

Fibonacci numbers occur widely in nature, suggesting that the progress of markets is not random or straight, but rather recur in three and five step patterns. Thus, the EWT is often interlinked with Fibonacci expansion and retracement levels, depending on the pattern displayed. More concretely, “Wave analysts” abide by the following rules:

  1. Wave 2 never retraces more than 100% of wave 1 of (1)

  2. Wave 3 cannot be the shortest of the three impulse waves (i.e. waves 1, 3, and 5) that construct (1)

  3. Wave 4 does not overlap with the price territory of wave 1

Similarly to the bases of the EWT, these rules have a number of sub-rules that are indicative of certain patterns that the impulse and corrective waves take. Chart analysis-based traders then apply these rules to Fibonacci extension and retracement levels, to identify potential profit and areas of support and resistance. Common Fibonacci extensions include 61.8%, 100%, 161.8%, 200%, and 261.8%. 61.8% is derived from dividing any Fibonacci number in the sequence by the number that immediately follows it, like 34 divided by 55. 161.8% is known as the “Golden Ratio” as it is derived by dividing any Fibonacci number in the sequence by another number that directly precedes it, like 144 divided by 89. 

Elliott Wave Theory and Fibonnaci Levels

Fibonacci extension points are chosen based on the start of the move, the end of the move, and the end of the retracement against the move — hence the association with Elliott’s Wave Theory.  Fibonacci retracement levels are established by multiplying the difference between a peak and a trough by the Fibonacci levels of 23.6%, 38.2%, 50%, 61.8%, and 100%. This product elicits the placement of support and resistance levels. 

Fibonacci extension/retracement levels herald the target of a wave’s movement within an Elliott Wave structure. These targets vary as different waves arise, for example in an impulse wave:

  • Wave 2 is 50%, 61.8%, 76.4%, or 85.4% of wave 1

  • Wave 3 is 161.8% of wave 1

  • Wave 4 is 14.6%, 23.6% or 38.2% of wave 3

  • Wave 5 can be measured in 3 different waves: 1) inverse retracement of 123.6-161.8% of wave 4 2) equal to wave 1 or 3) 61.8% of wave 1 to 3 

These rules only govern motive waves that are malleable given the nature of the impulse wave. For example, impulses can have periods of extension in one of its motive waves (either wave 1, 3, or 5). In the image below the third impulse wave of the Minor wave is elongated,  highlighting its subwaves — the Minute waves [i], [ii], [iii], [iv], [v]. This elongation could occur in any of the odd number waves that construct the first intermediate impulse wave (1) as shown below. 

Wave formation

This serves to reiterate the fractal nature of Elliott Waves and the variability of wave formation — hence the palpable skill-gap between new and seasoned traders. The rules that govern this example change when considering an impulse wave with a leading or ending diagonal, a zigzag, or regular and expanded flats. These patterns serve as the basis for judgment, gaining substance only when an obvious trend occurs. Despite this, as markets are deluged with participants and computing power, identifying these signals from Elliott Wave Theory and Fibonacci levels can help traders assume positions as the crowd joins in.

Returning to the previous WETH/USDC example, if one were to canonically follow the impulse wave rules stated above, their graph could look similar to the one illustrated below. The convoluted nature of using this technique in technical analysis is demonstrated below. Nevertheless, if one were to follow the laid out rules, they would notice the second wave is between 50% and 61.8% of wave 1, the third wave is 161.8% of wave 1, and the fourth wave is between 38.2% and 50% of wave 3 (as shown by the blue arrows). These four signals led up to a strong bullish trend in WETH/USDC, as shown by wave 5. While the locative capabilities of EWT in trading underscores its significance, incorporating it into technical analysis demands time and might seem arbitrary. Therefore, prudent practice suggests the utilization of additional indicators.

Application of EWT


The true ingenuity of the EWT lies in the nomenclature Elliott developed to assist traders in accurately discussing the price action of an asset. It facilitates communication with other traders and the sharing of information. This methodology can be leveraged throughout trading to identify levels of support/resistance as impulse waves run their course and corrective waves begin. Moreover, it can be combined with other forms of chart analysis, such as Fibonacci levels, to form more concrete projections of the price action. 

All content in this article does not address the circumstances of any particular individual or entity and is information of a general nature. Nothing in this article constitutes professional or financial advice, nor does any information in this article constitute a comprehensive or complete statement of the matters discussed.

Popular Crypto Trading Strategies & How to Backtest

What is Crypto Day Trading?

Crypto day trading is the buying and selling of cryptocurrencies within the same day, to profit from short-term price fluctuations. Traders rely on technical analysis, make frequent trades, and manage risk to capitalize on market volatility. Generally, traders employ 4 hour, 1 hour, or even 15 minute time frames to inform their decisions. Utilizing higher time-frames to inform shorter time-frame moves or backtesting their trading strategies can help overcome the inherently myopic nature of day trading.

In this article, we will examine the 5 most popular crypto day trading strategies and learn how to thoroughly backtest and validate those strategies using CoinGecko’s API. Regardless of whether you are new or experienced, we hope these insights will help you navigate crypto trading with confidence.

Let’s get started!

5 Most Popular Crypto Trading Strategies

1. Technical Analysis

The most popular crypto trading strategy is technical analysis, which can be broken down into two sections: chart analysis and technical indicators.

a) Chart Analysis

Chart analysis is the use of high time-frame chart patterns to analyze market movements and sentiment, understand trends, and inform trading decisions. This is commonly used by discretionary traders, and can be further divided into trend-following and mean-reverting strategies.

Trend-following assumes a persisting trend will break out of previously defined levels of resistance or support with sufficient momentum, and mean-reverting implies the price action is constrained by two eponymous levels, continuously reverting to some long-standing mean.

Chart analysis can involve the use of Japanese candlestick patterns. Popularized instruments include the Doji, the Mazuroba, the Spinning Top, the Hammer, amongst others. As the use of candlestick patterns is closely intertwined with market sentiment, chart analysis traders will also utilize the Fear & Greed Index to factor in volatility, volume, social media craze, surveys, Bitcoin dominance, whale activity, and Google search trends. That said, some traders exclusively rely on crypto Twitter (CT), or may use it in conjunction with chart analysis, to inform trading decisions.

b) Technical Indicators

The next prong of technical analysis is technical indicators. Like chart analysis, technical indicators also feature mean-reverting or trend-following strategies. To discern the two, one can employ the Augmented Dickey-Fuller (AFD) or Kwiatkowski–Phillips–Schmidt–Shin (KPSS) test. Both look for the existence of stationarity, allowing for traders to determine if mean-reversion is present. Both rely on the presumption that history will repeat itself, given that their inputs are historical price data.

While these tests are not necessary, it helps to explain the price action history. Traders can employ technical indicators to gain insight into the immediate future of the asset. Common indicators include:

  • Moving Averages
  • Moving Average Convergence Divergence (MACD)
  • Bollinger Bands
  • Average Directional Index (ADX)
  • Fibonacci Retracements
  • On-Balance Volume (OBV) 
  • And others

Technical indicators are used by most market participants and remain prevalent today. For example, if you aim to comprehend the direction of public interest, consider examining the Relative Strength Index (RSI). The RSI is widely recognized and utilized by retail traders for its popularity in capturing trends and market sentiment. Variations in trading success arise from a trader’s capacity to interpret the tool and deduce appropriate decisions.

2. Options

Most technical analysis tools are lagging indicators, slowing traders in their decision making and leaving them susceptible to sudden market changes. Given this gap, traders use other strategies like options trading, to mitigate risk. 

Options trading gives the owner the right to buy or sell a predetermined quantity of the underlying asset at or before a certain strike date for a specified strike price. There are 3 type of option styles:

  • American: Contracts can be exercised at any time up to and including the day of expiry.
  • European: Contracts can only be exercised on the day of expiry.
  • Bermudan: Contracts can be exercised on a fixed set of dates.

European options are most commonly used in crypto. An options contract has inherent leverage, as one contract may represent multiple units of the underlying asset, and the downside is restricted to the premium one pays to hold the contract (when buying a put or call).

Therefore, traders will utilize puts and calls to manage their risk profile. One example is a long straddle. A long straddle consists of one long call of a higher strike price and one long put at a lower strike price. Both have the same underlying asset and strike date. This setup allows traders to capitalize if the underlying asset increases, or decreases in price. The loss is constrained to the premium and fees paid to hold the contract. Other risk-mitigating option strategies include: 

  • Straddles
  • Butterflies
  • Married puts
  • Protective collars
  • And others

3. High-Frequency Trading

Alternatively, some traders utilize high-frequency trading – a technique that conducts many trades at once. It is a type of algorithmic trading strategy where computer programs execute a large number of trades in fractions of a second. They aim to anticipate market trends before they become apparent to other participants. 

One example is market making. High-frequency traders will submit a limit order to buy or a limit offer to sell and earn the bid-ask spread. By setting their sell order a tad above asking, and their buy order a little below the current bid, they gain the difference in price. Other examples include:

  • Event Arbitrage
  • Statistical Arbitrage
  • Latency Arbitrage
  • Index Arbitrage

4. Leading Signals

Leading indicators are measurable signals that help forecast future price action activity, giving traders more insight in the present. The previously mentioned technical indicators have all been lagging signals as they confirm the data that is already apparent. Leading signals leave room for innovation. For instance, John Ehler often employed electrical engineering concepts, such as bandpass filters, to construct new indicators like the Fisher Transformation or the Empirical Mode Decomposition (EMD) tool. 

The Fisher Transformation highlights when prices have moved to an extreme, based on recent data. It converts prices into a Gaussian Normal Distribution, highlighting peak swings and making price reversals easier to identify. This tool is an example of a leading indicator because it identifies potential price reversals before they occur. Despite most technical indicators being lagging, John Ehlers innovations stand as a testament to the possibilities of creating new leading tools for this strategy.

5. Perpetual Futures

A perpetual future is a type of crypto derivative that allows users to speculate on the price of an asset. Perpetual futures are like futures contracts, but they do not have an expiry date. Therefore, their only purpose is speculation. When a perpetual contract is opened it has a fixed value, like a futures contract, but with no expiry, allowing traders to hold it indefinitely. Rather than settling the contract, ‘perps’ use funding rates. If the perp price is above the underlying asset spot price, traders who are long pay a fee to traders who are short – this is a positive funding rate. In contrast, if the funding rate is negative, traders who are short pay the traders who are long. This mechanism keeps the perp price inline with the spot price, as it becomes more expensive for traders to hold the contract the more it diverges. 

This derivative is popular because it allows traders to utilize leverage, as some exchanges offer perps with extremely high leverage possibilities. They can be extremely risky, given their lack of regulation and potential for high significant fees.

In sum, trading encompasses the process of balancing risk with reward. To backtest trading strategies, one will require historical crypto price data. Fortunately, the process of acquiring and implementing aggregated crypto price data for trading strategies is simplified by the public CoinGecko API.

How to Backtest Your Crypto Trading Strategy

Backtesting is the process of applying a trading strategy over an asset’s historical prices, ideally covering both bear and bull market scenarios, to evaluate its effectiveness prior to its actual implementation. Common metrics to measure effectiveness include the Sharpe ratio, the max drawdown, or the max drawdown duration.

In this guide, we’ll be using CoinGecko’s Public API to fetch historical crypto price data via Python.

Get Crypto Price Data with CoinGecko API (Python)

An API is an application programming interface that allows two programs to talk to each other. CoinGecko’s API provides this data through RESTful JSON endpoints. REST APIs facilitate the communication over HTTP (Hypertext Transfer Protocol) between two computers. These API requests are sent and received through JSON (JavaScript Object Notation) formats. This is due to the difficulty of decoding data through previous formats like XML or HTML.

Installing CoinGecko’s API with python can be done by typing “pip install pycoingecko” into your computer’s terminal or command line. This opens up our python virtual environment. In this guide, I will be using Jupyter Notebook.

For our python program, we will install numpy, matplotlib, and pandas, which will allow us to manipulate, visualize, and picture our data.

Get Crypto Price Data with CoinGecko API (Python)

From the pycoingecko library we will call CoinGecko’s API to get various crypto price data based on specified parameter inputs, including the coin, the currency to compare it to, and the time frame of the data. For example, to get historical price, volume, and market cap data, type coinGecko.get_coin_market_chart_by_id(). Insert ‘bitcoin’, ’usd’, ‘365’ within the brackets. The granularity of these calls vary depending on the number of days specified in our query:

  • 1-day from current time produces data in 5-minute intervals (as in 5-minutes before the present, 5-minutes before that, etc.)
  • 2-90 days from current time produces hourly data
  • above 90 days returns daily data

We will also be using the OHLC endpoint, of which the granularity is automatic:

  • 1-2 days from current time results in 30-minute intervals of data
  • 3-30 days returns 4-hourly data
  • above 31 days shows 4-daily data

Tip: You can unlock a daily candle interval parameter by subscribing to CoinGecko’s paid API.

20-day SMA Strategy

Let’s imagine we are constructing a strategy surrounding Ethereum for the past year. To return OHLC data we will send a request to the CoinGeckoAPI to get_coin_ohlc_by_id, with inputs of ‘ethereum’, ‘usd’, and ‘365’.

For improved readability we can reconstruct the resultant data into a pandas dataframe, titling each column and setting the index to the date (after converting it into datetime structure). To_datetime converts our scalar, series, or array-like data into a pandas datetime object.

Tip: Specify unit=“ms” which will translate the date and time to milliseconds (ms) for improved readability. 

Now, we can visualize our newly constructed dataframe by plotting it through matplotpyplot. Let’s construct a simple strategy surrounding a 20-day simple moving average (SMA). As the API returns data on 4-day intervals, our lookback period will be 5, constructing a 20-day SMA.

Backtesting Your Crypto Day Trading Strategy

Backtest Your Crypto Day Trading Strategy

For this crypto trading strategy, we’ll assume a bullish signal is generated every time the price action crosses from below to above the 20-day SMA. Conversely a bearish signal is generated once the price action crosses from above to below the 20-day SMA. For this long-only strategy, we have just identified both entry and exit points.

To reiterate, we will generate our signals by adding a new ‘Signal’ series to our dataframe, where 1 implies a long signal and -1 a short.

Visualizing our dataframe can help confirm the accuracy of our code so far. Notice how a long signal (1) is generated and sustained in the ‘Signal’ series until a sell signal (-1) is indicated, causing the series to return to ‘0’.

Generating Results

Our percentage returns can be calculated by taking the percentage change in the ‘close’ series and multiplying it by the shifted ‘Signal’ series. This is to align the signal generated with the corresponding close price. The cumulative returns are merely the cumulative product of the ‘Returns’ series.

As shown above, traders can scrutinize an assortment of metrics based on their own strategy – that said, max drawdown and max drawdown duration are two of the most common ways to assess a strategy using technical indicators. The maximum drawdown (MDD) is the difference between the local maximum and local minimum of the equity curve, following the occurrence of the local maximum; it is the greatest observed loss between a peak and trough of the equity curve over a time period. The maximum drawdown duration is the longest it has taken for the equity curve to recover losses. The equity curve is simply a plot of the cumulative returns.

The cummax() pandas function sifts through each series, returning only the max value displayed up until that point. The drawdown is calculated by dividing the difference between the cumulative return at that point and the peak by the peak value. Max drawdown duration is established through a running total of the duration variable (duration += 1), returning the variable to 0 if the drawdown is equal to zero and if the duration is greater than zero. Meaning, the duration count has been recorded before returning it to 0, to count the next running total in an effort to determine the longest drawdown stint.

The Sharpe ratio is calculated by taking the expected return and dividing it by the standard deviation of the excess returns. The expected return is simply the mean of our excess returns, which is the difference between the assets return and a risk-free asset. In this instance, we will disregard the risk-free rate. Our excess returns is a list, where each value is generated from our long and short signals. We will consider a long signal created when the ‘cross_up’ series is true because our ‘Signal’ series features a number of ‘1’s, due to them repeating until a short signal materializes. Only the first instance of each 1 constitutes an entry signal, not each successive ‘1’. Each successive ‘1’ simply shows that we are still in a long position. Therefore, we use this alternative method as shown below.

Analyzing Strategy Results

Defining a strategy_result function amalgamates all previously discussed data to generate a signal output of consolidated figures. Similarly to our excess return function, we will define a long or ‘buy’ signal as the point where the ‘cross_up’ series is true, and the short or ‘sell’ signal where the ‘Signal’ series is equal to -1. Then we can determine our profit, number of trades, and number of wins based on the discrepancy between the generated entry and exit prices.

To display our data we can employ ‘f strings’. F-strings are string literals that begin with an ‘f’ and contain curly braces to signify expressions that will be replaced by values. This is conducive to our results being legible. The ‘5.2f’ or ‘.2f’ splattered throughout the below code specifies the width, number of decimals, and type of figure produced. ‘5.2f’ indicates a width up to ‘5’ characters, and a ‘float’ value up to ‘2’ decimal points.

Then we can print all of the above variables, as shown below. The reason for separating them is for improved code readability, as opposed to having the code rife with intermixed green ‘print’ and red ‘f-string’ letters we can simply disconnect them. 

As demonstrated in our subsequent output below, our SMA crossover strategy for Ethereum over the past year generated negative results. This is epitomized by the large loss, low win rate, and negative sharpe ratio, suggesting this strategy would have been worse than a risk-free US Treasury Bill.

Lastly, to conceptualize our max drawdown and MDD, we can use the below code to plot the equity curve. 

As shown above, this 20-day SMA crossover strategy ultimately yielded negative returns over the course of a year.


Crypto day trading can involve various methods like chart analysis, technical indicators, sentiment analysis, and High-Frequency Trading. Given the crypto market’s unpredictability and volatility, backtesting trading strategies on historical data, before using them, can reinforce solid ideas and weed out weak ones.

All information and examples in this article are provided for informational purposes only, and should not be taken as financial advice.

Get Historical Crypto Prices with CoinGecko API

CoinGecko API is the best crypto API for historical prices, as it includes price, market cap, 24hr trading volume for over 10k cryptocurrencies, spanning 10 years worth of historical price data since April 2013.

While the Public API is generally sufficient for traders, pro traders may consider subscribing to CoinGecko’s Analyst API to enjoy exclusive paid-only endpoints – including:

  • Historical market data of NFT collections (includes floor price, market cap and 24hr trading volume)
  • Historical trading volume data of exchanges
  • Get OHLC data of any cryptocurrency, where the candle interval is of daily data granularity

If you’re looking for a custom solution, get in touch with our Business Development team via the form below:

Internal Bar Strength (IBS) and the Adjusted Failed Bounce Strategy

The Internal Bar Strength (IBS) Indicator

The Internal Bar Strength (IBS) indicator is useful for short-term mean-reverting strategies. Measuring the relative position of a period’s closing price to the same period’s high and low, the IBS can be interpreted to predict a bullish signal when displaying a low value and a bearish signal when presenting a high value.  

Key Takeaways:

  • The Internal Bar Strength indicator assumes that the market is mean-reverting, and is useful for short-term trading strategies. 

  • A low IBS creates a bullish signal and a high IBS a bearish one.

  • The IBS can be utilized in a number of unique trading strategies, with some producing appealing backtesting results. 

The ceaseless alternation of legal maneuvers and regulatory challenges that characterizes the battle between the SEC and Ripple reached a momentary pause this past week. Thursday’s court ruling by Judge Analisa Torres indicated that almost all XRP sales did not constitute security transactions. Widespread positivity rang across the industry, with exchanges like Coinbase relisting XRP and many hoping this marked the unraveling of the war waged on crypto. This news galvanized many into investing, with XRP rising 63.1% over the past 7 days, causing a bullish sentiment to disseminate over many other coins in the space. Prior to this news, crypto was — and some argue still is — in the midst of a bearish winter. Many coins during this time exhibited mean-reverting tendencies, and to capitalize on this one can employ the Internal Bar Strength (IBS) indicator.

Understanding the Indicator

The Internal Bar Strength (IBS) indicator is useful in short-term mean-reverting strategies (mean reverting strategies assume that an asset’s price will eventually revert to its long-term mean or average price level). The indicator oscillates between zero and one, measuring the relative position of a period’s closing price to the same period’s high and low. Under the assumption that the market is mean-reverting, a low IBS acts as a bullish signal and a high value acts as a bearish signal. The core tenets of the IBS indicator are to buy on weakness and sell on strength — at least in the short-term. Emphasizing the short-term mean-reverting nature of this strategy serves to highlight that the markets are inundated with people and advanced computing power, meaning while the IBS has proven fruitful, most popular indicators are now ‘arbed’ away as they are widely used. Therefore, the majority of this article will pertain to a strategy that employs the IBS indicator in a unique manner. 

Calculating and Implementing the Internal Bar Strength (IBS) Indicator

The IBS indicator is simplistic in its interpretation, calculation, and implementation. While it is unavailable on GeckoTerminal as a preset, it is relatively easy to determine. Displaying the price action of a desired token on GeckoTerminal, like WETH/USDC on Uniswap, will help elucidate how the IBS is constructed. Once an asset, like WETH/USDC, is selected, one merely needs to pick a timeframe, for example ‘daily’, as shown below:

OHLC daily data

Calculating the indicator requires the OHLC data of the underlying asset. In the case of WETH, the previous day (15/07/2023) opened at $1,935.92, achieving a high and low of $1,940.55 and $1,932.18, respectively, before closing at $1,933.77. Using our example, we would calculate the IBS through the following formula:

IBS = (Close-Low)/(High-Low)

IBS = (1933.77-1932.18)/(1940.55-1932.18)

IBS = 1.59/ 8.37

IBS = 0.1897

This indicator is simple, but very intuitive. The nearer the close price to today’s low, the smaller the IBS value. The nearer the close price to today’s high, the bigger the IBS value. This suggests a buy signal is generated when the value is low, normally considered below 0.2, and an exit signal occurs when the IBS is high, normally above 0.8. 

Adjusted Failed Bounce Strategy

Returning to the strategy mentioned earlier, an amended version of Rob Hanna’s Failed Bounce Strategy illuminates the functionality of the IBS indicator. The strategy focuses on instances where the price action is declining, as indicated by the bearish sentiment of the IBS (>0.6), but there are still brief recoveries in the price (hence failed bounce) — essentially, a dead cat bounce. This long strategy is founded on the following four parameters:

  1. The IBS yesterday was at least 0.6 or higher.

  2. The low yesterday was lower than the lowest low during the five days before.

  3. The close today is lower than yesterday’s close.

  4. Exit when the close is higher than the highest high during the five days before.

This will be coded in python, hence one can utilize pandas, which is useful for data manipulation and analysis, numpy, which is handy when dealing with arrays, and matplotlib.pyplot, which will be used to visualize our findings.

Import data

Fetching Historical Data

The CoinGecko API provides comprehensive RESTful JSON endpoints to extract data from. Illustrated below is how to pull the OHLC ETH/USD data for the past 30 days and reorganize that data into a pandas dataframe. Given the granularity of the CoinGecko historical data, the API affords 4-hour intervals of OHLC data for 30-day periods. I will refer to these periods as “today” and “yesterday”, as these merely constitute the present and previous period — to avoid repeatedly writing “previous period” and “present period,” which is far more confusing. 

Fetch historical data

Applying Strategy

For code reusability, one can develop a StrategyAnalyzer class. The _init_ method is automatically called when an object — an instance — of this class is created. In the below code, the _init_ method initializes the object of the StrategyAnalyzer class by assigning the previously constructed dataframe, df, to the self.df attribute. Therefore, the dataframe can be accessed by other methods within the class, allowing for the data to be reused efficiently.Apply strategyThe previously mentioned IBS equation will help in constructing the next method. The only input parameter of the IBS method below is self, as it calls upon the aforementioned initializer to utilize the dataframe. Then the method uses the same formula as before to determine the IBS at each instance of the OHLC data provided for the past 30 days. determine ibsAfter developing the indicator, one can employ the previously laid out trading rules in the manner shown below. To reiterate, the signal starts at 0, indicating neither a long nor short signal, and only changes once the previous IBS value is above 0.6, yesterday’s low is lower than the lowest low of the previous 5 days, the close today is lower than yesterday’s close, and the signal is not already 1 (a long signal). When a long signal (=1) is achieved, the corresponding next day open price is appended to the LongPrice list, while nothing is added to the ShortPrice list. The exit signal is indicated once today’s close is higher than the highest high of the previous 5 days and the signal is currently 1 (meaning a trader is in a long position). Then the corresponding ShortPrice will be appended to the ShortPrice list. If neither condition is true no price will be appended to the LongPrice or ShortPrice list. Lastly, the signal value will be returned to 0 after a short signal is indicated. 

Long and short signals

In order to visualize these lists, the below code appends three new series to the existing dataframe, allowing for simplified code readability. 

Long and short signals readability

Visualizing Signals

Conceptualizing these signals and the equity curve of the strategy can be done through exercising the code below. The returns of this strategy are determined by taking the product of the percentage change in the close price and the shifted value of the ‘Signal’ series (1 for long signals, -1 for short signals, and 0 for no signal). By applying the shift(1) pandas function, the values of the ‘Signal’ column are shifted one position forward, allowing the index value at position ‘i’  to correspond to the signal that was generated at the index position ‘i-1.’ This permits the trading signal to correspond with its appropriate returns. Meaning, it allows the returns to be based on the previous signal, which reflects the action taken in that period to generate those returns. The rest of the code simply uses matplotlib.pyplot to display the trade signals and the equity curve.  Plot signals

Evaluating Strategy

To properly scrutinize a strategy, many traders look at the maximum drawdown and the maximum drawdown duration. The maximum drawdown (MDD) is the difference between the local maximum and local minimum of the equity curve, following the occurrence of the local maximum; it is the greatest observed loss between a peak and trough of the equity curve over a time period. The maximum drawdown duration is the longest it has taken for the equity curve to recover losses

Drawdowns are useful to determine one’s risk tolerance. Specifically, drawdowns increase the chance of behavioral mistakes. In the event a drawdown occurs, a traders risk tolerance will determine if they are faithful to their strategy. Hence the importance in determining the max drawdown (MDD) and the max drawdown duration. The extent to which a trader is willing to squirm without abandoning faith in their strategy can depend on their willingness to endure a drawdown.  

The ‘for loop’ in the code below checks if the drawdown at the current index is equal to 0, indicating the end of a drawdown period. If the duration is greater than 0 — meaning it has already been tracking a downward period — the code appends the duration to the durations list. If the drawdown at the current index is not 0, duration is incremented by 1, suggesting the continuation of an existing drawdown period.

Max drawdown duration

Displaying the results of the strategy is largely founded upon the previously written code. As demonstrated below, if a buy signal is indicated (=1) the corresponding open price is recorded. Similarly, if a sell signal has been generated the commensurate closing price is recorded. The difference between the two prices equates to profit, and the number of wins is determined by the number of times their difference is positive, and losses by the number of times it’s negative. All of this is then printed out, including the more comprehensive statistics of the MDD, MDD duration, Sharpe Ratio, and Avg. Trade (the profit/loss generated per trade).

strategy results ibs


Following the creation of all these functions, an instance of the class is created and the methods are called.

create instance and call methods

The equity curve can also be referred to as the cumulative profit and loss curve, assuming there has been no cash infusion. Therefore, the equity curve below shows the profit a trader would have gained had they invested $1 in ETH using this strategy over the past 30 days. Any peak to trough of the curve below is a drawdown, with the max drawdown occurring in between the 2023-07-03 and 2023-07-07 date ticks. Coincidentally, the MDD duration is also at the same timeframe, from 2023-07-05 at 08:00:00 UTC  to 2023-07-06 at 12:00:00 UTC. Most would assume the MDD duration is the length of time during which the MDD occurs, but this is not always true. The MDD duration is the longest time between peaks — the longest time it takes for the equity curve to recover; therefore, it is not guaranteed to occur when the MDD does, as in this case.

Equity curveThe long signals are illustrated by the green arrows on the price action below and the sell signals are demonstrated by the red arrows. This graph helps clarify the intention of the Failed Bounce Strategy. For example, the second and third buy signals occur right after the price action hits a support level, suggesting the price will ‘bounce’ upwards—as it does momentarily— triggering a sell signal, but the overall movement of the price action during that period of time is still bearish (i.e. from 2023-06-23 to 2023-06-29).

long short signals

Lastly, the figures below demonstrate the performance of this strategy. If one were to have traded a single ETH for the past 30 days when employing this strategy, they would have obtained a profit of $88.73 USD, over 12 trades, resulting in a win rate of 83.33%. The average trade would have returned $7.39 USD. A Sharpe Ratio that high is very encouraging, but may be a cause of ‘overfitting’ the equity curve or data-snooping complications. The max drawdown is 1.66%, as shown by the equity curve above, which, again, shows the return had one invested $1. The corresponding MDD duration, which overlapped the MDD, was 8 periods or 32 hours. 

adjusted failed bounce strategy results

This “Adjusted Failed Bounce Strategy” provided interesting backtesting results for ETH over the past 30 days. While seeming profitable, independently backtesting this strategy will help traders determine its profitability given different parameters and individual circumstances. This strategy accentuates the performance of the IBS in short-term mean-reverting time periods. 

All information and examples in this article are provided for informational purposes only, and should not be taken as financial advice. 

Strategizing With the On-Balance Volume (OBV) Indicator in Crypto

The On-Balance Volume Indicator (OBV)

The On Balance Volume Indicator is a momentum indicator that uses the cumulative volume of an asset to signal upcoming trend reversals or breakouts. 

Key Takeaways:

  • The OBV is the cumulative sum of volume flowing in and out of a security, and is referred to as a leading indicator as it is intended to reveal the actions of large players in a market before the effects are apparent in the price action.

  • Discrepancies and divergences in the price action of an asset can be taken as a potential indication of a near time price reversal.

  • The OBV can house a number of false signals, as parameters, time periods, and the asset itself can constitute a variation in the success or failure of the strategy.

The rise of online banking has allowed depositors to withdraw funds from commercial banks in a hasty and perfunctory manner. While convenient for clients, it can prove detrimental for banks. There are substantial precedents expressing this threat, with the recently condemned Silicon Valley Bank (SVB) being a primary example. According to Federal Reserve data, 25.3% of deposits were drained on the 9th of March 2023 and an additional 60.2% was scheduled to be withdrawn on the 10th. This peak of one-day withdrawals from the SVB was well above that experienced by Washington Mutual Bank in 2008, which resulted in the largest bank failure in history. The largest one-day withdrawal at the bank reached just over 2%. Hence, being aware of volume and money flows can be integral to identifying the strength of a firm or an asset. Especially in the domain of crypto, comprehending volume can be influential to trading given the ease with which money can flow.

Understanding the Indicator

Price and volume are two fundamental components of technical analysis. Volume is the total number of shares/contracts traded within a specified timeframe. Therefore, the higher the volume, the greater the liquidity. Traders like to see volume slowly increase in the direction of the price trend they have predicted. To visualize this, traders have popularized the use of the On-Balance Volume (OBV) indicator. Its function – simple yet vital – is to indicate to traders if money is flowing in or out of an asset.

The OBV is a momentum indicator. By taking the cumulative sum of an asset’s volume, it is intended to act as a leading indicator: signaling upcoming trend reversals or breakouts. Introduced in 1963 by Joe Granville, the OBV indicator is colloquially referred to as the “smart money indicator,” as it is intended to reveal the actions of large players in a market before the effects become apparent in the price action. This can be extremely useful to identify whale movements in crypto markets. Joe Granville’s ingenuity lies in the fact that the OBV was one of the first indicators to account for both the positive and negative flow of volume.

Calculating the On-Balance Volume Indicator

The OBV is the cumulative sum of volume flowing in and out of an asset. Due to the assumption that volume leads the price action, the OBV has received the moniker of a “leading indicator.” Preceding how it is utilized, looking at how it is calculated can be largely beneficial:

In the event today’s closing price is greater than yesterday’s:

Current OBV = Previous OBV + Today’s Volume

In the event the previous closing price is equal to today’s:

Current OBV = Previous OBV – Today’s Volume

If today’s closing price is equal to yesterday’s:

Current OBV = Previous OBV

As displayed above, the calculation of the OBV is seemingly undemanding. 

For crypto trading purposes, you can pull up the indicator easily on GeckoTerminal. All you have to do is select a desired liquidity pool featuring your token of interest, select “indicators”, and type in OBV for it to appear. This is shown in the image below:

OBV GeckoTerminal 

Standard and Hidden Divergences

Conceptually, the price action of an asset should follow its OBV, as the OBV is a simple line chart of the amalgamated volume. Any discrepancies can be taken as a potential indication of a near time price reversal. Similar to the RSI, the OBV can reveal standard or hidden divergences. 

Standard Divergences

Standard/normal divergences take both bullish and bearish forms. Bullish divergences occur when the price action reaches a lower low (LL) and the oscillator (the OBV) takes a higher low (HL). Bearish divergences are the antithesis, with them occurring when the price action reaches higher highs (HH) and the oscillator takes lower highs (LH). A bearish standard divergence is displayed in the graph below. As illustrated in the chart, the WETC/USDC price action takes on a higher high, while the OBV action reaches a lower high. The signal issued by this divergence is demonstrated by the cryptocurrency’s ensuing bearish trend.

Divergences OBV

Hidden Divergences

Hidden divergences are named after their eponymous nature – being well-hidden. Bullish hidden divergences take place where the price action reaches a higher low (HL) and the OBV reaches lower lows (LL). Conversely, bearish hidden divergences materialize when the price action reaches a lower high (LH) and the indicator achieves a higher high (HH). An example of a bullish hidden divergence is displayed below. Notice how the price action of the WETH/USDC pool achieves a higher low as the OBV veers to a lower low, signaling the bullish continuation that follows. 

Hidden Divergences OBV

Alternatively, one can tentatively conclude that a trend reversal might occur with an OBV trendline. The signal supplied by the OBV can precede the price action breakout. In the event of a bullish breakout, this would suggest the price of the crypto asset loitered behind the increasing volume, forcing the market to respond to the mass of bulls and buy orders, triggering a breakout.

Separating the OBV From Other Volume Indicators

The Accumulation/Distribution Line (A/D) attempts to measure the flow of money into and out of an asset. Although easily misconstrued, the A/D line varies from the OBV, as it takes the opening as well as the closing prices into its calculation. It is calculated by taking the money flow multiplier (MFM):

MFM = (Close-Low)/(High-Close)/(High-Low)

Multiplying this MFM by the period volume will obtain the Money Flow Volume (MFV). The multiplication of the current MFV and the previous A/D will obtain the current A/D. Similar to the OBV, this figure is plotted in a line graph and it is also used as a viable divergence indicator. The primary issue with the A/D line is that it does not reflect price gaps. This means that the MFM does not include changes in price ranges between periods, causing the A/D line to inaccurately reflect the price action.


Secondly, the OBV can be compared to the Ease of Movement (EOM) indicator. This oscillator reflects the amount of volume that is required to move the price of an asset. EOM is plotted on a line graph, with a midpoint of zero, and is normally smoothed with a 14-day moving average. When the price is moving up on light volume, the indicator shows high values above zero. Low values are displayed when price is moving downward on light volume. If a mass of volume is required to move the price, the indicator stays near zero. 

Long signals are divulged when the EOM crosses from below to above zero, short signals are given in the opposite scenario. The Ease of Movement is a euphemism for how far price shifts per unit of trading volume. Hence, if less volume is able to alter the price action to a greater extent, there is a superior ease of movement in the asset. The EOM is also used in determining states of divergences. Nevertheless, it is not a standalone indicator. It is often used to confirm the signals propagated by other indicators.


Flaws: How to Run Backtests to Check for False Signals

The OBV is a straightforward tool. However, as it is a leading indicator, it can house a number of false signals. This becomes apparent when utilizing the OBV with an SMA, one of the most popularized ways to use the indicator in a strategy. The following demonstrates how to construct an OBV-based strategy, and the backtested results of the OBV-SMA. The below code can be visualized using any web-based computing platform, such as Jupyter. 

First and foremost, obtaining historical price data from the CoinGecko API allows us to construct a dataframe.

Pandas dataframe

Import CoinGecko API data

This displays a pandas dataframe of the price, market cap, and the volume of ETH for the past 100 days, on a daily basis, aggregated across the 100 pools featuring Ether taken by CoinGecko. To recapitulate, CoinGecko aggregates all the pools featuring ETH, aggregating its price, and making it simple to convert into a pandas dataframe. I went about this in a slightly peculiar way: slicing the produced array, isolating for figures I wanted, and making it a readable dataframe.

Visualizing data

To visualize the price action over the past 100 days, and save the file, one can employ the above code. Now to create the moving average and the OBV indicator. The below code creates both an SMA and EMA, in the event the user wishes to manipulate their output. Then in plotting the OBV and SMA, the code produces the subsequent graph. To calculate OBV one can use the numpy cumulative sum function, accumulating volume based on the sign of the price change. In the event the price change is positive, the function takes the corresponding volume value, and adds it to the numpy array. If the price change is less than zero it subtracts (-Volume) the volume from the running total, and if it is equal (hence both other conditions are not true) it assigns a value of zero (as in no change). This is in accordance with the calculation of the OBV listed at the start of this article.

Plotting chart


OBV chart

A buy signal is created if the value of signal[col1] = df[‘obv’] is greater than the ‘obv_ma’ column at the same point, i.e. The LongShort function checks to see if the flag is equal to 1, if it is not, a buy signal is given and the flag value is set to 1. A sell signal is given when the converse happens, and the function checks for a value of zero, assigning a value of zero if these conditions are true. Then two columns of LongPrices and ShortPrices are created. Check out @ComputerSciencecompsci112358 for learning how to create other functions similar to this; he has a lot of useful videos concerning trading strategies.

Long Short Signal

The OBV-SMA strategy revolves around SMA crossovers. So, in the event the SMA crosses over the OBV line graph a buy or sell signal is created. Visualizing these sell orders produces:

Visualizing Buy and SellLong Short Signal Chart

At a glance, one can already denote the unexpected long and short signals generated by this strategy. To test for its numerical results, one can utilize the strategy_result function below. This checks the ‘Signal’ column to see if there is a buy order (=1) or sell order (=0) in the column. If there are, it changes the position we are in (waiting_for_close) and adds the price to the newly created variable. Check out Diego Degese on Medium for more insight into various trading strategies.

Strategy results

This strategy produced a 26.09% win rate on 23 trades, 17 being losses, and a total profit/loss of -$180.77. Now, this does not serve to discredit the entirety of this strategy, but it rather highlights the importance of backtesting a strategy. In adjusting the SMA and time period to 365 days, I obtained a win rate of 31.43%, producing a profit of $185.73. This was due to one bullish signal in July 2022 and two massive shorts indicated during September and November of 2022. Parameters, time periods, securities, all change and constitute a variation in the success or failure of the same strategy. Now, the parameters of this strategy can be manipulated to obtain better results, but one must be careful of data-snooping bias. This is the tailoring of numerous parameters to a single backtest, befitting it to circumstantial events in the past that may not repeat themselves in the future.

OBV + Autocorrelation Strategy

Out of interest, I sought to test the viability of combining the OBV, a measure of the cumulative volume flow of an asset, and Autocorrelation (ACI) – a measure that quantifies the correlation between an asset’s price at different time lags. 

Positive autocorrelation (ACI>0) indicates a tendency for the price to continue moving in the same direction and negative autocorrelation (ACI<0) suggests a tendency for the price to reverse its direction over consecutive time periods. This helps traders in identifying periods of momentum or persistence in price movements. 

Therefore, in combining the two strategies a bullish signal is generated when the OBV is trending upwards (indicating buying pressure) and the ACI is positive (indicating persistence in the price trend). Alternatively, a bullish signal can arrive when the OBV is trending downwards (indicating selling pressure) and the ACI is negative (suggesting a reversal in the price trend). The inverse of these indications supplies traders with bearish signals.


Long signals were identified if the ACI was above 0.8 and the OBV was increasing, or if the ACI was below 0.8 and the OBV was decreasing. The former suggested a persisting trend, and the latter a potential trend reversal. Likewise, sell signals were generated if the ACI was greater than 0.8 and the OBV was decreasing (persisting down-trend) or if the ACI was less than 0.8 and the OBV was increasing (potential reversal).

Identifying signals with ACi

This generated a profit of $698.3 over 365 days, with only 9 signals generated, resulting in a 55.56% win rate. Although seemingly appealing, this strategy is easily susceptible to data snooping complications, causing its high success rate. Additionally, the low number of signals generated suggests this strategy had overly restrictive conditions. Anyhow, it is always useful and interesting to backtest.

Strategy results 2

All information and examples in this article are provided for informational purposes only, and should not be taken as financial advice. 

Utilizing the Relative Strength Index (RSI) in Crypto

The Relative Strength Index (RSI)

The Relative Strength Index is a momentum indicator, meaning it provides a measure of the strength and direction of a price trend. It is plotted on a line graph on a scale of 0 to 100 and indicates overbought and oversold conditions. 

Key Takeaways:

  • The RSI indicator can signal potential entrance and exit points for long and short positions when it crosses the value thresholds for overbought and oversold conditions.

  • Midpoint Value Crosses can indicate whether there is a bullish or bearish bias in a trend, identify periods of consolidation, and can be considered as a potential indicator for a trend reversal.

  • The RSI also presents market signals through divergences and swing failures.

Mike Lazaridis. While a seemingly unfamiliar name, Mike will have had an impact on the life of anyone reading this article. Rightfully described as both imaginative and inquisitive, Mike is the inventor of the Blackberry. The Blackberry assuaged the difficulties experienced by businessmen across the world: disentangling the process of sending and receiving emails. Mike Lazaridis was intent on establishing the Blackberry as solely a mobile email device for your pocket. And his idea was evidently a success, as, in the summer of 2009, Blackberry assumed a 50% position in the market share for smartphones. By 2014, however, it was less than 1%. This was due to his overconfidence: he disregarded the need to add an internet browser or app development to his product. He assumed sticking to his guns was a virtue, but it was, and can often be, a fault – especially in trading.

Measuring when a trend or the sentiment concerning a security is growing or diminishing can greatly aid in trade management. Hence the point of this article: The Relative Strength Index. 

Understanding the Indicator

As mentioned above, the Relative Strength Index is a momentum indicator, providing a measure of the strength and direction of a price trend. It oscillates on a scale from 0 to 100 and indicates spells of excessive buying or selling. Commonly, these periods are signified when the oscillator surpasses a value of 70 (overbought) or falls below 30 (oversold). 

Some traders augment this rule when in the presence of a bull or bear market, propagating that one should instead apply the signals of overbuying/selling when the indicator features a value greater than 80/lower than 20. One proponent of this argument is John Murphy, a popular American financial analyst. Additionally, to comply with the volatility common to crypto employing the stochastic RSI— a more sensitive measure than RSI alone— can also be beneficial. However, the standalone RSI indicator also provides a number of signals. 

Overbought vs Oversold RSI 

The RSI indicator can sufficiently signal potential entrance points for long and short positions. If the RSI crosses from below 30— meaning it has previously been recognized as oversold— to above 30, it suggests the bears are finally dozing off and the bulls are waking up, marking the potential for the opening of a long position. Similarly, if the indicator crosses from above to below 70 the buyers begin to subside and the sellers are stirred into taking action, signifying the potential to open a short position. Among these indications, they also provide reason to close a short or long position.

Calculating the RSI

As with all indicators, understanding its process before the signals it provides can be hugely beneficial to utilizing the RSI.  The RSI, traditionally, determines the change in a security’s price over a 14-period time frame. This can be extended or contracted, but the formula follows the same process:

RSI = 100-[100/(1+RS)]


 RS = average gain over 14-periods/average loss over 14-periods

Albeit an overtly simple calculation, most traders will never have to perform it manually as it is readily available on most trading platforms. GeckoTerminal makes this a straightforward process. Simply select a desired crypto liquidity pool and then select “indicators,” and the RSI will appear in a graph below. This is shown in the image below.

 RSI GeckoTerminal 

Midpoint Value Crosses

Most traders use the previously mentioned extreme values to generate signals. But the RSI can afford many more luxuries in the way of indicators. Particularly, through the midpoint value, which can be applied in the following ways:

Indicating Trend Bias

The midpoint of 50 can help traders garner insight into the sentiment featured in their market. It houses a trinity of implications. Firstly, it can indicate when there is a bullish or bearish bias in a trend. Primarily judged on a discretionary basis, the trend bias is assessed by the amount of time the RSI action takes place above the 50 level (in the case of a bullish bias), or below (bearish bias). Notice in the figure below (WETH/USDC crypto liquidity pool) the dominating nature of the RSI action above the 50 line (with no breach of the line), and the expansion that follows this signal.

Indicating Bullish Trend Bias

Comparably— and this alludes to the discretionary nature of the midpoint value— notice in the image below the predominant RSI action that takes place below the 50 line, with few breaches. We can still infer the bearish bias of the market, as depicted by the down trend exemplified in the price action, despite the occasional breach of the midpoint value of the RSI.

Indicating bearish bias

Identify Periods of Consolidation

Secondly (and noted by CryptoCred, check him out @CryptoCred on Twitter), the midpoint value can be used to identify periods of consolidation. This occurs when the RSI is continuously chopping through the midpoint, alluding to the neither continuing nor reversing nature of the price action (hence consolidation). After this period of consolidation, the RSI action chooses to break towards the upside or downside, projecting the expansion or contraction that follows in the price action. This is shown in the WBTC/USDC crypto price action below.

Periods of Consolidation RSI

Potential Indicator for Trend Reversals

Thirdly, some traders treat the RSI as a potential indicator for a trend reversal. This is done by placing the 50 line under the guise of a dynamic support or resistance line. If, as shown below, the RSI action is above the 50 line, the midpoint line acts as a support; if below the 50 line the midpoint line acts as a resistance. Trend reversals occur when the RSI action crosses the midpoint (I should clarify this is synonymous with the  “50 line”) and the 50 line fails to maintain its appearance as a level of support or resistance.

Potential Indicator for Trend Reversals

Standard and Hidden Divergences

The RSI also presents market signals through divergences, as showcased by most articles seeking to describe the indicator— and for good reason. Divergences, as described by J. Welles Wilder “are the single most indicative characteristic of the relative strength index.” Simply, divergences occur when the price action moves in the opposing direction to an oscillator: in this case the RSI. This provides insight into the weakening or strengthening nature of a trend. Divergences can take two forms: standard or hidden.

Bullish standard divergences occur when the price action reaches lower lows (LL), while the RSI action takes on higher lows (HL). Visually, this is far more digestible:

Divergences RSI

As indicated above, the price action of WBTC/USD reaches lower lows as the RSI reaches higher lows, alluding to the divergence of the oscillator from the price. Conversely, bearish standard divergences materialize when the price action reaches higher highs (HH), as the indicator seeks lower highs (LH).

The hidden form of bullish or bearish divergences occur in a slightly different way.  A bullish hidden divergence appears when the price reaches higher lows (HL), as the indicator reaches lower lows (LL). Meanwhile a bearish hidden divergence is present when price reaches a lower high (LH) as the indicator achieves higher highs (HH). While the accidental intermixing or confusion of these patterns can cause traders to be rife with uncertainty during their implementation, it is far simpler to remember these patterns visually. Note the hidden bearish divergence below.

Hidden Divergence RSI 

These divergences can help indicate when the strength of a trend is waning. For example, in an uptrend, if a bearish divergence reveals itself one can take a counter-trending position, ultimately waiting for the bulls to get tired and the bears to pounce. Essentially, it can be hugely beneficial in order to avoid buying the top or selling at the bottom. 

The Potential for Failure Swings  

Nevertheless, there is always potential for a failure swing. Failure swings occur when the RSI action is at an extreme value (i.e., above 70 or below 30), and the RSI fails to make higher highs or lower lows, and instead reverses in the opposite direction. So, in the event the RSI is above the extreme value of 70, fails to make a higher high during a price uptrend (price has made a HH), and breaks a previous bottom during a retrace (often referred to as the fail point), it can reverse in the opposite direction. Refer to the image below:

Failure Swing RSI

The RSI action is above 70, fails to make a higher high during a price uptrend, and breaks the previous bottom during that retrace, indicating the RSI continues in a downwards direction, triggering a short signal. The highlighted area below follows the point where the RSI action breaks the line set by the previous retracement/ “fail point.”

RSI action fail point.png 

As expected, a failure swing bottom occurs when the RSI is below 30, the RSI action fails to make a lower low during a price downtrend (the price has made a lower low), and breaks the previous fail point, indicating a potential long signal. RSI swing failures are used for entering positions through anticipating trend reversals, exiting currently held positions, or —like divergences— to avoid buying/ selling the top/bottom. 


While the RSI is ideal for indicating overbought/oversold/trend-reverting conditions, it does not offer proper means for confirming a trade. Like most indicators, the RSI should be subjected to further analysis once a signal is indicated. Particularly in the erratic crypto market, other indicators that provide additional assertion to a trade decision are useful.

Bollinger Bands, VWMA, and RSI Strategy

An example of a combined strategy is using the RSI, a volume weighted moving average (VWMA), and Bollinger Bands. This strategy acts as a sort of rubber band that stretches and creates tension to move in the opposite direction as the indicators are tested. Uniquely, it features two sets of Bollinger Bands: one of a higher standard deviation (BB1) and one of a lower standard deviation (BB2). A long position in this strategy is indicated when the RSI is below 30 (oversold), the VWMA is trending upwards, and the price moves below the lower Bollinger Band of BB1. The entry point is then signaled when the price action crosses from below the lower Bollinger Band of BB1 past the lower Bollinger Band of BB2. An exit is then indicated when the price crosses above the upper Bollinger Band. Visually:

Bollinger Bands RSI

As seen in the graph above, these 4 indications constitute a long signal. A short position is thus indicated when the price action crosses above the upper BB (BB1), the RSI action is above 70, and the VWMA is trending down. A position is then entered when the price action crosses the upper BB (BB2). This trade strategy can be augmented to include varying levels of standard deviations, a different moving average, or different indicators altogether. The time frame can also play a large role in how this strategy is adapted. 


Much to the dismay of Mike Lazardis, shifting market sentiment is constant. Improvement is founded in embracing the possibility of changing one’s original opinion. For traders, especially in crypto, this is a perpetual process. The Relative Strength Index provides a quantifiable measure for traders to recognize this ever-changing feeling expressed in a market: providing signals for spot positions, bearish/bullish biases, standard/hidden divergences, and failure swings. When paired with additional indicators it gives even more substance to a trade signal— more solidity to an idea.

All content in this article does not address the circumstances of any particular individual or entity and is information of a general nature. Nothing in this article constitutes professional or financial advice, nor does any information in this article constitute a comprehensive or complete statement of the matters discussed.

Understanding the Parabolic SAR and Its Applications

The Parabolic SAR

The Parabolic SAR (PSAR) is developed for trending markets and is employed by traders to predict bearish or bullish price reversals and the plausibility of trend continuations. When utilized, the PSAR appears as a series of dots above or below charted candlesticks that indicates bullish or bearish signals.

Key Takeaways:

  • A dot below the price action indicates a bullish signal and a dot above indicates a bearish signal.

  • In trading, the PSAR can also be used to place stop-loss orders in accordance with the SAR points.

  • To avoid false signals in sideways markets, the PSAR is best used alongside other indicators like the Average Directional Index (ADX), mean reversion, and moving averages

The mathematical study of financial markets features a wide array of techniques and indicators. These tools are found throughout history, and vary from being easily interpretable for most retail traders to overly esoteric. A prominent example of analysis in trading can be dated back to the book of Aristotle. Thales, a Greek astronomer, was able to determine the weather of an ensuing harvest season purely from the movement of the stars during the winter. This allowed him to speculate in the supply of olives. He would thus preemptively rent all the olive presses for the harvesting season, allowing him to capitalize once demand swelled.

Since the time of Thales, technical analysis has matured to include the study of behavioral economics, market sentiments, and quantitative analysis (amongst other disciplines) and is indeed the most preferred method for speculating on crypto. Although technical analysis can be divided into multiple subdomains, technical indicators remain a prevalent option. And, with technical indicators abound, one of the most preferred is the Parabolic SAR (PSAR) indicator.

Understanding the Indicator 

The PSAR can be partitioned into its two components: parabolic referring to the parabola formed by the dots on the chart, and the dots themselves being stop-and-reversal (SAR) points. Therefore, the PSAR provides multiple indications. A dot below a candlestick is interpreted as a bullish signal, and a dot above a bearish. The indicator assumes the investor is constantly holding a spot position in the security; hence, the dots provide entry points for long positions, when to exit to hold short, and vice-versa. This also acts as a means for setting stop-loss orders, as investors can merely match the PSAR indicator.

Parabolic SAR

Source: GeckoTerminal 

Therefore, when a dot switches – as highlighted above – a potential change in price-direction is underway. The severity of this price-direction change, and its possibility of a breakout, is illustrated by the parabolic nature of the indicator as the dots accelerate with a persisting trend. The PSAR is also known as the Parabolic Time/Price System, as coined by its creator J. Welles Wilder Jr. This is to highlight that the stop is a function of price and time. As the indicator assumes a trader is constantly invested, if one is in a long position the stop (dot) will move up each day – this is the time function. The distance the stop moves up each period is relative to the distance the price has moved – hence the price function. Therefore, the longer a position is held – or the longer a price direction persists – the faster the stops accelerate. Consequently, when a dot switches direction it indicates a potential market reversal: if it switches from below to above, it can be perceived as a bearish signal with a decrease in price to follow.

Calculating the PSAR 

To properly understand the indicator, delving into its construction is useful. The PSAR is calculated using existing market data. Let us assume, for simplicity, the previous day had an extreme price point (SIP) of 10 and that we hold a long position. For the first day of calculation, this significant point is also our stop and reversal (SAR) point. Accordingly, 𝑆𝐼𝑃 = 𝑆𝐴𝑅 =10. We can now calculate the SAR for day 2 by using the following formula:


Where 𝐻1 is the previous day (or period) high and AF is the acceleration factor. The acceleration factor is the integral piece that gives the PSAR its parabolic nature. The AF was set by J. Welles Wilder Jr. to start at 0.02 and increase by 0.02 each day (or period) until it reaches a maximum value of 0.2. The acceleration factor varies depending on the new highs and lows set by the market. This demonstrates the accelerating appearance of the indicator as a trend continues over time. In the event a price swing occurs, and we are assumed to now be holding a short position, we instead subtract the previous day SAR from the previous SIP point (this time the low), and multiply the difference by the AF (starting back at 0.02) and subtract this from the previous SAR. To illustrate:


Adding the PSAR Indicator on GeckoTerminal

Following its simplistic construction, implementing the PSAR into a price chart is also straightforward on GeckoTerminal. Simply select a desired swap pool, like WETH/USDC on Uniswap V3 (as shown above), or WBTC/USDC on Uniswap V3, and then select “indicators” on the price chart. Type in “Parabolic SAR”, and the indicator will appear above and below the price action.
Add Parabolic SAR to GeckoTerminal

Source: GeckoTerminal 

Applying the PSAR to Crypto

PEPE, the meme coin that soared more than 2100% from its debut, can help demonstrate the potential gains and pitfalls of the indicator if it is followed religiously. The chart below portrays the PEPE/WETH pool found on Uniswap V3. As demonstrated by the nature of the price action, this pool illustrates a turbulent price history. If the PSAR is followed to predict bearish or bullish signals, with stop-losses placed in accordance with the SAR points, traders can experience regular gains in both long and short positions. Given the strength with which these price swings exist, one might notice the healthy acceleration of the SAR points (“price function”). However, the SAR points also suggest a constant switching between short and long positions during sideways movements – a flaw discussed later on.

PSAR $PEPE Example

Source: GeckoTerminal 

From its construction it is evident the PSAR bolsters in strength when utilized in a trending market. As overall crypto sentiment tends to be trend dominant, the efficacy of this indicator has been proven. As in the case of PEPE, the hype generated around the token, and the FOMO that followed, catalyzed its meteoric rise. Nevertheless, as time persisted, the market experienced enduring volatility and perpetually shifting market sentiment, as does the majority of crypto. Hence the indicator can house a number of flaws.

Flaws and False Signals

In sideways, anti-trend markets the PSAR can produce a number of false signals. As the indicator bobbles between bullish and bearish signals as the price moves sideways, it can harm traders, forcing them to augment its calculation. While moving sideways, a trader can expect smaller profits or increased losses as the indicator constantly signals to switch between long and short positions.

PSAR False Signal

Source: GeckoTerminal Platform

To alter the propensity with which the indicator swings from up-trending to down-trending, and vice-versa, one can manipulate the acceleration factor. In order to decrease the sensitivity of the PSAR, as it reacts to new highs and lows, the AF can be decreased. This produces less reversals. In increasing the AF value, the indicator can signal more SAR dot switches. Alternatively, one can manipulate the maximum AF value (0.2). Reducing the max AF value will produce fewer reversals, and increasing it will produce more. However, this approach has a less immediate effect as a price trend needs to persist to hit the maximum acceleration value.

PSAR Avoided False Signal

Source: GeckoTerminal Platform

Notice, from the first to second graph above, how in changing the AF from 0.02 to 0.01 the PSAR does not switch during the same period, avoiding the false signal.

As an alternative to manipulating the PSAR to account for its flaw, traders often use it in conjunction with other indicators. In the interest of brevity, these sections are intended to act as a basis for using the PSAR with other indicators, and further research is required before employing these strategies.

Average Directional Index (ADX)

In continuing to ride the coattails of J. Welles Wilder Jr., one can combine the PSAR with his average directional index (ADX) momentum indicator. The directional movement index (DMI) consolidates the ADX and two additional indicators, to measure the magnitude and direction of a trend. The DMI includes the ADX, the plus direction indicator (DI+), and the minus direction indicator (DI-). The ADX shows the strength of the trend – where a higher value constitutes a stronger trend – and the latter two indicators represent the current price direction. The current price momentum is up when the DI+ is above DI-, and the converse is true when the inverse occurs. As a heuristic process, you can use the following formulas to construct a 14-day period DMI strategy. The ADX is calculated as:


The prior ADX is the smoothed result of the previously consolidated directional movement index of the past 14 days:

Prior ADX

The directional movement index (DX) is the difference of +DI and -DI, divided by the sum of +DI and – DI:


In addition to the ADX, the plus/minus directional indicators are calculated as follows:


Where the smoothed +/-DM is:

Smoothed +/-DM

The DM is simply the directional movement and is determined as follows:


Lastly, the average true range – the denominator of the plus/minus directional indicators – is determined by:


The previous ATR is illustrated by:

Previous ATR

And the true range is simply the maximum of the difference between the current high and low, the current high and the previous close, and the current low and the previous close:


While the construction of the DMI and its constituents seem convoluted, its interpretation is simple. The DMI was developed by Wilder to show the strength of a trend, whether up or down. He suggested a trend was present when the ADX surpassed a value of 25. Therefore, if the DI- is above the DI+ and the ADX is above 25, this indicates a strong downtrend. If the DI+ is above the DI- and the ADX is above 25, this is an indication of a strong uptrend. It is important to note the ADX line does not consider the direction of the movement, but solely how much the market is trending in the present.

Applying the ADX to the PSAR


Source: GeckoTerminal

To be used in conjunction with the PSAR, it is best employed when a reversal of the PSAR occurs in tandem with a crossover of the DI+ and DI-, heralding a strong price-movement reversal. This is present in the above graph, wherein the DI+ crosses the DI-, while the ADX is above 25, and at the same time the PSAR turns bullish. Traders can maintain this position even if the ADX, DI+, or DI- changes, so long as the parabolic trailing stop is not taken out. Notwithstanding, if the ADX falls below the threshold of 25 or the DI+ and DI- relationship inverts, traders may need to reevaluate their positions. In using both indicators, traders can avoid the false signals produced by the PSAR when used in isolation in sideways trending markets.

Mean Reversion

Mean reversion is commonplace in the realm of quantitative trading. It is founded on the idea of stationarity – the constant variation in an asset’s price with no periodic fluctuations. This underpins the assumption that an asset’s price will eventually revert to its mean. The discrepancy between stationarity and non-stationarity is best described graphically:


Source: Wikipedia: Stationarity process

One can deduce the existence of stationarity in the first graph, given its oscillation around the mean. To test for stationarity, one might employ a variety of assessments, including the Augmented Dickey Fuller (ADF) test. The ADF tests the null hypothesis that the series is non-stationary. Individuals can check for stationarity if the resulting p-values are less than 0.01 or 0.05, for example. This allows us to reject the null hypothesis and recognize the presence of stationarity. The ADF test statistic suggests non-stationarity cannot be rejected at the 5% level in the second graph, hence its trend-like appearance. Both the ADF and the search for p-values are easily found in many statistics libraries.

The difficulty in mean reversion is determining if stationarity is present: the rest is simple. If you see a value lower than its mean, you long the asset, as you know it will return to its mean, and vice-versa. The classical Bollinger Bands strategy provides a more quantifiable range. For example, one can look to see if the price is 2 standard deviations below the mean (Lower Bollinger Band), and assume a long position. Or, if the asset price is 2 standard deviations above the mean (Upper Bollinger Band), one can go short. The Bollinger Bands are calculated by summating the moving average (MA) and the number of standard deviations (e.g., m=2) multiplied by the standard deviation over n periods of the typical price:



Typical Price

Regardless of these bounds, in a trending market – as shown in the second graph above – the asset price can go far beyond 2 standard deviations, leaving positions pregnable. Additionally, as hypothesized by the efficient market hypothesis, this technique can be pacified because of competition: the more people that do it, the less profitable it becomes.

Applying Mean Reversion to the PSAR

The implementation of mean reversion with the PSAR is fairly straightforward. Using the Bollinger bands strategy as a basis, if the price of a security is 2 standard deviations above its simple moving average (SMA), and a potential price-reversal is indicated by the PSAR, a short position is optimal. If the price of a security is 2 standard deviations below its SMA, and the PSAR has switched to a bullish signal, a long position is preferred. When used in unison, mean reversion reinforces the bearish/bullish signal highlighted by the PSAR indicator.

Moving Averages

Lastly, the PSAR can be used with the exponential moving average (EMA). The simple moving average (SMA) is at the foundation of its creation. Moving averages are simplistic, but used to identify the market’s direction. The SMA is calculated by taking the arithmetic mean of an assets price, over a given period of time:


The exponential moving average is calculated as:


Where 𝑃t is the price today, 𝐸𝑀𝐴y is the EMA yesterday (which is equal to the SMA for first time calculations), and k is the weighting factor:

EMA Parameters

This calculation of the EMA puts more weight on recent data points than the SMA, making it a weighted average calculation. A downwards trend in this indicator might signify a price downswing, and an increasing trend a price upswing.

Applying the EMA to the PSAR

The EMA and PSAR combination is based on the EMA crossover either below or above the price action.


Source: GeckoTerminal 

As depicted in the graph above, both the PSAR and the EMA are below price action prior to the PSAR switching. Once the PSAR switches, indicating a bearish signal, traders will wait to enter a short position until the EMA crosses over price action as well. This trade can be managed by placing a stop-loss order above the highest PSAR dot, or above where the EMA crosses over. Maintaining this position is contingent upon the PSAR dots remaining above the price action. Key support levels may supply satisfactory exit points for traders as well.


The purpose of the PSAR is to identify potential price reversals, exit points, trends, and satisfactory stop- loss order positions. In sideways markets, the indicator falls victim to misleading signals in isolation, as it was developed for trending markets. Considering crypto’s greater volatility, the PSAR is best employed in combination with other theories or indicators, providing more grounds for trade decisions and implications for trend directions.

All content in this article does not address the circumstances of any particular individual or entity and is information of a general nature. Nothing in this article constitutes professional or financial advice, nor does any information in this article constitute a comprehensive or complete statement of the matters discussed.