51 lines
1.3 KiB
Go
51 lines
1.3 KiB
Go
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
|
||
}
|