Files
hyper/clp_auto_hedger/velocity_config.py

190 lines
7.0 KiB
Python

#!/usr/bin/env python3
"""
Configuration module for enhanced velocity calculations in CLP Scalper Hedger
Provides configurable parameters for multi-timeframe velocity detection
"""
from dataclasses import dataclass, field
from typing import Dict, List, Optional
import json
import os
@dataclass
class VelocityTimeframe:
"""Configuration for a single velocity timeframe"""
name: str
periods: int # Number of periods to average over
weight: float # Weight in decision making (0.0 to 1.0)
threshold: float # Velocity threshold for this timeframe
description: str
@dataclass
class VelocityConfig:
"""Enhanced velocity configuration with multiple timeframes and market conditions"""
# Basic settings
max_velocity_cap: float = 0.5 # Cap at 50% change per interval
history_length: int = 60 # Keep last 60 price points for calculations
# Timeframe configurations
timeframes: Optional[List[VelocityTimeframe]] = None
# Market condition thresholds
normal_threshold: float = 0.0005 # 0.05% for normal markets
volatile_threshold: float = 0.001 # 0.1% for volatile markets
extreme_threshold: float = 0.002 # 0.2% for extreme markets
# Emergency detection settings
extreme_move_threshold: float = 0.002 # 0.2% for immediate response
sustained_move_periods: int = 5 # Periods for sustained move detection
# Smoothing settings
use_ema_smoothing: bool = True
ema_alpha: float = 0.2 # EMA smoothing factor
# Edge proximity for velocity triggers
edge_proximity_factor: float = 0.05 # 5% from range edge
def __post_init__(self):
"""Initialize default timeframes if not provided"""
if self.timeframes is None:
self.timeframes = [
VelocityTimeframe(
name="1s",
periods=1,
weight=0.4,
threshold=self.extreme_threshold,
description="Instantaneous velocity for emergency detection"
),
VelocityTimeframe(
name="5s",
periods=5,
weight=0.3,
threshold=self.normal_threshold,
description="Short-term smoothed velocity"
),
VelocityTimeframe(
name="10s",
periods=10,
weight=0.2,
threshold=self.normal_threshold * 0.8,
description="Medium-term trend detection"
),
VelocityTimeframe(
name="30s",
periods=30,
weight=0.1,
threshold=self.normal_threshold * 0.6,
description="Long-term sustained moves"
)
]
@classmethod
def conservative(cls) -> 'VelocityConfig':
"""Conservative configuration for low-risk trading"""
config = cls()
config.normal_threshold = 0.0003 # 0.03%
config.volatile_threshold = 0.0006 # 0.06%
config.extreme_threshold = 0.001 # 0.1%
config.extreme_move_threshold = 0.001 # 0.1%
return config
@classmethod
def aggressive(cls) -> 'VelocityConfig':
"""Aggressive configuration for high-frequency trading"""
config = cls()
config.normal_threshold = 0.001 # 0.1%
config.volatile_threshold = 0.002 # 0.2%
config.extreme_threshold = 0.003 # 0.3%
config.extreme_move_threshold = 0.003 # 0.3%
return config
@classmethod
def from_file(cls, config_path: str) -> 'VelocityConfig':
"""Load configuration from JSON file"""
if not os.path.exists(config_path):
raise FileNotFoundError(f"Configuration file not found: {config_path}")
with open(config_path, 'r') as f:
data = json.load(f)
# Reconstruct VelocityTimeframe objects
if 'timeframes' in data and data['timeframes'] is not None:
data['timeframes'] = [VelocityTimeframe(**tf) for tf in data['timeframes']]
return cls(**data)
def to_file(self, config_path: str) -> None:
"""Save configuration to JSON file"""
data = {
'max_velocity_cap': self.max_velocity_cap,
'history_length': self.history_length,
'timeframes': [
{
'name': tf.name,
'periods': tf.periods,
'weight': tf.weight,
'threshold': tf.threshold,
'description': tf.description
} for tf in self.timeframes or []
],
'normal_threshold': self.normal_threshold,
'volatile_threshold': self.volatile_threshold,
'extreme_threshold': self.extreme_threshold,
'extreme_move_threshold': self.extreme_move_threshold,
'sustained_move_periods': self.sustained_move_periods,
'use_ema_smoothing': self.use_ema_smoothing,
'ema_alpha': self.ema_alpha,
'edge_proximity_factor': self.edge_proximity_factor
}
# Only create directory if path contains directory
config_dir = os.path.dirname(config_path)
if config_dir:
os.makedirs(config_dir, exist_ok=True)
with open(config_path, 'w') as f:
json.dump(data, f, indent=2)
def get_active_threshold(self, market_volatility: float) -> float:
"""Get appropriate threshold based on market volatility"""
if market_volatility < 0.001: # Very low volatility
return self.normal_threshold
elif market_volatility < 0.003: # Normal volatility
return self.volatile_threshold
else: # High volatility
return self.extreme_threshold
def create_default_config() -> VelocityConfig:
"""Create default velocity configuration"""
return VelocityConfig()
def create_config_files() -> None:
"""Create example configuration files"""
configs = {
'velocity_config_conservative.json': create_default_config().conservative(),
'velocity_config_normal.json': create_default_config(),
'velocity_config_aggressive.json': create_default_config().aggressive()
}
for filename, config in configs.items():
config.to_file(filename)
if __name__ == "__main__":
# Example usage and config file creation
print("Creating velocity configuration files...")
create_config_files()
print("Configuration files created successfully!")
# Display default configuration
default_config = create_default_config()
print(f"\nDefault configuration:")
print(f"Normal threshold: {default_config.normal_threshold*100:.3f}%")
if default_config.timeframes:
print(f"Timeframes: {len(default_config.timeframes)}")
for tf in default_config.timeframes:
print(f" - {tf.name}: {tf.periods} periods, {tf.threshold*100:.3f}% threshold, {tf.weight:.1f} weight")