# 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.