This commit is contained in:
2026-04-20 21:29:22 +02:00
parent 53dd49612d
commit 89fc0119f3
25 changed files with 3744 additions and 134 deletions
+93
View File
@@ -0,0 +1,93 @@
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
}
+43
View File
@@ -0,0 +1,43 @@
package indicators
// RSI calcule le Relative Strength Index (Wilder's smoothing, période 14).
// Retourne NaN si pas assez de données.
func RSI(closes []float64, period int) float64 {
if period <= 0 {
period = 14
}
if len(closes) < period+1 {
return -1
}
var gains, losses float64
for i := 1; i <= period; i++ {
delta := closes[i] - closes[i-1]
if delta > 0 {
gains += delta
} else {
losses -= delta
}
}
avgGain := gains / float64(period)
avgLoss := losses / float64(period)
// Wilder's smoothing pour le reste
for i := period + 1; i < len(closes); i++ {
delta := closes[i] - closes[i-1]
if delta > 0 {
avgGain = (avgGain*float64(period-1) + delta) / float64(period)
avgLoss = (avgLoss * float64(period-1)) / float64(period)
} else {
avgGain = (avgGain * float64(period-1)) / float64(period)
avgLoss = (avgLoss*float64(period-1) - delta) / float64(period)
}
}
if avgLoss == 0 {
return 100
}
rs := avgGain / avgLoss
return 100 - (100 / (1 + rs))
}