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:
|
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)
|
trend_score = self.get_market_trend(dataframe=dataframe, metadata=metadata)
|
||||||
|
|
||||||
# 动态调整 cond2 和 cond3 的阈值
|
# 动态调整成交量阈值:牛市(trend_score=100)-> 0.5,熊市(trend_score=0)-> 1.5
|
||||||
# volume_z_score 阈值范围:0.5 (强牛市, trend_score=100) 到 2.0 (强熊市, trend_score=0)
|
|
||||||
volume_z_score_min = 0.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)
|
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_min = 40
|
||||||
rsi_max = 60
|
rsi_max = 60
|
||||||
rsi_threshold = self.linear_map(trend_score, 0, 100, rsi_max, rsi_min)
|
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:
|
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)
|
cond1 = (dataframe["&-price_value_divergence"] < self.buy_threshold)
|
||||||
cond2 = (dataframe["volume_z_score"] > volume_z_score_threshold)
|
cond2 = (dataframe["volume_z_score"] > volume_z_score_threshold)
|
||||||
cond3 = (dataframe["rsi"] < rsi_threshold)
|
cond3 = (dataframe["rsi"] < rsi_threshold)
|
||||||
cond4 = (dataframe["close"] <= dataframe["bb_lowerband"])
|
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)
|
conditions.append(buy_condition)
|
||||||
|
|
||||||
divergence_value = dataframe['&-price_value_divergence'].iloc[-1] if not dataframe['&-price_value_divergence'].isna().all() else np.nan
|
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
|
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
|
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}] 买入条件检查 - "
|
logger.debug(f"[{pair}] 买入条件检查 - "
|
||||||
f"&-price_value_divergence={divergence_value:.6f} < {self.buy_threshold:.6f}: {cond1.iloc[-1]}, "
|
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"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"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:
|
else:
|
||||||
logger.warning(f"[{pair}] ⚠️ &-price_value_divergence 列缺失,跳过买入信号生成")
|
logger.warning(f"[{pair}] ⚠️ &-price_value_divergence 列缺失,跳过买入信号生成")
|
||||||
|
|
||||||
@ -320,7 +328,6 @@ class FreqaiPrimer(IStrategy):
|
|||||||
logger.debug(f"[{pair}] 无有效买入条件")
|
logger.debug(f"[{pair}] 无有效买入条件")
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
pair = metadata.get('pair', 'Unknown')
|
pair = metadata.get('pair', 'Unknown')
|
||||||
conditions = []
|
conditions = []
|
||||||
@ -515,43 +522,27 @@ class FreqaiPrimer(IStrategy):
|
|||||||
return adjusted_rate
|
return adjusted_rate
|
||||||
|
|
||||||
def get_market_trend(self, dataframe: DataFrame = None, metadata: dict = None) -> int:
|
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:
|
try:
|
||||||
# 初始化得分和权重
|
|
||||||
timeframes = ["3m", "15m", "1h"]
|
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 = {}
|
trend_scores = {}
|
||||||
|
|
||||||
pair = metadata.get('pair', 'Unknown') if metadata else 'Unknown'
|
pair = metadata.get('pair', 'Unknown') if metadata else 'Unknown'
|
||||||
logger.debug(f"[{pair}] 正在计算多时间框架市场趋势得分")
|
logger.debug(f"[{pair}] 正在计算多时间框架市场趋势得分")
|
||||||
|
|
||||||
for tf in timeframes:
|
for tf in timeframes:
|
||||||
# 获取对应时间框架的数据
|
|
||||||
if tf == "3m" and dataframe is not None:
|
if tf == "3m" and dataframe is not None:
|
||||||
btc_df = dataframe
|
btc_df = dataframe
|
||||||
else:
|
else:
|
||||||
btc_df = self.dp.get_pair_dataframe("BTC/USDT", tf)
|
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:
|
if len(btc_df) < min_candles:
|
||||||
logger.warning(f"BTC 数据不足({tf},{len(btc_df)} 根K线),使用默认得分:50")
|
logger.warning(f"BTC 数据不足({tf},{len(btc_df)} 根K线),使用默认得分:50")
|
||||||
trend_scores[tf] = 50
|
trend_scores[tf] = 50
|
||||||
continue
|
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
|
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_short"] = ta.EMA(btc_df, timeperiod=ema_short_period)
|
||||||
btc_df["ema_long"] = ta.EMA(btc_df, timeperiod=ema_long_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:
|
elif ema_short_slope < -0.005:
|
||||||
price_score -= 15
|
price_score -= 15
|
||||||
|
|
||||||
# --- K 线形态 ---
|
# K线形态
|
||||||
btc_df["bullish_engulfing"] = (
|
btc_df["bullish_engulfing"] = (
|
||||||
(btc_df["close"].shift(1) < btc_df["open"].shift(1)) &
|
(btc_df["close"].shift(1) < btc_df["open"].shift(1)) &
|
||||||
(btc_df["close"] > btc_df["open"]) &
|
(btc_df["close"] > btc_df["open"]) &
|
||||||
@ -588,13 +579,13 @@ class FreqaiPrimer(IStrategy):
|
|||||||
kline_score = 0
|
kline_score = 0
|
||||||
if btc_df["bullish_engulfing"].iloc[-1]:
|
if btc_df["bullish_engulfing"].iloc[-1]:
|
||||||
kline_score += 15
|
kline_score += 15
|
||||||
elif btc_df["bearish_engulfing"].iloc[-1]:
|
elif btc_df["bearish_engulfing"]:
|
||||||
kline_score -= 15
|
kline_score -= 15
|
||||||
volatility = btc_df["close"].pct_change(10).std() * 100
|
volatility = btc_df["close"].pct_change(10).std() * 100
|
||||||
if volatility > 0.5:
|
if volatility > 0.5:
|
||||||
kline_score += 10 if price_score > 0 else -10
|
kline_score += 10 if price_score > 0 else -10
|
||||||
|
|
||||||
# --- StochRSI ---
|
# StochRSI
|
||||||
stochrsi = ta.STOCHRSI(btc_df, timeperiod=14, fastk_period=3, fastd_period=3)
|
stochrsi = ta.STOCHRSI(btc_df, timeperiod=14, fastk_period=3, fastd_period=3)
|
||||||
btc_df["stochrsi_k"] = stochrsi["fastk"]
|
btc_df["stochrsi_k"] = stochrsi["fastk"]
|
||||||
btc_df["stochrsi_d"] = stochrsi["fastd"]
|
btc_df["stochrsi_d"] = stochrsi["fastd"]
|
||||||
@ -611,7 +602,7 @@ class FreqaiPrimer(IStrategy):
|
|||||||
elif stochrsi_k < 50:
|
elif stochrsi_k < 50:
|
||||||
stochrsi_score -= 5
|
stochrsi_score -= 5
|
||||||
|
|
||||||
# --- 量价关系 ---
|
# 量价关系
|
||||||
btc_df["volume_mean_20"] = btc_df["volume"].rolling(20).mean()
|
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_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"]
|
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:
|
if btc_df["adx"].iloc[-1] > 25:
|
||||||
volume_score += 10 if price_score > 0 else -10
|
volume_score += 10 if price_score > 0 else -10
|
||||||
|
|
||||||
# --- 综合得分 ---
|
# 综合得分
|
||||||
raw_score = price_score + kline_score + stochrsi_score + volume_score
|
raw_score = price_score + kline_score + stochrsi_score + volume_score
|
||||||
raw_score = max(min(raw_score, 50), -50)
|
raw_score = max(min(raw_score, 50), -50)
|
||||||
|
|
||||||
@ -638,14 +629,19 @@ class FreqaiPrimer(IStrategy):
|
|||||||
f"价格得分:{price_score}, K线得分:{kline_score}, "
|
f"价格得分:{price_score}, K线得分:{kline_score}, "
|
||||||
f"StochRSI得分:{stochrsi_score}, 量价得分:{volume_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 = sum(trend_scores[tf] * weights[tf] for tf in timeframes)
|
||||||
final_score = int(round(final_score))
|
final_score = int(round(final_score))
|
||||||
final_score = max(0, min(100, final_score))
|
final_score = max(0, min(100, final_score))
|
||||||
|
|
||||||
logger.info(f"[{pair}] 最终趋势得分:{final_score}, "
|
logger.info(f"[{pair}] 最终趋势得分:{final_score}, "
|
||||||
f"3m得分:{trend_scores.get('3m', 50)}, 15m得分:{trend_scores.get('15m', 50)}, "
|
f"3m得分:{trend_scores.get('3m', 50)}, 15m得分:{trend_scores.get('15m', 50)}, "
|
||||||
f"1h得分:{trend_scores.get('1h', 50)}")
|
f"1h得分:{trend_scores.get('1h', 50)}")
|
||||||
return final_score
|
return final_score
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user