October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PCOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
The Finance Base
The Money Desk · Blog
Re:

Python in Finance: Real-Time Market Data Streaming in Jupyter Notebook

A practical guide to streaming market data in Jupyter with Python, using Alpaca WebSockets, a notebook-safe queue, live quote calculations, cleanup, and recovery.
From TheFinanceBase Team8 min to read
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Yes—you can stream live market data into Jupyter, calculate indicators, and update a table or chart in near real time. The reliable notebook pattern is to receive WebSocket events in a background thread, place them in a bounded queue, and let the notebook consume and display them at a controlled rate.

That makes Jupyter useful for research, monitoring, and strategy prototyping—not for guaranteed low-latency execution or an always-on market-data service.

As an Amazon Associate I earn from qualifying purchases.

What you will build

This tutorial uses Alpaca’s Python SDK to receive stock quotes for several symbols and display:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Bid and ask prices
  • Bid and ask sizes
  • Mid-price and spread
  • The provider’s event timestamp
  • The local time at which your notebook received the event

Alpaca’s official market-data documentation recommends WebSockets when you need continuously updated pricing rather than occasional snapshots. See Alpaca’s real-time pricing documentation and the Python SDK market-data reference.

Real-time data is not one thing

Data type What it represents Typical use
Trade An executed transaction Time-and-sales analysis
Quote A bid/ask update Spread, liquidity, and midpoint calculations
Bar Provider-aggregated OHLCV data for a period Charts and indicators
Snapshot A point-in-time REST response Initial state or occasional checks
Delayed data Data intentionally delivered after the event Education and non-time-sensitive analysis

“Real-time” describes the provider’s delivery behavior, not necessarily exchange-to-notebook latency. Your local receipt time includes network, SDK, operating-system, and notebook delays. A quote is also not a trade, and a live feed may still have incomplete exchange coverage.

WebSockets versus REST polling

Method Strength Weakness
REST polling Simple and useful for snapshots and historical data Introduces polling delay, wastes repeated requests, and may encounter rate limits
WebSocket Event-driven delivery with lower request overhead Requires buffering, reconnection, subscription, and cleanup logic
Broker-native API Can combine market data with account and order events More account permissions, platform dependencies, and client management

Use REST to initialize state, retrieve history, and repair gaps. Use WebSockets for the live event stream.

Choosing a provider

Alpaca

Alpaca is the most approachable choice for this walkthrough because it provides a first-party Python SDK, stock, crypto, and options streams, paper-trading workflows, and a documented WebSocket interface.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Be precise about feed coverage. Alpaca’s free stock offering uses IEX data; it is live but is not the entire US equity market. Alpaca’s paid Algo Trader Plus offering describes all-US-exchange SIP coverage. Plan entitlements and prices change, so verify them at Alpaca’s pricing page and market-data documentation before subscribing. The pricing page showed Basic at $0 per month and Algo Trader Plus at $99 per month during the August 16, 2026 research pass.

Interactive Brokers

Interactive Brokers is a stronger fit if you already have an account, need multiple asset classes or international markets, and can manage TWS or IB Gateway, contract definitions, and market-data permissions. Its Web API documentation says market-data streams terminate after 15 minutes unless the client sends a new request after 10 minutes. See the IBKR Web API market-data documentation.

yfinance

yfinance’s WebSocket clients are convenient for lightweight experiments. Its documentation includes synchronous and asynchronous clients and warns about Jupyter’s already-running event loop. Treat it as an exploratory option, not as an automatically complete, exchange-grade, or latency-guaranteed feed.

Notebook setup

Use a virtual environment where possible. Alpaca-py documentation lists Python 3.7 or newer as supported, but check the SDK’s current support matrix because package compatibility changes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
%pip install -U alpaca-py pandas matplotlib

Restart the kernel if the package imports fail after installation. Never place API keys directly in a notebook that will be committed, shared, screenshotted, or uploaded.

import os
from getpass import getpass

os.environ["ALPACA_API_KEY"] = getpass("Alpaca API key: ")
os.environ["ALPACA_SECRET_KEY"] = getpass("Alpaca secret key: ")

API_KEY = os.environ["ALPACA_API_KEY"]
SECRET_KEY = os.environ["ALPACA_SECRET_KEY"]

First: the minimal Alpaca stream

The official SDK pattern is asynchronous: create a stream, define a handler, subscribe, and run the client.

from alpaca.data.live import StockDataStream

stream = StockDataStream(API_KEY, SECRET_KEY)

async def quote_handler(data):
    print(data)

stream.subscribe_quotes(quote_handler, "SPY")
stream.run()

This works naturally in a normal Python process. In Jupyter, however, stream.run() may block the cell or conflict with the event loop already managed by Jupyter.

A Jupyter-safe queue and background thread

The following design separates ingestion from display:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
WebSocket provider
        ↓
SDK callback
        ↓
bounded queue
        ↓
notebook consumer
        ↓
DataFrame and calculations
        ↓
table or chart

Keep the callback lightweight. It should normalize the event and enqueue it—not perform expensive Pandas operations.

from alpaca.data.live import StockDataStream
from queue import Queue, Full
from threading import Thread
from datetime import datetime, timezone

import pandas as pd

events = Queue(maxsize=5000)
stream = StockDataStream(API_KEY, SECRET_KEY)

async def quote_handler(data):
    record = {
        "event_time": getattr(data, "timestamp", None),
        "received_at": datetime.now(timezone.utc),
        "symbol": getattr(data, "symbol", None),
        "bid_price": getattr(data, "bid_price", None),
        "ask_price": getattr(data, "ask_price", None),
        "bid_size": getattr(data, "bid_size", None),
        "ask_size": getattr(data, "ask_size", None),
    }

    try:
        events.put_nowait(record)
    except Full:
        # This queue serves the display, not durable storage.
        try:
            events.get_nowait()
            events.put_nowait(record)
        except Exception:
            pass

stream.subscribe_quotes(quote_handler, "SPY", "AAPL", "MSFT")
worker = Thread(target=stream.run, daemon=True)
worker.start()

Drain the queue in a separate cell:

rows = []

def drain_events():
    while True:
        try:
            rows.append(events.get_nowait())
        except Exception:
            break

drain_events()
quotes = pd.DataFrame(rows)
quotes.tail()

A bounded queue prevents the display pipeline from consuming unlimited memory. If every event must be retained, write batches to durable storage instead.

Display a bounded live table

Do not print every tick indefinitely. Unbounded notebook output can make the browser slow or crash.

from IPython.display import clear_output, display
import time

for _ in range(60):
    drain_events()

    if rows:
        frame = pd.DataFrame(rows[-100:])
        clear_output(wait=True)
        display(frame.tail(20))

    time.sleep(1)

This refreshes once per second while retaining only a small display history. A more polished notebook can use an ipywidgets.Output area or a dashboard framework. The important principle is to render on a timer rather than once per incoming event.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Calculate midpoint and spread safely

quotes["bid_price"] = pd.to_numeric(quotes["bid_price"], errors="coerce")
quotes["ask_price"] = pd.to_numeric(quotes["ask_price"], errors="coerce")

valid = quotes["bid_price"].notna() & quotes["ask_price"].notna()

quotes.loc[valid, "mid_price"] = (
    quotes.loc[valid, "bid_price"] + quotes.loc[valid, "ask_price"]
) / 2

quotes.loc[valid, "spread"] = (
    quotes.loc[valid, "ask_price"] - quotes.loc[valid, "bid_price"]
)

quotes.tail()

The midpoint is an analytical estimate, not necessarily an executable price. Missing values are normal. A locked or crossed market can produce a zero or negative spread, and a stale row can remain visible after a disconnection.

Streaming bars and indicators

Trade-by-trade and quote-by-quote streams can be unnecessarily noisy for beginners. One-minute bars are easier to chart, but they are aggregates rather than tick streams.

Distinguish between an incomplete current bar and a finalized bar. Do not treat an indicator calculated from an unfinished bar as final. Normalize timestamps to a known timezone, account for market and extended-hours settings, and expect missing bars for illiquid symbols or closed markets.

For locally retained prices, a simple rolling return might look like this:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
quotes = quotes.sort_values(["symbol", "event_time"])
quotes["mid_return"] = (
    quotes.groupby("symbol")["mid_price"].pct_change()
)

quotes["rolling_volatility"] = (
    quotes.groupby("symbol")["mid_return"]
          .rolling(20)
          .std()
          .reset_index(level=0, drop=True)
)

For sustained collection, avoid repeatedly concatenating a growing DataFrame. Batch records from the queue and write them to a durable store or time-series pipeline.

Stopping and restarting cleanly

stream.stop()

Alpaca-py exposes stream cleanup methods including run(), stop(), and close(); check the installed SDK version for the exact available API. If the kernel is interrupted, close the stream if supported, recreate the stream object before restarting, and avoid rerunning subscription cells without first stopping the previous client.

A visible cleanup cell is useful:

try:
    stream.stop()
except Exception as exc:
    print(f"Stream stop returned: {exc}")

If you no longer know how many clients are active, restart the kernel and run the setup once. Repeated notebook execution is a common cause of duplicate rows and multiple live connections.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Reconnect and repair missing data

A callback that has not raised an exception does not prove that every event arrived. Connections can fail because of network interruptions, provider maintenance, authentication problems, subscription limits, invalid symbols, laptop sleep, browser disconnects, or kernel restarts.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A robust workflow is:

  1. Detect connection termination or an unexpectedly long period without events.
  2. Stop and close the old client.
  3. Wait using exponential backoff.
  4. Create a fresh client and authenticate again.
  5. Re-subscribe to the required symbols.
  6. Backfill the suspected gap with historical REST data.
  7. Deduplicate and mark the recovered interval.

Use this state model:

historical REST data → initialize state
live WebSocket data   → update state
disconnect             → reconnect and backfill

Store the provider event timestamp and local receipt timestamp separately. If available, also retain the symbol, event type, sequence number, feed identifier, connection identifier, and whether the row came from live data or backfill.

Useful timestamp fields include:

event_timestamp
received_timestamp
processed_timestamp
display_timestamp

These fields support duplicate detection and gap analysis. They do not turn a notebook into a lossless market-data recorder.

Common failures

Symptom Likely cause Remedy
Event-loop error Jupyter already owns an event loop Use the background-thread pattern; for yfinance, its documentation discusses nest_asyncio as a workaround
Cell never returns run() is blocking the kernel Run the stream in a background thread
HTTP 403 Invalid credentials, endpoint, or feed permission Check keys, environment, account, endpoint, and plan
No events Invalid symbol, closed market, wrong feed, or failed subscription Test a liquid symbol and inspect the subscription and account permissions
Duplicate rows A subscription cell was rerun Stop clients or restart the kernel
Stale display The consumer stopped while ingestion continued Separate queue consumption from rendering and monitor event age
Memory growth Every event is retained forever Bound the queue and display history; batch-write durable records
Missing interval The connection dropped Reconnect and backfill historical data

Alpaca documents authentication, endpoint, and permission-related failures in its market-data FAQ.

Notebook versus production

A notebook is an excellent research console, visualization surface, and signal-development environment. It is a poor substitute for a supervised service because the kernel, browser, laptop, network, and Python process can all stop or become slow.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Before moving from experimentation to live operation:

  • Move ingestion into a separately supervised service.
  • Persist raw events and make them replayable.
  • Add structured logs, metrics, alerts, and connection-health checks.
  • Implement reconnect, backfill, deduplication, and clock handling.
  • Separate signal generation from order execution.
  • Add risk limits and explicit failure behavior.
  • Test disconnects, duplicate delivery, stale quotes, and provider errors.
  • Use paper trading before considering live orders.

Paper trading also does not make market data identical to live trading. Credentials, endpoints, permissions, account state, fills, and available feeds can differ. Streaming market data and order execution remain separate systems.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More post from the Money Desk

  1. The Money DeskBlogTheFinanceBase09 OCT 267 minMortgage Escrow FAQs: Taxes, Insurance, Shortages, and Refunds
  2. The Money DeskBlogTheFinanceBase09 OCT 265 minHow Mortgage Escrow Accounts Work and What Homeowners Pay For
  3. The Money DeskBlogTheFinanceBase09 OCT 265 minHow to Read a Stock Chart, Volume and Market-Cap Data
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.