Spaces:
No application file
No application file
| """ | |
| AFML helps portfolio managers and traders leverage machine learning with | |
| reproducible, interpretable, and easy to use tools. | |
| """ | |
| import importlib | |
| import sys | |
| from types import ModuleType | |
| from typing import Dict, List | |
| from loguru import logger | |
| from .cache import ( | |
| CacheAnalyzer, | |
| cache_maintenance, | |
| cacheable, | |
| clear_afml_cache, | |
| clear_cache_stats, | |
| get_cache_hit_rate, | |
| get_cache_stats, | |
| get_cache_summary, | |
| get_comprehensive_cache_status, | |
| initialize_cache_system, | |
| memory, | |
| optimize_cache_system, | |
| robust_cacheable, | |
| setup_production_cache, | |
| time_aware_cacheable, | |
| ) | |
| # ============================================================================= | |
| # IMPORT CACHE SYSTEM - Updated with new features | |
| # ============================================================================= | |
| # NEW: Import monitoring (optional - only if you want it at top level) | |
| try: | |
| from .cache import ( | |
| analyze_cache_patterns, | |
| get_cache_efficiency_report, | |
| get_cache_monitor, | |
| print_cache_health, | |
| ) | |
| CACHE_MONITORING_AVAILABLE = True | |
| except ImportError: | |
| CACHE_MONITORING_AVAILABLE = False | |
| logger.debug("Cache monitoring not available") | |
| # NEW: Import MLflow integration (optional) | |
| try: | |
| from .cache import ( | |
| MLFLOW_INTEGRATION_AVAILABLE, | |
| get_mlflow_cache, | |
| mlflow_cached, | |
| setup_mlflow_cache, | |
| ) | |
| except ImportError: | |
| MLFLOW_INTEGRATION_AVAILABLE = False | |
| logger.debug("MLflow integration not available") | |
| # NEW: Import backtest caching (optional) | |
| try: | |
| from .cache import BacktestCache, cached_backtest, get_backtest_cache | |
| BACKTEST_CACHE_AVAILABLE = True | |
| except ImportError: | |
| BACKTEST_CACHE_AVAILABLE = False | |
| logger.debug("Backtest cache not available") | |
| # Numba warmup utilities | |
| from .numba_warmup import lazy_warmup, prewarm_numba_in_package, register_numba_dummy | |
| # ============================================================================= | |
| # INITIALIZE CACHE SYSTEM FIRST (before any heavy imports) | |
| # ============================================================================= | |
| # Initialize cache system immediately | |
| initialize_cache_system() | |
| # Adjust these as needed after inspecting actual function signatures in your codebase. | |
| # register_numba_dummy( | |
| # "_precompute_active_indices_nopython", | |
| # args=(np.array([np.int64(0)]), np.array([np.int64(0)]), np.array([np.int64(0)])), | |
| # ) | |
| # ============================================================================= | |
| # LAZY LOADING SETUP | |
| # ============================================================================= | |
| # Module mapping - only add modules that are actually heavy to import | |
| HEAVY_MODULES = { | |
| # ML modules (typically have sklearn, xgboost, etc.) | |
| "cross_validation": "cross_validation", | |
| } | |
| # Lightweight modules - import directly for better IDE support | |
| try: | |
| from . import ( | |
| data_structures, | |
| datasets, | |
| features, | |
| labeling, | |
| mt5, | |
| production, | |
| sample_weights, | |
| sampling, | |
| util, | |
| ) | |
| # Handle nested modules | |
| from .filters import filters | |
| from .strategies import trading_strategies | |
| logger.debug("Imported lightweight modules directly") | |
| except ImportError as e: | |
| logger.warning("Some lightweight modules failed to import: {}", e) | |
| # Cache for lazy-loaded heavy modules | |
| _module_cache: Dict[str, ModuleType] = {} | |
| # ============================================================================= | |
| # LAZY LOADING FOR HEAVY MODULES ONLY | |
| # ============================================================================= | |
| def __getattr__(name: str) -> ModuleType: | |
| """Lazy load heavy modules only.""" | |
| if name in HEAVY_MODULES: | |
| # Check cache first | |
| if name in _module_cache: | |
| return _module_cache[name] | |
| # Import and cache | |
| try: | |
| import_path = f"afml.{HEAVY_MODULES[name]}" | |
| logger.debug("Lazy loading heavy module: {}", name) | |
| module = importlib.import_module(import_path) | |
| _module_cache[name] = module | |
| logger.info( | |
| "Loaded heavy module: {} ({} MB)", name, _get_module_size(module) | |
| ) | |
| return module | |
| except ImportError as e: | |
| logger.error("Failed to import heavy module {}: {}", name, e) | |
| raise AttributeError(f"Module 'afml' has no attribute '{name}'") from e | |
| # Handle filters special case (nested module) | |
| if name == "filters": | |
| try: | |
| from .filters import filters | |
| return filters | |
| except ImportError as e: | |
| raise AttributeError(f"Module 'afml' has no attribute '{name}'") from e | |
| if name == "strategies": | |
| try: | |
| from .strategies import trading_strategies | |
| return trading_strategies | |
| except ImportError as e: | |
| raise AttributeError(f"Module 'afml' has no attribute '{name}'") from e | |
| raise AttributeError(f"Module 'afml' has no attribute '{name}'") | |
| def _get_module_size(module) -> str: | |
| """Rough estimate of module memory footprint.""" | |
| try: | |
| # Count objects in module namespace | |
| obj_count = len( | |
| [ | |
| obj | |
| for obj in vars(module).values() | |
| if not callable(obj) or hasattr(obj, "__module__") | |
| ] | |
| ) | |
| return f"~{obj_count // 10}0" # Very rough estimate | |
| except Exception: | |
| return "unknown" | |
| # ============================================================================= | |
| # SIMPLE MODULE MANAGEMENT (only what's actually useful) | |
| # ============================================================================= | |
| def preload_heavy_modules(*module_names: str) -> Dict[str, ModuleType]: | |
| """ | |
| Preload specific heavy modules. Only use this if you know you'll need them. | |
| Args: | |
| *module_names: Names of heavy modules to preload | |
| Returns: | |
| Dict of successfully loaded modules | |
| """ | |
| loaded = {} | |
| for name in module_names: | |
| if name in HEAVY_MODULES: | |
| try: | |
| module = getattr(sys.modules[__name__], name) # Triggers __getattr__ | |
| loaded[name] = module | |
| except Exception as e: | |
| logger.warning("Failed to preload {}: {}", name, e) | |
| else: | |
| logger.warning( | |
| "'{}' is not a heavy module (already imported or doesn't exist)", name | |
| ) | |
| return loaded | |
| def get_loaded_heavy_modules() -> List[str]: | |
| """Get list of currently loaded heavy modules.""" | |
| return list(_module_cache.keys()) | |
| def preload_ml_modules() -> Dict[str, ModuleType]: | |
| """Convenience function to preload all ML-related modules.""" | |
| ml_modules = ["cross_validation"] | |
| return preload_heavy_modules(*ml_modules) | |
| def preload_portfolio_modules() -> Dict[str, ModuleType]: | |
| """Convenience function to preload portfolio-related modules.""" | |
| logger.warning("Portfolio modules are not present in this checkout") | |
| return {} | |
| # ============================================================================= | |
| # CACHE MONITORING UTILITIES - Enhanced | |
| # ============================================================================= | |
| def cache_status() -> str: | |
| """Get human-readable cache status string.""" | |
| summary = get_cache_summary() | |
| loaded = get_loaded_heavy_modules() | |
| status_parts = [ | |
| f"Hit rate: {summary['hit_rate']:.1%}", | |
| f"Tracked functions: {summary['functions_tracked']}", | |
| f"Heavy modules loaded: {len(loaded)}", | |
| ] | |
| if loaded: | |
| status_parts.append(f"({', '.join(loaded)})") | |
| return " | ".join(status_parts) | |
| def maintain_cache( | |
| auto_clear: bool = True, max_size_mb: int = 500, max_age_days: int = 30 | |
| ): | |
| """ | |
| Perform intelligent cache maintenance. | |
| Args: | |
| auto_clear: Automatically clear changed functions | |
| max_size_mb: Maximum cache size in MB | |
| max_age_days: Remove cache files older than this | |
| """ | |
| logger.info("Running cache maintenance...") | |
| report = cache_maintenance( | |
| auto_clear_changed=auto_clear, | |
| max_cache_size_mb=max_size_mb, | |
| max_age_days=max_age_days, | |
| ) | |
| return report | |
| # ============================================================================= | |
| # __all__ AND METADATA | |
| # ============================================================================= | |
| __version__ = "1.0.0" | |
| __author__ = "AFML Team" | |
| __all__ = [ | |
| # Core cache system | |
| "memory", | |
| "cacheable", | |
| "get_cache_hit_rate", | |
| "get_cache_stats", | |
| "clear_cache_stats", | |
| "clear_afml_cache", | |
| "get_cache_summary", | |
| "CacheAnalyzer", | |
| "initialize_cache_system", | |
| # NEW: Robust cache keys | |
| "robust_cacheable", | |
| "time_aware_cacheable", | |
| # NEW: Enhanced cache functions | |
| "get_comprehensive_cache_status", | |
| "optimize_cache_system", | |
| "setup_production_cache", | |
| # Cache monitoring (if available) | |
| "print_cache_health", | |
| "get_cache_efficiency_report", | |
| "analyze_cache_patterns", | |
| "get_cache_monitor", | |
| # MLflow integration (if available) | |
| "setup_mlflow_cache", | |
| "get_mlflow_cache", | |
| "mlflow_cached", | |
| # Backtest caching (if available) | |
| "cached_backtest", | |
| "get_backtest_cache", | |
| "BacktestCache", | |
| # Module management | |
| "preload_heavy_modules", | |
| "preload_ml_modules", | |
| "preload_portfolio_modules", | |
| "get_loaded_heavy_modules", | |
| # Utilities | |
| "cache_status", | |
| "maintain_cache", | |
| # Selective cache management | |
| "cache_maintenance", | |
| # Numba utilities | |
| "lazy_warmup", | |
| "prewarm_numba_in_package", | |
| "register_numba_dummy", | |
| # Lightweight modules (directly imported) | |
| "data_structures", | |
| "util", | |
| "datasets", | |
| "labeling", | |
| "features", | |
| "sample_weights", | |
| "sampling", | |
| "trading_strategies", | |
| "filters", | |
| "mt5", | |
| "production", | |
| # Heavy modules (lazy loaded) | |
| "cross_validation", | |
| ] | |
| # ============================================================================= | |
| # STARTUP | |
| # ============================================================================= | |
| logger.info( | |
| "AFML v{} ready - {} heavy modules available for lazy loading", | |
| __version__, | |
| len(HEAVY_MODULES), | |
| ) | |
| logger.debug("Cache status: {}", cache_status()) | |
| # Log available enhanced features | |
| if CACHE_MONITORING_AVAILABLE: | |
| logger.debug("✓ Cache monitoring available") | |
| if MLFLOW_INTEGRATION_AVAILABLE: | |
| logger.debug("✓ MLflow integration available") | |
| if BACKTEST_CACHE_AVAILABLE: | |
| logger.debug("✓ Backtest caching available") | |