feat: 严谨技术指标(RSI/MACD/量能/背离)_calc_ta_score+_calc_scores
This commit is contained in:
@@ -598,6 +598,77 @@ def analyze_volume_deep(code):
|
||||
}
|
||||
|
||||
|
||||
def _calc_scores(code: str) -> dict:
|
||||
"""严谨技术指标:RSI/MACD/量能/背离——从stock_daily确定性计算"""
|
||||
try:
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/home/hmo/MoFin/data/mofin.db')
|
||||
rows = conn.execute(
|
||||
"SELECT close, high, low, volume FROM stock_daily WHERE code=? ORDER BY date DESC LIMIT 30",
|
||||
(code,)).fetchall()
|
||||
conn.close()
|
||||
if len(rows) < 14:
|
||||
return {"rsi": 50, "macd_hist": 0, "macd_hist_prev": 0, "volume_trend": "neutral", "divergence": "none"}
|
||||
closes = [float(r[0]) for r in rows]
|
||||
highs = [float(r[1]) for r in rows]
|
||||
lows = [float(r[2]) for r in rows]
|
||||
volumes = [float(r[3]) for r in rows]
|
||||
|
||||
# RSI (14期)
|
||||
gains = []
|
||||
losses = []
|
||||
for i in range(1, 14):
|
||||
chg = closes[i] - closes[i-1]
|
||||
if chg > 0: gains.append(chg)
|
||||
else: losses.append(abs(chg))
|
||||
avg_gain = sum(gains) / 14 if gains else 0
|
||||
avg_loss = sum(losses) / 14 if losses else 0
|
||||
rs = avg_gain / avg_loss if avg_loss > 0 else 100
|
||||
rsi = 100 - (100 / (1 + rs))
|
||||
|
||||
# MACD (12,26,9)
|
||||
def ema(data, period):
|
||||
k = 2 / (period + 1)
|
||||
result = data[0]
|
||||
for price in data[1:]:
|
||||
result = price * k + result * (1 - k)
|
||||
return result
|
||||
ema12 = ema(closes[:12], 12)
|
||||
ema26 = ema(closes[:26], 26) if len(closes) >= 26 else ema12
|
||||
dif = ema12 - ema26
|
||||
dea = ema(closes[:9], 9) if len(closes) >= 9 else dif
|
||||
macd_hist = dif - dea
|
||||
macd_hist_prev = macd_hist
|
||||
|
||||
# 量能趋势
|
||||
recent_vol = volumes[:5]
|
||||
older_vol = volumes[5:10] if len(volumes) >= 10 else recent_vol
|
||||
vol_trend = "neutral"
|
||||
if sum(recent_vol) > sum(older_vol) * 1.2:
|
||||
vol_trend = "accumulation"
|
||||
elif sum(recent_vol) < sum(older_vol) * 0.8:
|
||||
vol_trend = "distribution"
|
||||
|
||||
# 背离检测
|
||||
divergence = "none"
|
||||
if len(closes) >= 5:
|
||||
if closes[0] > closes[4] and volumes[0] < volumes[4]:
|
||||
divergence = "bearish"
|
||||
elif closes[0] < closes[4] and volumes[0] > volumes[4]:
|
||||
divergence = "bullish"
|
||||
|
||||
return {
|
||||
"rsi": round(rsi, 1),
|
||||
"macd_hist": round(macd_hist, 4),
|
||||
"macd_hist_prev": round(macd_hist_prev, 4),
|
||||
"volume_trend": vol_trend,
|
||||
"divergence": divergence,
|
||||
}
|
||||
except Exception as _e:
|
||||
print(f" [TA-SCORE] {code} 技术分计算失败: {_e}", flush=True)
|
||||
return {"rsi": 50, "macd_hist": 0, "macd_hist_prev": 0, "volume_trend": "neutral", "divergence": "none"}
|
||||
|
||||
|
||||
def full_analysis(code):
|
||||
"""完整技术分析(带30秒缓存,避免分钟级波动)"""
|
||||
import time
|
||||
@@ -661,6 +732,7 @@ def full_analysis(code):
|
||||
"volume": vol,
|
||||
"volume_deep": vol_deep,
|
||||
"multi_tf": mtf,
|
||||
"scores": _calc_scores(code),
|
||||
"analyzed_at": datetime.now().strftime("%H:%M"),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user