全新的策略
This commit is contained in:
parent
9351d8b6dd
commit
7d5a14d9ec
@ -3,13 +3,13 @@ from pandas import DataFrame
|
||||
import pandas_ta as ta
|
||||
from freqtrade.exchange import timeframe_to_minutes
|
||||
|
||||
class FreqaiPrimer(IStrategy):
|
||||
class ShortTermMultiTimeframeStrategy(IStrategy):
|
||||
# 策略参数
|
||||
minimal_roi = {
|
||||
"0": 0.04, # 4% ROI(10 分钟内)
|
||||
"60": 0.02, # 2% ROI(1 小时)
|
||||
"180": 0.01, # 1% ROI(3 小时)
|
||||
"360": 0.0 # 0% ROI(6 小时)
|
||||
"0": 0.04, # 4% ROI (10 分钟内)
|
||||
"60": 0.02, # 2% ROI (1 小时)
|
||||
"180": 0.01, # 1% ROI (3 小时)
|
||||
"360": 0.0 # 0% ROI (6 小时)
|
||||
}
|
||||
|
||||
stoploss = -0.015 # 初始止损 -1.5%
|
||||
@ -27,6 +27,12 @@ class FreqaiPrimer(IStrategy):
|
||||
rsi_overbought = 70 # RSI 超买阈值
|
||||
rsi_oversold = 30 # RSI 超卖阈值
|
||||
|
||||
def informative_pairs(self):
|
||||
# 定义辅助时间框架
|
||||
pairs = self.dp.current_whitelist()
|
||||
informative_pairs = [(pair, '15m') for pair in pairs] + [(pair, '1h') for pair in pairs]
|
||||
return informative_pairs
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# 计算 3m 周期的指标
|
||||
bb_3m = ta.bbands(dataframe['close'], length=self.bb_length, std=self.bb_std)
|
||||
@ -46,7 +52,12 @@ class FreqaiPrimer(IStrategy):
|
||||
df_15m['bb_lower_15m'] = bb_15m[f'BBL_{self.bb_length}_{self.bb_std}']
|
||||
df_15m['bb_upper_15m'] = bb_15m[f'BBU_{self.bb_length}_{self.bb_std}']
|
||||
df_15m['rsi_15m'] = ta.rsi(df_15m['close'], length=self.rsi_length)
|
||||
dataframe = self.merge_informative_pair(dataframe, df_15m, self.timeframe, '15m')
|
||||
|
||||
# 手动合并 15m 数据
|
||||
df_15m = df_15m[['date', 'bb_lower_15m', 'bb_upper_15m', 'rsi_15m']]
|
||||
df_15m = df_15m.rename(columns={'date': 'date_15m'})
|
||||
dataframe = dataframe.merge(df_15m, how='left', left_on='date', right_on='date_15m')
|
||||
dataframe = dataframe.fillna(method='ffill') # 前向填充缺失值
|
||||
|
||||
# 获取 1h 数据
|
||||
df_1h = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='1h')
|
||||
@ -54,12 +65,55 @@ class FreqaiPrimer(IStrategy):
|
||||
df_1h['bb_lower_1h'] = bb_1h[f'BBL_{self.bb_length}_{self.bb_std}']
|
||||
df_1h['bb_upper_1h'] = bb_1h[f'BBU_{self.bb_length}_{self.bb_std}']
|
||||
df_1h['rsi_1h'] = ta.rsi(df_1h['close'], length=self.rsi_length)
|
||||
dataframe = self.merge_informative_pair(dataframe, df_1h, self.timeframe, '1h')
|
||||
|
||||
# 手动合并 1h 数据
|
||||
df_1h = df_1h[['date', 'bb_lower_1h', 'bb_upper_1h', 'rsi_1h']]
|
||||
df_1h = df_1h.rename(columns={'date': 'date_1h'})
|
||||
dataframe = dataframe.merge(df_1h, how='left', left_on='date', right_on='date_1h')
|
||||
dataframe = dataframe.fillna(method='ffill') # 前向填充缺失值
|
||||
|
||||
# K线形态:看涨吞没
|
||||
dataframe['bullish_engulfing'] = (
|
||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) & # 前一根是阴线
|
||||
(dataframe['close'] > dataframe['open']) & # 当前是阳线
|
||||
(dataframe['close'] > dataframe['open'].shift(1)) & # 吞没前一根
|
||||
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
|
||||
(dataframe['close'] > dataframe['open']) &
|
||||
(dataframe['close'] > dataframe['open'].shift(1)) &
|
||||
(dataframe['open'] < dataframe['close'].shift(1))
|
||||
)
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# 做多条件
|
||||
dataframe.loc[
|
||||
(
|
||||
(dataframe['close'] <= dataframe['bb_lower_3m']) &
|
||||
(dataframe['rsi_3m'] < self.rsi_oversold) &
|
||||
(dataframe['rsi_15m'] < self.rsi_oversold) &
|
||||
(dataframe['close'] <= dataframe['bb_lower_1h']) &
|
||||
(dataframe['bullish_engulfing']) &
|
||||
(dataframe['volume'] > dataframe['volume_ma'])
|
||||
),
|
||||
'enter_long'] = 1
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# 做多退出
|
||||
dataframe.loc[
|
||||
(
|
||||
(dataframe['close'] >= dataframe['bb_upper_3m']) |
|
||||
(dataframe['rsi_3m'] > self.rsi_overbought)
|
||||
),
|
||||
'exit_long'] = 1
|
||||
|
||||
return dataframe
|
||||
|
||||
def custom_stoploss(self, pair: str, trade: 'Trade', current_time, current_rate: float,
|
||||
current_profit: float, **kwargs) -> float:
|
||||
# 动态止损基于 ATR
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
last_candle = dataframe.iloc[-1]
|
||||
atr = last_candle['atr']
|
||||
if atr > 0:
|
||||
return -1.5 * atr / current_rate # 动态止损为 1.5 倍 ATR
|
||||
return self.stoploss # 回退到固定止损
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user