Files
Chan/strategies/EMA_Pattern.py
T
2025-10-31 20:34:27 +08:00

115 lines
5.4 KiB
Python

# --- Do not remove these libs ---
from statistics import median
from freqtrade.strategy import IStrategy
from technical.util import resample_to_interval, resampled_merge
from pandas import DataFrame
import talib.abstract as ta
from technical import qtpylib
### Now you can use logger.info('asfd') to log
# freqtrade plot-dataframe --strategy EMA_Pattern --datadir user_data/data/binance -c ./user_data/Chan/EMA_Pattern.json --timerange=20250309-
# freqtrade backtesting -c ./user_data/Chan/config/EMA_Pattern.json --strategy EMA_Pattern --strategy-path ./user_data/Chan/strategies --timerange=20251030-
# freqtrade download-data -c ./user_data/Chan/config/EMA_Pattern.json -t 1m 3m 5m 15m 30m 1h --pairs BTC/USDT:USDT --timerange=20250405-
# freqtrade download-data -c ./user_data/Chan/config/EMA_Pattern.json -t 1m 1h 1d 1M --pairs BTC/USDT --timerange=20170101-
# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLossDaily --spaces roi --strategy EMA_Pattern --strategy-path ./user_data/Chan/strategies -c ./user_data/Chan/config/EMA_Pattern.json -e 200 --timerange=20250201-20250901
# freqtrade edge -c ./user_data/Chan/config/EMA_Pattern.json --strategy EMA_Pattern --strategy-path ./user_data/Chan/strategies --timerange 20250721-20250901
# freqtrade plot-dataframe -c ./user_data/Chan/config/EMA_Pattern.json --strategy EMA_Pattern --strategy-path ./user_data/Chan/strategies --timerange 20250721-20250901
class EMA_Pattern(IStrategy):
time1h = 1440
can_short: bool = True
timeframe: str = "1m"
process_only_new_candles: bool = False
# ROI 与止损可根据需要在配置中覆盖
minimal_roi = {
"60": 0.005,
"30": 0.01,
"0": 0.02,
}
stoploss: float = -0.30
# 需要的历史K线数量(包含EMA等指标预热)
startup_candle_count: int = 200
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
if dataframe is None or dataframe.empty:
return dataframe
dataframe = self.add_indicators(dataframe)
return dataframe
def add_indicators(self, dataframe: DataFrame) -> DataFrame:
macd = ta.MACD(dataframe, timeperiod=12, fastperiod=12, slowperiod=26, signalperiod=9)
dataframe['macd'] = macd['macd']
dataframe['macdsignal'] = macd['macdsignal']
dataframe['macdhist'] = macd['macdhist']
dataframe['ema6'] = ta.EMA(dataframe, timeperiod=6)
dataframe['ema12'] = ta.EMA(dataframe, timeperiod=12)
dataframe['ema24'] = ta.EMA(dataframe, timeperiod=24)
dataframe['ema52'] = ta.EMA(dataframe, timeperiod=52)
dataframe['adx'] = ta.ADX(dataframe, timeperiod=14)
dataframe['strong_trend'] = dataframe['adx'] > 25
dataframe['UP_Pattern'] = (dataframe['ema6'] > dataframe['ema12']) & (dataframe['ema12'] > dataframe['ema24']) & (dataframe['ema24'] > dataframe['ema52'])
dataframe['DOWN_Pattern'] = (dataframe['ema6'] < dataframe['ema12']) & (dataframe['ema12'] < dataframe['ema24']) & (dataframe['ema24'] < dataframe['ema52'])
dataframe['UP_Confirm'] = (dataframe['ema6'] > dataframe['ema6'].shift(1)) & (dataframe['ema12'] > dataframe['ema12'].shift(1)) & (dataframe['ema24'] > dataframe['ema24'].shift(1)) & (dataframe['ema52'] > dataframe['ema52'].shift(1))
dataframe['DOWN_Confirm'] = (dataframe['ema6'] < dataframe['ema6'].shift(1)) & (dataframe['ema12'] < dataframe['ema12'].shift(1)) & (dataframe['ema24'] < dataframe['ema24'].shift(1)) & (dataframe['ema52'] < dataframe['ema52'].shift(1))
dataframe['EMA52_Cross_EMA24_UP'] = (dataframe['ema52'] < dataframe['ema24']) & (dataframe['ema52'].shift(1) > dataframe['ema24'].shift(1))
dataframe['EMA52_Cross_EMA24_DOWN'] = (dataframe['ema52'] > dataframe['ema24']) & (dataframe['ema52'].shift(1) < dataframe['ema24'].shift(1))
dataframe['Price_Above_EMA52'] = (dataframe['close'] > dataframe['ema52'])
dataframe['Price_Below_EMA52'] = (dataframe['close'] < dataframe['ema52'])
dataframe['MACD_Above_Zero'] = (dataframe['macd'] > 0) & (dataframe['macdsignal'] > 0)
dataframe['MACD_Below_Zero'] = (dataframe['macd'] < 0) & (dataframe['macdsignal'] < 0)
dataframe['BUY_END'] = dataframe['close'] < dataframe['ema52']
dataframe['SELL_END'] = dataframe['close'] > dataframe['ema52']
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
if dataframe is None or dataframe.empty:
return dataframe
dataframe.loc[
(
(dataframe['UP_Pattern']) &
(dataframe['UP_Confirm']) &
(dataframe['Price_Above_EMA52']) &
(dataframe['MACD_Above_Zero']) &
(dataframe['EMA52_Cross_EMA24_UP']) &
(dataframe['strong_trend'])
),
["enter_long", "enter_tag"],
] = (1, "ema_up_trend")
dataframe.loc[
(
(dataframe['DOWN_Pattern']) &
(dataframe['DOWN_Confirm']) &
(dataframe['Price_Below_EMA52']) &
(dataframe['MACD_Below_Zero']) &
(dataframe['EMA52_Cross_EMA24_DOWN']) &
(dataframe['strong_trend'])
),
["enter_short", "enter_tag"],
] = (1, "ema_down_trend")
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
if dataframe is None or dataframe.empty:
return dataframe
dataframe.loc[
(
(dataframe['BUY_END']) |
(dataframe['DOWN_Pattern']) |
(dataframe['EMA52_Cross_EMA24_DOWN'])
),
["exit_long", "exit_tag"],
] = (1, "ema_long_exit")
dataframe.loc[
(
(dataframe['SELL_END']) |
(dataframe['UP_Pattern']) |
(dataframe['EMA52_Cross_EMA24_UP'])
),
["exit_short", "exit_tag"],
] = (1, "ema_short_exit")
return dataframe
def get_ticker_indicator(self):
return int(self.timeframe[:-1])