DISCLAIMER
The codes in this post is just for educational purpose, and not to be used on live trading
To have multiple logics is quite easy. You can just do multiple dataframe.loc[]
like this
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
entry_1
, ['enter_long', 'enter_tag']
] = (1, 'entry_1 ')
dataframe.loc[
entry_2
, ['enter_long', 'enter_tag']
] = (1, 'entry_2 ')
dataframe.loc[
entry_3
, ['enter_long', 'enter_tag']
] = (1, 'entry_3 ')
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
exit_1
, ['exit_long', 'exit_tag']
] = (1, 'exit_1 ')
dataframe.loc[
exit_2
, ['exit_long', 'exit_tag']
] = (1, 'exit_2 ')
dataframe.loc[
exit_3
, ['exit_long', 'exit_tag']
] = (1, 'exit_3 ')
return dataframe
The issue with the code above is if multiple logics are triggered, then your enter_tag
and exit_tag
only have the last logic’s tag. For example, let’s say all the entry and exit logics are triggered respectively on enter and exit, then your enter_tag
and exit_tag
will be entry_3
and exit_3
. While this won’t have any effect on current code, if you want to have exit logics that are tied to specific enter_tag (I’ll discuss this next), then you want to have your enter_tag
to be accurate, which means it should be entry_1 entry_2 entry_3
.
To have that accurate enter and exit tag, the code should look like this
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['enter_tag'] = ''
dataframe.loc[
entry_1
|
entry_2
|
entry_3
, 'enter_long'
] = 1
dataframe.loc[
entry_1
, 'enter_tag'
] += 'entry_1 '
dataframe.loc[
entry_2
, 'enter_tag'
] += 'entry_2 '
dataframe.loc[
entry_3
, 'enter_tag'
] += 'entry_3 '
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['exit_tag'] = ''
dataframe.loc[
exit_1
|
exit_2
|
exit_3
, 'exit_long'
] = 1
dataframe.loc[
exit_1
, 'exit_tag'
] += 'exit_1 '
dataframe.loc[
exit_2
, 'exit_tag'
] += 'exit_2 '
dataframe.loc[
exit_3
, 'exit_tag'
] += 'exit_3 '
return dataframe
One important thing to note, if possible, don’t use space for your enter and exit tags if you want to use them further. Now let’s try to implement it on our sample strategy. On top of the golden/death cross, let’s add 2 more entry and exit logics, when close below ema_9/20 for entry and when close above ema_9/20 for exit. Our strategy now looks like this
from freqtrade.strategy import IStrategy, informative
from pandas import DataFrame
import freqtrade.vendor.qtpylib.indicators as qtpylib
import talib.abstract as ta
from freqtrade.persistence import Trade
from datetime import datetime, timedelta
from typing import Optional, Union
def EWO(source, sma_length=5, sma2_length=35):
sma1 = ta.SMA(source, timeperiod=sma_length)
sma2 = ta.SMA(source, timeperiod=sma2_length)
smadif = (sma1 - sma2) / source * 100
return smadif
class strat_template (IStrategy):
def version(self) -> str:
return "template-v1"
INTERFACE_VERSION = 3
minimal_roi = {
"0": 0.05
}
stoploss = -0.05
timeframe = '15m'
process_only_new_candles = True
startup_candle_count = 999
use_custom_stoploss = True
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> float:
sl_new = 1
if (current_time - timedelta(minutes=15) >= trade.open_date_utc):
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
current_candle = dataframe.iloc[-1].squeeze()
current_profit = trade.calc_profit_ratio(current_candle['close'])
if (current_profit >= 0.03):
sl_new = 0.01
return sl_new
def custom_exit(self, pair: str, trade: Trade, current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> Optional[Union[str, bool]]:
if ((current_time - timedelta(minutes=15)) >= trade.open_date_utc):
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
current_candle = dataframe.iloc[-1].squeeze()
current_profit = trade.calc_profit_ratio(current_candle['close'])
if (current_profit >= 0):
if (current_candle['rsi'] >= 70):
return "rsi_overbought"
@informative('30m')
def populate_indicators_inf1(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['rsi'] = ta.RSI(dataframe['close'], 14)
return dataframe
@informative('1h')
def populate_indicators_inf2(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['rsi'] = ta.RSI(dataframe['close'], 14)
return dataframe
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['ema_9'] = ta.EMA(dataframe['close'], 9)
dataframe['ema_20'] = ta.EMA(dataframe['close'], 20)
dataframe['rsi'] = ta.RSI(dataframe['close'], 14)
dataframe['ema_9_rsi'] = ta.EMA(dataframe['rsi'], 9)
dataframe['ewo'] = EWO(dataframe['close'], 50, 200)
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['enter_tag'] = ''
enter_1 = (
qtpylib.crossed_above(dataframe['ema_9'], dataframe['ema_20'])
&
(dataframe['rsi_30m'] < 50)
&
(dataframe['rsi_1h'] < 30)
&
(dataframe['ema_9_rsi'] < 70)
&
(dataframe['ewo'] > 3)
&
(dataframe['volume'] > 0)
)
enter_2 = (
(dataframe['close'] < dataframe['ema_9'])
&
(dataframe['volume'] > 0)
)
enter_3 = (
(dataframe['close'] < dataframe['ema_20'])
&
(dataframe['volume'] > 0)
)
dataframe.loc[
enter_1 | enter_2 | enter_3
, 'enter_long'
] = 1
dataframe.loc[
enter_1
, 'enter_tag'
] += 'golden_cross '
dataframe.loc[
enter_2
, 'enter_tag'
] += 'close_below_9 '
dataframe.loc[
enter_3
, 'enter_tag'
] += 'close_below_20 '
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['exit_tag'] = ''
exit_1 = (
qtpylib.crossed_below(dataframe['ema_9'], dataframe['ema_20'])
&
(dataframe['volume'] > 0)
)
exit_2 = (
(dataframe['close'] > dataframe['ema_9'])
&
(dataframe['volume'] > 0)
)
exit_3 = (
(dataframe['close'] > dataframe['ema_20'])
&
(dataframe['volume'] > 0)
)
dataframe.loc[
exit_1 | exit_2 | exit_3
, 'exit_long'
] = 1
dataframe.loc[
exit_1
, 'exit_tag'
] += 'death_cross '
dataframe.loc[
exit_2
, 'exit_tag'
] += 'close_above_9 '
dataframe.loc[
exit_3
, 'exit_tag'
] += 'close_above_20 '
return dataframe
[…] Previous – Custom indicators part 1 Next – Multiple entry and exit logics […]
[…] Previous – Multiple entry and exit logics Next […]
[…] Multiple entry and exit logics […]