Ménage vielles stratégies
This commit is contained in:
121
Strategy001.py
121
Strategy001.py
@@ -1,121 +0,0 @@
|
|||||||
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from freqtrade.strategy import IStrategy
|
|
||||||
from typing import Dict, List
|
|
||||||
from functools import reduce
|
|
||||||
from pandas import DataFrame
|
|
||||||
# --------------------------------
|
|
||||||
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
class Strategy001(IStrategy):
|
|
||||||
"""
|
|
||||||
Strategy 001
|
|
||||||
author@: Gerald Lonlas
|
|
||||||
github@: https://github.com/freqtrade/freqtrade-strategies
|
|
||||||
|
|
||||||
How to use it?
|
|
||||||
> python3 ./freqtrade/main.py -s Strategy001
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Minimal ROI designed for the strategy.
|
|
||||||
# This attribute will be overridden if the config file contains "minimal_roi"
|
|
||||||
minimal_roi = {
|
|
||||||
"60": 0.01,
|
|
||||||
"30": 0.03,
|
|
||||||
"20": 0.04,
|
|
||||||
"0": 0.05
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optimal stoploss designed for the strategy
|
|
||||||
# This attribute will be overridden if the config file contains "stoploss"
|
|
||||||
stoploss = -0.10
|
|
||||||
|
|
||||||
# Optimal timeframe for the strategy
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# trailing stoploss
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.01
|
|
||||||
trailing_stop_positive_offset = 0.02
|
|
||||||
|
|
||||||
# run "populate_indicators" only for new candle
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# Experimental settings (configuration will overide these if set)
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = True
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Optional order type mapping
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
"""
|
|
||||||
Define additional, informative pair/interval combinations to be cached from the exchange.
|
|
||||||
These pair/interval combinations are non-tradeable, unless they are part
|
|
||||||
of the whitelist as well.
|
|
||||||
For more information, please consult the documentation
|
|
||||||
:return: List of tuples in the format (pair, interval)
|
|
||||||
Sample: return [("ETH/USDT", "5m"),
|
|
||||||
("BTC/USDT", "15m"),
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Adds several different TA indicators to the given DataFrame
|
|
||||||
|
|
||||||
Performance Note: For the best performance be frugal on the number of indicators
|
|
||||||
you are using. Let uncomment only the indicator you are using in your strategies
|
|
||||||
or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
|
|
||||||
"""
|
|
||||||
|
|
||||||
dataframe['ema20'] = ta.EMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
heikinashi = qtpylib.heikinashi(dataframe)
|
|
||||||
dataframe['ha_open'] = heikinashi['open']
|
|
||||||
dataframe['ha_close'] = heikinashi['close']
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Based on TA indicators, populates the buy signal for the given dataframe
|
|
||||||
:param dataframe: DataFrame
|
|
||||||
:return: DataFrame with buy column
|
|
||||||
"""
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
qtpylib.crossed_above(dataframe['ema20'], dataframe['ema50']) &
|
|
||||||
(dataframe['ha_close'] > dataframe['ema20']) &
|
|
||||||
(dataframe['ha_open'] < dataframe['ha_close']) # green bar
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Based on TA indicators, populates the sell signal for the given dataframe
|
|
||||||
:param dataframe: DataFrame
|
|
||||||
:return: DataFrame with buy column
|
|
||||||
"""
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
qtpylib.crossed_above(dataframe['ema50'], dataframe['ema100']) &
|
|
||||||
(dataframe['ha_close'] < dataframe['ema20']) &
|
|
||||||
(dataframe['ha_open'] > dataframe['ha_close']) # red bar
|
|
||||||
),
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
from typing import Dict, List
|
|
||||||
from functools import reduce
|
|
||||||
from pandas import DataFrame
|
|
||||||
# --------------------------------
|
|
||||||
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
class Strategy001_custom_sell(IStrategy):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Strategy 001_custom_sell
|
|
||||||
author@: Gerald Lonlas, froggleston
|
|
||||||
github@: https://github.com/freqtrade/freqtrade-strategies
|
|
||||||
|
|
||||||
How to use it?
|
|
||||||
> python3 ./freqtrade/main.py -s Strategy001_custom_sell
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Minimal ROI designed for the strategy.
|
|
||||||
# This attribute will be overridden if the config file contains "minimal_roi"
|
|
||||||
minimal_roi = {
|
|
||||||
"60": 0.01,
|
|
||||||
"30": 0.03,
|
|
||||||
"20": 0.04,
|
|
||||||
"0": 0.05
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optimal stoploss designed for the strategy
|
|
||||||
# This attribute will be overridden if the config file contains "stoploss"
|
|
||||||
stoploss = -0.10
|
|
||||||
|
|
||||||
# Optimal timeframe for the strategy
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# trailing stoploss
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.01
|
|
||||||
trailing_stop_positive_offset = 0.02
|
|
||||||
|
|
||||||
# run "populate_indicators" only for new candle
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# Experimental settings (configuration will overide these if set)
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = True
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Optional order type mapping
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
"""
|
|
||||||
Define additional, informative pair/interval combinations to be cached from the exchange.
|
|
||||||
These pair/interval combinations are non-tradeable, unless they are part
|
|
||||||
of the whitelist as well.
|
|
||||||
For more information, please consult the documentation
|
|
||||||
:return: List of tuples in the format (pair, interval)
|
|
||||||
Sample: return [("ETH/USDT", "5m"),
|
|
||||||
("BTC/USDT", "15m"),
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Adds several different TA indicators to the given DataFrame
|
|
||||||
|
|
||||||
Performance Note: For the best performance be frugal on the number of indicators
|
|
||||||
you are using. Let uncomment only the indicator you are using in your strategies
|
|
||||||
or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
|
|
||||||
"""
|
|
||||||
|
|
||||||
dataframe['ema20'] = ta.EMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
heikinashi = qtpylib.heikinashi(dataframe)
|
|
||||||
dataframe['ha_open'] = heikinashi['open']
|
|
||||||
dataframe['ha_close'] = heikinashi['close']
|
|
||||||
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe, 14)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Based on TA indicators, populates the buy signal for the given dataframe
|
|
||||||
:param dataframe: DataFrame
|
|
||||||
:return: DataFrame with buy column
|
|
||||||
"""
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
qtpylib.crossed_above(dataframe['ema20'], dataframe['ema50']) &
|
|
||||||
(dataframe['ha_close'] > dataframe['ema20']) &
|
|
||||||
(dataframe['ha_open'] < dataframe['ha_close']) # green bar
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Based on TA indicators, populates the sell signal for the given dataframe
|
|
||||||
:param dataframe: DataFrame
|
|
||||||
:return: DataFrame with buy column
|
|
||||||
"""
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
qtpylib.crossed_above(dataframe['ema50'], dataframe['ema100']) &
|
|
||||||
(dataframe['ha_close'] < dataframe['ema20']) &
|
|
||||||
(dataframe['ha_open'] > dataframe['ha_close']) # red bar
|
|
||||||
),
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float, current_profit: float, **kwargs):
|
|
||||||
"""
|
|
||||||
Sell only when matching some criteria other than those used to generate the sell signal
|
|
||||||
:return: str sell_reason, if any, otherwise None
|
|
||||||
"""
|
|
||||||
# get dataframe
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
|
|
||||||
# get the current candle
|
|
||||||
current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
# if RSI greater than 70 and profit is positive, then sell
|
|
||||||
if (current_candle['rsi'] > 70) and (current_profit > 0):
|
|
||||||
return "rsi_profit_sell"
|
|
||||||
|
|
||||||
# else, hold
|
|
||||||
return None
|
|
||||||
135
Strategy002.py
135
Strategy002.py
@@ -1,135 +0,0 @@
|
|||||||
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from freqtrade.strategy import IStrategy
|
|
||||||
from typing import Dict, List
|
|
||||||
from functools import reduce
|
|
||||||
from pandas import DataFrame
|
|
||||||
# --------------------------------
|
|
||||||
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
import numpy # noqa
|
|
||||||
|
|
||||||
|
|
||||||
class Strategy002(IStrategy):
|
|
||||||
"""
|
|
||||||
Strategy 002
|
|
||||||
author@: Gerald Lonlas
|
|
||||||
github@: https://github.com/freqtrade/freqtrade-strategies
|
|
||||||
|
|
||||||
How to use it?
|
|
||||||
> python3 ./freqtrade/main.py -s Strategy002
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Minimal ROI designed for the strategy.
|
|
||||||
# This attribute will be overridden if the config file contains "minimal_roi"
|
|
||||||
minimal_roi = {
|
|
||||||
"60": 0.01,
|
|
||||||
"30": 0.03,
|
|
||||||
"20": 0.04,
|
|
||||||
"0": 0.05
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optimal stoploss designed for the strategy
|
|
||||||
# This attribute will be overridden if the config file contains "stoploss"
|
|
||||||
stoploss = -0.10
|
|
||||||
|
|
||||||
# Optimal timeframe for the strategy
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# trailing stoploss
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.01
|
|
||||||
trailing_stop_positive_offset = 0.02
|
|
||||||
|
|
||||||
# run "populate_indicators" only for new candle
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# Experimental settings (configuration will overide these if set)
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = True
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Optional order type mapping
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
"""
|
|
||||||
Define additional, informative pair/interval combinations to be cached from the exchange.
|
|
||||||
These pair/interval combinations are non-tradeable, unless they are part
|
|
||||||
of the whitelist as well.
|
|
||||||
For more information, please consult the documentation
|
|
||||||
:return: List of tuples in the format (pair, interval)
|
|
||||||
Sample: return [("ETH/USDT", "5m"),
|
|
||||||
("BTC/USDT", "15m"),
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Adds several different TA indicators to the given DataFrame
|
|
||||||
|
|
||||||
Performance Note: For the best performance be frugal on the number of indicators
|
|
||||||
you are using. Let uncomment only the indicator you are using in your strategies
|
|
||||||
or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Stoch
|
|
||||||
stoch = ta.STOCH(dataframe)
|
|
||||||
dataframe['slowk'] = stoch['slowk']
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# Inverse Fisher transform on RSI, values [-1.0, 1.0] (https://goo.gl/2JGGoy)
|
|
||||||
rsi = 0.1 * (dataframe['rsi'] - 50)
|
|
||||||
dataframe['fisher_rsi'] = (numpy.exp(2 * rsi) - 1) / (numpy.exp(2 * rsi) + 1)
|
|
||||||
|
|
||||||
# Bollinger bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
|
|
||||||
# SAR Parabol
|
|
||||||
dataframe['sar'] = ta.SAR(dataframe)
|
|
||||||
|
|
||||||
# Hammer: values [0, 100]
|
|
||||||
dataframe['CDLHAMMER'] = ta.CDLHAMMER(dataframe)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Based on TA indicators, populates the buy signal for the given dataframe
|
|
||||||
:param dataframe: DataFrame
|
|
||||||
:return: DataFrame with buy column
|
|
||||||
"""
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['rsi'] < 30) &
|
|
||||||
(dataframe['slowk'] < 20) &
|
|
||||||
(dataframe['bb_lowerband'] > dataframe['close']) &
|
|
||||||
(dataframe['CDLHAMMER'] == 100)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Based on TA indicators, populates the sell signal for the given dataframe
|
|
||||||
:param dataframe: DataFrame
|
|
||||||
:return: DataFrame with buy column
|
|
||||||
"""
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['sar'] > dataframe['close']) &
|
|
||||||
(dataframe['fisher_rsi'] > 0.3)
|
|
||||||
),
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
152
Strategy003.py
152
Strategy003.py
@@ -1,152 +0,0 @@
|
|||||||
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
from typing import Dict, List
|
|
||||||
from functools import reduce
|
|
||||||
from pandas import DataFrame
|
|
||||||
# --------------------------------
|
|
||||||
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
import numpy # noqa
|
|
||||||
|
|
||||||
|
|
||||||
class Strategy003(IStrategy):
|
|
||||||
"""
|
|
||||||
Strategy 003
|
|
||||||
author@: Gerald Lonlas
|
|
||||||
github@: https://github.com/freqtrade/freqtrade-strategies
|
|
||||||
|
|
||||||
How to use it?
|
|
||||||
> python3 ./freqtrade/main.py -s Strategy003
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Minimal ROI designed for the strategy.
|
|
||||||
# This attribute will be overridden if the config file contains "minimal_roi"
|
|
||||||
minimal_roi = {
|
|
||||||
"60": 0.01,
|
|
||||||
"30": 0.03,
|
|
||||||
"20": 0.04,
|
|
||||||
"0": 0.05
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optimal stoploss designed for the strategy
|
|
||||||
# This attribute will be overridden if the config file contains "stoploss"
|
|
||||||
stoploss = -0.10
|
|
||||||
|
|
||||||
# Optimal timeframe for the strategy
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# trailing stoploss
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.01
|
|
||||||
trailing_stop_positive_offset = 0.02
|
|
||||||
|
|
||||||
# run "populate_indicators" only for new candle
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# Experimental settings (configuration will overide these if set)
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = True
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Optional order type mapping
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
"""
|
|
||||||
Define additional, informative pair/interval combinations to be cached from the exchange.
|
|
||||||
These pair/interval combinations are non-tradeable, unless they are part
|
|
||||||
of the whitelist as well.
|
|
||||||
For more information, please consult the documentation
|
|
||||||
:return: List of tuples in the format (pair, interval)
|
|
||||||
Sample: return [("ETH/USDT", "5m"),
|
|
||||||
("BTC/USDT", "15m"),
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Adds several different TA indicators to the given DataFrame
|
|
||||||
|
|
||||||
Performance Note: For the best performance be frugal on the number of indicators
|
|
||||||
you are using. Let uncomment only the indicator you are using in your strategies
|
|
||||||
or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# MFI
|
|
||||||
dataframe['mfi'] = ta.MFI(dataframe)
|
|
||||||
|
|
||||||
# Stoch fast
|
|
||||||
stoch_fast = ta.STOCHF(dataframe)
|
|
||||||
dataframe['fastd'] = stoch_fast['fastd']
|
|
||||||
dataframe['fastk'] = stoch_fast['fastk']
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# Inverse Fisher transform on RSI, values [-1.0, 1.0] (https://goo.gl/2JGGoy)
|
|
||||||
rsi = 0.1 * (dataframe['rsi'] - 50)
|
|
||||||
dataframe['fisher_rsi'] = (numpy.exp(2 * rsi) - 1) / (numpy.exp(2 * rsi) + 1)
|
|
||||||
|
|
||||||
# Bollinger bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
|
|
||||||
# EMA - Exponential Moving Average
|
|
||||||
dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# SAR Parabol
|
|
||||||
dataframe['sar'] = ta.SAR(dataframe)
|
|
||||||
|
|
||||||
# SMA - Simple Moving Average
|
|
||||||
dataframe['sma'] = ta.SMA(dataframe, timeperiod=40)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Based on TA indicators, populates the buy signal for the given dataframe
|
|
||||||
:param dataframe: DataFrame
|
|
||||||
:return: DataFrame with buy column
|
|
||||||
"""
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['rsi'] < 28) &
|
|
||||||
(dataframe['rsi'] > 0) &
|
|
||||||
(dataframe['close'] < dataframe['sma']) &
|
|
||||||
(dataframe['fisher_rsi'] < -0.94) &
|
|
||||||
(dataframe['mfi'] < 16.0) &
|
|
||||||
(
|
|
||||||
(dataframe['ema50'] > dataframe['ema100']) |
|
|
||||||
(qtpylib.crossed_above(dataframe['ema5'], dataframe['ema10']))
|
|
||||||
) &
|
|
||||||
(dataframe['fastd'] > dataframe['fastk']) &
|
|
||||||
(dataframe['fastd'] > 0)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Based on TA indicators, populates the sell signal for the given dataframe
|
|
||||||
:param dataframe: DataFrame
|
|
||||||
:return: DataFrame with buy column
|
|
||||||
"""
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['sar'] > dataframe['close']) &
|
|
||||||
(dataframe['fisher_rsi'] > 0.3)
|
|
||||||
),
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
154
Strategy004.py
154
Strategy004.py
@@ -1,154 +0,0 @@
|
|||||||
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from freqtrade.strategy import IStrategy
|
|
||||||
from typing import Dict, List
|
|
||||||
from functools import reduce
|
|
||||||
from pandas import DataFrame
|
|
||||||
# --------------------------------
|
|
||||||
|
|
||||||
import talib.abstract as ta
|
|
||||||
|
|
||||||
|
|
||||||
class Strategy004(IStrategy):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Strategy 004
|
|
||||||
author@: Gerald Lonlas
|
|
||||||
github@: https://github.com/freqtrade/freqtrade-strategies
|
|
||||||
|
|
||||||
How to use it?
|
|
||||||
> python3 ./freqtrade/main.py -s Strategy004
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Minimal ROI designed for the strategy.
|
|
||||||
# This attribute will be overridden if the config file contains "minimal_roi"
|
|
||||||
minimal_roi = {
|
|
||||||
"60": 0.01,
|
|
||||||
"30": 0.03,
|
|
||||||
"20": 0.04,
|
|
||||||
"0": 0.05
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optimal stoploss designed for the strategy
|
|
||||||
# This attribute will be overridden if the config file contains "stoploss"
|
|
||||||
stoploss = -0.10
|
|
||||||
|
|
||||||
# Optimal timeframe for the strategy
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# trailing stoploss
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.01
|
|
||||||
trailing_stop_positive_offset = 0.02
|
|
||||||
|
|
||||||
# run "populate_indicators" only for new candle
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# Experimental settings (configuration will overide these if set)
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = True
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Optional order type mapping
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
"""
|
|
||||||
Define additional, informative pair/interval combinations to be cached from the exchange.
|
|
||||||
These pair/interval combinations are non-tradeable, unless they are part
|
|
||||||
of the whitelist as well.
|
|
||||||
For more information, please consult the documentation
|
|
||||||
:return: List of tuples in the format (pair, interval)
|
|
||||||
Sample: return [("ETH/USDT", "5m"),
|
|
||||||
("BTC/USDT", "15m"),
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Adds several different TA indicators to the given DataFrame
|
|
||||||
|
|
||||||
Performance Note: For the best performance be frugal on the number of indicators
|
|
||||||
you are using. Let uncomment only the indicator you are using in your strategies
|
|
||||||
or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# ADX
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['slowadx'] = ta.ADX(dataframe, 35)
|
|
||||||
|
|
||||||
# Commodity Channel Index: values Oversold:<-100, Overbought:>100
|
|
||||||
dataframe['cci'] = ta.CCI(dataframe)
|
|
||||||
|
|
||||||
# Stoch
|
|
||||||
stoch = ta.STOCHF(dataframe, 5)
|
|
||||||
dataframe['fastd'] = stoch['fastd']
|
|
||||||
dataframe['fastk'] = stoch['fastk']
|
|
||||||
dataframe['fastk-previous'] = dataframe.fastk.shift(1)
|
|
||||||
dataframe['fastd-previous'] = dataframe.fastd.shift(1)
|
|
||||||
|
|
||||||
# Slow Stoch
|
|
||||||
slowstoch = ta.STOCHF(dataframe, 50)
|
|
||||||
dataframe['slowfastd'] = slowstoch['fastd']
|
|
||||||
dataframe['slowfastk'] = slowstoch['fastk']
|
|
||||||
dataframe['slowfastk-previous'] = dataframe.slowfastk.shift(1)
|
|
||||||
dataframe['slowfastd-previous'] = dataframe.slowfastd.shift(1)
|
|
||||||
|
|
||||||
# EMA - Exponential Moving Average
|
|
||||||
dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
|
|
||||||
dataframe['mean-volume'] = dataframe['volume'].mean()
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Based on TA indicators, populates the buy signal for the given dataframe
|
|
||||||
:param dataframe: DataFrame
|
|
||||||
:return: DataFrame with buy column
|
|
||||||
"""
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(
|
|
||||||
(dataframe['adx'] > 50) |
|
|
||||||
(dataframe['slowadx'] > 26)
|
|
||||||
) &
|
|
||||||
(dataframe['cci'] < -100) &
|
|
||||||
(
|
|
||||||
(dataframe['fastk-previous'] < 20) &
|
|
||||||
(dataframe['fastd-previous'] < 20)
|
|
||||||
) &
|
|
||||||
(
|
|
||||||
(dataframe['slowfastk-previous'] < 30) &
|
|
||||||
(dataframe['slowfastd-previous'] < 30)
|
|
||||||
) &
|
|
||||||
(dataframe['fastk-previous'] < dataframe['fastd-previous']) &
|
|
||||||
(dataframe['fastk'] > dataframe['fastd']) &
|
|
||||||
(dataframe['mean-volume'] > 0.75) &
|
|
||||||
(dataframe['close'] > 0.00000100)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Based on TA indicators, populates the sell signal for the given dataframe
|
|
||||||
:param dataframe: DataFrame
|
|
||||||
:return: DataFrame with buy column
|
|
||||||
"""
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['slowadx'] < 25) &
|
|
||||||
((dataframe['fastk'] > 70) | (dataframe['fastd'] > 70)) &
|
|
||||||
(dataframe['fastk-previous'] < dataframe['fastd-previous']) &
|
|
||||||
(dataframe['close'] > dataframe['ema5'])
|
|
||||||
),
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "Strategy005",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.05,
|
|
||||||
"20": 0.04,
|
|
||||||
"40": 0.03,
|
|
||||||
"80": 0.02,
|
|
||||||
"1440": 0.01
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": false,
|
|
||||||
"trailing_stop_positive": 0.01,
|
|
||||||
"trailing_stop_positive_offset": 0.02,
|
|
||||||
"trailing_only_offset_is_reached": false
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_fastd": 7,
|
|
||||||
"buy_fishRsiNorma": 80,
|
|
||||||
"buy_rsi": 31,
|
|
||||||
"buy_volumeAVG": 119
|
|
||||||
},
|
|
||||||
"sell": {
|
|
||||||
"sell_fishRsiNorma": 30,
|
|
||||||
"sell_minusDI": 4,
|
|
||||||
"sell_rsi": 74,
|
|
||||||
"sell_trigger": "rsi-macd-minusdi"
|
|
||||||
},
|
|
||||||
"protection": {}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-07 18:45:24.449663+00:00"
|
|
||||||
}
|
|
||||||
185
Strategy005.py
185
Strategy005.py
@@ -1,185 +0,0 @@
|
|||||||
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from freqtrade.strategy import IStrategy
|
|
||||||
from freqtrade.strategy import CategoricalParameter, IntParameter
|
|
||||||
from functools import reduce
|
|
||||||
from pandas import DataFrame
|
|
||||||
# --------------------------------
|
|
||||||
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
import numpy # noqa
|
|
||||||
|
|
||||||
|
|
||||||
class Strategy005(IStrategy):
|
|
||||||
"""
|
|
||||||
Strategy 005
|
|
||||||
author@: Gerald Lonlas
|
|
||||||
github@: https://github.com/freqtrade/freqtrade-strategies
|
|
||||||
|
|
||||||
How to use it?
|
|
||||||
> python3 ./freqtrade/main.py -s Strategy005
|
|
||||||
"""
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# Minimal ROI designed for the strategy.
|
|
||||||
# This attribute will be overridden if the config file contains "minimal_roi"
|
|
||||||
minimal_roi = {
|
|
||||||
"1440": 0.01,
|
|
||||||
"80": 0.02,
|
|
||||||
"40": 0.03,
|
|
||||||
"20": 0.04,
|
|
||||||
"0": 0.05
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optimal stoploss designed for the strategy
|
|
||||||
# This attribute will be overridden if the config file contains "stoploss"
|
|
||||||
stoploss = -1
|
|
||||||
|
|
||||||
# Optimal timeframe for the strategy
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# trailing stoploss
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.01
|
|
||||||
trailing_stop_positive_offset = 0.02
|
|
||||||
|
|
||||||
# run "populate_indicators" only for new candle
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# Experimental settings (configuration will overide these if set)
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = True
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Optional order type mapping
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
buy_volumeAVG = IntParameter(low=50, high=300, default=70, space='buy', optimize=True)
|
|
||||||
buy_rsi = IntParameter(low=1, high=100, default=30, space='buy', optimize=True)
|
|
||||||
buy_fastd = IntParameter(low=1, high=100, default=30, space='buy', optimize=True)
|
|
||||||
buy_fishRsiNorma = IntParameter(low=1, high=100, default=30, space='buy', optimize=True)
|
|
||||||
|
|
||||||
sell_rsi = IntParameter(low=1, high=100, default=70, space='sell', optimize=True)
|
|
||||||
sell_minusDI = IntParameter(low=1, high=100, default=50, space='sell', optimize=True)
|
|
||||||
sell_fishRsiNorma = IntParameter(low=1, high=100, default=50, space='sell', optimize=True)
|
|
||||||
sell_trigger = CategoricalParameter(["rsi-macd-minusdi", "sar-fisherRsi"],
|
|
||||||
default=30, space='sell', optimize=True)
|
|
||||||
|
|
||||||
# Buy hyperspace params:
|
|
||||||
buy_params = {
|
|
||||||
"buy_fastd": 1,
|
|
||||||
"buy_fishRsiNorma": 5,
|
|
||||||
"buy_rsi": 26,
|
|
||||||
"buy_volumeAVG": 150,
|
|
||||||
}
|
|
||||||
|
|
||||||
# Sell hyperspace params:
|
|
||||||
sell_params = {
|
|
||||||
"sell_fishRsiNorma": 30,
|
|
||||||
"sell_minusDI": 4,
|
|
||||||
"sell_rsi": 74,
|
|
||||||
"sell_trigger": "rsi-macd-minusdi",
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
"""
|
|
||||||
Define additional, informative pair/interval combinations to be cached from the exchange.
|
|
||||||
These pair/interval combinations are non-tradeable, unless they are part
|
|
||||||
of the whitelist as well.
|
|
||||||
For more information, please consult the documentation
|
|
||||||
:return: List of tuples in the format (pair, interval)
|
|
||||||
Sample: return [("ETH/USDT", "5m"),
|
|
||||||
("BTC/USDT", "15m"),
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Adds several different TA indicators to the given DataFrame
|
|
||||||
|
|
||||||
Performance Note: For the best performance be frugal on the number of indicators
|
|
||||||
you are using. Let uncomment only the indicator you are using in your strategies
|
|
||||||
or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# MACD
|
|
||||||
macd = ta.MACD(dataframe)
|
|
||||||
dataframe['macd'] = macd['macd']
|
|
||||||
dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# Inverse Fisher transform on RSI, values [-1.0, 1.0] (https://goo.gl/2JGGoy)
|
|
||||||
rsi = 0.1 * (dataframe['rsi'] - 50)
|
|
||||||
dataframe['fisher_rsi'] = (numpy.exp(2 * rsi) - 1) / (numpy.exp(2 * rsi) + 1)
|
|
||||||
# Inverse Fisher transform on RSI normalized, value [0.0, 100.0] (https://goo.gl/2JGGoy)
|
|
||||||
dataframe['fisher_rsi_norma'] = 50 * (dataframe['fisher_rsi'] + 1)
|
|
||||||
|
|
||||||
# Stoch fast
|
|
||||||
stoch_fast = ta.STOCHF(dataframe)
|
|
||||||
dataframe['fastd'] = stoch_fast['fastd']
|
|
||||||
dataframe['fastk'] = stoch_fast['fastk']
|
|
||||||
|
|
||||||
# Overlap Studies
|
|
||||||
# ------------------------------------
|
|
||||||
|
|
||||||
# SAR Parabol
|
|
||||||
dataframe['sar'] = ta.SAR(dataframe)
|
|
||||||
|
|
||||||
# SMA - Simple Moving Average
|
|
||||||
dataframe['sma'] = ta.SMA(dataframe, timeperiod=40)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Based on TA indicators, populates the buy signal for the given dataframe
|
|
||||||
:param dataframe: DataFrame
|
|
||||||
:return: DataFrame with buy column
|
|
||||||
"""
|
|
||||||
dataframe.loc[
|
|
||||||
# Prod
|
|
||||||
(
|
|
||||||
(dataframe['close'] > 0.00000200) &
|
|
||||||
(dataframe['volume'] > dataframe['volume'].rolling(self.buy_volumeAVG.value).mean() * 4) &
|
|
||||||
(dataframe['close'] < dataframe['sma']) &
|
|
||||||
(dataframe['fastd'] > dataframe['fastk']) &
|
|
||||||
(dataframe['rsi'] > self.buy_rsi.value) &
|
|
||||||
(dataframe['fastd'] > self.buy_fastd.value) &
|
|
||||||
(dataframe['fisher_rsi_norma'] < self.buy_fishRsiNorma.value)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
"""
|
|
||||||
Based on TA indicators, populates the sell signal for the given dataframe
|
|
||||||
:param dataframe: DataFrame
|
|
||||||
:return: DataFrame with buy column
|
|
||||||
"""
|
|
||||||
|
|
||||||
conditions = []
|
|
||||||
if self.sell_trigger.value == 'rsi-macd-minusdi':
|
|
||||||
conditions.append(qtpylib.crossed_above(dataframe['rsi'], self.sell_rsi.value))
|
|
||||||
conditions.append(dataframe['macd'] < 0)
|
|
||||||
conditions.append(dataframe['minus_di'] > self.sell_minusDI.value)
|
|
||||||
if self.sell_trigger.value == 'sar-fisherRsi':
|
|
||||||
conditions.append(dataframe['sar'] > dataframe['close'])
|
|
||||||
conditions.append(dataframe['fisher_rsi'] > self.sell_fishRsiNorma.value)
|
|
||||||
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[reduce(lambda x, y: x & y, conditions), 'sell'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD",
|
|
||||||
"params": {
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.118
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.11,
|
|
||||||
"buy_decalage": 12,
|
|
||||||
"buy_sma_percent": 0.98
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.391,
|
|
||||||
"142": 0.134,
|
|
||||||
"347": 0.067,
|
|
||||||
"818": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-09 15:16:01.241716+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD",
|
|
||||||
"params": {
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.118
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.11,
|
|
||||||
"buy_decalage": 12,
|
|
||||||
"buy_sma_percent": 0.98
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.391,
|
|
||||||
"142": 0.134,
|
|
||||||
"347": 0.067,
|
|
||||||
"818": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-09 15:16:01.241716+00:00"
|
|
||||||
}
|
|
||||||
282
StrategyJD.py
282
StrategyJD.py
@@ -1,282 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
#buy_msma_10 = DecimalParameter(0.997, 1.020, decimals=3, default=0.998, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
buy_decalage = IntParameter(1, 24, default=1, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
'rsi': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
# current_profit: float, **kwargs):
|
|
||||||
# dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
# last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
#
|
|
||||||
# # Above 20% profit, sell when rsi < 80
|
|
||||||
# if current_profit > 0.2:
|
|
||||||
# if last_candle['rsi'] < 80:
|
|
||||||
# return 'rsi_below_80'
|
|
||||||
#
|
|
||||||
# # Between 2% and 10%, sell if EMA-long above EMA-short
|
|
||||||
# if 0.02 < current_profit < 0.1:
|
|
||||||
# if last_candle['ema100'] > last_candle['ema10']:
|
|
||||||
# return 'ema_long_below_80'
|
|
||||||
#
|
|
||||||
# # Sell any positions at a loss if they are held for more than one day.
|
|
||||||
# if current_profit < -0.20 and (current_time - trade.open_date_utc).days >= 3:
|
|
||||||
# return 'unclog'
|
|
||||||
|
|
||||||
# def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
# proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
# **kwargs) -> float:
|
|
||||||
#
|
|
||||||
# dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
# current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
#
|
|
||||||
# if dataframe['open'] < dataframe['sma100'] * 0.98:
|
|
||||||
# # if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# # return max_stake
|
|
||||||
# # else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
#
|
|
||||||
# # Use default stake amount.
|
|
||||||
# return proposed_stake
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
dataframe['min50'] = ta.MIN(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
dataframe['max50'] = ta.MAX(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['mema10_3'] = dataframe['ema10'] / dataframe['ema10'].shift(1)
|
|
||||||
# dataframe['mema10_5'] = dataframe['ema10'].rolling(5).mean()
|
|
||||||
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['msma10_3'] = dataframe['sma10'] / dataframe['sma10'].shift(1)
|
|
||||||
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# dataframe["rolling"] = (100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(5).mean()
|
|
||||||
# dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
# dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=5)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage.value - 2, self.buy_decalage.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['bb_width'].shift(decalage) >= self.buy_bollinger.value),
|
|
||||||
# (dataframe['close'].shift(decalage) < dataframe['bb_lowerband'].shift(decalage)),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['sma10'].shift(decalage)),
|
|
||||||
(dataframe['msma10_3'] > 0.998)
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(reduce(lambda x, y: x & y, conditions))
|
|
||||||
)
|
|
||||||
,
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_msma_' + str(decalage))
|
|
||||||
break
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (dataframe['close'] < dataframe['open']) &
|
|
||||||
# (dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
# (dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
# (((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# # (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
# ), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_1",
|
|
||||||
"params": {
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.11,
|
|
||||||
"buy_decalage": 17
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {
|
|
||||||
"n_percent": 5,
|
|
||||||
"percent_sell": -0.05
|
|
||||||
},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.41700000000000004,
|
|
||||||
"153": 0.14200000000000002,
|
|
||||||
"212": 0.044,
|
|
||||||
"658": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.069
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-09 18:26:53.845529+00:00"
|
|
||||||
}
|
|
||||||
287
StrategyJD_1.py
287
StrategyJD_1.py
@@ -1,287 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD_1(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
#buy_msma_10 = DecimalParameter(0.997, 1.020, decimals=3, default=0.998, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
# buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
buy_decalage = IntParameter(1, 24, default=1, space="buy")
|
|
||||||
|
|
||||||
n_percent = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
'rsi': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
if last_candle['percent' + str(self.n_percent.value)] < self.percent_sell.value:
|
|
||||||
return 'sell_lost_percent' + str(self.n_percent.value)
|
|
||||||
|
|
||||||
# Between 2% and 10%, sell if EMA-long above EMA-short
|
|
||||||
# if 0.02 < current_profit < 0.1:
|
|
||||||
# if last_candle['ema100'] > last_candle['ema10']:
|
|
||||||
# return 'ema_long_below_80'
|
|
||||||
#
|
|
||||||
# # Sell any positions at a loss if they are held for more than one day.
|
|
||||||
# if current_profit < -0.20 and (current_time - trade.open_date_utc).days >= 3:
|
|
||||||
# return 'unclog'
|
|
||||||
|
|
||||||
# def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
# proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
# **kwargs) -> float:
|
|
||||||
#
|
|
||||||
# dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
# current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
#
|
|
||||||
# if dataframe['open'] < dataframe['sma100'] * 0.98:
|
|
||||||
# # if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# # return max_stake
|
|
||||||
# # else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
#
|
|
||||||
# # Use default stake amount.
|
|
||||||
# return proposed_stake
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
dataframe['min50'] = ta.MIN(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
dataframe['max50'] = ta.MAX(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
for n in range(1, 13):
|
|
||||||
dataframe["percent" + str(n)] = dataframe['close'].pct_change(n)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['mema10_3'] = dataframe['ema10'] / dataframe['ema10'].shift(1)
|
|
||||||
# dataframe['mema10_5'] = dataframe['ema10'].rolling(5).mean()
|
|
||||||
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['msma10_3'] = dataframe['sma10'] / dataframe['sma10'].shift(1)
|
|
||||||
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# dataframe["rolling"] = (100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(5).mean()
|
|
||||||
# dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
# dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=5)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage.value - 2, self.buy_decalage.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['bb_width'].shift(decalage) >= self.buy_bollinger.value),
|
|
||||||
# (dataframe['close'].shift(decalage) < dataframe['bb_lowerband'].shift(decalage)),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['sma10'].shift(decalage)),
|
|
||||||
(dataframe['msma10_3'] > 0.998)
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(reduce(lambda x, y: x & y, conditions))
|
|
||||||
)
|
|
||||||
,
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_msma_' + str(decalage))
|
|
||||||
break
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (dataframe['close'] < dataframe['open']) &
|
|
||||||
# (dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
# (dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
# (((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# # (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
# ), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_2",
|
|
||||||
"params": {
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.11,
|
|
||||||
"buy_decalage": 10,
|
|
||||||
"buy_rsi_max": 83,
|
|
||||||
"buy_rsi_min": 9
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.225,
|
|
||||||
"191": 0.126,
|
|
||||||
"423": 0.078,
|
|
||||||
"673": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.33
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-09 00:51:43.483560+00:00"
|
|
||||||
}
|
|
||||||
340
StrategyJD_2.py
340
StrategyJD_2.py
@@ -1,340 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
from freqtrade.strategy.strategy_helper import merge_informative_pair
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD_2(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
# buy_bollinger2 = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
# buy_bollinger3 = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
|
|
||||||
#buy_msma_10 = DecimalParameter(0.997, 1.020, decimals=3, default=0.998, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
# buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
buy_decalage = IntParameter(1, 24, default=1, space="buy")
|
|
||||||
# buy_decalage2 = IntParameter(1, 24, default=1, space="buy")
|
|
||||||
# buy_decalage3 = IntParameter(1, 24, default=1, space="buy")
|
|
||||||
|
|
||||||
buy_rsi_min = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
'rsi': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
# current_profit: float, **kwargs):
|
|
||||||
# dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
# last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
#
|
|
||||||
# # Above 20% profit, sell when rsi < 80
|
|
||||||
# if current_profit > 0.2:
|
|
||||||
# if last_candle['rsi'] < 80:
|
|
||||||
# return 'rsi_below_80'
|
|
||||||
#
|
|
||||||
# # Between 2% and 10%, sell if EMA-long above EMA-short
|
|
||||||
# if 0.02 < current_profit < 0.1:
|
|
||||||
# if last_candle['ema100'] > last_candle['ema10']:
|
|
||||||
# return 'ema_long_below_80'
|
|
||||||
#
|
|
||||||
# # Sell any positions at a loss if they are held for more than one day.
|
|
||||||
# if current_profit < -0.20 and (current_time - trade.open_date_utc).days >= 3:
|
|
||||||
# return 'unclog'
|
|
||||||
|
|
||||||
# def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
# proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
# **kwargs) -> float:
|
|
||||||
#
|
|
||||||
# dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
# current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
#
|
|
||||||
# if dataframe['open'] < dataframe['sma100'] * 0.98:
|
|
||||||
# # if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# # return max_stake
|
|
||||||
# # else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
#
|
|
||||||
# # Use default stake amount.
|
|
||||||
# return proposed_stake
|
|
||||||
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
# get access to all pairs available in whitelist.
|
|
||||||
pairs = self.dp.current_whitelist()
|
|
||||||
# informative_pairs = [(pair, '1d') for pair in pairs]
|
|
||||||
# informative_pairs += [(pair, '4h') for pair in pairs]
|
|
||||||
informative_pairs = [(pair, '1h') for pair in pairs]
|
|
||||||
|
|
||||||
return informative_pairs
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
dataframe['min50'] = ta.MIN(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
dataframe['max50'] = ta.MAX(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['mema10_3'] = dataframe['ema10'] / dataframe['ema10'].shift(1)
|
|
||||||
# dataframe['mema10_5'] = dataframe['ema10'].rolling(5).mean()
|
|
||||||
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['msma10_3'] = dataframe['sma10'] / dataframe['sma10'].shift(1)
|
|
||||||
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1h
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
|
|
||||||
informative["rsi"] = ta.RSI(informative)
|
|
||||||
informative["rsi3"] = ta.RSI(informative, 3)
|
|
||||||
# informative["mrsi3"] = informative["rsi"].rolling(3).mean()
|
|
||||||
# informative["max3"] = ta.MAX(informative['close'], timeperiod=3)
|
|
||||||
# informative["min3"] = ta.MIN(informative['close'], timeperiod=3)
|
|
||||||
# informative['pct_change_1'] = informative['close'].pct_change(1)
|
|
||||||
# informative['pct_change_3'] = informative['close'].pct_change(3)
|
|
||||||
informative['pct_change_5'] = informative['close'].pct_change(5)
|
|
||||||
# informative['sma3'] = ta.SMA(informative, timeperiod=3)
|
|
||||||
# informative['sma5'] = ta.SMA(informative, timeperiod=5)
|
|
||||||
# informative['sma10'] = ta.SMA(informative, timeperiod=10)
|
|
||||||
# # informative['adx'] = ta.ADX(informative)
|
|
||||||
#
|
|
||||||
# bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(informative), window=20, stds=2)
|
|
||||||
# informative['bb_lowerband'] = bollinger['lower']
|
|
||||||
# informative['bb_middleband'] = bollinger['mid']
|
|
||||||
# informative['bb_upperband'] = bollinger['upper']
|
|
||||||
# informative["bb_percent"] = (
|
|
||||||
# (informative["close"] - informative["bb_lowerband"]) /
|
|
||||||
# (informative["bb_upperband"] - informative["bb_lowerband"])
|
|
||||||
# )
|
|
||||||
|
|
||||||
# informative["bb_width"] = (
|
|
||||||
# (informative["bb_upperband"] - informative["bb_lowerband"]) / informative["bb_middleband"]
|
|
||||||
# )
|
|
||||||
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage.value - 2, self.buy_decalage.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['bb_width'].shift(decalage) >= self.buy_bollinger.value),
|
|
||||||
# (dataframe['close'].shift(decalage) < dataframe['bb_lowerband'].shift(decalage)),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['sma10'].shift(decalage)),
|
|
||||||
(dataframe['msma10_3'] > 0.998),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(reduce(lambda x, y: x & y, conditions))
|
|
||||||
)
|
|
||||||
,
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_msma1_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
# for decalage2 in range(self.buy_decalage2.value - 2, self.buy_decalage2.value):
|
|
||||||
# conditions = [
|
|
||||||
# (dataframe['bb_width'].shift(decalage2) >= self.buy_bollinger2.value),
|
|
||||||
# # (dataframe['close'].shift(decalage) < dataframe['bb_lowerband'].shift(decalage)),
|
|
||||||
# (dataframe['close'].shift(decalage2) < dataframe['sma10'].shift(decalage2)),
|
|
||||||
# (dataframe['msma10_3'] > 0.998),
|
|
||||||
# (dataframe['rsi_1h'] < self.buy_rsi_min.value),
|
|
||||||
# ]
|
|
||||||
# # GUARDS AND TRENDS
|
|
||||||
# if conditions:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (reduce(lambda x, y: x & y, conditions))
|
|
||||||
# )
|
|
||||||
# ,
|
|
||||||
# ['buy', 'buy_tag']] = (1, 'buy_msma2_' + str(decalage2))
|
|
||||||
# break
|
|
||||||
#
|
|
||||||
# for decalage3 in range(self.buy_decalage3.value - 2, self.buy_decalage3.value):
|
|
||||||
# conditions = [
|
|
||||||
# (dataframe['bb_width'].shift(decalage3) >= self.buy_bollinger3.value),
|
|
||||||
# # (dataframe['close'].shift(decalage) < dataframe['bb_lowerband'].shift(decalage)),
|
|
||||||
# (dataframe['close'].shift(decalage3) < dataframe['sma10'].shift(decalage3)),
|
|
||||||
# (dataframe['msma10_3'] > 0.998),
|
|
||||||
# (dataframe['rsi_1h'] > self.buy_rsi_max.value),
|
|
||||||
# ]
|
|
||||||
# # GUARDS AND TRENDS
|
|
||||||
# if conditions:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (reduce(lambda x, y: x & y, conditions))
|
|
||||||
# )
|
|
||||||
# ,
|
|
||||||
# ['buy', 'buy_tag']] = (1, 'buy_msma3_' + str(decalage2))
|
|
||||||
# break
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (dataframe['close'] < dataframe['open']) &
|
|
||||||
# (dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
# (dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
# (((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# # (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
# ), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_3",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.225,
|
|
||||||
"191": 0.126,
|
|
||||||
"423": 0.078,
|
|
||||||
"673": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.33
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.11,
|
|
||||||
"buy_decalage": 10,
|
|
||||||
"buy_rsi_max": 83,
|
|
||||||
"buy_rsi_min": 9
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {
|
|
||||||
"n_percent": 2,
|
|
||||||
"percent_sell": -0.06
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-09 19:00:21.704495+00:00"
|
|
||||||
}
|
|
||||||
336
StrategyJD_3.py
336
StrategyJD_3.py
@@ -1,336 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
from freqtrade.strategy.strategy_helper import merge_informative_pair
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD_3(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
#buy_msma_10 = DecimalParameter(0.997, 1.020, decimals=3, default=0.998, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
# buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
buy_decalage = IntParameter(1, 24, default=1, space="buy")
|
|
||||||
|
|
||||||
buy_rsi_min = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
n_percent = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'min200': {'color': 'yellow'},
|
|
||||||
'min200_001': {'color': 'yellow'}
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
if last_candle['percent' + str(self.n_percent.value)] < self.percent_sell.value:
|
|
||||||
return 'sell_lost_percent' + str(self.n_percent.value)
|
|
||||||
|
|
||||||
# Between 2% and 10%, sell if EMA-long above EMA-short
|
|
||||||
# if 0.02 < current_profit < 0.1:
|
|
||||||
# if last_candle['ema100'] > last_candle['ema10']:
|
|
||||||
# return 'ema_long_below_80'
|
|
||||||
#
|
|
||||||
# # Sell any positions at a loss if they are held for more than one day.
|
|
||||||
# if current_profit < -0.20 and (current_time - trade.open_date_utc).days >= 3:
|
|
||||||
# return 'unclog'
|
|
||||||
|
|
||||||
# def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
# proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
# **kwargs) -> float:
|
|
||||||
#
|
|
||||||
# dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
# current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
#
|
|
||||||
# if dataframe['open'] < dataframe['sma100'] * 0.98:
|
|
||||||
# # if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# # return max_stake
|
|
||||||
# # else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
#
|
|
||||||
# # Use default stake amount.
|
|
||||||
# return proposed_stake
|
|
||||||
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
# get access to all pairs available in whitelist.
|
|
||||||
pairs = self.dp.current_whitelist()
|
|
||||||
# informative_pairs = [(pair, '1d') for pair in pairs]
|
|
||||||
# informative_pairs += [(pair, '4h') for pair in pairs]
|
|
||||||
informative_pairs = [(pair, '1h') for pair in pairs]
|
|
||||||
|
|
||||||
return informative_pairs
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
dataframe['min50'] = ta.MIN(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['min200_001'] = dataframe['min200'] * 1.01
|
|
||||||
|
|
||||||
dataframe['max50'] = ta.MAX(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
for n in range(1, 25):
|
|
||||||
dataframe["percent" + str(n)] = dataframe['close'].pct_change(n)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['mema10_3'] = dataframe['ema10'] / dataframe['ema10'].shift(1)
|
|
||||||
# dataframe['mema10_5'] = dataframe['ema10'].rolling(5).mean()
|
|
||||||
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['msma10_3'] = dataframe['sma10'] / dataframe['sma10'].shift(1)
|
|
||||||
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1h
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
|
|
||||||
informative["rsi"] = ta.RSI(informative)
|
|
||||||
informative["rsi3"] = ta.RSI(informative, 3)
|
|
||||||
# informative["mrsi3"] = informative["rsi"].rolling(3).mean()
|
|
||||||
# informative["max3"] = ta.MAX(informative['close'], timeperiod=3)
|
|
||||||
# informative["min3"] = ta.MIN(informative['close'], timeperiod=3)
|
|
||||||
# informative['pct_change_1'] = informative['close'].pct_change(1)
|
|
||||||
# informative['pct_change_3'] = informative['close'].pct_change(3)
|
|
||||||
informative['pct_change_5'] = informative['close'].pct_change(5)
|
|
||||||
# informative['sma3'] = ta.SMA(informative, timeperiod=3)
|
|
||||||
# informative['sma5'] = ta.SMA(informative, timeperiod=5)
|
|
||||||
# informative['sma10'] = ta.SMA(informative, timeperiod=10)
|
|
||||||
# # informative['adx'] = ta.ADX(informative)
|
|
||||||
#
|
|
||||||
# bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(informative), window=20, stds=2)
|
|
||||||
# informative['bb_lowerband'] = bollinger['lower']
|
|
||||||
# informative['bb_middleband'] = bollinger['mid']
|
|
||||||
# informative['bb_upperband'] = bollinger['upper']
|
|
||||||
# informative["bb_percent"] = (
|
|
||||||
# (informative["close"] - informative["bb_lowerband"]) /
|
|
||||||
# (informative["bb_upperband"] - informative["bb_lowerband"])
|
|
||||||
# )
|
|
||||||
|
|
||||||
# informative["bb_width"] = (
|
|
||||||
# (informative["bb_upperband"] - informative["bb_lowerband"]) / informative["bb_middleband"]
|
|
||||||
# )
|
|
||||||
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage.value - 2, self.buy_decalage.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['bb_width'].shift(decalage) >= self.buy_bollinger.value),
|
|
||||||
# (dataframe['close'].shift(decalage) < dataframe['bb_lowerband'].shift(decalage)),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['sma10'].shift(decalage)),
|
|
||||||
(dataframe['msma10_3'] > 0.998),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(reduce(lambda x, y: x & y, conditions))
|
|
||||||
)
|
|
||||||
,
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_msma1_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
# for decalage2 in range(self.buy_decalage2.value - 2, self.buy_decalage2.value):
|
|
||||||
# conditions = [
|
|
||||||
# (dataframe['bb_width'].shift(decalage2) >= self.buy_bollinger2.value),
|
|
||||||
# # (dataframe['close'].shift(decalage) < dataframe['bb_lowerband'].shift(decalage)),
|
|
||||||
# (dataframe['close'].shift(decalage2) < dataframe['sma10'].shift(decalage2)),
|
|
||||||
# (dataframe['msma10_3'] > 0.998),
|
|
||||||
# (dataframe['rsi_1h'] < self.buy_rsi_min.value),
|
|
||||||
# ]
|
|
||||||
# # GUARDS AND TRENDS
|
|
||||||
# if conditions:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (reduce(lambda x, y: x & y, conditions))
|
|
||||||
# )
|
|
||||||
# ,
|
|
||||||
# ['buy', 'buy_tag']] = (1, 'buy_msma2_' + str(decalage2))
|
|
||||||
# break
|
|
||||||
#
|
|
||||||
# for decalage3 in range(self.buy_decalage3.value - 2, self.buy_decalage3.value):
|
|
||||||
# conditions = [
|
|
||||||
# (dataframe['bb_width'].shift(decalage3) >= self.buy_bollinger3.value),
|
|
||||||
# # (dataframe['close'].shift(decalage) < dataframe['bb_lowerband'].shift(decalage)),
|
|
||||||
# (dataframe['close'].shift(decalage3) < dataframe['sma10'].shift(decalage3)),
|
|
||||||
# (dataframe['msma10_3'] > 0.998),
|
|
||||||
# (dataframe['rsi_1h'] > self.buy_rsi_max.value),
|
|
||||||
# ]
|
|
||||||
# # GUARDS AND TRENDS
|
|
||||||
# if conditions:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (reduce(lambda x, y: x & y, conditions))
|
|
||||||
# )
|
|
||||||
# ,
|
|
||||||
# ['buy', 'buy_tag']] = (1, 'buy_msma3_' + str(decalage2))
|
|
||||||
# break
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (dataframe['close'] < dataframe['open']) &
|
|
||||||
# (dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
# (dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
# (((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# # (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
# ), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_4",
|
|
||||||
"params": {
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.04,
|
|
||||||
"buy_decalage": 4
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {
|
|
||||||
"n_percent": 7,
|
|
||||||
"percent_sell": -0.08
|
|
||||||
},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.627,
|
|
||||||
"151": 0.182,
|
|
||||||
"397": 0.041,
|
|
||||||
"657": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.033
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-11 21:11:06.341495+00:00"
|
|
||||||
}
|
|
||||||
349
StrategyJD_4.py
349
StrategyJD_4.py
@@ -1,349 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
from freqtrade.strategy.strategy_helper import merge_informative_pair
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD_4(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
# buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
|
|
||||||
# bollinger_rsi = {}
|
|
||||||
# for n in range(0, 11):
|
|
||||||
# bollinger_rsi[n] = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
|
|
||||||
bollinger_rsi_01 = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="protection")
|
|
||||||
bollinger_rsi_02 = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="protection")
|
|
||||||
bollinger_rsi_03 = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="protection")
|
|
||||||
bollinger_rsi_04 = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="protection")
|
|
||||||
bollinger_rsi_05 = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="protection")
|
|
||||||
bollinger_rsi_06 = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="protection")
|
|
||||||
bollinger_rsi_07 = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="protection")
|
|
||||||
bollinger_rsi_08 = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="protection")
|
|
||||||
bollinger_rsi_09 = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="protection")
|
|
||||||
bollinger_rsi_10 = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="protection")
|
|
||||||
bollinger_rsi_11 = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="protection")
|
|
||||||
|
|
||||||
#buy_msma_10 = DecimalParameter(0.997, 1.020, decimals=3, default=0.998, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
# buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
buy_decalage = IntParameter(1, 24, default=1, space="buy")
|
|
||||||
|
|
||||||
buy_rsi_min = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
n_percent = IntParameter(1, 12, default=1, space="sell")
|
|
||||||
percent_sell = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="sell")
|
|
||||||
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
'rsi': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
if last_candle['percent' + str(self.n_percent.value)] < self.percent_sell.value:
|
|
||||||
return 'sell_lost_percent' + str(self.n_percent.value)
|
|
||||||
|
|
||||||
# Between 2% and 10%, sell if EMA-long above EMA-short
|
|
||||||
# if 0.02 < current_profit < 0.1:
|
|
||||||
# if last_candle['ema100'] > last_candle['ema10']:
|
|
||||||
# return 'ema_long_below_80'
|
|
||||||
#
|
|
||||||
# # Sell any positions at a loss if they are held for more than one day.
|
|
||||||
# if current_profit < -0.20 and (current_time - trade.open_date_utc).days >= 3:
|
|
||||||
# return 'unclog'
|
|
||||||
|
|
||||||
# def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
# proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
# **kwargs) -> float:
|
|
||||||
#
|
|
||||||
# dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
# current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
#
|
|
||||||
# if dataframe['open'] < dataframe['sma100'] * 0.98:
|
|
||||||
# # if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# # return max_stake
|
|
||||||
# # else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
#
|
|
||||||
# # Use default stake amount.
|
|
||||||
# return proposed_stake
|
|
||||||
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
# get access to all pairs available in whitelist.
|
|
||||||
pairs = self.dp.current_whitelist()
|
|
||||||
# informative_pairs = [(pair, '1d') for pair in pairs]
|
|
||||||
# informative_pairs += [(pair, '4h') for pair in pairs]
|
|
||||||
informative_pairs = [(pair, '1h') for pair in pairs]
|
|
||||||
|
|
||||||
return informative_pairs
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
dataframe['min50'] = ta.MIN(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
dataframe['max50'] = ta.MAX(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
for n in range(1, 25):
|
|
||||||
dataframe["percent" + str(n)] = dataframe['close'].pct_change(n)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['mema10_3'] = dataframe['ema10'] / dataframe['ema10'].shift(1)
|
|
||||||
# dataframe['mema10_5'] = dataframe['ema10'].rolling(5).mean()
|
|
||||||
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['msma10_3'] = dataframe['sma10'] / dataframe['sma10'].shift(1)
|
|
||||||
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1h
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
|
|
||||||
informative["rsi"] = ta.RSI(informative)
|
|
||||||
informative["rsi3"] = ta.RSI(informative, 3)
|
|
||||||
informative['r_rsi'] = (informative['rsi3'].div(10).round())
|
|
||||||
|
|
||||||
# informative["mrsi3"] = informative["rsi"].rolling(3).mean()
|
|
||||||
# informative["max3"] = ta.MAX(informative['close'], timeperiod=3)
|
|
||||||
# informative["min3"] = ta.MIN(informative['close'], timeperiod=3)
|
|
||||||
# informative['pct_change_1'] = informative['close'].pct_change(1)
|
|
||||||
# informative['pct_change_3'] = informative['close'].pct_change(3)
|
|
||||||
informative['pct_change_5'] = informative['close'].pct_change(5)
|
|
||||||
# informative['sma3'] = ta.SMA(informative, timeperiod=3)
|
|
||||||
# informative['sma5'] = ta.SMA(informative, timeperiod=5)
|
|
||||||
# informative['sma10'] = ta.SMA(informative, timeperiod=10)
|
|
||||||
# # informative['adx'] = ta.ADX(informative)
|
|
||||||
#
|
|
||||||
# bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(informative), window=20, stds=2)
|
|
||||||
# informative['bb_lowerband'] = bollinger['lower']
|
|
||||||
# informative['bb_middleband'] = bollinger['mid']
|
|
||||||
# informative['bb_upperband'] = bollinger['upper']
|
|
||||||
# informative["bb_percent"] = (
|
|
||||||
# (informative["close"] - informative["bb_lowerband"]) /
|
|
||||||
# (informative["bb_upperband"] - informative["bb_lowerband"])
|
|
||||||
# )
|
|
||||||
|
|
||||||
# informative["bb_width"] = (
|
|
||||||
# (informative["bb_upperband"] - informative["bb_lowerband"]) / informative["bb_middleband"]
|
|
||||||
# )
|
|
||||||
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
for r_rsi_1h in range(0, 11):
|
|
||||||
value = 0
|
|
||||||
if r_rsi_1h == 0:
|
|
||||||
value = self.bollinger_rsi_01.value
|
|
||||||
if r_rsi_1h == 1:
|
|
||||||
value = self.bollinger_rsi_02.value
|
|
||||||
if r_rsi_1h == 2:
|
|
||||||
value = self.bollinger_rsi_03.value
|
|
||||||
if r_rsi_1h == 3:
|
|
||||||
value = self.bollinger_rsi_04.value
|
|
||||||
if r_rsi_1h == 4:
|
|
||||||
value = self.bollinger_rsi_05.value
|
|
||||||
if r_rsi_1h == 5:
|
|
||||||
value = self.bollinger_rsi_06.value
|
|
||||||
if r_rsi_1h == 6:
|
|
||||||
value = self.bollinger_rsi_07.value
|
|
||||||
if r_rsi_1h == 7:
|
|
||||||
value = self.bollinger_rsi_08.value
|
|
||||||
if r_rsi_1h == 8:
|
|
||||||
value = self.bollinger_rsi_09.value
|
|
||||||
if r_rsi_1h == 9:
|
|
||||||
value = self.bollinger_rsi_10.value
|
|
||||||
if r_rsi_1h == 10:
|
|
||||||
value = self.bollinger_rsi_11.value
|
|
||||||
# if r_rsi_1h == 11:
|
|
||||||
# value = self.bollinger_rsi_02.value
|
|
||||||
for decalage in range(self.buy_decalage.value - 2, self.buy_decalage.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['r_rsi_1h'] == r_rsi_1h),
|
|
||||||
(dataframe['bb_width'].shift(decalage) >= value),
|
|
||||||
# (dataframe['close'].shift(decalage) < dataframe['bb_lowerband'].shift(decalage)),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['sma10'].shift(decalage)),
|
|
||||||
(dataframe['msma10_3'] > 0.998),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value)
|
|
||||||
# (dataframe['percent1'] > 0)
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(reduce(lambda x, y: x & y, conditions))
|
|
||||||
),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_msma1_' + str(decalage)+ '_' + str(value))
|
|
||||||
break
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (dataframe['close'] < dataframe['open']) &
|
|
||||||
# (dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
# (dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
# (((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# # (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
# ), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_5",
|
|
||||||
"params": {
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_decalage": 11,
|
|
||||||
"buy_min_max_n": 0.17,
|
|
||||||
"buy_rsi_max": 74,
|
|
||||||
"buy_rsi_min": 6
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {
|
|
||||||
"n_percent": 6,
|
|
||||||
"percent_sell": -0.06
|
|
||||||
},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.209,
|
|
||||||
"200": 0.158,
|
|
||||||
"453": 0.103,
|
|
||||||
"581": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.243
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-12 11:07:47.704622+00:00"
|
|
||||||
}
|
|
||||||
303
StrategyJD_5.py
303
StrategyJD_5.py
@@ -1,303 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
from freqtrade.strategy.strategy_helper import merge_informative_pair
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD_5(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
# buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
#buy_msma_10 = DecimalParameter(0.997, 1.020, decimals=3, default=0.998, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
# buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
buy_decalage = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
buy_min_max_n = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_rsi_min = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
n_percent = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'min200': {'color': 'yellow'},
|
|
||||||
'min200_001': {'color': 'yellow'},
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
if last_candle['percent' + str(self.n_percent.value)] < self.percent_sell.value:
|
|
||||||
return 'sell_lost_percent' + str(self.n_percent.value)
|
|
||||||
|
|
||||||
# Between 2% and 10%, sell if EMA-long above EMA-short
|
|
||||||
# if 0.02 < current_profit < 0.1:
|
|
||||||
# if last_candle['ema100'] > last_candle['ema10']:
|
|
||||||
# return 'ema_long_below_80'
|
|
||||||
#
|
|
||||||
# # Sell any positions at a loss if they are held for more than one day.
|
|
||||||
# if current_profit < -0.20 and (current_time - trade.open_date_utc).days >= 3:
|
|
||||||
# return 'unclog'
|
|
||||||
|
|
||||||
# def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
# proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
# **kwargs) -> float:
|
|
||||||
#
|
|
||||||
# dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
# current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
#
|
|
||||||
# if dataframe['open'] < dataframe['sma100'] * 0.98:
|
|
||||||
# # if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# # return max_stake
|
|
||||||
# # else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
#
|
|
||||||
# # Use default stake amount.
|
|
||||||
# return proposed_stake
|
|
||||||
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
# get access to all pairs available in whitelist.
|
|
||||||
pairs = self.dp.current_whitelist()
|
|
||||||
# informative_pairs = [(pair, '1d') for pair in pairs]
|
|
||||||
# informative_pairs += [(pair, '4h') for pair in pairs]
|
|
||||||
informative_pairs = [(pair, '1h') for pair in pairs]
|
|
||||||
|
|
||||||
return informative_pairs
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
dataframe['min50'] = ta.MIN(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['min200_001'] = dataframe['min200'] * 1.002
|
|
||||||
dataframe['max50'] = ta.MAX(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['min_max200'] = (dataframe['max200'] - dataframe['min200']) / dataframe['min200']
|
|
||||||
dataframe['min_max50'] = (dataframe['max50'] - dataframe['min50']) / dataframe['min50']
|
|
||||||
|
|
||||||
for n in range(1, 25):
|
|
||||||
dataframe["percent" + str(n)] = dataframe['close'].pct_change(n)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['mema10_3'] = dataframe['ema10'] / dataframe['ema10'].shift(1)
|
|
||||||
# dataframe['mema10_5'] = dataframe['ema10'].rolling(5).mean()
|
|
||||||
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['msma10_3'] = dataframe['sma10'] / dataframe['sma10'].shift(1)
|
|
||||||
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1h
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
|
|
||||||
informative["rsi"] = ta.RSI(informative)
|
|
||||||
informative["rsi3"] = ta.RSI(informative, 3)
|
|
||||||
# informative["mrsi3"] = informative["rsi"].rolling(3).mean()
|
|
||||||
# informative["max3"] = ta.MAX(informative['close'], timeperiod=3)
|
|
||||||
# informative["min3"] = ta.MIN(informative['close'], timeperiod=3)
|
|
||||||
# informative['pct_change_1'] = informative['close'].pct_change(1)
|
|
||||||
# informative['pct_change_3'] = informative['close'].pct_change(3)
|
|
||||||
informative['pct_change_5'] = informative['close'].pct_change(5)
|
|
||||||
# informative['sma3'] = ta.SMA(informative, timeperiod=3)
|
|
||||||
# informative['sma5'] = ta.SMA(informative, timeperiod=5)
|
|
||||||
# informative['sma10'] = ta.SMA(informative, timeperiod=10)
|
|
||||||
# # informative['adx'] = ta.ADX(informative)
|
|
||||||
#
|
|
||||||
# bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(informative), window=20, stds=2)
|
|
||||||
# informative['bb_lowerband'] = bollinger['lower']
|
|
||||||
# informative['bb_middleband'] = bollinger['mid']
|
|
||||||
# informative['bb_upperband'] = bollinger['upper']
|
|
||||||
# informative["bb_percent"] = (
|
|
||||||
# (informative["close"] - informative["bb_lowerband"]) /
|
|
||||||
# (informative["bb_upperband"] - informative["bb_lowerband"])
|
|
||||||
# )
|
|
||||||
|
|
||||||
# informative["bb_width"] = (
|
|
||||||
# (informative["bb_upperband"] - informative["bb_lowerband"]) / informative["bb_middleband"]
|
|
||||||
# )
|
|
||||||
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage.value - 2, self.buy_decalage.value):
|
|
||||||
conditions = [
|
|
||||||
# (dataframe['bb_width'].shift(decalage) >= self.buy_bollinger.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_001'].shift(decalage)),
|
|
||||||
(dataframe['min_max200'] >= self.buy_min_max_n.value),
|
|
||||||
# (dataframe['close'].shift(decalage) < dataframe['bb_lowerband'].shift(decalage)),
|
|
||||||
# (dataframe['msma10_3'] > 0.998),
|
|
||||||
# (dataframe['msma10_3'] > 0.999)
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(reduce(lambda x, y: x & y, conditions))
|
|
||||||
)
|
|
||||||
,
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_msma1_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (dataframe['close'] < dataframe['open']) &
|
|
||||||
# (dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
# (dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
# (((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# # (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
# ), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_5_2",
|
|
||||||
"params": {
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_decalage": 4,
|
|
||||||
"buy_min_max_n": 0.04,
|
|
||||||
"buy_rsi_max": 58,
|
|
||||||
"buy_rsi_min": 5
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {
|
|
||||||
"n_percent": 5,
|
|
||||||
"percent_sell": -0.16
|
|
||||||
},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.252,
|
|
||||||
"145": 0.21200000000000002,
|
|
||||||
"370": 0.096,
|
|
||||||
"831": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.08
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-12 14:40:04.336207+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,303 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
from freqtrade.strategy.strategy_helper import merge_informative_pair
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD_5_2(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
# buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
#buy_msma_10 = DecimalParameter(0.997, 1.020, decimals=3, default=0.998, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
# buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
buy_decalage = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
buy_min_max_n = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_rsi_min = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
n_percent = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'min200': {'color': 'yellow'},
|
|
||||||
'min200_001': {'color': 'yellow'},
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
if last_candle['percent' + str(self.n_percent.value)] < self.percent_sell.value:
|
|
||||||
return 'sell_lost_percent' + str(self.n_percent.value)
|
|
||||||
|
|
||||||
# Between 2% and 10%, sell if EMA-long above EMA-short
|
|
||||||
# if 0.02 < current_profit < 0.1:
|
|
||||||
# if last_candle['ema100'] > last_candle['ema10']:
|
|
||||||
# return 'ema_long_below_80'
|
|
||||||
#
|
|
||||||
# # Sell any positions at a loss if they are held for more than one day.
|
|
||||||
# if current_profit < -0.20 and (current_time - trade.open_date_utc).days >= 3:
|
|
||||||
# return 'unclog'
|
|
||||||
|
|
||||||
# def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
# proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
# **kwargs) -> float:
|
|
||||||
#
|
|
||||||
# dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
# current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
#
|
|
||||||
# if dataframe['open'] < dataframe['sma100'] * 0.98:
|
|
||||||
# # if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# # return max_stake
|
|
||||||
# # else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
#
|
|
||||||
# # Use default stake amount.
|
|
||||||
# return proposed_stake
|
|
||||||
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
# get access to all pairs available in whitelist.
|
|
||||||
pairs = self.dp.current_whitelist()
|
|
||||||
# informative_pairs = [(pair, '1d') for pair in pairs]
|
|
||||||
# informative_pairs += [(pair, '4h') for pair in pairs]
|
|
||||||
informative_pairs = [(pair, '1h') for pair in pairs]
|
|
||||||
|
|
||||||
return informative_pairs
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
dataframe['min50'] = ta.MIN(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['min200_001'] = dataframe['min200'] * 1.002
|
|
||||||
dataframe['max50'] = ta.MAX(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['min_max200'] = (dataframe['max200'] - dataframe['min200']) / dataframe['min200']
|
|
||||||
dataframe['min_max50'] = (dataframe['max50'] - dataframe['min50']) / dataframe['min50']
|
|
||||||
|
|
||||||
for n in range(1, 25):
|
|
||||||
dataframe["percent" + str(n)] = dataframe['close'].pct_change(n)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['mema10_3'] = dataframe['ema10'] / dataframe['ema10'].shift(1)
|
|
||||||
# dataframe['mema10_5'] = dataframe['ema10'].rolling(5).mean()
|
|
||||||
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['msma10_3'] = dataframe['sma10'] / dataframe['sma10'].shift(1)
|
|
||||||
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1h
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
|
|
||||||
informative["rsi"] = ta.RSI(informative)
|
|
||||||
informative["rsi3"] = ta.RSI(informative, 3)
|
|
||||||
# informative["mrsi3"] = informative["rsi"].rolling(3).mean()
|
|
||||||
# informative["max3"] = ta.MAX(informative['close'], timeperiod=3)
|
|
||||||
# informative["min3"] = ta.MIN(informative['close'], timeperiod=3)
|
|
||||||
# informative['pct_change_1'] = informative['close'].pct_change(1)
|
|
||||||
# informative['pct_change_3'] = informative['close'].pct_change(3)
|
|
||||||
informative['pct_change_5'] = informative['close'].pct_change(5)
|
|
||||||
# informative['sma3'] = ta.SMA(informative, timeperiod=3)
|
|
||||||
# informative['sma5'] = ta.SMA(informative, timeperiod=5)
|
|
||||||
# informative['sma10'] = ta.SMA(informative, timeperiod=10)
|
|
||||||
# # informative['adx'] = ta.ADX(informative)
|
|
||||||
#
|
|
||||||
# bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(informative), window=20, stds=2)
|
|
||||||
# informative['bb_lowerband'] = bollinger['lower']
|
|
||||||
# informative['bb_middleband'] = bollinger['mid']
|
|
||||||
# informative['bb_upperband'] = bollinger['upper']
|
|
||||||
# informative["bb_percent"] = (
|
|
||||||
# (informative["close"] - informative["bb_lowerband"]) /
|
|
||||||
# (informative["bb_upperband"] - informative["bb_lowerband"])
|
|
||||||
# )
|
|
||||||
|
|
||||||
# informative["bb_width"] = (
|
|
||||||
# (informative["bb_upperband"] - informative["bb_lowerband"]) / informative["bb_middleband"]
|
|
||||||
# )
|
|
||||||
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage.value - 2, self.buy_decalage.value):
|
|
||||||
conditions = [
|
|
||||||
# (dataframe['bb_width'].shift(decalage) >= self.buy_bollinger.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_001'].shift(decalage)),
|
|
||||||
(dataframe['min_max200'] >= self.buy_min_max_n.value),
|
|
||||||
# (dataframe['close'].shift(decalage) < dataframe['bb_lowerband'].shift(decalage)),
|
|
||||||
# (dataframe['msma10_3'] > 0.998),
|
|
||||||
# (dataframe['msma10_3'] > 0.999)
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(reduce(lambda x, y: x & y, conditions))
|
|
||||||
)
|
|
||||||
,
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_msma1_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (dataframe['close'] < dataframe['open']) &
|
|
||||||
# (dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
# (dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
# (((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# # (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
# ), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_5_3",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.402,
|
|
||||||
"191": 0.23,
|
|
||||||
"435": 0.078,
|
|
||||||
"711": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.243
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_decalage": 1,
|
|
||||||
"buy_decalage2": 10,
|
|
||||||
"buy_decalage3": 22,
|
|
||||||
"buy_decalage4": 5,
|
|
||||||
"buy_min_max_n": 0.0,
|
|
||||||
"buy_min_max_n2": 0.17,
|
|
||||||
"buy_min_max_n3": 0.17,
|
|
||||||
"buy_min_max_n4": 0.09,
|
|
||||||
"buy_rsi_max": 67,
|
|
||||||
"buy_rsi_max2": 70,
|
|
||||||
"buy_rsi_min": 10,
|
|
||||||
"buy_rsi_min2": 18,
|
|
||||||
"buy_rsi_min_1d": 5,
|
|
||||||
"buy_rsi_min_1d2": 42,
|
|
||||||
"buy_rsi_min_1d3": 52
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {
|
|
||||||
"n_percent": 6,
|
|
||||||
"percent_sell": -0.06
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-13 18:46:52.767429+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,346 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
from freqtrade.strategy.strategy_helper import merge_informative_pair
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD_5_3(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
# buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
#buy_msma_10 = DecimalParameter(0.997, 1.020, decimals=3, default=0.998, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
# buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
buy_decalage = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
buy_decalage2 = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
buy_decalage3 = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
buy_decalage4 = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
|
|
||||||
buy_min_max_n = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n2 = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n3 = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n4 = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
|
|
||||||
buy_rsi_min_1d = IntParameter(0, 25, default=5, space="buy")
|
|
||||||
buy_rsi_min_1d2 = IntParameter(25, 50, default=15, space="buy")
|
|
||||||
buy_rsi_min_1d3 = IntParameter(50, 75, default=50, space="buy")
|
|
||||||
buy_rsi_min_1d4 = IntParameter(75, 100, default=75, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
|
|
||||||
buy_rsi_min = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
buy_rsi_min2 = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
buy_rsi_max2 = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
n_percent = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'min200': {'color': 'yellow'},
|
|
||||||
'min200_001': {'color': 'yellow'},
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
if last_candle['percent' + str(self.n_percent.value)] < self.percent_sell.value:
|
|
||||||
return 'sell_lost_percent' + str(self.n_percent.value)
|
|
||||||
|
|
||||||
# Between 2% and 10%, sell if EMA-long above EMA-short
|
|
||||||
# if 0.02 < current_profit < 0.1:
|
|
||||||
# if last_candle['ema100'] > last_candle['ema10']:
|
|
||||||
# return 'ema_long_below_80'
|
|
||||||
#
|
|
||||||
# # Sell any positions at a loss if they are held for more than one day.
|
|
||||||
# if current_profit < -0.20 and (current_time - trade.open_date_utc).days >= 3:
|
|
||||||
# return 'unclog'
|
|
||||||
|
|
||||||
# def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
# proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
# **kwargs) -> float:
|
|
||||||
#
|
|
||||||
# dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
# current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
#
|
|
||||||
# if dataframe['open'] < dataframe['sma100'] * 0.98:
|
|
||||||
# # if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# # return max_stake
|
|
||||||
# # else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
#
|
|
||||||
# # Use default stake amount.
|
|
||||||
# return proposed_stake
|
|
||||||
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
# get access to all pairs available in whitelist.
|
|
||||||
pairs = self.dp.current_whitelist()
|
|
||||||
informative_pairs = [(pair, '1d') for pair in pairs]
|
|
||||||
# informative_pairs += [(pair, '4h') for pair in pairs]
|
|
||||||
informative_pairs += [(pair, '1h') for pair in pairs]
|
|
||||||
|
|
||||||
return informative_pairs
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
dataframe['min50'] = ta.MIN(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['min200_001'] = dataframe['min200'] * 1.002
|
|
||||||
dataframe['max50'] = ta.MAX(dataframe['close'], timeperiod=50)
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['min_max200'] = (dataframe['max200'] - dataframe['min200']) / dataframe['min200']
|
|
||||||
dataframe['min_max50'] = (dataframe['max50'] - dataframe['min50']) / dataframe['min50']
|
|
||||||
|
|
||||||
for n in range(1, 25):
|
|
||||||
dataframe["percent" + str(n)] = dataframe['close'].pct_change(n)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['mema10_3'] = dataframe['ema10'] / dataframe['ema10'].shift(1)
|
|
||||||
# dataframe['mema10_5'] = dataframe['ema10'].rolling(5).mean()
|
|
||||||
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['msma10_3'] = dataframe['sma10'] / dataframe['sma10'].shift(1)
|
|
||||||
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1h
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
|
|
||||||
informative["rsi"] = ta.RSI(informative)
|
|
||||||
informative["rsi3"] = ta.RSI(informative, 3)
|
|
||||||
informative['r_rsi'] = (informative['rsi3'].div(10).round())
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1d
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1d")
|
|
||||||
informative["rsi"] = ta.RSI(informative)
|
|
||||||
informative["rsi3"] = ta.RSI(informative, 3)
|
|
||||||
informative['r_rsi'] = (informative['rsi'].div(10).round())
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
# if (self.buy_min_max_n.value > self.buy_min_max_n2.value) | (self.buy_min_max_n2.value > self.buy_min_max_n3.value) | (self.buy_min_max_n3.value > self.buy_min_max_n4.value):
|
|
||||||
# return dataframe
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage.value - 2, self.buy_decalage.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_001'].shift(decalage)),
|
|
||||||
(dataframe['min_max200'] >= self.buy_min_max_n.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage2.value - 2, self.buy_decalage2.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= self.buy_rsi_min_1d.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d2.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_001'].shift(decalage)),
|
|
||||||
(dataframe['min_max200'] >= self.buy_min_max_n2.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage3.value - 2, self.buy_decalage3.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= self.buy_rsi_min_1d2.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d3.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_001'].shift(decalage)),
|
|
||||||
(dataframe['min_max200'] >= self.buy_min_max_n3.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage4.value - 2, self.buy_decalage4.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= self.buy_rsi_min_1d3.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d4.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_001'].shift(decalage)),
|
|
||||||
(dataframe['min_max200'] >= self.buy_min_max_n4.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min2.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max2.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (dataframe['close'] < dataframe['open']) &
|
|
||||||
# (dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
# (dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
# (((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# # (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
# ), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_5_4",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": false,
|
|
||||||
"trailing_stop_positive": 0.011,
|
|
||||||
"trailing_stop_positive_offset": 0.111,
|
|
||||||
"trailing_only_offset_is_reached": false
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_decalage": 5,
|
|
||||||
"buy_decalage2": 7,
|
|
||||||
"buy_decalage3": 17,
|
|
||||||
"buy_decalage4": 20,
|
|
||||||
"buy_min_max_n": 0.12,
|
|
||||||
"buy_min_max_n2": 0.14,
|
|
||||||
"buy_min_max_n3": 0.16,
|
|
||||||
"buy_min_max_n4": 0.0,
|
|
||||||
"buy_rsi_max": 51,
|
|
||||||
"buy_rsi_min": 3,
|
|
||||||
"buy_rsi_min_1d": 18,
|
|
||||||
"buy_rsi_min_1d2": 25,
|
|
||||||
"buy_rsi_min_1d3": 56,
|
|
||||||
"buy_rsi_min_1d4": 90,
|
|
||||||
"min_n": 11,
|
|
||||||
"min_p": 1.0,
|
|
||||||
"min_percent": 1.008,
|
|
||||||
"min_percent2": 1.006,
|
|
||||||
"min_percent3": 1.012,
|
|
||||||
"min_percent4": 1.018
|
|
||||||
},
|
|
||||||
"sell": {
|
|
||||||
"max_percent": 0.048,
|
|
||||||
"max_percent2": 0.018,
|
|
||||||
"max_percent3": 0.039,
|
|
||||||
"max_percent4": 0.003,
|
|
||||||
"max_profit": 0.0,
|
|
||||||
"max_profit2": 0.09,
|
|
||||||
"max_profit3": 0.07,
|
|
||||||
"max_profit4": 0.07,
|
|
||||||
"sell_h_RSI": 83,
|
|
||||||
"sell_h_RSI2": 72,
|
|
||||||
"sell_h_RSI2_percent": 0.017,
|
|
||||||
"sell_h_RSI3": 74
|
|
||||||
},
|
|
||||||
"protection": {
|
|
||||||
"n_percent": 1,
|
|
||||||
"percent_sell": -0.08
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-15 14:27:47.977295+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_5_4",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_decalage": 1,
|
|
||||||
"buy_decalage2": 9,
|
|
||||||
"buy_decalage3": 2,
|
|
||||||
"buy_decalage4": 8,
|
|
||||||
"buy_min_max_n": 0.14,
|
|
||||||
"buy_min_max_n2": 0.17,
|
|
||||||
"buy_min_max_n3": 0.07,
|
|
||||||
"buy_min_max_n4": 0.16,
|
|
||||||
"buy_rsi_max": 53,
|
|
||||||
"buy_rsi_min": 23,
|
|
||||||
"buy_rsi_min_1d": 24,
|
|
||||||
"buy_rsi_min_1d2": 50,
|
|
||||||
"buy_rsi_min_1d3": 57,
|
|
||||||
"min_n": 13,
|
|
||||||
"min_p": 1.006
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {
|
|
||||||
"n_percent": 1,
|
|
||||||
"percent_sell": -0.08
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-13 21:03:59.051913+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,326 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
from freqtrade.strategy.strategy_helper import merge_informative_pair
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD_5_4(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
# buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
#buy_msma_10 = DecimalParameter(0.997, 1.020, decimals=3, default=0.998, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
# buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
buy_decalage = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
buy_decalage2 = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
buy_decalage3 = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
buy_decalage4 = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
|
|
||||||
buy_min_max_n = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n2 = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n3 = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n4 = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
|
|
||||||
buy_rsi_min_1d = IntParameter(0, 25, default=5, space="buy")
|
|
||||||
buy_rsi_min_1d2 = IntParameter(25, 50, default=15, space="buy")
|
|
||||||
buy_rsi_min_1d3 = IntParameter(50, 75, default=50, space="buy")
|
|
||||||
buy_rsi_min_1d4 = IntParameter(75, 100, default=75, space="buy")
|
|
||||||
|
|
||||||
min_percent = DecimalParameter(1, 1.02, decimals=3, default=1.002, space='buy')
|
|
||||||
min_percent2 = DecimalParameter(1, 1.02, decimals=3, default=1.002, space='buy')
|
|
||||||
min_percent3 = DecimalParameter(1, 1.02, decimals=3, default=1.002, space='buy')
|
|
||||||
min_percent4 = DecimalParameter(1, 1.02, decimals=3, default=1.002, space='buy')
|
|
||||||
|
|
||||||
max_percent = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent2 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent3 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent4 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
|
|
||||||
max_profit = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit2 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit3 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit4 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
|
|
||||||
# sell_b_RSI = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
# sell_b_RSI2 = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
# sell_b_RSI3 = IntParameter(70, 98, default=80, space='sell')
|
|
||||||
#
|
|
||||||
# sell_b_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
||||||
sell_h_RSI = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
sell_h_RSI2 = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
sell_h_RSI3 = IntParameter(70, 98, default=80, space='sell')
|
|
||||||
|
|
||||||
sell_h_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
||||||
# buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
|
|
||||||
buy_rsi_min = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
# buy_rsi_min2 = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
# buy_rsi_max2 = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
|
|
||||||
min_n = IntParameter(0, 24, default=15, space="buy")
|
|
||||||
min_p = DecimalParameter(1, 1.01, decimals=3, default=1.002, space="buy")
|
|
||||||
|
|
||||||
n_percent = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
n_percent2 = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell2 = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
n_percent3 = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell3 = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
n_percent4 = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell4 = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'min200': {'color': 'yellow'},
|
|
||||||
'min200_001': {'color': 'yellow'},
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
|
|
||||||
if (last_candle['rsi_1h'] < self.buy_rsi_min_1d.value):
|
|
||||||
max_percent = self.max_percent.value
|
|
||||||
max_profit = self.max_profit.value
|
|
||||||
if last_candle['percent' + str(self.n_percent.value)] < self.percent_sell.value:
|
|
||||||
return 'sell_lost_percent' + str(self.n_percent.value)
|
|
||||||
else:
|
|
||||||
if (last_candle['rsi_1h'] < self.buy_rsi_min_1d2.value):
|
|
||||||
max_percent = self.max_percent2.value
|
|
||||||
max_profit = self.max_profit2.value
|
|
||||||
if last_candle['percent' + str(self.n_percent2.value)] < self.percent_sell2.value:
|
|
||||||
return 'sell_lost_percent' + str(self.n_percent2.value)
|
|
||||||
else:
|
|
||||||
if (last_candle['rsi_1h'] < self.buy_rsi_min_1d3.value):
|
|
||||||
max_percent = self.max_percent3.value
|
|
||||||
max_profit = self.max_profit3.value
|
|
||||||
if last_candle['percent' + str(self.n_percent3.value)] < self.percent_sell3.value:
|
|
||||||
return 'sell_lost_percent' + str(self.n_percent3.value)
|
|
||||||
else:
|
|
||||||
max_percent = self.max_percent4.value
|
|
||||||
max_profit = self.max_profit4.value
|
|
||||||
if last_candle['percent' + str(self.n_percent4.value)] < self.percent_sell4.value:
|
|
||||||
return 'sell_lost_percent' + str(self.n_percent4.value)
|
|
||||||
|
|
||||||
if (current_profit > max_profit) & (
|
|
||||||
(last_candle['percent1'] < -max_percent) | (last_candle['percent3'] < -max_percent) | (
|
|
||||||
last_candle['percent5'] < -max_percent)):
|
|
||||||
return 'h_percent_quick'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI.value):
|
|
||||||
return 'h_over_rsi'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI2.value) & \
|
|
||||||
(last_candle['percent1'] < - self.sell_h_RSI2_percent.value):
|
|
||||||
return 'h_over_rsi_2'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI3.value) & \
|
|
||||||
(last_candle['close'] >= last_candle['max200']):
|
|
||||||
return 'h_over_rsi_max'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
# get access to all pairs available in whitelist.
|
|
||||||
pairs = self.dp.current_whitelist()
|
|
||||||
# informative_pairs = [(pair, '1d') for pair in pairs]
|
|
||||||
# informative_pairs += [(pair, '4h') for pair in pairs]
|
|
||||||
informative_pairs = [(pair, '1h') for pair in pairs]
|
|
||||||
return informative_pairs
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['min200_001'] = dataframe['min200'] * self.min_percent.value
|
|
||||||
dataframe['min200_002'] = dataframe['min200'] * self.min_percent2.value
|
|
||||||
dataframe['min200_003'] = dataframe['min200'] * self.min_percent3.value
|
|
||||||
dataframe['min200_004'] = dataframe['min200'] * self.min_percent4.value
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
dataframe['min_n'] = ta.MIN(dataframe['close'], timeperiod=self.min_n.value * 12)
|
|
||||||
dataframe['max_n'] = ta.MAX(dataframe['close'], timeperiod=self.min_n.value * 12)
|
|
||||||
dataframe['min_max_n'] = (dataframe['max_n'] - dataframe['min_n']) / dataframe['min_n']
|
|
||||||
dataframe['min_n_p'] = dataframe['min_n'] * self.min_p.value
|
|
||||||
|
|
||||||
for n in range(1, 25):
|
|
||||||
dataframe["percent" + str(n)] = dataframe['close'].pct_change(n)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1h
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
|
|
||||||
informative["rsi"] = ta.RSI(informative)
|
|
||||||
informative["rsi3"] = ta.RSI(informative, 3)
|
|
||||||
informative['r_rsi'] = (informative['rsi3'].div(10).round())
|
|
||||||
for n in range(1, 5):
|
|
||||||
informative["percent" + str(n)] = informative['close'].pct_change(n)
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
for decalage in range(self.buy_decalage.value - 2, self.buy_decalage.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_001'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage2.value - 2, self.buy_decalage2.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= self.buy_rsi_min_1d.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d2.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_002'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n2.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage3.value - 2, self.buy_decalage3.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= self.buy_rsi_min_1d2.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d3.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_003'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n3.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage4.value - 2, self.buy_decalage4.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= self.buy_rsi_min_1d3.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d4.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_004'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n4.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_4_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
return dataframe
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_5_5",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": false,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_decalage": 5,
|
|
||||||
"buy_decalage2": 7,
|
|
||||||
"buy_decalage3": 17,
|
|
||||||
"buy_decalage4": 20,
|
|
||||||
"buy_min_max_n": 0.12,
|
|
||||||
"buy_min_max_n2": 0.14,
|
|
||||||
"buy_min_max_n3": 0.16,
|
|
||||||
"buy_min_max_n4": 0.0,
|
|
||||||
"buy_rsi_max": 51,
|
|
||||||
"buy_rsi_min": 3,
|
|
||||||
"buy_rsi_min_1d": 18,
|
|
||||||
"buy_rsi_min_1d2": 25,
|
|
||||||
"buy_rsi_min_1d3": 56,
|
|
||||||
"buy_rsi_min_1d4": 90,
|
|
||||||
"min_n": 11,
|
|
||||||
"min_p": 1.0,
|
|
||||||
"min_percent": 1.008,
|
|
||||||
"min_percent2": 1.006,
|
|
||||||
"min_percent3": 1.012,
|
|
||||||
"min_percent4": 1.018
|
|
||||||
},
|
|
||||||
"sell": {
|
|
||||||
"max_percent": 0.004,
|
|
||||||
"max_percent2": 0.006,
|
|
||||||
"max_percent3": 0.0,
|
|
||||||
"max_percent4": 0.038,
|
|
||||||
"max_profit": 0.06,
|
|
||||||
"max_profit2": 0.05,
|
|
||||||
"max_profit3": 0.0,
|
|
||||||
"max_profit4": 0.01,
|
|
||||||
"sell_h_RSI": 79,
|
|
||||||
"sell_h_RSI2": 90,
|
|
||||||
"sell_h_RSI2_percent": 0.005,
|
|
||||||
"sell_h_RSI3": 84
|
|
||||||
},
|
|
||||||
"protection": {
|
|
||||||
"n_percent": 1,
|
|
||||||
"percent_sell": -0.08
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-15 16:27:30.204760+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,314 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
from freqtrade.strategy.strategy_helper import merge_informative_pair
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD_5_5(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
# buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
#buy_msma_10 = DecimalParameter(0.997, 1.020, decimals=3, default=0.998, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
# buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
buy_decalage = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
buy_decalage2 = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
buy_decalage3 = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
buy_decalage4 = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
|
|
||||||
buy_min_max_n = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n2 = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n3 = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n4 = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
|
|
||||||
buy_rsi_min_1d = IntParameter(0, 25, default=5, space="buy")
|
|
||||||
buy_rsi_min_1d2 = IntParameter(25, 50, default=15, space="buy")
|
|
||||||
buy_rsi_min_1d3 = IntParameter(50, 75, default=50, space="buy")
|
|
||||||
buy_rsi_min_1d4 = IntParameter(75, 100, default=75, space="buy")
|
|
||||||
|
|
||||||
min_percent = DecimalParameter(1, 1.02, decimals=3, default=1.002, space='buy')
|
|
||||||
min_percent2 = DecimalParameter(1, 1.02, decimals=3, default=1.002, space='buy')
|
|
||||||
min_percent3 = DecimalParameter(1, 1.02, decimals=3, default=1.002, space='buy')
|
|
||||||
min_percent4 = DecimalParameter(1, 1.02, decimals=3, default=1.002, space='buy')
|
|
||||||
|
|
||||||
max_percent = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent2 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent3 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent4 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
|
|
||||||
max_profit = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit2 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit3 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit4 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
|
|
||||||
# sell_b_RSI = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
# sell_b_RSI2 = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
# sell_b_RSI3 = IntParameter(70, 98, default=80, space='sell')
|
|
||||||
#
|
|
||||||
# sell_b_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
||||||
sell_h_RSI = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
sell_h_RSI2 = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
sell_h_RSI3 = IntParameter(70, 98, default=80, space='sell')
|
|
||||||
|
|
||||||
sell_h_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
||||||
# buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
|
|
||||||
buy_rsi_min = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
# buy_rsi_min2 = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
# buy_rsi_max2 = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
|
|
||||||
min_n = IntParameter(0, 24, default=15, space="buy")
|
|
||||||
min_p = DecimalParameter(1, 1.01, decimals=3, default=1.002, space="buy")
|
|
||||||
n_percent = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'min200': {'color': 'yellow'},
|
|
||||||
'min200_001': {'color': 'yellow'},
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
|
|
||||||
if last_candle['percent' + str(self.n_percent.value)] < self.percent_sell.value:
|
|
||||||
return 'sell_lost_percent' + str(self.n_percent.value)
|
|
||||||
|
|
||||||
if (last_candle['rsi_1h'] < self.buy_rsi_min_1d.value):
|
|
||||||
max_percent = self.max_percent.value
|
|
||||||
max_profit = self.max_profit.value
|
|
||||||
else:
|
|
||||||
if (last_candle['rsi_1h'] < self.buy_rsi_min_1d2.value):
|
|
||||||
max_percent = self.max_percent2.value
|
|
||||||
max_profit = self.max_profit2.value
|
|
||||||
else:
|
|
||||||
if (last_candle['rsi_1h'] < self.buy_rsi_min_1d3.value):
|
|
||||||
max_percent = self.max_percent3.value
|
|
||||||
max_profit = self.max_profit3.value
|
|
||||||
else:
|
|
||||||
max_percent = self.max_percent4.value
|
|
||||||
max_profit = self.max_profit4.value
|
|
||||||
|
|
||||||
if (current_profit > max_profit) & (
|
|
||||||
(last_candle['percent1'] < -max_percent) | (last_candle['percent3'] < -max_percent) | (
|
|
||||||
last_candle['percent5'] < -max_percent)):
|
|
||||||
return 'h_percent_quick'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI.value):
|
|
||||||
return 'h_over_rsi'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI2.value) & \
|
|
||||||
(last_candle['percent1'] < - self.sell_h_RSI2_percent.value):
|
|
||||||
return 'h_over_rsi_2'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI3.value) & \
|
|
||||||
(last_candle['close'] >= last_candle['max200']):
|
|
||||||
return 'h_over_rsi_max'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
# get access to all pairs available in whitelist.
|
|
||||||
pairs = self.dp.current_whitelist()
|
|
||||||
# informative_pairs = [(pair, '1d') for pair in pairs]
|
|
||||||
# informative_pairs += [(pair, '4h') for pair in pairs]
|
|
||||||
informative_pairs = [(pair, '1h') for pair in pairs]
|
|
||||||
return informative_pairs
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['min200_001'] = dataframe['min200'] * self.min_percent.value
|
|
||||||
dataframe['min200_002'] = dataframe['min200'] * self.min_percent2.value
|
|
||||||
dataframe['min200_003'] = dataframe['min200'] * self.min_percent3.value
|
|
||||||
dataframe['min200_004'] = dataframe['min200'] * self.min_percent4.value
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
dataframe['min_n'] = ta.MIN(dataframe['close'], timeperiod=self.min_n.value * 12)
|
|
||||||
dataframe['max_n'] = ta.MAX(dataframe['close'], timeperiod=self.min_n.value * 12)
|
|
||||||
dataframe['min_max_n'] = (dataframe['max_n'] - dataframe['min_n']) / dataframe['min_n']
|
|
||||||
dataframe['min_n_p'] = dataframe['min_n'] * self.min_p.value
|
|
||||||
|
|
||||||
for n in range(1, 25):
|
|
||||||
dataframe["percent" + str(n)] = dataframe['close'].pct_change(n)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1h
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
|
|
||||||
informative["rsi"] = ta.RSI(informative)
|
|
||||||
informative["rsi3"] = ta.RSI(informative, 3)
|
|
||||||
informative['r_rsi'] = (informative['rsi3'].div(10).round())
|
|
||||||
# for n in range(1, 5):
|
|
||||||
# informative["percent" + str(n)] = informative['close'].pct_change(n)
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
for decalage in range(self.buy_decalage.value - 2, self.buy_decalage.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_001'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage2.value - 2, self.buy_decalage2.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= self.buy_rsi_min_1d.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d2.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_002'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n2.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage3.value - 2, self.buy_decalage3.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= self.buy_rsi_min_1d2.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d3.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_003'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n3.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage4.value - 2, self.buy_decalage4.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= self.buy_rsi_min_1d3.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d4.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_004'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n4.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_4_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
return dataframe
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_5_6",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": false,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_decalage": 5,
|
|
||||||
"buy_decalage2": 7,
|
|
||||||
"buy_decalage3": 17,
|
|
||||||
"buy_min_max_n": 0.12,
|
|
||||||
"buy_min_max_n2": 0.14,
|
|
||||||
"buy_min_max_n3": 0.16,
|
|
||||||
"buy_rsi_max": 55,
|
|
||||||
"buy_rsi_min": 3,
|
|
||||||
"buy_rsi_min_1d": 18,
|
|
||||||
"buy_rsi_min_1d2": 25,
|
|
||||||
"buy_rsi_min_1d3": 56,
|
|
||||||
"min_n": 11,
|
|
||||||
"min_p": 1.0,
|
|
||||||
"min_percent": 1.008,
|
|
||||||
"min_percent2": 1.010,
|
|
||||||
"min_percent3": 1.012
|
|
||||||
},
|
|
||||||
"sell": {
|
|
||||||
"max_percent": 0.045,
|
|
||||||
"max_percent2": 0.01,
|
|
||||||
"max_percent3": 0.004,
|
|
||||||
"max_profit": 0.09,
|
|
||||||
"max_profit2": 0.09,
|
|
||||||
"max_profit3": 0.0,
|
|
||||||
"sell_RSI": 73,
|
|
||||||
"sell_RSI2": 84,
|
|
||||||
"sell_RSI2_percent": 0.003,
|
|
||||||
"sell_RSI3": 73
|
|
||||||
},
|
|
||||||
"protection": {
|
|
||||||
"n_percent": 1,
|
|
||||||
"percent_sell": -0.08
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-16 17:52:27.040594+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,331 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
from freqtrade.strategy.strategy_helper import merge_informative_pair
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD_5_6(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
# buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
#buy_msma_10 = DecimalParameter(0.997, 1.020, decimals=3, default=0.998, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
# buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
buy_decalage = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
buy_decalage2 = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
buy_decalage3 = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
# buy_decalage4 = IntParameter(1, 24, default=5, space="buy")
|
|
||||||
|
|
||||||
buy_min_max_n = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n2 = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n3 = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
# buy_min_max_n4 = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
||||||
|
|
||||||
buy_rsi_min_1d = IntParameter(0, 20, default=5, space="buy")
|
|
||||||
buy_rsi_min_1d2 = IntParameter(20, 35, default=30, space="buy")
|
|
||||||
buy_rsi_min_1d3 = IntParameter(35, 50, default=45, space="buy")
|
|
||||||
# buy_rsi_min_1d4 = IntParameter(50, 70, default=60, space="buy")
|
|
||||||
|
|
||||||
min_percent = DecimalParameter(1, 1.02, decimals=3, default=1.002, space='buy')
|
|
||||||
min_percent2 = DecimalParameter(1, 1.02, decimals=3, default=1.002, space='buy')
|
|
||||||
min_percent3 = DecimalParameter(1, 1.02, decimals=3, default=1.002, space='buy')
|
|
||||||
# min_percent4 = DecimalParameter(1, 1.02, decimals=3, default=1.002, space='buy')
|
|
||||||
|
|
||||||
max_percent = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent2 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent3 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
# max_percent4 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
|
|
||||||
max_profit = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit2 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit3 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
# max_profit4 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
|
|
||||||
# sell_b_RSI = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
# sell_b_RSI2 = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
# sell_b_RSI3 = IntParameter(70, 98, default=80, space='sell')
|
|
||||||
#
|
|
||||||
# sell_b_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
||||||
sell_RSI = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
sell_RSI2 = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
sell_RSI3 = IntParameter(70, 98, default=80, space='sell')
|
|
||||||
|
|
||||||
sell_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
||||||
# buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
|
|
||||||
buy_rsi_min = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
# buy_rsi_min2 = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
# buy_rsi_max2 = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
# buy_rsi_min3 = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
# buy_rsi_max3 = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
# buy_rsi_min4 = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
# buy_rsi_max4 = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
|
|
||||||
min_n = IntParameter(0, 24, default=15, space="buy")
|
|
||||||
min_p = DecimalParameter(1, 1.01, decimals=3, default=1.002, space="buy")
|
|
||||||
n_percent = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
"main_plot": {
|
|
||||||
"bb_lowerband": {
|
|
||||||
"color": "white"
|
|
||||||
},
|
|
||||||
"bb_upperband": {
|
|
||||||
"color": "white"
|
|
||||||
},
|
|
||||||
"min200": {
|
|
||||||
"color": "yellow"
|
|
||||||
},
|
|
||||||
"min200_001": {
|
|
||||||
"color": "yellow"
|
|
||||||
},
|
|
||||||
"max200": {
|
|
||||||
"color": "yellow",
|
|
||||||
"type": "line"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"subplots": {
|
|
||||||
"BB": {
|
|
||||||
"bb_width": {
|
|
||||||
"color": "white"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Percent": {
|
|
||||||
"min_max200": {
|
|
||||||
"color": "#c046bb",
|
|
||||||
"type": "line"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
|
|
||||||
number = 0
|
|
||||||
if (last_candle['rsi_1h'] < self.buy_rsi_min_1d.value):
|
|
||||||
max_percent = self.max_percent.value
|
|
||||||
max_profit = self.max_profit.value
|
|
||||||
number = 1
|
|
||||||
else:
|
|
||||||
if (last_candle['rsi_1h'] < self.buy_rsi_min_1d2.value):
|
|
||||||
max_percent = self.max_percent2.value
|
|
||||||
max_profit = self.max_profit2.value
|
|
||||||
number = 2
|
|
||||||
else:
|
|
||||||
# if (last_candle['rsi_1h'] < self.buy_rsi_min_1d3.value):
|
|
||||||
max_percent = self.max_percent3.value
|
|
||||||
max_profit = self.max_profit3.value
|
|
||||||
number = 3
|
|
||||||
# else:
|
|
||||||
# max_percent = self.max_percent4.value
|
|
||||||
# max_profit = self.max_profit4.value
|
|
||||||
# number = 4
|
|
||||||
if last_candle['percent' + str(self.n_percent.value)] < self.percent_sell.value:
|
|
||||||
return 'sell_lost_percent_' + str(number)
|
|
||||||
|
|
||||||
if (current_profit > max_profit) & (
|
|
||||||
(last_candle['percent1'] < -max_percent) | (last_candle['percent3'] < -max_percent) | (
|
|
||||||
last_candle['percent5'] < -max_percent)):
|
|
||||||
return 'h_percent_quick_' + str(number)
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_RSI.value):
|
|
||||||
return 'h_over_rsi_' + str(number)
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_RSI2.value) & \
|
|
||||||
(last_candle['percent1'] < - self.sell_RSI2_percent.value):
|
|
||||||
return 'h_over_rsi_2_' + str(number)
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_RSI3.value) & \
|
|
||||||
(last_candle['close'] >= last_candle['max200']):
|
|
||||||
return 'h_over_rsi_max_' + str(number)
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
# get access to all pairs available in whitelist.
|
|
||||||
pairs = self.dp.current_whitelist()
|
|
||||||
# informative_pairs = [(pair, '1d') for pair in pairs]
|
|
||||||
# informative_pairs += [(pair, '4h') for pair in pairs]
|
|
||||||
informative_pairs = [(pair, '1h') for pair in pairs]
|
|
||||||
return informative_pairs
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['min200_001'] = dataframe['min200'] * self.min_percent.value
|
|
||||||
dataframe['min200_002'] = dataframe['min200'] * self.min_percent2.value
|
|
||||||
dataframe['min200_003'] = dataframe['min200'] * self.min_percent3.value
|
|
||||||
# dataframe['min200_004'] = dataframe['min200'] * self.min_percent4.value
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
dataframe['min_n'] = ta.MIN(dataframe['close'], timeperiod=self.min_n.value * 12)
|
|
||||||
dataframe['max_n'] = ta.MAX(dataframe['close'], timeperiod=self.min_n.value * 12)
|
|
||||||
dataframe['min_max_n'] = (dataframe['max_n'] - dataframe['min_n']) / dataframe['min_n']
|
|
||||||
dataframe['min_n_p'] = dataframe['min_n'] * self.min_p.value
|
|
||||||
|
|
||||||
for n in range(1, 25):
|
|
||||||
dataframe["percent" + str(n)] = dataframe['close'].pct_change(n)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1h
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
|
|
||||||
informative["rsi"] = ta.RSI(informative)
|
|
||||||
informative["rsi3"] = ta.RSI(informative, 3)
|
|
||||||
informative['r_rsi'] = (informative['rsi3'].div(10).round())
|
|
||||||
# for n in range(1, 5):
|
|
||||||
# informative["percent" + str(n)] = informative['close'].pct_change(n)
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
for decalage in range(self.buy_decalage.value - 2, self.buy_decalage.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_001'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage2.value - 2, self.buy_decalage2.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= self.buy_rsi_min_1d.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d2.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_002'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n2.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage3.value - 2, self.buy_decalage3.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= self.buy_rsi_min_1d2.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_min_1d3.value),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_003'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n3.value),
|
|
||||||
(dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
(dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
# for decalage in range(self.buy_decalage4.value - 2, self.buy_decalage4.value):
|
|
||||||
# conditions = [
|
|
||||||
# (dataframe['rsi_1h'] >= self.buy_rsi_min_1d3.value),
|
|
||||||
# (dataframe['rsi_1h'] < self.buy_rsi_min_1d4.value),
|
|
||||||
# (dataframe['close'].shift(decalage) < dataframe['min200_004'].shift(decalage)),
|
|
||||||
# (dataframe['min_max_n'] >= self.buy_min_max_n4.value),
|
|
||||||
# (dataframe['rsi_1h'] > self.buy_rsi_min.value),
|
|
||||||
# (dataframe['rsi_1h'] < self.buy_rsi_max.value),
|
|
||||||
# ]
|
|
||||||
# # GUARDS AND TRENDS
|
|
||||||
# if conditions:
|
|
||||||
# dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
# ['buy', 'buy_tag']] = (1, 'buy_4_' + str(decalage))
|
|
||||||
# break
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
return dataframe
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_5_7",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": false,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_decalage": 3,
|
|
||||||
"buy_decalage2": 8,
|
|
||||||
"buy_decalage3": 19,
|
|
||||||
"buy_min_max_n": 0.12,
|
|
||||||
"buy_min_max_n2": 0.11,
|
|
||||||
"buy_min_max_n3": 0.14,
|
|
||||||
"buy_mrsi3": -0.1,
|
|
||||||
"min_n": 11,
|
|
||||||
"min_p": 1.006,
|
|
||||||
"min_percent": 1.014,
|
|
||||||
"min_percent2": 1.006,
|
|
||||||
"min_percent3": 1.006
|
|
||||||
},
|
|
||||||
"sell": {
|
|
||||||
"max_percent": 0.004,
|
|
||||||
"max_percent2": 0.006,
|
|
||||||
"max_percent3": 0.0,
|
|
||||||
"max_profit": 0.06,
|
|
||||||
"max_profit2": 0.05,
|
|
||||||
"max_profit3": 0.0,
|
|
||||||
"sell_h_RSI": 79,
|
|
||||||
"sell_h_RSI2": 90,
|
|
||||||
"sell_h_RSI2_percent": 0.005,
|
|
||||||
"sell_h_RSI3": 84
|
|
||||||
},
|
|
||||||
"protection": {
|
|
||||||
"n_percent": 1,
|
|
||||||
"percent_sell": -0.08
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-17 13:07:40.696464+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,295 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
from freqtrade.strategy.strategy_helper import merge_informative_pair
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD_5_7(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
# buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
#buy_msma_10 = DecimalParameter(0.997, 1.020, decimals=3, default=0.998, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
# buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
buy_decalage = IntParameter(3, 10, default=5, space="buy")
|
|
||||||
buy_decalage2 = IntParameter(5, 15, default=5, space="buy")
|
|
||||||
buy_decalage3 = IntParameter(10, 20, default=5, space="buy")
|
|
||||||
|
|
||||||
buy_min_max_n = DecimalParameter(0.06, 0.14, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n2 = DecimalParameter(0.06, 0.14, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n3 = DecimalParameter(0.06, 0.14, decimals=2, default=0.05, space='buy')
|
|
||||||
|
|
||||||
# buy_rsi_min_1d = IntParameter(0, 25, default=5, space="buy")
|
|
||||||
# buy_rsi_min_1d2 = IntParameter(25, 50, default=15, space="buy")
|
|
||||||
# buy_rsi_min_1d3 = IntParameter(50, 75, default=50, space="buy")
|
|
||||||
|
|
||||||
min_percent = DecimalParameter(1.005, 1.015, decimals=3, default=1.002, space='buy')
|
|
||||||
min_percent2 = DecimalParameter(1.005, 1.015, decimals=3, default=1.002, space='buy')
|
|
||||||
min_percent3 = DecimalParameter(1.005, 1.015, decimals=3, default=1.002, space='buy')
|
|
||||||
|
|
||||||
max_percent = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent2 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent3 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
|
|
||||||
max_profit = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit2 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit3 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
|
|
||||||
# sell_b_RSI = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
# sell_b_RSI2 = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
# sell_b_RSI3 = IntParameter(70, 98, default=80, space='sell')
|
|
||||||
#
|
|
||||||
# sell_b_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
||||||
sell_h_RSI = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
sell_h_RSI2 = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
sell_h_RSI3 = IntParameter(70, 98, default=80, space='sell')
|
|
||||||
|
|
||||||
sell_h_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
||||||
# buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi_min = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
# buy_rsi_max = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
buy_mrsi3 = DecimalParameter(-0.1, 0.1, decimals=2, default=0, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi_min2 = IntParameter(0, 50, default=25, space="buy")
|
|
||||||
# buy_rsi_max2 = IntParameter(50, 100, default=60, space="buy")
|
|
||||||
|
|
||||||
min_n = IntParameter(0, 24, default=15, space="buy")
|
|
||||||
min_p = DecimalParameter(1, 1.01, decimals=3, default=1.002, space="buy")
|
|
||||||
n_percent = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'min200': {'color': 'yellow'},
|
|
||||||
'min200_001': {'color': 'yellow'},
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
|
|
||||||
if last_candle['percent' + str(self.n_percent.value)] < self.percent_sell.value:
|
|
||||||
return 'sell_lost_percent' + str(self.n_percent.value)
|
|
||||||
|
|
||||||
if (last_candle['rsi_1h'] < 18):
|
|
||||||
max_percent = self.max_percent.value
|
|
||||||
max_profit = self.max_profit.value
|
|
||||||
else:
|
|
||||||
if (last_candle['rsi_1h'] < 25):
|
|
||||||
max_percent = self.max_percent2.value
|
|
||||||
max_profit = self.max_profit2.value
|
|
||||||
else:
|
|
||||||
max_percent = self.max_percent3.value
|
|
||||||
max_profit = self.max_profit3.value
|
|
||||||
|
|
||||||
if (current_profit > max_profit) & (
|
|
||||||
(last_candle['percent1'] < -max_percent) | (last_candle['percent3'] < -max_percent) | (
|
|
||||||
last_candle['percent5'] < -max_percent)):
|
|
||||||
return 'h_percent_quick'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI.value):
|
|
||||||
return 'h_over_rsi'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI2.value) & \
|
|
||||||
(last_candle['percent1'] < - self.sell_h_RSI2_percent.value):
|
|
||||||
return 'h_over_rsi_2'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI3.value) & \
|
|
||||||
(last_candle['close'] >= last_candle['max200']):
|
|
||||||
return 'h_over_rsi_max'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
# get access to all pairs available in whitelist.
|
|
||||||
pairs = self.dp.current_whitelist()
|
|
||||||
# informative_pairs = [(pair, '1d') for pair in pairs]
|
|
||||||
# informative_pairs += [(pair, '4h') for pair in pairs]
|
|
||||||
informative_pairs = [(pair, '1h') for pair in pairs]
|
|
||||||
return informative_pairs
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['min200_001'] = dataframe['min200'] * self.min_percent.value
|
|
||||||
dataframe['min200_002'] = dataframe['min200'] * self.min_percent2.value
|
|
||||||
dataframe['min200_003'] = dataframe['min200'] * self.min_percent3.value
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
dataframe['min_n'] = ta.MIN(dataframe['close'], timeperiod=self.min_n.value * 12)
|
|
||||||
dataframe['max_n'] = ta.MAX(dataframe['close'], timeperiod=self.min_n.value * 12)
|
|
||||||
dataframe['min_max_n'] = (dataframe['max_n'] - dataframe['min_n']) / dataframe['min_n']
|
|
||||||
dataframe['min_n_p'] = dataframe['min_n'] * self.min_p.value
|
|
||||||
|
|
||||||
for n in range(1, 25):
|
|
||||||
dataframe["percent" + str(n)] = dataframe['close'].pct_change(n)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1h
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
|
|
||||||
informative["rsi"] = ta.RSI(informative)
|
|
||||||
informative["rsi3"] = ta.RSI(informative, 3)
|
|
||||||
informative["mrsi3"] = informative["rsi"].pct_change(3)
|
|
||||||
informative['r_rsi'] = (informative['rsi3'].div(10).round())
|
|
||||||
# for n in range(1, 5):
|
|
||||||
# informative["percent" + str(n)] = informative['close'].pct_change(n)
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
for decalage in range(self.buy_decalage.value - 2, self.buy_decalage.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] < 18),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_001'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n.value),
|
|
||||||
(dataframe['rsi_1h'] > 0),
|
|
||||||
(dataframe['rsi_1h'] < 51),
|
|
||||||
(dataframe['mrsi3_1h'] > self.buy_mrsi3.value)
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage2.value - 2, self.buy_decalage2.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= 18),
|
|
||||||
(dataframe['rsi_1h'] < 25),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_002'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n2.value),
|
|
||||||
(dataframe['rsi_1h'] > 0),
|
|
||||||
(dataframe['rsi_1h'] < 51),
|
|
||||||
(dataframe['mrsi3_1h'] > self.buy_mrsi3.value)
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage3.value - 2, self.buy_decalage3.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= 25),
|
|
||||||
(dataframe['rsi_1h'] < 56),
|
|
||||||
(dataframe['close'].shift(decalage) < dataframe['min200_003'].shift(decalage)),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n3.value),
|
|
||||||
(dataframe['rsi_1h'] > 0),
|
|
||||||
(dataframe['rsi_1h'] < 51),
|
|
||||||
(dataframe['mrsi3_1h'] > self.buy_mrsi3.value)
|
|
||||||
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
return dataframe
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_5_8",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": false,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_min_max_n": 0.27,
|
|
||||||
"buy_min_max_n2": 0.08,
|
|
||||||
"buy_min_max_n3": 0.06,
|
|
||||||
"buy_mrsi3": -0.07,
|
|
||||||
"min_n": 3,
|
|
||||||
"min_percent": 1.01,
|
|
||||||
"min_percent2": 1.004,
|
|
||||||
"min_percent3": 1.008
|
|
||||||
},
|
|
||||||
"sell": {
|
|
||||||
"max_percent": 0.032,
|
|
||||||
"max_percent2": 0.019,
|
|
||||||
"max_percent3": 0.024,
|
|
||||||
"max_profit": 0.1,
|
|
||||||
"max_profit2": 0.07,
|
|
||||||
"max_profit3": 0.04,
|
|
||||||
"sell_h_RSI": 91,
|
|
||||||
"sell_h_RSI2": 96,
|
|
||||||
"sell_h_RSI2_percent": 0.019,
|
|
||||||
"sell_h_RSI3": 92
|
|
||||||
},
|
|
||||||
"protection": {
|
|
||||||
"n_percent": 5,
|
|
||||||
"percent_sell": -0.13
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-17 18:41:11.974567+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,290 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
from freqtrade.strategy.strategy_helper import merge_informative_pair
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD_5_8(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
# buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
#buy_msma_10 = DecimalParameter(0.997, 1.020, decimals=3, default=0.998, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
# buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
buy_decalage = IntParameter(3, 10, default=5, space="buy")
|
|
||||||
buy_decalage2 = IntParameter(5, 15, default=5, space="buy")
|
|
||||||
buy_decalage3 = IntParameter(10, 20, default=5, space="buy")
|
|
||||||
|
|
||||||
buy_min_max_n = DecimalParameter(0.06, 0.30, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n2 = DecimalParameter(0.06, 0.14, decimals=2, default=0.05, space='buy')
|
|
||||||
buy_min_max_n3 = DecimalParameter(0.06, 0.14, decimals=2, default=0.05, space='buy')
|
|
||||||
|
|
||||||
# buy_rsi_min_1d = IntParameter(0, 25, default=5, space="buy")
|
|
||||||
# buy_rsi_min_1d2 = IntParameter(25, 50, default=15, space="buy")
|
|
||||||
# buy_rsi_min_1d3 = IntParameter(50, 75, default=50, space="buy")
|
|
||||||
|
|
||||||
min_percent = DecimalParameter(1.005, 1.015, decimals=3, default=1.002, space='buy')
|
|
||||||
min_percent2 = DecimalParameter(1.005, 1.015, decimals=3, default=1.002, space='buy')
|
|
||||||
min_percent3 = DecimalParameter(1.005, 1.015, decimals=3, default=1.002, space='buy')
|
|
||||||
|
|
||||||
buy_mrsi3 = DecimalParameter(-0.1, 0.1, decimals=2, default=0, space="buy")
|
|
||||||
|
|
||||||
min_n = IntParameter(0, 24, default=15, space="buy")
|
|
||||||
# min_p = DecimalParameter(1, 1.01, decimals=3, default=1.002, space="buy")
|
|
||||||
|
|
||||||
max_percent = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent2 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent3 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
|
|
||||||
max_profit = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit2 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit3 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
|
|
||||||
# sell_b_RSI = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
# sell_b_RSI2 = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
# sell_b_RSI3 = IntParameter(70, 98, default=80, space='sell')
|
|
||||||
#
|
|
||||||
# sell_b_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
||||||
sell_h_RSI = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
sell_h_RSI2 = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
sell_h_RSI3 = IntParameter(70, 98, default=80, space='sell')
|
|
||||||
|
|
||||||
sell_h_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
||||||
|
|
||||||
n_percent = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell = DecimalParameter(-0.2, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'min200': {'color': 'yellow'},
|
|
||||||
'min200_001': {'color': 'yellow'},
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
|
|
||||||
if last_candle['percent' + str(self.n_percent.value)] < self.percent_sell.value:
|
|
||||||
return 'sell_lost_percent' + str(self.n_percent.value)
|
|
||||||
|
|
||||||
if (last_candle['rsi_1h'] < 18):
|
|
||||||
max_percent = self.max_percent.value
|
|
||||||
max_profit = self.max_profit.value
|
|
||||||
else:
|
|
||||||
if (last_candle['rsi_1h'] < 25):
|
|
||||||
max_percent = self.max_percent2.value
|
|
||||||
max_profit = self.max_profit2.value
|
|
||||||
else:
|
|
||||||
max_percent = self.max_percent3.value
|
|
||||||
max_profit = self.max_profit3.value
|
|
||||||
|
|
||||||
if (current_profit > max_profit) & (
|
|
||||||
(last_candle['percent1'] < -max_percent) | (last_candle['percent3'] < -max_percent) | (
|
|
||||||
last_candle['percent5'] < -max_percent)):
|
|
||||||
return 'h_percent_quick'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI.value):
|
|
||||||
return 'h_over_rsi'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI2.value) & \
|
|
||||||
(last_candle['percent1'] < - self.sell_h_RSI2_percent.value):
|
|
||||||
return 'h_over_rsi_2'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI3.value) & \
|
|
||||||
(last_candle['close'] >= last_candle['max200']):
|
|
||||||
return 'h_over_rsi_max'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
# get access to all pairs available in whitelist.
|
|
||||||
pairs = self.dp.current_whitelist()
|
|
||||||
# informative_pairs = [(pair, '1d') for pair in pairs]
|
|
||||||
# informative_pairs += [(pair, '4h') for pair in pairs]
|
|
||||||
informative_pairs = [(pair, '1h') for pair in pairs]
|
|
||||||
return informative_pairs
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
dataframe['min_n'] = ta.MIN(dataframe['close'], timeperiod=self.min_n.value * 24)
|
|
||||||
dataframe['max_n'] = ta.MAX(dataframe['close'], timeperiod=self.min_n.value * 24)
|
|
||||||
dataframe['min_max_n'] = (dataframe['max_n'] - dataframe['min_n']) / dataframe['min_n']
|
|
||||||
# dataframe['min_n_p'] = dataframe['min_n'] * self.min_p.value
|
|
||||||
dataframe['minn_1'] = dataframe['min_n'] * self.min_percent.value
|
|
||||||
dataframe['minn_2'] = dataframe['min_n'] * self.min_percent2.value
|
|
||||||
dataframe['minn_3'] = dataframe['min_n'] * self.min_percent3.value
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
|
|
||||||
for n in range(1, 25):
|
|
||||||
dataframe["percent" + str(n)] = dataframe['close'].pct_change(n)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
# bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
# dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
# dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
# dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
# dataframe["bb_percent"] = (
|
|
||||||
# (dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
# (dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
# )
|
|
||||||
# dataframe["bb_width"] = (
|
|
||||||
# (dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
# )
|
|
||||||
|
|
||||||
################### INFORMATIVE 1h
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
|
|
||||||
informative["rsi"] = ta.RSI(informative)
|
|
||||||
informative["rsi3"] = ta.RSI(informative, 3)
|
|
||||||
informative["mrsi3"] = informative["rsi"].pct_change(3)
|
|
||||||
informative['r_rsi'] = (informative['rsi3'].div(10).round())
|
|
||||||
# for n in range(1, 5):
|
|
||||||
# informative["percent" + str(n)] = informative['close'].pct_change(n)
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
for decalage in range(self.buy_decalage.value - 2, self.buy_decalage.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] < 18),
|
|
||||||
(dataframe['close'] < dataframe['minn_1']),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n.value),
|
|
||||||
(dataframe['rsi_1h'] > 0),
|
|
||||||
(dataframe['rsi_1h'] < 51),
|
|
||||||
(dataframe['mrsi3_1h'] > self.buy_mrsi3.value)
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage2.value - 2, self.buy_decalage2.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= 18),
|
|
||||||
(dataframe['rsi_1h'] < 25),
|
|
||||||
(dataframe['close'] < dataframe['minn_2']),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n2.value),
|
|
||||||
(dataframe['rsi_1h'] > 0),
|
|
||||||
(dataframe['rsi_1h'] < 51),
|
|
||||||
(dataframe['mrsi3_1h'] > self.buy_mrsi3.value)
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
for decalage in range(self.buy_decalage3.value - 2, self.buy_decalage3.value):
|
|
||||||
conditions = [
|
|
||||||
(dataframe['rsi_1h'] >= 25),
|
|
||||||
(dataframe['rsi_1h'] < 56),
|
|
||||||
(dataframe['close'] < dataframe['minn_3']),
|
|
||||||
(dataframe['min_max_n'] >= self.buy_min_max_n3.value),
|
|
||||||
(dataframe['rsi_1h'] > 0),
|
|
||||||
(dataframe['rsi_1h'] < 51),
|
|
||||||
(dataframe['mrsi3_1h'] > self.buy_mrsi3.value)
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
|
|
||||||
break
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
return dataframe
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyJD_5_9",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": false,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_decalage4": 1,
|
|
||||||
"min_percent4": 7,
|
|
||||||
"rapport_min_n": 14
|
|
||||||
},
|
|
||||||
"sell": {
|
|
||||||
"max_percent": 0.041,
|
|
||||||
"max_percent2": 0.032,
|
|
||||||
"max_percent3": 0.013,
|
|
||||||
"max_profit": 0.09,
|
|
||||||
"max_profit2": 0.1,
|
|
||||||
"max_profit3": 0.06,
|
|
||||||
"sell_h_RSI": 82,
|
|
||||||
"sell_h_RSI2": 82,
|
|
||||||
"sell_h_RSI2_percent": 0.011,
|
|
||||||
"sell_h_RSI3": 72
|
|
||||||
},
|
|
||||||
"protection": {
|
|
||||||
"hours_sell": 16,
|
|
||||||
"n_percent": 7,
|
|
||||||
"percent_sell": -0.07,
|
|
||||||
"percent_sell_sma5_1d": -0.07,
|
|
||||||
"percent_sell_stop": -0.7
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2022-09-21 09:43:15.542215+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,301 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
from freqtrade.strategy.strategy_helper import merge_informative_pair
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyJD_5_9(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
buy_decalage4 = IntParameter(1, 10, default=5, space="buy")
|
|
||||||
|
|
||||||
min_percent4 = IntParameter(1, 20, default=10, space='buy')
|
|
||||||
# buy_mrsi3 = DecimalParameter(-0.1, 0.1, decimals=2, default=0, space="buy")
|
|
||||||
|
|
||||||
rapport_min_n = IntParameter(1, 20, default=10, space='buy')
|
|
||||||
|
|
||||||
min_n = 16
|
|
||||||
|
|
||||||
max_percent = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent2 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
max_percent3 = DecimalParameter(0, 0.05, decimals=3, default=0.005, space='sell')
|
|
||||||
|
|
||||||
max_profit = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit2 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
max_profit3 = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='sell')
|
|
||||||
|
|
||||||
sell_h_RSI = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
sell_h_RSI2 = IntParameter(70, 98, default=88, space='sell')
|
|
||||||
sell_h_RSI3 = IntParameter(70, 98, default=80, space='sell')
|
|
||||||
|
|
||||||
sell_h_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
||||||
|
|
||||||
n_percent = IntParameter(1, 12, default=1, space="protection")
|
|
||||||
percent_sell = DecimalParameter(-0.1, -0.01, decimals=2, default=-0.08, space="protection")
|
|
||||||
percent_sell_stop = DecimalParameter(-0.8, -0.1, decimals=1, default=-0.8, space="protection")
|
|
||||||
percent_sell_sma5_1d = DecimalParameter(-0.1, 0, decimals=2, default=0, space="protection")
|
|
||||||
hours_sell = IntParameter(5, 48, default=24, space="protection")
|
|
||||||
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
lim_0 = 10
|
|
||||||
lim_1 = 18
|
|
||||||
lim_2 = 25
|
|
||||||
lim_3 = 51
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
"main_plot": {
|
|
||||||
"bb_lowerband": {
|
|
||||||
"color": "white"
|
|
||||||
},
|
|
||||||
"bb_upperband": {
|
|
||||||
"color": "white"
|
|
||||||
},
|
|
||||||
"min200": {
|
|
||||||
"color": "yellow"
|
|
||||||
},
|
|
||||||
"max200": {
|
|
||||||
"color": "yellow"
|
|
||||||
},
|
|
||||||
"min_n": {
|
|
||||||
"color": "#600e82"
|
|
||||||
},
|
|
||||||
"max_n": {
|
|
||||||
"color": "#600e82"
|
|
||||||
},
|
|
||||||
"min5_1d": {
|
|
||||||
"color": "#6aa123",
|
|
||||||
},
|
|
||||||
"max5_1d": {
|
|
||||||
"color": "red"
|
|
||||||
},
|
|
||||||
"max3_1d": {
|
|
||||||
"color": "blue"
|
|
||||||
},
|
|
||||||
"close_1d": {
|
|
||||||
"color": "green"
|
|
||||||
},
|
|
||||||
"close_1M": {
|
|
||||||
"color": "cyan"
|
|
||||||
},
|
|
||||||
"min_n_1d": {
|
|
||||||
"color": "pink"
|
|
||||||
},
|
|
||||||
"max_n_1d": {
|
|
||||||
"color": "pink"
|
|
||||||
},
|
|
||||||
"sma5_1d": {
|
|
||||||
"color": "black"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"subplots": {
|
|
||||||
"Rsi": {
|
|
||||||
"rsi_1h": {
|
|
||||||
"color": "blue"
|
|
||||||
},
|
|
||||||
"rsi_1d": {
|
|
||||||
"color": "red"
|
|
||||||
},
|
|
||||||
"rsi": {
|
|
||||||
"color": "green"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
# "Percent": {
|
|
||||||
# "min_max200": {
|
|
||||||
# "color": "#c046bb"
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
previous_previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
|
|
||||||
days = (current_time - trade.open_date_utc).days
|
|
||||||
minutes = (current_time - trade.open_date_utc).seconds / 60
|
|
||||||
hours = minutes / 60
|
|
||||||
|
|
||||||
if (last_candle['sma5_diff_1d'] < self.percent_sell_sma5_1d.value) & (current_profit < -0.05):
|
|
||||||
return 'sell_sma5_1d'
|
|
||||||
|
|
||||||
if (current_profit < self.percent_sell_stop.value) & (hours >= self.hours_sell.value) & (last_candle['percent_1h'] <= -0.05):
|
|
||||||
return 'sell_stop'
|
|
||||||
|
|
||||||
# if (last_candle['percent1'] < -0.005) & (last_candle['max200'] == previous_previous_last_candle['max200']) & (minutes > 30):
|
|
||||||
# return 'sell_percent1'
|
|
||||||
#
|
|
||||||
# if (last_candle['percent3'] < -0.005) & (last_candle['percent1'] < 0) \
|
|
||||||
# & (previous_last_candle['percent1'] < 0) & (previous_previous_last_candle['percent1'] < 0) & (minutes > 30):
|
|
||||||
# return 'sell_percent3'
|
|
||||||
|
|
||||||
#if last_candle['percent' + str(self.n_percent.value)] < self.percent_sell.value:
|
|
||||||
# return 'sell_lost_percent_' + str(self.n_percent.value)
|
|
||||||
|
|
||||||
if (last_candle['rsi_1h'] < self.lim_1):
|
|
||||||
max_percent = self.max_percent.value
|
|
||||||
max_profit = self.max_profit.value
|
|
||||||
else:
|
|
||||||
if (last_candle['rsi_1h'] < self.lim_2):
|
|
||||||
max_percent = self.max_percent2.value
|
|
||||||
max_profit = self.max_profit2.value
|
|
||||||
else:
|
|
||||||
max_percent = self.max_percent3.value
|
|
||||||
max_profit = self.max_profit3.value
|
|
||||||
|
|
||||||
if (current_profit > max_profit) & (
|
|
||||||
#(last_candle['percent1'] < -max_percent) |
|
|
||||||
(last_candle['percent3'] < -max_percent) | (last_candle['percent5'] < -max_percent)):
|
|
||||||
#& (last_candle['close'] > last_candle['max3_1d']):
|
|
||||||
return 'h_percent_quick'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI.value):
|
|
||||||
return 'h_over_rsi'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI2.value) & \
|
|
||||||
(last_candle['percent1'] < - self.sell_h_RSI2_percent.value):
|
|
||||||
return 'h_over_rsi_2'
|
|
||||||
|
|
||||||
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI3.value) & \
|
|
||||||
(last_candle['close'] >= last_candle['max3_1d']):
|
|
||||||
return 'h_over_rsi_max'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
# get access to all pairs available in whitelist.
|
|
||||||
pairs = self.dp.current_whitelist()
|
|
||||||
informative_pairs = [(pair, '1d') for pair in pairs]
|
|
||||||
informative_pairs += [(pair, '1M') for pair in pairs]
|
|
||||||
informative_pairs += [(pair, '1h') for pair in pairs]
|
|
||||||
return informative_pairs
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# print(self.min_percent.value, self.min_percent2.value, self.min_percent3.value,
|
|
||||||
# self.buy_decalage.value, self.buy_decalage2.value, self.buy_decalage3.value,
|
|
||||||
# )
|
|
||||||
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
period = int(self.min_n * 24)
|
|
||||||
dataframe['min_n'] = ta.MIN(dataframe['close'], timeperiod=period)
|
|
||||||
dataframe['max_n'] = ta.MAX(dataframe['close'], timeperiod=period)
|
|
||||||
dataframe['min_max_n'] = (dataframe['max_n'] - dataframe['min_n']) / dataframe['min_n']
|
|
||||||
for n in range(1, 25):
|
|
||||||
dataframe["percent" + str(n)] = dataframe['close'].pct_change(n)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1h
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
|
|
||||||
informative["rsi"] = ta.RSI(informative)
|
|
||||||
informative["rsi3"] = ta.RSI(informative, 3)
|
|
||||||
# informative["mrsi3"] = informative["rsi"].pct_change(3)
|
|
||||||
informative['r_rsi'] = (informative['rsi3'].div(10).round())
|
|
||||||
informative['percent'] = informative['close'].pct_change(1)
|
|
||||||
# for n in range(1, 5):
|
|
||||||
# informative["percent" + str(n)] = informative['close'].pct_change(n)
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1d
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1d")
|
|
||||||
informative["rsi"] = ta.RSI(informative, period=5)
|
|
||||||
informative['min5'] = ta.MIN(informative['close'], timeperiod=5)
|
|
||||||
informative['max3'] = ta.MAX(informative['close'], timeperiod=3)
|
|
||||||
informative['max5'] = ta.MAX(informative['close'], timeperiod=5)
|
|
||||||
informative['sma5'] = ta.SMA(informative['close'], timeperiod=5)
|
|
||||||
informative['min_n'] = ta.MIN(informative['close'], timeperiod=14)
|
|
||||||
informative['max_n'] = ta.MAX(informative['close'], timeperiod=14)
|
|
||||||
informative['min_max_n'] = (informative['max_n'] - informative['min_n']) / informative['min_n']
|
|
||||||
informative['percent'] = informative['close'].pct_change(1)
|
|
||||||
informative['sma5_diff'] = informative['sma5'] - informative['sma5'].shift(1)
|
|
||||||
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True)
|
|
||||||
|
|
||||||
################### INFORMATIVE 1M
|
|
||||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1M")
|
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1M", ffill=True)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
conditions = [
|
|
||||||
(dataframe['close'] <= dataframe['min_n_1d']), # * (1 + (dataframe['min_max_n_1d'] / self.min_percent3.value))),
|
|
||||||
(dataframe['close'] <= dataframe['min_n'] * (1 + (dataframe['min_max_n'] / self.min_percent4.value))),
|
|
||||||
(dataframe['min_n'].shift(self.buy_decalage4.value) == dataframe['min_n']),
|
|
||||||
(dataframe['min_n_1d'] / dataframe['min_n'] > 1 + self.rapport_min_n.value / 100)
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
||||||
['buy', 'buy_tag']] = (1, 'buy_4')
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
return dataframe
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from pandas import DataFrame
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick(IStrategy):
|
|
||||||
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
#"0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 #0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
#max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"Aaron": {
|
|
||||||
'aroonup': {'color': 'blue'},
|
|
||||||
'aroondown': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
# MACD
|
|
||||||
#macd = ta.MACD(dataframe)
|
|
||||||
#dataframe['macd'] = macd['macd']
|
|
||||||
#dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
#dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
#dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband'])
|
|
||||||
& (dataframe['bb_width'] >= 0.065)
|
|
||||||
#& (dataframe['rsi'] < 45)
|
|
||||||
& (dataframe['volume'] > 0)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick2",
|
|
||||||
"params": {
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.04,
|
|
||||||
"buy_sma_percent": 0.93
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.237,
|
|
||||||
"19": 0.065,
|
|
||||||
"65": 0.026,
|
|
||||||
"185": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.327
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.116,
|
|
||||||
"trailing_stop_positive_offset": 0.15000000000000002,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-18 21:32:34.141258+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,272 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick2(IStrategy):
|
|
||||||
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
"0": 1,
|
|
||||||
# "600": 0.12,
|
|
||||||
# "1200": 0.08,
|
|
||||||
# "2400": 0.06,
|
|
||||||
# "3600": 0.04,
|
|
||||||
# "7289": 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
# Buy hypers
|
|
||||||
timeframe = '4h'
|
|
||||||
|
|
||||||
# Trailing stoploss
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.15
|
|
||||||
trailing_stop_positive_offset = 0.20
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"Aaron": {
|
|
||||||
'aroonup': {'color': 'blue'},
|
|
||||||
'aroondown': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
previous_5_candle = dataframe.iloc[-5].squeeze()
|
|
||||||
#print("last_candle", last_candle)
|
|
||||||
#print("previous_last_candle", previous_last_candle)
|
|
||||||
|
|
||||||
count = 0
|
|
||||||
for coin, balance in self.wallets.get_all_balances().items():
|
|
||||||
count = count + 1
|
|
||||||
# print(coin, " ", balance)
|
|
||||||
# print("count=", count)
|
|
||||||
|
|
||||||
# (last_candle['percent5'] < -0.005) \
|
|
||||||
# if (0 < current_profit < 0.005) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 2):
|
|
||||||
# # & (previous_last_candle['sma10'] > last_candle['sma10']):
|
|
||||||
# print("too_small_gain", pair, trade, " profit=", current_profit, " rate=", current_rate, " percent5=",
|
|
||||||
# last_candle['percent5'])
|
|
||||||
# return 'too_small_gain'
|
|
||||||
|
|
||||||
# if (current_profit < -0.05) \
|
|
||||||
# & ((current_time - trade.open_date_utc).days >= 3):
|
|
||||||
# print("lost_half_profit", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'stop_loss_profit'
|
|
||||||
|
|
||||||
# if (current_profit > 0.02) \
|
|
||||||
# & (last_candle['percent'] < 0.01) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600):
|
|
||||||
# print("lost_half_profit", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'lost_half_profit'
|
|
||||||
|
|
||||||
# ((current_time - trade.open_date_utc).seconds >= 3600 * 2) \
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& (previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
|
|
||||||
& ((last_candle['percent'] < 0) & (last_candle['percent3'] < - (current_profit / 4))):
|
|
||||||
# print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_bb_band_sma10_desc'
|
|
||||||
|
|
||||||
# if (current_profit > 0) \
|
|
||||||
# & (last_candle['percent'] < -0.02):
|
|
||||||
# # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'stop_percent_loss'
|
|
||||||
|
|
||||||
#if (current_profit > 0) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 2) \
|
|
||||||
# & (previous_last_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
# & (last_candle['percent'] < 0):
|
|
||||||
# print("over_bb_band_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'over_bb_band_sma20_desc'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& (last_candle['rsi'] > 88): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
|
|
||||||
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_rsi'
|
|
||||||
|
|
||||||
# description trade
|
|
||||||
# Trade(id=0, pair=CAKE/USDT, amount=4.19815281, open_rate=11.91000000, open_since=2021-12-22 17:55:00)
|
|
||||||
# print(last_candle)
|
|
||||||
# if 0.05 < current_profit < 1:
|
|
||||||
# if (
|
|
||||||
# (previous_last_candle['sma10'] > last_candle['sma10'] * 1.005) &
|
|
||||||
# (current_time - trade.open_date_utc).seconds >= 3600 * 3
|
|
||||||
# # ) | (
|
|
||||||
# # (current_time - trade.open_date_utc).seconds >= 3600 * 6
|
|
||||||
# ):
|
|
||||||
# # self.lock_pair(pair, until=current_time + timedelta(hours=3))
|
|
||||||
#
|
|
||||||
# print("profit_3h_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'profit_3h_sma10_desc'
|
|
||||||
#
|
|
||||||
# if (0 < current_profit < 0.1) \
|
|
||||||
# & (previous_last_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 5):
|
|
||||||
# print("profit_5h_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'profit_5h_sma20_desc'
|
|
||||||
|
|
||||||
# if (count == self.config['max_open_trades']) & (current_profit < -0.04) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 6):
|
|
||||||
# self.lock_pair(pair, until=current_time + timedelta(hours=10))
|
|
||||||
# print("stop_short_loss", pair, trade, " profit=", current_profit, " rate=", current_rate,
|
|
||||||
# "count=", count, "max=", self.config['max_open_trades'])
|
|
||||||
# return 'stop_short_loss'
|
|
||||||
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
#
|
|
||||||
# # Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
# dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
# dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe["percent5"] = dataframe["percent"].rolling(5).sum()
|
|
||||||
dataframe["percent3"] = dataframe["percent"].rolling(3).sum()
|
|
||||||
dataframe["percent20"] = dataframe["percent"].rolling(20).sum()
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
|
|
||||||
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max_min'] = dataframe['max'] / dataframe['min']
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
dataframe['bb_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
|
|
||||||
|
|
||||||
# Bollinger Bands - Weighted (EMA based instead of SMA)
|
|
||||||
weighted_bollinger = qtpylib.weighted_bollinger_bands(
|
|
||||||
qtpylib.typical_price(dataframe), window=20, stds=2
|
|
||||||
)
|
|
||||||
dataframe["wbb_upperband"] = weighted_bollinger["upper"]
|
|
||||||
dataframe["wbb_lowerband"] = weighted_bollinger["lower"]
|
|
||||||
dataframe["wbb_middleband"] = weighted_bollinger["mid"]
|
|
||||||
dataframe["wbb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["wbb_lowerband"]) /
|
|
||||||
(dataframe["wbb_upperband"] - dataframe["wbb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["wbb_width"] = (
|
|
||||||
(dataframe["wbb_upperband"] - dataframe["wbb_lowerband"]) / dataframe["wbb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband'])
|
|
||||||
& (dataframe['bb_width'] >= 0.065)
|
|
||||||
#& (dataframe['rsi'] < 45)
|
|
||||||
& (dataframe['volume'] * dataframe['close'] / 1000 >= 100)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from pandas import DataFrame
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick22(IStrategy):
|
|
||||||
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
#"0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 #0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
#max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"Aaron": {
|
|
||||||
'aroonup': {'color': 'blue'},
|
|
||||||
'aroondown': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
# MACD
|
|
||||||
#macd = ta.MACD(dataframe)
|
|
||||||
#dataframe['macd'] = macd['macd']
|
|
||||||
#dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
#dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
# Aroon, Aroon Oscillator
|
|
||||||
aroon = ta.AROON(dataframe)
|
|
||||||
dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
#dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband'])
|
|
||||||
& (
|
|
||||||
(dataframe['bb_width'] >= 0.095) |
|
|
||||||
((dataframe['bb_width'] >= 0.08) & (dataframe['close'].shift(20) / dataframe['close'] >= 1.03))
|
|
||||||
)
|
|
||||||
& (dataframe['volume'] > 0)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from pandas import DataFrame
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick23(IStrategy):
|
|
||||||
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
#"0": 0.015
|
|
||||||
"0": 0.10,
|
|
||||||
"60": 0.05,
|
|
||||||
"120": 0.03,
|
|
||||||
"180": 0.015,
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 #0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
#max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"Aaron": {
|
|
||||||
'aroonup': {'color': 'blue'},
|
|
||||||
'aroondown': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
# MACD
|
|
||||||
#macd = ta.MACD(dataframe)
|
|
||||||
#dataframe['macd'] = macd['macd']
|
|
||||||
#dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
#dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
# Aroon, Aroon Oscillator
|
|
||||||
aroon = ta.AROON(dataframe)
|
|
||||||
dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
#dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband'])
|
|
||||||
& (
|
|
||||||
(dataframe['bb_width'] >= 0.095) |
|
|
||||||
((dataframe['bb_width'] >= 0.08) & (dataframe['close'].shift(20) / dataframe['close'] >= 1.03))
|
|
||||||
)
|
|
||||||
& (dataframe['volume'] > 0)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick3(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'}
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"Aaron": {
|
|
||||||
'aroonup': {'color': 'blue'},
|
|
||||||
'aroondown': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# Aroon, Aroon Oscillator
|
|
||||||
aroon = ta.AROON(dataframe)
|
|
||||||
dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
# dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
|
|
||||||
condition = np.where(value >= 1.02, True, False)
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband'])
|
|
||||||
& (
|
|
||||||
(dataframe['bb_width'] >= 0.095) |
|
|
||||||
(
|
|
||||||
(dataframe['bb_width'] >= 0.04) & condition
|
|
||||||
)
|
|
||||||
)
|
|
||||||
# & (dataframe['close'] <= dataframe['sma500'])
|
|
||||||
& (dataframe['volume'] > 0)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick31(IStrategy):
|
|
||||||
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
#"0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 #0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
#max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'}
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"Aaron": {
|
|
||||||
'aroonup': {'color': 'blue'},
|
|
||||||
'aroondown': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
# MACD
|
|
||||||
#macd = ta.MACD(dataframe)
|
|
||||||
#dataframe['macd'] = macd['macd']
|
|
||||||
#dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
#dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
# Aroon, Aroon Oscillator
|
|
||||||
aroon = ta.AROON(dataframe)
|
|
||||||
dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
#dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
# Baisse depuis 20 cycles
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
condition = np.where(value >= 1.02, True, False)
|
|
||||||
|
|
||||||
# Baisse dans les 20% inférieur
|
|
||||||
horizon = int(12 * 60 / 5)
|
|
||||||
pmin = dataframe['min'].shift(horizon)
|
|
||||||
pmax = dataframe['max'].shift(horizon)
|
|
||||||
pmoy = (dataframe['max'] - dataframe['min']) / (pmax - pmin)
|
|
||||||
# print("pmoy=", pmoy)
|
|
||||||
for k, v in pmoy.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
condition2 = np.where(value <= 0.8, True, False)
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband'])
|
|
||||||
& (
|
|
||||||
(dataframe['bb_width'] >= 0.095) |
|
|
||||||
(
|
|
||||||
(dataframe['bb_width'] >= 0.04) & condition & condition2
|
|
||||||
)
|
|
||||||
)
|
|
||||||
& (dataframe['volume'] > 0)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick32(IStrategy):
|
|
||||||
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
#"0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 #0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
#max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"Aaron": {
|
|
||||||
'aroonup': {'color': 'blue'},
|
|
||||||
'aroondown': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
# MACD
|
|
||||||
#macd = ta.MACD(dataframe)
|
|
||||||
#dataframe['macd'] = macd['macd']
|
|
||||||
#dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
#dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
# Aroon, Aroon Oscillator
|
|
||||||
aroon = ta.AROON(dataframe)
|
|
||||||
dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
#dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
# Baisse depuis 20 cycles
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
condition = np.where(value >= 1.02, True, False)
|
|
||||||
|
|
||||||
# Baisse dans les 20% inférieur
|
|
||||||
horizon = int(4 * 60 / 5)
|
|
||||||
pmin = dataframe['min'].shift(horizon)
|
|
||||||
pmax = dataframe['max'].shift(horizon)
|
|
||||||
pmoy = (dataframe['max'] - dataframe['min']) / (pmax - pmin)
|
|
||||||
# print("pmoy=", pmoy)
|
|
||||||
for k, v in pmoy.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
condition2 = np.where(value <= 0.8, True, False)
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband'])
|
|
||||||
& (
|
|
||||||
(dataframe['bb_width'] >= 0.095) |
|
|
||||||
(
|
|
||||||
(dataframe['bb_width'] >= 0.04) & condition & condition2
|
|
||||||
)
|
|
||||||
)
|
|
||||||
& (dataframe['volume'] > 0)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick4(IStrategy):
|
|
||||||
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
#"0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 #0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
#max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"Aaron": {
|
|
||||||
'aroonup': {'color': 'blue'},
|
|
||||||
'aroondown': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
# MACD
|
|
||||||
#macd = ta.MACD(dataframe)
|
|
||||||
#dataframe['macd'] = macd['macd']
|
|
||||||
#dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
#dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# Aroon, Aroon Oscillator
|
|
||||||
aroon = ta.AROON(dataframe)
|
|
||||||
dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
#dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
|
|
||||||
condition = np.where(value >= 1.04, True, False)
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband'])
|
|
||||||
& (
|
|
||||||
(dataframe['bb_width'] >= 0.095) |
|
|
||||||
(
|
|
||||||
(dataframe['bb_width'] >= 0.04) & condition
|
|
||||||
)
|
|
||||||
)
|
|
||||||
& (dataframe['volume'] > 0)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
@@ -1,207 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick41(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma500_97': {'color': 'gray'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
# 'volatility_dcp': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"Aaron": {
|
|
||||||
'aroonup': {'color': 'blue'},
|
|
||||||
'aroondown': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# Aroon, Aroon Oscillator
|
|
||||||
aroon = ta.AROON(dataframe)
|
|
||||||
dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
# dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
|
|
||||||
condition = np.where(value >= 1.04, True, False)
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(dataframe['volume'] > 0) &
|
|
||||||
(
|
|
||||||
(dataframe['bb_width'] >= 0.095) |
|
|
||||||
((dataframe['bb_width'] >= 0.04) & condition)
|
|
||||||
& (dataframe['close'] <= dataframe['sma200_95'])
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick411",
|
|
||||||
"params": {
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.09,
|
|
||||||
"buy_bollinger_2": 0.08,
|
|
||||||
"buy_bollinger_2_enabled": false,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.99,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 18.9,
|
|
||||||
"buy_volume_enabled": true
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.096,
|
|
||||||
"30": 0.049,
|
|
||||||
"60": 0.032,
|
|
||||||
"120": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-07 21:14:40.877512+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick411",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.09,
|
|
||||||
"buy_bollinger_2": 0.08,
|
|
||||||
"buy_bollinger_2_enabled": true,
|
|
||||||
"buy_bollinger_3": 0.07,
|
|
||||||
"buy_bollinger_3_enabled": true,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.98,
|
|
||||||
"buy_sma_percent_enabled": true,
|
|
||||||
"buy_volume": 13.5,
|
|
||||||
"buy_volume_enabled": false
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-05 18:56:50.185120+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick411",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.09,
|
|
||||||
"buy_bollinger_2": 0.0,
|
|
||||||
"buy_bollinger_2_enabled": false,
|
|
||||||
"buy_bollinger_3": 0.08,
|
|
||||||
"buy_bollinger_3_enabled": true,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.97,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 42.0,
|
|
||||||
"buy_volume_enabled": false
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-04 21:37:54.391956+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick411",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.08,
|
|
||||||
"buy_bollinger_2": 0.04,
|
|
||||||
"buy_bollinger_2_enabled": true,
|
|
||||||
"buy_bollinger_enabled": true
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-04 16:23:57.580987+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick411",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.04,
|
|
||||||
"buy_bollinger_2": 0.0,
|
|
||||||
"buy_bollinger_2_enabled": true,
|
|
||||||
"buy_bollinger_3": 0.04,
|
|
||||||
"buy_bollinger_3_enabled": true,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 1.05,
|
|
||||||
"buy_sma_percent_enabled": true,
|
|
||||||
"buy_volume": 37.9,
|
|
||||||
"buy_volume_enabled": false
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-05 17:11:37.461801+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick411",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.11,
|
|
||||||
"buy_bollinger_2": 0.0,
|
|
||||||
"buy_bollinger_2_enabled": false,
|
|
||||||
"buy_bollinger_3": 0.07,
|
|
||||||
"buy_bollinger_3_enabled": true,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.98,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 40.3,
|
|
||||||
"buy_volume_enabled": false
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-05 17:31:26.224609+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick411",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.06,
|
|
||||||
"buy_bollinger_2": 0.02,
|
|
||||||
"buy_bollinger_2_enabled": false,
|
|
||||||
"buy_bollinger_3": 0.06,
|
|
||||||
"buy_bollinger_3_enabled": true,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 1.02,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 14.7,
|
|
||||||
"buy_volume_enabled": true
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-05 17:53:59.162189+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick411",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.12,
|
|
||||||
"buy_bollinger_2": 0.07,
|
|
||||||
"buy_bollinger_2_enabled": false,
|
|
||||||
"buy_bollinger_3": 0.02,
|
|
||||||
"buy_bollinger_3_enabled": false,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.98,
|
|
||||||
"buy_sma_percent_enabled": true,
|
|
||||||
"buy_volume": 10.5,
|
|
||||||
"buy_volume_enabled": false
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-05 16:38:40.768689+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick411",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.07,
|
|
||||||
"buy_bollinger_2": 0.02,
|
|
||||||
"buy_bollinger_2_enabled": true,
|
|
||||||
"buy_bollinger_3": 0.07,
|
|
||||||
"buy_bollinger_3_enabled": false,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.95,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 7.1,
|
|
||||||
"buy_volume_enabled": false
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-05 18:12:23.363449+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick411",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.09,
|
|
||||||
"buy_bollinger_2": 0.04,
|
|
||||||
"buy_bollinger_2_enabled": true,
|
|
||||||
"buy_bollinger_3": 0.06,
|
|
||||||
"buy_bollinger_3_enabled": false,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.96,
|
|
||||||
"buy_sma_percent_enabled": true,
|
|
||||||
"buy_volume": 11.9,
|
|
||||||
"buy_volume_enabled": true
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-05 18:27:26.631033+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick411(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
'rsi': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(5).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=5)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
conditions = [
|
|
||||||
dataframe['bb_width'] >= self.buy_bollinger.value,
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']),
|
|
||||||
(dataframe['close'] < dataframe['sma100'] * self.buy_sma_percent.value)
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(reduce(lambda x, y: x & y, conditions))
|
|
||||||
)
|
|
||||||
,
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4111",
|
|
||||||
"params": {
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_baisse_bollinger": 0.07,
|
|
||||||
"buy_baisse_bollinger_2": 0.05,
|
|
||||||
"buy_baisse_bollinger_2_enabled": true,
|
|
||||||
"buy_baisse_bollinger_enabled": true,
|
|
||||||
"buy_baisse_sma_percent": 0.99,
|
|
||||||
"buy_baisse_sma_percent_enabled": true,
|
|
||||||
"buy_baisse_volume": 44.7,
|
|
||||||
"buy_baisse_volume_enabled": true,
|
|
||||||
"buy_hausse_bollinger": 0.05,
|
|
||||||
"buy_hausse_bollinger_2": 0.0,
|
|
||||||
"buy_hausse_bollinger_2_enabled": false,
|
|
||||||
"buy_hausse_bollinger_enabled": false,
|
|
||||||
"buy_hausse_sma_percent": 1.05,
|
|
||||||
"buy_hausse_sma_percent_enabled": true,
|
|
||||||
"buy_hausse_volume": 12.7,
|
|
||||||
"buy_hausse_volume_enabled": true
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.092,
|
|
||||||
"29": 0.059,
|
|
||||||
"63": 0.036,
|
|
||||||
"182": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-07 20:42:50.719031+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4111",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_baisse_bollinger": 0.08,
|
|
||||||
"buy_baisse_bollinger_2": 0.03,
|
|
||||||
"buy_baisse_bollinger_2_enabled": true,
|
|
||||||
"buy_baisse_bollinger_enabled": true,
|
|
||||||
"buy_baisse_sma_percent": 1.0,
|
|
||||||
"buy_baisse_sma_percent_enabled": true,
|
|
||||||
"buy_baisse_volume": 32.0,
|
|
||||||
"buy_baisse_volume_enabled": false,
|
|
||||||
"buy_hausse_bollinger": 0.12,
|
|
||||||
"buy_hausse_bollinger_2": 0.01,
|
|
||||||
"buy_hausse_bollinger_2_enabled": true,
|
|
||||||
"buy_hausse_bollinger_enabled": true,
|
|
||||||
"buy_hausse_sma_percent": 1.01,
|
|
||||||
"buy_hausse_sma_percent_enabled": true,
|
|
||||||
"buy_hausse_volume": 12.7,
|
|
||||||
"buy_hausse_volume_enabled": true
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-06 21:26:35.306929+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,327 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick4111(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_hausse_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.095, space="buy")
|
|
||||||
buy_hausse_bollinger_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# Valeur de la deuxième h_condition bollinger avec h_condition sma200
|
|
||||||
buy_hausse_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
buy_hausse_bollinger_2_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
buy_hausse_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.098, space="buy")
|
|
||||||
buy_hausse_sma_percent_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_hausse_volume = DecimalParameter(0, 50, decimals=1, default=0, space="buy")
|
|
||||||
buy_hausse_volume_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_baisse_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.095, space="buy")
|
|
||||||
buy_baisse_bollinger_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# Valeur de la deuxième h_condition bollinger avec h_condition sma200
|
|
||||||
buy_baisse_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
buy_baisse_bollinger_2_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
buy_baisse_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.098, space="buy")
|
|
||||||
buy_baisse_sma_percent_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_baisse_volume = DecimalParameter(0, 50, decimals=1, default=0, space="buy")
|
|
||||||
buy_baisse_volume_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
|
|
||||||
# buy_hausse_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_hausse_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_hausse_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_hausse_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = 0.03
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.005
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_hausse_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
# 'volatility_dcp': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"Aaron": {
|
|
||||||
'aroonup': {'color': 'blue'},
|
|
||||||
'aroondown': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# Aroon, Aroon Oscillator
|
|
||||||
aroon = ta.AROON(dataframe)
|
|
||||||
dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
# dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
|
|
||||||
h_condition1 = np.where(value >= 1.04, True, False)
|
|
||||||
|
|
||||||
h_conditions = []
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if self.buy_hausse_bollinger_enabled.value:
|
|
||||||
h_conditions.append(dataframe['bb_width'] >= self.buy_hausse_bollinger.value)
|
|
||||||
|
|
||||||
h_conditions2 = []
|
|
||||||
if self.buy_hausse_bollinger_2_enabled.value:
|
|
||||||
h_conditions2.append(dataframe['bb_width'] >= self.buy_hausse_bollinger_2.value)
|
|
||||||
|
|
||||||
h_conditions_volume = []
|
|
||||||
h_condition_volume = True
|
|
||||||
if self.buy_hausse_volume_enabled.value:
|
|
||||||
h_conditions_volume.append(dataframe['volume'] >= self.buy_hausse_volume.value * 1000)
|
|
||||||
if h_conditions_volume:
|
|
||||||
h_condition_volume = np.where(h_conditions_volume, True, False)
|
|
||||||
|
|
||||||
h_condition2 = False
|
|
||||||
if h_conditions2:
|
|
||||||
h_condition2 = reduce(lambda x, y: x & y, h_conditions2) & h_condition1
|
|
||||||
|
|
||||||
h_condition_sma = False
|
|
||||||
h_conditions_sma = []
|
|
||||||
if self.buy_hausse_sma_percent_enabled.value:
|
|
||||||
#h_conditions_sma.append(dataframe['close'] <= dataframe['sma200'] * self.buy_hausse_sma_percent.value)
|
|
||||||
h_conditions_sma.append((dataframe['sma100'].shift(36) - dataframe['sma100']) / dataframe['sma100'] > self.buy_hausse_sma_percent.value)
|
|
||||||
if h_conditions_sma:
|
|
||||||
h_condition_sma = reduce(lambda x, y: x & y, h_conditions_sma)
|
|
||||||
|
|
||||||
b_condition1 = np.where(value >= 1.04, True, False)
|
|
||||||
|
|
||||||
b_conditions = []
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if self.buy_baisse_bollinger_enabled.value:
|
|
||||||
b_conditions.append(dataframe['bb_width'] >= self.buy_baisse_bollinger.value)
|
|
||||||
|
|
||||||
b_conditions2 = []
|
|
||||||
if self.buy_baisse_bollinger_2_enabled.value:
|
|
||||||
b_conditions2.append(dataframe['bb_width'] >= self.buy_baisse_bollinger_2.value)
|
|
||||||
|
|
||||||
b_conditions_volume = []
|
|
||||||
b_condition_volume = True
|
|
||||||
if self.buy_baisse_volume_enabled.value:
|
|
||||||
b_conditions_volume.append(dataframe['volume'] >= self.buy_baisse_volume.value * 1000)
|
|
||||||
if b_conditions_volume:
|
|
||||||
b_condition_volume = np.where(b_conditions_volume, True, False)
|
|
||||||
|
|
||||||
b_condition2 = False
|
|
||||||
if b_conditions2:
|
|
||||||
b_condition2 = reduce(lambda x, y: x & y, b_conditions2) & b_condition1
|
|
||||||
|
|
||||||
b_condition_sma = False
|
|
||||||
b_conditions_sma = []
|
|
||||||
if self.buy_baisse_sma_percent_enabled.value:
|
|
||||||
#b_conditions_sma.append(dataframe['close'] <= dataframe['sma200'] * self.buy_baisse_sma_percent.value)
|
|
||||||
b_conditions_sma.append((dataframe['sma100'].shift(36) - dataframe['sma100']) / dataframe['sma100'] > self.buy_baisse_sma_percent.value)
|
|
||||||
if b_conditions_sma:
|
|
||||||
b_condition_sma = reduce(lambda x, y: x & y, b_conditions_sma)
|
|
||||||
|
|
||||||
p = dataframe['sma500'].shift(60) - dataframe['sma500']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
hausse = np.where(value < 0, True, False)
|
|
||||||
|
|
||||||
if hausse:
|
|
||||||
if h_conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) < 0.025) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
h_condition_volume &
|
|
||||||
(
|
|
||||||
(
|
|
||||||
reduce(lambda x, y: x & y, h_conditions) |
|
|
||||||
(h_condition2 & h_condition_sma)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
else:
|
|
||||||
if b_conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) < 0.025) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
b_condition_volume &
|
|
||||||
(
|
|
||||||
(
|
|
||||||
reduce(lambda x, y: x & y, b_conditions) |
|
|
||||||
(b_condition2 & b_condition_sma)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(1) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.015)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4112",
|
|
||||||
"params": {
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.09,
|
|
||||||
"buy_bollinger_2": 0.08,
|
|
||||||
"buy_bollinger_2_enabled": false,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.98,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 18.9,
|
|
||||||
"buy_volume_enabled": false
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.096,
|
|
||||||
"30": 0.049,
|
|
||||||
"60": 0.032,
|
|
||||||
"120": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-07 21:14:40.877512+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,288 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick4112(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.095, space="buy")
|
|
||||||
buy_bollinger_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
buy_bollinger_2_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.098, space="buy")
|
|
||||||
buy_sma_percent_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = IntParameter(0, 50, default=0, space="buy")
|
|
||||||
buy_volume_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
|
|
||||||
buy_candel_percent = DecimalParameter(1.02, 1.10, decimals=2, default=1.04, space="buy")
|
|
||||||
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
'rsi': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"Pct": {
|
|
||||||
'percent': {'color': 'white'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
|
|
||||||
condition1 = np.where(value >= 1.04, True, False)
|
|
||||||
|
|
||||||
conditions = []
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if self.buy_bollinger_enabled.value:
|
|
||||||
conditions.append(dataframe['bb_width'] >= self.buy_bollinger.value)
|
|
||||||
|
|
||||||
conditions2 = []
|
|
||||||
if self.buy_bollinger_2_enabled.value:
|
|
||||||
conditions2.append(dataframe['bb_width'] >= self.buy_bollinger_2.value)
|
|
||||||
|
|
||||||
conditions_volume = []
|
|
||||||
condition_volume = True
|
|
||||||
if self.buy_volume_enabled.value:
|
|
||||||
conditions_volume.append(dataframe['volume'] >= self.buy_volume.value * 1000)
|
|
||||||
if conditions_volume:
|
|
||||||
condition_volume = np.where(conditions_volume, True, False)
|
|
||||||
|
|
||||||
condition2 = False
|
|
||||||
if conditions2:
|
|
||||||
condition2 = reduce(lambda x, y: x & y, conditions2) & condition1
|
|
||||||
|
|
||||||
condition_sma = False
|
|
||||||
conditions_sma = []
|
|
||||||
if self.buy_sma_percent_enabled.value:
|
|
||||||
# conditions_sma.append(dataframe['close'] <= dataframe['sma200'] * self.buy_sma_percent.value)
|
|
||||||
conditions_sma.append((dataframe['sma100'].shift(36) - dataframe['sma100']) / dataframe[
|
|
||||||
'sma100'] > self.buy_sma_percent.value)
|
|
||||||
if conditions_sma:
|
|
||||||
condition_sma = reduce(lambda x, y: x & y, conditions_sma)
|
|
||||||
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) < 0.025) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
condition_volume &
|
|
||||||
(reduce(lambda x, y: x & y, conditions)) #| (condition2 & condition_sma))
|
|
||||||
) | (
|
|
||||||
# condition2 &
|
|
||||||
(dataframe['close'] > dataframe['bb_upperband']) &
|
|
||||||
(dataframe['close'] > dataframe['open'] * 1.04) &
|
|
||||||
# (dataframe['bb_width'] < 0.2)
|
|
||||||
(dataframe['sma100'].shift(4) < dataframe['sma100'] * 1.01) &
|
|
||||||
(dataframe['sma100'].shift(4) > dataframe['sma100'] * 0.99)
|
|
||||||
# ) | (
|
|
||||||
# (
|
|
||||||
# (dataframe['percent']
|
|
||||||
# + dataframe['percent'].shift(1)
|
|
||||||
# + dataframe['percent'].shift(2)
|
|
||||||
# + dataframe['percent'].shift(3)
|
|
||||||
# + dataframe['percent'].shift(4) > 1.04) &
|
|
||||||
# (dataframe['close'] > dataframe['bb_upperband'])
|
|
||||||
# ) & (
|
|
||||||
# dataframe['close'] > dataframe['open'].shift(2) * 1.04
|
|
||||||
# )
|
|
||||||
)
|
|
||||||
,
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4113",
|
|
||||||
"params": {
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.09,
|
|
||||||
"buy_bollinger_2": 0.04,
|
|
||||||
"buy_bollinger_2_enabled": true,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.98,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 18.9,
|
|
||||||
"buy_volume_enabled": true
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.096,
|
|
||||||
"30": 0.049,
|
|
||||||
"60": 0.032,
|
|
||||||
"120": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-07 21:14:40.877512+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,281 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick4113(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.095, space="buy")
|
|
||||||
buy_bollinger_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
buy_bollinger_2_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.098, space="buy")
|
|
||||||
buy_sma_percent_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=0, space="buy")
|
|
||||||
buy_volume_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
'rsi': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
|
|
||||||
condition1 = np.where(value >= 1.04, True, False)
|
|
||||||
|
|
||||||
conditions = []
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if self.buy_bollinger_enabled.value:
|
|
||||||
conditions.append(dataframe['bb_width'] >= self.buy_bollinger.value)
|
|
||||||
|
|
||||||
conditions2 = []
|
|
||||||
if self.buy_bollinger_2_enabled.value:
|
|
||||||
conditions2.append(dataframe['bb_width'] >= self.buy_bollinger_2.value)
|
|
||||||
|
|
||||||
conditions_volume = []
|
|
||||||
condition_volume = True
|
|
||||||
if self.buy_volume_enabled.value:
|
|
||||||
conditions_volume.append(dataframe['volume'] >= self.buy_volume.value * 1000)
|
|
||||||
if conditions_volume:
|
|
||||||
condition_volume = np.where(conditions_volume, True, False)
|
|
||||||
|
|
||||||
condition2 = False
|
|
||||||
if conditions2:
|
|
||||||
condition2 = reduce(lambda x, y: x & y, conditions2) & condition1
|
|
||||||
|
|
||||||
condition_sma = False
|
|
||||||
conditions_sma = []
|
|
||||||
if self.buy_sma_percent_enabled.value:
|
|
||||||
# conditions_sma.append(dataframe['close'] <= dataframe['sma200'] * self.buy_sma_percent.value)
|
|
||||||
conditions_sma.append((dataframe['sma100'].shift(36) - dataframe['sma100']) / dataframe[
|
|
||||||
'sma100'] > self.buy_sma_percent.value)
|
|
||||||
if conditions_sma:
|
|
||||||
condition_sma = reduce(lambda x, y: x & y, conditions_sma)
|
|
||||||
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) < 0.025) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
condition_volume &
|
|
||||||
(reduce(lambda x, y: x & y, conditions) | (condition2 & condition_sma))
|
|
||||||
) | (
|
|
||||||
(dataframe['close'] > dataframe['bb_upperband']) &
|
|
||||||
(
|
|
||||||
(dataframe['close'] > dataframe['open'] * 1.04) |
|
|
||||||
(((dataframe['close'] - dataframe['bb_upperband']) / dataframe['bb_upperband']) >= 0.025)
|
|
||||||
) &
|
|
||||||
# (dataframe['bb_width'] < 0.2)
|
|
||||||
(dataframe['sma100'].shift(4) < dataframe['sma100'] * 1.01) &
|
|
||||||
(dataframe['sma100'].shift(4) > dataframe['sma100'] * 0.99)
|
|
||||||
# (dataframe['close'] < dataframe['open'] * 1.06)
|
|
||||||
# ) | (
|
|
||||||
# (
|
|
||||||
# (dataframe['close'] > dataframe['bb_upperband']) &
|
|
||||||
# (dataframe['close'].shift(1) > dataframe['bb_upperband'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) > dataframe['bb_upperband'].shift(2))
|
|
||||||
# # (dataframe['bb_width'] < 0.12)
|
|
||||||
# ) & (
|
|
||||||
# dataframe['close'] > dataframe['open'].shift(2) * 1.04
|
|
||||||
# )
|
|
||||||
)
|
|
||||||
,
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4114",
|
|
||||||
"params": {
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.09,
|
|
||||||
"buy_bollinger_2": 0.07,
|
|
||||||
"buy_bollinger_2_enabled": false,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 1.05,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 14.0,
|
|
||||||
"buy_volume_enabled": false
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.096,
|
|
||||||
"30": 0.049,
|
|
||||||
"60": 0.032,
|
|
||||||
"120": 0
|
|
||||||
}
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.31
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-11 13:07:34.278116+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,264 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick4114(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.095, space="buy")
|
|
||||||
buy_bollinger_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.065, space="buy")
|
|
||||||
buy_bollinger_2_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.098, space="buy")
|
|
||||||
buy_sma_percent_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=0, space="buy")
|
|
||||||
buy_volume_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
'rsi': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
|
|
||||||
condition1 = np.where(value >= 1.04, True, False)
|
|
||||||
|
|
||||||
conditions = []
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if self.buy_bollinger_enabled.value:
|
|
||||||
conditions.append(dataframe['bb_width'] >= self.buy_bollinger.value)
|
|
||||||
|
|
||||||
conditions2 = []
|
|
||||||
if self.buy_bollinger_2_enabled.value:
|
|
||||||
conditions2.append(dataframe['bb_width'] / dataframe['bb_width'].shift(5) >= 1.5) #self.buy_bollinger_2.value)
|
|
||||||
# conditions2.append(dataframe['close'] <= dataframe['sma100'] * 0.99)
|
|
||||||
|
|
||||||
conditions_volume = []
|
|
||||||
condition_volume = True
|
|
||||||
if self.buy_volume_enabled.value:
|
|
||||||
conditions_volume.append(dataframe['volume'] >= self.buy_volume.value * 1000)
|
|
||||||
if conditions_volume:
|
|
||||||
condition_volume = np.where(conditions_volume, True, False)
|
|
||||||
|
|
||||||
condition2 = False
|
|
||||||
if conditions2:
|
|
||||||
condition2 = reduce(lambda x, y: x & y, conditions2) & condition1
|
|
||||||
|
|
||||||
condition_sma = False
|
|
||||||
conditions_sma = []
|
|
||||||
if self.buy_sma_percent_enabled.value:
|
|
||||||
# conditions_sma.append(dataframe['close'] <= dataframe['sma200'] * self.buy_sma_percent.value)
|
|
||||||
conditions_sma.append((dataframe['sma100'].shift(36) - dataframe['sma100']) / dataframe['sma100'] > self.buy_sma_percent.value)
|
|
||||||
if conditions_sma:
|
|
||||||
condition_sma = reduce(lambda x, y: x & y, conditions_sma)
|
|
||||||
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) < 0.025) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
condition_volume &
|
|
||||||
(reduce(lambda x, y: x & y, conditions) | (condition2 & condition_sma))
|
|
||||||
# ) | (
|
|
||||||
)
|
|
||||||
,
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4115",
|
|
||||||
"params": {
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.09,
|
|
||||||
"buy_bollinger_2": 0.05,
|
|
||||||
"buy_bollinger_2_enabled": true,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.98,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 18.9,
|
|
||||||
"buy_volume_enabled": false
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.096,
|
|
||||||
"30": 0.049,
|
|
||||||
"60": 0.032,
|
|
||||||
"120": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-11 20:27:50.805367+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4115",
|
|
||||||
"params": {
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.09,
|
|
||||||
"buy_bollinger_2": 0.05,
|
|
||||||
"buy_bollinger_2_enabled": true,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.98,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 18.9,
|
|
||||||
"buy_volume_enabled": false
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.096,
|
|
||||||
"30": 0.049,
|
|
||||||
"60": 0.032,
|
|
||||||
"120": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-07 21:14:40.877512+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,282 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick4115(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.095, space="buy")
|
|
||||||
buy_bollinger_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
buy_bollinger_2_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.098, space="buy")
|
|
||||||
buy_sma_percent_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = IntParameter(0, 50, default=0, space="buy")
|
|
||||||
buy_volume_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
|
|
||||||
buy_candel_percent = DecimalParameter(1.02, 1.10, decimals=2, default=1.04, space="buy")
|
|
||||||
buy_candel_sma_percent = DecimalParameter(0.97, 1.04, decimals=2, default=0.99, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
'rsi': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"Pct": {
|
|
||||||
'percent': {'color': 'white'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
|
|
||||||
# condition1 = np.where(value >= 1.04, True, False)
|
|
||||||
|
|
||||||
conditions_bb_1 = []
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if self.buy_bollinger_enabled.value:
|
|
||||||
conditions_bb_1.append(dataframe['bb_width'] >= self.buy_bollinger.value)
|
|
||||||
|
|
||||||
condition1 = False
|
|
||||||
if conditions_bb_1:
|
|
||||||
condition1 = reduce(lambda x, y: x & y, conditions_bb_1)
|
|
||||||
|
|
||||||
conditions2_bb_2 = []
|
|
||||||
if self.buy_bollinger_2_enabled.value:
|
|
||||||
conditions2_bb_2.append(dataframe['bb_width'] >= self.buy_bollinger_2.value)
|
|
||||||
# conditions2_bb_2.append(dataframe['bb_width'] >= 0.03)
|
|
||||||
|
|
||||||
# conditions2_bb_2.append(dataframe['bb_width'] <= 0.1)
|
|
||||||
condition2 = False
|
|
||||||
if conditions2_bb_2:
|
|
||||||
condition2 = reduce(lambda x, y: x & y, conditions2_bb_2)
|
|
||||||
|
|
||||||
conditions_volume = []
|
|
||||||
condition_volume = True
|
|
||||||
if self.buy_volume_enabled.value:
|
|
||||||
conditions_volume.append(dataframe['volume'] >= self.buy_volume.value * 1000)
|
|
||||||
if conditions_volume:
|
|
||||||
condition_volume = np.where(conditions_volume, True, False)
|
|
||||||
|
|
||||||
condition_sma = False
|
|
||||||
conditions_sma = []
|
|
||||||
if self.buy_sma_percent_enabled.value:
|
|
||||||
# conditions_sma.append(dataframe['close'] <= dataframe['sma200'] * self.buy_sma_percent.value)
|
|
||||||
conditions_sma.append((dataframe['sma100'].shift(36) - dataframe['sma100']) / dataframe[
|
|
||||||
'sma100'] > self.buy_sma_percent.value)
|
|
||||||
if conditions_sma:
|
|
||||||
condition_sma = reduce(lambda x, y: x & y, conditions_sma)
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
condition_volume &
|
|
||||||
condition1
|
|
||||||
) | (
|
|
||||||
(dataframe['close'] > dataframe['bb_upperband']) &
|
|
||||||
(dataframe['close'] > dataframe['open'] * 1.04) &
|
|
||||||
(dataframe['close'] < dataframe['open'].shift(4) * 1.06) &
|
|
||||||
(dataframe['close'].shift(4) < dataframe['sma100'].shift(4) * 1.04)
|
|
||||||
)
|
|
||||||
,
|
|
||||||
'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe[
|
|
||||||
'bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
) | (
|
|
||||||
(dataframe['close'] * 1.04 < dataframe['open'])
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4116",
|
|
||||||
"params": {
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.06,
|
|
||||||
"buy_bollinger_2": 0.06,
|
|
||||||
"buy_candel_bb1": 2,
|
|
||||||
"buy_candel_percent": 1.05,
|
|
||||||
"buy_volume": 33
|
|
||||||
},
|
|
||||||
"sell": {
|
|
||||||
"sell_candel_percent": 1.1
|
|
||||||
},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.256,
|
|
||||||
"29": 0.076,
|
|
||||||
"52": 0.031,
|
|
||||||
"76": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.057
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-14 23:21:44.054656+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4116",
|
|
||||||
"params": {
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.03,
|
|
||||||
"buy_bollinger_2": 0.02,
|
|
||||||
"buy_bollinger_2_enabled": true,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_candel_percent": 1.02,
|
|
||||||
"buy_candel_sma_percent": 1.03,
|
|
||||||
"buy_sma_percent": 1.02,
|
|
||||||
"buy_sma_percent_enabled": true,
|
|
||||||
"buy_volume": 24,
|
|
||||||
"buy_volume_enabled": true
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.122,
|
|
||||||
"34": 0.092,
|
|
||||||
"62": 0.032,
|
|
||||||
"85": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.306
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-14 19:35:12.845988+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,255 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick4116(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.095, space="buy")
|
|
||||||
buy_candel_bb1 = IntParameter(0, 10, default=5, space="buy")
|
|
||||||
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = IntParameter(0, 50, default=0, space="buy")
|
|
||||||
|
|
||||||
buy_candel_percent = DecimalParameter(1.00, 1.10, decimals=2, default=1.04, space="buy")
|
|
||||||
sell_candel_percent = DecimalParameter(1.0, 1.10, decimals=2, default=1.04, space="sell")
|
|
||||||
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
# 'rsi': {'color': '#c58893'}
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"Pct": {
|
|
||||||
'percent': {'color': 'white'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
|
|
||||||
# condition1 = np.where(value >= 1.04, True, False)
|
|
||||||
|
|
||||||
conditions_bb_1 = []
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
conditions_bb_1.append(dataframe['bb_width'] >= self.buy_bollinger.value)
|
|
||||||
conditions_bb_1.append(dataframe['volume'] >= self.buy_volume.value * 1000)
|
|
||||||
conditions_bb_1.append(dataframe['close'] < dataframe['bb_lowerband'])
|
|
||||||
conditions_bb_1.append(
|
|
||||||
(dataframe['open'] - dataframe['bb_lowerband']) / (dataframe['bb_lowerband'] - dataframe['close']) > self.buy_candel_bb1.value
|
|
||||||
)
|
|
||||||
conditions_bb_1.append(dataframe['percent'] > -0.03)
|
|
||||||
condition1 = reduce(lambda x, y: x & y, conditions_bb_1)
|
|
||||||
|
|
||||||
conditions2_bb_2 = []
|
|
||||||
conditions2_bb_2.append(dataframe['bb_width'] <= self.buy_bollinger_2.value)
|
|
||||||
conditions2_bb_2.append(dataframe['close'] > dataframe['open'] * self.buy_candel_percent.value)
|
|
||||||
conditions2_bb_2.append(dataframe['close'] < dataframe['bb_upperband'])
|
|
||||||
condition2 = reduce(lambda x, y: x & y, conditions2_bb_2)
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
condition1
|
|
||||||
) | (
|
|
||||||
False &
|
|
||||||
(dataframe['bb_width'] > 0.065) &
|
|
||||||
(dataframe['close'] > dataframe['bb_upperband']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['bb_upperband'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(1) > dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) > dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'].shift(3) > dataframe['open'].shift(3)) &
|
|
||||||
(dataframe['close'] < dataframe['open'].shift(3) * 1.03) &
|
|
||||||
(dataframe['sma10'].shift(1) < dataframe['sma10'] * 1.01) &
|
|
||||||
(dataframe['sma10'].shift(1) > dataframe['sma10'] * 0.99)
|
|
||||||
) | (
|
|
||||||
condition2 &
|
|
||||||
# (dataframe['close'] > dataframe['open'] * 1.04) &
|
|
||||||
# (dataframe['close'] <= dataframe['open'] * 1.05) &
|
|
||||||
(dataframe['close'] > dataframe['sma10']) &
|
|
||||||
(dataframe['open'] < dataframe['sma10']) &
|
|
||||||
(dataframe['sma100'].shift(4) < dataframe['sma100'] * 1.01) &
|
|
||||||
(dataframe['sma100'].shift(4) > dataframe['sma100'] * 0.99)
|
|
||||||
# (dataframe['sma100'].shift(1) <= dataframe['sma100'])
|
|
||||||
) | (
|
|
||||||
False &
|
|
||||||
(dataframe['close'] > dataframe['bb_upperband']) &
|
|
||||||
(dataframe['close'] > dataframe['open'] * 1.02) &
|
|
||||||
(dataframe['close'] > dataframe['sma100']) &
|
|
||||||
(dataframe['open'] < dataframe['sma100']) &
|
|
||||||
(dataframe['close'].shift(1) > dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) > dataframe['open'].shift(2))
|
|
||||||
)
|
|
||||||
,
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
conditions_sell = []
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
conditions_sell.append(dataframe['close'] < dataframe['open'])
|
|
||||||
conditions_sell.append(dataframe['close'] < dataframe['bb_lowerband'])
|
|
||||||
conditions_sell.append(dataframe['close'].shift(1) < dataframe['open'].shift(1))
|
|
||||||
conditions_sell.append(dataframe['close'].shift(2) < dataframe['open'].shift(2))
|
|
||||||
conditions_sell.append(dataframe['close'] * self.sell_candel_percent.value < dataframe['open'].shift(2))
|
|
||||||
condition1 = reduce(lambda x, y: x & y, conditions_sell)
|
|
||||||
|
|
||||||
dataframe.loc[condition1, 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4117",
|
|
||||||
"params": {
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.09,
|
|
||||||
"buy_bollinger_2": 0.05,
|
|
||||||
"buy_bollinger_2_enabled": true,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.98,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 18.9,
|
|
||||||
"buy_volume_enabled": false
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.02,
|
|
||||||
"30": 0.015,
|
|
||||||
"60": 0.01,
|
|
||||||
"120": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-11 20:27:50.805367+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,319 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
from functools import reduce
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
from numpy.lib import math
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick4117(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.095, space="buy")
|
|
||||||
buy_bollinger_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
buy_bollinger_2_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.098, space="buy")
|
|
||||||
buy_sma_percent_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = IntParameter(0, 50, default=0, space="buy")
|
|
||||||
buy_volume_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
|
|
||||||
buy_candel_percent = DecimalParameter(1.02, 1.10, decimals=2, default=1.04, space="buy")
|
|
||||||
buy_candel_sma_percent = DecimalParameter(0.97, 1.04, decimals=2, default=0.99, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
# 'rsi': {'color': '#c58893'}
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"Pct": {
|
|
||||||
'percent': {'color': 'white'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
#dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
#dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
|
|
||||||
# condition1 = np.where(value >= 1.04, True, False)
|
|
||||||
|
|
||||||
conditions_bb_1 = [
|
|
||||||
dataframe['bb_width'] >= self.buy_bollinger.value,
|
|
||||||
dataframe['bb_width'] < 0.12,
|
|
||||||
dataframe['volume'] >= self.buy_volume.value * 1000,
|
|
||||||
dataframe['close'] < dataframe['bb_lowerband']]
|
|
||||||
condition1 = reduce(lambda x, y: x & y, conditions_bb_1)
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
False & condition1
|
|
||||||
) | (
|
|
||||||
False &
|
|
||||||
(dataframe['bb_width'] > 0.065) &
|
|
||||||
(dataframe['close'] > dataframe['bb_upperband']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['bb_upperband'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(1) > dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) > dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'].shift(3) > dataframe['open'].shift(3)) &
|
|
||||||
(dataframe['close'] < dataframe['open'].shift(3) * 1.03) &
|
|
||||||
(dataframe['sma10'].shift(1) < dataframe['sma10'] * 1.01) &
|
|
||||||
(dataframe['sma10'].shift(1) > dataframe['sma10'] * 0.99)
|
|
||||||
) | (
|
|
||||||
# (dataframe['bb_width'] >= 0.065) &
|
|
||||||
# (dataframe['bb_width'] <= 0.15) &
|
|
||||||
(dataframe['sma10'] < dataframe['sma100']) &
|
|
||||||
(dataframe['sma10'] / dataframe['sma50'] > 1.008) &
|
|
||||||
(dataframe['sma10'] / dataframe['sma50'] < 1.012) &
|
|
||||||
(dataframe['close'] > dataframe['bb_upperband'])
|
|
||||||
# (dataframe['close'] < dataframe['open'] * 1.025) &
|
|
||||||
# (dataframe['close'].shift(1) > dataframe['open'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) > dataframe['open'].shift(2)) &
|
|
||||||
# (dataframe['close'].shift(1) <= dataframe['bb_upperband'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) <= dataframe['bb_upperband'].shift(2)) &
|
|
||||||
# (dataframe['sma100'].shift(4) < dataframe['sma100'] * 1.01) &
|
|
||||||
# (dataframe['sma100'].shift(4) > dataframe['sma100'] * 0.99) &
|
|
||||||
# (dataframe['sma100'].shift(1) <= dataframe['sma100'])
|
|
||||||
) | (
|
|
||||||
False &
|
|
||||||
(dataframe['close'] > dataframe['bb_upperband']) &
|
|
||||||
(dataframe['close'] > dataframe['open'] * 1.02) &
|
|
||||||
(dataframe['close'] > dataframe['sma100']) &
|
|
||||||
(dataframe['open'] < dataframe['sma100']) &
|
|
||||||
(dataframe['close'].shift(1) > dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) > dataframe['open'].shift(2))
|
|
||||||
# ) | (
|
|
||||||
# (dataframe['close'] > dataframe['bb_upperband']) &
|
|
||||||
# ((dataframe['percent']
|
|
||||||
# + dataframe['percent'].shift(1)
|
|
||||||
# + dataframe['percent'].shift(2)
|
|
||||||
# + dataframe['percent'].shift(3)) > 0.015) &
|
|
||||||
# (dataframe['bb_width'] >= 0.03) &
|
|
||||||
# (dataframe['sma100'].shift(4) < dataframe['sma100'] * 1.01) &
|
|
||||||
# (dataframe['sma100'].shift(4) > dataframe['sma100'] * 0.99)
|
|
||||||
# ) | (
|
|
||||||
# (
|
|
||||||
# (dataframe['bb_width'] < 0.2) &
|
|
||||||
# # (dataframe['percent'] > 0.02) &
|
|
||||||
# ((dataframe['percent']
|
|
||||||
# + dataframe['percent'].shift(1)
|
|
||||||
# + dataframe['percent'].shift(2)
|
|
||||||
# + dataframe['percent'].shift(3)) > 0.015) &
|
|
||||||
# (dataframe['close'] > dataframe['bb_upperband'])
|
|
||||||
# # dataframe['bb_width'] >= 0.04
|
|
||||||
# )
|
|
||||||
)
|
|
||||||
,
|
|
||||||
'buy'] = 1
|
|
||||||
# else:
|
|
||||||
# if conditions2_bb_2:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (dataframe['close'] > dataframe['bb_upperband']) &
|
|
||||||
# reduce(lambda x, y: x & y,
|
|
||||||
# (dataframe['close'] > dataframe['open'] * self.buy_candel_percent.value)) &
|
|
||||||
# # (dataframe['bb_width'] < 0.2)
|
|
||||||
# reduce(lambda x, y: x & y,
|
|
||||||
# (dataframe['sma100'].shift(4) < dataframe[
|
|
||||||
# 'sma100'] * self.buy_candel_sma_percent.value + 0.02)) &
|
|
||||||
# reduce(lambda x, y: x & y,
|
|
||||||
# (dataframe['sma100'].shift(4) > dataframe[
|
|
||||||
# 'sma100'] * self.buy_candel_sma_percent.value))
|
|
||||||
# )
|
|
||||||
# , 'buy'] = 1
|
|
||||||
# else:
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2))
|
|
||||||
& (
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) # &
|
|
||||||
# (dataframe['close'] < dataframe['sma10'])
|
|
||||||
)
|
|
||||||
# (((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe[
|
|
||||||
# 'bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
) | (
|
|
||||||
(dataframe['close'] * 1.04 < dataframe['open'])
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4118",
|
|
||||||
"params": {
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.119,
|
|
||||||
"buy_candel_percent": 0.001,
|
|
||||||
"buy_volume": 17
|
|
||||||
},
|
|
||||||
"sell": {
|
|
||||||
"sell_candel_percent": 1.1
|
|
||||||
},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.146,
|
|
||||||
"31": 0.042,
|
|
||||||
"78": 0.021,
|
|
||||||
"186": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.337
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-16 19:58:16.082610+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4118",
|
|
||||||
"params": {
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.119,
|
|
||||||
"buy_candel_percent": 0.001,
|
|
||||||
"buy_volume": 17
|
|
||||||
},
|
|
||||||
"sell": {
|
|
||||||
"sell_candel_percent": 1.1
|
|
||||||
},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.146,
|
|
||||||
"31": 0.042,
|
|
||||||
"78": 0.021,
|
|
||||||
"186": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.337
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-16 19:58:16.082610+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4118",
|
|
||||||
"params": {
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.125,
|
|
||||||
"buy_candel_percent": 0.001,
|
|
||||||
"buy_volume": 38
|
|
||||||
},
|
|
||||||
"sell": {
|
|
||||||
"sell_candel_percent": 1.05
|
|
||||||
},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.22000000000000003,
|
|
||||||
"35": 0.083,
|
|
||||||
"91": 0.017,
|
|
||||||
"133": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.321
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-16 19:41:29.563783+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,250 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick4118(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.005, 0.125, decimals=3, default=0.03, space="buy")
|
|
||||||
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = IntParameter(0, 50, default=0, space="buy")
|
|
||||||
|
|
||||||
buy_candel_percent = DecimalParameter(0.001, 0.01, decimals=3, default=0.006, space="buy")
|
|
||||||
sell_candel_percent = DecimalParameter(1.0, 1.10, decimals=2, default=1.04, space="sell")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'min': {'color': 'green'},
|
|
||||||
'max': {'color': 'yellow'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
# 'rsi': {'color': '#c58893'}
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"Pct": {
|
|
||||||
'percent': {'color': 'white'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
# dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
# dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
conditions_bb_1 = [
|
|
||||||
dataframe['bb_width'] >= self.buy_bollinger.value,
|
|
||||||
dataframe['volume'] >= self.buy_volume.value * 1000,
|
|
||||||
dataframe['percent'].shift(3) >= self.buy_candel_percent.value
|
|
||||||
]
|
|
||||||
condition1 = reduce(lambda x, y: x & y, conditions_bb_1)
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# condition1 &
|
|
||||||
# (dataframe['min'] == dataframe['min'].shift(1)) &
|
|
||||||
# (dataframe['min'].shift(1) == dataframe['min'].shift(2)) &
|
|
||||||
# # courant est positif
|
|
||||||
# (dataframe['open'].shift(2) < dataframe['close'].shift(2)) &
|
|
||||||
# # previous cut BB
|
|
||||||
# (dataframe['close'].shift(3) < dataframe['bb_lowerband'].shift(3)) &
|
|
||||||
# # min
|
|
||||||
# (dataframe['min'].shift(2) * 1.001 >= dataframe['open'].shift(2))
|
|
||||||
# ), 'buy'] = 1
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
condition1 &
|
|
||||||
(dataframe['min'] == dataframe['min'].shift(1)) &
|
|
||||||
(dataframe['min'].shift(1) == dataframe['min'].shift(2)) &
|
|
||||||
(dataframe['min'].shift(2) == dataframe['min'].shift(3)) &
|
|
||||||
# courant est positif
|
|
||||||
(dataframe['open'].shift(3) < dataframe['close'].shift(3)) &
|
|
||||||
# previous cut BB
|
|
||||||
(dataframe['close'].shift(4) < dataframe['bb_lowerband'].shift(4)) &
|
|
||||||
# min
|
|
||||||
(dataframe['min'].shift(3) * 1.001 >= dataframe['open'].shift(3))
|
|
||||||
), 'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
conditions_sell = []
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
conditions_sell.append(dataframe['close'] < dataframe['open'])
|
|
||||||
conditions_sell.append(dataframe['close'] < dataframe['bb_lowerband'])
|
|
||||||
conditions_sell.append(dataframe['close'].shift(1) < dataframe['open'].shift(1))
|
|
||||||
conditions_sell.append(dataframe['close'].shift(2) < dataframe['open'].shift(2))
|
|
||||||
#conditions_sell.append(dataframe['close'] * self.sell_candel_percent.value < dataframe['open'].shift(2))
|
|
||||||
conditions_sell.append((((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02))
|
|
||||||
condition1 = reduce(lambda x, y: x & y, conditions_sell)
|
|
||||||
|
|
||||||
# (qtpylib.crossed_above(dataframe['close'], dataframe['ema800'])) &
|
|
||||||
|
|
||||||
dataframe.loc[condition1, 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4119",
|
|
||||||
"params": {
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.09,
|
|
||||||
"buy_bollinger_2": 0.08,
|
|
||||||
"buy_bollinger_2_enabled": false,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.98,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 18.9,
|
|
||||||
"buy_volume_enabled": true
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.096,
|
|
||||||
"30": 0.049,
|
|
||||||
"60": 0.032,
|
|
||||||
"120": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-07 21:14:40.877512+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,281 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick4119(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.095, space="buy")
|
|
||||||
buy_bollinger_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
buy_bollinger_2_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.098, space="buy")
|
|
||||||
buy_sma_percent_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=0, space="buy")
|
|
||||||
buy_volume_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'min': {'color': 'green'},
|
|
||||||
'max': {'color': 'yellow'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
|
|
||||||
condition1 = np.where(value >= 1.04, True, False)
|
|
||||||
|
|
||||||
conditions = []
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if self.buy_bollinger_enabled.value:
|
|
||||||
conditions.append(dataframe['bb_width'] >= self.buy_bollinger.value)
|
|
||||||
|
|
||||||
conditions2 = []
|
|
||||||
if self.buy_bollinger_2_enabled.value:
|
|
||||||
conditions2.append(dataframe['bb_width'] >= self.buy_bollinger_2.value)
|
|
||||||
|
|
||||||
conditions_volume = []
|
|
||||||
condition_volume = True
|
|
||||||
if self.buy_volume_enabled.value:
|
|
||||||
conditions_volume.append(dataframe['volume'] >= self.buy_volume.value * 1000)
|
|
||||||
if conditions_volume:
|
|
||||||
condition_volume = np.where(conditions_volume, True, False)
|
|
||||||
|
|
||||||
condition2 = False
|
|
||||||
if conditions2:
|
|
||||||
condition2 = reduce(lambda x, y: x & y, conditions2) & condition1
|
|
||||||
|
|
||||||
condition_sma = False
|
|
||||||
conditions_sma = []
|
|
||||||
if self.buy_sma_percent_enabled.value:
|
|
||||||
# conditions_sma.append(dataframe['close'] <= dataframe['sma200'] * self.buy_sma_percent.value)
|
|
||||||
conditions_sma.append((dataframe['sma100'].shift(36) - dataframe['sma100']) / dataframe['sma100'] > self.buy_sma_percent.value)
|
|
||||||
if conditions_sma:
|
|
||||||
condition_sma = reduce(lambda x, y: x & y, conditions_sma)
|
|
||||||
|
|
||||||
condition1 = reduce(lambda x, y: x & y, conditions)
|
|
||||||
|
|
||||||
conditions_bb_1 = [
|
|
||||||
dataframe['bb_width'] >= 0.119, # self.buy_bollinger.value,
|
|
||||||
dataframe['volume'] >= 17000, #self.buy_volume.value * 1000,
|
|
||||||
dataframe['percent'].shift(3) >= 0.001 #self.buy_candel_percent.value
|
|
||||||
]
|
|
||||||
condition_bb = reduce(lambda x, y: x & y, conditions_bb_1)
|
|
||||||
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
condition_volume &
|
|
||||||
(condition1 | (condition2 & condition_sma))
|
|
||||||
) | (
|
|
||||||
condition_bb &
|
|
||||||
(dataframe['min'] == dataframe['min'].shift(1)) &
|
|
||||||
(dataframe['min'].shift(1) == dataframe['min'].shift(2)) &
|
|
||||||
(dataframe['min'].shift(2) == dataframe['min'].shift(3)) &
|
|
||||||
# courant est positif
|
|
||||||
(dataframe['open'].shift(3) < dataframe['close'].shift(3)) &
|
|
||||||
# previous cut BB
|
|
||||||
(dataframe['close'].shift(4) < dataframe['bb_lowerband'].shift(4)) &
|
|
||||||
# min
|
|
||||||
(dataframe['min'].shift(3) * 1.001 >= dataframe['open'].shift(3))
|
|
||||||
), 'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick411_02",
|
|
||||||
"params": {
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.01,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.08,
|
|
||||||
"buy_sma_percent": 1.05
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.11,
|
|
||||||
"13": 0.055,
|
|
||||||
"51": 0.034,
|
|
||||||
"141": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -0.329
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-21 18:22:30.332701+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,246 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick411_02(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
'rsi': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
# current_profit: float, **kwargs):
|
|
||||||
# dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
# last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
# previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
# # print(last_candle)
|
|
||||||
# if current_profit > 0.05:
|
|
||||||
# if previous_last_candle['sma50'] > last_candle['sma50']:
|
|
||||||
# return 'ema_long_below_80'
|
|
||||||
# else:
|
|
||||||
# if current_profit > 0.005:
|
|
||||||
# if previous_last_candle['sma20'] > last_candle['sma20'] and (
|
|
||||||
# current_time - trade.open_date_utc).seconds >= 3200:
|
|
||||||
# return 'ema_long_below_80'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (
|
|
||||||
100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(
|
|
||||||
5).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=5)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
conditions = [
|
|
||||||
dataframe['bb_width'] >= self.buy_bollinger.value,
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']),
|
|
||||||
(dataframe['close'] < dataframe['sma100'] * self.buy_sma_percent.value)
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(reduce(lambda x, y: x & y, conditions))
|
|
||||||
)
|
|
||||||
,
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe[
|
|
||||||
'bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick411(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.07, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.97, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
'rsi': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(5).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=5)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
conditions = [
|
|
||||||
dataframe['bb_width'] >= self.buy_bollinger.value,
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']),
|
|
||||||
(dataframe['close'] < dataframe['sma100'] * self.buy_sma_percent.value)
|
|
||||||
]
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(reduce(lambda x, y: x & y, conditions))
|
|
||||||
)
|
|
||||||
,
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick412",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.096,
|
|
||||||
"30": 0.049,
|
|
||||||
"60": 0.032,
|
|
||||||
"120": 0
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.12,
|
|
||||||
"buy_bollinger_2": 0.04,
|
|
||||||
"buy_bollinger_2_enabled": true,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_candel": 0.07,
|
|
||||||
"buy_candel_enabled": true,
|
|
||||||
"buy_cross": 1.0,
|
|
||||||
"buy_cross_enabled": true,
|
|
||||||
"buy_sma_percent": 1.05,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 11.6,
|
|
||||||
"buy_volume_enabled": true
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-06 19:04:44.234113+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick412",
|
|
||||||
"params": {
|
|
||||||
"roi": {
|
|
||||||
"0": 0.5
|
|
||||||
},
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.04,
|
|
||||||
"buy_bollinger_2": 0.06,
|
|
||||||
"buy_bollinger_2_enabled": false,
|
|
||||||
"buy_bollinger_3": 0.04,
|
|
||||||
"buy_bollinger_3_enabled": true,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_candel": 0.06,
|
|
||||||
"buy_candel_enabled": true,
|
|
||||||
"buy_cross": 1.1,
|
|
||||||
"buy_cross_enabled": true,
|
|
||||||
"buy_sma_percent": 0.96,
|
|
||||||
"buy_sma_percent_enabled": true,
|
|
||||||
"buy_volume": 7.3,
|
|
||||||
"buy_volume_enabled": true
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-05 14:52:48.625435+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,282 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick412(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.095, space="buy")
|
|
||||||
buy_bollinger_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
buy_bollinger_2_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# pourcentage sma à dépasser
|
|
||||||
buy_sma_percent = DecimalParameter(0.95, 1.05, decimals=2, default=0.098, space="buy")
|
|
||||||
buy_sma_percent_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=0, space="buy")
|
|
||||||
buy_volume_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# Valeur maxi de la chandelle qui coupe la bande du bas
|
|
||||||
buy_candel = DecimalParameter(0, 0.10, decimals=2, default=0, space="buy")
|
|
||||||
buy_candel_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
|
|
||||||
buy_cross = DecimalParameter(0.8, 1.2, decimals=1, default=1, space="buy")
|
|
||||||
buy_cross_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma200_98': {'color': 'yellow'},
|
|
||||||
'sma200_95': {'color': 'cyan'},
|
|
||||||
# 'volatility_dcp': {'color': '#c58893'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"Aaron": {
|
|
||||||
'aroonup': {'color': 'blue'},
|
|
||||||
'aroondown': {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
# dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
value = 0
|
|
||||||
p = dataframe['close'].shift(20) / dataframe['close']
|
|
||||||
for k, v in p.iteritems():
|
|
||||||
# print(k, v)
|
|
||||||
value = v
|
|
||||||
|
|
||||||
condition1 = np.where(value >= 1.04, True, False)
|
|
||||||
|
|
||||||
conditions = []
|
|
||||||
# GUARDS AND TRENDS
|
|
||||||
if self.buy_bollinger_enabled.value:
|
|
||||||
conditions.append(dataframe['bb_width'] >= self.buy_bollinger.value)
|
|
||||||
|
|
||||||
conditions2 = []
|
|
||||||
if self.buy_bollinger_2_enabled.value:
|
|
||||||
conditions2.append(dataframe['bb_width'] >= self.buy_bollinger_2.value)
|
|
||||||
|
|
||||||
conditions_volume = []
|
|
||||||
condition_volume = True
|
|
||||||
if self.buy_volume_enabled.value:
|
|
||||||
conditions_volume.append(dataframe['volume'] >= self.buy_volume.value * 1000)
|
|
||||||
if conditions_volume:
|
|
||||||
condition_volume = np.where(conditions_volume, True, False)
|
|
||||||
|
|
||||||
condition2 = False
|
|
||||||
if conditions2:
|
|
||||||
condition2 = reduce(lambda x, y: x & y, conditions2) & condition1
|
|
||||||
|
|
||||||
condition_sma = False
|
|
||||||
conditions_sma = []
|
|
||||||
if self.buy_sma_percent_enabled.value:
|
|
||||||
#conditions_sma.append(dataframe['close'] <= dataframe['sma200'] * self.buy_sma_percent.value)
|
|
||||||
conditions_sma.append((dataframe['sma100'].shift(36) - dataframe['sma100']) / dataframe['sma100'] > self.buy_sma_percent.value)
|
|
||||||
if conditions_sma:
|
|
||||||
condition_sma = reduce(lambda x, y: x & y, conditions_sma)
|
|
||||||
|
|
||||||
condition_candel = True
|
|
||||||
conditions_candel = []
|
|
||||||
if self.buy_candel_enabled.value:
|
|
||||||
conditions_candel.append((dataframe['open'] - dataframe['close']) / dataframe['close'] <= self.buy_candel.value)
|
|
||||||
if conditions_candel:
|
|
||||||
condition_candel = reduce(lambda x, y: x & y, conditions_candel)
|
|
||||||
|
|
||||||
condition_cross = True
|
|
||||||
conditions_cross = []
|
|
||||||
if self.buy_cross_enabled.value:
|
|
||||||
conditions_cross.append(dataframe['close'] < dataframe['bb_lowerband'] * self.buy_cross.value)
|
|
||||||
if conditions_cross:
|
|
||||||
condition_cross = reduce(lambda x, y: x & y, conditions_cross)
|
|
||||||
|
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
condition_cross &
|
|
||||||
condition_candel &
|
|
||||||
condition_volume &
|
|
||||||
(
|
|
||||||
(
|
|
||||||
reduce(lambda x, y: x & y, conditions) |
|
|
||||||
(condition2 & condition_sma)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(1) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.015)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
),
|
|
||||||
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4120",
|
|
||||||
"params": {
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1.0
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.09,
|
|
||||||
"buy_bollinger_2": 0.08,
|
|
||||||
"buy_bollinger_2_enabled": false,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.98,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 18.9,
|
|
||||||
"buy_volume_enabled": true
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.096,
|
|
||||||
"30": 0.049,
|
|
||||||
"60": 0.032,
|
|
||||||
"120": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-07 21:14:40.877512+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,281 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick4120(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.095, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
buy_min = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
buy_percent = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=18, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -0.1
|
|
||||||
trailing_stop = True
|
|
||||||
trailing_stop_positive = 0.001
|
|
||||||
trailing_stop_positive_offset = 0.0175 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'white'},
|
|
||||||
'bb_upperband': {'color': 'white'},
|
|
||||||
'sma100': {'color': 'green'},
|
|
||||||
'sma500': {'color': 'blue'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'min': {'color': 'green'},
|
|
||||||
'max': {'color': 'yellow'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'rolling': {'color': 'white'},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['sma21'] = ta.SMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (100 * (dataframe["close"].shift(3) - dataframe["bb_lowerband"].shift(3)) / dataframe["bb_lowerband"].shift(3)).rolling(20).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=20)
|
|
||||||
|
|
||||||
# print(dataframe["rolling"].tolist())
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
# count = 0
|
|
||||||
# for i in range(20):
|
|
||||||
# print("i=", i, " count=", count)
|
|
||||||
# c = [(dataframe['close'].shift(i) <= dataframe['bb_lowerband'].shift(i))]
|
|
||||||
# value = reduce(lambda x, y: x & y, c)
|
|
||||||
|
|
||||||
# for k, v in value.iteritems():
|
|
||||||
# print("i=", i, " count=", count, " v=", v)
|
|
||||||
# if v:
|
|
||||||
# count = count + 1
|
|
||||||
# for i in range(20):
|
|
||||||
# print("i=", i)
|
|
||||||
# a = 1 if bool(dataframe['close'].shift(i) <= dataframe['bb_lowerband'].shift(i)) else 0
|
|
||||||
# print(a)
|
|
||||||
|
|
||||||
conditions_bb_1 = [
|
|
||||||
(dataframe['close'].shift(2) < dataframe['bb_lowerband'].shift(2)),
|
|
||||||
(dataframe['bb_width'].shift(2) >= 0.09), # & (dataframe['rolling'] < 2))
|
|
||||||
(dataframe['volume'].shift(2) >= self.buy_volume.value * 1000),
|
|
||||||
(dataframe['open'] < dataframe['close'])
|
|
||||||
# (
|
|
||||||
# (dataframe['bb_width'] >= 0.119) |
|
|
||||||
# (dataframe['open'].shift(3) < dataframe['close'].shift(3)) &
|
|
||||||
# ((dataframe['bb_width'].shift(3) >= 0.0) & (dataframe['bb_rolling'].shift(3) < 1))
|
|
||||||
|
|
||||||
# ((dataframe['bb_width'] >= 0.08) & (dataframe['rolling'] < 2))
|
|
||||||
# ((dataframe['bb_width'] >= 0.03) & (count >= 6)) |
|
|
||||||
# (
|
|
||||||
# (dataframe['bb_width'] >= self.buy_bollinger_2.value) &
|
|
||||||
# (dataframe['close'] / dataframe['min'] <= self.buy_min.value)
|
|
||||||
# )
|
|
||||||
# ), # self.buy_bollinger.value,
|
|
||||||
# dataframe['volume'] >= self.buy_volume.value * 1000,
|
|
||||||
# dataframe['percent'].shift(3) >= self.buy_percent.value
|
|
||||||
]
|
|
||||||
condition_bb = reduce(lambda x, y: x & y, conditions_bb_1)
|
|
||||||
conditions_bb_2 = [
|
|
||||||
(dataframe['close'].shift(3) < dataframe['bb_lowerband'].shift(3)),
|
|
||||||
(dataframe['bb_width'].shift(3) >= 0.09), # & (dataframe['rolling'] < 2))
|
|
||||||
(dataframe['volume'].shift(3) >= self.buy_volume.value * 1000),
|
|
||||||
(dataframe['open'] < dataframe['close'])
|
|
||||||
]
|
|
||||||
condition_bb2 = reduce(lambda x, y: x & y, conditions_bb_2)
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(condition_bb | condition_bb2) &
|
|
||||||
(dataframe['min'] == dataframe['min'].shift(1)) &
|
|
||||||
(dataframe['min'].shift(1) == dataframe['min'].shift(2)) &
|
|
||||||
(dataframe['min'].shift(2) == dataframe['min'].shift(3))
|
|
||||||
# # courant est positif
|
|
||||||
# (dataframe['open'].shift(3) < dataframe['close'].shift(3)) &
|
|
||||||
# # previous cut BB
|
|
||||||
# (dataframe['close'].shift(4) < dataframe['bb_lowerband'].shift(4))
|
|
||||||
# min
|
|
||||||
# (dataframe['min'].shift(3) * 1.001 >= dataframe['open'].shift(3))
|
|
||||||
), 'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"strategy_name": "StrategyPierrick4121",
|
|
||||||
"params": {
|
|
||||||
"stoploss": {
|
|
||||||
"stoploss": -1
|
|
||||||
},
|
|
||||||
"trailing": {
|
|
||||||
"trailing_stop": true,
|
|
||||||
"trailing_stop_positive": 0.001,
|
|
||||||
"trailing_stop_positive_offset": 0.0175,
|
|
||||||
"trailing_only_offset_is_reached": true
|
|
||||||
},
|
|
||||||
"buy": {
|
|
||||||
"buy_bollinger": 0.12,
|
|
||||||
"buy_bollinger_2": 0.08,
|
|
||||||
"buy_bollinger_2_enabled": false,
|
|
||||||
"buy_bollinger_enabled": true,
|
|
||||||
"buy_sma_percent": 0.98,
|
|
||||||
"buy_sma_percent_enabled": false,
|
|
||||||
"buy_volume": 18.9,
|
|
||||||
"buy_volume_enabled": true
|
|
||||||
},
|
|
||||||
"sell": {},
|
|
||||||
"protection": {},
|
|
||||||
"roi": {
|
|
||||||
"0": 0.096,
|
|
||||||
"30": 0.049,
|
|
||||||
"60": 0.032,
|
|
||||||
"120": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ft_stratparam_v": 1,
|
|
||||||
"export_time": "2021-12-18 12:33:59.714495+00:00"
|
|
||||||
}
|
|
||||||
@@ -1,286 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick4121(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.05, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
# buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
# buy_min = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# buy_percent = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=18, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.02
|
|
||||||
trailing_stop_positive_offset = 0.0275 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'red'},
|
|
||||||
'bb_upperband': {'color': 'green'},
|
|
||||||
'sma100': {'color': 'blue'},
|
|
||||||
# 'sma500': {'color': 'blue'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'min': {'color': 'white'},
|
|
||||||
'max': {'color': 'white'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
# print(last_candle)
|
|
||||||
# Above 20% profit, sell when rsi < 80
|
|
||||||
if (last_candle['bb_upperband'] > last_candle['max']) & (previous_last_candle['sma20'] > last_candle['sma20']):
|
|
||||||
return 'over_bb_band'
|
|
||||||
|
|
||||||
# # Between 2% and 10%, sell if EMA-long above EMA-short
|
|
||||||
if 0.05 < current_profit < 0.1:
|
|
||||||
if previous_last_candle['sma20'] > last_candle['sma20'] and (current_time - trade.open_date_utc).seconds >= 3600 * 3:
|
|
||||||
return 'profit_3h'
|
|
||||||
|
|
||||||
# Sell any positions at a loss if they are held for more than one day.
|
|
||||||
if 0.1 > current_profit > 0.0 and previous_last_candle['sma20'] > last_candle['sma20'] \
|
|
||||||
and (current_time - trade.open_date_utc).seconds >= 3600 * 5:
|
|
||||||
return 'profit_5h'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (
|
|
||||||
100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(
|
|
||||||
3).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=10)
|
|
||||||
dataframe['bb_buy'] = (dataframe['min'] + (dataframe['max'] - dataframe['min']) / 3)
|
|
||||||
# print(dataframe["rolling"].tolist())
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
# condition_bb_rolling = [
|
|
||||||
# (dataframe['bb_width'].shift(3) >= self.buy_bollinger.value),
|
|
||||||
# (dataframe['volume'].shift(3) * dataframe['close'] / 1000 >= 100), # self.buy_volume.value * 1000),
|
|
||||||
# (dataframe['open'] < dataframe['close']),
|
|
||||||
# (dataframe['open'] * 1.02 < dataframe['close']),
|
|
||||||
# # (dataframe['close'] <= dataframe['sma100'] * 1.01),
|
|
||||||
# (dataframe['close'].shift(1) <= dataframe['bb_lowerband'].shift(1)) |
|
|
||||||
# (dataframe['close'].shift(2) <= dataframe['bb_lowerband'].shift(2)) |
|
|
||||||
# (dataframe['close'].shift(3) <= dataframe['bb_lowerband'].shift(3)),
|
|
||||||
# ]
|
|
||||||
# condition_bb_rolling2 = reduce(lambda x, y: x & y, condition_bb_rolling)
|
|
||||||
#
|
|
||||||
# condition_bb_rolling_inf = [
|
|
||||||
# (dataframe['bb_width'] >= 0.04),
|
|
||||||
# (dataframe['volume'] * dataframe['close'] / 1000 >= 100), #>= self.buy_volume.value * 1000),
|
|
||||||
# (dataframe['open'] < dataframe['close']),
|
|
||||||
# (dataframe['open'] * 1.02 < dataframe['close']),
|
|
||||||
# # (dataframe['close'] <= dataframe['min'] * 1.01),
|
|
||||||
# (dataframe['close'] * 1.04) <= dataframe['sma100'],
|
|
||||||
# (dataframe['close'].shift(1) <= dataframe['bb_lowerband'].shift(1))
|
|
||||||
# ]
|
|
||||||
# condition_bb_rolling_inf2 = reduce(lambda x, y: x & y, condition_bb_rolling_inf)
|
|
||||||
|
|
||||||
condition_bb_rolling = [
|
|
||||||
# dataframe['bb_width'] >= self.buy_bollinger.value,
|
|
||||||
# (dataframe['open'] < dataframe['close']),
|
|
||||||
(dataframe['bb_rolling_min'].shift(5) <= -6),
|
|
||||||
(dataframe['bb_rolling_min'].shift(5) == dataframe['bb_rolling'].shift(5)),
|
|
||||||
# (dataframe['sma100'].shift(1) <= dataframe['sma100']),
|
|
||||||
(dataframe['close'].shift(5) < dataframe['min'].shift(5) + (
|
|
||||||
dataframe['max'].shift(5) - dataframe['min'].shift(5)) / 3),
|
|
||||||
(dataframe['min'].shift(5) == dataframe['min'])
|
|
||||||
]
|
|
||||||
condition_bb_rolling2 = reduce(lambda x, y: x & y, condition_bb_rolling)
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
condition_bb_rolling2 # | condition_bb_rolling_inf2
|
|
||||||
|
|
||||||
), 'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (dataframe['close'] < dataframe['open']) &
|
|
||||||
# (dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
# (dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
# (((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# # (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
# ), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,281 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick41211(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.025, 0.125, decimals=2, default=0.065, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
# buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
# buy_min = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# buy_percent = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=18, space="buy")
|
|
||||||
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.02
|
|
||||||
trailing_stop_positive_offset = 0.0275 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'red'},
|
|
||||||
'bb_upperband': {'color': 'green'},
|
|
||||||
'sma100': {'color': 'blue'},
|
|
||||||
'sma500': {'color': 'pink'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'min': {'color': 'white'},
|
|
||||||
'max': {'color': 'white'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"ADX": {
|
|
||||||
'adx': {'color': 'white'},
|
|
||||||
'minus_dm': {'color': 'blue'},
|
|
||||||
'plus_dm': {'color': 'red'}
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
# print(last_candle)
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& (last_candle['bb_upperband'] > last_candle['max']) \
|
|
||||||
& (previous_last_candle['sma20'] > last_candle['sma20']):
|
|
||||||
return 'over_bb_band_sma20_desc'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& (last_candle['close'] < last_candle['open']) \
|
|
||||||
& (previous_last_candle['bb_upperband'] < previous_last_candle['close']) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600):
|
|
||||||
# & (previous_last_candle['sma100'] > last_candle['sma100']) \
|
|
||||||
return 'close_over_bb_band_sma100_desc'
|
|
||||||
|
|
||||||
if 0.05 < current_profit < 0.1:
|
|
||||||
if (
|
|
||||||
(previous_last_candle['sma10'] > last_candle['sma10']) &
|
|
||||||
(current_time - trade.open_date_utc).seconds >= 3600 * 3
|
|
||||||
) | (
|
|
||||||
(current_time - trade.open_date_utc).seconds >= 3600 * 6
|
|
||||||
):
|
|
||||||
return 'profit_3h_sma10_desc'
|
|
||||||
|
|
||||||
if (0.1 > current_profit > 0.0) \
|
|
||||||
& (previous_last_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 5):
|
|
||||||
return 'profit_5h_sma20_desc'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # Plus Directional Indicator / Movement
|
|
||||||
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (
|
|
||||||
100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(
|
|
||||||
3).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=10)
|
|
||||||
dataframe['bb_buy'] = (dataframe['min'] + (dataframe['max'] - dataframe['min']) / 3)
|
|
||||||
# print(dataframe["rolling"].tolist())
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
step = 3
|
|
||||||
bb_rolling_max = -6
|
|
||||||
condition_bb_rolling = [
|
|
||||||
# dataframe['bb_width'] >= self.buy_bollinger.value,
|
|
||||||
(dataframe['close'] < dataframe['sma10']),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) <= bb_rolling_max),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) == dataframe['bb_rolling'].shift(step)),
|
|
||||||
# (dataframe['sma100'].shift(1) <= dataframe['sma100']),
|
|
||||||
(dataframe['close'].shift(step) < dataframe['min'].shift(step) + (
|
|
||||||
dataframe['max'].shift(step) - dataframe['min'].shift(step)) / 3),
|
|
||||||
(dataframe['min'].shift(step) == dataframe['min'])
|
|
||||||
]
|
|
||||||
condition_bb_rolling2 = reduce(lambda x, y: x & y, condition_bb_rolling)
|
|
||||||
|
|
||||||
# conditions = [
|
|
||||||
# dataframe['bb_width'] >= 0.09, #self.buy_bollinger.value,
|
|
||||||
# (dataframe['close'] < dataframe['bb_lowerband']),
|
|
||||||
# (dataframe['close'] < dataframe['sma100'] * 0.99) #self.buy_sma_percent.value)
|
|
||||||
# ]
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
condition_bb_rolling2 #| (reduce(lambda x, y: x & y, conditions))
|
|
||||||
), 'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (dataframe['close'] < dataframe['open']) &
|
|
||||||
# (dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
# (dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
# (((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# # (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
# ), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,338 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick41212(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.00, 0.18, decimals=2, default=0.065, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
# buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
# buy_min = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# buy_percent = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=18, space="buy")
|
|
||||||
|
|
||||||
buy_step = IntParameter(1, 8, default=3, space="buy")
|
|
||||||
buy_rolling = IntParameter(-20, 0, default=-6, space="buy")
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.02
|
|
||||||
trailing_stop_positive_offset = 0.0275 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'red'},
|
|
||||||
'bb_upperband': {'color': 'green'},
|
|
||||||
'sma100': {'color': 'blue'},
|
|
||||||
'sma500': {'color': 'pink'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'min': {'color': 'white'},
|
|
||||||
'max': {'color': 'white'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
# "ADX": {
|
|
||||||
# 'adx': {'color': 'white'},
|
|
||||||
# 'minus_dm': {'color': 'blue'},
|
|
||||||
# 'plus_dm': {'color': 'red'}
|
|
||||||
# },
|
|
||||||
"Rsi": {
|
|
||||||
'rsi': {'color': 'pink'},
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
**kwargs) -> float:
|
|
||||||
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
# # print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
|
|
||||||
# if current_candle['bb_width'] > 0.05:
|
|
||||||
# print("use more stake", pair, " ", proposed_stake * 2)
|
|
||||||
# return min(max_stake, proposed_stake * 2)
|
|
||||||
#
|
|
||||||
# if current_candle['bb_width'] > 0.035:
|
|
||||||
# print("use more stake", pair, " ", proposed_stake * 1.5)
|
|
||||||
# return min(max_stake, proposed_stake * 1.5)
|
|
||||||
|
|
||||||
# if current_candle['bb_width'] < 0.020:
|
|
||||||
# print("use less stake", pair, " ", proposed_stake / 2)
|
|
||||||
# return min(max_stake, proposed_stake / 2)
|
|
||||||
# if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# return max_stake
|
|
||||||
# else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
|
|
||||||
|
|
||||||
# Use default stake amount.
|
|
||||||
return proposed_stake
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
previous_5_candle = dataframe.iloc[-5].squeeze()
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 2) \
|
|
||||||
& (previous_5_candle['sma20'] > last_candle['sma20']):
|
|
||||||
# & (last_candle['bb_upperband'] > last_candle['max']) \
|
|
||||||
print("over_bb_band_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_bb_band_sma20_desc'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& (last_candle['rsi'] > 75):
|
|
||||||
print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_rsi'
|
|
||||||
|
|
||||||
# description trade
|
|
||||||
# Trade(id=0, pair=CAKE/USDT, amount=4.19815281, open_rate=11.91000000, open_since=2021-12-22 17:55:00)
|
|
||||||
# print(last_candle)
|
|
||||||
# if (current_profit > 0) \
|
|
||||||
# & (last_candle['close'] < last_candle['open']) \
|
|
||||||
# & (previous_last_candle['bb_upperband'] < previous_last_candle['close']) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600) \
|
|
||||||
# & ((previous_last_candle['sma10'] - last_candle['sma10']) / last_candle['sma10'] < 0.1):
|
|
||||||
# # & (previous_last_candle['sma100'] > last_candle['sma100']) \
|
|
||||||
# print("close_over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'close_over_bb_band_sma10_desc'
|
|
||||||
if 0.05 < current_profit < 0.1:
|
|
||||||
if (
|
|
||||||
(previous_last_candle['sma10'] > last_candle['sma10']) &
|
|
||||||
(current_time - trade.open_date_utc).seconds >= 3600 * 3
|
|
||||||
) | (
|
|
||||||
(current_time - trade.open_date_utc).seconds >= 3600 * 6
|
|
||||||
):
|
|
||||||
print("profit_3h_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'profit_3h_sma10_desc'
|
|
||||||
|
|
||||||
if (0 < current_profit < 0.1) \
|
|
||||||
& (previous_last_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 5):
|
|
||||||
print("profit_5h_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'profit_5h_sma20_desc'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
#
|
|
||||||
# # Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (
|
|
||||||
100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(
|
|
||||||
3).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=10)
|
|
||||||
dataframe['bb_buy'] = (dataframe['min'] + (dataframe['max'] - dataframe['min']) / 3)
|
|
||||||
# print(dataframe["rolling"].tolist())
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
step = self.buy_step.value
|
|
||||||
bb_rolling_max = self.buy_rolling.value
|
|
||||||
condition_bb_rolling = [
|
|
||||||
# dataframe['bb_width'] >= self.buy_bollinger.value,
|
|
||||||
# (100 * (dataframe['sma100'].shift(12) - dataframe['sma100']) / dataframe['sma100']) < 0.1,
|
|
||||||
(dataframe['close'] < dataframe['sma10']),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) <= bb_rolling_max),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) == dataframe['bb_rolling'].shift(step)),
|
|
||||||
# (dataframe['sma100'].shift(1) <= dataframe['sma100']),
|
|
||||||
#(100 * ((dataframe['sma20'].shift(1) - dataframe['sma20']) / dataframe['sma20']) < 0.1),
|
|
||||||
(dataframe['close'].shift(step) < dataframe['min'].shift(step) + (
|
|
||||||
dataframe['max'].shift(step) - dataframe['min'].shift(step)) / 3),
|
|
||||||
(dataframe['min'].shift(step) == dataframe['min'])
|
|
||||||
]
|
|
||||||
condition_bb_rolling2 = reduce(lambda x, y: x & y, condition_bb_rolling)
|
|
||||||
|
|
||||||
conditions = [
|
|
||||||
dataframe['bb_width'] >= 0.065, #self.buy_bollinger.value,
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband'])
|
|
||||||
]
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(
|
|
||||||
condition_bb_rolling2
|
|
||||||
# | (reduce(lambda x, y: x & y, conditions))
|
|
||||||
) & (
|
|
||||||
dataframe['volume'] > 0
|
|
||||||
)
|
|
||||||
), 'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,347 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick41213(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.00, 0.18, decimals=2, default=0.065, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
# buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
# buy_min = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# buy_percent = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=18, space="buy")
|
|
||||||
|
|
||||||
buy_step = IntParameter(1, 8, default=3, space="buy")
|
|
||||||
buy_rolling = IntParameter(-20, 0, default=-6, space="buy")
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.02
|
|
||||||
trailing_stop_positive_offset = 0.0275 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'red'},
|
|
||||||
'bb_upperband': {'color': 'green'},
|
|
||||||
'sma100': {'color': 'blue'},
|
|
||||||
'sma500': {'color': 'pink'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'min': {'color': 'white'},
|
|
||||||
'max': {'color': 'white'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
"Rsi": {
|
|
||||||
'rsi': {'color': 'pink'},
|
|
||||||
},
|
|
||||||
# "ADX": {
|
|
||||||
# 'adx': {'color': 'white'},
|
|
||||||
# 'minus_dm': {'color': 'blue'},
|
|
||||||
# 'plus_dm': {'color': 'red'}
|
|
||||||
# },
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
**kwargs) -> float:
|
|
||||||
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
# print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
|
|
||||||
# if current_candle['bb_width'] > 0.05:
|
|
||||||
# print("use more stake", pair, " ", proposed_stake * 2)
|
|
||||||
# return min(max_stake, proposed_stake * 2)
|
|
||||||
#
|
|
||||||
# if current_candle['bb_width'] > 0.035:
|
|
||||||
# print("use more stake", pair, " ", proposed_stake * 1.5)
|
|
||||||
# return min(max_stake, proposed_stake * 1.5)
|
|
||||||
|
|
||||||
# if current_candle['bb_width'] < 0.020:
|
|
||||||
# print("use less stake", pair, " ", proposed_stake / 2)
|
|
||||||
# return min(max_stake, proposed_stake / 2)
|
|
||||||
# if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# return max_stake
|
|
||||||
# else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
|
|
||||||
|
|
||||||
# Use default stake amount.
|
|
||||||
return proposed_stake
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
previous_5_candle = dataframe.iloc[-5].squeeze()
|
|
||||||
|
|
||||||
# description trade
|
|
||||||
# Trade(id=0, pair=CAKE/USDT, amount=4.19815281, open_rate=11.91000000, open_since=2021-12-22 17:55:00)
|
|
||||||
# print(last_candle)
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 2) \
|
|
||||||
& (previous_5_candle['sma20'] > last_candle['sma20']):
|
|
||||||
# & (last_candle['bb_upperband'] > last_candle['max']) \
|
|
||||||
print("over_bb_band_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_bb_band_sma20_desc'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& (last_candle['rsi'] > 80):
|
|
||||||
print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_rsi'
|
|
||||||
|
|
||||||
# if (current_profit > 0) \
|
|
||||||
# & (last_candle['close'] < last_candle['open']) \
|
|
||||||
# & (previous_last_candle['bb_upperband'] < previous_last_candle['close']) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600) \
|
|
||||||
# & ((previous_last_candle['sma10'] - last_candle['sma10']) / last_candle['sma10'] < 0.1):
|
|
||||||
# # & (previous_last_candle['sma100'] > last_candle['sma100']) \
|
|
||||||
# print("close_over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'close_over_bb_band_sma10_desc'
|
|
||||||
|
|
||||||
if 0.05 < current_profit < 0.1:
|
|
||||||
if (
|
|
||||||
(previous_last_candle['sma10'] > last_candle['sma10']) &
|
|
||||||
(current_time - trade.open_date_utc).seconds >= 3600 * 3
|
|
||||||
) | (
|
|
||||||
(current_time - trade.open_date_utc).seconds >= 3600 * 6
|
|
||||||
):
|
|
||||||
print("profit_3h_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'profit_3h_sma10_desc'
|
|
||||||
|
|
||||||
if (0 < current_profit < 0.1) \
|
|
||||||
& (previous_last_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 5):
|
|
||||||
print("profit_5h_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'profit_5h_sma20_desc'
|
|
||||||
|
|
||||||
# if (current_profit < -0.025) \
|
|
||||||
# & (previous_last_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 3):
|
|
||||||
# print("stop_loss_3h", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'stop_loss_3h'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
#
|
|
||||||
# # Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (
|
|
||||||
100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(
|
|
||||||
3).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=10)
|
|
||||||
dataframe['bb_buy'] = (dataframe['min'] + (dataframe['max'] - dataframe['min']) / 3)
|
|
||||||
# print(dataframe["rolling"].tolist())
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
step = self.buy_step.value
|
|
||||||
bb_rolling_max = self.buy_rolling.value
|
|
||||||
condition_bb_rolling = [
|
|
||||||
# dataframe['bb_width'] >= self.buy_bollinger.value,
|
|
||||||
# (100 * (dataframe['sma100'].shift(12) - dataframe['sma100']) / dataframe['sma100']) < 0.1,
|
|
||||||
(dataframe['close'] < dataframe['sma10']),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) <= bb_rolling_max),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) == dataframe['bb_rolling'].shift(step)),
|
|
||||||
# (100 * ((dataframe['sma100'].shift(12) - dataframe['sma100']) / dataframe['sma100']) < 0.25),
|
|
||||||
(dataframe['close'].shift(step) < dataframe['min'].shift(step) + (
|
|
||||||
dataframe['max'].shift(step) - dataframe['min'].shift(step)) / 3),
|
|
||||||
(dataframe['min'].shift(step) == dataframe['min']),
|
|
||||||
(dataframe['rsi'] <= 35)
|
|
||||||
|
|
||||||
]
|
|
||||||
condition_bb_rolling2 = reduce(lambda x, y: x & y, condition_bb_rolling)
|
|
||||||
|
|
||||||
conditions = [
|
|
||||||
dataframe['bb_width'] >= 0.065, #self.buy_bollinger.value,
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']),
|
|
||||||
(dataframe['rsi'] <= 35)
|
|
||||||
]
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(
|
|
||||||
# condition_bb_rolling2
|
|
||||||
(reduce(lambda x, y: x & y, conditions))
|
|
||||||
) & (
|
|
||||||
dataframe['volume'] > 0
|
|
||||||
)
|
|
||||||
), 'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# dataframe.loc[
|
|
||||||
# (
|
|
||||||
# (dataframe['close'] < dataframe['open']) &
|
|
||||||
# (dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
# (dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
# (dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
# (((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
|
|
||||||
# # (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
# ), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,359 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick41214(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.00, 0.18, decimals=2, default=0.065, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
# buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
# buy_min = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# buy_percent = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=18, space="buy")
|
|
||||||
|
|
||||||
buy_step = IntParameter(1, 8, default=3, space="buy")
|
|
||||||
buy_rolling = IntParameter(-20, 0, default=-6, space="buy")
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.02
|
|
||||||
trailing_stop_positive_offset = 0.0275 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'red'},
|
|
||||||
'bb_upperband': {'color': 'green'},
|
|
||||||
'sma100': {'color': 'blue'},
|
|
||||||
'sma500': {'color': 'pink'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'min': {'color': 'white'},
|
|
||||||
'max': {'color': 'white'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
# "ADX": {
|
|
||||||
# 'adx': {'color': 'white'},
|
|
||||||
# 'minus_dm': {'color': 'blue'},
|
|
||||||
# 'plus_dm': {'color': 'red'}
|
|
||||||
# },
|
|
||||||
"Rsi": {
|
|
||||||
'rsi': {'color': 'pink'},
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
},
|
|
||||||
"percent": {
|
|
||||||
"percent": {'color': 'green'},
|
|
||||||
"percent5": {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
**kwargs) -> float:
|
|
||||||
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
# print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
|
|
||||||
# if current_candle['bb_width'] > 0.05:
|
|
||||||
# print("use more stake", pair, " ", proposed_stake * 2)
|
|
||||||
# return min(max_stake, proposed_stake * 2)
|
|
||||||
#
|
|
||||||
# if current_candle['bb_width'] > 0.035:
|
|
||||||
# print("use more stake", pair, " ", proposed_stake * 1.5)
|
|
||||||
# return min(max_stake, proposed_stake * 1.5)
|
|
||||||
|
|
||||||
# if current_candle['bb_width'] < 0.020:
|
|
||||||
# print("use less stake", pair, " ", proposed_stake / 2)
|
|
||||||
# return min(max_stake, proposed_stake / 2)
|
|
||||||
# if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# return max_stake
|
|
||||||
# else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
|
|
||||||
# Use default stake amount.
|
|
||||||
return proposed_stake
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
previous_5_candle = dataframe.iloc[-5].squeeze()
|
|
||||||
|
|
||||||
# (last_candle['percent5'] < -0.005) \
|
|
||||||
# if (0 < current_profit < 0.005) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 2):
|
|
||||||
# # & (previous_last_candle['sma10'] > last_candle['sma10']):
|
|
||||||
# print("too_small_gain", pair, trade, " profit=", current_profit, " rate=", current_rate, " percent5=",
|
|
||||||
# last_candle['percent5'])
|
|
||||||
# return 'too_small_gain'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 2) \
|
|
||||||
& (previous_5_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& (last_candle['percent5'] < 0):
|
|
||||||
print("over_bb_band_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_bb_band_sma20_desc'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& (last_candle['rsi'] > 75):
|
|
||||||
print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_rsi'
|
|
||||||
|
|
||||||
# description trade
|
|
||||||
# Trade(id=0, pair=CAKE/USDT, amount=4.19815281, open_rate=11.91000000, open_since=2021-12-22 17:55:00)
|
|
||||||
# print(last_candle)
|
|
||||||
# if (current_profit > 0) \
|
|
||||||
# & (last_candle['close'] < last_candle['open']) \
|
|
||||||
# & (previous_last_candle['bb_upperband'] < previous_last_candle['close']) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600) \
|
|
||||||
# & ((previous_last_candle['sma10'] - last_candle['sma10']) / last_candle['sma10'] < 0.1):
|
|
||||||
# # & (previous_last_candle['sma100'] > last_candle['sma100']) \
|
|
||||||
# print("close_over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'close_over_bb_band_sma10_desc'
|
|
||||||
if 0.05 < current_profit < 0.1:
|
|
||||||
if (
|
|
||||||
(previous_last_candle['sma10'] > last_candle['sma10']) &
|
|
||||||
(current_time - trade.open_date_utc).seconds >= 3600 * 3
|
|
||||||
) | (
|
|
||||||
(current_time - trade.open_date_utc).seconds >= 3600 * 6
|
|
||||||
):
|
|
||||||
print("profit_3h_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'profit_3h_sma10_desc'
|
|
||||||
|
|
||||||
if (0 < current_profit < 0.1) \
|
|
||||||
& (previous_last_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 5):
|
|
||||||
print("profit_5h_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'profit_5h_sma20_desc'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
#
|
|
||||||
# # Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe["percent5"] = dataframe["percent"].rolling(5).sum()
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (
|
|
||||||
100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(
|
|
||||||
3).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=10)
|
|
||||||
dataframe['bb_buy'] = (dataframe['min'] + (dataframe['max'] - dataframe['min']) / 3)
|
|
||||||
# print(dataframe["rolling"].tolist())
|
|
||||||
# dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=20,
|
|
||||||
# window_atr=10,
|
|
||||||
# fillna=False,
|
|
||||||
# original_version=True
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
|
||||||
# dataframe['high'],
|
|
||||||
# dataframe['low'],
|
|
||||||
# dataframe['close'],
|
|
||||||
# window=10,
|
|
||||||
# offset=0,
|
|
||||||
# fillna=False
|
|
||||||
# )
|
|
||||||
|
|
||||||
# dataframe['bb_lower_reg'] = dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
step = self.buy_step.value
|
|
||||||
if reduce(lambda x, y: x & y, dataframe['bb_width'] < 0.015):
|
|
||||||
step = 1
|
|
||||||
else:
|
|
||||||
if reduce(lambda x, y: x & y, dataframe['bb_width'] < 0.03):
|
|
||||||
step = 2
|
|
||||||
bb_rolling_max = self.buy_rolling.value
|
|
||||||
condition_bb_rolling = [
|
|
||||||
# dataframe['bb_width'] >= self.buy_bollinger.value,
|
|
||||||
# (100 * (dataframe['sma100'].shift(12) - dataframe['sma100']) / dataframe['sma100']) < 0.1,
|
|
||||||
(dataframe['close'] < dataframe['sma10']),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) <= bb_rolling_max),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) == dataframe['bb_rolling'].shift(step)),
|
|
||||||
# (dataframe['sma100'].shift(1) <= dataframe['sma100']),
|
|
||||||
# (100 * ((dataframe['sma20'].shift(1) - dataframe['sma20']) / dataframe['sma20']) < 0.1),
|
|
||||||
(dataframe['close'].shift(step) < dataframe['min'].shift(step) + (
|
|
||||||
dataframe['max'].shift(step) - dataframe['min'].shift(step)) / 3),
|
|
||||||
(dataframe['min'].shift(step) == dataframe['min']),
|
|
||||||
# (dataframe['rsi'].shift(step) <= 32)
|
|
||||||
|
|
||||||
]
|
|
||||||
condition_bb_rolling2 = reduce(lambda x, y: x & y, condition_bb_rolling)
|
|
||||||
|
|
||||||
conditions = [
|
|
||||||
dataframe['bb_width'] >= 0.065, # self.buy_bollinger.value,
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband'])
|
|
||||||
]
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(
|
|
||||||
condition_bb_rolling2
|
|
||||||
# | (reduce(lambda x, y: x & y, conditions))
|
|
||||||
) & (
|
|
||||||
dataframe['volume'] > 0
|
|
||||||
)
|
|
||||||
), 'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe[
|
|
||||||
'bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,311 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick41215(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.00, 0.18, decimals=2, default=0.065, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
# buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
# buy_min = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# buy_percent = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=18, space="buy")
|
|
||||||
|
|
||||||
buy_step = IntParameter(1, 8, default=3, space="buy")
|
|
||||||
buy_rolling = IntParameter(-20, 0, default=-6, space="buy")
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.02
|
|
||||||
trailing_stop_positive_offset = 0.0275 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'red'},
|
|
||||||
'bb_upperband': {'color': 'green'},
|
|
||||||
'sma100': {'color': 'blue'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'min': {'color': 'white'},
|
|
||||||
'max': {'color': 'white'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
# "ADX": {
|
|
||||||
# 'adx': {'color': 'white'},
|
|
||||||
# 'minus_dm': {'color': 'blue'},
|
|
||||||
# 'plus_dm': {'color': 'red'}
|
|
||||||
# },
|
|
||||||
"Rsi": {
|
|
||||||
'rsi': {'color': 'pink'},
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
},
|
|
||||||
"percent": {
|
|
||||||
"percent": {'color': 'green'},
|
|
||||||
"percent5": {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
**kwargs) -> float:
|
|
||||||
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
# print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
|
|
||||||
# if current_candle['bb_width'] > 0.05:
|
|
||||||
# print("use more stake", pair, " ", proposed_stake * 2)
|
|
||||||
# return min(max_stake, proposed_stake * 2)
|
|
||||||
#
|
|
||||||
# if current_candle['bb_width'] > 0.035:
|
|
||||||
# print("use more stake", pair, " ", proposed_stake * 1.5)
|
|
||||||
# return min(max_stake, proposed_stake * 1.5)
|
|
||||||
|
|
||||||
# if current_candle['bb_width'] < 0.020:
|
|
||||||
# print("use less stake", pair, " ", proposed_stake / 2)
|
|
||||||
# return min(max_stake, proposed_stake / 2)
|
|
||||||
# if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# return max_stake
|
|
||||||
# else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
|
|
||||||
# Use default stake amount.
|
|
||||||
return proposed_stake
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
previous_5_candle = dataframe.iloc[-5].squeeze()
|
|
||||||
|
|
||||||
# (last_candle['percent5'] < -0.005) \
|
|
||||||
# if (0 < current_profit < 0.005) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 2):
|
|
||||||
# # & (previous_last_candle['sma10'] > last_candle['sma10']):
|
|
||||||
# print("too_small_gain", pair, trade, " profit=", current_profit, " rate=", current_rate, " percent5=",
|
|
||||||
# last_candle['percent5'])
|
|
||||||
# return 'too_small_gain'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 2) \
|
|
||||||
& (previous_5_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& (last_candle['percent'] < 0) \
|
|
||||||
& (last_candle['percent5'] < 0):
|
|
||||||
print("over_bb_band_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_bb_band_sma20_desc'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& (last_candle['rsi'] > 75):
|
|
||||||
print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_rsi'
|
|
||||||
|
|
||||||
# description trade
|
|
||||||
# Trade(id=0, pair=CAKE/USDT, amount=4.19815281, open_rate=11.91000000, open_since=2021-12-22 17:55:00)
|
|
||||||
# print(last_candle)
|
|
||||||
if 0.05 < current_profit < 0.1:
|
|
||||||
if (
|
|
||||||
(previous_last_candle['sma10'] > last_candle['sma10']) &
|
|
||||||
(current_time - trade.open_date_utc).seconds >= 3600 * 3
|
|
||||||
) | (
|
|
||||||
(current_time - trade.open_date_utc).seconds >= 3600 * 6
|
|
||||||
):
|
|
||||||
print("profit_3h_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'profit_3h_sma10_desc'
|
|
||||||
|
|
||||||
if (0 < current_profit < 0.1) \
|
|
||||||
& (previous_last_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 5):
|
|
||||||
print("profit_5h_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'profit_5h_sma20_desc'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
#
|
|
||||||
# # Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe["percent5"] = dataframe["percent"].rolling(5).sum()
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (
|
|
||||||
100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(
|
|
||||||
3).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=10)
|
|
||||||
dataframe['bb_buy'] = (dataframe['min'] + (dataframe['max'] - dataframe['min']) / 3)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
step = self.buy_step.value
|
|
||||||
if reduce(lambda x, y: x & y, dataframe['bb_width'] < 0.015):
|
|
||||||
step = 5
|
|
||||||
else:
|
|
||||||
if reduce(lambda x, y: x & y, dataframe['bb_width'] < 0.03):
|
|
||||||
step = 4
|
|
||||||
bb_rolling_max = self.buy_rolling.value
|
|
||||||
condition_bb_rolling = [
|
|
||||||
(dataframe['close'] < dataframe['sma10']),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) <= bb_rolling_max),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) == dataframe['bb_rolling'].shift(step)),
|
|
||||||
(dataframe['close'].shift(step) < dataframe['min'].shift(step) + (
|
|
||||||
dataframe['max'].shift(step) - dataframe['min'].shift(step)) / 3),
|
|
||||||
(dataframe['min'].shift(step) == dataframe['min']),
|
|
||||||
(dataframe['volume'] > 0)
|
|
||||||
]
|
|
||||||
condition_bb_rolling2 = reduce(lambda x, y: x & y, condition_bb_rolling)
|
|
||||||
|
|
||||||
dataframe.loc[condition_bb_rolling2, 'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe[
|
|
||||||
'bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,323 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick41216(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.00, 0.18, decimals=2, default=0.065, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
# buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
# buy_min = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# buy_percent = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=18, space="buy")
|
|
||||||
|
|
||||||
buy_step = IntParameter(1, 8, default=3, space="buy")
|
|
||||||
buy_rolling = IntParameter(-20, 0, default=-6, space="buy")
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.02
|
|
||||||
trailing_stop_positive_offset = 0.0275 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'red'},
|
|
||||||
'bb_upperband': {'color': 'green'},
|
|
||||||
'sma100': {'color': 'blue'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'min': {'color': 'white'},
|
|
||||||
'max': {'color': 'white'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
# "ADX": {
|
|
||||||
# 'adx': {'color': 'white'},
|
|
||||||
# 'minus_dm': {'color': 'blue'},
|
|
||||||
# 'plus_dm': {'color': 'red'}
|
|
||||||
# },
|
|
||||||
"Rsi": {
|
|
||||||
'rsi': {'color': 'pink'},
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
},
|
|
||||||
"percent": {
|
|
||||||
"percent": {'color': 'green'},
|
|
||||||
"percent5": {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
**kwargs) -> float:
|
|
||||||
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
# print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
|
|
||||||
if current_candle['bb_width'] > 0.065:
|
|
||||||
print("use more stake", pair, " ", proposed_stake * 2)
|
|
||||||
return min(max_stake, proposed_stake * 2)
|
|
||||||
|
|
||||||
if current_candle['bb_width'] > 0.045:
|
|
||||||
print("use more stake", pair, " ", proposed_stake * 1.5)
|
|
||||||
return min(max_stake, proposed_stake * 1.5)
|
|
||||||
|
|
||||||
# if current_candle['bb_width'] < 0.020:
|
|
||||||
# print("use less stake", pair, " ", proposed_stake / 2)
|
|
||||||
# return min(max_stake, proposed_stake / 2)
|
|
||||||
# if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# return max_stake
|
|
||||||
# else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
|
|
||||||
# Use default stake amount.
|
|
||||||
return proposed_stake
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
previous_5_candle = dataframe.iloc[-5].squeeze()
|
|
||||||
|
|
||||||
# (last_candle['percent5'] < -0.005) \
|
|
||||||
# if (0 < current_profit < 0.005) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 2):
|
|
||||||
# # & (previous_last_candle['sma10'] > last_candle['sma10']):
|
|
||||||
# print("too_small_gain", pair, trade, " profit=", current_profit, " rate=", current_rate, " percent5=",
|
|
||||||
# last_candle['percent5'])
|
|
||||||
# return 'too_small_gain'
|
|
||||||
|
|
||||||
# if (current_profit < -0.05) \
|
|
||||||
# & ((current_time - trade.open_date_utc).days >= 3):
|
|
||||||
# print("lost_half_profit", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'stop_loss_profit'
|
|
||||||
|
|
||||||
# if (current_profit > 0.02) \
|
|
||||||
# & (last_candle['percent'] < 0.01) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600):
|
|
||||||
# print("lost_half_profit", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'lost_half_profit'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 2) \
|
|
||||||
& (previous_5_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& (last_candle['percent'] < 0) \
|
|
||||||
& (last_candle['percent5'] < 0):
|
|
||||||
print("over_bb_band_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_bb_band_sma20_desc'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& (last_candle['rsi'] > 75):
|
|
||||||
print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_rsi'
|
|
||||||
|
|
||||||
# description trade
|
|
||||||
# Trade(id=0, pair=CAKE/USDT, amount=4.19815281, open_rate=11.91000000, open_since=2021-12-22 17:55:00)
|
|
||||||
# print(last_candle)
|
|
||||||
if 0.05 < current_profit < 0.1:
|
|
||||||
if (
|
|
||||||
(previous_last_candle['sma10'] > last_candle['sma10']) &
|
|
||||||
(current_time - trade.open_date_utc).seconds >= 3600 * 3
|
|
||||||
) | (
|
|
||||||
(current_time - trade.open_date_utc).seconds >= 3600 * 6
|
|
||||||
):
|
|
||||||
print("profit_3h_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'profit_3h_sma10_desc'
|
|
||||||
|
|
||||||
if (0 < current_profit < 0.1) \
|
|
||||||
& (previous_last_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 5):
|
|
||||||
print("profit_5h_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'profit_5h_sma20_desc'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
#
|
|
||||||
# # Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe["percent5"] = dataframe["percent"].rolling(5).sum()
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (
|
|
||||||
100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(
|
|
||||||
3).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=10)
|
|
||||||
dataframe['bb_buy'] = (dataframe['min'] + (dataframe['max'] - dataframe['min']) / 3)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
step = self.buy_step.value
|
|
||||||
# if reduce(lambda x, y: x & y, dataframe['bb_width'] < 0.015):
|
|
||||||
# step = 5
|
|
||||||
# else:
|
|
||||||
# if reduce(lambda x, y: x & y, dataframe['bb_width'] < 0.03):
|
|
||||||
# step = 4
|
|
||||||
bb_rolling_max = self.buy_rolling.value
|
|
||||||
condition_bb_rolling = [
|
|
||||||
(dataframe['bb_width'] >= 0.035),
|
|
||||||
(dataframe['close'] < dataframe['sma10']),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) <= bb_rolling_max),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) >= dataframe['bb_rolling'].shift(step)),
|
|
||||||
(dataframe['close'].shift(step) < dataframe['min'].shift(step) + (
|
|
||||||
dataframe['max'].shift(step) - dataframe['min'].shift(step)) / 3),
|
|
||||||
(dataframe['min'].shift(step) == dataframe['min']),
|
|
||||||
(dataframe['volume'] > 0)
|
|
||||||
]
|
|
||||||
condition_bb_rolling2 = reduce(lambda x, y: x & y, condition_bb_rolling)
|
|
||||||
|
|
||||||
dataframe.loc[condition_bb_rolling2, 'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe[
|
|
||||||
'bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,350 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import numpy
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick41217(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.00, 0.18, decimals=2, default=0.065, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
# buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
# buy_min = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# buy_percent = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=18, space="buy")
|
|
||||||
|
|
||||||
buy_step = IntParameter(1, 8, default=3, space="buy")
|
|
||||||
buy_rolling = IntParameter(-20, 0, default=-6, space="buy")
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.02
|
|
||||||
trailing_stop_positive_offset = 0.0275 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'red'},
|
|
||||||
'bb_upperband': {'color': 'green'},
|
|
||||||
'sma100': {'color': 'blue'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'min': {'color': 'white'},
|
|
||||||
'max': {'color': 'white'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
'bb_min': {'color': 'red'},
|
|
||||||
},
|
|
||||||
# "ADX": {
|
|
||||||
# 'adx': {'color': 'white'},
|
|
||||||
# 'minus_dm': {'color': 'blue'},
|
|
||||||
# 'plus_dm': {'color': 'red'}
|
|
||||||
# },
|
|
||||||
"Rsi": {
|
|
||||||
'rsi': {'color': 'pink'},
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
},
|
|
||||||
"percent": {
|
|
||||||
"percent": {'color': 'green'},
|
|
||||||
"percent5": {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
**kwargs) -> float:
|
|
||||||
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
# print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
|
|
||||||
if current_candle['bb_width'] > 0.065:
|
|
||||||
print("use more stake", pair, " ", proposed_stake * 2)
|
|
||||||
return min(max_stake, proposed_stake * 2)
|
|
||||||
|
|
||||||
if current_candle['bb_width'] > 0.045:
|
|
||||||
print("use more stake", pair, " ", proposed_stake * 1.5)
|
|
||||||
return min(max_stake, proposed_stake * 1.5)
|
|
||||||
|
|
||||||
# if current_candle['bb_width'] < 0.020:
|
|
||||||
# print("use less stake", pair, " ", proposed_stake / 2)
|
|
||||||
# return min(max_stake, proposed_stake / 2)
|
|
||||||
# if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# return max_stake
|
|
||||||
# else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
|
|
||||||
# Use default stake amount.
|
|
||||||
return proposed_stake
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
previous_5_candle = dataframe.iloc[-5].squeeze()
|
|
||||||
|
|
||||||
# (last_candle['percent5'] < -0.005) \
|
|
||||||
# if (0 < current_profit < 0.005) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 2):
|
|
||||||
# # & (previous_last_candle['sma10'] > last_candle['sma10']):
|
|
||||||
# print("too_small_gain", pair, trade, " profit=", current_profit, " rate=", current_rate, " percent5=",
|
|
||||||
# last_candle['percent5'])
|
|
||||||
# return 'too_small_gain'
|
|
||||||
|
|
||||||
# if (current_profit < -0.05) \
|
|
||||||
# & ((current_time - trade.open_date_utc).days >= 3):
|
|
||||||
# print("lost_half_profit", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'stop_loss_profit'
|
|
||||||
|
|
||||||
# if (current_profit > 0.02) \
|
|
||||||
# & (last_candle['percent'] < 0.01) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600):
|
|
||||||
# print("lost_half_profit", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'lost_half_profit'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 2) \
|
|
||||||
& (previous_5_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& (last_candle['percent'] < 0) \
|
|
||||||
& (last_candle['percent5'] < 0):
|
|
||||||
print("over_bb_band_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_bb_band_sma20_desc'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& (last_candle['rsi'] > 75):
|
|
||||||
print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_rsi'
|
|
||||||
|
|
||||||
# description trade
|
|
||||||
# Trade(id=0, pair=CAKE/USDT, amount=4.19815281, open_rate=11.91000000, open_since=2021-12-22 17:55:00)
|
|
||||||
# print(last_candle)
|
|
||||||
if 0.05 < current_profit < 1:
|
|
||||||
if (
|
|
||||||
(previous_last_candle['sma10'] > last_candle['sma10'] * 1.005) &
|
|
||||||
(current_time - trade.open_date_utc).seconds >= 3600 * 3
|
|
||||||
# ) | (
|
|
||||||
# (current_time - trade.open_date_utc).seconds >= 3600 * 6
|
|
||||||
):
|
|
||||||
# self.lock_pair(pair, until=current_time + timedelta(hours=3))
|
|
||||||
|
|
||||||
print("profit_3h_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'profit_3h_sma10_desc'
|
|
||||||
|
|
||||||
if (0 < current_profit < 0.1) \
|
|
||||||
& (previous_last_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 5):
|
|
||||||
print("profit_5h_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'profit_5h_sma20_desc'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
#
|
|
||||||
# # Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
# dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
# dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe["percent5"] = dataframe["percent"].rolling(5).sum()
|
|
||||||
dataframe["percent20"] = dataframe["percent"].rolling(20).sum()
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
|
|
||||||
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max_min'] = dataframe['max'] / dataframe['min']
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
dataframe['bb_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (
|
|
||||||
100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(
|
|
||||||
3).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=10)
|
|
||||||
dataframe['bb_buy'] = (dataframe['min'] + (dataframe['max'] - dataframe['min']) / 3)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
step = self.buy_step.value
|
|
||||||
# if reduce(lambda x, y: x & y, dataframe['bb_width'] < 0.015):
|
|
||||||
# step = 5
|
|
||||||
# else:
|
|
||||||
# if reduce(lambda x, y: x & y, dataframe['bb_width'] < 0.03):
|
|
||||||
# step = 4
|
|
||||||
bb_rolling_max = self.buy_rolling.value
|
|
||||||
condition_bb_rolling_1 = [
|
|
||||||
(dataframe['bb_width'] >= 0.035),
|
|
||||||
# (dataframe['close'] > dataframe['open']),
|
|
||||||
(dataframe['close'] < dataframe['sma10']),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) <= bb_rolling_max),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) >= dataframe['bb_rolling'].shift(step)),
|
|
||||||
(dataframe['close'].shift(step) < dataframe['min'].shift(step) + (
|
|
||||||
dataframe['max'].shift(step) - dataframe['min'].shift(step)) / 3),
|
|
||||||
(dataframe['min'].shift(step) == dataframe['min']),
|
|
||||||
(dataframe['volume'] * dataframe['close'] / 1000 > 100),
|
|
||||||
# (dataframe['rsi'] <= 30)
|
|
||||||
]
|
|
||||||
condition_bb_rolling1 = reduce(lambda x, y: x & y, condition_bb_rolling_1)
|
|
||||||
step = 2
|
|
||||||
condition_bb_rolling_2 = [
|
|
||||||
(dataframe['bb_width'] >= 0.04),
|
|
||||||
(dataframe['close'] < dataframe['sma10']),
|
|
||||||
((dataframe['close'] > dataframe['open']) | (dataframe['percent'] > -0.01)),
|
|
||||||
# (dataframe['bb_rolling_min'].shift(step) <= bb_rolling_max),
|
|
||||||
# (dataframe['bb_rolling_min'].shift(step) >= dataframe['bb_rolling'].shift(step)),
|
|
||||||
(dataframe['close'].shift(step) < dataframe['min'].shift(step) + (
|
|
||||||
dataframe['max'].shift(step) - dataframe['min'].shift(step)) / 3),
|
|
||||||
(dataframe['min'].shift(step) == dataframe['min']),
|
|
||||||
(dataframe['volume'] * dataframe['close'] / 1000 > 100),
|
|
||||||
(dataframe['rsi'] <= 30)
|
|
||||||
]
|
|
||||||
condition_bb_rolling2 = reduce(lambda x, y: x & y, condition_bb_rolling_2)
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
condition_bb_rolling1 |
|
|
||||||
condition_bb_rolling2, 'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe[
|
|
||||||
'bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,349 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime, timezone, timedelta
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick41218(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.00, 0.18, decimals=2, default=0.065, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
# buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
# buy_min = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# buy_percent = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=18, space="buy")
|
|
||||||
|
|
||||||
buy_step = IntParameter(1, 8, default=3, space="buy")
|
|
||||||
buy_rolling = IntParameter(-20, 0, default=-6, space="buy")
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.02
|
|
||||||
trailing_stop_positive_offset = 0.0275 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'red'},
|
|
||||||
'bb_upperband': {'color': 'green'},
|
|
||||||
'sma100': {'color': 'blue'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'min': {'color': 'white'},
|
|
||||||
'max': {'color': 'white'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
# "ADX": {
|
|
||||||
# 'adx': {'color': 'white'},
|
|
||||||
# 'minus_dm': {'color': 'blue'},
|
|
||||||
# 'plus_dm': {'color': 'red'}
|
|
||||||
# },
|
|
||||||
"Rsi": {
|
|
||||||
'rsi': {'color': 'pink'},
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
},
|
|
||||||
"percent": {
|
|
||||||
"percent": {'color': 'green'},
|
|
||||||
"percent5": {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
**kwargs) -> float:
|
|
||||||
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
# print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
|
|
||||||
if current_candle['bb_width'] > 0.065:
|
|
||||||
print("use more stake", pair, " ", proposed_stake * 2)
|
|
||||||
return min(max_stake, proposed_stake * 2)
|
|
||||||
|
|
||||||
if current_candle['bb_width'] > 0.045:
|
|
||||||
print("use more stake", pair, " ", proposed_stake * 1.5)
|
|
||||||
return min(max_stake, proposed_stake * 1.5)
|
|
||||||
|
|
||||||
# if current_candle['bb_width'] < 0.020:
|
|
||||||
# print("use less stake", pair, " ", proposed_stake / 2)
|
|
||||||
# return min(max_stake, proposed_stake / 2)
|
|
||||||
# if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# return max_stake
|
|
||||||
# else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
|
|
||||||
# Use default stake amount.
|
|
||||||
return proposed_stake
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
previous_5_candle = dataframe.iloc[-5].squeeze()
|
|
||||||
|
|
||||||
# (last_candle['percent5'] < -0.005) \
|
|
||||||
# if (0 < current_profit < 0.005) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 2):
|
|
||||||
# # & (previous_last_candle['sma10'] > last_candle['sma10']):
|
|
||||||
# print("too_small_gain", pair, trade, " profit=", current_profit, " rate=", current_rate, " percent5=",
|
|
||||||
# last_candle['percent5'])
|
|
||||||
# return 'too_small_gain'
|
|
||||||
|
|
||||||
# if (current_profit < -0.05) \
|
|
||||||
# & ((current_time - trade.open_date_utc).days >= 3):
|
|
||||||
# print("lost_half_profit", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'stop_loss_profit'
|
|
||||||
|
|
||||||
# if (current_profit > 0.02) \
|
|
||||||
# & (last_candle['percent'] < 0.01) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600):
|
|
||||||
# print("lost_half_profit", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'lost_half_profit'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 2) \
|
|
||||||
& (previous_5_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& (last_candle['percent'] < 0) \
|
|
||||||
& (last_candle['percent5'] < 0):
|
|
||||||
print("over_bb_band_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_bb_band_sma20_desc'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& (last_candle['rsi'] > 75):
|
|
||||||
self.lock_pair(pair, until=datetime.now(timezone.utc) + timedelta(hours=6))
|
|
||||||
print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_rsi'
|
|
||||||
|
|
||||||
# description trade
|
|
||||||
# Trade(id=0, pair=CAKE/USDT, amount=4.19815281, open_rate=11.91000000, open_since=2021-12-22 17:55:00)
|
|
||||||
# print(last_candle)
|
|
||||||
if 0.05 < current_profit < 1:
|
|
||||||
if (
|
|
||||||
(previous_last_candle['sma10'] > last_candle['sma10']) &
|
|
||||||
((current_time - trade.open_date_utc).seconds >= 3600 * 3) &
|
|
||||||
(last_candle['percent'] < 0) & (last_candle['percent5'] < 0) &
|
|
||||||
(last_candle['close'] < last_candle['bb_width'])
|
|
||||||
):
|
|
||||||
# self.lock_pair(pair, until=datetime.now(timezone.utc) + timedelta(hours=2))
|
|
||||||
print("profit_3h_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate, ' percent5=', last_candle['percent5'])
|
|
||||||
return 'profit_3h_sma10_desc'
|
|
||||||
|
|
||||||
if (0 < current_profit < 0.1) \
|
|
||||||
& (previous_last_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 5)\
|
|
||||||
& (last_candle['percent'] < 0) & (last_candle['percent5'] < 0) \
|
|
||||||
& (last_candle['close'] < last_candle['bb_width']):
|
|
||||||
# self.lock_pair(pair, until=datetime.now(timezone.utc) + timedelta(hours=3))
|
|
||||||
print("profit_5h_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate,
|
|
||||||
"percent5=", abs(last_candle['percent5']))
|
|
||||||
return 'profit_5h_sma20_desc'
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
#
|
|
||||||
# # Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
# dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
# dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe["percent5"] = dataframe["percent"].rolling(5).sum()
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (
|
|
||||||
100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(
|
|
||||||
3).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=10)
|
|
||||||
dataframe['bb_buy'] = (dataframe['min'] + (dataframe['max'] - dataframe['min']) / 3)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
step = self.buy_step.value
|
|
||||||
# if reduce(lambda x, y: x & y, dataframe['bb_width'] < 0.015):
|
|
||||||
# step = 5
|
|
||||||
# else:
|
|
||||||
# if reduce(lambda x, y: x & y, dataframe['bb_width'] < 0.03):
|
|
||||||
# step = 4
|
|
||||||
bb_rolling_max = self.buy_rolling.value
|
|
||||||
condition_bb_rolling_1 = [
|
|
||||||
(dataframe['bb_width'] >= 0.035),
|
|
||||||
# (dataframe['close'] > dataframe['open']),
|
|
||||||
(dataframe['close'] < dataframe['sma10']),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) <= bb_rolling_max),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) >= dataframe['bb_rolling'].shift(step)),
|
|
||||||
(dataframe['close'].shift(step) < dataframe['min'].shift(step) + (
|
|
||||||
dataframe['max'].shift(step) - dataframe['min'].shift(step)) / 3),
|
|
||||||
(dataframe['min'].shift(step) == dataframe['min']),
|
|
||||||
(dataframe['volume'] * dataframe['close'] / 1000 > 100),
|
|
||||||
# (dataframe['rsi'] <= 30)
|
|
||||||
]
|
|
||||||
condition_bb_rolling1 = reduce(lambda x, y: x & y, condition_bb_rolling_1)
|
|
||||||
step = 2
|
|
||||||
condition_bb_rolling_2 = [
|
|
||||||
(dataframe['bb_width'] >= 0.04),
|
|
||||||
# (dataframe['percent5'] >= 0.01),
|
|
||||||
(dataframe['close'] < dataframe['sma10']),
|
|
||||||
((dataframe['close'] > dataframe['open']) | (dataframe['percent'] > -0.01)),
|
|
||||||
# (dataframe['bb_rolling_min'].shift(step) <= bb_rolling_max),
|
|
||||||
# (dataframe['bb_rolling_min'].shift(step) >= dataframe['bb_rolling'].shift(step)),
|
|
||||||
(dataframe['close'].shift(step) < dataframe['min'].shift(step) + (
|
|
||||||
dataframe['max'].shift(step) - dataframe['min'].shift(step)) / 3),
|
|
||||||
(dataframe['min'].shift(step) == dataframe['min']),
|
|
||||||
(dataframe['volume'] * dataframe['close'] / 1000 > 100),
|
|
||||||
(dataframe['rsi'] <= 30)
|
|
||||||
]
|
|
||||||
condition_bb_rolling2 = reduce(lambda x, y: x & y, condition_bb_rolling_2)
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
condition_bb_rolling1 |
|
|
||||||
condition_bb_rolling2, 'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe[
|
|
||||||
'bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
@@ -1,378 +0,0 @@
|
|||||||
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
|
|
||||||
# isort: skip_file
|
|
||||||
# --- Do not remove these libs ---
|
|
||||||
from datetime import datetime, timezone, timedelta
|
|
||||||
|
|
||||||
import numpy as np # noqa
|
|
||||||
import pandas as pd # noqa
|
|
||||||
from freqtrade.strategy.parameters import DecimalParameter, BooleanParameter, IntParameter
|
|
||||||
from pandas import DataFrame
|
|
||||||
from freqtrade.persistence import Trade
|
|
||||||
import math
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from freqtrade.strategy.interface import IStrategy
|
|
||||||
|
|
||||||
# --------------------------------
|
|
||||||
# Add your lib to import here
|
|
||||||
import talib.abstract as ta
|
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
||||||
|
|
||||||
|
|
||||||
# This class is a sample. Feel free to customize it.
|
|
||||||
class StrategyPierrick41219(IStrategy):
|
|
||||||
# Strategy interface version - allow new iterations of the strategy interface.
|
|
||||||
# Check the documentation or the Sample strategy to get the latest version.
|
|
||||||
INTERFACE_VERSION = 2
|
|
||||||
|
|
||||||
# valeur de bbwidth pour démarrer
|
|
||||||
buy_bollinger = DecimalParameter(0.00, 0.18, decimals=2, default=0.065, space="buy")
|
|
||||||
# Valeur de la deuxième condition bollinger avec condition sma200
|
|
||||||
# buy_bollinger_2 = DecimalParameter(0.0, 0.08, decimals=2, default=0.04, space="buy")
|
|
||||||
# buy_min = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# buy_percent = DecimalParameter(1, 1.1, decimals=2, default=1.01, space="buy")
|
|
||||||
# volume à atteindre
|
|
||||||
buy_volume = DecimalParameter(0, 50, decimals=1, default=18, space="buy")
|
|
||||||
|
|
||||||
buy_step = IntParameter(1, 8, default=3, space="buy")
|
|
||||||
buy_rolling = IntParameter(-20, 0, default=-6, space="buy")
|
|
||||||
# buy_rsi = IntParameter(20, 40, default=30, space="buy")
|
|
||||||
# buy_adx_enabled = BooleanParameter(default=True, space="buy")
|
|
||||||
# buy_rsi_enabled = CategoricalParameter([True, False], default=False, space="buy")
|
|
||||||
# buy_trigger = CategoricalParameter(["bb_lower", "macd_cross_signal"], default="bb_lower", space="buy")
|
|
||||||
|
|
||||||
# ROI table:
|
|
||||||
minimal_roi = {
|
|
||||||
# "0": 0.015
|
|
||||||
"0": 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stoploss:
|
|
||||||
stoploss = -1
|
|
||||||
trailing_stop = False
|
|
||||||
trailing_stop_positive = 0.02
|
|
||||||
trailing_stop_positive_offset = 0.0275 # 0.015
|
|
||||||
trailing_only_offset_is_reached = True
|
|
||||||
|
|
||||||
# max_open_trades = 3
|
|
||||||
|
|
||||||
# Optimal ticker interval for the strategy.
|
|
||||||
timeframe = '5m'
|
|
||||||
|
|
||||||
# Run "populate_indicators()" only for new candle.
|
|
||||||
process_only_new_candles = False
|
|
||||||
|
|
||||||
# These values can be overridden in the "ask_strategy" section in the config.
|
|
||||||
use_sell_signal = True
|
|
||||||
sell_profit_only = False
|
|
||||||
ignore_roi_if_buy_signal = False
|
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
|
||||||
startup_candle_count: int = 30
|
|
||||||
|
|
||||||
# Optional order type mapping.
|
|
||||||
order_types = {
|
|
||||||
'buy': 'limit',
|
|
||||||
'sell': 'limit',
|
|
||||||
'stoploss': 'market',
|
|
||||||
'stoploss_on_exchange': False
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional order time in force.
|
|
||||||
order_time_in_force = {
|
|
||||||
'buy': 'gtc',
|
|
||||||
'sell': 'gtc'
|
|
||||||
}
|
|
||||||
|
|
||||||
plot_config = {
|
|
||||||
# Main plot indicators (Moving averages, ...)
|
|
||||||
'main_plot': {
|
|
||||||
'bb_lowerband': {'color': 'red'},
|
|
||||||
'bb_upperband': {'color': 'green'},
|
|
||||||
'sma100': {'color': 'blue'},
|
|
||||||
'sma10': {'color': 'yellow'},
|
|
||||||
'min': {'color': 'white'},
|
|
||||||
'max': {'color': 'white'},
|
|
||||||
'sma20': {'color': 'cyan'}
|
|
||||||
},
|
|
||||||
'subplots': {
|
|
||||||
# Subplots - each dict defines one additional plot
|
|
||||||
"BB": {
|
|
||||||
'bb_width': {'color': 'white'},
|
|
||||||
},
|
|
||||||
# "ADX": {
|
|
||||||
# 'adx': {'color': 'white'},
|
|
||||||
# 'minus_dm': {'color': 'blue'},
|
|
||||||
# 'plus_dm': {'color': 'red'}
|
|
||||||
# },
|
|
||||||
"Rsi": {
|
|
||||||
'rsi': {'color': 'pink'},
|
|
||||||
},
|
|
||||||
"rolling": {
|
|
||||||
'bb_rolling': {'color': '#87e470'},
|
|
||||||
"bb_rolling_min": {'color': '#ac3e2a'}
|
|
||||||
},
|
|
||||||
"percent": {
|
|
||||||
"percent": {'color': 'green'},
|
|
||||||
"percent5": {'color': 'red'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
|
||||||
proposed_stake: float, min_stake: float, max_stake: float,
|
|
||||||
**kwargs) -> float:
|
|
||||||
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
|
|
||||||
current_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
|
|
||||||
# print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
|
|
||||||
if current_candle['bb_width'] > 0.065:
|
|
||||||
print("use more stake", pair, " ", proposed_stake * 2)
|
|
||||||
return min(max_stake, proposed_stake * 2)
|
|
||||||
|
|
||||||
if current_candle['bb_width'] > 0.045:
|
|
||||||
print("use more stake", pair, " ", proposed_stake * 1.5)
|
|
||||||
return min(max_stake, proposed_stake * 1.5)
|
|
||||||
|
|
||||||
# if current_candle['bb_width'] < 0.020:
|
|
||||||
# print("use less stake", pair, " ", proposed_stake / 2)
|
|
||||||
# return min(max_stake, proposed_stake / 2)
|
|
||||||
# if self.config['stake_amount'] == 'unlimited':
|
|
||||||
# # Use entire available wallet during favorable conditions when in compounding mode.
|
|
||||||
# return max_stake
|
|
||||||
# else:
|
|
||||||
# # Compound profits during favorable conditions instead of using a static stake.
|
|
||||||
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
|
|
||||||
|
|
||||||
# Use default stake amount.
|
|
||||||
return proposed_stake
|
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
|
||||||
current_profit: float, **kwargs):
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1].squeeze()
|
|
||||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
|
||||||
previous_5_candle = dataframe.iloc[-5].squeeze()
|
|
||||||
|
|
||||||
# (last_candle['percent5'] < -0.005) \
|
|
||||||
# if (0 < current_profit < 0.005) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 2):
|
|
||||||
# # & (previous_last_candle['sma10'] > last_candle['sma10']):
|
|
||||||
# print("too_small_gain", pair, trade, " profit=", current_profit, " rate=", current_rate, " percent5=",
|
|
||||||
# last_candle['percent5'])
|
|
||||||
# return 'too_small_gain'
|
|
||||||
|
|
||||||
# if (current_profit < -0.05) \
|
|
||||||
# & ((current_time - trade.open_date_utc).days >= 3):
|
|
||||||
# print("lost_half_profit", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'stop_loss_profit'
|
|
||||||
|
|
||||||
# if (current_profit > 0.025) \
|
|
||||||
# & (last_candle['percent'] < 0) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds <= 1800):
|
|
||||||
# print("stop_quick_profit", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'stop_quick_profit'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 2) \
|
|
||||||
& (previous_5_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& (last_candle['percent'] < 0) \
|
|
||||||
& (last_candle['percent5'] < 0):
|
|
||||||
print("over_bb_band_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_bb_band_sma20_desc'
|
|
||||||
|
|
||||||
if (current_profit > 0) \
|
|
||||||
& (last_candle['rsi'] > 79):
|
|
||||||
self.lock_pair(pair, until=datetime.now(timezone.utc) + timedelta(hours=6))
|
|
||||||
print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'over_rsi'
|
|
||||||
|
|
||||||
# description trade
|
|
||||||
# Trade(id=0, pair=CAKE/USDT, amount=4.19815281, open_rate=11.91000000, open_since=2021-12-22 17:55:00)
|
|
||||||
# print(last_candle)
|
|
||||||
if 0.05 < current_profit < 0.1:
|
|
||||||
if (
|
|
||||||
(previous_last_candle['sma10'] > last_candle['sma10']) &
|
|
||||||
((current_time - trade.open_date_utc).seconds >= 3600 * 3) &
|
|
||||||
(last_candle['percent'] < 0) &
|
|
||||||
(abs(last_candle['percent5']) > current_profit / 5)
|
|
||||||
):
|
|
||||||
# self.lock_pair(pair, until=datetime.now(timezone.utc) + timedelta(hours=2))
|
|
||||||
print("profit_3h_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate, ' percent5=', last_candle['percent5'])
|
|
||||||
return 'profit_3h_sma10_desc'
|
|
||||||
|
|
||||||
if (0 < current_profit < 0.1) \
|
|
||||||
& (previous_last_candle['sma20'] > last_candle['sma20']) \
|
|
||||||
& ((current_time - trade.open_date_utc).seconds >= 3600 * 5)\
|
|
||||||
& (last_candle['percent'] < 0) \
|
|
||||||
& (abs(last_candle['percent5']) > current_profit / 5):
|
|
||||||
# self.lock_pair(pair, until=datetime.now(timezone.utc) + timedelta(hours=3))
|
|
||||||
print("profit_5h_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
return 'profit_5h_sma20_desc'
|
|
||||||
|
|
||||||
# if (-0.01 < current_profit < 0) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 10):
|
|
||||||
# # self.lock_pair(pair, until=datetime.now(timezone.utc) + timedelta(hours=3))
|
|
||||||
# print("stop_wait_10h", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'stop_wait_10h'
|
|
||||||
#
|
|
||||||
# if (-0.02 < current_profit < -0.01) \
|
|
||||||
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 5):
|
|
||||||
# # self.lock_pair(pair, until=datetime.now(timezone.utc) + timedelta(hours=3))
|
|
||||||
# print("stop_wait_5h", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'stop_wait_5h'
|
|
||||||
#
|
|
||||||
# if (current_profit < -0.02) :
|
|
||||||
# self.lock_pair(pair, until=datetime.now(timezone.utc) + timedelta(hours=3))
|
|
||||||
# print("stop_big_loss", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
||||||
# return 'stop_big_loss'
|
|
||||||
|
|
||||||
|
|
||||||
def informative_pairs(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# MACD
|
|
||||||
# macd = ta.MACD(dataframe)
|
|
||||||
# dataframe['macd'] = macd['macd']
|
|
||||||
# dataframe['macdsignal'] = macd['macdsignal']
|
|
||||||
# dataframe['macdhist'] = macd['macdhist']
|
|
||||||
|
|
||||||
# # # Plus Directional Indicator / Movement
|
|
||||||
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
|
|
||||||
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
|
||||||
#
|
|
||||||
# # Minus Directional Indicator / Movement
|
|
||||||
# dataframe['adx'] = ta.ADX(dataframe)
|
|
||||||
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
|
|
||||||
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
|
||||||
|
|
||||||
# dataframe['min'] = ta.MIN(dataframe)
|
|
||||||
# dataframe['max'] = ta.MAX(dataframe)
|
|
||||||
|
|
||||||
# # Aroon, Aroon Oscillator
|
|
||||||
# aroon = ta.AROON(dataframe)
|
|
||||||
# dataframe['aroonup'] = aroon['aroonup']
|
|
||||||
# dataframe['aroondown'] = aroon['aroondown']
|
|
||||||
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
|
|
||||||
|
|
||||||
# RSI
|
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
|
||||||
|
|
||||||
# # EMA - Exponential Moving Average
|
|
||||||
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
|
|
||||||
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
|
||||||
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
|
|
||||||
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
|
|
||||||
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
|
|
||||||
|
|
||||||
# # SMA - Simple Moving Average
|
|
||||||
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
|
|
||||||
# dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
|
|
||||||
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
|
|
||||||
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
|
|
||||||
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
|
|
||||||
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
|
|
||||||
# dataframe['sma200'] = ta.SMA(dataframe, timeperiod=200)
|
|
||||||
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
|
|
||||||
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
|
|
||||||
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
|
|
||||||
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
|
|
||||||
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
|
|
||||||
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
|
|
||||||
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
|
||||||
dataframe["percent5"] = dataframe["percent"].rolling(5).sum()
|
|
||||||
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
|
|
||||||
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
|
|
||||||
|
|
||||||
# Bollinger Bands
|
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
|
||||||
dataframe["bb_percent"] = (
|
|
||||||
(dataframe["close"] - dataframe["bb_lowerband"]) /
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
|
|
||||||
)
|
|
||||||
dataframe["bb_width"] = (
|
|
||||||
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["rolling"] = (
|
|
||||||
100 * (dataframe["close"] - dataframe["bb_lowerband"]) / dataframe["bb_lowerband"]).rolling(
|
|
||||||
3).mean()
|
|
||||||
dataframe["bb_rolling"] = dataframe["rolling"] / dataframe["bb_width"]
|
|
||||||
dataframe['bb_rolling_min'] = ta.MIN(dataframe['bb_rolling'], timeperiod=10)
|
|
||||||
dataframe['bb_buy'] = (dataframe['min'] + (dataframe['max'] - dataframe['min']) / 3)
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
# if self.config['runmode'].value in ('live', 'dry_run'):
|
|
||||||
# trades = Trade.get_trades([Trade.pair == metadata['pair'],
|
|
||||||
# Trade.open_date > datetime.utcnow() - timedelta(days=1),
|
|
||||||
# Trade.is_open.is_(False),
|
|
||||||
# ]).order_by(Trade.close_date).all()
|
|
||||||
# # Summarize profit for this pair.
|
|
||||||
# print("Trades=", trades)
|
|
||||||
# curdayprofit = sum(trade.close_profit for trade in trades)
|
|
||||||
|
|
||||||
step = self.buy_step.value
|
|
||||||
# if reduce(lambda x, y: x & y, dataframe['bb_width'] > 0.065):
|
|
||||||
# step = 1
|
|
||||||
# else:
|
|
||||||
# if reduce(lambda x, y: x & y, dataframe['bb_width'] > 0.045):
|
|
||||||
# step = 2
|
|
||||||
|
|
||||||
bb_rolling_max = self.buy_rolling.value
|
|
||||||
condition_bb_rolling_1 = [
|
|
||||||
(dataframe['bb_width'] >= 0.025),
|
|
||||||
# (dataframe['close'] > dataframe['open']),
|
|
||||||
(dataframe['close'] < dataframe['sma10']),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) <= bb_rolling_max),
|
|
||||||
(dataframe['bb_rolling_min'].shift(step) >= dataframe['bb_rolling'].shift(step)),
|
|
||||||
(dataframe['close'].shift(step) < dataframe['min'].shift(step) + (
|
|
||||||
dataframe['max'].shift(step) - dataframe['min'].shift(step)) / 3),
|
|
||||||
(dataframe['min'].shift(step) == dataframe['min']),
|
|
||||||
(dataframe['volume'] * dataframe['close'] / 1000 > 100),
|
|
||||||
# (dataframe['rsi'] <= 30)
|
|
||||||
]
|
|
||||||
condition_bb_rolling1 = reduce(lambda x, y: x & y, condition_bb_rolling_1)
|
|
||||||
step = 2
|
|
||||||
condition_bb_rolling_2 = [
|
|
||||||
(dataframe['bb_width'] >= 0.04),
|
|
||||||
# (dataframe['percent5'] >= 0.01),
|
|
||||||
(dataframe['close'] < dataframe['sma10']),
|
|
||||||
((dataframe['close'] > dataframe['open']) | (dataframe['percent'] > -0.01)),
|
|
||||||
# (dataframe['bb_rolling_min'].shift(step) <= bb_rolling_max),
|
|
||||||
# (dataframe['bb_rolling_min'].shift(step) >= dataframe['bb_rolling'].shift(step)),
|
|
||||||
(dataframe['close'].shift(step) < dataframe['min'].shift(step) + (
|
|
||||||
dataframe['max'].shift(step) - dataframe['min'].shift(step)) / 3),
|
|
||||||
(dataframe['min'].shift(step) == dataframe['min']),
|
|
||||||
(dataframe['volume'] * dataframe['close'] / 1000 > 100),
|
|
||||||
(dataframe['rsi'] <= 30)
|
|
||||||
]
|
|
||||||
condition_bb_rolling2 = reduce(lambda x, y: x & y, condition_bb_rolling_2)
|
|
||||||
|
|
||||||
dataframe.loc[
|
|
||||||
condition_bb_rolling1 |
|
|
||||||
condition_bb_rolling2, 'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
dataframe.loc[
|
|
||||||
(
|
|
||||||
(dataframe['close'] < dataframe['open']) &
|
|
||||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
|
||||||
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
|
|
||||||
(dataframe['close'] < dataframe['bb_lowerband']) &
|
|
||||||
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe[
|
|
||||||
'bb_lowerband']) >= 0.02)
|
|
||||||
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
|
|
||||||
# ) | (
|
|
||||||
# (dataframe['close'] * 1.04 < dataframe['open'])
|
|
||||||
), 'sell'] = 1
|
|
||||||
return dataframe
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user