Timeframe
5m
Direction
Long Only
Stoploss
-10.0%
Trailing Stop
Yes
ROI
0m: 3.0%
Interface Version
3
Startup Candles
N/A
Indicators
1
freqtrade/freqtrade-strategies
author@: lenik
from freqtrade.strategy import IStrategy, merge_informative_pair, IntParameter, DecimalParameter
from pandas import DataFrame
import numpy as np
import talib.abstract as ta
class VolatilityGaussianBandsStrategy(IStrategy):
INTERFACE_VERSION = 3
can_short = False
gaussian_length = IntParameter(5, 60, default=20, space="buy", optimize=True)
band_distance = DecimalParameter(0.5, 3.0, decimals=2, default=1.0, space="buy", optimize=True)
minimal_roi = { "0": 0.03 }
stoploss = -0.10
trailing_stop = True
trailing_stop_positive = 0.01
trailing_stop_positive_offset = 0.02
trailing_only_offset_is_reached = True
timeframe = '5m'
@property
def leverage(self) -> float:
return 3.0
def gaussian_filter(self, src: np.ndarray, length: int, sigma: float = 10) -> np.ndarray:
x = np.arange(length)
center = (length - 1) / 2
weights = np.exp(-0.5 * ((x - center) / sigma) ** 2)
weights /= np.sum(weights)
return np.convolve(src, weights, mode='same')
def multi_trend(self, df: DataFrame, price_col: str = 'close', period: int = 20, mode: str = 'AVG', band_distance: float = 1.0):
src = df[price_col].values
g_values = []
for step in range(21):
length = period + step
if length > len(src):
break
filtered = self.gaussian_filter(src, length)
g_values.append(filtered)
g_values = np.vstack(g_values)
if mode == 'AVG':
value = np.mean(g_values, axis=0)
elif mode == 'MEADIAN':
value = np.median(g_values, axis=0)
elif mode == 'MODE':
value = np.median(g_values, axis=0)
else:
value = np.mean(g_values, axis=0)
volatility = ta.SMA(df['high'] - df['low'], timeperiod=100)
lower_band = value - volatility * band_distance
upper_band = value + volatility * band_distance
close = df[price_col]
trend = (close > upper_band).astype(int) - (close < lower_band).astype(int)
score = (close - value) / (volatility + 1e-8)
trend_line = np.where(trend > 0, lower_band, upper_band)
return value, lower_band, upper_band, trend, score, trend_line
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
avg, lower, upper, trend, score, trend_line = self.multi_trend(
dataframe,
price_col='close',
period=self.gaussian_length.value,
mode='AVG',
band_distance=self.band_distance.value
)
dataframe['vgb_avg'] = avg
dataframe['vgb_lower'] = lower
dataframe['vgb_upper'] = upper
dataframe['vgb_trend'] = trend
dataframe['vgb_score'] = score
dataframe['vgb_trend_line'] = trend_line
dataframe['vgb_crossup'] = (dataframe['close'] > trend_line) & (dataframe['close'].shift(1) <= trend_line)
dataframe['vgb_crossdn'] = (dataframe['close'] < trend_line) & (dataframe['close'].shift(1) >= trend_line)
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# LONG ENTRY
dataframe.loc[
(
(dataframe['vgb_crossup']) &
(dataframe['vgb_trend'] > 0) &
(dataframe['volume'] > 0)
),
['enter_long', 'enter_tag']
] = (1, 'vgb_long')
# SHORT ENTRY
dataframe.loc[
(
(dataframe['vgb_crossdn']) &
(dataframe['vgb_trend'] < 0) &
(dataframe['volume'] > 0)
),
['enter_short', 'enter_tag']
] = (1, 'vgb_short')
print("Long signals:", dataframe['enter_long'].sum())
print("Short signals:", dataframe['enter_short'].sum())
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# LONG EXIT
dataframe.loc[
(
(dataframe['vgb_crossdn']) &
(dataframe['vgb_trend'] < 0) &
(dataframe['volume'] > 0)
),
['exit_long', 'exit_tag']
] = (1, 'vgb_exit_long')
# SHORT EXIT
dataframe.loc[
(
(dataframe['vgb_crossup']) &
(dataframe['vgb_trend'] > 0) &
(dataframe['volume'] > 0)
),
['exit_short', 'exit_tag']
] = (1, 'vgb_exit_short')
# --- Debug print statements ---
print("Long exits:", dataframe['exit_long'].sum())
print("Short exits:", dataframe['exit_short'].sum())
return dataframe