**Wave D Phase 6 - Technical Debt Cleanup (Agent C6)** ## Changes - Identified deprecated code patterns across codebase - Analyzed mock repository usage (strategically retained per AGENT_M13) - Documented deprecation cleanup strategy - Prepared deprecation removal todos ## Analysis Results - Mock structs: RETAINED (strategic testing infrastructure) - Never-read fields: 2 instances in backtesting_service - Dead code warnings: 35 total across workspace - databento_old references: None found in active code ## Status - ✅ Deprecation analysis complete - ⏳ Cleanup execution pending user confirmation - 📊 Test impact assessment ready 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
15 KiB
Agent M1: Backtesting Mock Usage Analysis Report
Mission: Investigate why backtesting service uses mocks instead of real data
Analysis Date: 2025-10-18 Analyst: Agent M1 Status: COMPLETE
Executive Summary
The backtesting service has dual repository architecture:
- Mocks (174 usages): Used EXCLUSIVELY in unit/integration tests for fast, deterministic testing
- Real Implementations (67 usages): Used in production and real-data backtests
Verdict: Mocks are NECESSARY and WELL-DESIGNED. They serve a legitimate, important purpose for unit testing. DELETE recommendation: REJECT - keep mocks, they are not legacy code.
Findings
1. Mock Repository Definitions
Location: /home/jgrusewski/Work/foxhunt/services/backtesting_service/src/repositories.rs (301 lines)
Three mock implementations:
MockMarketDataRepository(23 lines) - Returns empty VecMockTradingRepository(59 lines) - In-memory store with RwLockMockNewsRepository(22 lines) - Returns empty Vec
Key Code:
// Production: Defaults to empty implementations
pub struct MockMarketDataRepository;
#[async_trait]
impl MarketDataRepository for MockMarketDataRepository {
async fn load_historical_data(...) -> Result<Vec<...>> {
Ok(vec![]) // Empty implementation for unit tests
}
}
Also in test directory: /home/jgrusewski/Work/foxhunt/services/backtesting_service/tests/mock_repositories.rs (440 lines)
This file contains DIFFERENT, STATEFUL MOCK IMPLEMENTATIONS:
MockMarketDataRepository- WithArc<RwLock<Vec<MarketData>>>for holding test dataMockTradingRepository- WithArc<RwLock<HashMap>>for tracking trades and metricsMockNewsRepository- WithArc<RwLock<Vec<NewsEvent>>>for events- Helper functions:
generate_sample_market_data(),generate_sample_news_events() - Factory function:
create_dbn_repository()- Creates real DBN repository
2. Mock Usage Breakdown
Total Occurrences: 174 lines matching mock repository patterns
| Mock Type | Count | Primary Usage |
|---|---|---|
MockMarketDataRepository |
59 | Unit tests for strategy logic |
MockTradingRepository |
61 | Unit tests for trade execution |
MockNewsRepository |
54 | Unit tests for news integration |
Usage Pattern Distribution:
| Category | Files | Purpose |
|---|---|---|
| Unit Tests | 8 test files | Fast, deterministic strategy testing |
| Strategy Tests | strategy_engine_tests.rs |
Portfolio management, position tracking |
| Integration Tests | integration_tests.rs |
Multi-strategy execution |
| Service Tests | service_tests.rs |
gRPC service validation |
| Wave Comparison | wave_comparison.rs (src/) |
Metric calculation validation (2 usages) |
3. Real Repository Implementations
Location: /home/jgrusewski/Work/foxhunt/services/backtesting_service/src/repository_impl.rs (365 lines)
Four real implementations:
| Implementation | Purpose | Data Source |
|---|---|---|
DataProviderMarketDataRepository |
Production market data | Databento API |
StorageManagerTradingRepository |
Results persistence | PostgreSQL |
BenzingaNewsRepository |
News events | Benzinga API |
DbnMarketDataRepository |
Real historical data | DBN files (test_data/) |
Factory Function (line 297):
pub async fn create_repositories(
storage_manager: Arc<StorageManager>,
) -> Result<DefaultRepositories> {
// Checks USE_DBN_DATA environment variable:
// - "true": DbnMarketDataRepository (local test files)
// - "false" or unset: DataProviderMarketDataRepository (Databento API)
...
}
Production Usage: main.rs line 133:
let repositories = Arc::new(
create_repositories(storage_manager)
.await
.context("Failed to create repositories")?,
);
4. Test File Analysis
Files Using Mocks (8 files, 174 occurrences):
strategy_engine_tests.rs- 50+ usages (portfolio, position tracking, multi-strategy)service_tests.rs- 5+ usages (gRPC service testing)integration_tests.rs- Uses mocksma_crossover_multi_symbol_tests.rs- Multi-symbol strategy testsdata_replay.rs- Data replay with mocks and real datastrategy_execution.rs- Order execution testsreport_generation.rs- Report generation testsmock_repositories.rs- Test helpers and mock implementations
Files Using Real Data (15 files):
dbn_integration_tests.rs- Full DBN file loading testsdbn_loader_filtering_test.rs- DBN filtering validationdbn_performance_tests.rs- DBN parsing performancedbn_multi_symbol_tests.rs- Multi-symbol DBN testsdbn_multi_day_tests.rs- Multi-day backtestsdbn_filtering_validation.rs- Data filtering edge casesml_strategy_backtest_test.rs- ML strategy with real datawave_d_regime_backtest_test.rs- Regime detection with real dataedge_cases_and_error_handling.rs- Real data edge caseshealth_check_tests.rs- Health checksperformance_metrics.rs- Performance with real data- And others...
Hybrid Approach (data_replay.rs):
- Uses BOTH mocks and real DBN data
- Tests can switch between modes for comprehensive coverage
5. Why Mocks Exist - Design Justification
A. Fast Unit Testing (Primary Reason)
// Tests use mocks for deterministic, in-memory testing
let market_data_repo = Box::new(MockMarketDataRepository::with_data(market_data.clone()));
let engine = StrategyEngine::new(&config, repositories).await?;
// No I/O overhead, no API calls, no file loading
// Executes in milliseconds
B. Deterministic Test Data
// generate_sample_market_data() creates predictable sine-wave prices
// Ensures tests pass consistently, not flaky
pub fn generate_sample_market_data(
symbol: &str,
num_points: usize,
start_price: f64,
volatility: f64,
) -> Vec<MarketData>
C. Isolation from External Dependencies
- No database connection required
- No API credentials needed
- No file system access
- Tests can run in any environment (CI/CD, offline, etc.)
D. Specific Scenario Testing
// Can test exact conditions:
// - Partial fills
// - Transaction costs
// - Position sizing edge cases
// - News event correlations
let market_data_repo = Box::new(
MockMarketDataRepository::with_data(specific_test_scenario)
);
E. Wave Comparison Validation (src/ code)
// Uses mocks for metric calculation verification
// Ensures improvement calculations are correct
// Not testing data loading, only metric math
let backtest = WaveComparisonBacktest::new(
Arc::new(DefaultRepositories::mock()),
100000.0,
);
6. Real Data Testing Strategy
Separate, Parallel Approach:
- Mocks: Fast unit tests (< 1 second)
- DBN: Real data integration tests (1-10 seconds)
- Both approaches coexist in CI/CD pipeline
Examples:
- Unit Test with Mocks (strategy_engine_tests.rs):
#[tokio::test]
async fn test_position_tracking_buy_sell_cycles() -> Result<()> {
let market_data_repo = Box::new(
MockMarketDataRepository::with_data(market_data.clone())
);
let engine = StrategyEngine::new(&config, repositories).await?;
let trades = engine.execute_backtest(&context).await?;
// Assert specific trade sequences
}
- Integration Test with Real DBN Data (dbn_integration_tests.rs):
#[tokio::test]
async fn test_real_dbn_data_loading() -> Result<()> {
let repo = DbnMarketDataRepository::new(file_mapping).await?;
let data = repo.load_historical_data(&symbols, start_time, end_time).await?;
// Assert real market data patterns
}
7. Production Code Does NOT Use Mocks
main.rs line 133 - Production entry point:
// Creates REAL repositories, never mocks
let repositories = Arc::new(
create_repositories(storage_manager)
.await
.context("Failed to create repositories")?,
);
// Uses either Databento API or DBN files, based on environment
// USE_DBN_DATA environment variable controls mode
No mock usage in production code - Only in tests and wave comparison calculations.
8. Architecture Summary
┌─────────────────────────────────────────┐
│ Backtesting Service │
├─────────────────────────────────────────┤
│ Production Code (main.rs) │
│ └─ create_repositories() │
│ ├─ DbnMarketDataRepository │ ← Real: DBN files
│ ├─ DataProviderMarketDataRepository│ ← Real: Databento API
│ ├─ StorageManagerTradingRepository │ ← Real: PostgreSQL
│ └─ BenzingaNewsRepository │ ← Real: Benzinga API
│ │
│ Test Code │
│ ├─ Unit Tests (Fast) │
│ │ └─ MockMarketDataRepository │ ← Mock: In-memory
│ │ └─ MockTradingRepository │ ← Mock: In-memory
│ │ └─ MockNewsRepository │ ← Mock: In-memory
│ │ │
│ └─ Integration Tests (Real Data) │
│ └─ DbnMarketDataRepository │ ← Real: DBN files
│ └─ StorageManager │ ← Real: PostgreSQL
│ │
│ Wave Comparison (Validation) │
│ └─ DefaultRepositories::mock() │ ← Mock (no data needed)
│ (Only validates metric math, not data loading)
└─────────────────────────────────────────┘
9. Test Coverage Impact
| Test Category | Count | Data Source | Typical Duration |
|---|---|---|---|
| Unit Tests | 50+ | Mock (in-memory) | <1 sec total |
| Integration Tests (Real Data) | 40+ | DBN files | 1-10 sec each |
| E2E Tests | Several | Mix of both | 5-30 sec |
| Total Test Pass Rate | 1,403/1,427 (98.3%) | Mixed | Variable |
10. Code Statistics
| Component | Lines | Purpose |
|---|---|---|
| Mock definitions (src/) | 112 | Simple empty implementations |
| Mock implementations (tests/) | 440 | Stateful test helpers + generators |
| Real implementations | 365+ | Production data loading |
| Mock usage in tests | 174 total | Test isolation |
| Real usage in production | 67 total | Real data in main.rs, ml_strategy_engine.rs, dbn_repository.rs tests |
Recommendations
1. KEEP Mocks - DO NOT DELETE
Rationale:
- Mocks are essential for fast, deterministic unit testing
- They provide test isolation from external dependencies
- They enable testing of specific edge cases
- They follow industry best practices (dependency injection, mocking)
- They cause zero performance impact in production
2. Improve Mock Organization (Optional)
Current: Two separate mock implementations (src/ and tests/) Options:
- Option A (Recommended): Keep current structure - tests/ mocks are richer and reusable
- Option B: Consolidate to single location if tests/ mocks fully replace src/ mocks
- Requires audit of src/ mock usage
3. Enhance Documentation
- Add comments explaining mock vs. real repository selection
- Document environment variables:
USE_DBN_DATA,DBN_SYMBOL_MAPPINGS - Create troubleshooting guide for switching between mock/real modes
4. Validate CI/CD Pipeline
- Ensure unit tests (with mocks) run in fast path
- Ensure integration tests (with real data) run in separate phase
- Confirm production code never uses mocks
Detailed Usage Breakdown
Mock Usage by Test File
| Test File | Mock Type | Count | Purpose |
|---|---|---|---|
| strategy_engine_tests.rs | MarketData | 15+ | Portfolio state tests |
| strategy_engine_tests.rs | Trading | 15+ | Trade execution tests |
| strategy_engine_tests.rs | News | 10+ | News integration tests |
| service_tests.rs | All 3 | 5 | gRPC service validation |
| integration_tests.rs | MarketData | 8+ | Multi-symbol tests |
| ma_crossover_multi_symbol_tests.rs | MarketData | 8+ | Multi-asset validation |
| strategy_execution.rs | Trading | 12+ | Order execution tests |
| report_generation.rs | Trading | 8+ | Report generation tests |
| data_replay.rs | Mixed | 20+ | Hybrid mock + real data |
| Total | All | 174 | Fast test isolation |
Real Usage by Source File
| Source File | Real Type | Count | Purpose |
|---|---|---|---|
| main.rs | All 3 | 3 | Production initialization |
| ml_strategy_engine.rs | All 3 | 8 | ML backtesting pipeline |
| dbn_repository.rs | DbnMarketDataRepository | 24 | DBN file loading + tests |
| repository_impl.rs | All 3 | 12 | Factory + implementations |
| dbn_integration_tests.rs | DbnMarketDataRepository | 20 | Real data integration |
| Total | All | 67 | Real data loading/testing |
Conclusion
The backtesting service demonstrates excellent software engineering practices:
- Clear Separation of Concerns: Mocks for unit tests, real implementations for integration tests
- Dependency Injection: Service accepts repositories as abstractions, not concrete types
- Production Safety: Main.rs never uses mocks, always creates real repositories
- Test Performance: Fast unit tests with mocks, separate real data integration tests
- Maintainability: Two layers of mock implementations serve different purposes (empty stubs vs. stateful test helpers)
Mocks are NOT legacy code - they are ESSENTIAL for the testing architecture.
Appendix: File Locations
Mock Definitions:
/home/jgrusewski/Work/foxhunt/services/backtesting_service/src/repositories.rs(lines 188-302)/home/jgrusewski/Work/foxhunt/services/backtesting_service/tests/mock_repositories.rs(entire file)
Real Implementations:
/home/jgrusewski/Work/foxhunt/services/backtesting_service/src/repository_impl.rs/home/jgrusewski/Work/foxhunt/services/backtesting_service/src/dbn_repository.rs
Production Code Using Repositories:
/home/jgrusewski/Work/foxhunt/services/backtesting_service/src/main.rs(line 133)/home/jgrusewski/Work/foxhunt/services/backtesting_service/src/ml_strategy_engine.rs(line 362)
Test Files Using Mocks (8 files):
- strategy_engine_tests.rs
- service_tests.rs
- integration_tests.rs
- ma_crossover_multi_symbol_tests.rs
- strategy_execution.rs
- report_generation.rs
- data_replay.rs
- mock_repositories.rs
Test Files Using Real Data (15+ files):
- dbn_integration_tests.rs
- dbn_loader_filtering_test.rs
- dbn_performance_tests.rs
- dbn_multi_symbol_tests.rs
- dbn_multi_day_tests.rs
- ml_strategy_backtest_test.rs
- wave_d_regime_backtest_test.rs
- edge_cases_and_error_handling.rs
- (and 7+ others)
Report End