|
| 1 | +# Statistics System Migration Guide (v3.2.1 → v3.3.0) |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +The v3.3.0 release introduces a completely redesigned statistics system that is 100% async internally. This guide helps you migrate from the old mixed sync/async patterns to the new unified async architecture. |
| 6 | + |
| 7 | +## Key Changes |
| 8 | + |
| 9 | +### 1. All New Statistics Methods are Async |
| 10 | + |
| 11 | +**Old Pattern (v3.2.1):** |
| 12 | +```python |
| 13 | +# Mixed sync/async methods caused deadlocks |
| 14 | +stats = component.get_memory_stats() # Synchronous |
| 15 | +await component.track_operation("test") # Async |
| 16 | +``` |
| 17 | + |
| 18 | +**New Pattern (v3.3.0):** |
| 19 | +```python |
| 20 | +# All new methods are async |
| 21 | +stats = await component.get_stats() # Async |
| 22 | +health = await component.get_health_score() # Async |
| 23 | +await component.track_error(error, "context") # Async |
| 24 | +``` |
| 25 | + |
| 26 | +### 2. Backward Compatibility |
| 27 | + |
| 28 | +For backward compatibility, `get_memory_stats()` remains synchronous: |
| 29 | + |
| 30 | +```python |
| 31 | +# Still works for existing code |
| 32 | +memory_stats = component.get_memory_stats() # Synchronous - DEPRECATED |
| 33 | +``` |
| 34 | + |
| 35 | +This method is deprecated and will be removed in v4.0.0. New code should use: |
| 36 | + |
| 37 | +```python |
| 38 | +# New async approach |
| 39 | +stats = await component.get_stats() |
| 40 | +memory_usage = await component.get_memory_usage() |
| 41 | +``` |
| 42 | + |
| 43 | +## Migration Strategy |
| 44 | + |
| 45 | +### Phase 1: Immediate Changes (Required) |
| 46 | + |
| 47 | +1. **Remove old imports:** |
| 48 | +```python |
| 49 | +# Remove these |
| 50 | +from project_x_py.utils import EnhancedStatsTrackingMixin |
| 51 | +from project_x_py.utils import StatsTrackingMixin |
| 52 | +from project_x_py.utils import StatisticsAggregator |
| 53 | + |
| 54 | +# Use these instead |
| 55 | +from project_x_py.statistics import ( |
| 56 | + BaseStatisticsTracker, |
| 57 | + StatisticsAggregator, |
| 58 | + HealthMonitor, |
| 59 | + StatsExporter |
| 60 | +) |
| 61 | +``` |
| 62 | + |
| 63 | +2. **Update statistics calls to async:** |
| 64 | +```python |
| 65 | +# Old |
| 66 | +stats = manager.get_order_statistics() |
| 67 | + |
| 68 | +# New |
| 69 | +stats = await manager.get_order_statistics_async() |
| 70 | +# Or for new unified interface: |
| 71 | +stats = await manager.get_stats() |
| 72 | +``` |
| 73 | + |
| 74 | +### Phase 2: Recommended Updates |
| 75 | + |
| 76 | +1. **Use new health monitoring:** |
| 77 | +```python |
| 78 | +# Get component health score (0-100) |
| 79 | +health = await component.get_health_score() |
| 80 | + |
| 81 | +# Get detailed health breakdown |
| 82 | +monitor = HealthMonitor() |
| 83 | +breakdown = await monitor.get_health_breakdown(stats) |
| 84 | +``` |
| 85 | + |
| 86 | +2. **Use new export capabilities:** |
| 87 | +```python |
| 88 | +from project_x_py.statistics import StatsExporter |
| 89 | + |
| 90 | +exporter = StatsExporter() |
| 91 | +json_stats = await exporter.to_json(stats, pretty=True) |
| 92 | +prometheus_metrics = await exporter.to_prometheus(stats) |
| 93 | +``` |
| 94 | + |
| 95 | +3. **Use new error tracking:** |
| 96 | +```python |
| 97 | +# Track errors with context |
| 98 | +await component.track_error( |
| 99 | + error=exception, |
| 100 | + context="order_placement", |
| 101 | + details={"order_id": "12345", "size": 10} |
| 102 | +) |
| 103 | + |
| 104 | +# Get error statistics |
| 105 | +error_count = await component.get_error_count() |
| 106 | +recent_errors = await component.get_recent_errors(limit=10) |
| 107 | +``` |
| 108 | + |
| 109 | +## Component-Specific Notes |
| 110 | + |
| 111 | +### OrderManager |
| 112 | +- `get_order_statistics()` → `await get_order_statistics_async()` (new method) |
| 113 | +- Internal statistics automatically tracked on order events |
| 114 | + |
| 115 | +### PositionManager |
| 116 | +- `get_position_stats()` → `await get_position_stats()` (new async method) |
| 117 | +- P&L tracking now automatic with event system |
| 118 | + |
| 119 | +### RealtimeDataManager |
| 120 | +- Uses composition pattern with BaseStatisticsTracker |
| 121 | +- All statistics methods delegated to internal tracker |
| 122 | + |
| 123 | +### OrderBook |
| 124 | +- Now inherits from BaseStatisticsTracker |
| 125 | +- `get_memory_stats()` is now async internally but wrapped for compatibility |
| 126 | + |
| 127 | +### RiskManager |
| 128 | +- Comprehensive risk statistics tracking added |
| 129 | +- New metrics: violations, checks, position sizing |
| 130 | + |
| 131 | +## Performance Considerations |
| 132 | + |
| 133 | +### TTL Caching |
| 134 | +The new system includes 5-second TTL caching by default: |
| 135 | + |
| 136 | +```python |
| 137 | +# Cached automatically for 5 seconds |
| 138 | +stats1 = await component.get_stats() |
| 139 | +stats2 = await component.get_stats() # Returns cached value if < 5 seconds |
| 140 | +``` |
| 141 | + |
| 142 | +### Parallel Collection |
| 143 | +Statistics are collected in parallel from all components: |
| 144 | + |
| 145 | +```python |
| 146 | +aggregator = StatisticsAggregator() |
| 147 | +# Collects from all components simultaneously |
| 148 | +stats = await aggregator.get_comprehensive_stats() |
| 149 | +``` |
| 150 | + |
| 151 | +### Memory Management |
| 152 | +Automatic cleanup with bounded collections: |
| 153 | +- Error history: Max 100 entries |
| 154 | +- Operation timings: Max 1000 per operation |
| 155 | +- Circular buffers prevent memory leaks |
| 156 | + |
| 157 | +## Common Migration Issues |
| 158 | + |
| 159 | +### Issue 1: Import Errors |
| 160 | +```python |
| 161 | +ImportError: cannot import name 'EnhancedStatsTrackingMixin' |
| 162 | +``` |
| 163 | +**Solution:** Update imports to use new statistics module. |
| 164 | + |
| 165 | +### Issue 2: Sync/Async Mismatch |
| 166 | +```python |
| 167 | +TypeError: object dict can't be used in 'await' expression |
| 168 | +``` |
| 169 | +**Solution:** Remove `await` for `get_memory_stats()`, add `await` for new methods. |
| 170 | + |
| 171 | +### Issue 3: Missing Methods |
| 172 | +```python |
| 173 | +AttributeError: 'OrderManager' object has no attribute 'get_stats' |
| 174 | +``` |
| 175 | +**Solution:** Ensure you're using v3.3.0+ of the SDK. |
| 176 | + |
| 177 | +## Testing Your Migration |
| 178 | + |
| 179 | +Run this test to verify your migration: |
| 180 | + |
| 181 | +```python |
| 182 | +import asyncio |
| 183 | +from project_x_py import TradingSuite |
| 184 | + |
| 185 | +async def test_statistics(): |
| 186 | + suite = await TradingSuite.create("MNQ") |
| 187 | + |
| 188 | + # Test new async methods |
| 189 | + stats = await suite.orders.get_stats() |
| 190 | + assert "name" in stats |
| 191 | + assert stats["name"] == "order_manager" |
| 192 | + |
| 193 | + # Test health scoring |
| 194 | + health = await suite.orders.get_health_score() |
| 195 | + assert 0 <= health <= 100 |
| 196 | + |
| 197 | + # Test backward compatibility |
| 198 | + memory_stats = suite.orders.get_memory_stats() |
| 199 | + assert isinstance(memory_stats, dict) |
| 200 | + |
| 201 | + print("✅ Migration successful!") |
| 202 | + |
| 203 | +asyncio.run(test_statistics()) |
| 204 | +``` |
| 205 | + |
| 206 | +## Support |
| 207 | + |
| 208 | +For migration assistance: |
| 209 | +1. Check the [CHANGELOG](../CHANGELOG.md) for detailed changes |
| 210 | +2. Review the [test files](../tests/statistics/) for usage examples |
| 211 | +3. Open an issue on GitHub for specific problems |
| 212 | + |
| 213 | +## Timeline |
| 214 | + |
| 215 | +- **v3.3.0** (Current): New async statistics system introduced |
| 216 | +- **v3.4.0** (Future): Deprecation warnings for sync methods |
| 217 | +- **v4.0.0** (Future): Removal of deprecated sync methods |
| 218 | + |
| 219 | +Plan your migration accordingly to avoid breaking changes in v4.0.0. |
0 commit comments