Skip to content

Commit 8d5dab6

Browse files
committed
Implement Stochastic RSI Indicator
1 parent a2f4ef8 commit 8d5dab6

2 files changed

Lines changed: 144 additions & 0 deletions

File tree

indicator_stochastic_rsi.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package techan
2+
3+
import (
4+
"github.com/sdcoffey/big"
5+
)
6+
7+
type stochasticRSIIndicator struct {
8+
curRSI Indicator
9+
minRSI Indicator
10+
maxRSI Indicator
11+
}
12+
13+
// NewStochasticRSIIndicator returns a derivative Indicator which returns the stochastic RSI indicator for the given
14+
// RSI window.
15+
// https://www.investopedia.com/terms/s/stochrsi.asp
16+
func NewStochasticRSIIndicator(indicator Indicator, timeframe int) Indicator {
17+
rsiIndicator := NewRelativeStrengthIndexIndicator(indicator, timeframe)
18+
return stochasticRSIIndicator{
19+
curRSI: rsiIndicator,
20+
minRSI: NewMinimumValueIndicator(rsiIndicator, timeframe),
21+
maxRSI: NewMaximumValueIndicator(rsiIndicator, timeframe),
22+
}
23+
}
24+
25+
func (sri stochasticRSIIndicator) Calculate(index int) big.Decimal {
26+
curRSI := sri.curRSI.Calculate(index)
27+
minRSI := sri.minRSI.Calculate(index)
28+
maxRSI := sri.maxRSI.Calculate(index)
29+
30+
if minRSI.EQ(maxRSI) {
31+
return big.NewDecimal(100)
32+
}
33+
34+
return curRSI.Sub(minRSI).Div(maxRSI.Sub(minRSI)).Mul(big.NewDecimal(100))
35+
}
36+
37+
type stochRSIKIndicator struct {
38+
stochasticRSI Indicator
39+
window int
40+
}
41+
42+
// NewFastStochasticRSIIndicator returns a derivative Indicator which returns the fast stochastic RSI indicator (%K)
43+
// for the given stochastic window.
44+
func NewFastStochasticRSIIndicator(stochasticRSI Indicator, timeframe int) Indicator {
45+
return stochRSIKIndicator{stochasticRSI, timeframe}
46+
}
47+
48+
func (k stochRSIKIndicator) Calculate(index int) big.Decimal {
49+
return NewSimpleMovingAverage(k.stochasticRSI, k.window).Calculate(index)
50+
}
51+
52+
type stochRSIDIndicator struct {
53+
fastStochasticRSI Indicator
54+
window int
55+
}
56+
57+
// NewSlowStochasticRSIIndicator returns a derivative Indicator which returns the slow stochastic RSI indicator (%D)
58+
// for the given stochastic window.
59+
func NewSlowStochasticRSIIndicator(fastStochasticRSI Indicator, timeframe int) Indicator {
60+
return stochRSIDIndicator{fastStochasticRSI, timeframe}
61+
}
62+
63+
func (d stochRSIDIndicator) Calculate(index int) big.Decimal {
64+
return NewSimpleMovingAverage(d.fastStochasticRSI, d.window).Calculate(index)
65+
}

indicator_stochastic_rsi_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package techan
2+
3+
import (
4+
"testing"
5+
6+
"github.com/sdcoffey/big"
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestStochasticRSIIndicator(t *testing.T) {
11+
indicator := NewStochasticRSIIndicator(NewClosePriceIndicator(mockedTimeSeries), 5)
12+
13+
expectedValues := []float64{
14+
100,
15+
100,
16+
100,
17+
100,
18+
100,
19+
100,
20+
100,
21+
95.9481,
22+
54.5245,
23+
93.1791,
24+
0,
25+
21.6754,
26+
}
27+
28+
indicatorEquals(t, expectedValues, indicator)
29+
}
30+
31+
func TestFastStochasticRSIIndicator(t *testing.T) {
32+
indicator := NewFastStochasticRSIIndicator(NewStochasticRSIIndicator(NewClosePriceIndicator(mockedTimeSeries),
33+
5), 3)
34+
35+
expectedValues := []float64{
36+
0,
37+
0,
38+
100,
39+
100,
40+
100,
41+
100,
42+
100,
43+
98.6494,
44+
83.4909,
45+
81.2173,
46+
49.2346,
47+
38.2848,
48+
}
49+
50+
indicatorEquals(t, expectedValues, indicator)
51+
}
52+
53+
func TestSlowStochasticRSIIndicator(t *testing.T) {
54+
indicator := NewSlowStochasticRSIIndicator(NewFastStochasticRSIIndicator(NewStochasticRSIIndicator(
55+
NewClosePriceIndicator(mockedTimeSeries), 5), 3), 3)
56+
57+
expectedValues := []float64{
58+
0,
59+
0,
60+
33.3333,
61+
66.6667,
62+
100,
63+
100,
64+
100,
65+
99.5498,
66+
94.0468,
67+
87.7858,
68+
71.3142,
69+
56.2456,
70+
}
71+
72+
indicatorEquals(t, expectedValues, indicator)
73+
}
74+
75+
func TestFastStochasticRSIIndicatorNoPriceChange(t *testing.T) {
76+
close := NewClosePriceIndicator(mockTimeSeries("42.0", "42.0"))
77+
rsInd := NewStochasticRSIIndicator(close, 2)
78+
assert.Equal(t, big.NewDecimal(100).FormattedString(2), rsInd.Calculate(1).FormattedString(2))
79+
}

0 commit comments

Comments
 (0)