Cycles/cycles/Analysis/boillinger_band.py
Ajasra a924328c90 Implement Market Regime Strategy and refactor Bollinger Bands and RSI classes
- Introduced a new Strategy class to encapsulate trading strategies, including the Market Regime Strategy that adapts to different market conditions.
- Refactored BollingerBands and RSI classes to accept configuration parameters for improved flexibility and maintainability.
- Updated test_bbrsi.py to utilize the new strategy implementation and adjusted date ranges for testing.
- Enhanced documentation to include details about the new Strategy class and its components.
2025-05-22 16:44:59 +08:00

76 lines
3.4 KiB
Python

import pandas as pd
class BollingerBands:
"""
Calculates Bollinger Bands for given financial data.
"""
def __init__(self, config):
"""
Initializes the BollingerBands calculator.
Args:
period (int): The period for the moving average and standard deviation.
std_dev_multiplier (float): The number of standard deviations for the upper and lower bands.
bb_width (float): The width of the Bollinger Bands.
"""
if config['bb_period'] <= 0:
raise ValueError("Period must be a positive integer.")
if config['trending']['bb_std_dev_multiplier'] <= 0 or config['sideways']['bb_std_dev_multiplier'] <= 0:
raise ValueError("Standard deviation multiplier must be positive.")
if config['bb_width'] <= 0:
raise ValueError("BB width must be positive.")
self.config = config
def calculate(self, data_df: pd.DataFrame, price_column: str = 'close', squeeze = False) -> pd.DataFrame:
"""
Calculates Bollinger Bands and adds them to the DataFrame.
Args:
data_df (pd.DataFrame): DataFrame with price data. Must include the price_column.
price_column (str): The name of the column containing the price data (e.g., 'close').
Returns:
pd.DataFrame: The original DataFrame with added columns:
'SMA' (Simple Moving Average),
'UpperBand',
'LowerBand'.
"""
if price_column not in data_df.columns:
raise ValueError(f"Price column '{price_column}' not found in DataFrame.")
if not squeeze:
# Calculate SMA
data_df['SMA'] = data_df[price_column].rolling(window=self.config['bb_period']).mean()
# Calculate Standard Deviation
std_dev = data_df[price_column].rolling(window=self.config['bb_period']).std()
# Calculate Upper and Lower Bands
data_df['UpperBand'] = data_df['SMA'] + (2.0* std_dev)
data_df['LowerBand'] = data_df['SMA'] - (2.0* std_dev)
# Calculate the width of the Bollinger Bands
data_df['BBWidth'] = (data_df['UpperBand'] - data_df['LowerBand']) / data_df['SMA']
# Calculate the market regime
# 1 = sideways, 0 = trending
data_df['MarketRegime'] = (data_df['BBWidth'] < self.config['bb_width']).astype(int)
if data_df['MarketRegime'].sum() > 0:
data_df['UpperBand'] = data_df['SMA'] + (self.config['trending']['bb_std_dev_multiplier'] * std_dev)
data_df['LowerBand'] = data_df['SMA'] - (self.config['trending']['bb_std_dev_multiplier'] * std_dev)
else:
data_df['UpperBand'] = data_df['SMA'] + (self.config['sideways']['bb_std_dev_multiplier'] * std_dev)
data_df['LowerBand'] = data_df['SMA'] - (self.config['sideways']['bb_std_dev_multiplier'] * std_dev)
else:
data_df['SMA'] = data_df[price_column].rolling(window=14).mean()
# Calculate Standard Deviation
std_dev = data_df[price_column].rolling(window=14).std()
# Calculate Upper and Lower Bands
data_df['UpperBand'] = data_df['SMA'] + 1.5* std_dev
data_df['LowerBand'] = data_df['SMA'] - 1.5* std_dev
return data_df