blockchain/internal/lib/strategy/macd.go

90 lines
2.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package strategy
import (
"sync/atomic"
"github.com/shopspring/decimal"
)
// =========================
// MACD單寫快照多讀
// fastEMA / slowEMA 吃「收盤價」signalEMA 吃「MACDLine」
// 與 EMA/SMA 一致風格Update()單寫、Load()(多讀)
// =========================
// MACDSnapshot 對外發佈的不可變快照
type MACDSnapshot struct {
Params [3]uint // (fast, slow, signal)
LastPrice decimal.Decimal // 最近一次喂入的收盤價
MACDLine decimal.Decimal // DIF = fastEMA - slowEMA
SignalLine decimal.Decimal // DEA = EMA(MACDLine, signalPeriod)
Histogram decimal.Decimal // Hist = MACDLine - SignalLine
Ready bool // 三條線皆 ready 才會 true
}
// MACD 快照發佈器(單寫多讀)
type MACD struct {
// 內部用你已完成的 EMA其本身就含 SMA-seed 與 ready 狀態)
fastEMA *EMA
slowEMA *EMA
signalEMA *EMA
fastPeriod, slowPeriod, signalPeriod uint
last decimal.Decimal // 只作紀錄debug/觀察用)
snap atomic.Value // holds MACDSnapshot
}
// NewMACD 建立 MACD預設 12,26,9也可自訂
func NewMACD(fast, slow, signal uint) *MACD {
if !(fast > 0 && slow > 0 && signal > 0) {
panic("MACD periods must be > 0")
}
if fast >= slow {
panic("MACD requires fast < slow (e.g., 12 < 26)")
}
m := &MACD{
fastEMA: NewEMA(fast),
slowEMA: NewEMA(slow),
signalEMA: NewEMA(signal),
fastPeriod: fast,
slowPeriod: slow,
signalPeriod: signal,
}
// 初始化一個空快照
m.snap.Store(MACDSnapshot{Params: [3]uint{fast, slow, signal}})
return m
}
// Update 僅供單一 writer 呼叫;回傳並發佈最新快照
func (m *MACD) Update(close decimal.Decimal) MACDSnapshot {
// 先用 EMA你已改好的版本各自更新快、慢線
fast := m.fastEMA.Update(close)
slow := m.slowEMA.Update(close)
macdLine := fast.Value.Sub(slow.Value)
// 信號線吃的是 MACDLine非收盤價
sig := m.signalEMA.Update(macdLine)
ready := fast.Ready && slow.Ready && sig.Ready
snap := MACDSnapshot{
Params: [3]uint{m.fastPeriod, m.slowPeriod, m.signalPeriod},
LastPrice: close,
MACDLine: macdLine,
SignalLine: sig.Value,
Histogram: macdLine.Sub(sig.Value),
Ready: ready,
}
m.last = close
m.snap.Store(snap)
return snap
}
// Load 多 goroutine 零鎖讀取最新快照
func (m *MACD) Load() MACDSnapshot {
return m.snap.Load().(MACDSnapshot)
}