Timeframe
N/A
Direction
Long Only
Stoploss
N/A
Trailing Stop
No
ROI
N/A
Interface Version
N/A
Startup Candles
N/A
Indicators
2
freqtrade/freqtrade-strategies
freqtrade/freqtrade-strategies
this is an example class, implementing a PSAR based trailing stop loss you are supposed to take the `custom_stoploss()` and `populate_indicators()` parts and adapt it to your own strategy
freqtrade/freqtrade-strategies
Strategy 003 author@: Gerald Lonlas github@: https://github.com/freqtrade/freqtrade-strategies
import pandas as pd
import numpy as np
import talib.abstract as ta
import logging
from datetime import datetime
from typing import Dict, List, Optional, Tuple, Union
from scipy import signal
from statistics import mean
from freqtrade.persistence.trade_model import Trade
from freqtrade.strategy.interface import IStrategy
# "minimal_roi": {
# "0": 0.05
# },
# "stoploss": -0.05,
#
# "trailing_stop": true,
# "trailing_stop_positive": 0.05,
# "trailing_stop_positive_offset": 0.2,
# "trailing_only_offset_is_reached": true,
class TaSearchLevelG15m(IStrategy):
can_short: bool = True
def populate_indicators(self, df: pd.DataFrame, metadata: dict) -> pd.DataFrame:
pd.set_option('display.max_rows', 100000)
pd.set_option('display.precision', 10)
pd.set_option('mode.chained_assignment', None)
df['rsi_7'] = ta.RSI(df['close'], timeperiod=7).round(2)
df['min_level'] = 0
df['max_level'] = 0
df['buy_short'] = 0
df['buy_long'] = 0
df['buy_short2'] = 0
df['buy_long2'] = 0
df['i_close'] = 0
df['i_open'] = 0
df['i_low'] = 0
df['i_high'] = 0
logging.getLogger('freqtrade').info(str(metadata))
df = self.do_heikin_ashi(df)
df = self.do_long(df)
df = self.do_short(df)
return df
def do_long(self, df: pd.DataFrame) -> pd.DataFrame:
n = 200
df['min_local'] = df.iloc[signal.argrelextrema(df.c.values, np.less_equal, order=n)[0]]['c']
min = df['c'].max()
times = df.query(f'min_local > 0')
prices = []
if len(times) > 0:
for i in range(500, len(df)):
if df['min_local'].loc[i] > 0:
close = df['c'].loc[i]
chunk = df[:i - 10]
chunk['min_local'] = chunk.iloc[signal.argrelextrema(chunk.c.values, np.less_equal, order=n)[0]]['c']
time_chunk = chunk.query(f'min_local > 0')
for x, row in time_chunk.iterrows():
close_chunk = time_chunk['c'].loc[x]
prices.append(close_chunk)
for p in prices:
diff = self.diff_percentage(p, close)
if 0 < diff < 0.3:
logging.getLogger('freqtrade').info(str([i, '+++', diff, p]))
df['min_level'].loc[i] = 1
for x in range(i - 2, i):
# if candle green
# if df['min_level'].loc[x] > 0 and df['o'].loc[i] < df['c'].loc[i]:
if df['min_level'].loc[x] > 0:
close = df['c'].loc[i]
# if same value presented in past
# and if value < average for long
df_tail = df[i - 200: i].query(f'c < {close}')
if len(df_tail) > 0:
logging.getLogger('freqtrade').info(
str([i, '++++', min, diff, '---', prices, 'long ++++++'])
)
df['buy_long'].loc[i] = 1
df['i_low'].loc[i] = df['low'].loc[x]
df['i_high'].loc[i] = df['high'].loc[x]
df['i_open'].loc[i] = df['o'].loc[x]
df['i_close'].loc[i] = df['c'].loc[x]
for x in range(i - 100, i):
if df['min_level'].loc[x] > 0:
diff = self.diff_percentage(df['c'].loc[x], df['c'].loc[i])
# print('long ------- ', diff)
# long
# past < now
# if df['c'].loc[x] < df['c'].loc[i] and 0 < diff < 1:
if 0 < diff < 1:
logging.getLogger('freqtrade').info(
str([i, '---- long2 ----'])
)
df['buy_long2'].loc[i] = 1
df['i_low'].loc[i] = df['low'].loc[x]
df['i_high'].loc[i] = df['high'].loc[x]
df['i_open'].loc[i] = df['o'].loc[x]
df['i_close'].loc[i] = df['c'].loc[x]
return df
def do_short(self, df: pd.DataFrame) -> pd.DataFrame:
n = 200
df['max_local'] = df.iloc[signal.argrelextrema(df.c.values, np.greater_equal, order=n)[0]]['c']
max = df['c'].min()
times = df.query(f'max_local > 0')
prices = []
if len(times) > 0:
for i in range(500, len(df)):
if df['max_local'].loc[i] > 0:
close = df['c'].loc[i]
chunk = df[:i - 10]
chunk['max_x'] = chunk.iloc[signal.argrelextrema(chunk.c.values, np.greater_equal, order=n)[0]]['c']
time_chunk = chunk.query(f'max_x > 0')
for x, row in time_chunk.iterrows():
close_chunk = time_chunk['c'].loc[x]
prices.append(close_chunk)
for p in prices:
diff = self.diff_percentage(p, close)
if 0 < diff < 0.3:
logging.getLogger('freqtrade').info(str([i, '---', diff, p]))
df['max_level'].loc[i] = 1
for x in range(i - 2, i):
# if candle red
# if df['max_level'].loc[x] > 0 and df['o'].loc[i] > df['c'].loc[i]:
if df['max_level'].loc[x] > 0:
close = df['c'].loc[i]
# if same value presented in past
# and if value > average for short
df_tail = df[i - 200: i].query(f'c > {close}')
if len(df_tail) > 0:
logging.getLogger('freqtrade').info(
str([i, '---', max, diff, '---', prices, 'short -----'])
)
df['buy_short'].loc[i] = 1
df['i_low'].loc[i] = df['low'].loc[x]
df['i_high'].loc[i] = df['high'].loc[x]
df['i_open'].loc[i] = df['o'].loc[x]
df['i_close'].loc[i] = df['c'].loc[x]
for x in range(i - 100, i):
if df['max_level'].loc[x] > 0:
diff = self.diff_percentage(df['c'].loc[x], df['c'].loc[i])
# past > now
# if df['c'].loc[x] > df['c'].loc[i] and 0 < diff < 1:
if 0 < diff < 1:
logging.getLogger('freqtrade').info(
str([i, '---- short2 ----'])
)
df['buy_short2'].loc[i] = 1
df['i_low'].loc[i] = df['low'].loc[x]
df['i_high'].loc[i] = df['high'].loc[x]
df['i_open'].loc[i] = df['o'].loc[x]
df['i_close'].loc[i] = df['c'].loc[x]
return df
def populate_entry_trend(self, df: pd.DataFrame, metadata: dict) -> pd.DataFrame:
df.loc[(df['buy_short'] > 0), 'enter_short'] = 1
df.loc[(df['buy_short2'] > 0), 'enter_short'] = 1
df.loc[(df['buy_long'] > 0), 'enter_long'] = 1
df.loc[(df['buy_long2'] > 0), 'enter_long'] = 1
return df
def populate_exit_trend(self, df: pd.DataFrame, metadata: dict) -> pd.DataFrame:
df.loc[
(df['rsi_7'] < 10),
'exit_short'
] = 1
df.loc[
(df['rsi_7'] > 90),
'exit_long'
] = 1
return df
def leverage(self, pair: str, current_time: datetime, current_rate: float,
proposed_leverage: float, max_leverage: float, entry_tag: Optional[str],
side: str, **kwargs) -> float:
return 10
def diff_percentage(self, v2, v1) -> float:
diff = ((v2 - v1) / ((v2 + v1) / 2)) * 100
diff = np.round(diff, 4)
return np.abs(diff)
def do_heikin_ashi(self, df: pd.DataFrame) -> pd.DataFrame:
"""
https://www.investopedia.com/trading/heikin-ashi-better-candlestick/
"""
df['h'] = df.apply(lambda x: max(x['high'], x['open'], x['close']), axis=1)
df['l'] = df.apply(lambda x: min(x['low'], x['open'], x['close']), axis=1)
for i in range(1, len(df)):
df.loc[i, 'c'] = 1 / 4 * (
df['open'].iloc[i] +
df['close'].iloc[i] +
df['high'].iloc[i] +
df['low'].iloc[i]
)
df.loc[i, 'o'] = 1 / 2 * (
df['open'].iloc[i - 1] +
df['close'].iloc[i - 1]
)
return df
def confirm_trade_entry(self,
pair: str,
order_type: str,
amount: float,
rate: float,
time_in_force: str,
current_time: datetime,
entry_tag: Optional[str],
side: str,
**kwargs) -> bool:
"""
https://www.freqtrade.io/en/stable/strategy-callbacks/#trade-entry-buy-order-confirmation
"""
df, last_updated = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
print('------------------- confirm_trade_entry -------------', pair, rate)
mean = (
df['i_open'].iat[-1] +
df['i_close'].iat[-1]
) / 2
# # open = df['i_open'].iat[-1]
# # close = df['i_close'].iat[-1]
# min_ = min(
# # df['i_high'].iat[-1],
# # df['i_low'].iat[-1],
# df['i_open'].iat[-1],
# df['i_close'].iat[-1]
# )
# max_ = max(
# # df['i_high'].iat[-1],
# # df['i_low'].iat[-1],
# df['i_open'].iat[-1],
# df['i_close'].iat[-1]
# )
if mean == 0:
return False
if side == 'long':
return rate < mean
if side == 'short':
return rate > mean
return False
# def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float,
# entry_tag: Optional[str], side: str, **kwargs) -> float:
#
# # https://www.freqtrade.io/en/stable/strategy-callbacks/#custom-order-entry-and-exit-price-example
#
# df, last_updated = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
# avg = (
# # df['i_high'].iat[-1] +
# # df['i_low'].iat[-1] +
# df['i_open'].iat[-1] +
# df['i_close'].iat[-1]
# ) / 2
#
# min_ = min(
# df['i_high'].iat[-1],
# df['i_low'].iat[-1],
# df['i_open'].iat[-1],
# df['i_close'].iat[-1]
# )
# max_ = max(
# df['i_high'].iat[-1],
# df['i_low'].iat[-1],
# df['i_open'].iat[-1],
# df['i_close'].iat[-1]
# )
#
# print(
# '------------------- confirm_trade_entry -------------',
# pair, proposed_rate, side, '---', min_, max_, avg
# )
#
# if side == 'long':
# return min(proposed_rate, avg)
#
# if side == 'short':
# return max(proposed_rate, avg)
#
# return avg