How to Build a Crypto Portfolio Rebalancing Tool with TensorFlow

How to Build a Crypto Portfolio Rebalancing Tool with TensorFlow

Managing a cryptocurrency portfolio can be challenging due to the volatile nature of crypto markets. AI-powered tools are becoming increasingly popular to help traders and investors make data-driven decisions. In this guide, we’ll show you how to build a crypto portfolio rebalancing tool using TensorFlow and the CoinGecko API. By the end of this tutorial, you’ll have a working model that predicts crypto price trends and implements rebalancing strategies based on AI predictions.

What is Portfolio Rebalancing?

Portfolio rebalancing is the process of realigning asset weights in an investment portfolio. In crypto, rebalancing helps manage risk and maintain a desired allocation despite price fluctuations. For instance, if your portfolio is split 60% Bitcoin (BTC) and 40% Ethereum (ETH), a sudden rise in BTC’s price could skew your allocation. Rebalancing restores the portfolio to its target allocation.

How AI & Machine Learning Enhance Rebalancing

With machine learning, you can predict price trends and make smarter decisions about when and how to rebalance your portfolio. Using TensorFlow, we’ll train an LSTM (Long Short-Term Memory) model to forecast price movements based on historical data.


Prerequisites

Before getting started, ensure you have a basic working knowledge of the following:

Python

This project heavily relies on Python programming, and hence, it is essential to understand Python syntax, libraries, and how to manipulate data. Ensure Python (version 3.8 or higher) is installed on your system. Python’s package manager, pip, is required for installing the dependencies used in this project – we’ll outline the installation steps below.

CoinGecko API

We will use the CoinGecko API’s free Demo plan to fetch market chart data for cryptocurrencies—specifically, the endpoint /coins/{id}/market_chart.

The Demo API plan is freely accessible to anyone with a CoinGecko account, capped at 10,000 calls monthly and a 30 calls/min rate limit. Explore 60+ endpoints on our API documentation, or create a Demo account to try it out!

Machine Learning Basics & Familiarity with TensorFlow

Familiarity with machine learning’s core concepts, such as datasets, models, training, testing, and evaluation, will help you understand the workflow.

Specifically, we’ll be leveraging the TensorFlow machine learning framework, used for creating and training models. Familiarity with TensorFlow or a similar library (like PyTorch) is crucial to implementing the LSTM model used in this project.

Data Visualization Basics

We’ll use Matplotlib for visualizing data and predictions – understanding how to create line plots and customize visualizations will be helpful.

Familiarity with NumPy (for numerical operations) and Pandas (for handling tabular data) is essential, as these libraries form the backbone of data manipulation in Python.

Text Editor or IDE

A robust text editor or IDE like Visual Studio Code (VSCode) or PyCharm is recommended for coding. These tools provide features such as syntax highlighting, debugging, and extensions to improve the development experience.

Python & Pip Package Installation using Visual Studio Code

To install Python and pip using VSCode, first download and install Python from the official Python website, ensuring to check the box that says “Add Python to PATH” during installation. Once installed, verify Python and pip are working by opening a terminal and running python –version and pip –version. If you’re using macOS or Linux, follow the platform-specific instructions on the Python website.

Next, download and install Visual Studio Code from the VSCode website, and then open VSCode. Install the Python extension by navigating to the Extensions view (Ctrl+Shift+X or Cmd+Shift+X on macOS), searching for “Python” by Microsoft, and clicking “Install.” After that, you can verify pip is installed by running pip –version in the terminal. If it’s not installed, you can run python -m ensurepip –upgrade to install it. You can now install any required Python packages using pip, for example, pip install requests.

For project isolation, it’s recommended to use a virtual environment. To create one, run python -m venv venv in the terminal, then activate it with .\venv\Scripts\activate on Windows or source venv/bin/activate on macOS/Linux. With the virtual environment active, install any dependencies needed for your project using pip. To deactivate, simply type deactivate. You can run your Python code by creating a .py file in VSCode and running it via the terminal or by right-clicking it and selecting “Run Python File in Terminal.” This setup ensures you have everything to start coding with Python in VSCode.

Note: To install TensorFlow on Windows, use Python 3.11. Create a virtual environment and install TensorFlow with pip install tensorflow pandas numpy requests sci-kit-learn flask. Switching to Python 3.11 solved the compatibility issue.

pip installation guide

With these prerequisites in place, you’ll be well-equipped to start building your AI-powered crypto portfolio rebalancing tool. Let’s dive in!


File Structure of the Crypto Portfolio Rebalancer

Here is the file structure for the Crypto Portfolio Rebalancer project:

/project-directory

    /templates

        index.html

    /static

        script.js

    app.py

    rebalance.py

file structure

Step 1. Crypto Portfolio Rebalancing Code Script

In this section, we’ll delve into rebalance.py, the key script that powers our AI-powered crypto portfolio rebalancing tool. We’ll explore the essential imports, functions, and logic that make this program work.

import requests

import numpy as np

import tensorflow as tf

from tensorflow.keras.models import Sequential

from tensorflow.keras.layers import LSTM, Dense

from sklearn.preprocessing import MinMaxScaler

# Step 1: Fetch Historical Data Using CoinGecko API

def fetch_historical_data(crypto_id, currency='usd', days="90", api_key=None):

    url = f"

    params = {'vs_currency': currency, 'days': days}

    headers = {'Authorization': f'Bearer {api_key}'} if api_key else {}

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

    data = response.json()

    prices = [price[1] for price in data['prices']]

    return prices

# Step 2: Preprocess the Data

def preprocess_data(prices, sequence_length=30):

    scaler = MinMaxScaler()

    prices = np.array(prices).reshape(-1, 1)

    scaled_prices = scaler.fit_transform(prices)

    sequences = []

    targets = []

    for i in range(len(scaled_prices) - sequence_length):

        sequences.append(scaled_prices[i:i + sequence_length])

        targets.append(scaled_prices[i + sequence_length])

    return np.array(sequences), np.array(targets), scaler

# Step 3: Build and Train the LSTM Model

def build_lstm_model(input_shape):

    model = Sequential([

        LSTM(50, return_sequences=True, input_shape=input_shape),

        LSTM(50),

        Dense(1)

    ])

    model.compile(optimizer="adam", loss="mse")

    return model

# Step 4: Predict Future Prices Using LSTM Model

def predict_price(model, sequences, scaler):

    # Predict the next price

    last_sequence = sequences[-1].reshape(1, -1, 1)

    predicted_price_scaled = model.predict(last_sequence)

    # Inverse transform to get the actual price

    predicted_price = scaler.inverse_transform(predicted_price_scaled)

    return float(predicted_price[0][0])  # Convert to standard float

# Step 5: Rebalance the Portfolio

def rebalance_portfolio(current_allocation, predicted_prices, target_allocation):

    # Calculate the current total value of the portfolio

    current_value = sum(current_allocation)

   # Calculate target values based on current total value and target allocation percentages

    target_values = [current_value * ta for ta in target_allocation]

   # Calculate adjustments required to reach target values

    adjustments = []

    for current, target, predicted in zip(current_allocation, target_values, predicted_prices):

        # Adjust the current allocation based on predicted prices to meet the target allocation

        adjusted_value = target / predicted

        adjustments.append(adjusted_value - current)

    # Round adjustments and predicted prices to 3 decimal places for consistency

    adjustments = [round(adj, 3) for adj in adjustments]

    predicted_prices = [round(price, 3) for price in predicted_prices]

    return adjustments, predicted_prices

In summary, rebalance.py is designed to fetch historical price data, preprocess it for model training, build and train an LSTM model to predict future prices, and then use these predictions to rebalance a cryptocurrency portfolio according to target allocations. Each step is critical for the overall functionality of the rebalancing tool, ensuring that the portfolio is aligned with future market predictions. This results in a dynamic and effective portfolio management strategy powered by AI.


Step 2. Build the Frontend User Interface

Here, we’ll create the HTML and CSS for the user interface (UI) that allows users to input their portfolio and target allocation.

HTML (index.html)

    

    

    Crypto Portfolio Rebalancer

    

    

        body {

            font-family: Arial, sans-serif;

            background-color: #f4f4f4;

            margin: 0;

            padding: 0;

        }

        .container {

            max-width: 800px;

            margin: 50px auto;

            background: white;

            padding: 20px;

            box-shadow: 0 0 10px rgba(0,0,0,0.1);

            border-radius: 8px;

        }

        h1 {

            text-align: center;

            color: #333;

        }

        .current-prices {

            display: flex;

            justify-content: space-around;

            margin-bottom: 20px;

        }

        .current-prices div {

            text-align: center;

        }

        .current-prices i {

            font-size: 2em;

            margin-bottom: 10px;

        }

        form {

            display: flex;

            flex-direction: column;

        }

        label {

            margin: 10px 0 5px;

            color: #555;

        }

        input {

            padding: 10px;

            margin-bottom: 20px;

            border: 1px solid #ccc;

            border-radius: 4px;

        }

        button {

            padding: 15px;

            color: white;

            background-color: #007bff;

            border: none;

            border-radius: 4px;

            cursor: pointer;

            font-size: 16px;

        }

        button:hover {

            background-color: #0056b3;

        }

        #results {

            margin-top: 20px;

        }

        #results h3 {

            color: #333;

        }

        #results p {

            color: #555;

        }

        #loading {

            display: none;

            text-align: center;

            color: #555;

        }

        .progress-bar-container {

            width: 100%;

            background-color: #f3f3f3;

            border-radius: 4px;

            margin: 20px 0;

        }

        .progress-bar {

            width: 0;

            height: 20px;

            background-color: #007bff;

            border-radius: 4px;

        }

    

    

        

        

            

                

                

Loading BTC price...

            

            

                

                

Loading ETH price...

            

        

        

            

            

            

            

            

            

            

            

            

        

        

Rebalancing, please wait...

        

            

        

        

    

    


Step 3. Add Interactivity with JavaScript

To make the UI functional, we’ll connect it to the Python backend for predictions and portfolio rebalancing using JavaScript.

JavaScript File (script.js)

document.addEventListener("DOMContentLoaded", async function() {

    const response = await fetch("/current_prices");

    const data = await response.json();

   

    document.getElementById("current-btc-price").innerText = `Current BTC Price: $${data.btc_price.toFixed(3)}`;

    document.getElementById("current-eth-price").innerText = `Current ETH Price: $${data.eth_price.toFixed(3)}`;

});

 

document.getElementById("rebalance-form").addEventListener("submit", async function (event) {

    event.preventDefault();

    // Show the loading message

    document.getElementById("loading").style.display = "block";

    document.getElementById("results").innerHTML = "";

    // Reset the progress bar

    const progressBar = document.getElementById("progress-bar");

    progressBar.style.width = "0%";

 

    const btcAllocation = parseFloat(document.getElementById("btc-allocation").value);

    const ethAllocation = parseFloat(document.getElementById("eth-allocation").value);

    const targetBTC = parseFloat(document.getElementById("target-btc").value) / 100;

    const targetETH = parseFloat(document.getElementById("target-eth").value) / 100;

   

    const response = await fetch("/rebalance", {

        method: "POST",

        headers: {

            "Content-Type": "application/json",

        },

        body: JSON.stringify({

            current_allocation: [btcAllocation, ethAllocation],

            target_allocation: [targetBTC, targetETH],

        }),

    });

    const result = await response.json();

    console.log(result); // Log the result to see if data is returned

    displayResults(result.adjustments, result.predicted_prices);

    // Hide the loading message

    document.getElementById("loading").style.display = "none";

});

function updateProgressBar(progress) {

    const progressBar = document.getElementById("progress-bar");

    progressBar.style.width = `${progress}%`;

}

function displayResults(adjustments, predicted_prices) {

    const resultsDiv = document.getElementById("results");

    resultsDiv.innerHTML = `

        

Rebalancing Suggestions

        

Adjust BTC by: $${adjustments[0].toFixed(3)}

        

Adjust ETH by: $${adjustments[1].toFixed(3)}

        

Predicted Prices

        

Predicted BTC Price: $${predicted_prices[0].toFixed(3)}

        

Predicted ETH Price: $${predicted_prices[1].toFixed(3)}

    `;

}

// Example of updating the progress bar incrementally

async function simulateProgress() {

    for (let i = 0; i

        updateProgressBar(i);

        await new Promise(resolve => setTimeout(resolve, 100)); // Simulate training time

    }

}

// Call simulateProgress when the form is submitted

document.getElementById("rebalance-form").addEventListener("submit", async function (event) {

    event.preventDefault();

    // Show the loading message

    document.getElementById("loading").style.display = "block";

    document.getElementById("results").innerHTML = "";

    // Reset the progress bar

    const progressBar = document.getElementById("progress-bar");

    progressBar.style.width = "0%";

    const btcAllocation = parseFloat(document.getElementById("btc-allocation").value);

    const ethAllocation = parseFloat(document.getElementById("eth-allocation").value);

    const targetBTC = parseFloat(document.getElementById("target-btc").value) / 100;

    const targetETH = parseFloat(document.getElementById("target-eth").value) / 100;

    // Start simulating progress

    simulateProgress();

    const response = await fetch("/rebalance", {

        method: "POST",

        headers: {

            "Content-Type": "application/json",

        },

        body: JSON.stringify({

            current_allocation: [btcAllocation, ethAllocation],

            target_allocation: [targetBTC, targetETH],

        }),

    });

    const result = await response.json();

    console.log(result); // Log the result to see if data is returned

    displayResults(result.adjustments, result.predicted_prices);

    // Hide the loading message

    document.getElementById("loading").style.display = "none";

});


Step 4. Create the Python Backend

The backend will handle the prediction and rebalancing logic. Use Flask to create an API that connects the JavaScript frontend to the Python logic.

Flask Server (app.py)

from flask import Flask, request, jsonify, render_template

from rebalance import fetch_historical_data, preprocess_data, build_lstm_model, predict_price, rebalance_portfolio

from tqdm import tqdm

app = Flask(__name__)

# Serve the index.html file

@app.route("

def home():

    return render_template('index.html')

@app.route('/current_prices', methods=['GET'])

def current_prices():

    api_key = 'CG-api_key '

    btc_prices = fetch_historical_data('bitcoin', api_key=api_key)

    eth_prices = fetch_historical_data('ethereum', api_key=api_key)

    current_btc_price = round(btc_prices[-1], 3)  # Latest BTC price

    current_eth_price = round(eth_prices[-1], 3)  # Latest ETH price

    return jsonify({"btc_price": current_btc_price, "eth_price": current_eth_price})

@app.route('/rebalance', methods=['POST'])

def rebalance():

    data = request.json

    current_allocation = data['current_allocation']

    target_allocation = data['target_allocation']

   # Fetching data from CoinGecko API

    api_key = 'CG-k63f6X3RG6T7MGVf6BdfHWh1'

    btc_prices = fetch_historical_data('bitcoin', api_key=api_key)

    eth_prices = fetch_historical_data('ethereum', api_key=api_key)

   # Preprocessing data

    btc_sequences, btc_targets, btc_scaler = preprocess_data(btc_prices)

    eth_sequences, eth_targets, eth_scaler = preprocess_data(eth_prices)

   

    # Build and train model

    btc_model = build_lstm_model((btc_sequences.shape[1], btc_sequences.shape[2]))

    eth_model = build_lstm_model((eth_sequences.shape[1], eth_sequences.shape[2]))

   # Training BTC model with progress bar

    for epoch in tqdm(range(10), desc="Training BTC Model"):

        btc_model.fit(btc_sequences, btc_targets, epochs=1, batch_size=32, verbose=0)

   # Training ETH model with progress bar

    for epoch in tqdm(range(10), desc="Training ETH Model"):

        eth_model.fit(eth_sequences, eth_targets, epochs=1, batch_size=32, verbose=0)

   # Predict prices using the trained models

    btc_predicted_price = predict_price(btc_model, btc_sequences, btc_scaler)

    eth_predicted_price = predict_price(eth_model, eth_sequences, eth_scaler)

   # Log the predicted prices to ensure they're being generated

    print(f"Predicted BTC Price: {btc_predicted_price}")

    print(f"Predicted ETH Price: {eth_predicted_price}")

   predicted_prices = [btc_predicted_price, eth_predicted_price]

   # Rebalance portfolio

    adjustments, rounded_predicted_prices = rebalance_portfolio(current_allocation, predicted_prices, target_allocation)

   return jsonify({"adjustments": adjustments, "predicted_prices": rounded_predicted_prices})

if __name__ == '__main__':

    app.run(debug=True)


Step 5. Run the Application

  1. Run app.py to start the Flask server backend.
  2. Open index.html in your browser to open the front end:
  3. Enter your portfolio details and target allocation percentages, and click “Rebalance Portfolio.”
  4. View results: The UI will display the rebalancing suggestions based on your input and the AI’s predictions.

Crypto Rebalancer


Conclusion

Congratulations! You’ve developed an AI-powered crypto portfolio rebalancing tool that integrates the CoinGecko API and TensorFlow. This dynamic tool allows us to fetch historical data, analyze real-time data using LSTM, and predict cryptocurrency prices and trends. It also automates the rebalancing of your crypto portfolio by adjusting allocations according to target percentages. Finally, our custom frontend enables us to visualize and analyze the results effectively.

Unlock OHLC chart data - CoinGecko API

What’s Next? Expanding Functionality

This guide serves as a foundation for building a crypto portfolio rebalancing tool, but there are several ways to extend its functionality. Adding more cryptocurrencies will expand the range of assets in your portfolio management. You can also improve prediction accuracy by experimenting with different machine learning models and fine-tuning hyperparameters, which could result in more precise rebalancing decisions. Additionally, integrating live crypto exchange APIs like Binance or Coinbase Pro can take your tool to the next level, enabling automated rebalancing in real-time based on market movements. These enhancements can transform your tool into a more powerful and dynamic solution tailored to your unique crypto investing strategy.


If you found this article helpful, you might enjoy our step-by-step guide on backtesting crypto trading strategies with Python.

More From Author

ChatGPT builds a $1,000 stock portfolio for 2025

ChatGPT builds a $1,000 stock portfolio for 2025

Steven Fiorillo profile picture

Dividend Harvesting Portfolio Week 199: $19,900 Allocated, $1,908.79 Projected Dividends

Leave a Reply

Your email address will not be published. Required fields are marked *