Skip to content

Commit

Permalink
Moving Standard Deviation and Bollinger Bands are added.
Browse files Browse the repository at this point in the history
  • Loading branch information
cinar committed Dec 30, 2023
1 parent cd31450 commit 875fdc9
Show file tree
Hide file tree
Showing 14 changed files with 990 additions and 12 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ The following list of indicators are currently supported by this package:
- Acceleration Bands
- Actual True Range (ATR)
- Bollinger Band Width
- Bollinger Bands
- [Bollinger Bands](volatility/README.md#type-bollingerbands)
- Chandelier Exit
- Donchian Channel (DC)
- Keltner Channel (KC)
- Moving Standard Deviation (Std)
- [Moving Standard Deviation (Std)](volatility/README.md#type-movingstd)
- Projection Oscillator (PO)
- Ulcer Index (UI)

Expand Down
22 changes: 21 additions & 1 deletion helper/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,10 @@ The information provided on this project is strictly for informational purposes
- [func NewNumericReportColumn\[T Number\]\(name string, values \<\-chan T\) ReportColumn](<#NewNumericReportColumn>)
- [type Ring](<#Ring>)
- [func NewRing\[T any\]\(size int\) \*Ring\[T\]](<#NewRing>)
- [func \(r \*Ring\[T\]\) At\(index int\) T](<#Ring[T].At>)
- [func \(r \*Ring\[T\]\) Get\(\) \(T, bool\)](<#Ring[T].Get>)
- [func \(r \*Ring\[T\]\) IsEmpty\(\) bool](<#Ring[T].IsEmpty>)
- [func \(r \*Ring\[T\]\) IsFull\(\) bool](<#Ring[T].IsFull>)
- [func \(r \*Ring\[T\]\) Put\(t T\) T](<#Ring[T].Put>)


Expand Down Expand Up @@ -1050,6 +1052,15 @@ func NewRing[T any](size int) *Ring[T]

NewRing creates a new ring instance with the given size.

<a name="Ring[T].At"></a>
### func \(\*Ring\[T\]\) [At](<https://github.com/cinar/indicator/blob/v2/helper/ring.go#L71>)

```go
func (r *Ring[T]) At(index int) T
```

At returns the value at the given index.

<a name="Ring[T].Get"></a>
### func \(\*Ring\[T\]\) [Get](<https://github.com/cinar/indicator/blob/v2/helper/ring.go#L53>)

Expand All @@ -1060,14 +1071,23 @@ func (r *Ring[T]) Get() (T, bool)
Get retrieves the available value from the ring buffer. If empty, it returns the default value \(T\) and false.

<a name="Ring[T].IsEmpty"></a>
### func \(\*Ring\[T\]\) [IsEmpty](<https://github.com/cinar/indicator/blob/v2/helper/ring.go#L71>)
### func \(\*Ring\[T\]\) [IsEmpty](<https://github.com/cinar/indicator/blob/v2/helper/ring.go#L76>)

```go
func (r *Ring[T]) IsEmpty() bool
```

IsEmpty checks if the current ring buffer is empty.

<a name="Ring[T].IsFull"></a>
### func \(\*Ring\[T\]\) [IsFull](<https://github.com/cinar/indicator/blob/v2/helper/ring.go#L81>)

```go
func (r *Ring[T]) IsFull() bool
```

IsFull checks if the current ring buffer is full.

<a name="Ring[T].Put"></a>
### func \(\*Ring\[T\]\) [Put](<https://github.com/cinar/indicator/blob/v2/helper/ring.go#L37>)

Expand Down
12 changes: 11 additions & 1 deletion helper/ring.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func NewRing[T any](size int) *Ring[T] {
// Put inserts the specified value into the ring and returns the
// value that was previously stored at that index.
func (r *Ring[T]) Put(t T) T {
if !r.empty && (r.end == r.begin) {
if r.IsFull() {
r.begin = r.nextIndex(r.begin)
}

Expand Down Expand Up @@ -67,11 +67,21 @@ func (r *Ring[T]) Get() (T, bool) {
return t, true
}

// At returns the value at the given index.
func (r *Ring[T]) At(index int) T {
return r.buffer[(r.begin+index)%len(r.buffer)]
}

// IsEmpty checks if the current ring buffer is empty.
func (r *Ring[T]) IsEmpty() bool {
return r.empty
}

// IsFull checks if the current ring buffer is full.
func (r *Ring[T]) IsFull() bool {
return !r.empty && (r.end == r.begin)
}

// nextIndex returns the next index in a ring buffer, wrapping
// around if it reaches the capacity.
func (r *Ring[T]) nextIndex(i int) int {
Expand Down
15 changes: 14 additions & 1 deletion helper/ring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,25 @@ func TestRingEmpty(t *testing.T) {
t.Fatal("not empty")
}

for _, n := range input {
for i, n := range input {
ring.Put(n)

if ring.IsEmpty() {
t.Fatal("is empty")
}

j := i
if j >= size {
j = size - 1
}

if ring.At(j) != n {
t.Fatalf("actual %v expected %v", ring.At(j), n)
}
}

if !ring.IsFull() {
t.Fatal("not full")
}

for i := 0; i < size; i++ {
Expand Down
21 changes: 18 additions & 3 deletions trend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ The information provided on this project is strictly for informational purposes
- [func \(m \*MovingMin\[T\]\) Compute\(c \<\-chan T\) \<\-chan T](<#MovingMin[T].Compute>)
- [type MovingSum](<#MovingSum>)
- [func NewMovingSum\[T helper.Number\]\(\) \*MovingSum\[T\]](<#NewMovingSum>)
- [func NewMovingSumWithPeriod\[T helper.Number\]\(period int\) \*MovingSum\[T\]](<#NewMovingSumWithPeriod>)
- [func \(m \*MovingSum\[T\]\) Compute\(c \<\-chan T\) \<\-chan T](<#MovingSum[T].Compute>)
- [type Rma](<#Rma>)
- [func NewRma\[T helper.Number\]\(\) \*Rma\[T\]](<#NewRma>)
Expand Down Expand Up @@ -766,12 +767,17 @@ func (m *MovingMin[T]) Compute(c <-chan T) <-chan T
Compute function takes a channel of numbers and computes the Moving Min over the specified period.

<a name="MovingSum"></a>
## type [MovingSum](<https://github.com/cinar/indicator/blob/v2/trend/moving_sum.go#L13-L16>)
## type [MovingSum](<https://github.com/cinar/indicator/blob/v2/trend/moving_sum.go#L15-L18>)

MovingSum represents the configuration parameters for calculating the Moving Sum over the specified period.

Example:

```
sum := trend.NewMovingSum[float64]()
sum.Period = 20
```

```go
type MovingSum[T helper.Number] struct {
// Time period.
Expand All @@ -780,16 +786,25 @@ type MovingSum[T helper.Number] struct {
```

<a name="NewMovingSum"></a>
### func [NewMovingSum](<https://github.com/cinar/indicator/blob/v2/trend/moving_sum.go#L20>)
### func [NewMovingSum](<https://github.com/cinar/indicator/blob/v2/trend/moving_sum.go#L21>)

```go
func NewMovingSum[T helper.Number]() *MovingSum[T]
```

NewMovingSum function initializes a new Moving Sum instance with the default parameters.

<a name="NewMovingSumWithPeriod"></a>
### func [NewMovingSumWithPeriod](<https://github.com/cinar/indicator/blob/v2/trend/moving_sum.go#L26>)

```go
func NewMovingSumWithPeriod[T helper.Number](period int) *MovingSum[T]
```

NewMovingSumWithPeriod function initializes a new Moving Sum instance with the given period.

<a name="MovingSum[T].Compute"></a>
### func \(\*MovingSum\[T\]\) [Compute](<https://github.com/cinar/indicator/blob/v2/trend/moving_sum.go#L26>)
### func \(\*MovingSum\[T\]\) [Compute](<https://github.com/cinar/indicator/blob/v2/trend/moving_sum.go#L34>)

```go
func (m *MovingSum[T]) Compute(c <-chan T) <-chan T
Expand Down
16 changes: 12 additions & 4 deletions trend/moving_sum.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,29 @@ package trend

import "github.com/cinar/indicator/helper"

// MovingSum represents the configuration parameters for calculating the
// Moving Sum over the specified period.
// MovingSum represents the configuration parameters for calculating the Moving Sum over the specified period.
//
// Example:
//
// sum := trend.NewMovingSum[float64]()
// sum.Period = 20
type MovingSum[T helper.Number] struct {
// Time period.
Period int
}

// NewMovingSum function initializes a new Moving Sum instance
// with the default parameters.
// NewMovingSum function initializes a new Moving Sum instance with the default parameters.
func NewMovingSum[T helper.Number]() *MovingSum[T] {
return &MovingSum[T]{}
}

// NewMovingSumWithPeriod function initializes a new Moving Sum instance with the given period.
func NewMovingSumWithPeriod[T helper.Number](period int) *MovingSum[T] {
sum := NewMovingSum[T]()
sum.Period = period
return sum
}

// Compute function takes a channel of numbers and computes the
// Moving Sum over the specified period.
func (m *MovingSum[T]) Compute(c <-chan T) <-chan T {
Expand Down
156 changes: 156 additions & 0 deletions volatility/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<!-- Code generated by gomarkdoc. DO NOT EDIT -->

# volatility

```go
import "github.com/cinar/indicator/volatility"
```

Package volatility contains the volatility indicator functions.

This package belongs to the Indicator project. Indicator is a Golang module that supplies a variety of technical indicators, strategies, and a backtesting framework for analysis.

### License

```
Copyright (c) 2021-2023 Onur Cinar.
The source code is provided under GNU AGPLv3 License.
https://github.com/cinar/indicator
```

### Disclaimer

The information provided on this project is strictly for informational purposes and is not to be construed as advice or solicitation to buy or sell any security.

## Index

- [Constants](<#constants>)
- [type BollingerBands](<#BollingerBands>)
- [func NewBollingerBands\[T helper.Number\]\(\) \*BollingerBands\[T\]](<#NewBollingerBands>)
- [func \(b \*BollingerBands\[T\]\) Compute\(c \<\-chan T\) \(\<\-chan T, \<\-chan T, \<\-chan T\)](<#BollingerBands[T].Compute>)
- [func \(b \*BollingerBands\[T\]\) IdlePeriod\(\) int](<#BollingerBands[T].IdlePeriod>)
- [type MovingStd](<#MovingStd>)
- [func NewMovingStd\[T helper.Number\]\(\) \*MovingStd\[T\]](<#NewMovingStd>)
- [func NewMovingStdWithPeriod\[T helper.Number\]\(period int\) \*MovingStd\[T\]](<#NewMovingStdWithPeriod>)
- [func \(m \*MovingStd\[T\]\) Compute\(c \<\-chan T\) \<\-chan T](<#MovingStd[T].Compute>)
- [func \(m \*MovingStd\[T\]\) IdlePeriod\(\) int](<#MovingStd[T].IdlePeriod>)


## Constants

<a name="DefaultBollingerBandsPeriod"></a>

```go
const (
// DefaultBollingerBandsPeriod is the default period for the Bollinger Bands.
DefaultBollingerBandsPeriod = 20
)
```

<a name="BollingerBands"></a>
## type [BollingerBands](<https://github.com/cinar/indicator/blob/v2/volatility/bollinger_bands.go#L29-L32>)

BollingerBands represents the configuration parameters for calculating the Bollinger Bands. It is a technical analysis tool used to gauge a market's volatility and identify overbought and oversold conditions. Returns the upper band, the middle band, and the lower band.

```
Middle Band = 20-Period SMA.
Upper Band = 20-Period SMA + 2 (20-Period Std)
Lower Band = 20-Period SMA - 2 (20-Period Std)
```

Example:

```
bollingerBands := NewBollingerBands[float64]()
bollingerBands.Compute(values)
```

```go
type BollingerBands[T helper.Number] struct {
// Time period.
Period int
}
```

<a name="NewBollingerBands"></a>
### func [NewBollingerBands](<https://github.com/cinar/indicator/blob/v2/volatility/bollinger_bands.go#L35>)

```go
func NewBollingerBands[T helper.Number]() *BollingerBands[T]
```

NewBollingerBands function initializes a new Bollinger Bands instance with the default parameters.

<a name="BollingerBands[T].Compute"></a>
### func \(\*BollingerBands\[T\]\) [Compute](<https://github.com/cinar/indicator/blob/v2/volatility/bollinger_bands.go#L42>)

```go
func (b *BollingerBands[T]) Compute(c <-chan T) (<-chan T, <-chan T, <-chan T)
```

Compute function takes a channel of numbers and computes the Bollinger Bands over the specified period.

<a name="BollingerBands[T].IdlePeriod"></a>
### func \(\*BollingerBands\[T\]\) [IdlePeriod](<https://github.com/cinar/indicator/blob/v2/volatility/bollinger_bands.go#L74>)

```go
func (b *BollingerBands[T]) IdlePeriod() int
```

IdlePeriod is the initial period that Bollinger Bands won't yield any results.

<a name="MovingStd"></a>
## type [MovingStd](<https://github.com/cinar/indicator/blob/v2/volatility/moving_std.go#L19-L22>)

MovingStd represents the configuration parameters for calculating the Moving Standard Deviation over the specified period.

```
Std = Sqrt(1/Period * Sum(Pow(value - sma), 2))
```

Example:

```go
type MovingStd[T helper.Number] struct {
// Time period.
Period int
}
```

<a name="NewMovingStd"></a>
### func [NewMovingStd](<https://github.com/cinar/indicator/blob/v2/volatility/moving_std.go#L25>)

```go
func NewMovingStd[T helper.Number]() *MovingStd[T]
```

NewMovingStd function initializes a new Moving Standard Deviation instance with the default parameters.

<a name="NewMovingStdWithPeriod"></a>
### func [NewMovingStdWithPeriod](<https://github.com/cinar/indicator/blob/v2/volatility/moving_std.go#L30>)

```go
func NewMovingStdWithPeriod[T helper.Number](period int) *MovingStd[T]
```

NewMovingStdWithPeriod function initializes a new Moving Standard Deviation instance with the given period.

<a name="MovingStd[T].Compute"></a>
### func \(\*MovingStd\[T\]\) [Compute](<https://github.com/cinar/indicator/blob/v2/volatility/moving_std.go#L37>)

```go
func (m *MovingStd[T]) Compute(c <-chan T) <-chan T
```

Compute function takes a channel of numbers and computes the Moving Standard Deviation over the specified period.

<a name="MovingStd[T].IdlePeriod"></a>
### func \(\*MovingStd\[T\]\) [IdlePeriod](<https://github.com/cinar/indicator/blob/v2/volatility/moving_std.go#L69>)

```go
func (m *MovingStd[T]) IdlePeriod() int
```

IdlePeriod is the initial period that Moving Standard Deviation won't yield any results.

Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)
Loading

0 comments on commit 875fdc9

Please sign in to comment.