// // Dip / Retracement Catcher https://github.com/Haehnchen/crypto-trading-bot/tree/master/src/modules/strategy/strategies/dip_catcher https://github.com/Haehnchen/crypto-trading-bot/blob/master/src/modules/strategy/strategies/dip_catcher/dip_catcher.js translated for freqtrade: viksal1982 viktors.s@gmail.com https://github.com/viktors1982/trading/tree/main/freqtrade/strategies
Timeframe
5m
Direction
Long Only
Stoploss
-8.0%
Trailing Stop
No
ROI
0m: 3.0%, 30m: 2.0%, 60m: 1.0%
Interface Version
3
Startup Candles
N/A
Indicators
4
freqtrade/freqtrade-strategies
Strategy 003 author@: Gerald Lonlas github@: https://github.com/freqtrade/freqtrade-strategies
# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
# flake8: noqa: F401
# isort: skip_file
# --- Do not remove these libs ---
import numpy as np
import pandas as pd
from pandas import DataFrame
from datetime import datetime
from typing import Optional, Union
from freqtrade.persistence import Trade
from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter,
IntParameter, IStrategy, merge_informative_pair)
# --------------------------------
# Add your lib to import here
import talib.abstract as ta
import pandas_ta as pta
from technical import qtpylib
from datetime import timedelta
import math
class dip_catcher(IStrategy):
"""
//
// Dip / Retracement Catcher
https://github.com/Haehnchen/crypto-trading-bot/tree/master/src/modules/strategy/strategies/dip_catcher
https://github.com/Haehnchen/crypto-trading-bot/blob/master/src/modules/strategy/strategies/dip_catcher/dip_catcher.js
translated for freqtrade: viksal1982 viktors.s@gmail.com
https://github.com/viktors1982/trading/tree/main/freqtrade/strategies
"""
INTERFACE_VERSION = 3
timeframe = '5m'
# Can this strategy go short?
can_short: bool = True
minimal_roi = {
"60": 0.01,
"30": 0.02,
"0": 0.03
}
stoploss = -0.08
trailing_stop = False
trailing_stop_positive = 0.01
trailing_stop_positive_offset = 0.0
trailing_only_offset_is_reached = False
process_only_new_candles = True
# These values can be overridden in the config.
use_exit_signal = True
exit_profit_only = False
ignore_roi_if_entry_signal = False
# Number of candles the strategy requires before producing valid signals
startup_candle_count: int = 30
length_hma = IntParameter(4, 20, default=9, space="buy", optimize=True)
length_hma_high = IntParameter(4, 20, default=9, space="buy", optimize=True)
length_hma_low = IntParameter(4, 20, default=9, space="buy", optimize=True)
bollinger_window = IntParameter(2, 40, default=20, space="buy", optimize=True)
trend_cloud_multiplier = IntParameter(1, 10, default=4, space="buy", optimize=True)
# Optional order type mapping.
order_types = {
'entry': 'limit',
'exit': 'limit',
'stoploss': 'market',
'stoploss_on_exchange': False
}
# Optional order time in force.
order_time_in_force = {
'entry': 'GTC',
'exit': 'GTC'
}
@property
def plot_config(self):
return {
'main_plot': {
},
'subplots': {
}
}
def informative_pairs(self):
return []
def ichimoku_cloud(self, dataframe, conversion_periods=9, base_periods=26, lagging_span2_periods=52, displacement=26):
def donchian_channel(series, length):
return (series.rolling(length).min() + series.rolling(length).max()) / 2
dataframe['conversion_line'] = (donchian_channel(dataframe['high'], conversion_periods) + donchian_channel(dataframe['low'], conversion_periods)) / 2
dataframe['base_line'] = (donchian_channel(dataframe['high'], base_periods) + donchian_channel(dataframe['low'], base_periods)) / 2
dataframe['lead_line1'] = ((dataframe['conversion_line'] + dataframe['base_line']) / 2).shift(displacement)
dataframe['lead_line2'] = ((donchian_channel(dataframe['high'], lagging_span2_periods) + donchian_channel(dataframe['low'], lagging_span2_periods)) / 2).shift(displacement)
dataframe['lagging_span'] = dataframe['close'].shift(displacement)
return dataframe[['conversion_line', 'base_line', 'lead_line1', 'lead_line2', 'lagging_span']]
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['hma'] = ta.WMA(
2 * ta.WMA(dataframe['close'], int(math.floor(int(self.length_hma.value)/2))) - ta.WMA(dataframe['close'], int(self.length_hma.value)), int(round(np.sqrt(int(self.length_hma.value))))
)
dataframe['hma_high'] = ta.WMA(
2 * ta.WMA(dataframe['close'], int(math.floor(int(self.length_hma_high.value/2)))) - ta.WMA(dataframe['close'], int(self.length_hma_high.value)), int(round(np.sqrt(int(self.length_hma_high.value))))
)
dataframe['hma_low'] = ta.WMA(
2 * ta.WMA(dataframe['close'], int(math.floor(int(self.length_hma_low.value/2)))) - ta.WMA(dataframe['close'], int(self.length_hma_low.value)), int(round(np.sqrt(int(self.length_hma_low.value))))
)
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=int(self.bollinger_window.value), stds=2)
dataframe['bb_lowerband'] = bollinger['lower']
dataframe['bb_middleband'] = bollinger['mid']
dataframe['bb_upperband'] = bollinger['upper']
dataframe[['conversion_line', 'base_line', 'spanA', 'spanB', 'lagging_span']] = self.ichimoku_cloud(dataframe, conversion_periods= (9 * int(self.trend_cloud_multiplier.value)), base_periods=(26 * int(self.trend_cloud_multiplier.value)) , lagging_span2_periods=(52* int(self.trend_cloud_multiplier.value)), displacement=(10* int(self.trend_cloud_multiplier.value)))
dataframe.loc[
(
# Condition for a long entry
(dataframe['hma_low'] > dataframe['bb_lowerband']) &
(dataframe['hma'] > dataframe['spanB'])
),
'enter_long'] = 1
dataframe.loc[
(
# Condition for a short entry
(dataframe['hma_high'] < dataframe['bb_upperband']) &
(dataframe['hma'] < dataframe['spanB'])
),
'enter_short'] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe