Skip to content

Latest commit

 

History

History
263 lines (223 loc) · 14.5 KB

File metadata and controls

263 lines (223 loc) · 14.5 KB

OpenBackTest Codebase Guide

AI Generated Documentation

This document provides a comprehensive overview of the OpenBackTest project structure. It is intended to help developers and AI agents navigate the codebase efficiently.


Architecture Overview

OpenBackTest is a high-performance trading backtesting utility built with React and Vite.

  • Charting Engine: KlineCharts is used for high-performance financial charting.
  • State Management: Zustand handles global application state, split into backtest playback and trading simulation.
  • Styling: Modern, dark-themed UI built with custom CSS utilities and lucide-react icons.

Entry Points


Architectural Approach

The codebase follows a Decoupled Bridge Architecture:

  1. State (Pure): Stores handle raw data and math (PnL, aggregation). They are chart-agnostic.
  2. View (Declarative): React components manage layout and user input.
  3. Hooks (The Bridge): These "watch" the State and imperatively update the Chart Engine (chart.applyNewData(), chart.createOverlay()).
  4. Engine (Imperative): KlineCharts handles high-performance Canvas rendering via extensions in lib/chart/.
  5. Data Connections (Provider-neutral): Market-data providers implement a shared connection contract and feed normalized candles into the backtest store.

Directory Structure

src/components

UI components categorized by functional area.

  • ChartGrid.tsx: Dynamic, resizable grid layout using react-resizable-panels to display up to 3 charts simultaneously.
  • TradingChart/: All components related to the chart interface (overlays, menus, legends, individual chart containers).
  • Controls.tsx: Top navigation, data loading controls, and session import/export management.
  • PlaybackBar.tsx: The bottom timeline and playback controls.
  • TradingPanel.tsx: The right-side panel for trade execution and account status.
  • ActualAccountPanel.tsx: Broker account snapshot, live statistics, and guarded Rithmic market-order controls.
  • StatsModal.tsx: Performance analysis dashboard with equity curve and export features.

src/hooks

Custom React hooks encapsulating complex logic.

  • useChart.ts: Lifecycle management for the KlineCharts instance.
  • useIndicators.ts: Logic for adding, removing, and managing technical indicators.
  • useTradeOverlays.ts: Rendering logic for TP/SL lines and trade entry areas.
  • useContextMenu.ts: Logic for the chart's right-click interaction.

src/store

Zustand stores defining the global state and actions.

  • useBacktestStore.ts: Controls data playback (Play/Pause/Step), symbol selection, and multi-chart state management (array of ChartConfig).
  • useTradeStore.ts: Core trading engine. Manages positions, orders, PnL calculations, trade history, and session statistics.
  • useMarketDataStore.ts: Manages provider-neutral connection state, normalized symbols, historical data, and live candle subscriptions.
  • useExecutionStore.ts: Owns the selected broker account, live account snapshot, execution subscriptions, and order actions without touching simulation state.
  • useBinanceStore.ts: Deprecated compatibility alias for useMarketDataStore.
  • useChartStyleStore.ts: Manages styling properties for the chart, such as bullish/bearish candle colors, and persists user settings in localStorage.

src/lib/chart

Low-level extensions for KlineCharts.

  • customIndicators.ts: Registry for custom indicators and their default parameters.
  • indicators/: One implementation file per custom indicator (ATR, anchored VWAP, anchored Volume Profile, and VPVR).
  • overlays.ts: Registration of custom visual elements (e.g., TP/SL lines and anchored indicator range selectors).
  • constants.ts: Shared IDs and configuration constants for the chart.

src/types

  • index.ts: Shared TypeScript interfaces for Candles, Trades, and Timeframes.
  • indicatorTypes.ts: Types specific to indicator configurations.

File Manifest

File Responsibility
src/App.tsx Main application shell and layout. Hosts the ChartGrid.
src/components/ChartGrid.tsx Manages the resizable split-pane layout for multiple charts.
src/hooks/useChart.ts Initializes chart, handles data updates, and manages responsive resizing with isolated container IDs.
src/store/useBacktestStore.ts Centralizes data state; includes stepForward, togglePlayback, loadData, updateLiveCandle, and multi-chart configurations.
src/store/useTradeStore.ts Executes trades; tracks account equity, leverage, and aggregates positions for statistics.
src/store/useMarketDataStore.ts Owns the active market-data connection and maps provider events into normalized candles.
src/store/useExecutionStore.ts Owns actual-account state and routes provider-neutral orders through the active provider's execution adapter.
src/store/useBinanceStore.ts Compatibility alias for the provider-neutral market-data store.
src/store/useChartStyleStore.ts Central store managing persistent chart styles and styling properties.
src/components/TradingChart/CandleStyleEditor.tsx Floating overlay editor for bullish/bearish candle, border, and wick colors.
src/components/StatsModal.tsx Calculates and displays Win Rate, Profit Factor, R/R, and Equity Curve; handles CSV exports.
src/lib/chart/customIndicators.ts Registry and defaults for indicators not natively supported by KlineCharts.
src/lib/chart/indicators/*.ts One file per custom indicator implementation; anchored VWAP and anchored Volume Profile receive their selected time range from chart overlays.
src/components/TradingChart/ContextMenu.tsx UI for the right-click menu (Set TP/SL, Reset View).
src/components/TradingChart/DrawingToolbar.tsx Left-side sidebar for chart annotation tools (Lines, Measures).
src/hooks/useIndicators.ts Bridges the store state to the KlineCharts indicator API.
src/utils/aggregation.ts Logic to convert 1m raw data into higher timeframes (5m, 1h, etc.).
src/services/binance.ts Handles Binance API interactions (fetching symbols, historical klines, live polling).
src/services/rithmic.ts Browser-side WebSocket adapter for the local RAPI+ Rithmic market-data gateway.
src/services/marketData.ts Shared MarketDataSource, MarketDataConnection, and subscription interfaces for provider adapters.
src/services/marketDataRegistry.ts Registry used to select an available market-data provider.
src/services/execution.ts Provider-neutral account, order, fill, position, and live-statistics contracts.

Developer & Agent Guide

Common Tasks

  • Adding a New Indicator:
    1. Define the indicator in its own file under src/lib/chart/indicators/.
    2. Register it and its defaults in src/lib/chart/customIndicators.ts.
    3. Add any required UI label or parameter metadata in IndicatorMenu.tsx and IndicatorProperties.tsx.
  • Anchored VWAP / Volume Profile:
    • Choose the indicator from the chart's Indicators menu, then draw the two-point range overlay on the chart.
    • Drag either endpoint to recalculate the selected range. The range and indicator settings are persisted per symbol and chart screen.
  • Modifying Trading Logic:
    • Edit src/store/useTradeStore.ts for execution logic.
    • Edit src/hooks/useTradeOverlays.ts to change how positions look on the chart.
  • Adjusting Statistics & Reporting:
    • Statistics are calculated in src/components/StatsModal.tsx using finishedPositions from the trade store.
    • To add new metrics, update the Position interface in useTradeStore.ts and the calculation logic in StatsModal.tsx.

Search Keywords

  • KlineCharts: For chart API questions.
  • Zustand: For state management patterns.
  • VPVR: For Volume Profile logic.
  • useBacktestStore: For playback control.
  • StatsModal: For performance metrics and reporting.

Rules for AI Agents Contributing to this Project

When working on features, bug fixes, or enhancements, you MUST adhere to the following rules:

  1. Test Directory Structure: All unit and integration tests MUST be placed in the root tests/ directory (e.g., tests/store, tests/components, tests/hooks). Do not place __tests__ folders or .test.ts files alongside the source code in the src/ directory.
  2. Testing Stack: The project uses vitest, jsdom, and @testing-library/react.
  3. Mocking: When writing tests for complex React hooks and Zustand stores (especially those interacting with the canvas or browser APIs), actively use @testing-library/react's renderHook and vitest's vi.mock()/vi.spyOn().
  4. Coverage: When adding new UI components or data stores, ensure that you provide corresponding test coverage. Run npm run coverage to verify your changes.

State Flow

  1. Data Source: CSV/JSON loaded into useBacktestStore.
  2. Aggregation: useBacktestStore uses aggregation.ts to prepare data for the current timeframe.
  3. Rendering: useChart detects data changes and calls chart.applyNewData().
  4. Interaction: User actions trigger useTradeStore, which updates overlays via useTradeOverlays.
  5. Completion: When a simulation is finished, useTradeStore aggregates all trades into finishedPositions and triggers the StatsModal.

Architecture Mapping

graph TD
    %% Layers
    subgraph UI ["View Layer (React)"]
        App["App.tsx"]
        Controls["Controls.tsx"]
        ChartGrid["ChartGrid.tsx"]
        ChartUI["TradingChart/index.tsx"]
        CandleEditor["TradingChart/CandleStyleEditor.tsx"]
        Stats["StatsModal.tsx"]
    end

    subgraph Logic ["Logic & State (Zustand)"]
        BS["useBacktestStore (Playback)"]
        TS["useTradeStore (Execution & Stats)"]
        CSS["useChartStyleStore (Styles)"]
        BNS["useMarketDataStore (Live Data)"]
    end

    subgraph Bridge ["Bridge Hooks (Glue)"]
        UC["useChart (Lifecycle)"]
        UIH["useIndicators (Math)"]
        UT["useTradeOverlays (Visuals)"]
    end

    subgraph Engine ["Engine Layer"]
        KC["KlineCharts (Canvas)"]
        Lib["lib/chart/* (Extensions)"]
    end

    %% Mapping
    App --> Controls & ChartGrid & Stats
    ChartGrid --> ChartUI
    Controls --> BS & TS & BNS
    BNS --> BS
    ChartUI --> UC & UIH & UT & CandleEditor
    CandleEditor --> CSS
    Stats --> TS
    UC & UIH & UT --> KC
    UC --> CSS
    KC <--> Lib
    BS --> Agg["aggregation.ts"]
Loading

External Data Integration

Market Data Connections

OpenBackTest consumes live data through a provider-neutral connection contract.

  • src/services/marketData.ts defines MarketDataSource, MarketDataConnection, and MarketDataSubscription.
  • src/services/marketDataRegistry.ts registers available providers.
  • src/services/binance.ts implements the current Binance Futures adapter: futures symbols, historical 1m klines, and REST-based live polling.
  • src/services/rithmic.ts implements the browser side of the Rithmic adapter. It speaks a small WebSocket protocol to the local .NET gateway and maps RAPI+ reference data, trade replay, and live trades into normalized symbols and candles.
  • src/store/useMarketDataStore.ts owns the active connection, loads historical data, starts/stops subscriptions, and maps provider symbols to normalized MarketSymbol values.
  • src/store/useBinanceStore.ts remains as a compatibility alias while consumers migrate to useMarketDataStore.
  • src/store/useBacktestStore.ts remains provider-agnostic and only receives normalized candles through updateLiveCandle(kline).

Rithmic market data and actual-account execution are available through the local gateway/ project. The gateway uses the Quantower-compatible RAPI+ runtime and the checked-in Chicago paper profile, while credentials and native library paths remain environment/browser configuration. The provider-neutral execution contract is separate from chart data, so future providers such as Binance can add account and order adapters without changing the simulation code. The account-wide flatten path cancels all working orders and exits every open account position before reporting completion.

The execution boundary is defined in src/services/execution.ts. It models broker accounts, orders, order updates, fills, positions, and live statistics without changing the current local simulation behavior. Rithmic is the first provider implementing it.

Importing Third-Party Trade Data

Import trades from another platform and analyze them using OpenBackTest's Statistics Modal. Construct a JSON file that mimics the internal session state. Load a CSV file into the application before importing the JSON session file.

JSON structure required to populate the statistics:

{
  "backtest": {},
  "trade": {
    "initialBalance": 10000,
    "isFinished": true,
    "showStatsModal": true,
    "tradeHistory": [
      {
        "id": "trade-1",
        "type": "buy",
        "price": 50000,
        "time": 1704067200,
        "quantity": 1,
        "fee": 0,
        "realizedPnL": 0,
        "positionSize": 1,
        "entryPrice": 50000,
        "balance": 10000
      },
      {
        "id": "trade-2",
        "type": "sell",
        "price": 51000,
        "time": 1704070800,
        "quantity": 1,
        "fee": 10,
        "realizedPnL": 1000,
        "positionSize": 0,
        "entryPrice": null,
        "balance": 11000
      }
    ],
    "finishedPositions": [
      {
        "id": "pos-1",
        "type": "long",
        "entryPrice": 50000,
        "exitPrice": 51000,
        "quantity": 1,
        "pnl": 1000,
        "openTime": 1704067200,
        "closeTime": 1704070800,
        "trades": []
      }
    ]
  }
}

Key Fields to Map:

  • initialBalance: Your starting account equity.
  • isFinished & showStatsModal: Set to true to immediately open the dashboard.
  • finishedPositions: Powers core stats (Win Rate, PnL, Drawdown, Profit Factor). The pnl field should be the gross profit/loss (before fees). The trades array should be left empty ([]) for imported data.
  • tradeHistory: Powers the "Trade Log" export, "Backtest from/to" dates, and fee calculations. Fees in tradeHistory entries are automatically subtracted from the gross PnL to compute the net profit displayed in the Statistics Modal.