stock-bot/apps/stock/engine/MIGRATION.md
2025-07-04 11:24:27 -04:00

4.6 KiB

Migration Guide: Modular Architecture

This guide explains how to migrate from the current monolithic structure to the new modular architecture.

Overview

The new architecture introduces:

  • Domain-driven design with separated domain types
  • Event-driven architecture with EventBus
  • Mode-based trading engines (Backtest, Paper, Live)
  • Modular API structure
  • Enhanced strategy framework

Migration Steps

Step 1: Use Adapters for Compatibility

The adapters module provides compatibility between old and new implementations:

ExecutionHandler Adapters

use engine::adapters::{ExecutionHandlerAdapter, NewExecutionHandler};

// Wrap a new-style handler to work with old interface
let new_handler = MyNewExecutionHandler::new();
let adapted = ExecutionHandlerAdapter::new(new_handler);
// Now 'adapted' implements the old ExecutionHandler trait

// Or wrap an old handler to work with new interface
use engine::adapters::LegacyExecutionHandlerAdapter;
let old_handler = MyOldExecutionHandler::new();
let adapted = LegacyExecutionHandlerAdapter::new(old_handler);
// Now 'adapted' implements NewExecutionHandler

Event System Adapters

use engine::adapters::events::{EventBusAdapter, EventAdapter};

// Create adapter that bridges old and new event systems
let mut adapter = EventBusAdapter::new();

// Use old-style event handling
adapter.subscribe_old("market_update", |event| {
    // Handle event in old format
});

// Events are automatically converted between formats

Strategy Adapters

use engine::adapters::strategy::{NewToOldStrategyAdapter, OldToNewStrategyAdapter};

// Use new strategy with old system
let new_strategy = MyNewStrategy::new();
let context = Arc::new(StrategyContext::new());
let adapted = NewToOldStrategyAdapter::new(Box::new(new_strategy), context);

// Use old strategy with new system
let old_strategy = MyOldStrategy::new();
let adapted = OldToNewStrategyAdapter::new(Box::new(old_strategy));

Step 2: Gradual Module Migration

  1. Start with Domain Types (Low Risk)

    • Move from inline types to domain::market, domain::orders, etc.
    • These are mostly data structures with minimal behavior
  2. Migrate Event System (Medium Risk)

    • Replace direct callbacks with EventBus subscriptions
    • Use EventBusAdapter during transition
  3. Update Strategy Framework (Medium Risk)

    • Migrate strategies one at a time using adapters
    • Test thoroughly before removing adapters
  4. Implement Mode-Specific Engines (High Risk)

    • Start with backtest mode (most isolated)
    • Move to paper trading
    • Finally implement live trading
  5. API Migration (Final Step)

    • Run old and new APIs in parallel
    • Gradually move endpoints to new structure
    • Deprecate old API when stable

Step 3: Remove Adapters

Once all components are migrated:

  1. Remove adapter usage
  2. Delete old implementations
  3. Remove adapter modules

Testing Strategy

  1. Unit Tests: Test adapters ensure compatibility
  2. Integration Tests: Verify old and new systems work together
  3. Regression Tests: Ensure no functionality is lost
  4. Performance Tests: Verify no performance degradation

Common Issues and Solutions

Issue: Trait method signatures don't match

Solution: Use adapters to bridge the differences

Issue: Event types are incompatible

Solution: Use EventAdapter for conversion

Issue: Existing code expects synchronous behavior

Solution: Use tokio::runtime::Handle::current().block_on() temporarily

Issue: New modules not found

Solution: Ensure modules are properly declared in lib.rs

Example Migration

Here's a complete example migrating a backtest:

// Old way
use engine::backtest::BacktestEngine as OldBacktest;
let old_engine = OldBacktest::new(config);

// During migration (using adapters)
use engine::adapters::ExecutionHandlerAdapter;
use engine::modes::backtest::BacktestEngine as NewBacktest;

let new_engine = NewBacktest::new(config);
let execution_handler = ExecutionHandlerAdapter::new(new_engine.get_execution_handler());

// After migration
use engine::modes::backtest::BacktestEngine;
let engine = BacktestEngine::new(config);

Timeline

  1. Week 1-2: Implement and test adapters
  2. Week 3-4: Migrate domain types and events
  3. Week 5-6: Migrate strategies and modes
  4. Week 7-8: Migrate API and cleanup

Support

For questions or issues during migration:

  1. Check adapter documentation
  2. Review test examples
  3. Consult team lead for architectural decisions