Cycles/docs/strategy_manager.md
2025-05-23 20:37:14 +08:00

12 KiB

Strategy Manager Documentation

Overview

The Strategy Manager is a sophisticated orchestration system that enables the combination of multiple trading strategies with configurable signal aggregation rules. It supports multi-timeframe analysis, weighted consensus voting, and flexible signal combination methods.

🏗️ New Architecture: The Strategy Manager has been enhanced as part of the framework's modular refactoring. It now integrates seamlessly with the new BacktestRunner, ConfigManager, and ResultsProcessor components while maintaining full backward compatibility.

New Framework Integration

Modular Architecture Benefits

The refactored framework provides several advantages for strategy management:

  • 🔧 Simplified Configuration: Unified configuration through ConfigManager
  • Enhanced Execution: Streamlined execution via BacktestRunner
  • 📊 Better Processing: Integrated results processing with ResultsProcessor
  • 🔄 Improved Reusability: Strategy manager can be used independently

Usage in New Framework

# Direct usage with new components
from cycles.utils import ConfigManager, BacktestRunner

config_manager = ConfigManager("config.json")
runner = BacktestRunner()

# Configuration is automatically prepared
strategy_config = config_manager.get_strategy_manager_config()
task_config = config_manager.get_timeframe_task_config("15min")

# Execution is handled cleanly
results = runner.run_single_timeframe(data, "15min", task_config)

Integration with BacktestApplication

The Strategy Manager seamlessly integrates with the new BacktestApplication:

from cycles.application import BacktestApplication

# Strategy manager is automatically created and managed
app = BacktestApplication("config.json")
app.run(debug=False)  # Strategy manager handles all strategy coordination

Architecture

Core Components

  1. StrategyBase: Abstract base class defining the strategy interface
  2. StrategySignal: Encapsulates trading signals with confidence levels
  3. StrategyManager: Orchestrates multiple strategies and combines signals
  4. Strategy Implementations: DefaultStrategy, BBRSStrategy, etc.

New Timeframe System

The framework now supports strategy-level timeframe management:

  • Strategy-Controlled Timeframes: Each strategy specifies its required timeframes
  • Automatic Data Resampling: Framework automatically resamples 1-minute data to strategy needs
  • Multi-Timeframe Support: Strategies can use multiple timeframes simultaneously
  • Precision Stop-Loss: All strategies maintain 1-minute data for precise execution
class MyStrategy(StrategyBase):
    def get_timeframes(self):
        return ["15min", "1h"]  # Strategy needs both timeframes
    
    def initialize(self, backtester):
        # Access resampled data
        data_15m = self.get_data_for_timeframe("15min")
        data_1h = self.get_data_for_timeframe("1h")
        # Setup indicators...

Strategy Interface

StrategyBase Class

All strategies must inherit from StrategyBase and implement:

from cycles.strategies.base import StrategyBase, StrategySignal

class MyStrategy(StrategyBase):
    def get_timeframes(self) -> List[str]:
        """Specify required timeframes"""
        return ["15min"]
    
    def initialize(self, backtester) -> None:
        """Setup strategy with data"""
        self._resample_data(backtester.original_df)
        # Calculate indicators...
        self.initialized = True
    
    def get_entry_signal(self, backtester, df_index: int) -> StrategySignal:
        """Generate entry signals"""
        if condition_met:
            return StrategySignal("ENTRY", confidence=0.8)
        return StrategySignal("HOLD", confidence=0.0)
    
    def get_exit_signal(self, backtester, df_index: int) -> StrategySignal:
        """Generate exit signals"""
        if exit_condition:
            return StrategySignal("EXIT", confidence=1.0, 
                                metadata={"type": "SELL_SIGNAL"})
        return StrategySignal("HOLD", confidence=0.0)

StrategySignal Class

Encapsulates trading signals with metadata:

# Entry signal with high confidence
entry_signal = StrategySignal("ENTRY", confidence=0.9)

# Exit signal with specific price
exit_signal = StrategySignal("EXIT", confidence=1.0, price=50000,
                           metadata={"type": "STOP_LOSS"})

# Hold signal
hold_signal = StrategySignal("HOLD", confidence=0.0)

Available Strategies

1. Default Strategy

Meta-trend analysis using multiple Supertrend indicators.

Features:

  • Uses 3 Supertrend indicators with different parameters
  • Configurable timeframe (default: 15min)
  • Entry when all trends align upward
  • Exit on trend reversal or stop-loss

Configuration:

{
    "name": "default",
    "weight": 1.0,
    "params": {
        "timeframe": "15min",
        "stop_loss_pct": 0.03
    }
}

Timeframes:

  • Primary: Configurable (default 15min)
  • Stop-loss: Always includes 1min for precision

2. BBRS Strategy

Bollinger Bands + RSI with market regime detection.

Features:

  • Market regime detection (trending vs sideways)
  • Adaptive parameters based on market conditions
  • Volume analysis and confirmation
  • Multi-timeframe internal analysis (1min → 15min/1h)

Configuration:

{
    "name": "bbrs",
    "weight": 1.0,
    "params": {
        "bb_width": 0.05,
        "bb_period": 20,
        "rsi_period": 14,
        "strategy_name": "MarketRegimeStrategy",
        "stop_loss_pct": 0.05
    }
}

Timeframes:

  • Input: 1min (Strategy class handles internal resampling)
  • Internal: 15min, 1h (handled by underlying Strategy class)
  • Output: Mapped back to 1min for backtesting

Signal Combination

Entry Signal Combination

combination_rules = {
    "entry": "weighted_consensus",  # or "any", "all", "majority"
    "min_confidence": 0.6
}

Methods:

  • any: Enter if ANY strategy signals entry
  • all: Enter only if ALL strategies signal entry
  • majority: Enter if majority of strategies signal entry
  • weighted_consensus: Enter based on weighted average confidence

Exit Signal Combination

combination_rules = {
    "exit": "priority"  # or "any", "all"
}

Methods:

  • any: Exit if ANY strategy signals exit (recommended for risk management)
  • all: Exit only if ALL strategies agree
  • priority: Prioritized exit (STOP_LOSS > SELL_SIGNAL > others)

Configuration

Basic Strategy Manager Setup

{
    "strategies": [
        {
            "name": "default",
            "weight": 0.6,
            "params": {
                "timeframe": "15min",
                "stop_loss_pct": 0.03
            }
        },
        {
            "name": "bbrs", 
            "weight": 0.4,
            "params": {
                "bb_width": 0.05,
                "strategy_name": "MarketRegimeStrategy"
            }
        }
    ],
    "combination_rules": {
        "entry": "weighted_consensus",
        "exit": "any",
        "min_confidence": 0.5
    }
}

Timeframe Examples

Single Timeframe Strategy:

{
    "name": "default",
    "params": {
        "timeframe": "5min"  # Strategy works on 5-minute data
    }
}

Multi-Timeframe Strategy (Future Enhancement):

{
    "name": "multi_tf_strategy",
    "params": {
        "timeframes": ["5min", "15min", "1h"],  # Multiple timeframes
        "primary_timeframe": "15min"
    }
}

Usage Examples

Create Strategy Manager

from cycles.strategies import create_strategy_manager

config = {
    "strategies": [
        {"name": "default", "weight": 1.0, "params": {"timeframe": "15min"}}
    ],
    "combination_rules": {
        "entry": "any",
        "exit": "any"
    }
}

strategy_manager = create_strategy_manager(config)

Initialize and Use

# Initialize with backtester
strategy_manager.initialize(backtester)

# Get signals during backtesting
entry_signal = strategy_manager.get_entry_signal(backtester, df_index)
exit_signal, exit_price = strategy_manager.get_exit_signal(backtester, df_index)

# Get strategy summary
summary = strategy_manager.get_strategy_summary()
print(f"Loaded strategies: {[s['name'] for s in summary['strategies']]}")
print(f"All timeframes: {summary['all_timeframes']}")

Extending the System

Adding New Strategies

  1. Create Strategy Class:
class NewStrategy(StrategyBase):
    def get_timeframes(self):
        return ["1h"]  # Specify required timeframes
    
    def initialize(self, backtester):
        self._resample_data(backtester.original_df)
        # Setup indicators...
        self.initialized = True
    
    def get_entry_signal(self, backtester, df_index):
        # Implement entry logic
        pass
    
    def get_exit_signal(self, backtester, df_index):
        # Implement exit logic
        pass
  1. Register in StrategyManager:
# In StrategyManager._load_strategies()
elif name == "new_strategy":
    strategies.append(NewStrategy(weight, params))

Multi-Timeframe Strategy Development

For strategies requiring multiple timeframes:

class MultiTimeframeStrategy(StrategyBase):
    def get_timeframes(self):
        return ["5min", "15min", "1h"]
    
    def initialize(self, backtester):
        self._resample_data(backtester.original_df)
        
        # Access different timeframes
        data_5m = self.get_data_for_timeframe("5min")
        data_15m = self.get_data_for_timeframe("15min") 
        data_1h = self.get_data_for_timeframe("1h")
        
        # Calculate indicators on each timeframe
        # ...
    
    def _calculate_signal_confidence(self, backtester, df_index):
        # Analyze multiple timeframes for confidence
        primary_signal = self._get_primary_signal(df_index)
        confirmation = self._get_timeframe_confirmation(df_index)
        
        return primary_signal * confirmation

Performance Considerations

Timeframe Management

  • Efficient Resampling: Each strategy resamples data once during initialization
  • Memory Usage: Only required timeframes are kept in memory
  • Signal Mapping: Efficient mapping between timeframes using pandas reindex

Strategy Combination

  • Lazy Evaluation: Signals calculated only when needed
  • Error Handling: Individual strategy failures don't crash the system
  • Logging: Comprehensive logging for debugging and monitoring

Best Practices

  1. Strategy Design:

    • Specify minimal required timeframes
    • Include 1min for stop-loss precision
    • Use confidence levels effectively
  2. Signal Combination:

    • Use any for exits (risk management)
    • Use weighted_consensus for entries
    • Set appropriate minimum confidence levels
  3. Error Handling:

    • Implement robust initialization checks
    • Handle missing data gracefully
    • Log strategy-specific warnings
  4. Testing:

    • Test strategies individually before combining
    • Validate timeframe requirements
    • Monitor memory usage with large datasets

Troubleshooting

Common Issues

  1. Timeframe Mismatches:

    • Ensure strategy specifies correct timeframes
    • Check data availability for all timeframes
  2. Signal Conflicts:

    • Review combination rules
    • Adjust confidence thresholds
    • Monitor strategy weights
  3. Performance Issues:

    • Minimize timeframe requirements
    • Optimize indicator calculations
    • Use efficient pandas operations

Debugging Tips

  • Enable detailed logging: logging.basicConfig(level=logging.DEBUG)
  • Use strategy summary: manager.get_strategy_summary()
  • Test individual strategies before combining
  • Monitor signal confidence levels

Version: 1.0.0
Last Updated: January 2025
TCP Cycles Project