DEV Community

EmilyL
EmilyL

Posted on

Python Tip: Distinguishing Pre-market, Regular, and After-hours Ticks from a WebSocket Stream

Ever received a WebSocket tick stream for US stocks and wondered why your indicators behave oddly outside regular hours? The raw data doesn’t tell you which session a trade belongs to, but identifying the session is crucial for signal quality. Here’s a clean, no-dependency-heavy way to do it in Python.

Quick Session Reference

Session US Eastern Time Data Characteristics
Pre-market 04:00-09:30 Sparse trades, choppy moves
Regular hours 09:30-16:00 Dense liquidity, smooth price action
After-hours 16:00-20:00 Volatility often triggered by news

Method 1: Timestamp Conversion

Almost every API sends a UTC timestamp. Convert it to US/Eastern and classify.

from datetime import datetime
import pytz

# US Eastern timezone
et = pytz.timezone('US/Eastern')

def get_session(ts):
    t = datetime.fromtimestamp(ts, et)
    # Check pre-market window
    if t.hour < 9 or (t.hour == 9 and t.minute < 30):
        return "pre"
    # Regular session
    if t.hour < 16:
        return "regular"
    # After-hours
    return "after"
Enter fullscreen mode Exit fullscreen mode

Method 2: Use a Session Status Field

If your provider sends a field like sessionType, you can skip the timezone math. Just make sure to test edge cases at session boundaries.

Live Integration Example

Using a WebSocket feed (like AllTick’s market data stream) that includes a timestamp, I label ticks on the fly.

import websocket
import json
from datetime import datetime
import pytz

# US Eastern timezone
et = pytz.timezone('US/Eastern')

def session(ts):
    t = datetime.fromtimestamp(ts, et)
    if t.hour < 9 or (t.hour == 9 and t.minute < 30):
        return "pre"
    elif t.hour < 16:
        return "regular"
    else:
        return "after"

def on_message(ws, message):
    data = json.loads(message)
    s = session(data["timestamp"])
    print(f"{data['symbol']} | {s} | {data['price']} | {data['volume']}")

# Open WebSocket connection
ws = websocket.WebSocketApp("wss://ws.alltick.co/stock", on_message=on_message)
ws.run_forever()
Enter fullscreen mode Exit fullscreen mode

Efficiency takeaway: Doing session classification at ingestion keeps the rest of your pipeline clean. Each downstream module simply filters by session == "regular" and ignores the noise. It’s a tiny compute cost that prevents huge modeling headaches down the line. Hope this helps your next real-time project!

Top comments (0)