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
|
|||
|
}
|