DEV Community

Cover image for Integrating Nigerian (NG) Stock Market Data via iTick API – Real-time Quotes & Historical K-Line
San Si wu
San Si wu

Posted on

Integrating Nigerian (NG) Stock Market Data via iTick API – Real-time Quotes & Historical K-Line

As a developer who has worked extensively with overseas financial data APIs, I recently took on a project requiring access to Nigerian Stock Exchange (NGX / NSENG) data. I encountered quite a few challenges and learned some valuable lessons along the way.

Unlike the mature API ecosystems of A-share or U.S. markets, documentation and Chinese-language resources for the Nigerian market are almost non-existent — even English materials are very limited. In this article, I’ll share my real-world experience using the iTick API to fetch real-time quotes and historical K-line data for NG stocks. I hope this can save time for others facing similar needs.

1. Preparation: API Setup Basics

1.1 Registration & API Token

iTick is currently one of the more reliable local financial data providers for the Nigerian market, offering both real-time and historical data.

First, go to the official website Register a developer account, complete email verification, and you’ll receive your API_TOKEN (sometimes still called API_KEY in older docs). This token is the core credential for all subsequent API calls — keep it secure.

1.2 Environment Setup

I’m using Python 3.8+. You only need two main libraries for basic usage:

pip install requests pandas mplfinance
Enter fullscreen mode Exit fullscreen mode
  • requests — for HTTP calls
  • pandas — for data structuring
  • mplfinance — optional, for candlestick charting

2.实战1 – Fetching Real-time Quotes

Current endpoint (2026):

GET /stock/quote?region=NG&code=xxxx

Important: The market code for Nigeria is now NG (not NSENG anymore).

Clean & Reusable Implementation

import requests
import time
from typing import Dict, Optional
import pandas as pd


class ITickNGAPI:
    """
    iTick API wrapper for Nigerian (NG) stock market data – 2026 version
    """
    def __init__(self, token: str):
        self.base_url = "https://api.itick.org"
        self.token = token
        self.headers = {
            "accept": "application/json",
            "token": self.token
        }

    def get_realtime_quote(self, stock_code: str) -> Optional[Dict]:
        """
        Get real-time quote for a single stock
        :param stock_code: e.g. "DANGCEM"
        :return: quote dictionary or None if failed
        """
        for retry in range(3):
            try:
                url = f"{self.base_url}/stock/quote"
                params = {
                    "region": "NG",
                    "code": stock_code.upper()      # must be uppercase
                }

                response = requests.get(
                    url,
                    headers=self.headers,
                    params=params,
                    timeout=10
                )

                if response.status_code == 200:
                    result = response.json()
                    if result.get("code") == 0 and "data" in result:
                        quote = result["data"]
                        return {
                            "Symbol": quote["s"],
                            "Last Price": quote["ld"],
                            "Open": quote["o"],
                            "High": quote["h"],
                            "Low": quote["l"],
                            "Volume": quote["v"],
                            "Change": quote["ch"],
                            "Change %": quote["chp"],
                            "Timestamp": quote["t"],
                            "Trading Status": quote["ts"]   # 0=normal, 1=suspended, etc.
                        }
                    else:
                        print(f"No real-time data found for {stock_code} or API error")
                        return None
                else:
                    print(f"Request failed – status {response.status_code} – retry {retry+1}")
                    time.sleep(1.5)

            except requests.exceptions.Timeout:
                print(f"Timeout – retry {retry+1}")
                time.sleep(1.5)
            except Exception as e:
                print(f"Exception: {str(e)}")
                return None

        return None


# ────────────────────────────────────────────────
if __name__ == "__main__":
    MY_TOKEN = "your_itick_token_here"
    api = ITickNGAPI(MY_TOKEN)

    quote = api.get_realtime_quote("DANGCEM")
    if quote:
        print("=== Nigerian (NG) Real-time Quote ===")
        for k, v in quote.items():
            print(f"{k: <14}: {v}")
Enter fullscreen mode Exit fullscreen mode

Sample Output

=== Nigerian (NG) Real-time Quote ===
Symbol        : DANGCEM
Last Price    : 312.5
Open          : 310.0
High          : 315.0
Low           : 308.0
Volume        : 156800
Change        : 2.5
Change %      : 0.81
Timestamp     : 1765526889000
Trading Status: 0
Enter fullscreen mode Exit fullscreen mode

3.实战2 – Fetching Historical K-Line Data

Current endpoint (2026):

GET /stock/kline?region=NG&code=xxxx&kType=8&limit=100

Common kType values:

  • 8 → Daily
  • 9 → Weekly
  • 10 → Monthly
  • 1~7 → Minute bars (1min, 5min, 15min, etc.)

Implementation – Historical K-lines

# Add this method to the ITickNGAPI class above

def get_historical_klines(
    self,
    stock_code: str,
    k_type: int = 8,            # 8 = daily
    limit: int = 100,
    end_timestamp: int = None   # optional end time (ms)
) -> Optional[pd.DataFrame]:
    """
    Fetch historical k-line data
    """
    try:
        url = f"{self.base_url}/stock/kline"
        params = {
            "region": "NG",
            "code": stock_code.upper(),
            "kType": k_type,
            "limit": limit
        }
        if end_timestamp:
            params["et"] = end_timestamp

        response = requests.get(
            url, headers=self.headers, params=params, timeout=12
        )

        if response.status_code == 200:
            result = response.json()
            if result.get("code") == 0 and isinstance(result.get("data"), list):
                data = result["data"]
                if not data:
                    print(f"No historical data for {stock_code}")
                    return None

                df = pd.DataFrame(data)
                df = df[["t", "o", "h", "l", "c", "v"]]
                df.rename(columns={
                    "t": "timestamp_ms",
                    "o": "Open",
                    "h": "High",
                    "l": "Low",
                    "c": "Close",
                    "v": "Volume"
                }, inplace=True)

                # Convert UTC ms → Beijing time
                df["datetime"] = pd.to_datetime(df["timestamp_ms"], unit="ms", utc=True)
                df["datetime"] = df["datetime"].dt.tz_convert("Asia/Shanghai")
                df["date"] = df["datetime"].dt.strftime("%Y-%m-%d %H:%M:%S")

                # Reorder columns
                df = df[["date", "Open", "High", "Low", "Close", "Volume", "timestamp_ms"]]

                return df
            else:
                print("Unexpected API response format")
                return None
        else:
            print(f"K-line request failed – status {response.status_code}")
            return None

    except Exception as e:
        print(f"Error fetching k-line: {str(e)}")
        return None


# ────────────────────────────────────────────────
if __name__ == "__main__":
    # ... (api instance already created)

    df = api.get_historical_klines("DANGCEM", k_type=8, limit=60)

    if df is not None:
        print("\n=== Historical Daily K-line (first 5 rows) ===")
        print(df.head())

        # Optional: candlestick chart
        import mplfinance as mpf
        plot_df = df.copy()
        plot_df["date"] = pd.to_datetime(plot_df["date"])
        plot_df.set_index("date", inplace=True)

        mpf.plot(
            plot_df,
            type='candle',
            volume=True,
            title='DANGCEM (NG) Daily',
            ylabel='Price (NGN)',
            figratio=(16,9),
            style='yahoo'
        )
Enter fullscreen mode Exit fullscreen mode

4. Important Notes (2026 Edition)

  • Market code is NGnot NSENG anymore
  • Authentication now uses plain token header (no more Bearer api_key:secret)
  • All timestamps are millisecond Unix timestamps in UTC
  • Free tier has rate limits — add sleep or upgrade plan for production use
  • Prices are in Nigerian Naira (NGN)

5. Summary & Recommendations

Integrating Nigerian stock data is definitely less plug-and-play than U.S. or Chinese markets, but once you understand the quirks (market code change, timestamp handling, rate limits), it becomes manageable.

Key takeaways:

  • Always implement timeout + retry logic
  • Convert timestamps properly (UTC → your target timezone)
  • Use pandas early — it makes data cleaning and visualization much easier

Disclaimer: This article is for technical reference only. It does not constitute investment advice. Investing involves risks.

Official Documentation
https://docs.itick.org/rest-api/stocks/stock-kline
GitHub Organization
https://github.com/itick-org/

Hope this helps someone trying to access NGX data in 2026!
Feel free to leave questions or share your own experience in the comments.

Good luck with your project!

Top comments (0)