blockchain/internal/lib/strategy/ring_queue.go

51 lines
1.3 KiB
Go
Raw Normal View History

2025-08-14 23:41:29 +00:00
package strategy
import (
"container/list"
"github.com/shopspring/decimal"
)
/************** 基礎的固定長度隊列,用來計算移動平均 **************/
type ringQD struct {
N int // 窗口大小(需要保留的資料數量)
l *list.List // 用於儲存資料的雙向鏈表
sum decimal.Decimal // 當前窗口的總和,方便快速計算平均值
}
// 建立一個固定長度的隊列
func newRingQD(n int) *ringQD {
return &ringQD{N: n, l: list.New(), sum: decimal.Zero}
}
// push將新的數值放入隊列並維護總和
func (q *ringQD) push(x decimal.Decimal) {
q.l.PushBack(x)
q.sum = q.sum.Add(x)
// 如果超出最大長度,移除最舊的數值
if q.l.Len() > q.N {
f := q.l.Front()
q.sum = q.sum.Sub(f.Value.(decimal.Decimal))
q.l.Remove(f)
}
}
// ready判斷隊列是否已經填滿
func (q *ringQD) ready() bool { return q.l.Len() == q.N }
// mean計算平均值
func (q *ringQD) mean() decimal.Decimal {
if q.l.Len() == 0 {
return decimal.Zero
}
return q.sum.Div(decimal.NewFromInt(int64(q.l.Len())))
}
// values返回隊列中所有的值複製一份不影響原資料
func (q *ringQD) values() []decimal.Decimal {
out := make([]decimal.Decimal, 0, q.l.Len())
for e := q.l.Front(); e != nil; e = e.Next() {
out = append(out, e.Value.(decimal.Decimal))
}
return out
}