feat: Add SunnyBands indicator implementation with ATR and signal generation
This commit is contained in:
parent
c3f8d7ce80
commit
fc7a6e7343
@ -0,0 +1 @@
|
||||
# Initialize indicators package
|
||||
83
src/indicators/sunny_bands.py
Normal file
83
src/indicators/sunny_bands.py
Normal 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']
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user