Skip to content

Commit

Permalink
Implement Stochastic RSI Indicator
Browse files Browse the repository at this point in the history
  • Loading branch information
tsubus committed Mar 8, 2021
1 parent a2f4ef8 commit e4d4a5d
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 0 deletions.
67 changes: 67 additions & 0 deletions indicator_stochastic_rsi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package techan

import (
"math"

"github.com/sdcoffey/big"
)

type stochasticRSIIndicator struct {
curRSI Indicator
minRSI Indicator
maxRSI Indicator
}

// NewStochasticRSIIndicator returns a derivative Indicator which returns the stochastic RSI indicator for the given
// RSI window.
// https://www.investopedia.com/terms/s/stochrsi.asp
func NewStochasticRSIIndicator(indicator Indicator, timeframe int) Indicator {
rsiIndicator := NewRelativeStrengthIndexIndicator(indicator, timeframe)
return stochasticRSIIndicator{
curRSI: rsiIndicator,
minRSI: NewMinimumValueIndicator(rsiIndicator, timeframe),
maxRSI: NewMaximumValueIndicator(rsiIndicator, timeframe),
}
}

func (sri stochasticRSIIndicator) Calculate(index int) big.Decimal {
curRSI := sri.curRSI.Calculate(index)
minRSI := sri.minRSI.Calculate(index)
maxRSI := sri.maxRSI.Calculate(index)

if minRSI.EQ(maxRSI) {
return big.NewDecimal(math.Inf(1))
}

return curRSI.Sub(minRSI).Div(maxRSI.Sub(minRSI)).Mul(big.NewDecimal(100))
}

type rsiKIndicator struct {
stochasticRSI Indicator
window int
}

// NewFastStochasticRSIIndicator returns a derivative Indicator which returns the fast stochastic RSI indicator (%K)
// for the given stochastic window.
func NewFastStochasticRSIIndicator(stochasticRSI Indicator, timeframe int) Indicator {
return rsiKIndicator{stochasticRSI, timeframe}
}

func (k rsiKIndicator) Calculate(index int) big.Decimal {
return NewSimpleMovingAverage(k.stochasticRSI, k.window).Calculate(index)
}

type rsiDIndicator struct {
k Indicator
window int
}

// NewSlowStochasticRSIIndicator returns a derivative Indicator which returns the slow stochastic RSI indicator (%D)
// for the given stochastic window.
func NewSlowStochasticRSIIndicator(k Indicator, timeframe int) Indicator {
return rsiDIndicator{k, timeframe}
}

func (d rsiDIndicator) Calculate(index int) big.Decimal {
return NewSimpleMovingAverage(d.k, d.window).Calculate(index)
}
80 changes: 80 additions & 0 deletions indicator_stochastic_rsi_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package techan

import (
"math"
"testing"

"github.com/sdcoffey/big"
"github.com/stretchr/testify/assert"
)

func TestStochasticRSIIndicator(t *testing.T) {
indicator := NewStochasticRSIIndicator(NewClosePriceIndicator(mockedTimeSeries), 5)

expectedValues := []float64{
math.Inf(1),
math.Inf(1),
math.Inf(1),
math.Inf(1),
math.Inf(1),
math.Inf(1),
100,
95.9481,
54.5245,
93.1791,
0,
21.6754,
}

indicatorEquals(t, expectedValues, indicator)
}

func TestFastStochasticRSIIndicator(t *testing.T) {
indicator := NewFastStochasticRSIIndicator(NewStochasticRSIIndicator(NewClosePriceIndicator(mockedTimeSeries),
5), 3)

expectedValues := []float64{
0,
0,
math.Inf(1),
math.Inf(1),
math.Inf(1),
math.Inf(1),
math.Inf(1),
math.Inf(1),
83.4909,
81.2173,
49.2346,
38.2848,
}

indicatorEquals(t, expectedValues, indicator)
}

func TestSlowStochasticRSIIndicator(t *testing.T) {
indicator := NewSlowStochasticRSIIndicator(NewFastStochasticRSIIndicator(NewStochasticRSIIndicator(
NewClosePriceIndicator(mockedTimeSeries), 5), 3), 3)

expectedValues := []float64{
0,
0,
math.Inf(1),
math.Inf(1),
math.Inf(1),
math.Inf(1),
math.Inf(1),
math.Inf(1),
math.Inf(1),
math.Inf(1),
71.3142,
56.2456,
}

indicatorEquals(t, expectedValues, indicator)
}

func TestFastStochasticRSIIndicatorNoPriceChange(t *testing.T) {
close := NewClosePriceIndicator(mockTimeSeries("42.0", "42.0"))
rsInd := NewRelativeStrengthIndicator(close, 2)
assert.Equal(t, big.NewDecimal(math.Inf(1)).FormattedString(2), rsInd.Calculate(1).FormattedString(2))
}

0 comments on commit e4d4a5d

Please sign in to comment.