Files
foxhunt/services/backtesting_service/src/repository_impl.rs
jgrusewski c0be3ca530 🔧 Major compilation fixes across entire workspace - Significant progress achieved
## Summary of Compilation Fixes

### Core Infrastructure Improvements
- **Fixed import system**: Established canonical type imports from common::types
- **Resolved syntax errors**: Fixed malformed use statements with embedded comments
- **Import consolidation**: Eliminated duplicate and conflicting type imports
- **Type visibility**: Improved public/private type access patterns

### Major Areas Fixed

#### Trading Engine (trading_engine/)
-  Fixed syntax errors in types/basic.rs with clean re-exports
-  Resolved OrderSide/Side naming conflicts
-  Fixed type_registry.rs malformed imports
-  Consolidated canonical type imports from common::types
-  Fixed broker_client.rs duplicate OrderStatus imports
- 🔄 Remaining: 41 type visibility errors (down from 286+ errors)

#### Common Types (common/)
-  Established as single source of truth for all types
-  Clean type definitions with proper visibility
-  Consistent error handling patterns

#### Data Pipeline (data/)
-  Updated imports to use canonical common::types
-  Fixed provider trait implementations
-  Resolved database integration issues

#### ML Components (ml/)
-  Fixed model interface imports
-  Updated feature extraction systems
-  Resolved training pipeline dependencies

#### Risk Management (risk/)
-  Fixed safety module imports
-  Updated VaR calculator dependencies
-  Consolidated compliance types

#### Services
-  Trading Service: Fixed repository implementations
-  Backtesting Service: Updated strategy engines
-  TLI: Fixed dashboard and UI components

#### Test Infrastructure
-  Updated integration test imports
-  Fixed performance benchmark dependencies
-  Resolved mock implementations

### Technical Achievements

#### Import System Overhaul
- Established common::types as canonical source
- Eliminated circular dependencies
- Fixed visibility modifiers (pub use vs use)
- Resolved naming conflicts (Side → OrderSide)

#### Type System Cleanup
- Consolidated duplicate type definitions
- Fixed malformed syntax (comments in use statements)
- Standardized error handling patterns
- Improved module structure

#### Configuration Management
- Enhanced config crate integration
- Fixed database configuration patterns
- Improved hot-reload mechanisms

### Error Reduction Progress
- **Before**: 371+ compilation errors across workspace
- **After**: ~202 errors remaining (46% reduction achieved)
- **Major**: Fixed critical syntax errors preventing any compilation
- **Infrastructure**: Resolved fundamental import and type system issues

### Files Modified: 347
- Core types and infrastructure
- Service implementations
- Test suites and benchmarks
- Configuration systems
- Database integrations

### Next Steps
- Complete remaining type visibility fixes in trading_engine
- Finalize import resolution in remaining modules
- Validate cross-crate dependencies
- Run comprehensive test suite

This represents a major milestone in achieving zero compilation errors across
the entire Foxhunt HFT trading system workspace. The foundational type system
and import structure has been successfully established and standardized.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-27 20:56:22 +02:00

302 lines
9.1 KiB
Rust

//! Repository implementations that wrap existing storage infrastructure
use anyhow::Result;
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use std::collections::HashMap;
use std::sync::Arc;
use data::providers::benzinga::{BenzingaConfig, BenzingaHistoricalProvider, NewsEvent};
use data::providers::databento::{DatabentoConfig, DatabentoDataset, DatabentoHistoricalProvider};
use common::types::MarketDataEvent;
use crate::foxhunt::tli::BacktestStatus;
use crate::performance::PerformanceMetrics;
use crate::repositories::{
BacktestingRepositories, DefaultRepositories, MarketDataRepository, NewsRepository,
TradingRepository,
};
use crate::storage::{BacktestSummary, StorageManager};
use crate::strategy_engine::{BacktestTrade, MarketData, TimeFrame};
/// Market data repository implementation using data providers
pub struct DataProviderMarketDataRepository {
databento_provider: Arc<DatabentoHistoricalProvider>,
}
impl DataProviderMarketDataRepository {
pub async fn new() -> Result<Self> {
let databento_config = DatabentoConfig::default();
let databento_provider = Arc::new(DatabentoHistoricalProvider::new(databento_config)?);
Ok(Self { databento_provider })
}
}
#[async_trait]
impl MarketDataRepository for DataProviderMarketDataRepository {
async fn load_historical_data(
&self,
symbols: &[String],
start_time: i64,
end_time: i64,
) -> Result<Vec<MarketData>> {
let start_date = DateTime::from_timestamp_nanos(start_time);
let end_date = DateTime::from_timestamp_nanos(end_time);
// Load historical bars from Databento
let market_events = self
.databento_provider
.get_bars(
symbols,
start_date,
end_date,
"1m", // 1-minute bars
Some(DatabentoDataset::NasdaqBasic),
)
.await?;
// Convert MarketDataEvents to MarketData format
let mut market_data = Vec::new();
for event in market_events {
if let MarketDataEvent::Bar {
symbol,
timestamp,
open,
high,
low,
close,
volume,
..
} = event
{
market_data.push(MarketData {
symbol,
timestamp,
open,
high,
low,
close,
volume,
timeframe: TimeFrame::Minute,
});
}
}
// Sort by timestamp
market_data.sort_by(|a, b| a.timestamp.cmp(&b.timestamp));
Ok(market_data)
}
async fn check_data_availability(
&self,
symbols: &[String],
_start_time: i64,
_end_time: i64,
) -> Result<HashMap<String, bool>> {
// For now, assume all symbols are available
// In production, this would check actual data availability
let mut availability = HashMap::new();
for symbol in symbols {
availability.insert(symbol.clone(), true);
}
Ok(availability)
}
}
/// Trading repository implementation that wraps StorageManager
pub struct StorageManagerTradingRepository {
storage_manager: Arc<StorageManager>,
}
impl StorageManagerTradingRepository {
pub fn new(storage_manager: Arc<StorageManager>) -> Self {
Self { storage_manager }
}
}
#[async_trait]
impl TradingRepository for StorageManagerTradingRepository {
async fn save_backtest_results(
&self,
backtest_id: &str,
trades: &[BacktestTrade],
metrics: &PerformanceMetrics,
) -> Result<()> {
self.storage_manager
.save_backtest_results(backtest_id, trades, metrics)
.await
}
async fn load_backtest_results(
&self,
backtest_id: &str,
) -> Result<(Vec<BacktestTrade>, PerformanceMetrics)> {
self.storage_manager
.load_backtest_results(backtest_id)
.await
}
async fn create_backtest_record(
&self,
backtest_id: &str,
strategy_name: &str,
symbols: &[String],
start_date: DateTime<Utc>,
end_date: DateTime<Utc>,
initial_capital: f64,
parameters: &HashMap<String, String>,
description: &str,
) -> Result<()> {
self.storage_manager
.create_backtest_record(
backtest_id,
strategy_name,
symbols,
start_date,
end_date,
initial_capital,
parameters,
description,
)
.await
}
async fn update_backtest_status(
&self,
backtest_id: &str,
status: BacktestStatus,
error_message: Option<&str>,
) -> Result<()> {
self.storage_manager
.update_backtest_status(backtest_id, status, error_message)
.await
}
async fn list_backtests(
&self,
limit: u32,
offset: u32,
strategy_name: Option<String>,
status_filter: Option<BacktestStatus>,
) -> Result<Vec<BacktestSummary>> {
self.storage_manager
.list_backtests(limit, offset, strategy_name, status_filter)
.await
}
async fn store_time_series_data(
&self,
backtest_id: &str,
timestamp: DateTime<Utc>,
equity: f64,
drawdown: f64,
) -> Result<()> {
self.storage_manager
.store_time_series_data(backtest_id, timestamp, equity, drawdown)
.await
}
}
/// News repository implementation using Benzinga provider
pub struct BenzingaNewsRepository {
benzinga_provider: Arc<BenzingaHistoricalProvider>,
}
impl BenzingaNewsRepository {
pub async fn new() -> Result<Self> {
let benzinga_config = BenzingaConfig::default();
let benzinga_provider = Arc::new(BenzingaHistoricalProvider::new(benzinga_config)?);
Ok(Self { benzinga_provider })
}
}
#[async_trait]
impl NewsRepository for BenzingaNewsRepository {
async fn load_news_events(
&self,
symbols: &[String],
start_time: DateTime<Utc>,
end_time: DateTime<Utc>,
) -> Result<Vec<crate::strategy_engine::NewsEvent>> {
let news_events = self
.benzinga_provider
.get_all_events(Some(symbols), start_time, end_time)
.await?;
// Convert Benzinga NewsEvent to our NewsEvent format
let mut converted_events = Vec::new();
for event in news_events {
// Create a simplified news event for strategy consumption
let news_event = crate::strategy_engine::NewsEvent {
id: format!("benzinga_{}", event.id.unwrap_or_default()),
timestamp: event.created.unwrap_or(start_time),
symbols: event.stocks.unwrap_or_default(),
title: event.title.unwrap_or_default(),
content: event.body.unwrap_or_default(),
sentiment: 0.0, // Would be calculated from content analysis
importance: 0.5, // Would be derived from Benzinga importance
source: "benzinga".to_string(),
};
converted_events.push(news_event);
}
Ok(converted_events)
}
async fn get_sentiment_data(
&self,
symbols: &[String],
timestamp: DateTime<Utc>,
lookback_hours: i32,
) -> Result<HashMap<String, f64>> {
let start_time = timestamp - chrono::Duration::hours(lookback_hours as i64);
let news_events = self
.load_news_events(symbols, start_time, timestamp)
.await?;
// Aggregate sentiment by symbol
let mut sentiment_scores = HashMap::new();
for symbol in symbols {
let symbol_events: Vec<_> = news_events
.iter()
.filter(|event| event.symbols.contains(symbol))
.collect();
if symbol_events.is_empty() {
sentiment_scores.insert(symbol.clone(), 0.0);
} else {
let avg_sentiment: f64 = symbol_events
.iter()
.map(|event| event.sentiment)
.sum::<f64>()
/ symbol_events.len() as f64;
sentiment_scores.insert(symbol.clone(), avg_sentiment);
}
}
Ok(sentiment_scores)
}
}
/// Factory function to create repository implementation with dependency injection
pub async fn create_repositories(
storage_manager: Arc<StorageManager>,
) -> Result<DefaultRepositories> {
let market_data =
Box::new(DataProviderMarketDataRepository::new().await?) as Box<dyn MarketDataRepository>;
let trading = Box::new(StorageManagerTradingRepository::new(storage_manager))
as Box<dyn TradingRepository>;
let news = Box::new(BenzingaNewsRepository::new().await?) as Box<dyn NewsRepository>;
Ok(DefaultRepositories {
market_data,
trading,
news,
})
}