Enhance README and documentation for Cycles framework

- Expanded the README.md to provide a comprehensive overview of the Cycles framework, including features, quick start instructions, and configuration examples.
- Updated strategies documentation to detail the architecture, available strategies, and their configurations, emphasizing the new multi-timeframe capabilities.
- Added a new timeframe system documentation to explain the strategy-controlled timeframe management and automatic data resampling.
- Improved the strategy manager documentation to clarify its role in orchestrating multiple strategies and combining signals effectively.
- Adjusted configuration examples to reflect recent changes in strategy parameters and usage.
This commit is contained in:
Vasily.onl 2025-05-23 17:06:35 +08:00
parent 9b15f9f44f
commit 9629d3090b
5 changed files with 1335 additions and 304 deletions

178
README.md
View File

@ -1 +1,177 @@
# Cycles # Cycles - Advanced Trading Strategy Backtesting Framework
A sophisticated Python framework for backtesting cryptocurrency trading strategies with multi-timeframe analysis, strategy combination, and advanced signal processing.
## Features
- **Multi-Strategy Architecture**: Combine multiple trading strategies with configurable weights and rules
- **Multi-Timeframe Analysis**: Strategies can operate on different timeframes (1min, 5min, 15min, 1h, etc.)
- **Advanced Strategies**:
- **Default Strategy**: Meta-trend analysis using multiple Supertrend indicators
- **BBRS Strategy**: Bollinger Bands + RSI with market regime detection
- **Flexible Signal Combination**: Weighted consensus, majority voting, any/all combinations
- **Precise Stop-Loss**: 1-minute precision for accurate risk management
- **Comprehensive Backtesting**: Detailed performance metrics and trade analysis
- **Data Visualization**: Interactive charts and performance plots
## Quick Start
### Prerequisites
- Python 3.8+
- [uv](https://github.com/astral-sh/uv) package manager (recommended)
### Installation
```bash
# Clone the repository
git clone <repository-url>
cd Cycles
# Install dependencies with uv
uv sync
# Or install with pip
pip install -r requirements.txt
```
### Running Backtests
Use the `uv run` command to execute backtests with different configurations:
```bash
# Run default strategy on 5-minute timeframe
uv run .\main.py .\configs\config_default_5min.json
# Run default strategy on 15-minute timeframe
uv run .\main.py .\configs\config_default.json
# Run BBRS strategy with market regime detection
uv run .\main.py .\configs\config_bbrs.json
# Run combined strategies
uv run .\main.py .\configs\config_combined.json
```
### Configuration Examples
#### Default Strategy (5-minute timeframe)
```bash
uv run .\main.py .\configs\config_default_5min.json
```
#### BBRS Strategy with Multi-timeframe Analysis
```bash
uv run .\main.py .\configs\config_bbrs_multi_timeframe.json
```
#### Combined Strategies with Weighted Consensus
```bash
uv run .\main.py .\configs\config_combined.json
```
## Configuration
Strategies are configured using JSON files in the `configs/` directory:
```json
{
"start_date": "2024-01-01",
"stop_date": "2024-01-31",
"initial_usd": 10000,
"timeframes": ["15min"],
"stop_loss_pcts": [0.03, 0.05],
"strategies": [
{
"name": "default",
"weight": 1.0,
"params": {
"timeframe": "15min"
}
}
],
"combination_rules": {
"entry": "any",
"exit": "any",
"min_confidence": 0.5
}
}
```
### Available Strategies
1. **Default Strategy**: Meta-trend analysis using Supertrend indicators
2. **BBRS Strategy**: Bollinger Bands + RSI with market regime detection
### Combination Rules
- **Entry**: `any`, `all`, `majority`, `weighted_consensus`
- **Exit**: `any`, `all`, `priority` (prioritizes stop-loss signals)
## Project Structure
```
Cycles/
├── configs/ # Configuration files
├── cycles/ # Core framework
│ ├── strategies/ # Strategy implementation
│ │ ├── base.py # Base strategy classes
│ │ ├── default_strategy.py
│ │ ├── bbrs_strategy.py
│ │ └── manager.py # Strategy manager
│ ├── Analysis/ # Technical analysis
│ ├── utils/ # Utilities
│ └── charts.py # Visualization
├── docs/ # Documentation
├── data/ # Market data
├── results/ # Backtest results
└── main.py # Main entry point
```
## Documentation
Detailed documentation is available in the `docs/` directory:
- **[Strategy Manager](./docs/strategy_manager.md)** - Multi-strategy orchestration and signal combination
- **[Strategies](./docs/strategies.md)** - Individual strategy implementations and usage
- **[Timeframe System](./docs/timeframe_system.md)** - Advanced timeframe management and multi-timeframe strategies
- **[Analysis](./docs/analysis.md)** - Technical analysis components
- **[Storage Utils](./docs/utils_storage.md)** - Data storage and retrieval
- **[System Utils](./docs/utils_system.md)** - System utilities
## Examples
### Single Strategy Backtest
```bash
# Test default strategy on different timeframes
uv run .\main.py .\configs\config_default.json # 15min
uv run .\main.py .\configs\config_default_5min.json # 5min
```
### Multi-Strategy Backtest
```bash
# Combine multiple strategies with different weights
uv run .\main.py .\configs\config_combined.json
```
### Custom Configuration
Create your own configuration file and run:
```bash
uv run .\main.py .\configs\your_config.json
```
## Output
Backtests generate:
- **CSV Results**: Detailed performance metrics per timeframe/strategy
- **Trade Log**: Individual trade records with entry/exit details
- **Performance Charts**: Visual analysis of strategy performance (in debug mode)
- **Log Files**: Detailed execution logs
## License
[Add your license information here]
## Contributing
[Add contributing guidelines here]

View File

@ -2,7 +2,7 @@
"start_date": "2025-03-01", "start_date": "2025-03-01",
"stop_date": "2025-03-15", "stop_date": "2025-03-15",
"initial_usd": 10000, "initial_usd": 10000,
"timeframes": ["15min"], "timeframes": ["1min"],
"stop_loss_pcts": [0.05], "stop_loss_pcts": [0.05],
"strategies": [ "strategies": [
{ {

View File

@ -1,98 +1,405 @@
# Trading Strategies (`cycles/Analysis/strategies.py`) # Strategies Documentation
This document outlines the trading strategies implemented within the `Strategy` class. These strategies utilize technical indicators calculated by other classes in the `Analysis` module. ## Overview
## Class: `Strategy` The Cycles framework implements advanced trading strategies with sophisticated timeframe management, signal processing, and multi-strategy combination capabilities. Each strategy can operate on its preferred timeframes while maintaining precise execution control.
Manages and executes different trading strategies. ## Architecture
### `__init__(self, config: dict = None, logging = None)` ### Strategy System Components
- **Description**: Initializes the Strategy class. 1. **StrategyBase**: Abstract base class with timeframe management
- **Parameters**: 2. **Individual Strategies**: DefaultStrategy, BBRSStrategy implementations
- `config` (dict, optional): Configuration dictionary containing parameters for various indicators and strategy settings. Must be provided if strategies requiring config are used. 3. **StrategyManager**: Multi-strategy orchestration and signal combination
- `logging` (logging.Logger, optional): Logger object for outputting messages. Defaults to `None`. 4. **Timeframe System**: Automatic data resampling and signal mapping
### `run(self, data: pd.DataFrame, strategy_name: str) -> pd.DataFrame` ### New Timeframe Management
- **Description**: Executes a specified trading strategy on the input data. Each strategy now controls its own timeframe requirements:
- **Parameters**:
- `data` (pd.DataFrame): Input DataFrame containing at least price data (e.g., 'close', 'volume'). Specific strategies might require other columns or will calculate them.
- `strategy_name` (str): The name of the strategy to run. Supported names include:
- `"MarketRegimeStrategy"`
- `"CryptoTradingStrategy"`
- `"no_strategy"` (or any other unrecognized name will default to this)
- **Returns**: `pd.DataFrame` - A DataFrame containing the original data augmented with indicator values, and `BuySignal` and `SellSignal` (boolean) columns specific to the executed strategy. The structure of the DataFrame (e.g., daily, 15-minute) depends on the strategy.
### `no_strategy(self, data: pd.DataFrame) -> pd.DataFrame` ```python
class MyStrategy(StrategyBase):
def get_timeframes(self):
return ["15min", "1h"] # Strategy specifies needed timeframes
def initialize(self, backtester):
# Framework automatically resamples data
self._resample_data(backtester.original_df)
# Access resampled data
data_15m = self.get_data_for_timeframe("15min")
data_1h = self.get_data_for_timeframe("1h")
```
- **Description**: A default strategy that generates no trading signals. It can serve as a baseline or placeholder. ## Available Strategies
- **Parameters**:
- `data` (pd.DataFrame): Input data DataFrame.
- **Returns**: `pd.DataFrame` - The input DataFrame with `BuySignal` and `SellSignal` columns added, both containing all `False` values.
--- ### 1. Default Strategy (Meta-Trend Analysis)
## Implemented Strategies **Purpose**: Meta-trend analysis using multiple Supertrend indicators
### 1. `MarketRegimeStrategy` **Timeframe Behavior**:
- **Configurable Primary Timeframe**: Set via `params["timeframe"]` (default: "15min")
- **1-Minute Precision**: Always includes 1min data for precise stop-loss execution
- **Example Timeframes**: `["15min", "1min"]` or `["5min", "1min"]`
- **Description**: An adaptive strategy that combines Bollinger Bands and RSI, adjusting its parameters based on detected market regimes (trending vs. sideways). It operates on daily aggregated data (aggregation is performed internally). **Configuration**:
- **Core Logic**: ```json
- Calculates Bollinger Bands (using `BollingerBands` class) with adaptive standard deviation multipliers based on `MarketRegime` (derived from `BBWidth`). {
- Calculates RSI (using `RSI` class). "name": "default",
- **Trending Market (Breakout Mode)**: "weight": 1.0,
- Buy: Price < Lower Band RSI < 50 Volume Spike. "params": {
- Sell: Price > Upper Band ∧ RSI > 50 ∧ Volume Spike. "timeframe": "15min", // Configurable: "5min", "15min", "1h", etc.
- **Sideways Market (Mean Reversion)**: "stop_loss_pct": 0.03 // Stop loss percentage
- Buy: Price ≤ Lower Band ∧ RSI ≤ 40. }
- Sell: Price ≥ Upper Band ∧ RSI ≥ 60. }
- **Squeeze Confirmation** (if `config["SqueezeStrategy"]` is `True`): ```
- Requires additional confirmation from RSI Bollinger Bands (calculated by `rsi_bollinger_confirmation` helper method).
- Sideways markets also check for volume contraction.
- **Key Configuration Parameters (from `config` dict)**:
- `bb_period`, `bb_width`
- `trending['bb_std_dev_multiplier']`, `trending['rsi_threshold']`
- `sideways['bb_std_dev_multiplier']`, `sideways['rsi_threshold']`
- `rsi_period`
- `SqueezeStrategy` (boolean)
- **Output DataFrame Columns (Daily)**: Includes input columns plus `SMA`, `UpperBand`, `LowerBand`, `BBWidth`, `MarketRegime`, `RSI`, `BuySignal`, `SellSignal`.
#### `rsi_bollinger_confirmation(self, rsi: pd.Series, window: int = 14, std_mult: float = 1.5) -> tuple` **Algorithm**:
1. Calculate 3 Supertrend indicators with different parameters on primary timeframe
2. Determine meta-trend: all three must agree for directional signal
3. **Entry**: Meta-trend changes from != 1 to == 1 (all trends align upward)
4. **Exit**: Meta-trend changes to -1 (trend reversal) or stop-loss triggered
5. **Stop-Loss**: 1-minute precision using percentage-based threshold
- **Description** (Helper for `MarketRegimeStrategy`): Calculates Bollinger Bands on RSI values for signal confirmation. **Strengths**:
- **Parameters**: - Robust trend following with multiple confirmations
- `rsi` (pd.Series): Series containing RSI values. - Configurable for different market timeframes
- `window` (int, optional): The period for the moving average. Defaults to 14. - Precise risk management
- `std_mult` (float, optional): Standard deviation multiplier for bands. Defaults to 1.5. - Low false signals in trending markets
- **Returns**: `tuple` - (oversold_condition, overbought_condition) as pandas Series (boolean).
### 2. `CryptoTradingStrategy` **Best Use Cases**:
- Medium to long-term trend following
- Markets with clear directional movements
- Risk-conscious trading with defined exits
- **Description**: A multi-timeframe strategy primarily designed for volatile assets like cryptocurrencies. It aggregates input data into 15-minute and 1-hour intervals for analysis. ### 2. BBRS Strategy (Bollinger Bands + RSI)
- **Core Logic**:
- Aggregates data to 15-minute (`data_15m`) and 1-hour (`data_1h`) resolutions using `aggregate_to_minutes` and `aggregate_to_hourly` from `data_utils.py`.
- Calculates 15-minute Bollinger Bands (20-period, 2 std dev) and 15-minute EMA-smoothed RSI (14-period) using `BollingerBands.calculate_custom_bands` and `RSI.calculate_custom_rsi`.
- Calculates 1-hour Bollinger Bands (50-period, 1.8 std dev) using `BollingerBands.calculate_custom_bands`.
- **Signal Generation (on 15m timeframe)**:
- Buy Signal: Price ≤ Lower 15m Band ∧ Price ≤ Lower 1h Band ∧ RSI_15m < 35 Volume Confirmation.
- Sell Signal: Price ≥ Upper 15m Band ∧ Price ≥ Upper 1h Band ∧ RSI_15m > 65 ∧ Volume Confirmation.
- **Volume Confirmation**: Current 15m volume > 1.5 × 20-period MA of 15m volume.
- **Risk Management**: Calculates `StopLoss` and `TakeProfit` levels based on a simplified ATR (standard deviation of 15m close prices over the last 4 periods).
- Buy: SL = Price - 2 * ATR; TP = Price + 4 * ATR
- Sell: SL = Price + 2 * ATR; TP = Price - 4 * ATR
- **Key Configuration Parameters**: While this strategy uses fixed parameters for its core indicator calculations, the `config` object passed to the `Strategy` class might be used by helper functions or for future extensions (though not heavily used by the current `CryptoTradingStrategy` logic itself for primary indicator settings).
- **Output DataFrame Columns (15-minute)**: Includes resampled 15m OHLCV, plus `UpperBand_15m`, `SMA_15m`, `LowerBand_15m`, `RSI_15m`, `VolumeMA_15m`, `UpperBand_1h` (forward-filled), `LowerBand_1h` (forward-filled), `BuySignal`, `SellSignal`, `StopLoss`, `TakeProfit`.
--- **Purpose**: Market regime-adaptive strategy combining Bollinger Bands and RSI
## General Strategy Concepts (from previous high-level notes) **Timeframe Behavior**:
- **1-Minute Input**: Strategy receives 1-minute data
- **Internal Resampling**: Underlying Strategy class handles resampling to 15min/1h
- **No Double-Resampling**: Avoids conflicts with existing resampling logic
- **Signal Mapping**: Results mapped back to 1-minute resolution
While the specific implementations above have their own detailed logic, some general concepts that often inspire trading strategies include: **Configuration**:
```json
{
"name": "bbrs",
"weight": 1.0,
"params": {
"bb_width": 0.05, // Bollinger Band width threshold
"bb_period": 20, // Bollinger Band period
"rsi_period": 14, // RSI calculation period
"trending_rsi_threshold": [30, 70], // RSI thresholds for trending market
"trending_bb_multiplier": 2.5, // BB multiplier for trending market
"sideways_rsi_threshold": [40, 60], // RSI thresholds for sideways market
"sideways_bb_multiplier": 1.8, // BB multiplier for sideways market
"strategy_name": "MarketRegimeStrategy", // Implementation variant
"SqueezeStrategy": true, // Enable squeeze detection
"stop_loss_pct": 0.05 // Stop loss percentage
}
}
```
- **Adaptive Parameters**: Adjusting indicator settings (like Bollinger Band width or RSI thresholds) based on market conditions (e.g., trending vs. sideways). **Algorithm**:
- **Multi-Timeframe Analysis**: Confirming signals on one timeframe with trends or levels on another (e.g., 15-minute signals confirmed by 1-hour context).
- **Volume Confirmation**: Using volume spikes or contractions to validate price-based signals.
- **Volatility-Adjusted Risk Management**: Using measures like ATR (Average True Range) to set stop-loss and take-profit levels, or to size positions dynamically.
These concepts are partially reflected in the implemented strategies, particularly in `MarketRegimeStrategy` (adaptive parameters) and `CryptoTradingStrategy` (multi-timeframe, volume confirmation, ATR-based risk levels). **MarketRegimeStrategy** (Primary Implementation):
1. **Market Regime Detection**: Determines if market is trending or sideways
2. **Adaptive Parameters**: Adjusts BB/RSI thresholds based on market regime
3. **Trending Market Entry**: Price < Lower Band RSI < 50 Volume Spike
4. **Sideways Market Entry**: Price ≤ Lower Band ∧ RSI ≤ 40
5. **Exit Conditions**: Opposite band touch, RSI reversal, or stop-loss
6. **Volume Confirmation**: Requires 1.5× average volume for trending signals
**CryptoTradingStrategy** (Alternative Implementation):
1. **Multi-Timeframe Analysis**: Combines 15-minute and 1-hour Bollinger Bands
2. **Entry**: Price ≤ both 15m & 1h lower bands + RSI < 35 + Volume surge
3. **Exit**: 2:1 risk-reward ratio with ATR-based stops
4. **Adaptive Volatility**: Uses ATR for dynamic stop-loss/take-profit
**Strengths**:
- Adapts to different market regimes
- Multiple timeframe confirmation (internal)
- Volume analysis for signal quality
- Sophisticated entry/exit conditions
**Best Use Cases**:
- Volatile cryptocurrency markets
- Markets with alternating trending/sideways periods
- Short to medium-term trading
## Strategy Combination
### Multi-Strategy Architecture
The StrategyManager allows combining multiple strategies with configurable rules:
```json
{
"strategies": [
{
"name": "default",
"weight": 0.6,
"params": {"timeframe": "15min"}
},
{
"name": "bbrs",
"weight": 0.4,
"params": {"strategy_name": "MarketRegimeStrategy"}
}
],
"combination_rules": {
"entry": "weighted_consensus",
"exit": "any",
"min_confidence": 0.6
}
}
```
### Signal Combination Methods
**Entry Combinations**:
- **`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 confidence average
**Exit Combinations**:
- **`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)
## Performance Characteristics
### Default Strategy Performance
**Strengths**:
- **Trend Accuracy**: High accuracy in strong trending markets
- **Risk Management**: Defined stop-losses with 1-minute precision
- **Low Noise**: Multiple Supertrend confirmation reduces false signals
- **Adaptable**: Works across different timeframes
**Weaknesses**:
- **Sideways Markets**: May generate false signals in ranging markets
- **Lag**: Multiple confirmations can delay entry/exit signals
- **Whipsaws**: Vulnerable to rapid trend reversals
**Optimal Conditions**:
- Clear trending markets
- Medium to low volatility trending
- Sufficient data history for Supertrend calculation
### BBRS Strategy Performance
**Strengths**:
- **Market Adaptation**: Automatically adjusts to market regime
- **Volume Confirmation**: Reduces false signals with volume analysis
- **Multi-Timeframe**: Internal analysis across multiple timeframes
- **Volatility Handling**: Designed for cryptocurrency volatility
**Weaknesses**:
- **Complexity**: More parameters to optimize
- **Market Noise**: Can be sensitive to short-term noise
- **Volume Dependency**: Requires reliable volume data
**Optimal Conditions**:
- High-volume cryptocurrency markets
- Markets with clear regime shifts
- Sufficient data for regime detection
## Usage Examples
### Single Strategy Backtests
```bash
# Default strategy on 15-minute timeframe
uv run .\main.py .\configs\config_default.json
# Default strategy on 5-minute timeframe
uv run .\main.py .\configs\config_default_5min.json
# BBRS strategy with market regime detection
uv run .\main.py .\configs\config_bbrs.json
```
### Multi-Strategy Backtests
```bash
# Combined strategies with weighted consensus
uv run .\main.py .\configs\config_combined.json
```
### Custom Configurations
**Aggressive Default Strategy**:
```json
{
"name": "default",
"params": {
"timeframe": "5min", // Faster signals
"stop_loss_pct": 0.02 // Tighter stop-loss
}
}
```
**Conservative BBRS Strategy**:
```json
{
"name": "bbrs",
"params": {
"bb_width": 0.03, // Tighter BB width
"stop_loss_pct": 0.07, // Wider stop-loss
"SqueezeStrategy": false // Disable squeeze for simplicity
}
}
```
## Development Guidelines
### Creating New Strategies
1. **Inherit from StrategyBase**:
```python
from cycles.strategies.base import StrategyBase, StrategySignal
class NewStrategy(StrategyBase):
def __init__(self, weight=1.0, params=None):
super().__init__("new_strategy", weight, params)
```
2. **Specify Timeframes**:
```python
def get_timeframes(self):
return ["1h"] # Specify required timeframes
```
3. **Implement Core Methods**:
```python
def initialize(self, backtester):
self._resample_data(backtester.original_df)
# Calculate indicators...
self.initialized = True
def get_entry_signal(self, backtester, df_index):
# Entry logic...
return StrategySignal("ENTRY", confidence=0.8)
def get_exit_signal(self, backtester, df_index):
# Exit logic...
return StrategySignal("EXIT", confidence=1.0)
```
4. **Register Strategy**:
```python
# In StrategyManager._load_strategies()
elif name == "new_strategy":
strategies.append(NewStrategy(weight, params))
```
### Timeframe Best Practices
1. **Minimize Timeframe Requirements**:
```python
def get_timeframes(self):
return ["15min"] # Only what's needed
```
2. **Include 1min for Stop-Loss**:
```python
def get_timeframes(self):
primary_tf = self.params.get("timeframe", "15min")
timeframes = [primary_tf]
if "1min" not in timeframes:
timeframes.append("1min")
return timeframes
```
3. **Handle Multi-Timeframe Synchronization**:
```python
def get_entry_signal(self, backtester, df_index):
# Get current timestamp from primary timeframe
primary_data = self.get_primary_timeframe_data()
current_time = primary_data.index[df_index]
# Map to other timeframes
hourly_data = self.get_data_for_timeframe("1h")
h1_idx = hourly_data.index.get_indexer([current_time], method='ffill')[0]
```
## Testing and Validation
### Strategy Testing Workflow
1. **Individual Strategy Testing**:
- Test each strategy independently
- Validate on different timeframes
- Check edge cases and data sufficiency
2. **Multi-Strategy Testing**:
- Test strategy combinations
- Validate combination rules
- Monitor for signal conflicts
3. **Timeframe Validation**:
- Ensure consistent behavior across timeframes
- Validate data alignment
- Check memory usage with large datasets
### Performance Monitoring
```python
# Get strategy summary
summary = strategy_manager.get_strategy_summary()
print(f"Strategies: {[s['name'] for s in summary['strategies']]}")
print(f"Timeframes: {summary['all_timeframes']}")
# Monitor individual strategy performance
for strategy in strategy_manager.strategies:
print(f"{strategy.name}: {strategy.get_timeframes()}")
```
## Advanced Topics
### Multi-Timeframe Strategy Development
For strategies requiring multiple timeframes:
```python
class MultiTimeframeStrategy(StrategyBase):
def get_timeframes(self):
return ["5min", "15min", "1h"]
def get_entry_signal(self, backtester, df_index):
# Analyze multiple 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")
# Synchronize across timeframes
current_time = data_5m.index[df_index]
idx_15m = data_15m.index.get_indexer([current_time], method='ffill')[0]
idx_1h = data_1h.index.get_indexer([current_time], method='ffill')[0]
# Multi-timeframe logic
short_signal = self._analyze_5min(data_5m, df_index)
medium_signal = self._analyze_15min(data_15m, idx_15m)
long_signal = self._analyze_1h(data_1h, idx_1h)
# Combine signals with appropriate confidence
if short_signal and medium_signal and long_signal:
return StrategySignal("ENTRY", confidence=0.9)
elif short_signal and medium_signal:
return StrategySignal("ENTRY", confidence=0.7)
else:
return StrategySignal("HOLD", confidence=0.0)
```
### Strategy Optimization
1. **Parameter Optimization**: Systematic testing of strategy parameters
2. **Timeframe Optimization**: Finding optimal timeframes for each strategy
3. **Combination Optimization**: Optimizing weights and combination rules
4. **Market Regime Adaptation**: Adapting strategies to different market conditions
For detailed timeframe system documentation, see [Timeframe System](./timeframe_system.md).

View File

@ -1,83 +1,180 @@
# TCP Cycles Strategy Management System # Strategy Manager Documentation
The Strategy Manager system provides a flexible framework for implementing, combining, and managing multiple trading strategies within the TCP Cycles project. ## Overview
## 🏗️ Architecture 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.
### Module Structure ## Architecture
```
cycles/
├── strategies/ # Strategy management module
│ ├── __init__.py # Module exports and version info
│ ├── base.py # Base classes (StrategyBase, StrategySignal)
│ ├── default_strategy.py # Meta-trend strategy implementation
│ ├── bbrs_strategy.py # Bollinger Bands + RSI strategy
│ └── manager.py # StrategyManager and orchestration
├── Analysis/ # Technical analysis tools
├── utils/ # Utility functions
├── backtest.py # Backtesting engine
└── charts.py # Charting and visualization
```
### Core Components ### Core Components
1. **`StrategyBase`**: Abstract base class that all strategies inherit from 1. **StrategyBase**: Abstract base class defining the strategy interface
2. **`StrategySignal`**: Represents trading signals with confidence levels and metadata 2. **StrategySignal**: Encapsulates trading signals with confidence levels
3. **`DefaultStrategy`**: Implementation of the meta-trend strategy using Supertrend indicators 3. **StrategyManager**: Orchestrates multiple strategies and combines signals
4. **`BBRSStrategy`**: Implementation of the Bollinger Bands + RSI strategy with market regime detection 4. **Strategy Implementations**: DefaultStrategy, BBRSStrategy, etc.
5. **`StrategyManager`**: Orchestrates multiple strategies and combines their signals
### Signal Types ### New Timeframe System
- **`"ENTRY"`**: Strategy suggests entering a position
- **`"EXIT"`**: Strategy suggests exiting a position
- **`"HOLD"`**: Strategy suggests no action
## 📋 Configuration The framework now supports strategy-level timeframe management:
### Single Strategy Configuration - **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
**Default Strategy Only:** ```python
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:
```python
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:
```python
# 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:**
```json ```json
{ {
"start_date": "2025-03-01", "name": "default",
"stop_date": "2025-03-15", "weight": 1.0,
"initial_usd": 10000, "params": {
"timeframes": ["15min"], "timeframe": "15min",
"stop_loss_pcts": [0.03, 0.05], "stop_loss_pct": 0.03
"strategies": [
{
"name": "default",
"weight": 1.0,
"params": {}
}
],
"combination_rules": {
"entry": "any",
"exit": "any",
"min_confidence": 0.5
} }
} }
``` ```
**BBRS Strategy Only:** **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:**
```json ```json
{ {
"strategies": [ "name": "bbrs",
{ "weight": 1.0,
"name": "bbrs", "params": {
"weight": 1.0, "bb_width": 0.05,
"params": { "bb_period": 20,
"bb_width": 0.05, "rsi_period": 14,
"bb_period": 20, "strategy_name": "MarketRegimeStrategy",
"rsi_period": 14, "stop_loss_pct": 0.05
"strategy_name": "MarketRegimeStrategy" }
}
}
]
} }
``` ```
### Multiple Strategy Configuration **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
```python
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
```python
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
```json ```json
{ {
@ -85,11 +182,14 @@ cycles/
{ {
"name": "default", "name": "default",
"weight": 0.6, "weight": 0.6,
"params": {} "params": {
"timeframe": "15min",
"stop_loss_pct": 0.03
}
}, },
{ {
"name": "bbrs", "name": "bbrs",
"weight": 0.4, "weight": 0.4,
"params": { "params": {
"bb_width": 0.05, "bb_width": 0.05,
"strategy_name": "MarketRegimeStrategy" "strategy_name": "MarketRegimeStrategy"
@ -99,229 +199,189 @@ cycles/
"combination_rules": { "combination_rules": {
"entry": "weighted_consensus", "entry": "weighted_consensus",
"exit": "any", "exit": "any",
"min_confidence": 0.6 "min_confidence": 0.5
} }
} }
``` ```
## 🔧 Combination Rules ### Timeframe Examples
### Entry Signal Combination Methods **Single Timeframe Strategy:**
```json
- **`"any"`**: Enter if ANY strategy signals entry above min_confidence {
- **`"all"`**: Enter only if ALL strategies signal entry above min_confidence "name": "default",
- **`"majority"`**: Enter if more than 50% of strategies signal entry "params": {
- **`"weighted_consensus"`**: Enter based on weighted average confidence "timeframe": "5min" # Strategy works on 5-minute data
}
### Exit Signal Combination Methods }
- **`"any"`**: Exit if ANY strategy signals exit (recommended for risk management)
- **`"all"`**: Exit only if ALL strategies agree on exit
- **`"priority"`**: Exit based on priority: STOP_LOSS > SELL_SIGNAL > others
### Parameters
- **`min_confidence`**: Minimum confidence threshold (0.0 to 1.0)
- **`weight`**: Strategy weight for weighted calculations
## 🚀 Usage Examples
### Running with Default Strategy
```bash
python main.py config_default.json
``` ```
### Running with BBRS Strategy **Multi-Timeframe Strategy (Future Enhancement):**
```bash ```json
python main.py config_bbrs.json {
"name": "multi_tf_strategy",
"params": {
"timeframes": ["5min", "15min", "1h"], # Multiple timeframes
"primary_timeframe": "15min"
}
}
``` ```
### Running with Combined Strategies ## Usage Examples
```bash
python main.py config_combined.json
```
### Running without Config (Interactive) ### Create Strategy Manager
```bash
python main.py
```
### Programmatic Usage
```python ```python
from cycles.strategies import create_strategy_manager from cycles.strategies import create_strategy_manager
# Create strategy manager from config
config = { config = {
"strategies": [ "strategies": [
{"name": "default", "weight": 0.7, "params": {}}, {"name": "default", "weight": 1.0, "params": {"timeframe": "15min"}}
{"name": "bbrs", "weight": 0.3, "params": {"bb_width": 0.05}}
], ],
"combination_rules": { "combination_rules": {
"entry": "weighted_consensus", "entry": "any",
"exit": "any", "exit": "any"
"min_confidence": 0.6
} }
} }
strategy_manager = create_strategy_manager(config) strategy_manager = create_strategy_manager(config)
``` ```
## ⚙️ Strategy Parameters ### Initialize and Use
### Default Strategy Parameters
- **`stop_loss_pct`**: Stop loss percentage (default: 0.03)
### BBRS Strategy Parameters
- **`bb_width`**: Bollinger Band width (default: 0.05)
- **`bb_period`**: Bollinger Band period (default: 20)
- **`rsi_period`**: RSI period (default: 14)
- **`trending_rsi_threshold`**: RSI thresholds for trending market [low, high]
- **`trending_bb_multiplier`**: BB multiplier for trending market
- **`sideways_rsi_threshold`**: RSI thresholds for sideways market [low, high]
- **`sideways_bb_multiplier`**: BB multiplier for sideways market
- **`strategy_name`**: Strategy implementation name
- **`SqueezeStrategy`**: Enable squeeze strategy (boolean)
- **`stop_loss_pct`**: Stop loss percentage (default: 0.05)
## 🔌 Adding New Strategies
### 1. Create Strategy Class
Create a new file in `cycles/strategies/` (e.g., `my_strategy.py`):
```python ```python
from .base import StrategyBase, StrategySignal # Initialize with backtester
strategy_manager.initialize(backtester)
class MyStrategy(StrategyBase): # Get signals during backtesting
def __init__(self, weight=1.0, params=None): entry_signal = strategy_manager.get_entry_signal(backtester, df_index)
super().__init__("my_strategy", weight, params) 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:**
```python
class NewStrategy(StrategyBase):
def get_timeframes(self):
return ["1h"] # Specify required timeframes
def initialize(self, backtester): def initialize(self, backtester):
# Initialize your strategy indicators self._resample_data(backtester.original_df)
# Setup indicators...
self.initialized = True self.initialized = True
def get_entry_signal(self, backtester, df_index): def get_entry_signal(self, backtester, df_index):
# Implement entry logic # Implement entry logic
if entry_condition: pass
return StrategySignal("ENTRY", confidence=0.8)
return StrategySignal("HOLD", confidence=0.0)
def get_exit_signal(self, backtester, df_index): def get_exit_signal(self, backtester, df_index):
# Implement exit logic # Implement exit logic
if exit_condition: pass
return StrategySignal("EXIT", confidence=1.0,
metadata={"type": "MY_EXIT"})
return StrategySignal("HOLD", confidence=0.0)
``` ```
### 2. Register Strategy 2. **Register in StrategyManager:**
```python
# In StrategyManager._load_strategies()
elif name == "new_strategy":
strategies.append(NewStrategy(weight, params))
```
Update `cycles/strategies/manager.py` in the `_load_strategies` method: ### Multi-Timeframe Strategy Development
For strategies requiring multiple timeframes:
```python ```python
elif name == "my_strategy": class MultiTimeframeStrategy(StrategyBase):
from .my_strategy import MyStrategy def get_timeframes(self):
strategies.append(MyStrategy(weight, params)) 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
``` ```
### 3. Export Strategy ## Performance Considerations
Update `cycles/strategies/__init__.py`: ### Timeframe Management
```python - **Efficient Resampling**: Each strategy resamples data once during initialization
from .my_strategy import MyStrategy - **Memory Usage**: Only required timeframes are kept in memory
- **Signal Mapping**: Efficient mapping between timeframes using pandas reindex
__all__ = [ ### Strategy Combination
# ... existing exports ...
'MyStrategy'
]
```
## 📊 Performance Features - **Lazy Evaluation**: Signals calculated only when needed
- **Error Handling**: Individual strategy failures don't crash the system
- **Logging**: Comprehensive logging for debugging and monitoring
### Strategy Analysis ## Best Practices
- Individual strategy performance tracking
- Combined strategy performance metrics
- Signal quality analysis
- Confidence level monitoring
### Plotting Support 1. **Strategy Design:**
- Automatic chart generation for BBRS strategies - Specify minimal required timeframes
- Meta-trend visualization for default strategy - Include 1min for stop-loss precision
- Combined signal overlays - Use confidence levels effectively
- Performance comparison charts
## 🔄 Backward Compatibility 2. **Signal Combination:**
- Use `any` for exits (risk management)
- Use `weighted_consensus` for entries
- Set appropriate minimum confidence levels
The system maintains full backward compatibility: 3. **Error Handling:**
- ✅ Existing code using single strategies works unchanged - Implement robust initialization checks
- ✅ Legacy strategy functions are preserved in main.py - Handle missing data gracefully
- ✅ Default behavior matches original implementation - Log strategy-specific warnings
- ✅ Gradual migration path available
## 📚 Best Practices 4. **Testing:**
- Test strategies individually before combining
- Validate timeframe requirements
- Monitor memory usage with large datasets
### 1. **Risk Management** ## Troubleshooting
- Use `"any"` exit rule for faster risk exits
- Set appropriate stop loss percentages per strategy
- Monitor combined drawdown vs individual strategies
### 2. **Signal Quality** ### Common Issues
- Set appropriate `min_confidence` based on strategy reliability
- Test individual strategies thoroughly before combining
- Monitor signal frequency and quality
### 3. **Weight Distribution** 1. **Timeframe Mismatches:**
- Balance strategy weights based on historical performance - Ensure strategy specifies correct timeframes
- Consider strategy correlation when setting weights - Check data availability for all timeframes
- Regularly rebalance based on changing market conditions
### 4. **Testing & Validation** 2. **Signal Conflicts:**
- Backtest individual strategies first - Review combination rules
- Test combinations on historical data - Adjust confidence thresholds
- Validate on out-of-sample data - Monitor strategy weights
### 5. **Monitoring** 3. **Performance Issues:**
- Log strategy initialization and errors - Minimize timeframe requirements
- Track individual vs combined performance - Optimize indicator calculations
- Monitor signal generation frequency - Use efficient pandas operations
## 🔍 Troubleshooting ### Debugging Tips
### Strategy Not Found Error - Enable detailed logging: `logging.basicConfig(level=logging.DEBUG)`
``` - Use strategy summary: `manager.get_strategy_summary()`
ValueError: Unknown strategy: my_strategy - Test individual strategies before combining
``` - Monitor signal confidence levels
**Solution**: Ensure strategy is registered in `manager.py` `_load_strategies` method
### No Signals Generated
**Possible Causes**:
- Strategy initialization failed
- Data insufficient for strategy requirements
- `min_confidence` threshold too high
**Solution**: Check logs, verify data, adjust confidence threshold
### Poor Combined Performance
**Analysis Steps**:
1. Review individual strategy performance
2. Check strategy correlation and overlap
3. Adjust weights and combination rules
4. Consider market regime compatibility
### Import Errors
```
ImportError: cannot import name 'StrategyManager'
```
**Solution**: Use correct import path: `from cycles.strategies import StrategyManager`
## 📞 Support
For issues, feature requests, or contributions:
1. Check existing documentation and examples
2. Review troubleshooting section
3. Examine configuration files for proper syntax
4. Ensure all dependencies are installed
--- ---

488
docs/timeframe_system.md Normal file
View File

@ -0,0 +1,488 @@
# Timeframe System Documentation
## Overview
The Cycles framework features a sophisticated timeframe management system that allows strategies to operate on their preferred timeframes while maintaining precise execution control. This system supports both single-timeframe and multi-timeframe strategies with automatic data resampling and intelligent signal mapping.
## Architecture
### Core Concepts
1. **Strategy-Controlled Timeframes**: Each strategy specifies its required timeframes
2. **Automatic Resampling**: Framework resamples 1-minute data to strategy needs
3. **Precision Execution**: All strategies maintain 1-minute data for accurate stop-loss execution
4. **Signal Mapping**: Intelligent mapping between different timeframe resolutions
### Data Flow
```
Original 1min Data
Strategy.get_timeframes() → ["15min", "1h"]
Automatic Resampling
Strategy Logic (15min + 1h analysis)
Signal Generation
Map to Working Timeframe
Backtesting Engine
```
## Strategy Timeframe Interface
### StrategyBase Methods
All strategies inherit timeframe capabilities from `StrategyBase`:
```python
class MyStrategy(StrategyBase):
def get_timeframes(self) -> List[str]:
"""Specify required timeframes for this strategy"""
return ["15min", "1h"] # Strategy needs both timeframes
def initialize(self, backtester) -> None:
# Automatic resampling happens here
self._resample_data(backtester.original_df)
# Access resampled data
data_15m = self.get_data_for_timeframe("15min")
data_1h = self.get_data_for_timeframe("1h")
# Calculate indicators on each timeframe
self.indicators_15m = self._calculate_indicators(data_15m)
self.indicators_1h = self._calculate_indicators(data_1h)
self.initialized = True
```
### Data Access Methods
```python
# Get data for specific timeframe
data_15m = strategy.get_data_for_timeframe("15min")
# Get primary timeframe data (first in list)
primary_data = strategy.get_primary_timeframe_data()
# Check available timeframes
timeframes = strategy.get_timeframes()
```
## Supported Timeframes
### Standard Timeframes
- **`"1min"`**: 1-minute bars (original resolution)
- **`"5min"`**: 5-minute bars
- **`"15min"`**: 15-minute bars
- **`"30min"`**: 30-minute bars
- **`"1h"`**: 1-hour bars
- **`"4h"`**: 4-hour bars
- **`"1d"`**: Daily bars
### Custom Timeframes
Any pandas-compatible frequency string is supported:
- **`"2min"`**: 2-minute bars
- **`"10min"`**: 10-minute bars
- **`"2h"`**: 2-hour bars
- **`"12h"`**: 12-hour bars
## Strategy Examples
### Single Timeframe Strategy
```python
class SingleTimeframeStrategy(StrategyBase):
def get_timeframes(self):
return ["15min"] # Only needs 15-minute data
def initialize(self, backtester):
self._resample_data(backtester.original_df)
# Work with 15-minute data
data = self.get_primary_timeframe_data()
self.indicators = self._calculate_indicators(data)
self.initialized = True
def get_entry_signal(self, backtester, df_index):
# df_index refers to 15-minute data
if self.indicators['signal'][df_index]:
return StrategySignal("ENTRY", confidence=0.8)
return StrategySignal("HOLD", confidence=0.0)
```
### Multi-Timeframe Strategy
```python
class MultiTimeframeStrategy(StrategyBase):
def get_timeframes(self):
return ["15min", "1h", "4h"] # Multiple timeframes
def initialize(self, backtester):
self._resample_data(backtester.original_df)
# Access different timeframes
self.data_15m = self.get_data_for_timeframe("15min")
self.data_1h = self.get_data_for_timeframe("1h")
self.data_4h = self.get_data_for_timeframe("4h")
# Calculate indicators on each timeframe
self.trend_4h = self._calculate_trend(self.data_4h)
self.momentum_1h = self._calculate_momentum(self.data_1h)
self.entry_signals_15m = self._calculate_entries(self.data_15m)
self.initialized = True
def get_entry_signal(self, backtester, df_index):
# Primary timeframe is 15min (first in list)
# Map df_index to other timeframes for confirmation
# Get current 15min timestamp
current_time = self.data_15m.index[df_index]
# Find corresponding indices in other timeframes
h1_idx = self.data_1h.index.get_indexer([current_time], method='ffill')[0]
h4_idx = self.data_4h.index.get_indexer([current_time], method='ffill')[0]
# Multi-timeframe confirmation
trend_ok = self.trend_4h[h4_idx] > 0
momentum_ok = self.momentum_1h[h1_idx] > 0.5
entry_signal = self.entry_signals_15m[df_index]
if trend_ok and momentum_ok and entry_signal:
confidence = 0.9 # High confidence with all timeframes aligned
return StrategySignal("ENTRY", confidence=confidence)
return StrategySignal("HOLD", confidence=0.0)
```
### Configurable Timeframe Strategy
```python
class ConfigurableStrategy(StrategyBase):
def get_timeframes(self):
# Strategy timeframe configurable via parameters
primary_tf = self.params.get("timeframe", "15min")
return [primary_tf, "1min"] # Primary + 1min for stop-loss
def initialize(self, backtester):
self._resample_data(backtester.original_df)
primary_tf = self.get_timeframes()[0]
self.data = self.get_data_for_timeframe(primary_tf)
# Indicator parameters can also be timeframe-dependent
if primary_tf == "5min":
self.ma_period = 20
elif primary_tf == "15min":
self.ma_period = 14
else:
self.ma_period = 10
self.indicators = self._calculate_indicators(self.data)
self.initialized = True
```
## Built-in Strategy Timeframe Behavior
### Default Strategy
**Timeframes**: Configurable primary + 1min for stop-loss
```python
# Configuration
{
"name": "default",
"params": {
"timeframe": "5min" # Configurable timeframe
}
}
# Resulting timeframes: ["5min", "1min"]
```
**Features**:
- Supertrend analysis on configured timeframe
- 1-minute precision for stop-loss execution
- Optimized for 15-minute default, but works on any timeframe
### BBRS Strategy
**Timeframes**: 1min input (internal resampling)
```python
# Configuration
{
"name": "bbrs",
"params": {
"strategy_name": "MarketRegimeStrategy"
}
}
# Resulting timeframes: ["1min"]
```
**Features**:
- Uses 1-minute data as input
- Internal resampling to 15min/1h by Strategy class
- Signals mapped back to 1-minute resolution
- No double-resampling issues
## Advanced Features
### Timeframe Synchronization
When working with multiple timeframes, synchronization is crucial:
```python
def _get_synchronized_signals(self, df_index, primary_timeframe="15min"):
"""Get signals synchronized across timeframes"""
# Get timestamp from primary timeframe
primary_data = self.get_data_for_timeframe(primary_timeframe)
current_time = primary_data.index[df_index]
signals = {}
for tf in self.get_timeframes():
if tf == primary_timeframe:
signals[tf] = df_index
else:
# Find corresponding index in other timeframe
tf_data = self.get_data_for_timeframe(tf)
tf_idx = tf_data.index.get_indexer([current_time], method='ffill')[0]
signals[tf] = tf_idx
return signals
```
### Dynamic Timeframe Selection
Strategies can adapt timeframes based on market conditions:
```python
class AdaptiveStrategy(StrategyBase):
def get_timeframes(self):
# Fixed set of timeframes strategy might need
return ["5min", "15min", "1h"]
def _select_active_timeframe(self, market_volatility):
"""Select timeframe based on market conditions"""
if market_volatility > 0.8:
return "5min" # High volatility -> shorter timeframe
elif market_volatility > 0.4:
return "15min" # Medium volatility -> medium timeframe
else:
return "1h" # Low volatility -> longer timeframe
def get_entry_signal(self, backtester, df_index):
# Calculate market volatility
volatility = self._calculate_volatility(df_index)
# Select appropriate timeframe
active_tf = self._select_active_timeframe(volatility)
# Generate signal on selected timeframe
return self._generate_signal_for_timeframe(active_tf, df_index)
```
## Configuration Examples
### Single Timeframe Configuration
```json
{
"strategies": [
{
"name": "default",
"weight": 1.0,
"params": {
"timeframe": "15min",
"stop_loss_pct": 0.03
}
}
]
}
```
### Multi-Timeframe Configuration
```json
{
"strategies": [
{
"name": "multi_timeframe_strategy",
"weight": 1.0,
"params": {
"primary_timeframe": "15min",
"confirmation_timeframes": ["1h", "4h"],
"signal_timeframe": "5min"
}
}
]
}
```
### Mixed Strategy Configuration
```json
{
"strategies": [
{
"name": "default",
"weight": 0.6,
"params": {
"timeframe": "15min"
}
},
{
"name": "bbrs",
"weight": 0.4,
"params": {
"strategy_name": "MarketRegimeStrategy"
}
}
]
}
```
## Performance Considerations
### Memory Usage
- Only required timeframes are resampled and stored
- Original 1-minute data shared across all strategies
- Efficient pandas resampling with minimal memory overhead
### Processing Speed
- Resampling happens once during initialization
- No repeated resampling during backtesting
- Vectorized operations on pre-computed timeframes
### Data Alignment
- All timeframes aligned to original 1-minute timestamps
- Forward-fill resampling ensures data availability
- Intelligent handling of missing data points
## Best Practices
### 1. Minimize Timeframe Requirements
```python
# Good - minimal timeframes
def get_timeframes(self):
return ["15min"]
# Less optimal - unnecessary timeframes
def get_timeframes(self):
return ["1min", "5min", "15min", "1h", "4h", "1d"]
```
### 2. Use Appropriate Timeframes for Strategy Logic
```python
# Good - timeframe matches strategy logic
class TrendStrategy(StrategyBase):
def get_timeframes(self):
return ["1h"] # Trend analysis works well on hourly data
class ScalpingStrategy(StrategyBase):
def get_timeframes(self):
return ["1min", "5min"] # Scalping needs fine-grained data
```
### 3. Include 1min for Stop-Loss Precision
```python
def get_timeframes(self):
primary_tf = self.params.get("timeframe", "15min")
timeframes = [primary_tf]
# Always include 1min for precise stop-loss
if "1min" not in timeframes:
timeframes.append("1min")
return timeframes
```
### 4. Handle Timeframe Edge Cases
```python
def get_entry_signal(self, backtester, df_index):
# Check bounds for all timeframes
if df_index >= len(self.get_primary_timeframe_data()):
return StrategySignal("HOLD", confidence=0.0)
# Robust timeframe indexing
try:
signal = self._calculate_signal(df_index)
return signal
except IndexError:
return StrategySignal("HOLD", confidence=0.0)
```
## Troubleshooting
### Common Issues
1. **Index Out of Bounds**
```python
# Problem: Different timeframes have different lengths
# Solution: Always check bounds
if df_index < len(self.data_1h):
signal = self.data_1h[df_index]
```
2. **Timeframe Misalignment**
```python
# Problem: Assuming same index across timeframes
# Solution: Use timestamp-based alignment
current_time = primary_data.index[df_index]
h1_idx = hourly_data.index.get_indexer([current_time], method='ffill')[0]
```
3. **Memory Issues with Large Datasets**
```python
# Solution: Only include necessary timeframes
def get_timeframes(self):
# Return minimal set
return ["15min"] # Not ["1min", "5min", "15min", "1h"]
```
### Debugging Tips
```python
# Log timeframe information
def initialize(self, backtester):
self._resample_data(backtester.original_df)
for tf in self.get_timeframes():
data = self.get_data_for_timeframe(tf)
print(f"Timeframe {tf}: {len(data)} bars, "
f"from {data.index[0]} to {data.index[-1]}")
self.initialized = True
```
## Future Enhancements
### Planned Features
1. **Dynamic Timeframe Switching**: Strategies adapt timeframes based on market conditions
2. **Timeframe Confidence Weighting**: Different confidence levels per timeframe
3. **Cross-Timeframe Signal Validation**: Automatic signal confirmation across timeframes
4. **Optimized Memory Management**: Lazy loading and caching for large datasets
### Extension Points
The timeframe system is designed for easy extension:
- Custom resampling methods
- Alternative timeframe synchronization strategies
- Market-specific timeframe preferences
- Real-time timeframe adaptation