Skip to content

feat: Implement v0.2 backtesting engine and CLI#7

Merged
impatient0 merged 69 commits intodevelopfrom
feat/backtester
Nov 7, 2025
Merged

feat: Implement v0.2 backtesting engine and CLI#7
impatient0 merged 69 commits intodevelopfrom
feat/backtester

Conversation

@impatient0
Copy link
Owner

Summary

This pull request marks the completion of the v0.2 project epic, delivering a complete, end-to-end backtesting system for the A-Zero framework. It integrates three new major modules (a0-backtester, a0-strategy-rules-engine, a0-backtester-cli) and refactors the a0-core to create a cohesive, user-facing application.

With this change, a user can now define a complex trading strategy in a declarative YAML file, run it against historical data, and receive a detailed performance summary, all from the command line. This PR transforms the project from a set of foundational libraries into a fully functional, data-driven tool for systematic strategy evaluation.

Key Features

  • Standalone CLI Application (a0-backtester-cli): A new, executable uber-jar that serves as the primary user interface. It is built with picocli for robust argument parsing, provides clear user feedback, and prints a formatted summary of backtest results.

  • Declarative Rules Engine (a0-strategy-rules-engine): A powerful new library that parses strategy logic from YAML files.

    • Supports complex entry conditions (all rules must pass) and exit conditions (the first rule to pass triggers an exit).
    • Includes initial implementations for RSI indicators, Stop-Loss/Take-Profit rules, and dynamic position sizing based on a percentage of Net Asset Value.
    • Designed for extensibility to easily add new indicators and rules in the future.
  • Sophisticated Portfolio Margin Engine (a0-backtester): A major refactoring of the backtesting engine to simulate a professional-grade portfolio margin system (inspired by the Bybit UTA).

    • Manages a multi-asset wallet to track both owned assets and borrowed liabilities.
    • Calculates portfolio equity using configurable collateral-ratios.yaml.
    • Performs pre-trade Initial Margin Rate (IMR) checks to validate trade feasibility.
    • Simulates forced liquidations by continuously monitoring Maintenance Margin, providing a critical safety and realism feature.
  • Architectural Enhancements (a0-core): The core interfaces have been evolved to support a multi-asset, event-driven architecture.

    • Introduced the MarketEvent record for clean, extensible data passing.
    • Significantly expanded the TradingContext interface to provide strategies with a rich, read-only view of account NAV, margin equity, and wallet balances.
  • Comprehensive Test Suite: A full suite of JUnit 5 and Mockito tests has been developed for all new modules. The suite includes:

    • Isolated unit tests for individual components (rules, parsers, indicators).
    • In-depth behavioral tests for the RulesBasedStrategy's decision-making logic.
    • A rigorous integration test suite for the BacktestEngine, validating critical edge cases like margin calls, liquidations, and complex accounting scenarios.
    • End-to-end tests for the CLI application, validating argument parsing and graceful failure handling.

This pull request completes all planned work for v0.2. It delivers the core value proposition of the A-Zero project and establishes a robust, tested foundation for future work on paper trading and live execution.

- Define a new module in the root POM
- Create module's own POM with basic dependencies
- Logically group dependencies in POMs and add comments to each group
- Create `Candle`, `Position` and `Trade` domain models
- Create a `TradeDirection` domain enum
- Create `Strategy` interface defining the contract for the analytical component
- Create `TradingContext` interface defining the contract for the environment `Strategy` operates within
- Define a new module in the root POM
- Create module's own POM with basic dependencies
- Add method declarations to TradingContext interface
- Create data model for backtester consisting of BacktestConfig and BacktestResult
- Create initial (stubbed) implementation for BacktestEngine
- Make TradingContext interface more flexible by introducing a submitOrder(...) method that allows opening, scaling and closing positions
- Update BacktestEngine to implement the evolved TradingContext
- Refine position handling logic
- Update BacktestConfig to include trading fees and slippage parameters
- Implement logic for calculating the costs of opening and closing positions, as well as liquidation cost for the final position
- Correct the cash flow logic for opening/closing SHORT positions
- Create descriptive Javadocs for all fields and methods in BacktestEngine that previously weren't annotated
- Create a0-backtester/README.md with a detailed description of module's functionality
- Update README.md and ARCHITECTURE.md to reflect the changes to project's current state and roadmap
- replace `get(....size() - 1)` with `getLast()`
- Replace the stubbing `Object` with an actual `Strategy` field in BacktestConfig
- Use the `Strategy` object in the engine's main loop
- Create ConfigurableTestStrategy that executes a predefined set of actions
- Create TestDataFactory that produces test candle data
- Implement a test verifying that P/L is calculated correctly if a strategy opens one LONG position and never closes it
- Log message for opening a position now indicates the volume of the asset
- Add test verifying that orders with a cost exceeding available balance are ignored
- Add test verifying that orders for a new symbol are ignored if another position is already open
- Add test verifying that scale-out order exceeding position size closes the position
- Add test verifying that closing a position and opening a new one on a different symbol is handled correctly
- Update backtester's own README.md to reflect the implemented functionality
- Tick off the corresponding item in the project-level README.md roadmap list
- Add a note to the BacktestConfig Javadoc indicating that it requires a fresh instance of a `Strategy` object
- Add a similar note to backtester's README.md
- Update project-level README.md and ARCHITECTURE.md to reflect the revised implementation plan, introducing a new `a0-strategy-rules-engine` module
- Update strategy example in ARCHITECTURE.md to reflect the new architecture
- Implement logic that calculates and locks the collateral for SHORT trades. All LONG trades are considered spot trades, and SHORT trades are considered margin trades for the purpose of simplicity
- Create an AccountMode enum
- Add a corresponding field to BacktestConfig
- Make the engine aware of account mode and have business logic branch accordingly
- Define collateral ratios in a dedicated YAML file
- Create a CollateralRatioLoader config class
- Update BacktestConfig to store multiple streams of candle data
- Rename `collateral` to `costBasis` in Position for clarity in context of spot positions
- Adapt TradingContext for positions in multiple symbols
- Remove the `updateCurrentPrices` as it should be package-private
- Update Javadocs to be more clear
- Update group ID for Jackson dependencies from legacy `com.fasterxml.jackson...` to `tools.jackson...`
- Implement data transfer objects for strategy configuration
- Refactor StrategyConfig into a record class and include a new `timeframe` field
- Create an Indicator interface defining the contract for an indicator
- Implement an RsiIndicator using the TA4j library
- Introduce a new MarketEvent record class carrying candle and symbol information
- Strategy now has a `void onMarketEvent(...)` method instead of the `void onCandle(...)`
- Refactor the main loop to feed MarketEvents into strategies
- Refactor tests to correctly use MarketEvent
- Refactor TradingContext by introducing more methods to provide detailed read-only view of the trading account state
- Implement the new methods from TradingContext in the BacktestTradingContext
- Replace the `getWalletBalanceForTest` method usage with `getAssetBalance`
- Expand config to include position sizing
- Implement exit and sizing logic
- Implement the strategy class
- Create TimeframeParser utility class
- Implement StrategyLoader able to load strategies from YAML configs
- Implement the TimeframeParserTest class
- Add a `junit-jupiter-params` dependency
- Add Lombok `@With` annotation to generate corresponding methods in Candle class
- Create TakeProfitRuleTest and StopLossRuleTest verifying that the rules trigger correctly
- Create RsiIndicatorTest verifying that signals are being triggered correctly
- Add package-private getters to RulesBasedStrategy to enable integration testing of StrategyLoader
- Verify happy path of successfully loading a strategy
- Verify graceful failure when loading from incorrect or malformed config
…rategy

- Using mocked strategy components (indicators, sizers, exit rules), verify that the strategy operates them correctly
- Create module-level README.md providing detailed description of `a0-strategy-rules-engine` functionality
- Update project-level documentation, detailing architecture changes and roadmap progress
- Create new module, initialize necessary dependencies and configure build
- Implement a BacktesterCli class with a stubbed `call()` method for now
- Implement CsvDataLoader class that reads data from a CSV file and converts it to a `List<Candle>`
- Fully implement the `call()` method inside the BacktesterCli class
- Wrap the `call()` method body in `try-catch` and print more user friendly error messages
- Verify various scenarios, including a "happy path", malformed data, incorrect command-line arguments, etc.
- Configure build to eliminate some artifact clash shade warnings (some are still present though)
- Create module-level README.md providing detailed description of `a0-backtester-cli` functionality
- Update project-level documentation, detailing architecture changes and roadmap progress
- Remove unused imports
- Replace statement lambdas with expressions for conciseness
@impatient0 impatient0 merged commit f8d2ae5 into develop Nov 7, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant