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, andResultsProcessorcomponents 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
- StrategyBase: Abstract base class defining the strategy interface
- StrategySignal: Encapsulates trading signals with confidence levels
- StrategyManager: Orchestrates multiple strategies and combines signals
- 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 entryall: Enter only if ALL strategies signal entrymajority: Enter if majority of strategies signal entryweighted_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 agreepriority: 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
- 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
- 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
-
Strategy Design:
- Specify minimal required timeframes
- Include 1min for stop-loss precision
- Use confidence levels effectively
-
Signal Combination:
- Use
anyfor exits (risk management) - Use
weighted_consensusfor entries - Set appropriate minimum confidence levels
- Use
-
Error Handling:
- Implement robust initialization checks
- Handle missing data gracefully
- Log strategy-specific warnings
-
Testing:
- Test strategies individually before combining
- Validate timeframe requirements
- Monitor memory usage with large datasets
Troubleshooting
Common Issues
-
Timeframe Mismatches:
- Ensure strategy specifies correct timeframes
- Check data availability for all timeframes
-
Signal Conflicts:
- Review combination rules
- Adjust confidence thresholds
- Monitor strategy weights
-
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