Skip to content

Commit

Permalink
Acceleration Bands is added.
Browse files Browse the repository at this point in the history
  • Loading branch information
cinar committed Dec 31, 2023
1 parent a8fc93b commit a885b2d
Show file tree
Hide file tree
Showing 5 changed files with 457 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ The following list of indicators are currently supported by this package:

### 🎢 Volatility Indicators

- Acceleration Bands
- [Acceleration Bands](volatility/README.md#type-accelerationbands)
- Actual True Range (ATR)
- [Bollinger Band Width](volatility/README.md#type-bollingerbandwidth)
- [Bollinger Bands](volatility/README.md#type-bollingerbands)
Expand Down
65 changes: 65 additions & 0 deletions volatility/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ The information provided on this project is strictly for informational purposes
## Index

- [Constants](<#constants>)
- [type AccelerationBands](<#AccelerationBands>)
- [func NewAccelerationBands\[T helper.Number\]\(\) \*AccelerationBands\[T\]](<#NewAccelerationBands>)
- [func \(a \*AccelerationBands\[T\]\) Compute\(high, low, closing \<\-chan T\) \(\<\-chan T, \<\-chan T, \<\-chan T\)](<#AccelerationBands[T].Compute>)
- [func \(a \*AccelerationBands\[T\]\) IdlePeriod\(\) int](<#AccelerationBands[T].IdlePeriod>)
- [type BollingerBandWidth](<#BollingerBandWidth>)
- [func NewBollingerBandWidth\[T helper.Number\]\(\) \*BollingerBandWidth\[T\]](<#NewBollingerBandWidth>)
- [func \(b \*BollingerBandWidth\[T\]\) Compute\(c \<\-chan T\) \<\-chan T](<#BollingerBandWidth[T].Compute>)
Expand All @@ -42,6 +46,15 @@ The information provided on this project is strictly for informational purposes

## Constants

<a name="DefaultAccelerationBandsPeriod"></a>

```go
const (
// DefaultAccelerationBandsPeriod is the default period for the Acceleration Bands.
DefaultAccelerationBandsPeriod = 20
)
```

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

```go
Expand All @@ -51,6 +64,58 @@ const (
)
```

<a name="AccelerationBands"></a>
## type [AccelerationBands](<https://github.com/cinar/indicator/blob/v2/volatility/acceleration_bands.go#L27-L30>)

AccelerationBands represents the configuration parameters for calculating the Acceleration Bands.

```
Upper Band = SMA(High * (1 + 4 * (High - Low) / (High + Low)))
Middle Band = SMA(Closing)
Lower Band = SMA(Low * (1 - 4 * (High - Low) / (High + Low)))
```

Example:

```
accelerationBands := NewAccelerationBands[float64]()
accelerationBands.Compute(values)
```

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

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

```go
func NewAccelerationBands[T helper.Number]() *AccelerationBands[T]
```

NewAccelerationBands function initializes a new Acceleration Bands instance with the default parameters.

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

```go
func (a *AccelerationBands[T]) Compute(high, low, closing <-chan T) (<-chan T, <-chan T, <-chan T)
```

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

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

```go
func (a *AccelerationBands[T]) IdlePeriod() int
```

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

<a name="BollingerBandWidth"></a>
## type [BollingerBandWidth](<https://github.com/cinar/indicator/blob/v2/volatility/bollinger_band_width.go#L24-L27>)

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

package volatility

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

const (
// DefaultAccelerationBandsPeriod is the default period for the Acceleration Bands.
DefaultAccelerationBandsPeriod = 20
)

// AccelerationBands represents the configuration parameters for calculating the Acceleration Bands.
//
// Upper Band = SMA(High * (1 + 4 * (High - Low) / (High + Low)))
// Middle Band = SMA(Closing)
// Lower Band = SMA(Low * (1 - 4 * (High - Low) / (High + Low)))
//
// Example:
//
// accelerationBands := NewAccelerationBands[float64]()
// accelerationBands.Compute(values)
type AccelerationBands[T helper.Number] struct {
// Time period.
Period int
}

// NewAccelerationBands function initializes a new Acceleration Bands instance with the default parameters.
func NewAccelerationBands[T helper.Number]() *AccelerationBands[T] {
return &AccelerationBands[T]{
Period: DefaultAccelerationBandsPeriod,
}
}

// Compute function takes a channel of numbers and computes the Acceleration Bands over the specified period.
func (a *AccelerationBands[T]) Compute(high, low, closing <-chan T) (<-chan T, <-chan T, <-chan T) {
highs := helper.Duplicate(high, 3)
lows := helper.Duplicate(low, 3)

ks := helper.Duplicate(
helper.Divide(
helper.Subtract(highs[0], lows[0]),
helper.Add(highs[1], lows[1]),
),
2,
)

sma := trend.NewSmaWithPeriod[T](a.Period)

upper := sma.Compute(
helper.Multiply(
highs[2],
helper.IncrementBy(
helper.MultiplyBy(
ks[0],
4,
),
1,
),
),
)

middle := sma.Compute(closing)

lower := sma.Compute(
helper.Multiply(
lows[2],
helper.IncrementBy(
helper.MultiplyBy(
ks[1],
-4,
),
1,
),
),
)

return upper, middle, lower
}

// IdlePeriod is the initial period that Acceleration Bands won't yield any results.
func (a *AccelerationBands[T]) IdlePeriod() int {
return a.Period - 1
}
51 changes: 51 additions & 0 deletions volatility/acceleration_bands_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2021-2023 Onur Cinar.
// The source code is provided under GNU AGPLv3 License.
// https://github.com/cinar/indicator

package volatility_test

import (
"testing"

"github.com/cinar/indicator/helper"
"github.com/cinar/indicator/volatility"
)

func TestAccelerationBands(t *testing.T) {
type Data struct {
High float64
Low float64
Close float64
Upper float64
Middle float64
Lower float64
}

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

inputs := helper.Duplicate(input, 6)
highs := helper.Map(inputs[0], func(d *Data) float64 { return d.High })
lows := helper.Map(inputs[1], func(d *Data) float64 { return d.Low })
closings := helper.Map(inputs[2], func(d *Data) float64 { return d.Close })
upper := helper.Map(inputs[3], func(d *Data) float64 { return d.Upper })
middle := helper.Map(inputs[4], func(d *Data) float64 { return d.Middle })
lower := helper.Map(inputs[5], func(d *Data) float64 { return d.Lower })

ab := volatility.NewAccelerationBands[float64]()
actualUpper, actualMiddle, actualLower := ab.Compute(highs, lows, closings)
actualUpper = helper.RoundDigits(actualUpper, 2)
actualMiddle = helper.RoundDigits(actualMiddle, 2)
actualLower = helper.RoundDigits(actualLower, 2)

upper = helper.Skip(upper, ab.IdlePeriod())
middle = helper.Skip(middle, ab.IdlePeriod())
lower = helper.Skip(lower, ab.IdlePeriod())

err = helper.CheckEquals(actualUpper, upper, actualMiddle, middle, actualLower, lower)
if err != nil {
t.Fatal(err)
}
}
Loading

0 comments on commit a885b2d

Please sign in to comment.