From 32dd907bf8dd427b04113d8b3e11a36edab6faff Mon Sep 17 00:00:00 2001 From: Will Charczuk Date: Sun, 17 Jul 2016 11:10:04 -0700 Subject: [PATCH] more iterating on macd, need to get a better handle on how to test. --- bollinger_band_series.go | 2 +- bollinger_band_series_test.go | 4 +- ema_series.go | 98 ++++++ ...erage_series_test.go => ema_series_test.go | 4 +- exp_moving_average_series.go | 94 ------ macd_series.go | 287 ++++++++++++++++-- simple_moving_average_series.go | 105 ------- sma_series.go | 90 ++++++ ...erage_series_test.go => sma_series_test.go | 26 +- 9 files changed, 464 insertions(+), 246 deletions(-) create mode 100644 ema_series.go rename exp_moving_average_series_test.go => ema_series_test.go (84%) delete mode 100644 exp_moving_average_series.go delete mode 100644 simple_moving_average_series.go create mode 100644 sma_series.go rename simple_moving_average_series_test.go => sma_series_test.go (79%) diff --git a/bollinger_band_series.go b/bollinger_band_series.go index 444a3d9..8154b01 100644 --- a/bollinger_band_series.go +++ b/bollinger_band_series.go @@ -37,7 +37,7 @@ func (bbs BollingerBandsSeries) GetWindowSize(defaults ...int) int { if len(defaults) > 0 { return defaults[0] } - return DefaultMovingAverageWindowSize + return DefaultSimpleMovingAveragePeriod } return bbs.WindowSize } diff --git a/bollinger_band_series_test.go b/bollinger_band_series_test.go index 67a34f4..6aed159 100644 --- a/bollinger_band_series_test.go +++ b/bollinger_band_series_test.go @@ -46,6 +46,6 @@ func TestBollingerBandLastValue(t *testing.T) { x, y1, y2 := bbs.GetLastBoundedValue() assert.Equal(100.0, x) - assert.Equal(100, math.Floor(y1)) - assert.Equal(95, math.Floor(y2)) + assert.Equal(101, math.Floor(y1)) + assert.Equal(83, math.Floor(y2)) } diff --git a/ema_series.go b/ema_series.go new file mode 100644 index 0000000..5a610e3 --- /dev/null +++ b/ema_series.go @@ -0,0 +1,98 @@ +package chart + +const ( + // DefaultEMASigma is the default exponential smoothing factor. + DefaultEMASigma = 0.25 +) + +// EMASeries is a computed series. +type EMASeries struct { + Name string + Style Style + YAxis YAxisType + + // Sigma is the 'smoothing factor' parameter. + Sigma float64 + Period int + InnerSeries ValueProvider +} + +// GetName returns the name of the time series. +func (ema EMASeries) GetName() string { + return ema.Name +} + +// GetStyle returns the line style. +func (ema EMASeries) GetStyle() Style { + return ema.Style +} + +// GetYAxis returns which YAxis the series draws on. +func (ema EMASeries) GetYAxis() YAxisType { + return ema.YAxis +} + +// GetPeriod returns the window size. +func (ema EMASeries) GetPeriod(defaults ...int) int { + if ema.Period == 0 { + if len(defaults) > 0 { + return defaults[0] + } + return ema.InnerSeries.Len() + } + return ema.Period +} + +// Len returns the number of elements in the series. +func (ema EMASeries) Len() int { + return ema.InnerSeries.Len() +} + +// GetSigma returns the smoothing factor for the serise. +func (ema EMASeries) GetSigma(defaults ...float64) float64 { + if ema.Sigma == 0 { + if len(defaults) > 0 { + return defaults[0] + } + return DefaultEMASigma + } + return ema.Sigma +} + +// GetValue gets a value at a given index. +func (ema EMASeries) GetValue(index int) (x float64, y float64) { + if ema.InnerSeries == nil { + return + } + vx, _ := ema.InnerSeries.GetValue(index) + x = vx + y = ema.compute(ema.GetPeriod(), index) + return +} + +// GetLastValue computes the last moving average value but walking back window size samples, +// and recomputing the last moving average chunk. +func (ema EMASeries) GetLastValue() (x float64, y float64) { + if ema.InnerSeries == nil { + return + } + lastIndex := ema.InnerSeries.Len() - 1 + x, _ = ema.InnerSeries.GetValue(lastIndex) + y = ema.compute(ema.GetPeriod(), lastIndex) + return +} + +func (ema EMASeries) compute(period, index int) float64 { + _, v := ema.InnerSeries.GetValue(index) + if period == 1 || index == 0 { + return v + } + sig := ema.GetSigma() + return sig*v + ((1.0 - sig) * ema.compute(period-1, index-1)) +} + +// Render renders the series. +func (ema EMASeries) Render(r Renderer, canvasBox Box, xrange, yrange Range, defaults Style) { + style := ema.Style.WithDefaultsFrom(defaults) + DrawLineSeries(r, canvasBox, xrange, yrange, style, ema) +} diff --git a/exp_moving_average_series_test.go b/ema_series_test.go similarity index 84% rename from exp_moving_average_series_test.go rename to ema_series_test.go index 4b23b7c..1778960 100644 --- a/exp_moving_average_series_test.go +++ b/ema_series_test.go @@ -7,7 +7,7 @@ import ( "github.com/blendlabs/go-assert" ) -func TestExponentialMovingAverageSeries(t *testing.T) { +func TestEMASeries(t *testing.T) { assert := assert.New(t) mockSeries := mockValueProvider{ @@ -16,7 +16,7 @@ func TestExponentialMovingAverageSeries(t *testing.T) { } assert.Equal(10, mockSeries.Len()) - mas := &ExponentialMovingAverageSeries{ + mas := &EMASeries{ InnerSeries: mockSeries, } diff --git a/exp_moving_average_series.go b/exp_moving_average_series.go deleted file mode 100644 index 671c740..0000000 --- a/exp_moving_average_series.go +++ /dev/null @@ -1,94 +0,0 @@ -package chart - -const ( - // DefaultExponentialMovingAverageSigma is the default exponential smoothing factor. - DefaultExponentialMovingAverageSigma = 0.25 -) - -// ExponentialMovingAverageSeries is a computed series. -type ExponentialMovingAverageSeries struct { - Name string - Style Style - YAxis YAxisType - - // Sigma is the 'smoothing factor' parameter. - Sigma float64 - InnerSeries ValueProvider - - valueBuffer []float64 -} - -// GetName returns the name of the time series. -func (mas ExponentialMovingAverageSeries) GetName() string { - return mas.Name -} - -// GetStyle returns the line style. -func (mas ExponentialMovingAverageSeries) GetStyle() Style { - return mas.Style -} - -// GetYAxis returns which YAxis the series draws on. -func (mas ExponentialMovingAverageSeries) GetYAxis() YAxisType { - return mas.YAxis -} - -// Len returns the number of elements in the series. -func (mas *ExponentialMovingAverageSeries) Len() int { - return mas.InnerSeries.Len() -} - -// GetSigma returns the smoothing factor for the serise. -func (mas ExponentialMovingAverageSeries) GetSigma(defaults ...float64) float64 { - if mas.Sigma == 0 { - if len(defaults) > 0 { - return defaults[0] - } - return DefaultExponentialMovingAverageSigma - } - return mas.Sigma -} - -// GetValue gets a value at a given index. -func (mas *ExponentialMovingAverageSeries) GetValue(index int) (x float64, y float64) { - if mas.InnerSeries == nil { - return - } - if mas.valueBuffer == nil || index == 0 { - mas.valueBuffer = make([]float64, mas.InnerSeries.Len()) - } - vx, vy := mas.InnerSeries.GetValue(index) - x = vx - if index == 0 { - mas.valueBuffer[0] = vy - y = vy - return - } - - sig := mas.GetSigma() - mas.valueBuffer[index] = sig*vy + ((1.0 - sig) * mas.valueBuffer[index-1]) - y = mas.valueBuffer[index] - return -} - -// GetLastValue computes the last moving average value but walking back window size samples, -// and recomputing the last moving average chunk. -func (mas ExponentialMovingAverageSeries) GetLastValue() (x float64, y float64) { - if mas.InnerSeries == nil { - return - } - - seriesLength := mas.InnerSeries.Len() - for index := 0; index < seriesLength; index++ { - x, _ = mas.GetValue(index) - } - - y = mas.valueBuffer[seriesLength-1] - return -} - -// Render renders the series. -func (mas *ExponentialMovingAverageSeries) Render(r Renderer, canvasBox Box, xrange, yrange Range, defaults Style) { - style := mas.Style.WithDefaultsFrom(defaults) - DrawLineSeries(r, canvasBox, xrange, yrange, style, mas) -} diff --git a/macd_series.go b/macd_series.go index d7d0899..fd10a67 100644 --- a/macd_series.go +++ b/macd_series.go @@ -1,37 +1,45 @@ package chart const ( - // DefaultMACDWindowPrimary is the long window. - DefaultMACDWindowPrimary = 26 - // DefaultMACDWindowSecondary is the short window. - DefaultMACDWindowSecondary = 12 + // DefaultMACDPeriodPrimary is the long window. + DefaultMACDPeriodPrimary = 26 + // DefaultMACDPeriodSecondary is the short window. + DefaultMACDPeriodSecondary = 12 + // DefaultMACDSignalPeriod is the signal period to compute for the MACD. + DefaultMACDSignalPeriod = 9 ) -// MACDSeries (or Moving Average Convergence Divergence) is a special type of series that -// computes the difference between two different EMA values for a given index, as denoted by WindowPrimary(26) and WindowSecondary(12). +// MACDSeries computes the difference between the MACD line and the MACD Signal line. +// It is used in technical analysis and gives a lagging indicator of momentum. type MACDSeries struct { Name string Style Style YAxis YAxisType InnerSeries ValueProvider - WindowPrimary int - WindowSecondary int + PrimaryPeriod int + SecondaryPeriod int + SignalPeriod int Sigma float64 } -// GetWindows returns the primary and secondary window sizes. -func (macd MACDSeries) GetWindows() (w1, w2 int) { - if macd.WindowPrimary == 0 { - w1 = DefaultMACDWindowPrimary +// GetPeriods returns the primary and secondary periods. +func (macd MACDSeries) GetPeriods() (w1, w2, sig int) { + if macd.PrimaryPeriod == 0 { + w1 = DefaultMACDPeriodPrimary } else { - w1 = macd.WindowPrimary + w1 = macd.PrimaryPeriod } - if macd.WindowSecondary == 0 { - w2 = DefaultMACDWindowSecondary + if macd.SecondaryPeriod == 0 { + w2 = DefaultMACDPeriodSecondary } else { - w2 = macd.WindowSecondary + w2 = macd.SecondaryPeriod + } + if macd.SignalPeriod == 0 { + sig = DefaultMACDSignalPeriod + } else { + sig = macd.SignalPeriod } return } @@ -42,7 +50,7 @@ func (macd MACDSeries) GetSigma(defaults ...float64) float64 { if len(defaults) > 0 { return defaults[0] } - return DefaultExponentialMovingAverageSigma + return DefaultEMASigma } return macd.Sigma } @@ -68,7 +76,7 @@ func (macd MACDSeries) Len() int { return 0 } - w1, _ := macd.GetWindows() + w1, _, _ := macd.GetPeriods() innerLen := macd.InnerSeries.Len() if innerLen > w1 { return innerLen - w1 @@ -76,35 +84,250 @@ func (macd MACDSeries) Len() int { return 0 } -// GetValue gets a value at a given index. +// GetValue gets a value at a given index. For MACD it is the signal value. func (macd MACDSeries) GetValue(index int) (x float64, y float64) { if macd.InnerSeries == nil { return } - w1, w2 := macd.GetWindows() + w1, w2, sig := macd.GetPeriods() + sigma := macd.GetSigma() effectiveIndex := index + w1 x, _ = macd.InnerSeries.GetValue(effectiveIndex) - ema1 := macd.computeEMA(w1, effectiveIndex) - ema2 := macd.computeEMA(w2, effectiveIndex) + signal := EMASeries{ + InnerSeries: MACDLineSeries{ + InnerSeries: macd.InnerSeries, + PrimaryPeriod: w1, + SecondaryPeriod: w2, + Sigma: sigma, + }, + Sigma: sigma, + Period: sig, + } + + macdl := MACDLineSeries{ + InnerSeries: macd.InnerSeries, + PrimaryPeriod: w1, + SecondaryPeriod: w2, + Sigma: sigma, + } + + _, sv := signal.GetValue(index) + _, lv := macdl.GetValue(index) + y = lv - sv - y = ema1 - ema2 return } -func (macd MACDSeries) computeEMA(windowSize int, index int) float64 { - _, v := macd.InnerSeries.GetValue(index) - if windowSize == 1 { - return v +// MACDSignalSeries computes the EMA of the MACDLineSeries. +type MACDSignalSeries struct { + Name string + Style Style + YAxis YAxisType + InnerSeries ValueProvider + + PrimaryPeriod int + SecondaryPeriod int + SignalPeriod int + + Sigma float64 +} + +// GetPeriods returns the primary and secondary periods. +func (macds MACDSignalSeries) GetPeriods() (w1, w2, sig int) { + if macds.PrimaryPeriod == 0 { + w1 = DefaultMACDPeriodPrimary + } else { + w1 = macds.PrimaryPeriod } - sig := macd.GetSigma() - return sig*v + ((1.0 - sig) * macd.computeEMA(windowSize-1, index-1)) + if macds.SecondaryPeriod == 0 { + w2 = DefaultMACDPeriodSecondary + } else { + w2 = macds.SecondaryPeriod + } + if macds.SignalPeriod == 0 { + sig = DefaultMACDSignalPeriod + } else { + sig = macds.SignalPeriod + } + return +} + +// GetSigma returns the smoothing factor for the serise. +func (macds MACDSignalSeries) GetSigma(defaults ...float64) float64 { + if macds.Sigma == 0 { + if len(defaults) > 0 { + return defaults[0] + } + return DefaultEMASigma + } + return macds.Sigma +} + +// GetName returns the name of the time series. +func (macds MACDSignalSeries) GetName() string { + return macds.Name +} + +// GetStyle returns the line style. +func (macds MACDSignalSeries) GetStyle() Style { + return macds.Style +} + +// GetYAxis returns which YAxis the series draws on. +func (macds MACDSignalSeries) GetYAxis() YAxisType { + return macds.YAxis +} + +// Len returns the number of elements in the series. +func (macds MACDSignalSeries) Len() int { + if macds.InnerSeries == nil { + return 0 + } + + w1, _, _ := macds.GetPeriods() + innerLen := macds.InnerSeries.Len() + if innerLen > w1 { + return innerLen - w1 + } + return 0 +} + +// GetValue gets a value at a given index. For MACD it is the signal value. +func (macds MACDSignalSeries) GetValue(index int) (x float64, y float64) { + if macds.InnerSeries == nil { + return + } + + w1, w2, sig := macds.GetPeriods() + sigma := macds.GetSigma() + + effectiveIndex := index + w1 + x, _ = macds.InnerSeries.GetValue(effectiveIndex) + + signal := EMASeries{ + InnerSeries: MACDLineSeries{ + InnerSeries: macds.InnerSeries, + PrimaryPeriod: w1, + SecondaryPeriod: w2, + Sigma: sigma, + }, + Sigma: sigma, + Period: sig, + } + + _, y = signal.GetValue(index) + return } // Render renders the series. -func (macd MACDSeries) Render(r Renderer, canvasBox Box, xrange, yrange Range, defaults Style) { - style := macd.Style.WithDefaultsFrom(defaults) - DrawLineSeries(r, canvasBox, xrange, yrange, style, macd) +func (macds MACDSignalSeries) Render(r Renderer, canvasBox Box, xrange, yrange Range, defaults Style) { + style := macds.Style.WithDefaultsFrom(defaults) + DrawLineSeries(r, canvasBox, xrange, yrange, style, macds) +} + +// MACDLineSeries is a series that computes the inner ema1-ema2 value as a series. +type MACDLineSeries struct { + Name string + Style Style + YAxis YAxisType + InnerSeries ValueProvider + + PrimaryPeriod int + SecondaryPeriod int + + Sigma float64 +} + +// GetName returns the name of the time series. +func (macdl MACDLineSeries) GetName() string { + return macdl.Name +} + +// GetStyle returns the line style. +func (macdl MACDLineSeries) GetStyle() Style { + return macdl.Style +} + +// GetYAxis returns which YAxis the series draws on. +func (macdl MACDLineSeries) GetYAxis() YAxisType { + return macdl.YAxis +} + +// GetPeriods returns the primary and secondary periods. +func (macdl MACDLineSeries) GetPeriods() (w1, w2 int) { + if macdl.PrimaryPeriod == 0 { + w1 = DefaultMACDPeriodPrimary + } else { + w1 = macdl.PrimaryPeriod + } + if macdl.SecondaryPeriod == 0 { + w2 = DefaultMACDPeriodSecondary + } else { + w2 = macdl.SecondaryPeriod + } + return +} + +// Len returns the number of elements in the series. +func (macdl MACDLineSeries) Len() int { + if macdl.InnerSeries == nil { + return 0 + } + + w1, _ := macdl.GetPeriods() + innerLen := macdl.InnerSeries.Len() + if innerLen > w1 { + return innerLen - w1 + } + return 0 +} + +// GetSigma returns the smoothing factor for the serise. +func (macdl MACDLineSeries) GetSigma(defaults ...float64) float64 { + if macdl.Sigma == 0 { + if len(defaults) > 0 { + return defaults[0] + } + return DefaultEMASigma + } + return macdl.Sigma +} + +// GetValue gets a value at a given index. For MACD it is the signal value. +func (macdl MACDLineSeries) GetValue(index int) (x float64, y float64) { + if macdl.InnerSeries == nil { + return + } + + w1, w2 := macdl.GetPeriods() + + effectiveIndex := index + w1 + x, _ = macdl.InnerSeries.GetValue(effectiveIndex) + + ema1 := EMASeries{ + InnerSeries: macdl.InnerSeries, + Period: w1, + Sigma: macdl.GetSigma(), + } + + ema2 := EMASeries{ + InnerSeries: macdl.InnerSeries, + Period: w2, + Sigma: macdl.GetSigma(), + } + + _, emav1 := ema1.GetValue(index) + _, emav2 := ema2.GetValue(index) + + y = emav1 - emav2 + return +} + +// Render renders the series. +func (macdl MACDLineSeries) Render(r Renderer, canvasBox Box, xrange, yrange Range, defaults Style) { + style := macdl.Style.WithDefaultsFrom(defaults) + DrawLineSeries(r, canvasBox, xrange, yrange, style, macdl) } diff --git a/simple_moving_average_series.go b/simple_moving_average_series.go deleted file mode 100644 index 4b3a701..0000000 --- a/simple_moving_average_series.go +++ /dev/null @@ -1,105 +0,0 @@ -package chart - -const ( - // DefaultMovingAverageWindowSize is the default number of values to average. - DefaultMovingAverageWindowSize = 5 -) - -// SimpleMovingAverageSeries is a computed series. -type SimpleMovingAverageSeries struct { - Name string - Style Style - YAxis YAxisType - - WindowSize int - InnerSeries ValueProvider - - valueBuffer *RingBuffer -} - -// GetName returns the name of the time series. -func (mas SimpleMovingAverageSeries) GetName() string { - return mas.Name -} - -// GetStyle returns the line style. -func (mas SimpleMovingAverageSeries) GetStyle() Style { - return mas.Style -} - -// GetYAxis returns which YAxis the series draws on. -func (mas SimpleMovingAverageSeries) GetYAxis() YAxisType { - return mas.YAxis -} - -// Len returns the number of elements in the series. -func (mas *SimpleMovingAverageSeries) Len() int { - return mas.InnerSeries.Len() -} - -// GetValue gets a value at a given index. -func (mas *SimpleMovingAverageSeries) GetValue(index int) (x float64, y float64) { - if mas.InnerSeries == nil { - return - } - if mas.valueBuffer == nil || index == 0 { - mas.valueBuffer = NewRingBufferWithCapacity(mas.GetWindowSize()) - } - if mas.valueBuffer.Len() >= mas.GetWindowSize() { - mas.valueBuffer.Dequeue() - } - px, py := mas.InnerSeries.GetValue(index) - mas.valueBuffer.Enqueue(py) - x = px - y = mas.getAverage(mas.valueBuffer) - return -} - -// GetLastValue computes the last moving average value but walking back window size samples, -// and recomputing the last moving average chunk. -func (mas SimpleMovingAverageSeries) GetLastValue() (x float64, y float64) { - if mas.InnerSeries == nil { - return - } - windowSize := mas.GetWindowSize() - seriesLength := mas.InnerSeries.Len() - startAt := seriesLength - windowSize - if startAt < 0 { - startAt = 0 - } - vb := NewRingBufferWithCapacity(windowSize) - for index := startAt; index < seriesLength; index++ { - xn, yn := mas.InnerSeries.GetValue(index) - vb.Enqueue(yn) - x = xn - } - y = mas.getAverage(vb) - return -} - -// GetWindowSize returns the window size. -func (mas SimpleMovingAverageSeries) GetWindowSize(defaults ...int) int { - if mas.WindowSize == 0 { - if len(defaults) > 0 { - return defaults[0] - } - return DefaultMovingAverageWindowSize - } - return mas.WindowSize -} - -func (mas SimpleMovingAverageSeries) getAverage(valueBuffer *RingBuffer) float64 { - var accum float64 - valueBuffer.Each(func(v interface{}) { - if typed, isTyped := v.(float64); isTyped { - accum += typed - } - }) - return accum / float64(valueBuffer.Len()) -} - -// Render renders the series. -func (mas *SimpleMovingAverageSeries) Render(r Renderer, canvasBox Box, xrange, yrange Range, defaults Style) { - style := mas.Style.WithDefaultsFrom(defaults) - DrawLineSeries(r, canvasBox, xrange, yrange, style, mas) -} diff --git a/sma_series.go b/sma_series.go new file mode 100644 index 0000000..b0ed98b --- /dev/null +++ b/sma_series.go @@ -0,0 +1,90 @@ +package chart + +const ( + // DefaultSimpleMovingAveragePeriod is the default number of values to average. + DefaultSimpleMovingAveragePeriod = 16 +) + +// SMASeries is a computed series. +type SMASeries struct { + Name string + Style Style + YAxis YAxisType + + Period int + InnerSeries ValueProvider +} + +// GetName returns the name of the time series. +func (sma SMASeries) GetName() string { + return sma.Name +} + +// GetStyle returns the line style. +func (sma SMASeries) GetStyle() Style { + return sma.Style +} + +// GetYAxis returns which YAxis the series draws on. +func (sma SMASeries) GetYAxis() YAxisType { + return sma.YAxis +} + +// Len returns the number of elements in the series. +func (sma SMASeries) Len() int { + return sma.InnerSeries.Len() +} + +// GetValue gets a value at a given index. +func (sma SMASeries) GetValue(index int) (x float64, y float64) { + if sma.InnerSeries == nil { + return + } + px, _ := sma.InnerSeries.GetValue(index) + x = px + y = sma.getAverage(index) + return +} + +// GetLastValue computes the last moving average value but walking back window size samples, +// and recomputing the last moving average chunk. +func (sma SMASeries) GetLastValue() (x float64, y float64) { + if sma.InnerSeries == nil { + return + } + seriesLen := sma.InnerSeries.Len() + px, _ := sma.InnerSeries.GetValue(seriesLen - 1) + x = px + y = sma.getAverage(seriesLen - 1) + return +} + +// GetPeriod returns the window size. +func (sma SMASeries) GetPeriod(defaults ...int) int { + if sma.Period == 0 { + if len(defaults) > 0 { + return defaults[0] + } + return DefaultSimpleMovingAveragePeriod + } + return sma.Period +} + +func (sma SMASeries) getAverage(index int) float64 { + period := sma.GetPeriod() + floor := MaxInt(0, index-period) + var accum float64 + var count float64 + for x := index; x >= floor; x-- { + _, vy := sma.InnerSeries.GetValue(x) + accum += vy + count += 1.0 + } + return accum / count +} + +// Render renders the series. +func (sma *SMASeries) Render(r Renderer, canvasBox Box, xrange, yrange Range, defaults Style) { + style := sma.Style.WithDefaultsFrom(defaults) + DrawLineSeries(r, canvasBox, xrange, yrange, style, sma) +} diff --git a/simple_moving_average_series_test.go b/sma_series_test.go similarity index 79% rename from simple_moving_average_series_test.go rename to sma_series_test.go index 7ef513d..e2f5e4f 100644 --- a/simple_moving_average_series_test.go +++ b/sma_series_test.go @@ -16,12 +16,18 @@ func (m mockValueProvider) Len() int { } func (m mockValueProvider) GetValue(index int) (x, y float64) { + if index < 0 { + panic("negative index at GetValue()") + } + if index > MinInt(len(m.X), len(m.Y)) { + panic("index is outside the length of m.X or m.Y") + } x = m.X[index] y = m.Y[index] return } -func TestSimpleMovingAverageSeriesGetValue(t *testing.T) { +func TestSMASeriesGetValue(t *testing.T) { assert := assert.New(t) mockSeries := mockValueProvider{ @@ -30,9 +36,9 @@ func TestSimpleMovingAverageSeriesGetValue(t *testing.T) { } assert.Equal(10, mockSeries.Len()) - mas := &SimpleMovingAverageSeries{ + mas := &SMASeries{ InnerSeries: mockSeries, - WindowSize: 10, + Period: 10, } var yvalues []float64 @@ -52,7 +58,7 @@ func TestSimpleMovingAverageSeriesGetValue(t *testing.T) { assert.Equal(6.0, yvalues[8]) } -func TestSimpleMovingAverageSeriesGetLastValueWindowOverlap(t *testing.T) { +func TestSMASeriesGetLastValueWindowOverlap(t *testing.T) { assert := assert.New(t) mockSeries := mockValueProvider{ @@ -61,9 +67,9 @@ func TestSimpleMovingAverageSeriesGetLastValueWindowOverlap(t *testing.T) { } assert.Equal(10, mockSeries.Len()) - mas := &SimpleMovingAverageSeries{ + mas := &SMASeries{ InnerSeries: mockSeries, - WindowSize: 15, + Period: 15, } var yvalues []float64 @@ -78,7 +84,7 @@ func TestSimpleMovingAverageSeriesGetLastValueWindowOverlap(t *testing.T) { assert.Equal(yvalues[len(yvalues)-1], ly) } -func TestSimpleMovingAverageSeriesGetLastValue(t *testing.T) { +func TestSMASeriesGetLastValue(t *testing.T) { assert := assert.New(t) mockSeries := mockValueProvider{ @@ -87,9 +93,9 @@ func TestSimpleMovingAverageSeriesGetLastValue(t *testing.T) { } assert.Equal(100, mockSeries.Len()) - mas := &SimpleMovingAverageSeries{ + mas := &SMASeries{ InnerSeries: mockSeries, - WindowSize: 10, + Period: 10, } var yvalues []float64 @@ -100,6 +106,6 @@ func TestSimpleMovingAverageSeriesGetLastValue(t *testing.T) { lx, ly := mas.GetLastValue() assert.Equal(100.0, lx) - assert.Equal(5.5, ly) + assert.Equal(6, ly) assert.Equal(yvalues[len(yvalues)-1], ly) }