blockchain/internal/lib/strategy/rsi_test.go

72 lines
1.7 KiB
Go
Raw Normal View History

2025-08-20 12:35:31 +00:00
package strategy
import (
"github.com/shopspring/decimal"
"testing"
)
func TestRSI_WarmupAndRange(t *testing.T) {
n := 2
r := NewRSI(n)
type step struct {
close float64
wantReady bool
}
steps := []step{
{10, false}, // 第一根,只建立 prevC
{11, false}, // 第二根,累積
{12, true}, // 第三根,完成 seed -> ready
{13, true},
{12, true},
{11, true},
{12, true},
{13, true},
}
for i, st := range steps {
val, ready := r.Push(CandleForStrategy{C: dv(st.close)})
if ready != st.wantReady {
t.Fatalf("step %d: ready got=%v want=%v", i, ready, st.wantReady)
}
if ready {
// RSI 應落在 0..100
if val.LessThan(decimal.Zero) || val.GreaterThan(decimal.NewFromInt(100)) {
t.Fatalf("step %d: RSI out of [0,100], got %s", i, val)
}
}
}
}
func TestRSI_PerfectUpAndDown(t *testing.T) {
n := 2
r := NewRSI(n)
// 先 seed
_, _ = r.Push(CandleForStrategy{C: d(10)})
_, _ = r.Push(CandleForStrategy{C: d(11)})
val, ready := r.Push(CandleForStrategy{C: d(12)})
if !ready {
t.Fatalf("should be ready after %d candles", n)
}
// 連續上漲:理想情況 avgLoss -> 0RSI 逼近 100
val, ready = r.Push(CandleForStrategy{C: d(13)})
if !ready || !val.LessThanOrEqual(decimal.NewFromInt(100)) {
t.Fatalf("uptrend: ready=%v val=%s", ready, val)
}
// 連續下跌:理想情況 avgGain -> 0RSI 逼近 0
r = NewRSI(n)
_, _ = r.Push(CandleForStrategy{C: d(13)})
_, _ = r.Push(CandleForStrategy{C: d(12)})
val, ready = r.Push(CandleForStrategy{C: d(11)})
if !ready {
t.Fatalf("should be ready after %d candles", n)
}
val, ready = r.Push(CandleForStrategy{C: d(10)})
if !ready || !val.GreaterThanOrEqual(decimal.Zero) {
t.Fatalf("downtrend: ready=%v val=%s", ready, val)
}
}