Merge pull request #327 from kagari306/kagari306-patch-1
Refactor Supertrend method for efficiency
This commit is contained in:
@@ -18,6 +18,7 @@ from freqtrade.strategy import IStrategy, IntParameter
|
|||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
import talib.abstract as ta
|
import talib.abstract as ta
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
class Supertrend(IStrategy):
|
class Supertrend(IStrategy):
|
||||||
# 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'
|
# 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'
|
||||||
@@ -80,30 +81,47 @@ class Supertrend(IStrategy):
|
|||||||
sell_p3 = IntParameter(7, 21, default=14)
|
sell_p3 = IntParameter(7, 21, default=14)
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
new_cols = []
|
||||||
|
|
||||||
for multiplier in self.buy_m1.range:
|
for multiplier in self.buy_m1.range:
|
||||||
for period in self.buy_p1.range:
|
for period in self.buy_p1.range:
|
||||||
dataframe[f'supertrend_1_buy_{multiplier}_{period}'] = self.supertrend(dataframe, multiplier, period)['STX']
|
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 multiplier in self.buy_m2.range:
|
||||||
for period in self.buy_p2.range:
|
for period in self.buy_p2.range:
|
||||||
dataframe[f'supertrend_2_buy_{multiplier}_{period}'] = self.supertrend(dataframe, multiplier, period)['STX']
|
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 multiplier in self.buy_m3.range:
|
||||||
for period in self.buy_p3.range:
|
for period in self.buy_p3.range:
|
||||||
dataframe[f'supertrend_3_buy_{multiplier}_{period}'] = self.supertrend(dataframe, multiplier, period)['STX']
|
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 multiplier in self.sell_m1.range:
|
||||||
for period in self.sell_p1.range:
|
for period in self.sell_p1.range:
|
||||||
dataframe[f'supertrend_1_sell_{multiplier}_{period}'] = self.supertrend(dataframe, multiplier, period)['STX']
|
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 multiplier in self.sell_m2.range:
|
||||||
for period in self.sell_p2.range:
|
for period in self.sell_p2.range:
|
||||||
dataframe[f'supertrend_2_sell_{multiplier}_{period}'] = self.supertrend(dataframe, multiplier, period)['STX']
|
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 multiplier in self.sell_m3.range:
|
||||||
for period in self.sell_p3.range:
|
for period in self.sell_p3.range:
|
||||||
dataframe[f'supertrend_3_sell_{multiplier}_{period}'] = self.supertrend(dataframe, multiplier, period)['STX']
|
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)
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
@@ -136,42 +154,43 @@ class Supertrend(IStrategy):
|
|||||||
Supertrend Indicator; adapted for freqtrade
|
Supertrend Indicator; adapted for freqtrade
|
||||||
from: https://github.com/freqtrade/freqtrade-strategies/issues/30
|
from: https://github.com/freqtrade/freqtrade-strategies/issues/30
|
||||||
"""
|
"""
|
||||||
def supertrend(self, dataframe: DataFrame, multiplier, period):
|
def supertrend(self, dataframe: pd.DataFrame, multiplier, period):
|
||||||
df = dataframe.copy()
|
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
|
||||||
|
|
||||||
df['TR'] = ta.TRANGE(df)
|
|
||||||
df['ATR'] = ta.SMA(df['TR'], period)
|
|
||||||
|
|
||||||
st = 'ST_' + str(period) + '_' + str(multiplier)
|
|
||||||
stx = 'STX_' + str(period) + '_' + str(multiplier)
|
|
||||||
|
|
||||||
# Compute basic upper and lower bands
|
|
||||||
df['basic_ub'] = (df['high'] + df['low']) / 2 + multiplier * df['ATR']
|
|
||||||
df['basic_lb'] = (df['high'] + df['low']) / 2 - multiplier * df['ATR']
|
|
||||||
|
|
||||||
# Compute final upper and lower bands
|
|
||||||
df['final_ub'] = 0.00
|
|
||||||
df['final_lb'] = 0.00
|
|
||||||
for i in range(period, len(df)):
|
|
||||||
df['final_ub'].iat[i] = df['basic_ub'].iat[i] if df['basic_ub'].iat[i] < df['final_ub'].iat[i - 1] or df['close'].iat[i - 1] > df['final_ub'].iat[i - 1] else df['final_ub'].iat[i - 1]
|
|
||||||
df['final_lb'].iat[i] = df['basic_lb'].iat[i] if df['basic_lb'].iat[i] > df['final_lb'].iat[i - 1] or df['close'].iat[i - 1] < df['final_lb'].iat[i - 1] else df['final_lb'].iat[i - 1]
|
|
||||||
|
|
||||||
# Set the Supertrend value
|
|
||||||
df[st] = 0.00
|
|
||||||
for i in range(period, len(df)):
|
|
||||||
df[st].iat[i] = df['final_ub'].iat[i] if df[st].iat[i - 1] == df['final_ub'].iat[i - 1] and df['close'].iat[i] <= df['final_ub'].iat[i] else \
|
|
||||||
df['final_lb'].iat[i] if df[st].iat[i - 1] == df['final_ub'].iat[i - 1] and df['close'].iat[i] > df['final_ub'].iat[i] else \
|
|
||||||
df['final_lb'].iat[i] if df[st].iat[i - 1] == df['final_lb'].iat[i - 1] and df['close'].iat[i] >= df['final_lb'].iat[i] else \
|
|
||||||
df['final_ub'].iat[i] if df[st].iat[i - 1] == df['final_lb'].iat[i - 1] and df['close'].iat[i] < df['final_lb'].iat[i] else 0.00
|
|
||||||
# Mark the trend direction up/down
|
|
||||||
df[stx] = np.where((df[st] > 0.00), np.where((df['close'] < df[st]), 'down', 'up'), None)
|
|
||||||
|
|
||||||
# Remove basic and final bands from the columns
|
|
||||||
df.drop(['basic_ub', 'basic_lb', 'final_ub', 'final_lb'], inplace=True, axis=1)
|
|
||||||
|
|
||||||
df.fillna(0, inplace=True)
|
|
||||||
|
|
||||||
return DataFrame(index=df.index, data={
|
|
||||||
'ST' : df[st],
|
|
||||||
'STX' : df[stx]
|
|
||||||
})
|
|
||||||
|
|||||||
Reference in New Issue
Block a user