- Removed unused configuration for daily data and consolidated minute configuration into a single config dictionary. - Updated plotting logic to dynamically handle different strategies, ensuring appropriate bands and signals are displayed based on the selected strategy. - Improved error handling and logging for missing data in plots. - Enhanced the Bollinger Bands and RSI classes to support adaptive parameters based on market regimes, improving flexibility in strategy execution. - Added new CryptoTradingStrategy with multi-timeframe analysis and volume confirmation for better trading signal accuracy. - Updated documentation to reflect changes in strategy implementations and configuration requirements.
107 lines
7.1 KiB
Markdown
107 lines
7.1 KiB
Markdown
# Analysis Module
|
||
|
||
This document provides an overview of the `Analysis` module and its components, which are typically used for technical analysis of financial market data.
|
||
|
||
## Modules
|
||
|
||
The `Analysis` module includes classes for calculating common technical indicators:
|
||
|
||
- **Relative Strength Index (RSI)**: Implemented in `cycles/Analysis/rsi.py`.
|
||
- **Bollinger Bands**: Implemented in `cycles/Analysis/boillinger_band.py`.
|
||
- Note: Trading strategies are detailed in `strategies.md`.
|
||
|
||
## Class: `RSI`
|
||
|
||
Found in `cycles/Analysis/rsi.py`.
|
||
|
||
Calculates the Relative Strength Index.
|
||
### Mathematical Model
|
||
The standard RSI calculation typically involves Wilder's smoothing for average gains and losses.
|
||
1. **Price Change (Delta)**: Difference between consecutive closing prices.
|
||
2. **Gain and Loss**: Separate positive (gain) and negative (loss, expressed as positive) price changes.
|
||
3. **Average Gain (AvgU)** and **Average Loss (AvgD)**: Smoothed averages of gains and losses over the RSI period. Wilder's smoothing is a specific type of exponential moving average (EMA):
|
||
- Initial AvgU/AvgD: Simple Moving Average (SMA) over the first `period` values.
|
||
- Subsequent AvgU: `(Previous AvgU * (period - 1) + Current Gain) / period`
|
||
- Subsequent AvgD: `(Previous AvgD * (period - 1) + Current Loss) / period`
|
||
4. **Relative Strength (RS)**:
|
||
$$
|
||
RS = \\frac{\\text{AvgU}}{\\text{AvgD}}
|
||
$$
|
||
5. **RSI**:
|
||
$$
|
||
RSI = 100 - \\frac{100}{1 + RS}
|
||
$$
|
||
Special conditions:
|
||
- If AvgD is 0: RSI is 100 if AvgU > 0, or 50 if AvgU is also 0 (neutral).
|
||
|
||
### `__init__(self, config: dict)`
|
||
|
||
- **Description**: Initializes the RSI calculator.
|
||
- **Parameters**:\n - `config` (dict): Configuration dictionary. Must contain an `'rsi_period'` key with a positive integer value (e.g., `{'rsi_period': 14}`).
|
||
|
||
### `calculate(self, data_df: pd.DataFrame, price_column: str = 'close') -> pd.DataFrame`
|
||
|
||
- **Description**: Calculates the RSI (using Wilder's smoothing by default) and adds it as an 'RSI' column to the input DataFrame. This method utilizes `calculate_custom_rsi` internally with `smoothing='EMA'`.
|
||
- **Parameters**:\n - `data_df` (pd.DataFrame): DataFrame with historical price data. Must contain the `price_column`.\n - `price_column` (str, optional): The name of the column containing price data. Defaults to 'close'.
|
||
- **Returns**: `pd.DataFrame` - A copy of the input DataFrame with an added 'RSI' column. If data length is insufficient for the period, the 'RSI' column will contain `np.nan`.
|
||
|
||
### `calculate_custom_rsi(price_series: pd.Series, window: int = 14, smoothing: str = 'SMA') -> pd.Series` (Static Method)
|
||
|
||
- **Description**: Calculates RSI with a specified window and smoothing method (SMA or EMA). This is the core calculation engine.
|
||
- **Parameters**:
|
||
- `price_series` (pd.Series): Series of prices.
|
||
- `window` (int, optional): The period for RSI calculation. Defaults to 14. Must be a positive integer.
|
||
- `smoothing` (str, optional): Smoothing method, can be 'SMA' (Simple Moving Average) or 'EMA' (Exponential Moving Average, specifically Wilder's smoothing when `alpha = 1/window`). Defaults to 'SMA'.
|
||
- **Returns**: `pd.Series` - Series containing the RSI values. Returns a series of NaNs if data length is insufficient.
|
||
|
||
## Class: `BollingerBands`
|
||
|
||
Found in `cycles/Analysis/boillinger_band.py`.
|
||
|
||
Calculates Bollinger Bands.
|
||
### Mathematical Model
|
||
1. **Middle Band**: Simple Moving Average (SMA) over `period`.
|
||
$$
|
||
\\text{Middle Band} = \\text{SMA}(\\text{price}, \\text{period})
|
||
$$
|
||
2. **Standard Deviation (σ)**: Standard deviation of price over `period`.
|
||
3. **Upper Band**: Middle Band + `num_std` × σ
|
||
$$
|
||
\\text{Upper Band} = \\text{Middle Band} + \\text{num_std} \\times \\sigma_{\\text{period}}
|
||
$$
|
||
4. **Lower Band**: Middle Band − `num_std` × σ
|
||
$$
|
||
\\text{Lower Band} = \\text{Middle Band} - \\text{num_std} \\times \\sigma_{\\text{period}}
|
||
$$
|
||
For the adaptive calculation in the `calculate` method (when `squeeze=False`):
|
||
- **BBWidth**: `(Reference Upper Band - Reference Lower Band) / SMA`, where reference bands are typically calculated using a 2.0 standard deviation multiplier.
|
||
- **MarketRegime**: Determined by comparing `BBWidth` to a threshold from the configuration. `1` for sideways, `0` for trending.
|
||
- The `num_std` used for the final Upper and Lower Bands then varies based on this `MarketRegime` and the `bb_std_dev_multiplier` values for "trending" and "sideways" markets from the configuration, applied row-wise.
|
||
|
||
### `__init__(self, config: dict)`
|
||
|
||
- **Description**: Initializes the BollingerBands calculator.
|
||
- **Parameters**:\n - `config` (dict): Configuration dictionary. It must contain:
|
||
- `'bb_period'` (int): Positive integer for the moving average and standard deviation period.
|
||
- `'trending'` (dict): Containing `'bb_std_dev_multiplier'` (float, positive) for trending markets.
|
||
- `'sideways'` (dict): Containing `'bb_std_dev_multiplier'` (float, positive) for sideways markets.
|
||
- `'bb_width'` (float): Positive float threshold for determining market regime.
|
||
|
||
### `calculate(self, data_df: pd.DataFrame, price_column: str = 'close', squeeze: bool = False) -> pd.DataFrame`
|
||
|
||
- **Description**: Calculates Bollinger Bands and adds relevant columns to the DataFrame.
|
||
- If `squeeze` is `False` (default): Calculates adaptive Bollinger Bands. It determines the market regime (trending/sideways) based on `BBWidth` and applies different standard deviation multipliers (from the `config`) on a row-by-row basis. Adds 'SMA', 'UpperBand', 'LowerBand', 'BBWidth', and 'MarketRegime' columns.
|
||
- If `squeeze` is `True`: Calculates simpler Bollinger Bands with a fixed window of 14 and a standard deviation multiplier of 1.5 by calling `calculate_custom_bands`. Adds 'SMA', 'UpperBand', 'LowerBand' columns; 'BBWidth' and 'MarketRegime' will be `NaN`.
|
||
- **Parameters**:\n - `data_df` (pd.DataFrame): DataFrame with price data. Must include the `price_column`.\n - `price_column` (str, optional): The name of the column containing the price data. Defaults to 'close'.\n - `squeeze` (bool, optional): If `True`, calculates bands with fixed parameters (window 14, std 1.5). Defaults to `False`.
|
||
- **Returns**: `pd.DataFrame` - A copy of the original DataFrame with added Bollinger Band related columns.
|
||
|
||
### `calculate_custom_bands(price_series: pd.Series, window: int = 20, num_std: float = 2.0, min_periods: int = None) -> tuple[pd.Series, pd.Series, pd.Series]` (Static Method)
|
||
|
||
- **Description**: Calculates Bollinger Bands with a specified window, standard deviation multiplier, and minimum periods.
|
||
- **Parameters**:
|
||
- `price_series` (pd.Series): Series of prices.
|
||
- `window` (int, optional): The period for the moving average and standard deviation. Defaults to 20.
|
||
- `num_std` (float, optional): The number of standard deviations for the upper and lower bands. Defaults to 2.0.
|
||
- `min_periods` (int, optional): Minimum number of observations in window required to have a value. Defaults to `window` if `None`.
|
||
- **Returns**: `tuple[pd.Series, pd.Series, pd.Series]` - A tuple containing the Upper band, SMA, and Lower band series.
|