无论在 live 还是回测模式下都能正常工作
This commit is contained in:
parent
5782f4d3a8
commit
60490ef078
@ -991,6 +991,12 @@ class FreqaiPrimer(IStrategy):
|
||||
dataframe['stochrsi_k_3m'] = stochrsi_3m[f'STOCHRSIk_{rsi_length_value}_{rsi_length_value}_3_3']
|
||||
dataframe['stochrsi_d_3m'] = stochrsi_3m[f'STOCHRSId_{rsi_length_value}_{rsi_length_value}_3_3']
|
||||
|
||||
# 新增 KDJ 指标(3m)
|
||||
kdj_3m = ta.stoch(high=dataframe['high'], low=dataframe['low'], close=dataframe['close'], k=9, d=3, smooth_k=3)
|
||||
dataframe['kdj_k_3m'] = kdj_3m['STOCHk_9_3_3']
|
||||
dataframe['kdj_d_3m'] = kdj_3m['STOCHd_9_3_3']
|
||||
dataframe['kdj_j_3m'] = 3 * dataframe['kdj_k_3m'] - 2 * dataframe['kdj_d_3m']
|
||||
|
||||
# 新增 MACD 指标
|
||||
macd_3m = ta.macd(dataframe['close'], fast=12, slow=26, signal=9)
|
||||
dataframe['macd_3m'] = macd_3m['MACD_12_26_9']
|
||||
@ -1085,6 +1091,12 @@ class FreqaiPrimer(IStrategy):
|
||||
df_1h['stochrsi_k_1h'] = stochrsi_1h[f'STOCHRSIk_{rsi_length_value}_{rsi_length_value}_3_3']
|
||||
df_1h['stochrsi_d_1h'] = stochrsi_1h[f'STOCHRSId_{rsi_length_value}_{rsi_length_value}_3_3']
|
||||
|
||||
# 新增 KDJ 指标(1h)
|
||||
kdj_1h = ta.stoch(high=df_1h['high'], low=df_1h['low'], close=df_1h['close'], k=9, d=3, smooth_k=3)
|
||||
df_1h['kdj_k_1h'] = kdj_1h['STOCHk_9_3_3']
|
||||
df_1h['kdj_d_1h'] = kdj_1h['STOCHd_9_3_3']
|
||||
df_1h['kdj_j_1h'] = 3 * df_1h['kdj_k_1h'] - 2 * df_1h['kdj_d_1h']
|
||||
|
||||
# 新增 MACD 指标
|
||||
macd_1h = ta.macd(df_1h['close'], fast=12, slow=26, signal=9)
|
||||
df_1h['macd_1h'] = macd_1h['MACD_12_26_9']
|
||||
@ -1193,6 +1205,7 @@ class FreqaiPrimer(IStrategy):
|
||||
df_1h = df_1h[[
|
||||
'date', 'rsi_1h', 'trend_1h', 'ema_50_1h', 'ema_200_1h',
|
||||
'bb_lower_1h', 'bb_upper_1h', 'stochrsi_k_1h', 'stochrsi_d_1h',
|
||||
'kdj_k_1h', 'kdj_d_1h', 'kdj_j_1h', # KDJ 指标
|
||||
'macd_1h', 'macd_signal_1h', 'ema_5_1h', 'ema_20_1h', 'ema5_cross_above_ema20',
|
||||
# === 1h 趋势特征 ===
|
||||
'adx_1h', 'plus_di_1h', 'minus_di_1h', # ADX 趋势强度
|
||||
@ -1317,6 +1330,12 @@ class FreqaiPrimer(IStrategy):
|
||||
# 条件4: RSI 进入超买区域(使用可优化的超买阈值)
|
||||
rsi_overbought = dataframe['rsi_1h'] > self.rsi_overbought.value
|
||||
|
||||
# 条件5: KDJ 高位死叉(3m KDJ 辅助出场)
|
||||
kdj_3m_exit = pd.Series(False, index=dataframe.index)
|
||||
if 'kdj_k_3m' in dataframe.columns and 'kdj_d_3m' in dataframe.columns:
|
||||
kdj_3m_death_cross = (dataframe['kdj_k_3m'] > 80) & (dataframe['kdj_k_3m'] < dataframe['kdj_d_3m']) & (dataframe['kdj_k_3m'].shift(1) >= dataframe['kdj_d_3m'].shift(1))
|
||||
kdj_3m_exit = kdj_3m_death_cross
|
||||
|
||||
# === 新增:1h 趋势反转检测 ===
|
||||
# 计算趋势反转得分(0-100,得分越高越可能反转)
|
||||
if 'ema_bear_align_1h' in dataframe.columns and 'adx_1h' in dataframe.columns:
|
||||
@ -1381,12 +1400,13 @@ class FreqaiPrimer(IStrategy):
|
||||
self.strategy_log(f"[{metadata['pair']}] 警告:缺少趋势特征,趋势出场禁用")
|
||||
|
||||
# === 最终出场条件 ===
|
||||
# 方案1:传统条件 OR 趋势反转
|
||||
# 方案1:传统条件 OR 趋势反转 OR KDJ 高位死叉
|
||||
final_condition = (
|
||||
breakout_condition |
|
||||
volume_spike |
|
||||
macd_downward |
|
||||
rsi_overbought |
|
||||
kdj_3m_exit |
|
||||
trend_protected_exit
|
||||
)
|
||||
|
||||
@ -1471,6 +1491,23 @@ class FreqaiPrimer(IStrategy):
|
||||
tech_score += vol_score
|
||||
tech_components += 1
|
||||
|
||||
# 1.6 KDJ 得分(3m + 1h 组合)
|
||||
# 3m KDJ:低位金叉加分
|
||||
if 'kdj_k_3m' in dataframe.columns and 'kdj_d_3m' in dataframe.columns:
|
||||
kdj_3m_golden = (dataframe['kdj_k_3m'] < 40) & (dataframe['kdj_k_3m'] > dataframe['kdj_d_3m']) & (dataframe['kdj_k_3m'].shift(1) <= dataframe['kdj_d_3m'].shift(1))
|
||||
kdj_3m_j_recovery = (dataframe['kdj_j_3m'] > 0) & (dataframe['kdj_j_3m'].shift(1) <= 0)
|
||||
kdj_3m_score = ((kdj_3m_golden | kdj_3m_j_recovery).astype(float) * 100)
|
||||
tech_score += kdj_3m_score
|
||||
tech_components += 1
|
||||
|
||||
# 1h KDJ:禁止极端高位(扣分机制)
|
||||
if 'kdj_k_1h' in dataframe.columns and 'kdj_j_1h' in dataframe.columns:
|
||||
kdj_1h_block = (dataframe['kdj_k_1h'] > 85) & (dataframe['kdj_j_1h'] < dataframe['kdj_j_1h'].shift(1))
|
||||
# 高位见顶时扣 50 分(通过乘以 -0.5 实现)
|
||||
kdj_1h_score = (~kdj_1h_block).astype(float) * 50 + 50 # 正常状态 100 分,见顶状态 50 分
|
||||
tech_score += kdj_1h_score
|
||||
tech_components += 1
|
||||
|
||||
# 计算技术指标平均得分
|
||||
if tech_components > 0:
|
||||
tech_score = tech_score / tech_components
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user