f36123ccaf
Implement industrial-standard semantic versioning (SemVer 2.0.0) with automated feature detection and comprehensive changelog management. New Features: - VERSION file: Single source of truth for base version (0.0.0) - src/version.py: Centralized version manager with auto-detection - CHANGELOG.md: Keep a Changelog format for all changes - Auto-versioning: Features increment MINOR version automatically - Version display: Shows in startup banner and logs Predictive Intelligence (v6.3) Complete: - src/trajectory_predictor.py: Forecast profit 1-5 minutes ahead - src/momentum_persistence.py: Detect momentum continuation (0-1 score) - src/recovery_detector.py: Analyze recovery strength from losses - src/fuzzy_exit_logic.py: Fuzzy logic exit confidence (0-1) - src/kalman_filter.py: Kalman filter for velocity smoothing - src/kelly_position_scaler.py: Kelly criterion position scaling Version Calculation: Base 0.0.0 + Kalman(0.1) + Fuzzy(0.1) + Kelly(0.1) + Trajectory(0.1) + Momentum(0.1) + Recovery(0.1) = v0.6.0 Modified: - CLAUDE.md: Added comprehensive versioning documentation - main_live.py: Display version in startup banner - src/smart_risk_manager.py: Use centralized versioning Documentation: - CLAUDE.md: Full versioning guidelines (SemVer, workflows, examples) - CHANGELOG.md: Initial release documentation with feature tracking - VERSION: Base version 0.0.0 Benefits: - Professional version management (industry standard) - Automatic feature tracking and version updates - Complete change history with Keep a Changelog format - Clear upgrade paths (MAJOR.MINOR.PATCH) Version: v0.6.0 (Kalman + Fuzzy + Kelly + Predictive) Exit Strategy: v6.3 Predictive Intelligence Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
254 lines
8.5 KiB
Python
254 lines
8.5 KiB
Python
"""
|
|
XAUBot AI - Centralized Version Management
|
|
==========================================
|
|
|
|
Semantic Versioning (SemVer): MAJOR.MINOR.PATCH
|
|
|
|
MAJOR: Incompatible API changes, breaking changes
|
|
MINOR: New features, backward compatible
|
|
PATCH: Bug fixes, backward compatible
|
|
|
|
Author: AI Assistant
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Dict, Tuple
|
|
from loguru import logger
|
|
|
|
|
|
class VersionManager:
|
|
"""
|
|
Centralized version management for XAUBot AI.
|
|
|
|
Auto-detects version based on enabled features and components.
|
|
Reads base version from VERSION file, calculates effective version.
|
|
"""
|
|
|
|
def __init__(self):
|
|
self.base_version = self._read_version_file()
|
|
self.features = self._detect_features()
|
|
self.effective_version = self._calculate_version()
|
|
|
|
def _read_version_file(self) -> Tuple[int, int, int]:
|
|
"""Read version from VERSION file."""
|
|
version_file = Path(__file__).parent.parent / "VERSION"
|
|
try:
|
|
with open(version_file, 'r') as f:
|
|
version_str = f.read().strip()
|
|
parts = version_str.split('.')
|
|
if len(parts) != 3:
|
|
raise ValueError(f"Invalid version format: {version_str}")
|
|
return tuple(int(p) for p in parts)
|
|
except Exception as e:
|
|
logger.warning(f"Could not read VERSION file: {e}, using default 0.0.0")
|
|
return (0, 0, 0)
|
|
|
|
def _detect_features(self) -> Dict[str, bool]:
|
|
"""
|
|
Auto-detect enabled features from environment and imports.
|
|
"""
|
|
features = {}
|
|
|
|
# Core features (always enabled)
|
|
features['mt5_integration'] = True
|
|
features['smc_analysis'] = True
|
|
features['ml_prediction'] = True
|
|
features['hmm_regime'] = True
|
|
|
|
# Advanced exit features (from environment flags)
|
|
features['kalman_filter'] = os.environ.get("KALMAN_ENABLED", "1") == "1"
|
|
features['advanced_exits'] = os.environ.get("ADVANCED_EXITS_ENABLED", "1") == "1"
|
|
features['predictive_intelligence'] = os.environ.get("PREDICTIVE_ENABLED", "1") == "1"
|
|
|
|
# Component detection
|
|
try:
|
|
# Fuzzy Logic
|
|
from src.fuzzy_exit_logic import FuzzyExitController
|
|
features['fuzzy_logic'] = True
|
|
except ImportError:
|
|
features['fuzzy_logic'] = False
|
|
|
|
try:
|
|
# Kelly Criterion
|
|
from src.kelly_position_scaler import KellyPositionScaler
|
|
features['kelly_criterion'] = True
|
|
except ImportError:
|
|
features['kelly_criterion'] = False
|
|
|
|
try:
|
|
# Trajectory Predictor
|
|
from src.trajectory_predictor import TrajectoryPredictor
|
|
features['trajectory_predictor'] = True
|
|
except ImportError:
|
|
features['trajectory_predictor'] = False
|
|
|
|
try:
|
|
# Momentum Persistence
|
|
from src.momentum_persistence import MomentumPersistence
|
|
features['momentum_persistence'] = True
|
|
except ImportError:
|
|
features['momentum_persistence'] = False
|
|
|
|
try:
|
|
# Recovery Detector
|
|
from src.recovery_detector import RecoveryDetector
|
|
features['recovery_detector'] = True
|
|
except ImportError:
|
|
features['recovery_detector'] = False
|
|
|
|
return features
|
|
|
|
def _calculate_version(self) -> Tuple[int, int, int]:
|
|
"""
|
|
Calculate effective version based on base + features.
|
|
|
|
Version increments:
|
|
- Kalman Filter: +0.1.0 (MINOR)
|
|
- Fuzzy Logic: +0.1.0 (MINOR)
|
|
- Kelly Criterion: +0.1.0 (MINOR)
|
|
- Predictive Intelligence (all 3): +0.3.0 (MINOR)
|
|
- Each predictor separately: +0.1.0 (MINOR)
|
|
"""
|
|
major, minor, patch = self.base_version
|
|
|
|
# MINOR increments for features
|
|
if self.features.get('kalman_filter', False):
|
|
minor += 1 # v0.1.0
|
|
|
|
if self.features.get('fuzzy_logic', False):
|
|
minor += 1 # v0.2.0
|
|
|
|
if self.features.get('kelly_criterion', False):
|
|
minor += 1 # v0.3.0
|
|
|
|
# Predictive Intelligence components
|
|
predictive_count = sum([
|
|
self.features.get('trajectory_predictor', False),
|
|
self.features.get('momentum_persistence', False),
|
|
self.features.get('recovery_detector', False)
|
|
])
|
|
|
|
if predictive_count > 0:
|
|
minor += predictive_count # Each predictor = +0.1.0
|
|
|
|
return (major, minor, patch)
|
|
|
|
def get_version_string(self) -> str:
|
|
"""Get version as string (MAJOR.MINOR.PATCH)."""
|
|
major, minor, patch = self.effective_version
|
|
return f"{major}.{minor}.{patch}"
|
|
|
|
def get_detailed_version(self) -> str:
|
|
"""
|
|
Get detailed version with feature breakdown.
|
|
|
|
Example: "v0.6.0 (Kalman + Fuzzy + Kelly + Predictive)"
|
|
"""
|
|
major, minor, patch = self.effective_version
|
|
version_str = f"v{major}.{minor}.{patch}"
|
|
|
|
# Build feature list
|
|
feature_list = []
|
|
|
|
if self.features.get('kalman_filter', False):
|
|
feature_list.append("Kalman")
|
|
|
|
if self.features.get('fuzzy_logic', False):
|
|
feature_list.append("Fuzzy")
|
|
|
|
if self.features.get('kelly_criterion', False):
|
|
feature_list.append("Kelly")
|
|
|
|
# Check if all 3 predictive components enabled
|
|
predictive_all = all([
|
|
self.features.get('trajectory_predictor', False),
|
|
self.features.get('momentum_persistence', False),
|
|
self.features.get('recovery_detector', False)
|
|
])
|
|
|
|
if predictive_all:
|
|
feature_list.append("Predictive")
|
|
else:
|
|
# Add individual predictive components
|
|
if self.features.get('trajectory_predictor', False):
|
|
feature_list.append("Trajectory")
|
|
if self.features.get('momentum_persistence', False):
|
|
feature_list.append("Momentum")
|
|
if self.features.get('recovery_detector', False):
|
|
feature_list.append("Recovery")
|
|
|
|
if feature_list:
|
|
features_str = " + ".join(feature_list)
|
|
return f"{version_str} ({features_str})"
|
|
else:
|
|
return f"{version_str} (Core)"
|
|
|
|
def get_exit_strategy_version(self) -> str:
|
|
"""Get exit strategy version label."""
|
|
if self.features.get('predictive_intelligence', False):
|
|
return "Exit v6.3 Predictive Intelligence"
|
|
elif self.features.get('advanced_exits', False):
|
|
return "Exit v6.2 Advanced"
|
|
elif self.features.get('kalman_filter', False):
|
|
return "Exit v6.0 Kalman"
|
|
else:
|
|
return "Exit v5.0 Dynamic"
|
|
|
|
def print_version_info(self):
|
|
"""Print comprehensive version information."""
|
|
logger.info("=" * 60)
|
|
logger.info(f"XAUBot AI {self.get_detailed_version()}")
|
|
logger.info(f"Exit Strategy: {self.get_exit_strategy_version()}")
|
|
logger.info("=" * 60)
|
|
logger.info("Enabled Features:")
|
|
|
|
for feature, enabled in sorted(self.features.items()):
|
|
status = "✓" if enabled else "✗"
|
|
feature_name = feature.replace('_', ' ').title()
|
|
logger.info(f" [{status}] {feature_name}")
|
|
|
|
logger.info("=" * 60)
|
|
|
|
def get_component_versions(self) -> Dict[str, str]:
|
|
"""Get version info for each component."""
|
|
return {
|
|
"core": self.get_version_string(),
|
|
"exit_strategy": self.get_exit_strategy_version(),
|
|
"detailed": self.get_detailed_version(),
|
|
"base": f"{self.base_version[0]}.{self.base_version[1]}.{self.base_version[2]}",
|
|
"effective": self.get_version_string()
|
|
}
|
|
|
|
|
|
# Global version instance
|
|
__version_manager__ = VersionManager()
|
|
|
|
# Expose convenient module-level attributes
|
|
__version__ = __version_manager__.get_version_string()
|
|
__version_detailed__ = __version_manager__.get_detailed_version()
|
|
__exit_strategy__ = __version_manager__.get_exit_strategy_version()
|
|
|
|
|
|
def get_version() -> str:
|
|
"""Get version string."""
|
|
return __version__
|
|
|
|
|
|
def get_detailed_version() -> str:
|
|
"""Get detailed version with features."""
|
|
return __version_detailed__
|
|
|
|
|
|
def print_version_info():
|
|
"""Print version information."""
|
|
__version_manager__.print_version_info()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Test version detection
|
|
print_version_info()
|
|
print(f"\nVersion: {get_version()}")
|
|
print(f"Detailed: {get_detailed_version()}")
|
|
print(f"\nComponents: {__version_manager__.get_component_versions()}")
|