DEV Community

Emily
Emily

Posted on

Tick by Tick: Computing 1-Minute Forex Order Imbalance with WebSockets

I’ve been a cross-border forex trader for years, and if there’s one mistake I see over and over — both in my own past trades and in the community — it’s treating a 1-minute candle as if it’s the smallest meaningful unit of information. It isn’t. The real story unfolds inside the bar, through every single tick.

In this article, I’ll walk through how I extract a metric called order imbalance from forex tick data, why it matters for short-term trading, and how I built a reliable WebSocket pipeline to compute it in real time.

Why Tick Data? The Trader’s Requirement

Cross-border forex traders who operate on very short timeframes — holding positions for just a few minutes — need to understand whether buyers or sellers are the aggressors right now. A green 1-minute candle might be the result of genuine buying pressure, or it could be a fluke driven by low liquidity and a couple of erratic ticks. Making fast decisions based solely on candle color is essentially gambling. The real requirement is to decompose that minute into its actual buy and sell flows.

The Pain Point: Candle Charting Masks Order Flow

Most trading platforms and analysis tools still present the market in OHLC format. This format throws away the sequence of transactions and the distribution of volume across the minute. I’ve personally been burned by “false strength” candles — minutes where price ticked higher but where sell volume was actually double the buy volume. No chart pattern would warn you about that. The disconnect between what the candle shows and what the order flow reveals is a critical pain point for any serious intraday trader.

The Data: Calculating Order Imbalance

Order Imbalance = (Buy Volume - Sell Volume) / (Buy Volume + Sell Volume)

For a given minute, suppose:

Type Volume
Buy Volume 800
Sell Volume 500

Imbalance = 0.23. A positive number indicates buying pressure; negative indicates selling pressure.

I look at the sequence of imbalances over consecutive minutes. A run of increasing values often signals a shift in short-term sentiment.

Tackling the Lack of Buy/Sell Tags in Forex Ticks

Forex data providers usually don’t label trades as buys or sells. To infer direction, I compare the current tick’s price with the previous one:

  • Higher → buyer-initiated
  • Lower → seller-initiated

Consider this tiny tick sequence:

Time Price Direction
10:00:01 1.0860
10:00:04 1.0862 Buy
10:00:08 1.0858 Sell

By aggregating these labeled volumes inside fixed 1-minute windows, I produce the raw inputs for the imbalance formula.

Upgrading to a WebSocket Architecture

I initially tried fetching ticks via REST polling. It was a disaster for this use case: uneven intervals and missed ticks made the 1-minute imbalance values almost random. The clear upgrade was to adopt a WebSocket client that receives a continuous stream of tick data.

I switched to a persistent connection, caching ticks in memory and flushing the calculation at the end of each minute. This approach gave me the reliability and precision I needed. My current feed comes from AllTick’s WebSocket API, which delivers low-latency forex ticks without gaps that would ruin the aggregation.

WebSocket client example:

import websocket
import json

def on_message(ws, message):
    data = json.loads(message)

    print(
        data["symbol"],
        data["price"],
        data["volume"]
    )

def on_open(ws):
    request = {
        "symbol": "EURUSD",
        "type": "tick"
    }

    ws.send(json.dumps(request))


ws = websocket.WebSocketApp(
    "wss://api.alltick.co/ws",
    on_open=on_open,
    on_message=on_message
)

ws.run_forever()
Enter fullscreen mode Exit fullscreen mode

Minute-window aggregation:

ticks = [
    {"price": 1.0860, "volume": 100},
    {"price": 1.0862, "volume": 180},
    {"price": 1.0858, "volume": 120}
]

buy_volume = 0
sell_volume = 0

for i in range(1, len(ticks)):
    if ticks[i]["price"] > ticks[i-1]["price"]:
        buy_volume += ticks[i]["volume"]
    else:
        sell_volume += ticks[i]["volume"]

imbalance = (
    buy_volume - sell_volume
) / (buy_volume + sell_volume)

print(imbalance)
Enter fullscreen mode Exit fullscreen mode

In production, I’ve also added timestamp normalization and a gap detector that flags windows with incomplete data. An imbalance derived from a partial window can mislead you badly.

Thoughts From the Trenches

Adding tick-level imbalance to my intraday workflow didn’t replace my existing strategy — it supplemented it with a layer of truth that candles simply can’t provide. If you’re building your own forex analysis stack, I’d urge you to look beyond OHLC and start thinking in terms of continuous order flow. The code to do it is surprisingly small; the hard part is committing to a solid data pipeline.

Top comments (0)