Skip to content

feat(cqrs): harden active order refresh#115

Merged
blackms merged 14 commits into
mainfrom
codex/cqrs-open-position-foundation
Apr 24, 2026
Merged

feat(cqrs): harden active order refresh#115
blackms merged 14 commits into
mainfrom
codex/cqrs-open-position-foundation

Conversation

@blackms

@blackms blackms commented Apr 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds a transactional order lifecycle foundation for submitted, active, partially filled, filled, canceled, and rejected orders.
  • Reworks the refresh pipeline around active orders, including CQRS handlers, background refresh service, JSON persistence, domain events, and audit handlers.
  • Hardens the implementation with TDD coverage across domain state machines, application handlers, dispatching, and JSON transaction rollback/commit paths.

Acceptance Criteria

  • Given an active order is refreshed from the exchange, when the exchange reports a new terminal or partial status, then the order lifecycle transitions through the domain state machine and persists consistently.
  • Given a partial open, DCA, or close order is refreshed repeatedly, when cumulative fills grow, then only the unapplied delta affects position and portfolio state.
  • Given JSON-backed repositories participate in a transaction, when commit succeeds or rollback/failure occurs, then persisted files and in-memory caches remain consistent.
  • Given active order refresh runs in the background, when it dispatches the CQRS batch command, then submitted and partially filled orders are included while terminal orders are ignored.

Changes

  • Added order lifecycle CQRS commands/handlers, active order queries, and refresh result models.
  • Added ActiveOrderRefreshService and kept the legacy submitted refresh contract as a compatible alias.
  • Added JSON persistence and transaction support for order lifecycles and portfolio defaults.
  • Hardened InMemoryCommandDispatcher transaction cleanup and exception unwrapping.
  • Added extensive TDD coverage for order lifecycle, position fill deltas, refresh handler negative paths, JSON repositories, and background refresh behavior.

Testing

  • dotnet test tests/IntelliTrader.Application.Tests/IntelliTrader.Application.Tests.csproj --configuration Release
  • dotnet test tests/IntelliTrader.Infrastructure.Tests/IntelliTrader.Infrastructure.Tests.csproj --configuration Release
  • dotnet test tests/IntelliTrader.Core.Tests/IntelliTrader.Core.Tests.csproj --configuration Release
  • dotnet test tests/IntelliTrader.Domain.Tests/IntelliTrader.Domain.Tests.csproj --configuration Release
  • dotnet build IntelliTrader.sln --configuration Release --no-restore

Checklist

  • Tests pass
  • Coverage maintained
  • Linter clean
  • Documentation not required for this internal architecture slice

Summary by CodeRabbit

Release Notes

  • New Features

    • Added comprehensive order lifecycle tracking and persistence with status reconciliation
    • Added portfolio and order query capabilities with filtering and sorting
    • Added automatic background reconciliation of active orders with exchange
    • Added trading use case facade providing unified interface for position and portfolio operations
    • Added detailed trading history and statistics calculations
  • Infrastructure

    • Enhanced data persistence layer with transactional support
    • Improved trading service startup/shutdown lifecycle management

@coderabbitai

coderabbitai Bot commented Apr 24, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2fc7394f-966d-4083-8478-0d09ef2dad8d

📥 Commits

Reviewing files that changed from the base of the PR and between 0e6c007 and 89b9a1f.

📒 Files selected for processing (64)
  • .gitignore
  • IntelliTrader.Application/Ports/Driven/IOrderRepository.cs
  • IntelliTrader.Application/Trading/Commands/RefreshOrderStatusCommand.cs
  • IntelliTrader.Application/Trading/Commands/RefreshSubmittedOrdersCommand.cs
  • IntelliTrader.Application/Trading/Handlers/ClosePositionHandler.cs
  • IntelliTrader.Application/Trading/Handlers/ExchangeOrderLifecycleFactory.cs
  • IntelliTrader.Application/Trading/Handlers/ExecuteDCAHandler.cs
  • IntelliTrader.Application/Trading/Handlers/OpenPositionHandler.cs
  • IntelliTrader.Application/Trading/Handlers/OrderQueryHandlers.cs
  • IntelliTrader.Application/Trading/Handlers/PortfolioQueryHandlers.cs
  • IntelliTrader.Application/Trading/Handlers/PositionQueryHandlers.cs
  • IntelliTrader.Application/Trading/Handlers/RefreshOrderStatusHandler.cs
  • IntelliTrader.Application/Trading/Handlers/RefreshSubmittedOrdersHandler.cs
  • IntelliTrader.Application/Trading/Queries/OrderQueries.cs
  • IntelliTrader.Application/Trading/TradingUseCase.cs
  • IntelliTrader.Core/Interfaces/Services/IActiveOrderRefreshService.cs
  • IntelliTrader.Core/Interfaces/Services/ISubmittedOrderRefreshService.cs
  • IntelliTrader.Core/Services/CoreService.cs
  • IntelliTrader.Domain/Trading/Aggregates/Portfolio/Portfolio.cs
  • IntelliTrader.Domain/Trading/Aggregates/Position/Position.cs
  • IntelliTrader.Domain/Trading/Events/PositionPartiallyClosed.cs
  • IntelliTrader.Domain/Trading/Orders/OrderLifecycle.cs
  • IntelliTrader.Infrastructure/Adapters/Persistence/Json/JsonOrderRepository.cs
  • IntelliTrader.Infrastructure/Adapters/Persistence/Json/JsonPortfolioRepository.cs
  • IntelliTrader.Infrastructure/Adapters/Persistence/Json/JsonPositionRepository.cs
  • IntelliTrader.Infrastructure/Adapters/Persistence/Json/OrderLifecycleDto.cs
  • IntelliTrader.Infrastructure/Adapters/Persistence/Json/OrderLifecycleMapper.cs
  • IntelliTrader.Infrastructure/Adapters/Persistence/Json/PortfolioDto.cs
  • IntelliTrader.Infrastructure/Adapters/Persistence/Json/PortfolioMapper.cs
  • IntelliTrader.Infrastructure/AppModule.cs
  • IntelliTrader.Infrastructure/BackgroundServices/ActiveOrderRefreshService.cs
  • IntelliTrader.Infrastructure/BackgroundServices/OrderStatusRefreshService.cs
  • IntelliTrader.Infrastructure/Dispatching/InMemoryCommandDispatcher.cs
  • IntelliTrader.Infrastructure/Events/OrderFilledAuditHandler.cs
  • IntelliTrader.Infrastructure/Events/OrderPlacedAuditHandler.cs
  • IntelliTrader.Infrastructure/Events/PositionOpenedAuditHandler.cs
  • IntelliTrader.Infrastructure/Transactions/JsonTransactionalUnitOfWork.cs
  • tests/IntelliTrader.Application.Tests/Trading/Handlers/ClosePositionHandlerTests.cs
  • tests/IntelliTrader.Application.Tests/Trading/Handlers/ExchangeOrderLifecycleFactoryTests.cs
  • tests/IntelliTrader.Application.Tests/Trading/Handlers/ExecuteDCAHandlerTests.cs
  • tests/IntelliTrader.Application.Tests/Trading/Handlers/OpenPositionHandlerTests.cs
  • tests/IntelliTrader.Application.Tests/Trading/Handlers/OrderQueryHandlerTests.cs
  • tests/IntelliTrader.Application.Tests/Trading/Handlers/PortfolioQueryHandlerTests.cs
  • tests/IntelliTrader.Application.Tests/Trading/Handlers/PositionQueryHandlerTests.cs
  • tests/IntelliTrader.Application.Tests/Trading/Handlers/RefreshOrderStatusHandlerTests.cs
  • tests/IntelliTrader.Application.Tests/Trading/Handlers/RefreshSubmittedOrdersHandlerTests.cs
  • tests/IntelliTrader.Application.Tests/Trading/TradingUseCaseTests.cs
  • tests/IntelliTrader.Core.Tests/CoreServiceAdditionalTests.cs
  • tests/IntelliTrader.Core.Tests/CoreServiceTests.cs
  • tests/IntelliTrader.Domain.Tests/Trading/Aggregates/PortfolioTests.cs
  • tests/IntelliTrader.Domain.Tests/Trading/Aggregates/PositionTests.cs
  • tests/IntelliTrader.Domain.Tests/Trading/Orders/OrderLifecycleTests.cs
  • tests/IntelliTrader.Infrastructure.Tests/Adapters/Persistence/JsonOrderRepositoryTests.cs
  • tests/IntelliTrader.Infrastructure.Tests/Adapters/Persistence/JsonPortfolioRepositoryTests.cs
  • tests/IntelliTrader.Infrastructure.Tests/Dispatching/InMemoryCommandDispatcherTests.cs
  • tests/IntelliTrader.Infrastructure.Tests/Integration/ActiveOrderRefreshServiceBehaviorTests.cs
  • tests/IntelliTrader.Infrastructure.Tests/Integration/ActiveOrderRefreshServiceRegistrationTests.cs
  • tests/IntelliTrader.Infrastructure.Tests/Integration/JsonTransactionalUnitOfWorkIntegrationTests.cs
  • tests/IntelliTrader.Infrastructure.Tests/Integration/OpenPositionCommandDispatchIntegrationTests.cs
  • tests/IntelliTrader.Infrastructure.Tests/Integration/OrderLifecycleCommandDispatchIntegrationTests.cs
  • tests/IntelliTrader.Infrastructure.Tests/Integration/OrderStatusRefreshServiceTests.cs
  • tests/IntelliTrader.Infrastructure.Tests/Integration/RefreshOrderStatusCommandDispatchIntegrationTests.cs
  • tests/IntelliTrader.Infrastructure.Tests/Integration/RefreshSubmittedOrdersCommandDispatchIntegrationTests.cs
  • tests/IntelliTrader.Infrastructure.Tests/Integration/TradingUseCaseRegistrationTests.cs

📝 Walkthrough

Walkthrough

This pull request introduces persistent order lifecycle management with transactional support. It adds an OrderLifecycle domain aggregate with a state machine, an IOrderRepository port with JSON file-based implementation, command handlers for refreshing order statuses, background services for batch reconciliation, comprehensive query handlers for orders/positions/portfolios, a TradingUseCase application service, and transactional JSON infrastructure with commit/rollback semantics.

Changes

Cohort / File(s) Summary
Order Lifecycle Domain
IntelliTrader.Domain/Trading/Orders/OrderLifecycle.cs, IntelliTrader.Domain/Trading/Events/PositionPartiallyClosed.cs
New OrderLifecycle aggregate root with state machine (Submit/MarkFilled/Cancel/Reject), intent/related-position tracking, unapplied fill staging, and domain events (OrderPlacedEvent, OrderFilledEvent). New PositionPartiallyClosed domain event for partial close scenarios.
Order Repository & Commands
IntelliTrader.Application/Ports/Driven/IOrderRepository.cs, IntelliTrader.Application/Trading/Commands/RefreshOrderStatusCommand.cs, IntelliTrader.Application/Trading/Commands/RefreshSubmittedOrdersCommand.cs, IntelliTrader.Application/Trading/Queries/OrderQueries.cs
New IOrderRepository port with async CRUD for OrderLifecycle. New command types RefreshOrderStatusCommand/Result, RefreshActiveOrdersCommand/Result, RefreshSubmittedOrdersCommand/Result with batch metrics. New query types GetOrderQuery, GetRecentOrdersQuery, GetActiveOrdersQuery, and read model OrderView.
Order Query & Refresh Handlers
IntelliTrader.Application/Trading/Handlers/OrderQueryHandlers.cs, IntelliTrader.Application/Trading/Handlers/RefreshOrderStatusHandler.cs, IntelliTrader.Application/Trading/Handlers/RefreshSubmittedOrdersHandler.cs, IntelliTrader.Application/Trading/Handlers/ExchangeOrderLifecycleFactory.cs
New query handlers for single/recent/active orders and trading history with filtering/pagination. New RefreshOrderStatusHandler that reconciles persisted orders with exchange state via intent-based routing (OpenPosition/ClosePosition/ExecuteDca), applies fill deltas to positions/portfolio, and manages transaction lifecycle. New factory for creating/refreshing OrderLifecycle from exchange data.
Position & Portfolio Domain Extensions
IntelliTrader.Domain/Trading/Aggregates/Position/Position.cs, IntelliTrader.Domain/Trading/Aggregates/Portfolio/Portfolio.cs
New delta-based methods ApplyDCAFillDelta, ApplyOpeningFillDelta, ApplyCloseFillDelta for reconciling cumulative fills. New PositionCloseFillDelta record type for close results. New Portfolio.RecordPositionCostReduced for partial close cost tracking.
Existing Handler Updates
IntelliTrader.Application/Trading/Handlers/ClosePositionHandler.cs, IntelliTrader.Application/Trading/Handlers/ExecuteDCAHandler.cs, IntelliTrader.Application/Trading/Handlers/OpenPositionHandler.cs
Updated to construct/persist OrderLifecycle, use ITransactionalUnitOfWork, inject IOrderRepository, apply fill deltas to positions/portfolio, and dispatch order domain events. Changed core logic to depend on orderLifecycle.CanAffectPosition instead of raw exchange status.
Query Handlers (Positions & Portfolio)
IntelliTrader.Application/Trading/Handlers/PositionQueryHandlers.cs, IntelliTrader.Application/Trading/Handlers/PortfolioQueryHandlers.cs
New handlers for retrieving single/active/closed positions with margin filtering/sorting and current price resolution. New handlers for portfolio view and statistics (unrealized PnL, margin, win/loss metrics, trade counts).
Trading Use Case
IntelliTrader.Application/Trading/TradingUseCase.cs
New application service implementing ITradingUseCase as a facade delegating commands/queries to dispatchers. Includes position decision validation (CanOpenPosition, CanExecuteDCA) and position summary aggregation.
Transactional Infrastructure
IntelliTrader.Infrastructure/Transactions/JsonTransactionalUnitOfWork.cs
New JSON-backed transactional unit of work with JsonTransactionCoordinator managing ambient async-context transaction state, multi-resource prepare/commit/rollback with file-based atomicity (temp file swap), and rollback recovery.
JSON Persistence Repositories
IntelliTrader.Infrastructure/Adapters/Persistence/Json/JsonOrderRepository.cs, IntelliTrader.Infrastructure/Adapters/Persistence/Json/JsonPortfolioRepository.cs, IntelliTrader.Infrastructure/Adapters/Persistence/Json/JsonPositionRepository.cs
New JsonOrderRepository with in-memory cache and transactional staging. Updated JsonPortfolioRepository with default portfolio promotion logic and transactional support. Updated JsonPositionRepository to participate in transaction coordinator.
Order Lifecycle Persistence
IntelliTrader.Infrastructure/Adapters/Persistence/Json/OrderLifecycleDto.cs, IntelliTrader.Infrastructure/Adapters/Persistence/Json/OrderLifecycleMapper.cs, IntelliTrader.Infrastructure/Adapters/Persistence/Json/PortfolioDto.cs, IntelliTrader.Infrastructure/Adapters/Persistence/Json/PortfolioMapper.cs
New DTOs and reflection-based mappers for serializing/deserializing OrderLifecycle and Portfolio aggregates to/from JSON with private field rehydration.
Background Services
IntelliTrader.Core/Interfaces/Services/IActiveOrderRefreshService.cs, IntelliTrader.Core/Interfaces/Services/ISubmittedOrderRefreshService.cs, IntelliTrader.Infrastructure/BackgroundServices/ActiveOrderRefreshService.cs, IntelliTrader.Infrastructure/BackgroundServices/OrderStatusRefreshService.cs
New service contracts and implementations for background refresh of active orders. ActiveOrderRefreshService wraps OrderStatusRefreshService with lifecycle Start/Stop. OrderStatusRefreshService is timed background task dispatching RefreshActiveOrdersCommand per cycle.
Core Service & DI Wiring
IntelliTrader.Core/Services/CoreService.cs, IntelliTrader.Infrastructure/AppModule.cs, IntelliTrader.Infrastructure/Dispatching/InMemoryCommandDispatcher.cs
CoreService updated to start/stop IActiveOrderRefreshService. AppModule refactored to introduce JsonTransactionCoordinator, assembly-scanned CQRS handler registration, JSON repository wiring, exchange adapter selection, and refresh service registration. InMemoryCommandDispatcher adds transactional support with automatic rollback on handler failure.
Audit Event Handlers
IntelliTrader.Infrastructure/Events/OrderPlacedAuditHandler.cs, IntelliTrader.Infrastructure/Events/OrderFilledAuditHandler.cs, IntelliTrader.Infrastructure/Events/PositionOpenedAuditHandler.cs
New domain event handlers that log OrderPlaced, OrderFilled, and PositionOpened events to audit service with formatted details.
.gitignore Excludes new local agent tooling artifacts (.agents/, .dev-prompts/, .claude-flow/, AGENTS.md) and .gitmodules.
Comprehensive Test Coverage
tests/IntelliTrader.Application.Tests/Trading/Handlers/*Tests.cs, tests/IntelliTrader.Domain.Tests/Trading/*, tests/IntelliTrader.Infrastructure.Tests/*
Unit tests for handlers (refresh, query, existing handler updates), domain aggregates (OrderLifecycle, Position fill deltas, Portfolio cost reduction), and integration tests for transactional persistence, command dispatch pipelines, and background service behavior. Over 2000 lines for RefreshOrderStatusHandlerTests alone with comprehensive scenario coverage.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant RefreshHandler as RefreshOrderStatusHandler
    participant ExchangePort
    participant Factory as ExchangeOrderLifecycleFactory
    participant OrderRepo as IOrderRepository
    participant PositionRepo as IPositionRepository
    participant PortfolioRepo as IPortfolioRepository
    participant TxnUOW as ITransactionalUnitOfWork
    participant EventDispatcher

    Client->>RefreshHandler: HandleAsync(RefreshOrderStatusCommand)
    RefreshHandler->>OrderRepo: GetByIdAsync(orderId)
    OrderRepo-->>RefreshHandler: OrderLifecycle
    RefreshHandler->>ExchangePort: GetOrderAsync(exchangeOrderId)
    ExchangePort-->>RefreshHandler: ExchangeOrderInfo
    RefreshHandler->>Factory: Refresh(lifecycle, exchangeOrderInfo)
    Factory-->>RefreshHandler: bool (changed)
    
    alt Status Changed or Unapplied Fill
        RefreshHandler->>TxnUOW: BeginTransactionAsync()
        
        alt Intent == OpenPosition
            RefreshHandler->>PositionRepo: GetByPairAsync(pair)
            PositionRepo-->>RefreshHandler: Position
            RefreshHandler->>RefreshHandler: Create/Update Position
        else Intent == ClosePosition
            RefreshHandler->>PositionRepo: GetByIdAsync(posId)
            PositionRepo-->>RefreshHandler: Position
            RefreshHandler->>RefreshHandler: ApplyCloseFillDelta()
        else Intent == ExecuteDca
            RefreshHandler->>PositionRepo: GetByIdAsync(posId)
            PositionRepo-->>RefreshHandler: Position
            RefreshHandler->>RefreshHandler: ApplyDCAFillDelta()
        end
        
        RefreshHandler->>PortfolioRepo: GetDefaultAsync()
        PortfolioRepo-->>RefreshHandler: Portfolio
        RefreshHandler->>RefreshHandler: Update Portfolio Balance
        
        RefreshHandler->>OrderRepo: SaveAsync(orderLifecycle)
        RefreshHandler->>PositionRepo: SaveAsync(position)
        RefreshHandler->>PortfolioRepo: SaveAsync(portfolio)
        
        RefreshHandler->>TxnUOW: CommitAsync()
        TxnUOW-->>RefreshHandler: Result
        
        alt Commit Success
            RefreshHandler->>EventDispatcher: DispatchAsync(orderEvents + positionEvents)
        else Commit Failure
            RefreshHandler->>TxnUOW: RollbackAsync()
            RefreshHandler-->>Client: Failure(error)
        end
    end
    
    RefreshHandler-->>Client: RefreshOrderStatusResult
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Poem

🐰 Hoppy refactoring, orders now persist,
Lifecycles tracked from exchange to list,
Transactional hops through JSON so bright,
Background refresh keeps portfolios tight!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/cqrs-open-position-foundation

@codecov

codecov Bot commented Apr 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.28099% with 243 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...der.Domain/Trading/Aggregates/Position/Position.cs 83.94% 11 Missing and 11 partials ⚠️
...tion/Trading/Handlers/RefreshOrderStatusHandler.cs 90.74% 8 Missing and 13 partials ⚠️
...ication/Trading/Handlers/PortfolioQueryHandlers.cs 83.05% 5 Missing and 15 partials ⚠️
...Application/Trading/Handlers/OrderQueryHandlers.cs 80.61% 3 Missing and 16 partials ⚠️
...plication/Trading/Handlers/ClosePositionHandler.cs 81.01% 11 Missing and 4 partials ⚠️
...apters/Persistence/Json/JsonPortfolioRepository.cs 91.50% 6 Missing and 7 partials ⚠️
...ucture/Transactions/JsonTransactionalUnitOfWork.cs 88.98% 5 Missing and 8 partials ⚠️
...ntelliTrader.Application/Trading/TradingUseCase.cs 92.40% 3 Missing and 9 partials ⚠️
...lication/Trading/Handlers/PositionQueryHandlers.cs 89.71% 1 Missing and 10 partials ⚠️
.../Trading/Handlers/ExchangeOrderLifecycleFactory.cs 91.89% 6 Missing and 3 partials ⚠️
... and 17 more
Files with missing lines Coverage Δ
...tion/Trading/Commands/RefreshOrderStatusCommand.cs 100.00% <100.00%> (ø)
.../Trading/Commands/RefreshSubmittedOrdersCommand.cs 100.00% <100.00%> (ø)
...Trader.Application/Trading/Queries/OrderQueries.cs 100.00% <100.00%> (ø)
IntelliTrader.Core/Services/CoreService.cs 55.90% <100.00%> (+26.30%) ⬆️
...ure/Adapters/Persistence/Json/OrderLifecycleDto.cs 100.00% <100.00%> (ø)
...tructure/Adapters/Persistence/Json/PortfolioDto.cs 100.00% <100.00%> (ø)
...r.Infrastructure/Events/OrderFilledAuditHandler.cs 90.00% <90.00%> (ø)
...r.Infrastructure/Events/OrderPlacedAuditHandler.cs 88.88% <88.88%> (ø)
...nfrastructure/Events/PositionOpenedAuditHandler.cs 90.00% <90.00%> (ø)
...r.Domain/Trading/Aggregates/Portfolio/Portfolio.cs 94.24% <85.71%> (-0.24%) ⬇️
... and 23 more

... and 18 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@blackms blackms marked this pull request as ready for review April 24, 2026 17:02
@blackms blackms merged commit 24ea348 into main Apr 24, 2026
1 of 2 checks passed
@blackms blackms deleted the codex/cqrs-open-position-foundation branch April 24, 2026 17:47
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