npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

hurst-framework

v0.2.0

Published

**Hurst Trading Framework** — a TypeScript algorithmic trading engine for Interactive Brokers (IBKR) and beyond. Write a strategy once, run it unchanged in backtest, paper, and live modes.

Downloads

293

Readme

hurst-framework

Hurst Trading Framework — a TypeScript algorithmic trading engine for Interactive Brokers (IBKR) and beyond. Write a strategy once, run it unchanged in backtest, paper, and live modes.

License: ISO NORD CA Commercial & Source-Available (LicenseRef-ISO-NORD-CA-1.0) · Status: ✅ Phase 1+ implemented (backtest engine, CSV+Parquet adapters, extended metrics, JSON output) · npm: [email protected]

Current Status

Phase 1 is implemented. src/ contains a working hexagonal backtest engine — core types, IDataFeed/ParquetAdapter, IBroker/BacktestBroker, Portfolio with isolated sub-portfolios, BacktestEngine, two example strategies (SMA crossover, mean-reversion), Sharpe/Sortino/max-drawdown/win-rate metrics, and a hurst backtest CLI — with a passing Vitest suite (72 tests) and a clean npm run build. Still pending (Phase 2+, per the design spec): IBKR connection (PaperBroker/IBBroker are stub classes only), Docker packaging, npm publish, and the full 55-strategy library. The Full Vision section below is the end-state blueprint; the Phase 1 section below is what's built now.

Full design detail: docs/superpowers/specs/2026-08-12-core-engine-design.md. Implementation plan: docs/superpowers/plans/2026-08-12-core-engine-implementation.md.

Repo uses a single branch (main) — no master; work lands via short-lived feature branches merged directly into main.

Quick Start

Runnable today, against the bundled sample fixture:

git clone https://github.com/iso-nord-ca/hurst-framework
cd hurst-framework
npm install
npm run build
node dist/cli/index.js backtest --strategies sma,mean-reversion --data test/fixtures/sample.parquet --from 2024-01-01 --to 2024-01-30

test/fixtures/sample.parquet is a small synthetic 2-ticker, 30-day fixture generated by scripts/generate-fixture.ts (regenerate with npx tsx scripts/generate-fixture.ts). For real data, write a Parquet or CSV file in the same 7-column schema (ticker, timestamp,open,high,low,close,volume) — see src/data/import/generic-importer.ts for the importer contract — then point --data at it.

CLI options

| Option | Required | Default | Description | |---|---|---|---| | --strategies <names> | ✅ | — | Comma-separated strategy names (sma, mean-reversion) | | --data <path> | ✅ | — | Path to a Parquet (.parquet) or CSV (.csv) data file | | --from <date> | ✅ | — | Start date YYYY-MM-DD (filters the data feed) | | --to <date> | ✅ | — | End date YYYY-MM-DD (filters the data feed) | | --ticker <symbol> | — | SPY | Ticker symbol passed to strategies | | --initial-cash <amount> | — | 100000 | Initial cash per strategy | | --json | — | off | Output the full report as JSON on stdout |


Phase 1: Core Engine

Implemented. This section describes what's built, matching the spec.

Architecture

Hexagonal architecture (ports & adapters): the engine's domain logic never talks to a data source or broker directly, only through interfaces. This is what will let backtest, paper, and live modes reuse identical strategy code without changes.

flowchart TB
    subgraph domain["Domain (Phase 1 scope)"]
        STRAT["Strategy\n(onBar → Signal)"]
        ENGINE["BacktestEngine\n(the loop)"]
        PORT["Portfolio\n(sub-portfolios, one per strategy)"]
        STRAT -->|Signal| ENGINE
        ENGINE -->|Fill| PORT
    end

    subgraph ports["Ports (interfaces)"]
        IDF["IDataFeed"]
        IBR["IBroker"]
    end

    subgraph adapters["Adapters (Phase 1 scope)"]
        PARQ["ParquetAdapter"]
        BTB["BacktestBroker"]
    end

    subgraph future["Adapters (later phases)"]
        IBKRD["IBKRDataAdapter"]
        PAPB["PaperBroker"]
        IBB["IBBroker (live)"]
    end

    IDF --> ENGINE
    ENGINE --> IBR
    PARQ -.implements.-> IDF
    BTB -.implements.-> IBR
    IBKRD -.implements.-> IDF
    PAPB -.implements.-> IBR
    IBB -.implements.-> IBR

    style future fill:#00000000,stroke-dasharray: 4 3

Data flow

flowchart LR
    IMPORT["import script\n(generic source / CSV)"] -->|writes| PARQUET[("data/*.parquet")]
    PARQUET --> ADAPTER["ParquetAdapter\n(IDataFeed, streaming)"]
    ADAPTER --> LOOP["BacktestEngine.run(strategies[])"]

    subgraph fanout["fan-out per bar — concurrent"]
        direction TB
        SA["Strategy A.onBar"]
        SB["Strategy B.onBar"]
        SC["Strategy C.onBar"]
    end

    LOOP --> fanout
    SA --> ORD["Signal → Order"]
    SB --> ORD
    SC --> ORD
    ORD --> BROKER["BacktestBroker\n(fills at current bar OHLC)"]
    BROKER --> SUBP["Sub-Portfolio\nper strategy"]
    SUBP --> REPORT["Per-strategy + aggregate\nBacktestReport"]

Parallelism — two independent kinds

flowchart TB
    subgraph run1["One BacktestEngine run"]
        direction LR
        A1["Strategy A"] --> P1["Sub-Portfolio A"]
        A2["Strategy B"] --> P2["Sub-Portfolio B"]
        A3["Strategy C"] --> P3["Sub-Portfolio C"]
        note1["Isolated ledgers — A's fills\nnever touch B's positions,\neven on the same ticker"]
    end

    subgraph sweep["Concurrent independent runs"]
        direction LR
        R1["Engine run 1\n(strategy set X, 2020-2022)"]
        R2["Engine run 2\n(strategy set Y, 2022-2024)"]
        R3["Engine run N…"]
        note2["Plain async concurrency\n(Promise.all) — for\nsweeps / leaderboards"]
    end

Components — build checklist

| Layer | Component | Status | |---|---|---| | Core types | Bar, Signal, Order, Fill, Position | ✅ done | | Data | IDataFeed interface, ParquetAdapter, CsvAdapter | ✅ done | | Data | generic import script | ✅ done | | Data | IBKRImporter | ⏭ later phase (stub only) | | Broker | IBroker interface, BacktestBroker | ✅ done | | Broker | PaperBroker, IBBroker | ⏭ later phase (stub only) | | Engine | Portfolio (sub-portfolios), BacktestEngine | ✅ done | | Strategy | BaseStrategy, SMA-crossover, mean-reversion examples | ✅ done | | Metrics | Sharpe, Sortino, max drawdown, win rate, total trades, exposure, annualized return | ✅ done | | CLI | hurst backtest with --json, --ticker, --initial-cash, date-range filtering | ✅ done | | Packaging | npm-ready package.json/tsup build, published to npm | ✅ done | | Docker | — | ⏭ later phase | | Live/Paper trading | — | ⏭ later phase | | Risk manager | — | ⏭ later phase | | 55-strategy library | — | ⏭ later phase |

This table is the single source of truth for what's actually built — update it as pieces land instead of trusting prose elsewhere in this file to stay in sync.

Folder structure

hurst-framework/
├── src/
│   ├── core/            # types.ts, config.ts
│   ├── engine/           # portfolio.ts, backtest-engine.ts
│   ├── data/
│   │   ├── feed.ts
│   │   ├── adapters/parquet-adapter.ts, csv-adapter.ts
│   │   └── import/       # generic-importer.ts, ibkr-importer.ts (stub)
│   ├── brokers/
│   │   ├── broker-interface.ts
│   │   ├── backtest-broker.ts
│   │   ├── paper-broker.ts       # stub
│   │   └── ibkr/ibkr-broker.ts   # stub
│   ├── strategies/
│   │   ├── base.ts
│   │   └── examples/sma-crossover.ts, mean-reversion.ts
│   ├── metrics/calculator.ts, ratios.ts
│   └── cli/index.ts
├── scripts/             # generate-fixture.ts
├── test/                # Vitest specs mirroring src/, fixtures/ for sample data
├── package.json
├── tsconfig.json
└── tsup.config.ts

The data/ directory is for your own Parquet files; the bundled sample fixture lives under test/fixtures/sample.parquet for tests and the Quick Start demo.

Error handling

  • A strategy's onBar throwing fails only that strategy's run (caught per-strategy in the fan-out) — one bad strategy shouldn't abort concurrent runs of the others.
  • ParquetAdapter fails fast on missing/malformed files at construction, not mid-stream.
  • BacktestBroker rejects orders for tickers absent from the current bar set, logged as a rejected-order count on the report rather than thrown.

Testing

Vitest unit tests cover Portfolio fill isolation, the BacktestEngine loop against a fake in-memory feed, metrics calculations against hand-computed values, and an integration test running both example strategies concurrently to confirm independent, non-interfering reports.

Next phases

  1. IBKR paper broker + IBKR historical/live data adapter
  2. Docker packaging (IB Gateway container + engine container)
  3. npm publish
  4. Risk manager overlay
  5. Expand strategy library toward the full 55-strategy set

Full Vision (end-state blueprint)

Everything below describes where the framework is headed once every phase lands — kept here as the reference blueprint, none of it exists today.

Core Principles

  • Write Once, Run Anywhere — zero code changes switching between backtest, paper, live
  • Multi-Strategy Parallelism — run dozens of strategies concurrently on different symbols/timeframes
  • Zero-Dependency Deployment — self-contained Docker images for Proxmox, AWS, Raspberry Pi, or local
  • Developer-First — TypeScript-native, fully typed, powerful CLI, modular architecture

Planned Features

🎯 marks planned/end-state features — none of these are implemented yet (see the build checklist above for what's actually in progress).

  • 🎯 3 execution modes: Backtest, Paper, Live
  • 🎯 Parallel strategy execution with isolated per-strategy state
  • 🎯 Native IBKR integration (@stoqey/ibkr) with auto-reconnect and IBC auto-login
  • 🎯 High-performance streaming data layer (Parquet for backtest, WebSocket for live)
  • 🎯 Comprehensive metrics: Sharpe, Sortino, Calmar, Win Rate, Max Drawdown, Exposure, Equity Curve
  • 🎯 Portfolio-level risk management via sub-portfolios
  • 🎯 Docker-first universal deployment
  • 🎯 Extensible CLI: hurst init, hurst backtest, hurst run, hurst list

End-state architecture

flowchart TB
    CLI["CLI / Programmatic API"]
    MGR["Strategy Manager\n(multi-strategy lifecycle & routing)"]

    subgraph runners["Runner Layer"]
        direction LR
        BR["Backtest Runner"]
        PR["Paper Runner"]
        LR2["Live Runner"]
    end

    subgraph core["Core Engine (Domain)"]
        LOOP2["Engine Loop"] --> OM["Order Manager"] --> RM["Risk Manager"] --> PORT2["Portfolio"]
    end

    subgraph ports2["Ports (interfaces)"]
        IDF2["IDataFeed"]
        IBR2["IBroker"]
    end

    subgraph adapters2["Adapters"]
        CSVA["CSVAdapter"]
        PARQA["ParquetAdapter"]
        IBKRA["IBKRDataAdapter"]
        BTB2["BacktestBroker"]
        PAPB2["PaperBroker"]
        IBB2["IBBroker (live)"]
    end

    subgraph infra["External Infrastructure"]
        FILES["CSV / Parquet files"]
        GATE["IBKR Gateway (TWS / IBC)"]
    end

    CLI --> MGR --> runners --> core
    core --> ports2
    IDF2 --- CSVA & PARQA & IBKRA
    IBR2 --- BTB2 & PAPB2 & IBB2
    CSVA & PARQA --> FILES
    IBKRA & IBB2 & PAPB2 --> GATE

Docker deployment

flowchart LR
    subgraph host["Any host — Proxmox / AWS / RPi / local"]
        subgraph gw["ib-gateway container"]
            IBC["IBC (auto-login, 2FA handling)"]
            TWS["IB Gateway"]
        end
        subgraph eng["hurst-engine container"]
            HE["Hurst CLI\n(backtest / paper / live)"]
        end
        HE -->|"port 4002"| TWS
    end
    IBKR_CLOUD["IBKR"] <--> TWS

CLI (end state)

hurst init my-bot                                              # scaffold a new project
hurst backtest --strategy ./strategies/sma-cross.ts \
  --symbol AAPL --from 2024-01-01 --to 2024-12-31               # backtest
hurst run --mode paper --strategy ./strategies/mean-revert.ts   # paper trade
hurst run --mode live --strategy ./strategies/hurst-trend.ts    # live trade
hurst list                                                       # running strategies/status

Deployment (end state)

git clone https://github.com/iso-nord-ca/hurst-framework
cd hurst-framework
cp .env.example .env            # add IBKR credentials
docker-compose -f docker/docker-compose.yml up -d
docker logs -f hurst-engine

Metrics output shape

{
  "totalReturn": 24.5,
  "annualizedReturn": 18.3,
  "sharpeRatio": 1.42,
  "sortinoRatio": 2.1,
  "maxDrawdown": -12.4,
  "winRate": 62.5,
  "totalTrades": 145,
  "avgTrade": 0.18,
  "exposure": 0.72,
  "equityCurve": [100000, 100500, 101200]
}

The "Hurst" indicator

Named after the Hurst Exponent — a rescaled-range (R/S) regime detector: H > 0.5 trending, H < 0.5 mean-reverting. Planned as a built-in indicator once the strategy library expands beyond the Phase 1 examples.


Coming Soon

Planned features beyond the phases above — none decided as final except where noted:

  • Multi-broker support (planned) — the IBroker port already abstracts execution away from any single vendor (that's the point of the ports & adapters design), so adding a broker will be a new adapter, not an engine change. IBKR is the first adapter being built. A SnapTrade adapter is planned as a way to trade through whichever brokerage you already have credentials for (Alpaca, Robinhood, TD/Schwab, Questrade, and others SnapTrade supports) instead of being locked into IBKR alone — not yet finalized as the specific integration, but the leading candidate.
  • Risk manager overlay (volatility targeting, drawdown gates, correlation monitoring)
  • Expansion of the strategy library toward the full 55-strategy set
  • Docker packaging and npm publish
  • Web dashboard for live monitoring of running strategies
  • CONTRIBUTING.md, SECURITY.md, and a dedicated docs/roadmap.md as the project grows past a single spec file

License

Proprietary Software — Copyright © 2026 Théodore Beaupré, operating as ISO NORD CA. All rights reserved.

This repository is made available for limited viewing and evaluation only. It is not open source. No permission is granted to use, copy, modify, distribute, deploy, sell, sublicense, reverse engineer, scrape, or use this repository for artificial-intelligence or machine-learning training except where expressly authorized in writing by ISO NORD CA or unavoidably permitted by applicable law. Public GitHub repositories remain subject to GitHub's Terms of Service, including GitHub's platform-level viewing and forking permissions.

Commercial and other licensing requests: [email protected]

Full terms: LICENSE.