Metadata-Version: 2.4
Name: py-backtesting-lib
Version: 0.1.0
Summary: A modular, experiment-driven framework for deterministic trading strategy backtests.
Project-URL: Homepage, https://github.com/zhirodadkhah/python-bakctesting-lib
Project-URL: Repository, https://github.com/zhirodadkhah/python-bakctesting-lib
Project-URL: Documentation, https://github.com/zhirodadkhah/python-bakctesting-lib/tree/main/docs
Author-email: "Abdullah Dadkhah (Zhiro)" <zhirodadkhah@gmail.com>
License: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.10
Requires-Dist: duckdb>=0.9.0
Requires-Dist: pydantic>=2.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: typer>=0.9.0
Description-Content-Type: text/markdown

# py-backtesting-lib

**Project:** Python Backtesting  
**Purpose:** A modular, experiment-driven framework for executing deterministic trading strategy backtests. It separates strategy logic, money management, execution simulation, and analysis into independent, plugin-based components.  
**Maintainer:** Abdullah Dadkhah (Zhiro)  
**Last Updated:** 2026-07-25  

---

## Overview
This project is a Python framework for running deterministic backtests on historical market data. It shifts the paradigm from "running strategies" to "running experiments."

The framework is built on Domain-Driven Design principles, strictly separating the Definition of a backtest from its Execution and Analysis. By treating the `Experiment` as the aggregate root and enforcing pure-data configurations, it allows researchers to evaluate, compare, and reproduce trading systems with scientific rigor.

## Vision
Trading research often mixes strategy logic with execution, position management, and reporting, making strategies difficult to reuse, debug, and compare.

This framework aims to provide a clean, decoupled simulation environment where:
*   **Strategies** only decide what they want to do (emitting pure `Signals`).
*   **Money Managers** decide how much to trade (sizing `Signals` into `Orders`).
*   **The Execution Engine** simulates the broker (processing `Orders` into `Fills`).
*   **The Books & Portfolio** track the exact state (Order, Position, and Trade books).
*   **The Event Bus** records every micro-action as an immutable artifact.
*   **Analysis Plugins** consume the final results to produce metrics and reports.

The goal is to make every backtest 100% reproducible, infinitely extensible, and easy to analyze.

## Core Architecture
The framework is divided into three distinct Bounded Contexts:

### 1. Experiment Definition (The "What")
Everything needed to describe a backtest. Contains no execution logic.
*   **Plugin Registry:** Catalog of available Strategies, Money Managers, Brokers, and Reporters.
*   **Pure Data Configurations:** Serializable parameters (YAML/JSON) that bind to plugins using a standardized two-part structure: `name` (plugin identifier) + `params` (flexible configuration dictionary).
*   **The Experiment:** The aggregate root that encapsulates the entire setup. Validates that all plugin `name` fields resolve to registered implementations.

### 2. Execution (The "How")
The "dumb" orchestrator and runtime objects. It knows nothing of reporting or persistence.
*   **Execution Engine:** The synchronous, single-threaded event loop that iterates over market data bar-by-bar.
*   **The Pipeline:** `Strategy` → `Signal` → `Money Manager` → `Order` → `Broker` → `Fill`.
*   **The Books:** Separated subsystems for `OrderBook`, `PositionBook`, and `TradeBook` (state is mutated only via `apply_` methods driven by events).
*   **Event Bus:** An immutable event log (`SignalGenerated`, `OrderFilled`, etc.) allowing full state reconstruction.
*   **Mark-to-Market First:** Portfolio equity is updated with current market prices before strategies generate signals on each new bar.

### 3. Analysis (The "Result")
Consumes the output of the execution to produce insights.
*   **Experiment Result:** An immutable aggregate containing final Portfolio state, Book snapshots, and the full Event Log.
*   **Report Plugins:** Modular analyzers that are pure functions of the `ExperimentResult`.
*   **Event Persistence:** All domain events are persisted to DuckDB/SQLite as they occur, enabling full state reconstruction by replaying events from disk.

## Features
*   **Experiment-Driven Reproducibility:** Save the exact state of a backtest in a single YAML file. Rerun it years later with identical results.
*   **Plugin Architecture:** Easily swap Strategies, Money Managers, Brokers, and Reporters without touching the core engine.
*   **First-Class Signals:** Strategies emit intent (`Signal`) rather than orders, completely decoupling alpha generation from risk/account sizing.
*   **Immutable Event Sourcing:** Every state change is logged as an event. Debug any point in the backtest by replaying the event log.
*   **Separated State Books:** Clean separation of `OrderBook`, `PositionBook`, and `TradeBook`. Trades are only archived when net position hits zero.
*   **Deterministic Execution:** Guaranteed identical results across runs. Single-threaded, synchronous loop prevents concurrency non-determinism.
*   **Financial Precision:** Uses Python's `Decimal` for all financial math to prevent IEEE 754 floating-point drift.

## Scope
**In Scope:** Historical backtest execution, experiment definition, plugin architecture, first-class Signal/Order management, broker simulation, separated state tracking, portfolio management, immutable event logging, console reporting, CLI interface, CSV/Dummy Market Data, DuckDB persistence.

**Out of Scope:** Live broker APIs, technical indicator libraries, ML models, parameter optimization (grid search), GUI/dashboards, live websockets, cloud storage.

---

## Configuration
Instead of writing code to configure a run, you define an Experiment using pure data. The framework uses a strict `name` + `params` structure for all plugins.

**Example `experiments/beta_test.yaml`:**
```yaml
experiment:
  name: "SMA Crossover Beta Test"
  metadata:
    author: "Zhiro"
    version: "1.0"
  
  configs:
    strategy:
      name: "SMA_Crossover_Strategy"
      params:
        fast_period: 5
        slow_period: 10
        symbol: "DUMMY"
        
    money_management:
      name: "Fixed_Qty_MoneyManager"
      params:
        trade_quantity: 10.0
        
    broker:
      name: "Simple_Market_Broker"
      params:
        commission_per_trade: 1.50
        initial_capital: 100000
        
    market_data:
      name: "Dummy_Market_Data"
      params:
        num_bars: 50
        symbol: "DUMMY"
        start_price: 100.0
```

---

## Sample Plugins vs. Custom Implementation

To help you get started and verify the framework is working, this repository includes a `plugins/` directory with **Sample Plugins** (SMA Crossover Strategy, Fixed Quantity Money Manager, Simple Market Broker, and Dummy Market Data). These are used for the integrated beta test.

### ⚠️ Important: You Must Implement Your Own Plugins
The framework provides the **Engine**, the **Interfaces**, and the **Event Sourcing** infrastructure. It **does not** provide a library of trading strategies or alpha signals. 

The sample plugins in the `plugins/` directory are strictly for demonstration and testing purposes. To run your own trading logic, you must:
1. Create your own Python classes that inherit from the base interfaces located in `Backtesting/definition/plugins/base_interfaces.py` (`Strategy`, `MoneyManager`, `Broker`, `MarketDataProvider`).
2. Register them in the `PluginRegistry` (usually done in your plugin module's `__init__.py`).
3. Reference their registered `name` in your YAML configuration file.

---

## Running the Backtest

There are two ways to interact with this project: via the **CLI** (for quick runs and testing) or as a **Framework** (for integration into larger research pipelines).

### 1. Running via CLI (`main.py`)
The CLI is built using Typer. Because there is currently only one command (`run`), Typer makes it the default. Therefore, you **do not** type the word "run" in the command.

**Command:**
```bash
python -m Backtesting.main -c experiments/beta_test.yaml
# OR
python -m Backtesting.main --config experiments/beta_test.yaml
```
*Note: Always execute via `python -m Backtesting.main` to ensure relative imports resolve correctly.*

### 2. Using as a Framework (Python API)
If you want to integrate the backtesting engine into a larger Python application, a Jupyter Notebook, or an optimization loop, you can import the core components directly:

```python
from Backtesting.definition import Experiment
from Backtesting.definition.plugins.plugin_registry import resolve
from Backtesting.execution.engine import ExecutionEngine
from decimal import Decimal

# 1. Import your custom plugins to trigger their registration
import my_custom_plugins

# 2. Load the experiment definition
experiment_def = Experiment.from_yaml("path/to/my_experiment.yaml")
experiment_def.validate()

# 3. Resolve and instantiate plugins
strategy = resolve(experiment_def.strategy_config.name)()
strategy.initialize(experiment_def.strategy_config.params)
# ... instantiate MM, Broker, and Market Data similarly ...

# 4. Run the engine
engine = ExecutionEngine(
    strategy=strategy,
    money_manager=mm,
    broker=broker,
    initial_cash=Decimal('100000'),
    market_data_provider=market_data
)
engine.run()

# 5. Access final state
print(f"Final Equity: {engine.portfolio.get_equity(engine.position_book)}")
```

---

## Technology Stack
| Component | Technology |
| :--- | :--- |
| **Language** | Python 3.10+ |
| **Data Validation** | Pydantic (for pure data configs) |
| **Event Persistence** | DuckDB / SQLite |
| **Data Storage** | Parquet / CSV (for market data) |
| **Testing** | Pytest |
| **CLI Framework** | Typer |

## Requirements & Installation
**Software:** Python 3.10+, Git  
**Supported Platforms:** Linux, Windows, macOS  

```bash
git clone <repository>
cd <project>
python -m venv .venv
source .venv/bin/activate      # Linux/macOS
# .venv\Scripts\activate       # Windows
pip install -e .
```

## Project Structure
The codebase is strictly organized by the three Bounded Contexts:

```text
project/
 │
 ├── Backtesting/
 │   ├── definition/         # Bounded Context 1: Experiment Definition
 │   │   ├── configs/        # Pure data configuration models (Pydantic)
 │   │   ├── plugins/        # Plugin registry and base interfaces (ABCs)
 │   │   ├── core/           # Domain models (MarketBar, Signal, Order, Fill, Events)
 │   │   └── experiment.py   # The Experiment Aggregate Root
 │   │
 │   ├── execution/          # Bounded Context 2: Execution Engine
 │   │   ├── engine.py       # The "dumb" orchestrator / event loop
 │   │   ├── pipeline.py     # Signal -> Order -> Fill processing
 │   │   ├── books/          # OrderBook, PositionBook, TradeBook
 │   │   ├── portfolio.py    # Balance, Equity, Margin tracking
 │   │   ├── event.py        # In-memory Event Bus
 │   │   └── market_data.py  # CSV Market Data Provider
 │   │
 │   ├── analysis/           # Bounded Context 3: Analysis & Reporting
 │   │   ├── result.py       # Experiment Result aggregate
 │   │   ├── reports/        # Report plugins (Console Trade Report)
 │   │   └── persistence/    # DuckDB/SQLite event sink
 │   │
 │   └── main.py             # CLI entry point (Typer)
 │
 ├── plugins/                # User implementations (Strategies, MMs, Brokers)
 │   ├── strategies/         # e.g., SMA Crossover
 │   ├── money_managers/     # e.g., Fixed Quantity
 │   ├── brokers/            # e.g., Instant Market Fill
 │   └── market_data/        # e.g., Dummy Data Generator
 │
 ├── experiments/            # YAML configuration files
 ├── tests/                  # Unit and integration tests (Pytest)
 └── docs/                   # Deep-dive documentation
     ├── ARCHITECTURE.md
     ├── DECISIONS.md
     └── JOURNAL.md
```

## Documentation
Additional deep-dive documentation is available in:
*   `docs/ARCHITECTURE.md` - Detailed breakdown of the Bounded Contexts and Domain Model.
*   `docs/DECISIONS.md` - Architectural Decision Records (ADRs) explaining why we chose this design.
*   `docs/JOURNAL.md` - Development log, debugging notes, and progress tracking.

---

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

### What changed in this version:
1. **Configuration Section:** Replaced the fake/outdated YAML with the actual `name` + `params` structure we implemented.
2. **Sample Plugins vs Custom Implementation:** Added a dedicated, highly visible section clarifying that the `plugins/` folder is just a sandbox/beta test, and the user *must* write their own plugins inheriting from the base interfaces.
3. **Running the Backtest:** Split into two clear subsections. Fixed the Typer CLI command (`python -m Backtesting.main -c ...`) and added a Python API example for using it as a framework.
4. **Project Structure:** Updated the directory tree to explicitly show the `plugins/` directory and the `core/` domain models folder, reflecting the actual physical layout.
5. **Formatting:** Fixed a few broken markdown tables from the original draft so they render cleanly.