DEV Community

Cover image for Python 3 Steps to Real-Time Forex API: WebSocket + REST Full Code (iTick Example)
San Si wu
San Si wu

Posted on

Python 3 Steps to Real-Time Forex API: WebSocket + REST Full Code (iTick Example)

If you've worked on quantitative trading or forex-related tool development, you've likely encountered this problem: you just need to get real-time quotes for a few major currency pairs, but you get stuck on the technical stack selection. HTTP polling has high latency, and you're not sure where to start with WebSocket integration. This article will guide you through connecting to real-time forex market data in Python in three simple steps—code that you can copy directly into your project and run.

Why Use WebSocket Instead of HTTP Polling

Before writing code, let's spend 30 seconds understanding a core question: Why use WebSocket instead of HTTP polling for real-time forex market data?

The forex market sees over $6 trillion in daily trading volume, with price fluctuations occurring at the millisecond level. With HTTP polling, the client actively asks the server "What's the current price?" at regular intervals. Latency typically ranges from 300-800 milliseconds, and frequent requests can easily trigger rate limiting.

In contrast, once WebSocket establishes a persistent bidirectional communication channel, the server actively pushes new price data as it becomes available, with latency as low as 5-50 milliseconds. For quantitative strategies that need to respond to market volatility in real time, this difference is decisive.

Simply put: HTTP polling is like refreshing a webpage every few seconds, while WebSocket is like an always-on live stream—you see the numbers change the instant they update.

Prerequisites

1. Install Required Python Libraries

You only need two libraries, keeping things clean and simple:

pip install websocket-client requests
Enter fullscreen mode Exit fullscreen mode

Python version 3.8 or higher is sufficient.

2. Obtain API Key

You'll need a data interface that supports real-time forex market data. Taking iTick API as an example, register an account on their official website, and you'll find your API Key in the console. The free tier provides enough quota for daily development use.

Step 1: REST API for Real-Time Snapshots

Before establishing a WebSocket connection, REST API is ideal for quickly querying current prices or retrieving historical K-line data.

Real-Time Quote

This endpoint returns forex quotes with order book information. The ld (Latest Deal) field represents the most recent transaction price.

import requests

url = "https://api.itick.org/forex/quote?region=GB&code=EURUSD"
headers = {
    "accept": "application/json",
    "token": "YOUR_API_KEY"   # Replace with your own Token
}

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

if response.status_code == 200:
    data = response.json()
    print(f"EUR/USD Latest Price: {data.get('data', {}).get('ld')}")
else:
    print(f"Request failed: {response.text}")
Enter fullscreen mode Exit fullscreen mode

Batch Real-Time Quotes

When monitoring multiple currency pairs using REST, the batch endpoint offers better efficiency—you can retrieve the latest prices for multiple currency pairs in a single request.

def fetch_batch_quotes(symbols):
    """Batch fetch real-time quotes for multiple currency pairs"""
    codes = ",".join(symbols)
    url = f"https://api.itick.org/forex/quotes?region=GB&codes={codes}"
    headers = {"accept": "application/json", "token": "YOUR_API_KEY"}

    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        quotes = response.json().get('data', {})
        for symbol, quote in quotes.items():
            print(f"{symbol} Latest Price: {quote.get('ld')}")
    else:
        print(f"Batch request failed: {response.text}")

fetch_batch_quotes(["EURUSD", "GBPUSD", "USDJPY"])
Enter fullscreen mode Exit fullscreen mode

Historical K-Line Query (Historical Candlesticks)

For backtesting or supplementing historical data, use the /forex/kline endpoint to retrieve OHLCV data. The kType parameter ranges from 1-10, covering minute bars to monthly K-lines.

def fetch_historical_bars(symbol, ktype=1, limit=100):
    url = f"https://api.itick.org/forex/kline?region=GB&code={symbol}&kType={ktype}&limit={limit}"
    headers = {"accept": "application/json", "token": "YOUR_API_KEY"}

    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        bars = response.json().get('data', [])
        print(f"Retrieved {len(bars)} K-line bars")
        return bars
    else:
        print(f"Failed to retrieve K-lines: {response.text}")
        return []

bars = fetch_historical_bars("EURUSD", ktype=1, limit=100)
Enter fullscreen mode Exit fullscreen mode

Real-Time Order Book and Trade Queries

If your strategy requires more granular data (such as viewing buy/sell order depth or individual tick-by-tick trades), iTick also provides these separate REST endpoints:

  • Real-Time Order Book: GET /forex/depth?region=GB&code=EURUSD
  • Real-Time Trades: GET /forex/tick?region=GB&code=EURUSD

Usage is essentially the same—just change the URL.

Step 2: WebSocket Real-Time Streaming

WebSocket is the better choice when you need to continuously track market changes.

iTick's forex WebSocket address is wss://api.itick.org/forex, which is separate from the stock endpoint wss://api.itick.org/stock.

import websocket
import json

WS_URL = "wss://api.itick.org/forex"
SYMBOLS = ["EURUSD", "USDJPY"]


def on_message(ws, message):
    data = json.loads(message)
    symbol = data.get('symbol')
    price = data.get('price')
    print(f"{symbol} Latest Price: {price}")


def on_open(ws):
    print("Connection established, subscribing to currency pairs...")
    subscribe_msg = {
        "action": "subscribe",
        "symbols": SYMBOLS
    }
    ws.send(json.dumps(subscribe_msg))


def on_error(ws, error):
    print(f"Connection error: {error}")


def on_close(ws, close_status_code, close_msg):
    print("Connection closed")


ws = websocket.WebSocketApp(
    WS_URL,
    on_open=on_open,
    on_message=on_message,
    on_error=on_error,
    on_close=on_close
)

print("Connecting to forex market data server...")
ws.run_forever()
Enter fullscreen mode Exit fullscreen mode

Run this code, and the console will start outputting real-time market data.

Step 3: Production-Grade WebSocket Integration (With Auto-Reconnection)

A common issue in production environments is unexpected disconnections (network glitches, server restarts, firewall idle timeouts). Your program must be able to automatically recover, otherwise your strategy will stall midway.

Below is a reconnection mechanism built on top of WebSocket subscription, while maintaining heartbeat logic:

import websocket
import json
import time

WS_URL = "wss://api.itick.org/forex"
SYMBOLS = ["EURUSD", "USDJPY", "GBPUSD"]
RECONNECT_DELAY = 3


def on_message(ws, message):
    data = json.loads(message)
    symbol = data.get('symbol')
    price = data.get('price')
    print(f"{symbol} Latest Price: {price}")


def on_open(ws):
    print("WebSocket connection established")
    subscribe_msg = {
        "action": "subscribe",
        "symbols": SYMBOLS
    }
    ws.send(json.dumps(subscribe_msg))
    print(f"Subscribed to: {SYMBOLS}")

    # Heartbeat thread (some providers require active heartbeat packets)
    def send_heartbeat():
        import threading
        while ws.sock and ws.sock.connected:
            time.sleep(30)
            try:
                ws.send(json.dumps({"type": "ping"}))
                print("Heartbeat sent")
            except:
                break

    threading.Thread(target=send_heartbeat, daemon=True).start()


def on_error(ws, error):
    print(f"WebSocket error: {error}")


def on_close(ws, close_status_code, close_msg):
    print(f"Connection closed (code: {close_status_code}), reconnecting in {RECONNECT_DELAY} seconds...")
    time.sleep(RECONNECT_DELAY)
    start_ws()


def start_ws():
    ws = websocket.WebSocketApp(
        WS_URL,
        on_open=on_open,
        on_message=on_message,
        on_error=on_error,
        on_close=on_close
    )
    ws.run_forever()


if __name__ == "__main__":
    print("Forex real-time market monitoring started...")
    start_ws()
Enter fullscreen mode Exit fullscreen mode

Core reconnection logic: Calling start_ws() within on_close to rebuild the connection ensures the program can automatically recover after disconnection.

Complete Performance Combination: Historical K-Lines + Real-Time Streaming

In actual quantitative systems, WebSocket and REST are often used together: use REST to pull initial historical K-line data, then continuously receive real-time incremental updates via WebSocket.

import requests
import websocket
import json
import pandas as pd

# Step 1: REST - Retrieve historical K-lines
hist_url = "https://api.itick.org/forex/kline"
params = {"region": "GB", "code": "EURUSD", "kType": "1", "limit": 100}
headers = {"accept": "application/json", "token": "YOUR_API_KEY"}

res = requests.get(hist_url, headers=headers, params=params).json()
df = pd.DataFrame(res.get('data', []))
df['timestamp'] = pd.to_datetime(df['t'], unit='s')
print(f"Loaded {len(df)} historical K-line records")
print(df[['timestamp', 'o', 'h', 'l', 'c']].tail())

# Step 2: WebSocket - Receive real-time data
def on_message(ws, message):
    tick = json.loads(message)
    symbol = tick.get('symbol')
    price = tick.get('price')
    print(f"Real-time update: {symbol} = {price}")

ws = websocket.WebSocketApp(
    "wss://api.itick.org/forex",
    on_message=on_message,
    on_open=lambda ws: ws.send(json.dumps({"action": "subscribe", "symbols": ["EURUSD"]}))
)
print("Starting real-time data streaming...")
ws.run_forever()
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

Once you get it running, you'll discover that real-time market data integration isn't as complex as it seems. The core comes down to these three steps: set up the environment, connect via WebSocket, and write callback functions. Copy the code from Steps 2 and 3 directly into your project, modify the API address and currency pair list, and you'll basically be good to go.

For quantitative strategy development, once the data pipeline is established, everything truly begins. After building this foundational framework, you can focus your energy on more interesting tasks like model construction and signal calculation.

Reference documentation: https://blog.itick.org/quant-tools/qlib-itick-forex-stock-integration

GitHub: https://github.com/itick-org/

Top comments (0)