-
-
Notifications
You must be signed in to change notification settings - Fork 110
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Describe Request %B indicator is added. Fixed #254 # Change Type New indicator. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a new volatility indicator, `%B`, enhancing technical analysis capabilities. - Added methods for creating and computing the `%B` indicator, including `NewPercentB` and `NewPercentBWithPeriod`. - Updated Bollinger Bands functionality to allow custom periods with `NewBollingerBandsWithPeriod`. - **Bug Fixes** - Adjusted method signatures for improved clarity and usability. - **Tests** - Added tests for the `%B` indicator to validate functionality and string representation. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Loading branch information
Showing
7 changed files
with
518 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Copyright (c) 2021-2024 Onur Cinar. | ||
// The source code is provided under GNU AGPLv3 License. | ||
// https://github.com/cinar/indicator | ||
|
||
package volatility | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/cinar/indicator/v2/helper" | ||
) | ||
|
||
// PercentB represents the parameters for calculating the %B indicator. | ||
// | ||
// %B = (Close - Lower Band) / (Upper Band - Lower Band) | ||
type PercentB[T helper.Number] struct { | ||
// BollingerBands is the underlying Bollinger Bands indicator used for calculations. | ||
BollingerBands *BollingerBands[T] | ||
} | ||
|
||
// NewPercentB function initializes a new %B instance with the default parameters. | ||
func NewPercentB[T helper.Number]() *PercentB[T] { | ||
return NewPercentBWithPeriod[T](DefaultBollingerBandsPeriod) | ||
} | ||
|
||
// NewPercentBWithPeriod function initializes a new %B instance with the given period. | ||
func NewPercentBWithPeriod[T helper.Number](period int) *PercentB[T] { | ||
return &PercentB[T]{ | ||
BollingerBands: NewBollingerBandsWithPeriod[T](period), | ||
} | ||
} | ||
|
||
// Compute function takes a channel of numbers and computes the %B over the specified period. | ||
func (p *PercentB[T]) Compute(closings <-chan T) <-chan T { | ||
closingsSplice := helper.Duplicate(closings, 2) | ||
|
||
// Compute the Bollinger Bands | ||
upperBands, middleBands, lowerBands := p.BollingerBands.Compute(closingsSplice[0]) | ||
|
||
// Skip closings until the Bollinger Bands are available | ||
closingsSplice[1] = helper.Skip(closingsSplice[1], p.BollingerBands.IdlePeriod()) | ||
|
||
// Drain the middle bands | ||
go helper.Drain(middleBands) | ||
|
||
return helper.Operate3(upperBands, lowerBands, closingsSplice[1], func(upperBand, lowerBand, closing T) T { | ||
// %B = (Close - Lower Band) / (Upper Band - Lower Band) | ||
return (closing - lowerBand) / (upperBand - lowerBand) | ||
}) | ||
} | ||
|
||
// IdlePeriod is the initial period that %B yield any results. | ||
func (p *PercentB[T]) IdlePeriod() int { | ||
return p.BollingerBands.IdlePeriod() | ||
} | ||
|
||
// String is the string representation of the %B. | ||
func (p *PercentB[T]) String() string { | ||
return fmt.Sprintf("%%B(%d)", p.BollingerBands.Period) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Copyright (c) 2021-2024 Onur Cinar. | ||
// The source code is provided under GNU AGPLv3 License. | ||
// https://github.com/cinar/indicator | ||
|
||
package volatility_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/cinar/indicator/v2/helper" | ||
"github.com/cinar/indicator/v2/volatility" | ||
) | ||
|
||
func ExamplePercentB() { | ||
// Closing prices | ||
closes := helper.SliceToChan([]float64{ | ||
318.600006, 315.839996, 316.149994, 310.570007, 307.779999, | ||
305.820007, 305.98999, 306.390015, 311.450012, 312.329987, | ||
309.290009, 301.910004, 300, 300.029999, 302, | ||
307.820007, 302.690002, 306.48999, 305.549988, 303.429993, | ||
}) | ||
|
||
// Initialize the %B indicator | ||
percentB := volatility.NewPercentB[float64]() | ||
|
||
// Compute %B | ||
result := percentB.Compute(closes) | ||
|
||
// Round digits | ||
result = helper.RoundDigits(result, 2) | ||
|
||
fmt.Println(helper.ChanToSlice(result)) | ||
// Output: [0.3] | ||
} | ||
|
||
func TestPercentB(t *testing.T) { | ||
type Data struct { | ||
Close float64 | ||
PercentB float64 | ||
} | ||
|
||
input, err := helper.ReadFromCsvFile[Data]("testdata/percent_b.csv", true) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
inputs := helper.Duplicate(input, 2) | ||
closing := helper.Map(inputs[0], func(d *Data) float64 { return d.Close }) | ||
expected := helper.Map(inputs[1], func(d *Data) float64 { return d.PercentB }) | ||
|
||
percentB := volatility.NewPercentB[float64]() | ||
|
||
actual := percentB.Compute(closing) | ||
actual = helper.RoundDigits(actual, 2) | ||
|
||
expected = helper.Skip(expected, percentB.IdlePeriod()) | ||
|
||
err = helper.CheckEquals(actual, expected) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
} | ||
|
||
func TestPercentBString(t *testing.T) { | ||
expected := "%B(10)" | ||
actual := volatility.NewPercentBWithPeriod[float64](10).String() | ||
|
||
if actual != expected { | ||
t.Fatalf("actual %v expected %v", actual, expected) | ||
} | ||
} |
Oops, something went wrong.