debug log结合豆包对币对行情截图分析, 让grok进行优化 https://x.com/i/grok?conversation=1939204516592906372
This commit is contained in:
parent
5c36aabec4
commit
fcd39bfd31
@ -270,42 +270,50 @@ class FreqaiPrimer(IStrategy):
|
||||
]
|
||||
|
||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
"""
|
||||
生成买入信号,优化条件以增加交易机会
|
||||
"""
|
||||
pair = metadata.get('pair', 'Unknown')
|
||||
conditions = []
|
||||
pair = metadata.get('pair', 'Unknown')
|
||||
conditions = []
|
||||
|
||||
# 获取市场趋势得分
|
||||
trend_score = self.get_market_trend(dataframe=dataframe, metadata=metadata)
|
||||
|
||||
# 动态调整 cond2 和 cond3 的阈值
|
||||
# volume_z_score 阈值范围:0.5 (强牛市, trend_score=100) 到 2.0 (强熊市, trend_score=0)
|
||||
# 动态调整成交量阈值:牛市(trend_score=100)-> 0.5,熊市(trend_score=0)-> 1.5
|
||||
volume_z_score_min = 0.5
|
||||
volume_z_score_max = 2.0
|
||||
volume_z_score_max = 1.5
|
||||
volume_z_score_threshold = self.linear_map(trend_score, 0, 100, volume_z_score_max, volume_z_score_min)
|
||||
|
||||
# rsi 阈值范围:40 (强牛市, trend_score=100) 到 60 (强熊市, trend_score=0)
|
||||
# 动态调整 RSI 阈值:牛市(trend_score=100)-> 40,熊市(trend_score=0)-> 60
|
||||
rsi_min = 40
|
||||
rsi_max = 60
|
||||
rsi_threshold = self.linear_map(trend_score, 0, 100, rsi_max, rsi_min)
|
||||
|
||||
# 新增:动态调整 STOCHRSI 阈值,牛市 -> 30,熊市 -> 50
|
||||
stochrsi_min = 30
|
||||
stochrsi_max = 50
|
||||
stochrsi_threshold = self.linear_map(trend_score, 0, 100, stochrsi_max, stochrsi_min)
|
||||
|
||||
if "&-price_value_divergence" in dataframe.columns:
|
||||
# 计算 STOCHRSI
|
||||
stochrsi = ta.STOCHRSI(dataframe, timeperiod=14, fastk_period=3, fastd_period=3)
|
||||
dataframe["stochrsi_k"] = stochrsi["fastk"]
|
||||
|
||||
cond1 = (dataframe["&-price_value_divergence"] < self.buy_threshold)
|
||||
cond2 = (dataframe["volume_z_score"] > volume_z_score_threshold)
|
||||
cond3 = (dataframe["rsi"] < rsi_threshold)
|
||||
cond4 = (dataframe["close"] <= dataframe["bb_lowerband"])
|
||||
buy_condition = cond1 & cond2 & cond3 & cond4
|
||||
cond5 = (dataframe["stochrsi_k"] < stochrsi_threshold) # 新增 STOCHRSI 条件
|
||||
buy_condition = cond1 & cond2 & cond3 & cond4 & cond5
|
||||
conditions.append(buy_condition)
|
||||
|
||||
divergence_value = dataframe['&-price_value_divergence'].iloc[-1] if not dataframe['&-price_value_divergence'].isna().all() else np.nan
|
||||
volume_z_score_value = dataframe['volume_z_score'].iloc[-1] if not dataframe['volume_z_score'].isna().all() else np.nan
|
||||
rsi_value = dataframe['rsi'].iloc[-1] if not dataframe['rsi'].isna().all() else np.nan
|
||||
stochrsi_value = dataframe['stochrsi_k'].iloc[-1] if not dataframe['stochrsi_k'].isna().all() else np.nan
|
||||
logger.debug(f"[{pair}] 买入条件检查 - "
|
||||
f"&-price_value_divergence={divergence_value:.6f} < {self.buy_threshold:.6f}: {cond1.iloc[-1]}, "
|
||||
f"volume_z_score={volume_z_score_value:.2f} > {volume_z_score_threshold:.2f}: {cond2.iloc[-1]}, "
|
||||
f"rsi={rsi_value:.2f} < {rsi_threshold:.2f}: {cond3.iloc[-1]}, "
|
||||
f"close={dataframe['close'].iloc[-1]:.6f} <= bb_lowerband={dataframe['bb_lowerband'].iloc[-1]:.6f}: {cond4.iloc[-1]}")
|
||||
f"close={dataframe['close'].iloc[-1]:.6f} <= bb_lowerband={dataframe['bb_lowerband'].iloc[-1]:.6f}: {cond4.iloc[-1]}, "
|
||||
f"stochrsi_k={stochrsi_value:.2f} < {stochrsi_threshold:.2f}: {cond5.iloc[-1]}")
|
||||
else:
|
||||
logger.warning(f"[{pair}] ⚠️ &-price_value_divergence 列缺失,跳过买入信号生成")
|
||||
|
||||
@ -320,7 +328,6 @@ class FreqaiPrimer(IStrategy):
|
||||
logger.debug(f"[{pair}] 无有效买入条件")
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
pair = metadata.get('pair', 'Unknown')
|
||||
conditions = []
|
||||
@ -515,43 +522,27 @@ class FreqaiPrimer(IStrategy):
|
||||
return adjusted_rate
|
||||
|
||||
def get_market_trend(self, dataframe: DataFrame = None, metadata: dict = None) -> int:
|
||||
"""
|
||||
计算市场趋势得分,0 表示强熊,100 表示强牛,50 表示中性。
|
||||
综合 3m、15m 和 1h 时间框架的趋势,使用对数函数映射,非线性增强两端趋势。
|
||||
融合价格趋势、K 线形态、StochRSI 和量价关系。
|
||||
|
||||
参数:
|
||||
dataframe: 可选,外部传入的 BTC/USDT 数据(3m 时间框架),默认为 None(自动获取)。
|
||||
metadata: 可选,包含币种信息。
|
||||
|
||||
返回值:
|
||||
int: 0-100 的趋势得分。
|
||||
"""
|
||||
try:
|
||||
# 初始化得分和权重
|
||||
timeframes = ["3m", "15m", "1h"]
|
||||
weights = {"3m": 0.5, "15m": 0.3, "1h": 0.2} # 短期框架权重更高
|
||||
weights = {"3m": 0.5, "15m": 0.3, "1h": 0.2} # 默认权重
|
||||
trend_scores = {}
|
||||
|
||||
pair = metadata.get('pair', 'Unknown') if metadata else 'Unknown'
|
||||
logger.debug(f"[{pair}] 正在计算多时间框架市场趋势得分")
|
||||
|
||||
for tf in timeframes:
|
||||
# 获取对应时间框架的数据
|
||||
if tf == "3m" and dataframe is not None:
|
||||
btc_df = dataframe
|
||||
else:
|
||||
btc_df = self.dp.get_pair_dataframe("BTC/USDT", tf)
|
||||
|
||||
# 检查数据量
|
||||
min_candles = 200 if tf == "3m" else 100 if tf == "15m" else 50 # 不同时间框架所需最小数据量
|
||||
min_candles = 200 if tf == "3m" else 100 if tf == "15m" else 50
|
||||
if len(btc_df) < min_candles:
|
||||
logger.warning(f"BTC 数据不足({tf},{len(btc_df)} 根K线),使用默认得分:50")
|
||||
trend_scores[tf] = 50
|
||||
continue
|
||||
|
||||
# --- 价格趋势 ---
|
||||
ema_short_period = 50 if tf == "3m" else 20 if tf == "15m" else 12 # 调整周期以适应时间框架
|
||||
# 价格趋势
|
||||
ema_short_period = 50 if tf == "3m" else 20 if tf == "15m" else 12
|
||||
ema_long_period = 200 if tf == "3m" else 80 if tf == "15m" else 50
|
||||
btc_df["ema_short"] = ta.EMA(btc_df, timeperiod=ema_short_period)
|
||||
btc_df["ema_long"] = ta.EMA(btc_df, timeperiod=ema_long_period)
|
||||
@ -571,7 +562,7 @@ class FreqaiPrimer(IStrategy):
|
||||
elif ema_short_slope < -0.005:
|
||||
price_score -= 15
|
||||
|
||||
# --- K 线形态 ---
|
||||
# K线形态
|
||||
btc_df["bullish_engulfing"] = (
|
||||
(btc_df["close"].shift(1) < btc_df["open"].shift(1)) &
|
||||
(btc_df["close"] > btc_df["open"]) &
|
||||
@ -588,13 +579,13 @@ class FreqaiPrimer(IStrategy):
|
||||
kline_score = 0
|
||||
if btc_df["bullish_engulfing"].iloc[-1]:
|
||||
kline_score += 15
|
||||
elif btc_df["bearish_engulfing"].iloc[-1]:
|
||||
elif btc_df["bearish_engulfing"]:
|
||||
kline_score -= 15
|
||||
volatility = btc_df["close"].pct_change(10).std() * 100
|
||||
if volatility > 0.5:
|
||||
kline_score += 10 if price_score > 0 else -10
|
||||
|
||||
# --- StochRSI ---
|
||||
# StochRSI
|
||||
stochrsi = ta.STOCHRSI(btc_df, timeperiod=14, fastk_period=3, fastd_period=3)
|
||||
btc_df["stochrsi_k"] = stochrsi["fastk"]
|
||||
btc_df["stochrsi_d"] = stochrsi["fastd"]
|
||||
@ -611,7 +602,7 @@ class FreqaiPrimer(IStrategy):
|
||||
elif stochrsi_k < 50:
|
||||
stochrsi_score -= 5
|
||||
|
||||
# --- 量价关系 ---
|
||||
# 量价关系
|
||||
btc_df["volume_mean_20"] = btc_df["volume"].rolling(20).mean()
|
||||
btc_df["volume_std_20"] = btc_df["volume"].rolling(20).std()
|
||||
btc_df["volume_z_score"] = (btc_df["volume"] - btc_df["volume_mean_20"]) / btc_df["volume_std_20"]
|
||||
@ -623,7 +614,7 @@ class FreqaiPrimer(IStrategy):
|
||||
if btc_df["adx"].iloc[-1] > 25:
|
||||
volume_score += 10 if price_score > 0 else -10
|
||||
|
||||
# --- 综合得分 ---
|
||||
# 综合得分
|
||||
raw_score = price_score + kline_score + stochrsi_score + volume_score
|
||||
raw_score = max(min(raw_score, 50), -50)
|
||||
|
||||
@ -638,14 +629,19 @@ class FreqaiPrimer(IStrategy):
|
||||
f"价格得分:{price_score}, K线得分:{kline_score}, "
|
||||
f"StochRSI得分:{stochrsi_score}, 量价得分:{volume_score}")
|
||||
|
||||
# 加权融合多时间框架得分
|
||||
# 动态调整权重:当 1h 得分显著高于 3m(差值 > 20),提高 1h 权重
|
||||
if trend_scores.get("1h", 50) - trend_scores.get("3m", 50) > 20:
|
||||
weights = {"3m": 0.3, "15m": 0.3, "1h": 0.4}
|
||||
logger.debug(f"[{pair}] 1h 趋势得分({trend_scores.get('1h', 50)})显著高于 3m({trend_scores.get('3m', 50)}),调整权重为 {weights}")
|
||||
|
||||
# 加权融合
|
||||
final_score = sum(trend_scores[tf] * weights[tf] for tf in timeframes)
|
||||
final_score = int(round(final_score))
|
||||
final_score = max(0, min(100, final_score))
|
||||
|
||||
logger.info(f"[{pair}] 最终趋势得分:{final_score}, "
|
||||
f"3m得分:{trend_scores.get('3m', 50)}, 15m得分:{trend_scores.get('15m', 50)}, "
|
||||
f"1h得分:{trend_scores.get('1h', 50)}")
|
||||
f"3m得分:{trend_scores.get('3m', 50)}, 15m得分:{trend_scores.get('15m', 50)}, "
|
||||
f"1h得分:{trend_scores.get('1h', 50)}")
|
||||
return final_score
|
||||
|
||||
except Exception as e:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user