Skip to main content

lightcone

Strict-ordering bar feed for backtests and live trading strategies. Lookahead-proof by construction.

Only the past light cone influences the present.

tests Python License Zero dependencies


Why this exists

Every major Python backtest framework has known lookahead pitfalls. The classic failure mode: each bar's "scene" / "context" object holds references to mutable state. Future bars mutate that state. By the time your trading loop reads bars[10].scene.zone.broken, the value reflects bars 11..N — your trading decision read the future.

Tests can catch known lookahead patterns. They cannot catch the unknown ones.

The structural approach: make it impossible for the strategy to see a bar before it has confirmed processing all earlier bars. Then lookahead bugs are not testable failures — they are architectural impossibilities.

That's lightcone.

How it works

  1. Bars are delivered one at a time through a feed.
  2. Each delivery returns an opaque token. The strategy MUST call confirm(token) before requesting the next bar.
  3. Each bar is wrapped in a BarView that exposes only the fields the strategy declared in advance.
  4. Backtest and live use the same API. Only the data source changes.

Install

pip install lightcone-feed

Zero dependencies. Python 3.9+.

Quick start

from lightcone import Lightcone, OHLCV, FeedExhausted, from_ohlcv_rows

# Build a feed from Binance/HL-style OHLCV rows
feed = from_ohlcv_rows(
    {("BTC", "5m"): btc_rows, ("ETH", "5m"): eth_rows},
    config=OHLCV,
)

while True:
    try:
        bar, key, token = feed.next_bar()
    except FeedExhausted:
        break

    # Your strategy reads only declared fields
    if bar.close > bar.open and bar.volume > some_threshold:
        decide_long(asset=key, ts=bar.ts)

    feed.confirm(token)   # ← MUST call before requesting next bar

Try to peek at a field you didn't declare → FieldNotDeclared. Try to skip confirm() and request the next bar → NotConfirmed. Try to confirm with the wrong token → BadToken.

Configuration profiles

from lightcone import CLOSE_ONLY, OHLCV, FULL_TAPE, custom

CLOSE_ONLY   # → ts + close. Discretionary / human-trader replay.
OHLCV        # → ts + OHLCV. Standard algorithmic backtest.
FULL_TAPE    # → OHLCV + n_trades + taker_buy. Microstructure.

cfg = custom("close", "volume", "n_trades")
cfg = custom("close", extras=["funding_rate"])

Multi-asset / multi-timeframe

feed = Lightcone(streams={
    ("BTC", "5m"):  btc_5m,
    ("BTC", "15m"): btc_15m,
    ("ETH", "5m"):  eth_5m,
})

Bars across all streams come out in strict timestamp order via a min-heap, with deterministic tie-breaking. Same API for one stream or fifty.

Fill simulation (for limit / stop strategies)

from lightcone import Order, Side, OrderType, simulate_fill

fill = simulate_fill(
    Order(Side.BUY, qty=1.0, order_type=OrderType.LIMIT, price=97.0),
    bar,
    slippage_bps=2.0,
)

The fill simulator reads the bar's full OHLC range — that's separate from the strategy's declared-field view, so your decision logic can't peek at high/low while the fill logic still uses them realistically.

Hardening

  • Bars are frozen dataclasses; immutable post-construction
  • Bar.extras is auto-frozen via MappingProxyType (external mutation can't leak in)
  • BarView blocks all underscore-prefixed access — no view._bar.high escape hatch
  • FieldNotDeclared does NOT inherit from AttributeError, so hasattr() cannot silently swallow it
  • Tokens are 16 random bytes, compared with secrets.compare_digest
  • Stream sequences are snapshotted to tuples — caller mutation can't affect the feed
  • Strictly ascending timestamps required within each stream

Performance

Workload Throughput
1M bars, single stream ~400k bars/sec
1M bars, 10 streams via heap ~370k bars/sec
Per-bar overhead ~2.5 microseconds
Memory ~80 bytes / Bar

The feed will never be your bottleneck. Strategy logic dominates by 10-100x.

What lightcone is NOT

  • Not a full backtest framework. It's the data layer. Your strategy code, P&L tracking, and reporting live outside.
  • Not thread-safe. Single-threaded use only. If parallelizing, give each thread its own feed.
  • Not a training pipeline. Model training is offline batch work that uses the full timeline. Use lightcone for inference (backtest and live).
  • Not a sandbox. A determined caller can read the feed's internal state. The contract catches accidents, not adversaries.

Documentation

Doc Read it for
docs/CONTRACT.md The seven protocol rules. Read first.
docs/API.md Reference for every public symbol.
docs/ARCHITECTURE.md Why the package is designed the way it is.
docs/EXAMPLES.md Backtest, multi-asset, fill sim, walk-forward recipes.
docs/LIVE.md Wiring lightcone to a live WebSocket data source.

Testing

pip install -e ".[dev]"
pytest lightcone/tests/

95 tests, ~14s runtime, 100% line coverage on production modules.

License

Apache-2.0. See LICENSE.

Contributing

See CONTRIBUTING.md. lightcone is small and focused — read that first.

Metadata

Release files for lightcone-feed 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lightcone-feed 0.1.0
File Size Uploaded
lightcone_feed-0.1.0.tar.gz 22.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lightcone-feed 0.1.0
File Interpreter ABI Platform
lightcone_feed-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 44.9 kB

Release files / lightcone_feed-0.1.0.tar.gz

Download URL lightcone_feed-0.1.0.tar.gz
Size 22.6 kB
Tags Source
SHA-256 checksum
How to use checksums
3fbde9286345ccbc0206871f4b6abdbb4927b0b57b2026a66cb99e4bebcee634
BLAKE2b-256 checksum
How to use checksums
df40e28ec31a7ed7e8cc5c125424c332f64b54f365493dce8e7b2cfbe8675f38
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 14, 2026.

Transparency log

Release files / lightcone_feed-0.1.0-py3-none-any.whl

Download URL lightcone_feed-0.1.0-py3-none-any.whl
Size 22.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
81849a8d44b5d39fbb3124cc7dc29c477fd9f2f8f633c7e4316aa46950ad0b12
BLAKE2b-256 checksum
How to use checksums
bbb026cd23941b80ed27d69a2e18a8d52b321e62919ee188da79e7caf0cfbd11
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 14, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page