feat: Add SunnyBands indicator implementation with ATR and signal generation

This commit is contained in:
Bobby Abellana (aider) 2025-02-06 21:42:01 -08:00
parent c3f8d7ce80
commit fc7a6e7343
No known key found for this signature in database
GPG Key ID: 647714CC45F3647B
2 changed files with 84 additions and 0 deletions

View File

@ -0,0 +1 @@
# Initialize indicators package

View File

@ -0,0 +1,83 @@
import numpy as np
import pandas as pd
class SunnyBands:
def __init__(self, length: int = 50, atr_multiplier: float = 1.5, smooth_factor: int = 2):
"""
Initialize SunnyBands indicator
Args:
length (int): DMA Length (default: 50)
atr_multiplier (float): ATR Multiplier (default: 1.5)
smooth_factor (int): Smoothing Factor (default: 2)
"""
self.length = length
self.atr_multiplier = atr_multiplier
self.smooth_factor = smooth_factor
def calculate_atr(self, high: pd.Series, low: pd.Series, close: pd.Series) -> pd.Series:
"""Calculate Average True Range"""
tr1 = high - low
tr2 = abs(high - close.shift(1))
tr3 = abs(low - close.shift(1))
tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)
return tr.rolling(window=self.length).mean()
def calculate(self, df: pd.DataFrame) -> pd.DataFrame:
"""
Calculate SunnyBands indicator
Args:
df (pd.DataFrame): DataFrame with 'high', 'low', 'close' columns
Returns:
pd.DataFrame: DataFrame with added columns for DMA and bands
"""
# Calculate DMA (Double EMA)
ema1 = df['close'].ewm(span=self.length, adjust=False).mean()
dma = ema1.ewm(span=self.smooth_factor, adjust=False).mean()
# Calculate ATR
atr = self.calculate_atr(df['high'], df['low'], df['close'])
# Calculate Bands
upper_band = dma + (atr * self.atr_multiplier)
lower_band = dma - (atr * self.atr_multiplier)
# Generate signals
bullish = (df['close'] > lower_band) & (df['close'].shift(1) <= lower_band)
bearish = (df['close'] < upper_band) & (df['close'].shift(1) >= upper_band)
# Add results to DataFrame
results = pd.DataFrame({
'dma': dma,
'upper_band': upper_band,
'lower_band': lower_band,
'bullish_signal': bullish,
'bearish_signal': bearish
})
return results
def get_signals(self, df: pd.DataFrame) -> dict:
"""
Get the current trading signals based on SunnyBands
Args:
df (pd.DataFrame): DataFrame with price data
Returns:
dict: Dictionary containing current signals and band values
"""
results = self.calculate(df)
# Get latest values
current = results.iloc[-1]
return {
'dma': current['dma'],
'upper_band': current['upper_band'],
'lower_band': current['lower_band'],
'is_bullish': current['bullish_signal'],
'is_bearish': current['bearish_signal']
}