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 }