Skip to content

Commit

Permalink
Stochastic RSI is added. (#156)
Browse files Browse the repository at this point in the history
# Describe Request

Stochastic RSI is added.

Fixed #54 

# Change Type

Momentum indicator and strategy.
  • Loading branch information
cinar authored Jun 15, 2024
1 parent 2da686e commit 1832e4f
Show file tree
Hide file tree
Showing 10 changed files with 966 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ The following list of indicators are currently supported by this package:
- [Relative Strength Index (RSI)](momentum/README.md#type-rsi)
- [Qstick](momentum/README.md#type-qstick)
- [Stochastic Oscillator](momentum/README.md#type-stochasticoscillator)
- [Stochastic RSI](momentum/README.md#type-stochasticrsi)
- [Williams R](momentum/README.md#type-williamsr)

### 🎢 Volatility Indicators
Expand Down Expand Up @@ -133,6 +134,7 @@ The following list of strategies are currently supported by this package:

- [Awesome Oscillator Strategy](strategy/momentum/README.md#type-awesomeoscillatorstrategy)
- [RSI Strategy](strategy/momentum/README.md#type-rsistrategy)
- [Stochastic RSI Strategy](strategy/momentum/README.md#type-stochasticrsistrategy)
- Williams R Strategy

### 🎢 Volatility Strategies
Expand Down
81 changes: 81 additions & 0 deletions momentum/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ The information provided on this project is strictly for informational purposes
- [func NewStochasticOscillator\[T helper.Number\]\(\) \*StochasticOscillator\[T\]](<#NewStochasticOscillator>)
- [func \(s \*StochasticOscillator\[T\]\) Compute\(highs, lows, closings \<\-chan T\) \(\<\-chan T, \<\-chan T\)](<#StochasticOscillator[T].Compute>)
- [func \(s \*StochasticOscillator\[T\]\) IdlePeriod\(\) int](<#StochasticOscillator[T].IdlePeriod>)
- [type StochasticRsi](<#StochasticRsi>)
- [func NewStochasticRsi\[T helper.Number\]\(\) \*StochasticRsi\[T\]](<#NewStochasticRsi>)
- [func NewStochasticRsiWithPeriod\[T helper.Number\]\(period int\) \*StochasticRsi\[T\]](<#NewStochasticRsiWithPeriod>)
- [func \(s \*StochasticRsi\[T\]\) Compute\(closings \<\-chan T\) \<\-chan T](<#StochasticRsi[T].Compute>)
- [func \(s \*StochasticRsi\[T\]\) IdlePeriod\(\) int](<#StochasticRsi[T].IdlePeriod>)
- [type WilliamsR](<#WilliamsR>)
- [func NewWilliamsR\[T helper.Number\]\(\) \*WilliamsR\[T\]](<#NewWilliamsR>)
- [func \(w \*WilliamsR\[T\]\) Compute\(highs, lows, closings \<\-chan T\) \<\-chan T](<#WilliamsR[T].Compute>)
Expand Down Expand Up @@ -168,6 +173,15 @@ const (
)
```

<a name="DefaultStochasticRsiPeriod"></a>

```go
const (
// DefaultStochasticRsiPeriod is the default period for the Stochastic Relative Strength Index (RSI).
DefaultStochasticRsiPeriod = 14
)
```

<a name="DefaultWilliamsRPeriod"></a>

```go
Expand Down Expand Up @@ -645,6 +659,73 @@ func (s *StochasticOscillator[T]) IdlePeriod() int

IdlePeriod is the initial period that Stochastic Oscillator won't yield any results.

<a name="StochasticRsi"></a>
## type [StochasticRsi](<https://github.com/cinar/indicator/blob/master/momentum/stochastic_rsi.go#L29-L38>)

StochasticRsi represents the configuration parameter for calculating the Stochastic Relative Strength Index \(RSI\). It is a momentum indicator that focuses on the historical performance to evaluate overbought and oversold conditions.

```
RSI - Min(RSI)
Stochastic RSI = -------------------------
Max(RSI) - Min(RSI)
```

Example:

```
stochasticRsi := momentum.NewStochasticRsi[float64]()
result := stochasticRsi.Compute(closings)
```

```go
type StochasticRsi[T helper.Number] struct {
// Rsi is that RSI instance.
Rsi *Rsi[T]

// Min is the Moving Min instance.
Min *trend.MovingMin[T]

// Max is the Moving Max instance.
Max *trend.MovingMax[T]
}
```

<a name="NewStochasticRsi"></a>
### func [NewStochasticRsi](<https://github.com/cinar/indicator/blob/master/momentum/stochastic_rsi.go#L41>)

```go
func NewStochasticRsi[T helper.Number]() *StochasticRsi[T]
```

NewStochasticRsi function initializes a new Storchastic RSI instance with the default parameters.

<a name="NewStochasticRsiWithPeriod"></a>
### func [NewStochasticRsiWithPeriod](<https://github.com/cinar/indicator/blob/master/momentum/stochastic_rsi.go#L46>)

```go
func NewStochasticRsiWithPeriod[T helper.Number](period int) *StochasticRsi[T]
```

NewStochasticRsiWithPeriod function initializes a new Stochastic RSI instance with the given period.

<a name="StochasticRsi[T].Compute"></a>
### func \(\*StochasticRsi\[T\]\) [Compute](<https://github.com/cinar/indicator/blob/master/momentum/stochastic_rsi.go#L55>)

```go
func (s *StochasticRsi[T]) Compute(closings <-chan T) <-chan T
```

Compute function takes a channel of closings numbers and computes the Stochastic RSI.

<a name="StochasticRsi[T].IdlePeriod"></a>
### func \(\*StochasticRsi\[T\]\) [IdlePeriod](<https://github.com/cinar/indicator/blob/master/momentum/stochastic_rsi.go#L85>)

```go
func (s *StochasticRsi[T]) IdlePeriod() int
```

IdlePeriod is the initial period that Stochasic RSI won't yield any results.

<a name="WilliamsR"></a>
## type [WilliamsR](<https://github.com/cinar/indicator/blob/master/momentum/williams_r.go#L29-L35>)

Expand Down
87 changes: 87 additions & 0 deletions momentum/stochastic_rsi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// StochasticRsipyright (c) 2021-2024 Onur Cinar.
// The source code is provided under GNU AGPLv3 License.
// https://github.com/cinar/indicator

package momentum

import (
"github.com/cinar/indicator/v2/helper"
"github.com/cinar/indicator/v2/trend"
)

const (
// DefaultStochasticRsiPeriod is the default period for the Stochastic Relative Strength Index (RSI).
DefaultStochasticRsiPeriod = 14
)

// StochasticRsi represents the configuration parameter for calculating the Stochastic Relative Strength Index (RSI).
// It is a momentum indicator that focuses on the historical performance to evaluate overbought and
// oversold conditions.
//
// RSI - Min(RSI)
// Stochastic RSI = -------------------------
// Max(RSI) - Min(RSI)
//
// Example:
//
// stochasticRsi := momentum.NewStochasticRsi[float64]()
// result := stochasticRsi.Compute(closings)
type StochasticRsi[T helper.Number] struct {
// Rsi is that RSI instance.
Rsi *Rsi[T]

// Min is the Moving Min instance.
Min *trend.MovingMin[T]

// Max is the Moving Max instance.
Max *trend.MovingMax[T]
}

// NewStochasticRsi function initializes a new Storchastic RSI instance with the default parameters.
func NewStochasticRsi[T helper.Number]() *StochasticRsi[T] {
return NewStochasticRsiWithPeriod[T](DefaultStochasticRsiPeriod)
}

// NewStochasticRsiWithPeriod function initializes a new Stochastic RSI instance with the given period.
func NewStochasticRsiWithPeriod[T helper.Number](period int) *StochasticRsi[T] {
return &StochasticRsi[T]{
Rsi: NewRsiWithPeriod[T](period),
Min: trend.NewMovingMinWithPeriod[T](period),
Max: trend.NewMovingMaxWithPeriod[T](period),
}
}

// Compute function takes a channel of closings numbers and computes the Stochastic RSI.
func (s *StochasticRsi[T]) Compute(closings <-chan T) <-chan T {
rsisSplice := helper.Duplicate(
s.Rsi.Compute(closings),
3,
)

rsisSplice[0] = helper.Skip(rsisSplice[0], s.Max.IdlePeriod())

minRsisSplice := helper.Duplicate(
s.Min.Compute(rsisSplice[1]),
2,
)

maxRsis := s.Max.Compute(rsisSplice[2])

result := helper.Divide(
helper.Subtract(
rsisSplice[0],
minRsisSplice[0],
),
helper.Subtract(
maxRsis,
minRsisSplice[1],
),
)

return result
}

// IdlePeriod is the initial period that Stochasic RSI won't yield any results.
func (s *StochasticRsi[T]) IdlePeriod() int {
return s.Rsi.IdlePeriod() + s.Min.IdlePeriod()
}
39 changes: 39 additions & 0 deletions momentum/stochastic_rsi_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// StochasticRsipyright (c) 2021-2024 Onur Cinar.
// The source code is provided under GNU AGPLv3 License.
// https://github.com/cinar/indicator

package momentum_test

import (
"testing"

"github.com/cinar/indicator/v2/helper"
"github.com/cinar/indicator/v2/momentum"
)

func TestStochasticRsi(t *testing.T) {
type Data struct {
Close float64
StochasticRsi float64
}

input, err := helper.ReadFromCsvFile[Data]("testdata/stochastic_rsi.csv", true)
if err != nil {
t.Fatal(err)
}

inputs := helper.Duplicate(input, 2)
closings := helper.Map(inputs[0], func(d *Data) float64 { return d.Close })
expected := helper.Map(inputs[1], func(d *Data) float64 { return d.StochasticRsi })

stochasticRsi := momentum.NewStochasticRsi[float64]()
actual := stochasticRsi.Compute(closings)
actual = helper.RoundDigits(actual, 2)

expected = helper.Skip(expected, stochasticRsi.IdlePeriod())

err = helper.CheckEquals(actual, expected)
if err != nil {
t.Fatal(err)
}
}
Loading

0 comments on commit 1832e4f

Please sign in to comment.