Files
StockRadar/internal/indicators/macd.go
T
2026-04-20 21:29:22 +02:00

94 lines
2.1 KiB
Go

package indicators
// MACDResult contient MACD line, signal line et histogramme.
type MACDResult struct {
MACD float64
Signal float64
Histogram float64
}
// MACD calcule le Moving Average Convergence Divergence (12/26/9 standard).
// Retourne zéro-value si pas assez de données.
func MACD(closes []float64) MACDResult {
return MACDCustom(closes, 12, 26, 9)
}
func MACDCustom(closes []float64, fast, slow, signal int) MACDResult {
if len(closes) < slow+signal {
return MACDResult{}
}
emaFast := emaSlice(closes, fast)
emaSlow := emaSlice(closes, slow)
// Aligner les deux séries (emaSlow est plus courte)
offset := len(emaFast) - len(emaSlow)
macdLine := make([]float64, len(emaSlow))
for i := range emaSlow {
macdLine[i] = emaFast[offset+i] - emaSlow[i]
}
if len(macdLine) < signal {
return MACDResult{}
}
signalLine := emaSlice(macdLine, signal)
last := macdLine[len(macdLine)-1]
sig := signalLine[len(signalLine)-1]
return MACDResult{
MACD: last,
Signal: sig,
Histogram: last - sig,
}
}
// SMA calcule la moyenne mobile simple sur les n dernières valeurs.
func SMA(closes []float64, period int) float64 {
if len(closes) < period {
return 0
}
slice := closes[len(closes)-period:]
sum := 0.0
for _, v := range slice {
sum += v
}
return sum / float64(period)
}
// AvgVolume calcule le volume moyen sur les n dernières barres.
func AvgVolume(volumes []int64, period int) int64 {
if len(volumes) < period {
period = len(volumes)
}
if period == 0 {
return 0
}
slice := volumes[len(volumes)-period:]
var sum int64
for _, v := range slice {
sum += v
}
return sum / int64(period)
}
func emaSlice(data []float64, period int) []float64 {
if len(data) < period {
return nil
}
k := 2.0 / float64(period+1)
// Première valeur = SMA des `period` premières
sum := 0.0
for i := 0; i < period; i++ {
sum += data[i]
}
ema := make([]float64, 0, len(data)-period+1)
ema = append(ema, sum/float64(period))
for i := period; i < len(data); i++ {
ema = append(ema, data[i]*k+ema[len(ema)-1]*(1-k))
}
return ema
}