-
-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
549 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
<!-- Code generated by gomarkdoc. DO NOT EDIT --> | ||
|
||
# volatility | ||
|
||
```go | ||
import "github.com/cinar/indicator/strategy/volatility" | ||
``` | ||
|
||
Package volatility contains the volatility strategy 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 | ||
|
||
- [func AllStrategies\(\) \[\]strategy.Strategy](<#AllStrategies>) | ||
- [type BollingerBandsStrategy](<#BollingerBandsStrategy>) | ||
- [func NewBollingerBandsStrategy\(\) \*BollingerBandsStrategy](<#NewBollingerBandsStrategy>) | ||
- [func \(b \*BollingerBandsStrategy\) Compute\(snapshots \<\-chan \*asset.Snapshot\) \<\-chan strategy.Action](<#BollingerBandsStrategy.Compute>) | ||
- [func \(\*BollingerBandsStrategy\) Name\(\) string](<#BollingerBandsStrategy.Name>) | ||
- [func \(b \*BollingerBandsStrategy\) Report\(c \<\-chan \*asset.Snapshot\) \*helper.Report](<#BollingerBandsStrategy.Report>) | ||
|
||
|
||
<a name="AllStrategies"></a> | ||
## func [AllStrategies](<https://github.com/cinar/indicator/blob/v2/strategy/volatility/volatility.go#L24>) | ||
|
||
```go | ||
func AllStrategies() []strategy.Strategy | ||
``` | ||
|
||
AllStrategies returns a slice containing references to all available volatility strategies. | ||
|
||
<a name="BollingerBandsStrategy"></a> | ||
## type [BollingerBandsStrategy](<https://github.com/cinar/indicator/blob/v2/strategy/volatility/bollinger_bands_strategy.go#L17-L22>) | ||
|
||
BollingerBandsStrategy represents the configuration parameters for calculating the Bollinger Bands strategy. A closing value crossing above the upper band suggets a Buy signal, while crossing below the lower band indivates a Sell signal. | ||
|
||
```go | ||
type BollingerBandsStrategy struct { | ||
strategy.Strategy | ||
|
||
// BollingerBands represents the configuration parameters for calculating the Bollinger Bands. | ||
BollingerBands *volatility.BollingerBands[float64] | ||
} | ||
``` | ||
|
||
<a name="NewBollingerBandsStrategy"></a> | ||
### func [NewBollingerBandsStrategy](<https://github.com/cinar/indicator/blob/v2/strategy/volatility/bollinger_bands_strategy.go#L25>) | ||
|
||
```go | ||
func NewBollingerBandsStrategy() *BollingerBandsStrategy | ||
``` | ||
|
||
NewBollingerBandsStrategy function initializes a new Bollinger Bands strategy instance. | ||
|
||
<a name="BollingerBandsStrategy.Compute"></a> | ||
### func \(\*BollingerBandsStrategy\) [Compute](<https://github.com/cinar/indicator/blob/v2/strategy/volatility/bollinger_bands_strategy.go#L37>) | ||
|
||
```go | ||
func (b *BollingerBandsStrategy) Compute(snapshots <-chan *asset.Snapshot) <-chan strategy.Action | ||
``` | ||
|
||
Compute processes the provided asset snapshots and generates a stream of actionable recommendations. | ||
|
||
<a name="BollingerBandsStrategy.Name"></a> | ||
### func \(\*BollingerBandsStrategy\) [Name](<https://github.com/cinar/indicator/blob/v2/strategy/volatility/bollinger_bands_strategy.go#L32>) | ||
|
||
```go | ||
func (*BollingerBandsStrategy) Name() string | ||
``` | ||
|
||
Name returns the name of the strategy. | ||
|
||
<a name="BollingerBandsStrategy.Report"></a> | ||
### func \(\*BollingerBandsStrategy\) [Report](<https://github.com/cinar/indicator/blob/v2/strategy/volatility/bollinger_bands_strategy.go#L82>) | ||
|
||
```go | ||
func (b *BollingerBandsStrategy) Report(c <-chan *asset.Snapshot) *helper.Report | ||
``` | ||
|
||
Report processes the provided asset snapshots and generates a report annotated with the recommended actions. | ||
|
||
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>) |
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,118 @@ | ||
// 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/asset" | ||
"github.com/cinar/indicator/helper" | ||
"github.com/cinar/indicator/strategy" | ||
"github.com/cinar/indicator/volatility" | ||
) | ||
|
||
// BollingerBandsStrategy represents the configuration parameters for calculating the Bollinger Bands strategy. | ||
// A closing value crossing above the upper band suggets a Buy signal, while crossing below the lower band | ||
// indivates a Sell signal. | ||
type BollingerBandsStrategy struct { | ||
strategy.Strategy | ||
|
||
// BollingerBands represents the configuration parameters for calculating the Bollinger Bands. | ||
BollingerBands *volatility.BollingerBands[float64] | ||
} | ||
|
||
// NewBollingerBandsStrategy function initializes a new Bollinger Bands strategy instance. | ||
func NewBollingerBandsStrategy() *BollingerBandsStrategy { | ||
return &BollingerBandsStrategy{ | ||
BollingerBands: volatility.NewBollingerBands[float64](), | ||
} | ||
} | ||
|
||
// Name returns the name of the strategy. | ||
func (*BollingerBandsStrategy) Name() string { | ||
return "Bollinger Bands Strategy" | ||
} | ||
|
||
// Compute processes the provided asset snapshots and generates a stream of actionable recommendations. | ||
func (b *BollingerBandsStrategy) Compute(snapshots <-chan *asset.Snapshot) <-chan strategy.Action { | ||
closings := helper.Duplicate( | ||
asset.SnapshotsAsClosings(snapshots), | ||
3, | ||
) | ||
|
||
uppers, middles, lowers := b.BollingerBands.Compute(closings[0]) | ||
|
||
go helper.Drain(middles) | ||
|
||
closings[1] = helper.Skip(closings[1], b.BollingerBands.IdlePeriod()) | ||
|
||
aboveUppers := helper.Subtract( | ||
closings[1], | ||
uppers, | ||
) | ||
|
||
closings[2] = helper.Skip(closings[2], b.BollingerBands.IdlePeriod()) | ||
|
||
belowLowers := helper.Subtract( | ||
closings[2], | ||
lowers, | ||
) | ||
|
||
actions := helper.Operate(aboveUppers, belowLowers, func(aboveUpper, belowLower float64) strategy.Action { | ||
if aboveUpper > 0 { | ||
return strategy.Buy | ||
} | ||
|
||
if belowLower < 0 { | ||
return strategy.Sell | ||
} | ||
|
||
return strategy.Hold | ||
}) | ||
|
||
actions = strategy.NormalizeActions(actions) | ||
|
||
// Bollinger Bands starts only after a full period. | ||
actions = helper.Shift(actions, b.BollingerBands.IdlePeriod(), strategy.Hold) | ||
|
||
return actions | ||
} | ||
|
||
// Report processes the provided asset snapshots and generates a report annotated with the recommended actions. | ||
func (b *BollingerBandsStrategy) Report(c <-chan *asset.Snapshot) *helper.Report { | ||
// | ||
// snapshots[0] -> dates | ||
// snapshots[1] -> closings[0] -> closings | ||
// closings[1] -> upper | ||
// -> middle | ||
// -> lower | ||
// snapshots[2] -> actions -> annotations | ||
// -> outcomes | ||
// | ||
snapshots := helper.Duplicate(c, 3) | ||
|
||
dates := asset.SnapshotsAsDates(snapshots[0]) | ||
closings := helper.Duplicate(asset.SnapshotsAsClosings(snapshots[1]), 2) | ||
|
||
uppers, middles, lowers := b.BollingerBands.Compute(closings[0]) | ||
uppers = helper.Shift(uppers, b.BollingerBands.IdlePeriod(), 0) | ||
middles = helper.Shift(middles, b.BollingerBands.IdlePeriod(), 0) | ||
lowers = helper.Shift(lowers, b.BollingerBands.IdlePeriod(), 0) | ||
|
||
actions, outcomes := strategy.ComputeWithOutcome(b, snapshots[2]) | ||
annotations := strategy.ActionsToAnnotations(actions) | ||
outcomes = helper.MultiplyBy(outcomes, 100) | ||
|
||
report := helper.NewReport(b.Name(), dates) | ||
report.AddChart() | ||
|
||
report.AddColumn(helper.NewNumericReportColumn("Close", closings[1])) | ||
report.AddColumn(helper.NewNumericReportColumn("Upper", uppers)) | ||
report.AddColumn(helper.NewNumericReportColumn("Middle", middles)) | ||
report.AddColumn(helper.NewNumericReportColumn("Lower", lowers)) | ||
report.AddColumn(helper.NewAnnotationReportColumn(annotations)) | ||
|
||
report.AddColumn(helper.NewNumericReportColumn("Outcome", outcomes), 1) | ||
|
||
return report | ||
} |
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,55 @@ | ||
// Copyright (c) 2021-2023 Onur Cinar. | ||
// The source code is provided under GNU AGPLv3 License. | ||
// https://github.com/cinar/indicator | ||
|
||
package volatility_test | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"github.com/cinar/indicator/asset" | ||
"github.com/cinar/indicator/helper" | ||
"github.com/cinar/indicator/strategy" | ||
"github.com/cinar/indicator/strategy/volatility" | ||
) | ||
|
||
func TestBollingerBandsStrategy(t *testing.T) { | ||
snapshots, err := helper.ReadFromCsvFile[asset.Snapshot]("testdata/brk-b.csv", true) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
results, err := helper.ReadFromCsvFile[strategy.Result]("testdata/bollinger_bands_strategy.csv", true) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
bb := volatility.NewBollingerBandsStrategy() | ||
actions, outcomes := strategy.ComputeWithOutcome(bb, snapshots) | ||
outcomes = helper.RoundDigits(outcomes, 2) | ||
|
||
err = strategy.CheckResults(results, actions, outcomes) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
} | ||
|
||
func TestBollingerBandsStrategyReport(t *testing.T) { | ||
snapshots, err := helper.ReadFromCsvFile[asset.Snapshot]("testdata/brk-b.csv", true) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
bb := volatility.NewBollingerBandsStrategy() | ||
|
||
report := bb.Report(snapshots) | ||
|
||
fileName := "bollinger_bands_strategy.html" | ||
defer os.Remove(fileName) | ||
|
||
err = report.WriteToFile(fileName) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
} |
Oops, something went wrong.