Have you ever tried plotting a real‑time intraday chart only to watch the line fracture into disconnected segments? The culprit is almost always missing data for certain minutes. In this tutorial, I’ll walk you through a pattern that turns a turbulent WebSocket tick stream into a smooth, reliable 1‑minute series—perfect for financial dashboards, trading bots, or just satisfying your own data curiosity.
Why minutes go missing
When you query minute‑level endpoints, the server usually returns only the minutes that had trades. If a stock sits idle for sixty seconds, that slot simply doesn’t appear. Front‑end libraries connect the dots they have, leaving an ugly jump. The solution? Accept raw trades and build the minute bars yourself, ensuring every minute gets a value.
The fields you absolutely need
Before we code, let’s lock down the schema for a minute bar:
- timestamp aligned to the minute floor.
- price using the last trade of that minute.
- volume (optional but helpful) aggregated over the window.
Getting the tick stream
I’m using a WebSocket connection to AllTick in this example because it delivers the essential fields in a straightforward JSON format. Here’s the basic subscriber:
import websocket
import json
def on_message(ws, message):
data = json.loads(message)
# Display each incoming tick
print(f"Time: {data['time']}, Price: {data['price']}, Volume: {data['volume']}")
def on_open(ws):
subscribe_data = {
"action": "subscribe",
"symbol": "AAPL"
}
ws.send(json.dumps(subscribe_data))
ws = websocket.WebSocketApp(
"wss://api.alltick.co/stock",
on_message=on_message,
on_open=on_open
)
ws.run_forever()
In a real application, you’d push these ticks into a buffer or a lightweight time‑series database instead of just printing them.
Aggregating to one‑minute candles
pandas makes resampling almost trivial. We parse the timestamps, set them as the index, and call resample('1min'). The last() method grabs the final price of each minute, and ffill() propagates the last known price through any empty minutes.
import pandas as pd
df['time'] = pd.to_datetime(df['time'])
df.set_index('time', inplace=True)
# Resample ticks to 1-minute bars, forward-filling any gaps
df_1min = df['price'].resample('1min').last().ffill()
After this step, df_1min is a Series with a continuous time index—no more holes.
Plotting the minute chart
With a clean sequence, we can plot using plotly for a nice interactive experience:
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(
go.Scatter(
x=df_1min.index,
y=df_1min.values,
mode='lines',
name='Price'
)
)
fig.show()
Feel free to add a bar trace for volume to make the chart even richer.
Why this matters beyond the tutorial
Steady, gap‑free minute data is the foundation of many academic studies in finance, such as analyzing intraday volatility patterns or testing algorithmic trading strategies. By learning to control the aggregation yourself, you’re not just fixing a chart—you’re gaining a skill that opens the door to serious quantitative work. Next time your intraday line misbehaves, you’ll know exactly where to look.

Top comments (0)