Timeframe
15m
Direction
Long & Short
Stoploss
-99.0%
Trailing Stop
Yes
ROI
N/A
Interface Version
N/A
Startup Candles
N/A
Indicators
4
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
freqtrade/freqtrade-strategies
import arrow
import numpy as np
import pandas as pd
import talib.abstract as ta
from pandas import DataFrame
from freqtrade.strategy.interface import IStrategy
from freqtrade.exchange import timeframe_to_seconds
from datetime import timedelta
pd.set_option("display.precision", 10)
class 777(IStrategy):
stoploss = -0.99
can_short = True
trailing_stop = True
trailing_stop_positive = 0.5
trailing_stop_positive_offset = 0.6
trailing_only_offset_is_reached = True
disable_dataframe_checks = True
atr_period = 20
timeframe = '15m'
timeframe_seconds = timeframe_to_seconds(timeframe)
plot_config = {
'main_plot': {
'renko_close': {'color': 'blue'},
'renko_open': {'color': 'orange'},
'sar': {'color': 'green'},
}
}
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['sar'] = ta.SAR(dataframe, acceleration=0.02, maximum=0.2)
dataframe['tema'] = ta.TEMA(dataframe, timeperiod=50)
dataframe['ATR'] = ta.ATR(dataframe, timeperiod=self.atr_period)
renko_columns = [
'date', 'renko_open', 'renko_high', 'renko_low', 'renko_close',
'trend', 'prev_trend', 'prev2_trend', 'prev3_trend',
'prev_date', 'new_brick'
]
DATE_IDX = 0
CLOSE_IDX = 4
TREND_IDX = 5
PREV_TREND_IDX = 6
PREV2_TREND_IDX = 7
NEW_BRICK = True
COPIED_BRICK = False
brick_size = np.NaN
data = []
prev_brick = None
prev2_trend = False
prev3_trend = False
for row in dataframe.itertuples():
if np.isnan(row.ATR):
continue
else:
brick_size = row.ATR
close = row.close
date = row.date
if prev_brick is None:
trend = True
prev_brick = [
date,
close - brick_size,
close,
close - brick_size,
close,
trend,
False,
False,
False,
date,
NEW_BRICK,
]
prev2_trend = prev_brick[PREV_TREND_IDX]
prev3_trend = prev_brick[PREV2_TREND_IDX]
data.append(prev_brick)
continue
prev_date = prev_brick[DATE_IDX]
prev_close = prev_brick[CLOSE_IDX]
prev_trend = prev_brick[TREND_IDX]
new_brick = None
trend = prev_trend
bricks = int(np.nan_to_num((close - prev_close) / brick_size))
if trend and bricks >= 1:
new_brick = [
date,
prev_close,
prev_close + bricks * brick_size,
prev_close,
prev_close + bricks * brick_size,
trend,
prev_trend,
prev2_trend,
prev3_trend,
prev_date,
NEW_BRICK,
]
elif trend and bricks <= -2:
trend = not trend
new_brick = [
date,
prev_close - brick_size,
prev_close - brick_size,
prev_close - abs(bricks) * brick_size,
prev_close - abs(bricks) * brick_size,
trend,
prev_trend,
prev2_trend,
prev3_trend,
prev_date,
NEW_BRICK,
]
elif not trend and bricks <= -1:
new_brick = [
date,
prev_close,
prev_close,
prev_close - abs(bricks) * brick_size,
prev_close - abs(bricks) * brick_size,
trend,
prev_trend,
prev2_trend,
prev3_trend,
prev_date,
NEW_BRICK,
]
elif not trend and bricks >= 2:
trend = not trend
new_brick = [
date,
prev_close + brick_size,
prev_close + bricks * brick_size,
prev_close + brick_size,
prev_close + bricks * brick_size,
trend,
prev_trend,
prev2_trend,
prev3_trend,
prev_date,
NEW_BRICK,
]
else:
data.append([
date,
prev_brick[1],
prev_brick[2],
prev_brick[3],
prev_brick[4],
prev_brick[5],
prev_brick[6],
prev_brick[7],
prev_brick[8],
prev_brick[9],
COPIED_BRICK,
])
if new_brick is not None:
data.append(new_brick)
prev2_trend = prev_brick[PREV_TREND_IDX]
prev3_trend = prev_brick[PREV2_TREND_IDX]
prev_brick = new_brick
renko_chart = pd.DataFrame(data=data, columns=renko_columns)
merged_dataframe = dataframe.merge(renko_chart, how='left', on='date')
merged_dataframe[['renko_open', 'renko_high', 'renko_low', 'renko_close', 'trend', 'prev_trend', 'prev2_trend', 'prev3_trend']] = merged_dataframe[
['renko_open', 'renko_high', 'renko_low', 'renko_close', 'trend', 'prev_trend', 'prev2_trend', 'prev3_trend']
].ffill()
return merged_dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Вхід у довгу позицію на першій стрілочці PSAR або Renko
"""
dataframe['enter_long'] = 0
dataframe['psar_shifted'] = dataframe['sar'].shift(1)
dataframe.loc[
(
(dataframe['psar_shifted'] > dataframe['close']) & # PSAR був вище ціни
(dataframe['sar'] < dataframe['close']) & # PSAR тепер нижче ціни
(dataframe['trend'] == True) & # Поточний brick бичачий
(dataframe['prev_trend'] == False) # Попередній brick ведмежий
),
'enter_long'
] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Вихід з довгої позиції або вхід у коротку позицію на першій стрілочці PSAR або Renko
"""
dataframe['enter_short'] = 0
dataframe['exit_long'] = 0
dataframe['psar_shifted'] = dataframe['sar'].shift(1)
dataframe.loc[
(
(dataframe['psar_shifted'] < dataframe['close']) & # PSAR був нижче ціни
(dataframe['sar'] > dataframe['close']) & # PSAR тепер вище ціни
(dataframe['trend'] == False) & # Поточний brick ведмежий
(dataframe['prev_trend'] == True) # Попередній brick бичачий
),
'enter_short'
] = 1
return dataframe