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:
parent
9b15f9f44f
commit
9629d3090b
178
README.md
178
README.md
@ -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]
|
||||||
|
|||||||
@ -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": [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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).
|
||||||
|
|||||||
@ -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
488
docs/timeframe_system.md
Normal 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
|
||||||
Loading…
x
Reference in New Issue
Block a user