mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
Merge pull request #540 from narumiruna/indicator/update
indicator: make parameters of update method consistent
This commit is contained in:
commit
46015324e9
|
@ -22,12 +22,7 @@ type AD struct {
|
|||
UpdateCallbacks []func(value float64)
|
||||
}
|
||||
|
||||
func (inc *AD) Update(kLine types.KLine) {
|
||||
cloze := kLine.Close.Float64()
|
||||
high := kLine.High.Float64()
|
||||
low := kLine.Low.Float64()
|
||||
volume := kLine.Volume.Float64()
|
||||
|
||||
func (inc *AD) Update(high, low, cloze, volume float64) {
|
||||
var moneyFlowVolume float64
|
||||
if high == low {
|
||||
moneyFlowVolume = 0
|
||||
|
@ -65,7 +60,7 @@ func (inc *AD) calculateAndUpdate(kLines []types.KLine) {
|
|||
if inc.EndTime != zeroTime && !k.EndTime.After(inc.EndTime) {
|
||||
continue
|
||||
}
|
||||
inc.Update(k)
|
||||
inc.Update(k.High.Float64(), k.Low.Float64(), k.Close.Float64(), k.Volume.Float64())
|
||||
}
|
||||
|
||||
inc.EmitUpdate(inc.Last())
|
||||
|
|
|
@ -11,25 +11,26 @@ import (
|
|||
type ATR struct {
|
||||
types.IntervalWindow
|
||||
Values types.Float64Slice
|
||||
TrueRanges types.Float64Slice
|
||||
PercentageVolatility types.Float64Slice
|
||||
|
||||
PriviousClose float64
|
||||
RMA *RMA
|
||||
|
||||
EndTime time.Time
|
||||
UpdateCallbacks []func(value float64)
|
||||
}
|
||||
|
||||
func (inc *ATR) Update(kLine types.KLine) {
|
||||
func (inc *ATR) Update(high, low, cloze float64) {
|
||||
if inc.Window <= 0 {
|
||||
panic("window must be greater than 0")
|
||||
}
|
||||
|
||||
cloze := kLine.Close.Float64()
|
||||
high := kLine.High.Float64()
|
||||
low := kLine.Low.Float64()
|
||||
if len(inc.Values) == 0 {
|
||||
inc.RMA = &RMA{IntervalWindow: types.IntervalWindow{Window: inc.Window}}
|
||||
}
|
||||
|
||||
if inc.PriviousClose == 0 {
|
||||
inc.PriviousClose = kLine.Close.Float64()
|
||||
inc.PriviousClose = cloze
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -39,24 +40,12 @@ func (inc *ATR) Update(kLine types.KLine) {
|
|||
math.Abs(high - inc.PriviousClose),
|
||||
math.Abs(low - inc.PriviousClose),
|
||||
}.Max()
|
||||
inc.TrueRanges.Push(trueRange)
|
||||
|
||||
inc.PriviousClose = cloze
|
||||
|
||||
// apply rolling moving average
|
||||
if len(inc.TrueRanges) < inc.Window {
|
||||
return
|
||||
}
|
||||
|
||||
if len(inc.TrueRanges) == inc.Window {
|
||||
atr := inc.TrueRanges.Mean()
|
||||
inc.Values.Push(atr)
|
||||
inc.PercentageVolatility.Push(atr / cloze)
|
||||
return
|
||||
}
|
||||
|
||||
lambda := 1 / float64(inc.Window)
|
||||
atr := inc.Values.Last()*(1-lambda) + inc.TrueRanges.Last()*lambda
|
||||
inc.RMA.Update(trueRange)
|
||||
atr := inc.RMA.Last()
|
||||
inc.Values.Push(atr)
|
||||
inc.PercentageVolatility.Push(atr / cloze)
|
||||
}
|
||||
|
@ -87,7 +76,7 @@ func (inc *ATR) calculateAndUpdate(kLines []types.KLine) {
|
|||
if inc.EndTime != zeroTime && !k.EndTime.After(inc.EndTime) {
|
||||
continue
|
||||
}
|
||||
inc.Update(k)
|
||||
inc.Update(k.High.Float64(), k.Low.Float64(), k.Close.Float64())
|
||||
}
|
||||
|
||||
inc.EmitUpdate(inc.Last())
|
||||
|
|
|
@ -29,25 +29,16 @@ type MACD struct {
|
|||
UpdateCallbacks []func(value float64)
|
||||
}
|
||||
|
||||
func (inc *MACD) calculateMACD(kLines []types.KLine, priceF KLinePriceMapper) float64 {
|
||||
for _, kline := range kLines {
|
||||
inc.Update(kline, priceF)
|
||||
}
|
||||
return inc.Values[len(inc.Values)-1]
|
||||
}
|
||||
|
||||
func (inc *MACD) Update(kLine types.KLine, priceF KLinePriceMapper) {
|
||||
func (inc *MACD) Update(x float64) {
|
||||
if len(inc.Values) == 0 {
|
||||
inc.FastEWMA = EWMA{IntervalWindow: types.IntervalWindow{Window: inc.ShortPeriod}}
|
||||
inc.SlowEWMA = EWMA{IntervalWindow: types.IntervalWindow{Window: inc.LongPeriod}}
|
||||
inc.SignalLine = EWMA{IntervalWindow: types.IntervalWindow{Window: inc.Window}}
|
||||
}
|
||||
|
||||
price := priceF(kLine)
|
||||
|
||||
// update fast and slow ema
|
||||
inc.FastEWMA.Update(price)
|
||||
inc.SlowEWMA.Update(price)
|
||||
inc.FastEWMA.Update(x)
|
||||
inc.SlowEWMA.Update(x)
|
||||
|
||||
// update macd
|
||||
macd := inc.FastEWMA.Last() - inc.SlowEWMA.Last()
|
||||
|
@ -60,18 +51,23 @@ func (inc *MACD) Update(kLine types.KLine, priceF KLinePriceMapper) {
|
|||
inc.Histogram.Push(macd - inc.SignalLine.Last())
|
||||
}
|
||||
|
||||
func (inc *MACD) calculateMACD(kLines []types.KLine, priceF KLinePriceMapper) float64 {
|
||||
for _, kline := range kLines {
|
||||
inc.Update(kline.Close.Float64())
|
||||
}
|
||||
return inc.Values[len(inc.Values)-1]
|
||||
}
|
||||
|
||||
func (inc *MACD) calculateAndUpdate(kLines []types.KLine) {
|
||||
if len(kLines) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var priceF = KLineClosePriceMapper
|
||||
|
||||
for _, k := range kLines {
|
||||
if inc.EndTime != zeroTime && !k.EndTime.After(inc.EndTime) {
|
||||
continue
|
||||
}
|
||||
inc.Update(k, priceF)
|
||||
inc.Update(k.Close.Float64())
|
||||
}
|
||||
|
||||
inc.EmitUpdate(inc.Values[len(inc.Values)-1])
|
||||
|
|
|
@ -22,10 +22,7 @@ type OBV struct {
|
|||
UpdateCallbacks []func(value float64)
|
||||
}
|
||||
|
||||
func (inc *OBV) Update(kLine types.KLine, priceF KLinePriceMapper) {
|
||||
price := priceF(kLine)
|
||||
volume := kLine.Volume.Float64()
|
||||
|
||||
func (inc *OBV) Update(price, volume float64) {
|
||||
if len(inc.Values) == 0 {
|
||||
inc.PrePrice = price
|
||||
inc.Values.Push(volume)
|
||||
|
@ -47,17 +44,16 @@ func (inc *OBV) Last() float64 {
|
|||
}
|
||||
|
||||
func (inc *OBV) calculateAndUpdate(kLines []types.KLine) {
|
||||
var priceF = KLineClosePriceMapper
|
||||
|
||||
for _, k := range kLines {
|
||||
if inc.EndTime != zeroTime && !k.EndTime.After(inc.EndTime) {
|
||||
continue
|
||||
}
|
||||
inc.Update(k, priceF)
|
||||
inc.Update(k.Close.Float64(), k.Volume.Float64())
|
||||
}
|
||||
inc.EmitUpdate(inc.Last())
|
||||
inc.EndTime = kLines[len(kLines)-1].EndTime.Time()
|
||||
}
|
||||
|
||||
func (inc *OBV) handleKLineWindowUpdate(interval types.Interval, window types.KLineWindow) {
|
||||
if inc.Interval != interval {
|
||||
return
|
||||
|
|
|
@ -24,8 +24,7 @@ type RSI struct {
|
|||
UpdateCallbacks []func(value float64)
|
||||
}
|
||||
|
||||
func (inc *RSI) Update(kline types.KLine, priceF KLinePriceMapper) {
|
||||
price := priceF(kline)
|
||||
func (inc *RSI) Update(price float64) {
|
||||
inc.Prices.Push(price)
|
||||
|
||||
if len(inc.Prices) < inc.Window+1 {
|
||||
|
@ -78,13 +77,11 @@ func (inc *RSI) Length() int {
|
|||
var _ types.Series = &RSI{}
|
||||
|
||||
func (inc *RSI) calculateAndUpdate(kLines []types.KLine) {
|
||||
var priceF = KLineClosePriceMapper
|
||||
|
||||
for _, k := range kLines {
|
||||
if inc.EndTime != zeroTime && !k.EndTime.After(inc.EndTime) {
|
||||
continue
|
||||
}
|
||||
inc.Update(k, priceF)
|
||||
inc.Update(k.Close.Float64())
|
||||
}
|
||||
|
||||
inc.EmitUpdate(inc.Last())
|
||||
|
|
|
@ -20,21 +20,21 @@ type STOCH struct {
|
|||
K types.Float64Slice
|
||||
D types.Float64Slice
|
||||
|
||||
KLineWindow types.KLineWindow
|
||||
HighValues types.Float64Slice
|
||||
LowValues types.Float64Slice
|
||||
|
||||
EndTime time.Time
|
||||
UpdateCallbacks []func(k float64, d float64)
|
||||
}
|
||||
|
||||
func (inc *STOCH) update(kLine types.KLine) {
|
||||
inc.KLineWindow.Add(kLine)
|
||||
inc.KLineWindow.Truncate(inc.Window)
|
||||
func (inc *STOCH) Update(high, low, cloze float64) {
|
||||
inc.HighValues.Push(high)
|
||||
inc.LowValues.Push(low)
|
||||
|
||||
lowest := inc.KLineWindow.GetLow().Float64()
|
||||
highest := inc.KLineWindow.GetHigh().Float64()
|
||||
clos := kLine.Close.Float64()
|
||||
lowest := inc.LowValues.Tail(inc.Window).Min()
|
||||
highest := inc.HighValues.Tail(inc.Window).Max()
|
||||
|
||||
k := 100.0 * (clos - lowest) / (highest - lowest)
|
||||
k := 100.0 * (cloze - lowest) / (highest - lowest)
|
||||
inc.K.Push(k)
|
||||
|
||||
d := inc.K.Tail(DPeriod).Mean()
|
||||
|
@ -64,7 +64,7 @@ func (inc *STOCH) calculateAndUpdate(kLines []types.KLine) {
|
|||
if inc.EndTime != zeroTime && !k.EndTime.After(inc.EndTime) {
|
||||
continue
|
||||
}
|
||||
inc.update(k)
|
||||
inc.Update(k.High.Float64(), k.Low.Float64(), k.Close.Float64())
|
||||
}
|
||||
|
||||
inc.EmitUpdate(inc.LastK(), inc.LastD())
|
||||
|
|
|
@ -28,6 +28,23 @@ type VWAP struct {
|
|||
UpdateCallbacks []func(value float64)
|
||||
}
|
||||
|
||||
func (inc *VWAP) Update(price, volume float64) {
|
||||
inc.Prices.Push(price)
|
||||
inc.Volumes.Push(volume)
|
||||
|
||||
if inc.Window != 0 && len(inc.Prices) > inc.Window {
|
||||
popIndex := len(inc.Prices) - inc.Window - 1
|
||||
inc.WeightedSum -= inc.Prices[popIndex] * inc.Volumes[popIndex]
|
||||
inc.VolumeSum -= inc.Volumes[popIndex]
|
||||
}
|
||||
|
||||
inc.WeightedSum += price * volume
|
||||
inc.VolumeSum += volume
|
||||
|
||||
vwap := inc.WeightedSum / inc.VolumeSum
|
||||
inc.Values.Push(vwap)
|
||||
}
|
||||
|
||||
func (inc *VWAP) Last() float64 {
|
||||
if len(inc.Values) == 0 {
|
||||
return 0.0
|
||||
|
@ -50,26 +67,6 @@ func (inc *VWAP) Length() int {
|
|||
|
||||
var _ types.Series = &VWAP{}
|
||||
|
||||
func (inc *VWAP) Update(kLine types.KLine, priceF KLinePriceMapper) {
|
||||
price := priceF(kLine)
|
||||
volume := kLine.Volume.Float64()
|
||||
|
||||
inc.Prices.Push(price)
|
||||
inc.Volumes.Push(volume)
|
||||
|
||||
if inc.Window != 0 && len(inc.Prices) > inc.Window {
|
||||
popIndex := len(inc.Prices) - inc.Window - 1
|
||||
inc.WeightedSum -= inc.Prices[popIndex] * inc.Volumes[popIndex]
|
||||
inc.VolumeSum -= inc.Volumes[popIndex]
|
||||
}
|
||||
|
||||
inc.WeightedSum += price * volume
|
||||
inc.VolumeSum += volume
|
||||
|
||||
vwap := inc.WeightedSum / inc.VolumeSum
|
||||
inc.Values.Push(vwap)
|
||||
}
|
||||
|
||||
func (inc *VWAP) calculateAndUpdate(kLines []types.KLine) {
|
||||
var priceF = KLineTypicalPriceMapper
|
||||
|
||||
|
@ -77,7 +74,7 @@ func (inc *VWAP) calculateAndUpdate(kLines []types.KLine) {
|
|||
if inc.EndTime != zeroTime && !k.EndTime.After(inc.EndTime) {
|
||||
continue
|
||||
}
|
||||
inc.Update(k, priceF)
|
||||
inc.Update(priceF(k), k.Volume.Float64())
|
||||
}
|
||||
|
||||
inc.EmitUpdate(inc.Last())
|
||||
|
@ -99,7 +96,7 @@ func (inc *VWAP) Bind(updater KLineWindowUpdater) {
|
|||
func CalculateVWAP(klines []types.KLine, priceF KLinePriceMapper, window int) float64 {
|
||||
vwap := VWAP{IntervalWindow: types.IntervalWindow{Window: window}}
|
||||
for _, k := range klines {
|
||||
vwap.Update(k, priceF)
|
||||
vwap.Update(priceF(k), k.Volume.Float64())
|
||||
}
|
||||
return vwap.Last()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user