Timeframe
4h
Direction
Long Only
Stoploss
-25.0%
Trailing Stop
No
ROI
0m: 10.0%, 720m: 6.0%, 1920m: 3.0%, 3840m: 0.0%
Interface Version
N/A
Startup Candles
250
Indicators
3
freqtrade/freqtrade-strategies
This strategy uses custom_stoploss() to enforce a fixed risk/reward ratio by first calculating a dynamic initial stoploss via ATR - last negative peak
freqtrade/freqtrade-strategies
Strategy 003 author@: Gerald Lonlas github@: https://github.com/freqtrade/freqtrade-strategies
freqtrade/freqtrade-strategies
import logging
from numpy.lib import math
from freqtrade.strategy import IStrategy, IntParameter
from pandas import DataFrame
import talib.abstract as ta
import numpy as np
import pandas as pd
class Supertrend(IStrategy):
use_exit_signal = True
# Buy params, Sell params, ROI, Stoploss and Trailing Stop are values generated by 'freqtrade hyperopt --strategy Supertrend --hyperopt-loss ShortTradeDurHyperOptLoss --timerange=20210101- --timeframe=1h --spaces all'
# It's encourage you find the values that better suites your needs and risk management strategies
INTERFACE_VERSION: int = 3
# Buy hyperspace params:
buy_params = {
"buy_m1": 4,
"buy_m2": 7,
"buy_m3": 1,
"buy_p1": 8,
"buy_p2": 9,
"buy_p3": 8,
}
# Sell hyperspace params:
sell_params = {
"sell_m1": 1,
"sell_m2": 3,
"sell_m3": 6,
"sell_p1": 16,
"sell_p2": 18,
"sell_p3": 18,
}
# ROI table:
minimal_roi = {
"0": 0.10,
"720": 0.06,
"1920": 0.03,
"3840": 0
}
stoploss = -0.25
trailing_stop = False
trailing_stop_positive = 0.03
trailing_stop_positive_offset = 0.06
trailing_only_offset_is_reached = True
timeframe = '4h'
startup_candle_count = 250
buy_m1 = IntParameter(1, 7, default=4)
buy_m2 = IntParameter(1, 7, default=4)
buy_m3 = IntParameter(1, 7, default=4)
buy_p1 = IntParameter(7, 21, default=14)
buy_p2 = IntParameter(7, 21, default=14)
buy_p3 = IntParameter(7, 21, default=14)
sell_m1 = IntParameter(1, 7, default=4)
sell_m2 = IntParameter(1, 7, default=4)
sell_m3 = IntParameter(1, 7, default=4)
sell_p1 = IntParameter(7, 21, default=14)
sell_p2 = IntParameter(7, 21, default=14)
sell_p3 = IntParameter(7, 21, default=14)
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
new_cols = []
for multiplier in self.buy_m1.range:
for period in self.buy_p1.range:
st = self.supertrend(dataframe, multiplier, period)[['STX']].rename(
columns={'STX': f'supertrend_1_buy_{multiplier}_{period}'})
new_cols.append(st)
for multiplier in self.buy_m2.range:
for period in self.buy_p2.range:
st = self.supertrend(dataframe, multiplier, period)[['STX']].rename(
columns={'STX': f'supertrend_2_buy_{multiplier}_{period}'})
new_cols.append(st)
for multiplier in self.buy_m3.range:
for period in self.buy_p3.range:
st = self.supertrend(dataframe, multiplier, period)[['STX']].rename(
columns={'STX': f'supertrend_3_buy_{multiplier}_{period}'})
new_cols.append(st)
for multiplier in self.sell_m1.range:
for period in self.sell_p1.range:
st = self.supertrend(dataframe, multiplier, period)[['STX']].rename(
columns={'STX': f'supertrend_1_sell_{multiplier}_{period}'})
new_cols.append(st)
for multiplier in self.sell_m2.range:
for period in self.sell_p2.range:
st = self.supertrend(dataframe, multiplier, period)[['STX']].rename(
columns={'STX': f'supertrend_2_sell_{multiplier}_{period}'})
new_cols.append(st)
for multiplier in self.sell_m3.range:
for period in self.sell_p3.range:
st = self.supertrend(dataframe, multiplier, period)[['STX']].rename(
columns={'STX': f'supertrend_3_sell_{multiplier}_{period}'})
new_cols.append(st)
if new_cols:
dataframe = pd.concat([dataframe] + new_cols, axis=1)
dataframe['ema200'] = ta.EMA(dataframe, timeperiod=200)
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
(dataframe[f'supertrend_1_buy_{self.buy_m1.value}_{self.buy_p1.value}'] == 'up') &
(dataframe[f'supertrend_2_buy_{self.buy_m2.value}_{self.buy_p2.value}'] == 'up') &
(dataframe[f'supertrend_3_buy_{self.buy_m3.value}_{self.buy_p3.value}'] == 'up') & # The three indicators are 'up' for the current candle
(dataframe['close'] > dataframe['ema200']) &
(dataframe['volume'] > 0) # There is at least some trading volume
),
'enter_long'] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
(dataframe[f'supertrend_1_sell_{self.sell_m1.value}_{self.sell_p1.value}'] == 'down') &
(dataframe[f'supertrend_2_sell_{self.sell_m2.value}_{self.sell_p2.value}'] == 'down') &
(dataframe[f'supertrend_3_sell_{self.sell_m3.value}_{self.sell_p3.value}'] == 'down') & # The three indicators are 'down' for the current candle
(dataframe['volume'] > 0) # There is at least some trading volume
),
'exit_long'] = 1
return dataframe
"""
Supertrend Indicator; adapted for freqtrade
from: https://github.com/freqtrade/freqtrade-strategies/issues/30
"""
def supertrend(self, dataframe: pd.DataFrame, multiplier, period):
df = dataframe.copy()
high = df['high'].values
low = df['low'].values
close = df['close'].values
length = len(df)
# 1. TR and ATR
tr = ta.TRANGE(df['high'], df['low'], df['close'])
atr = pd.Series(tr).rolling(period).mean().to_numpy()
# 2. basic upper / lower bands
basic_ub = (high + low) / 2 + multiplier * atr
basic_lb = (high + low) / 2 - multiplier * atr
# 3. final upper / lower bands
final_ub = np.zeros(length)
final_lb = np.zeros(length)
for i in range(period, length):
final_ub[i] = basic_ub[i] if basic_ub[i] < final_ub[i-1] or close[i-1] > final_ub[i-1] else final_ub[i-1]
final_lb[i] = basic_lb[i] if basic_lb[i] > final_lb[i-1] or close[i-1] < final_lb[i-1] else final_lb[i-1]
# 4. ST calculation
st = np.zeros(length)
for i in range(period, length):
if st[i-1] == final_ub[i-1]:
st[i] = final_ub[i] if close[i] <= final_ub[i] else final_lb[i]
elif st[i-1] == final_lb[i-1]:
st[i] = final_lb[i] if close[i] >= final_lb[i] else final_ub[i]
# 5. STX direction
stx = np.where(st > 0, np.where(close < st, 'down', 'up'), None)
# 6. fillna
result = pd.DataFrame({'ST': st, 'STX': stx}, index=df.index)
result.fillna(0, inplace=True)
return result