This commit is contained in:
2026-02-25 11:04:03 +08:00
parent 24fe2a97cf
commit 13cb1ed479
8 changed files with 118 additions and 92 deletions

View File

@@ -44,6 +44,7 @@ MACD在0轴下方金叉后股价小幅调整导致快慢线黏合但并未
import (
"fmt"
"math"
"strings"
"git.apinb.com/bsm-sdk/core/utils"
"git.apinb.com/quant/gostock/internal/impl"
@@ -57,11 +58,21 @@ const (
defaultMacdSignal = 9
)
var (
desc []string
)
type MacdResult struct {
Score int
Val float64
Desc string
}
// RunMacd 根据MACD红绿柱及价量关系对当前标的进行打分与描述
func (r *IndicatorFactory) RunMacd() (int, string) {
args, _, err := GetArgConfig(r.Model.Code)
func RunMacd(code string) *MacdResult {
args, _, err := GetArgConfig(code)
if err != nil {
return -1, "MACD参数错误"
return &MacdResult{Score: -1, Desc: "MACD参数错误"}
}
fast := args.EmaFast
@@ -85,19 +96,19 @@ func (r *IndicatorFactory) RunMacd() (int, string) {
var vols []float64
impl.DBService.Model(models.StockDaily{}).
Where("ts_code = ?", r.Model.Code).
Where("ts_code = ?", code).
Order("trade_date desc").
Limit(limit).
Pluck("close", &closes)
impl.DBService.Model(models.StockDaily{}).
Where("ts_code = ?", r.Model.Code).
Where("ts_code = ?", code).
Order("trade_date desc").
Limit(limit).
Pluck("vol", &vols)
if len(closes) < slow+signal+5 {
return -1, "MACD 数据不足"
return &MacdResult{Score: -1, Desc: "MACD 数据不足"}
}
closes = ReverseSlice(closes)
@@ -112,7 +123,7 @@ func (r *IndicatorFactory) RunMacd() (int, string) {
macdLine, signalLine, hist := talib.Macd(closes, fast, slow, signal)
n := len(hist)
if n < 5 {
return -1, "MACD 计算结果不足"
return &MacdResult{Score: -1, Desc: "MACD 计算结果不足"}
}
lastIdx := n - 1
@@ -123,33 +134,33 @@ func (r *IndicatorFactory) RunMacd() (int, string) {
lastMacd := macdLine[lastIdx]
lastSignal := signalLine[lastIdx]
r.Model.MacdVal = utils.FloatRound(lastHist, 4)
macdVal := utils.FloatRound(lastHist, 4)
score := -1
// 3.1 基础买入信号:绿柱转红柱,零轴下方或附近
if prevHist < 0 && lastHist > 0 && lastMacd <= 0 {
score = maxInt(score, 1)
return score, fmt.Sprintf("MACD红绿柱反转由绿转红零轴下方/附近hist=%.4f", lastHist)
desc = append(desc, "MACD红绿柱反转由绿转红零轴下方/附近")
}
// 3.2 趋势跟随买入红柱连续伸长DIF/DEA在零轴上方
if lastMacd > 0 && lastSignal > 0 && isGrowingPositive(hist, 3) {
score = maxInt(score, 2)
return score, "MACD红柱连续伸长DIF/DEA零轴上方趋势跟随买入信号"
desc = append(desc, "MACD红柱连续伸长DIF/DEA零轴上方趋势跟随买入信号")
}
// 3.4 底背离买入:价格新低但绿柱底部抬高,随后红柱确认
if lastHist > 0 && hasBottomDivergence(closes, hist) {
score = maxInt(score, 2)
return score, "MACD底背离:价格新低但绿柱底部抬高,红柱确认"
desc = append(desc, "MACD价格新低但绿柱底部抬高后续红柱确认")
}
// 5.1 零轴下金叉后的拒绝死叉:金叉发生在零轴下方,之后未形成有效死叉,红柱再次放大
if lastHist > 0 && isGrowingPositive(hist, 2) && hasGoldenCrossRejection(macdLine, signalLine, hist) {
score = maxInt(score, 3)
return score, "MACD零轴下金叉后拒绝死叉红柱再次放大,疑似洗盘结束主升浪启动"
desc = append(desc, "MACD零轴下金叉后拒绝死叉红柱再次放大")
}
// 成交量验证:红柱放大但缩量,降低一次评分
@@ -159,17 +170,21 @@ func (r *IndicatorFactory) RunMacd() (int, string) {
if score <= 0 {
score = -1
}
return score, "MACD红柱放大但成交量未同步放大信号可靠性降低"
return &MacdResult{Score: score, Val: macdVal, Desc: "MACD红柱放大但成交量未同步放大信号可靠性降低"}
}
}
if score == -1 {
if lastHist <= 0 {
return -1, fmt.Sprintf("MACD未出现明确多头信号hist=%.4f", lastHist)
return &MacdResult{Score: -1, Val: macdVal, Desc: fmt.Sprintf("MACD未出现明确多头信号hist=%.4f", lastHist)}
}
}
return score, "无信号"
if score > 0 {
return &MacdResult{Score: score, Val: macdVal, Desc: strings.Join(desc, "||")}
}
return &MacdResult{Score: -1, Val: macdVal, Desc: "无信号"}
}
// 最近k根红柱是否连续伸长严格递增且均为正
@@ -329,4 +344,3 @@ func maxInt(a, b int) int {
}
return b
}