Implementing MACD strategy using Qt/C++ using Zerodha API and deploying in AWS for High Frequency Trading.

Implementing MACD strategy using Qt/C++ using Zerodha API and deploying in AWS for High Frequency Trading.

Overview

In this article we will:

  • Build a High Frequency Trading application written using the Qt/C++ cross-platform framework.
  • We will use Zerodha's Kite API for this.
  • Discuss why it is a better choice over a Python based stack for this use case
  • Present an implementation of the MACD strategy in Qt/C++
  • Discuss deployment of the code on AWS.

Why Qt and C++ are Ideal for High-Frequency Trading Over Python

High-frequency trading (HFT) is a demanding segment of the financial market where transactions are executed within microseconds. The choice of programming language and framework is critical for achieving optimal performance. In this post, we'll explore why Qt and C++ are preferred over Python for HFT, explain the Moving Average Convergence Divergence (MACD) indicator, and provide an example of implementing a MACD trading strategy using C++. We'll also discuss the benefits of deploying this setup on AWS to minimize latency.

Why Choose Qt and C++ for High-Frequency Trading?

  1. Performance and Speed:
  2. Low-Level System Access:
  3. Concurrency and Multithreading:
  4. Comprehensive Libraries and Frameworks:

Understanding MACD

The Moving Average Convergence Divergence (MACD) is a widely used technical analysis tool for identifying trends in stock prices. It consists of three main components:

  • MACD Line: The difference between the 12-period and 26-period Exponential Moving Averages (EMA).
  • Signal Line: A 9-period EMA of the MACD line.
  • Histogram: The difference between the MACD line and the Signal line.

A basic MACD trading strategy involves:

  • Buy Signal: When the MACD line crosses above the Signal line.
  • Sell Signal: When the MACD line crosses below the Signal line.

Implementing MACD Strategy in Qt/C++

Below is an example of a MACD strategy for trading NIFTY futures using Zerodha's REST API in Qt/C++.

Understanding the Methods in Our High-Frequency Trading (HFT) Application

In our HFT application using Qt and C++, we've implemented a MACD (Moving Average Convergence Divergence) trading strategy for NIFTY futures using Zerodha's REST API. Let's dive into each method used in our?ZerodhaTraderclass to understand their roles and functionality.

1.?Constructor:?ZerodhaTrader

The constructor initializes the?ZerodhaTrader?object with the API key and access token required for authentication with Zerodha's REST API.

Functionality:

  • Initializes a?"QNetworkAccessManager"?object to handle HTTP requests.

ZerodhaTrader(const QString &apiKey, const QString &accessToken, QObject *parent = nullptr)
    : QObject(parent), apiKey(apiKey), accessToken(accessToken) {
    manager = new QNetworkAccessManager(this);
}        

2.?Method:?fetchHistoricalData

This method fetches historical price data for a specified instrument and date range from Zerodha's API.

Functionality:

  • Constructs the API URL with query parameters for date range.
  • Sets up the HTTP request headers with API key and access token.
  • Initiates the GET request to fetch historical data.

void fetchHistoricalData(const QString &instrumentToken, const QString &fromDate, const QString &toDate) {
    QUrl url("https://api.kite.trade/instruments/historical/" + instrumentToken + "/minute");
    QUrlQuery query;
    query.addQueryItem("from", fromDate);
    query.addQueryItem("to", toDate);
    url.setQuery(query);

    QNetworkRequest request(url);
    request.setRawHeader("X-Kite-Version", "3");
    request.setRawHeader("Authorization", "token " + apiKey + ":" + accessToken);

    QNetworkReply *reply = manager->get(request);
    connect(reply, &QNetworkReply::finished, this, &ZerodhaTrader::onHistoricalDataFetched);
}        

3. Slot:?onHistoricalDataFetched()

This slot is called when the historical data fetch request is completed.

  • Reads the response and checks for errors.
  • Parses the JSON response to extract historical close prices.
  • Calls the?calculateMACD?method to process the fetched data.

void onHistoricalDataFetched() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if (reply->error() == QNetworkReply::NoError) {
        QByteArray response = reply->readAll();
        QJsonDocument jsonDoc = QJsonDocument::fromJson(response);
        QJsonObject jsonObj = jsonDoc.object();
        QJsonArray data = jsonObj["data"].toArray();

        QVector<double> closePrices;
        for (const QJsonValue &value : data) {
            closePrices.append(value.toObject()["close"].toDouble());
        }

        calculateMACD(closePrices);
    } else {
        qWarning() << "Error fetching historical data:" << reply->errorString();
    }
    reply->deleteLater();
}        

4.?Method:?calculateMACD

Functionality:

  • Defines the windows for short-term (12 periods), long-term (26 periods), and signal (9 periods) EMAs.
  • Iterates over the price data to compute the MACD line and Signal line.
  • Detects buy and sell signals based on the MACD histogram.

void calculateMACD(const QVector<double> &prices) {
    int shortWindow = 12;
    int longWindow = 26;
    int signalWindow = 9;

    QVector<double> macdLine;
    QVector<double> signalLine;
    QVector<double> macdHistogram;

    for (int i = 0; i < prices.size(); ++i) {
        if (i >= longWindow - 1) {
            double shortEma = calculateEMA(prices, i - shortWindow + 1, i, shortWindow);
            double longEma = calculateEMA(prices, i - longWindow + 1, i, longWindow);
            macdLine.append(shortEma - longEma);

            if (i >= longWindow + signalWindow - 2) {
                double signalEma = calculateEMA(macdLine, i - signalWindow + 1, i, signalWindow);
                signalLine.append(signalEma);
                macdHistogram.append(macdLine[i] - signalLine.last());

                if (macdHistogram.last() > 0 && macdHistogram[macdHistogram.size() - 2] <= 0) {
                    qDebug() << "Buy signal at index" << i;
                } else if (macdHistogram.last() < 0 && macdHistogram[macdHistogram.size() - 2] >= 0) {
                    qDebug() << "Sell signal at index" << i;
                }
            }
        }
    }
}        

5. Helper Method:?calculateEMA

Functionality:

  • This method calculates the Exponential Moving Average (EMA) for a given window.

double calculateEMA(const QVector<double> &data, int start, int end, int window) {
    double multiplier = 2.0 / (window + 1);
    double ema = data[start];
    for (int i = start + 1; i <= end; ++i) {
        ema = ((data[i] - ema) * multiplier) + ema;
    }
    return ema;
}        

Deploying on AWS to Minimize Latency

Deploying your HFT system on AWS can significantly reduce latency, enhancing the performance of your trading algorithms. Here's a step-by-step guide to deploying your Qt/C++ application on AWS:

  1. Choose the Right EC2 Instance: Opt for instances with high network performance and low latency, such as the?c5n?series.
  2. Set Up Your Environment: Install necessary libraries and tools on your EC2 instance, such as Qt, GCC, and other dependencies.
  3. Deploy Your Application: Push your code to the instance. You can use a private Github repo to accomplish this. Ensure you have setup the API keys and other environment variables securely.
  4. Optimize for Latency: Use AWS Direct Connect to establish a dedicated network connection between your HFT system and financial exchanges. Leverage AWS regions and availability zones close to the financial hubs. Mumbai/Chennai would be the right choice for us
  5. Monitor and Scale: Use AWS CloudWatch to monitor the performance and health of your application.

By leveraging Qt and C++ for your HFT system, you gain the performance and control necessary for executing trades swiftly and efficiently. Deploying this setup on AWS further enhances your system’s performance by reducing latency and providing a robust, scalable infrastructure.

Abhishek Kumar

Computing Engineering and Mathematics Undergrad | Ex- Chegg Expert | Problem Solver | Django Developer | DU'25

3 个月

This article is very interesting bcz in this article Manish Chakravarty discuss how to build a High Frequency Trading application written using the Qt/C++ cross-platform framework and with using Zerodha's Kite API and discuss why it is a better choice over a python based stack to use case and implementation of the MACD strategy in Qt/C++ and discuss how to deployment on AWS. Keep posting Manish Chakravarty ????????

回复
Seyyed Mohammad Soheil Mostafavi

Qt | QML | C++ | Scripting | Unity | Software Engineer

6 个月

That's amazing ??

回复
Brahmadath S Mampazhassery

Engineering Consultant || Full Stack Lead Developer || ex-DXC || ex-CGI Inc || Certified SAFe 5 Practitioner Engineering

7 个月

Interesting!

回复
M.ASHFAQULLA SHARIF

Embedded C | C++ STL | Qt/QML | Bash | Device Drivers | e-linux |

9 个月

Very Interesting!Manish Chakravarty

回复

要查看或添加评论,请登录

社区洞察

其他会员也浏览了