-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #30 from sdcoffey/sc/adx-ketlner-crsi
ADx, Keltner Chan, CRSI
- Loading branch information
Showing
27 changed files
with
654 additions
and
350 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
ignore: | ||
- testutils.go | ||
- example/**/* | ||
- scripts/**/* |
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,46 @@ | ||
package techan | ||
|
||
import "github.com/sdcoffey/big" | ||
|
||
type resultCache []*big.Decimal | ||
|
||
type cachedIndicator interface { | ||
Indicator | ||
cache() resultCache | ||
setCache(cache resultCache) | ||
windowSize() int | ||
} | ||
|
||
func cacheResult(indicator cachedIndicator, index int, val big.Decimal) { | ||
if index < len(indicator.cache()) { | ||
indicator.cache()[index] = &val | ||
} else if index == len(indicator.cache()) { | ||
indicator.setCache(append(indicator.cache(), &val)) | ||
} else { | ||
expandResultCache(indicator, index+1) | ||
cacheResult(indicator, index, val) | ||
} | ||
} | ||
|
||
func expandResultCache(indicator cachedIndicator, newSize int) { | ||
sizeDiff := newSize - len(indicator.cache()) | ||
|
||
expansion := make([]*big.Decimal, sizeDiff) | ||
indicator.setCache(append(indicator.cache(), expansion...)) | ||
} | ||
|
||
func returnIfCached(indicator cachedIndicator, index int, firstValueFallback func(int) big.Decimal) *big.Decimal { | ||
if index >= len(indicator.cache()) { | ||
expandResultCache(indicator, index+1) | ||
} else if index < indicator.windowSize()-1 { | ||
return &big.ZERO | ||
} else if val := indicator.cache()[index]; val != nil { | ||
return val | ||
} else if index == indicator.windowSize()-1 { | ||
value := firstValueFallback(index) | ||
cacheResult(indicator, index, value) | ||
return &value | ||
} | ||
|
||
return nil | ||
} |
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 |
---|---|---|
@@ -1,72 +1,19 @@ | ||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= | ||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | ||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= | ||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= | ||
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= | ||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | ||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | ||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk= | ||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= | ||
github.com/sdcoffey/big v0.0.0-20180413224939-438f3d83db4c h1:avDKoFuBXMQAcu0sxdpbS88WAiPt2e9YtSuEWfOPj7E= | ||
github.com/sdcoffey/big v0.0.0-20180413224939-438f3d83db4c/go.mod h1:WzOYJJhNOp7m1u1MrNQaYSHmgqHGkZThC+VgDqdFl0I= | ||
github.com/sdcoffey/big v0.4.1 h1:DyK4tHRbbAfdIZV/VbxrEz/ZpcVv5GWNNw+G6AOhfpM= | ||
github.com/sdcoffey/big v0.4.1/go.mod h1:spXh3ZRHdlXkg4SzauLC8ahWmHpxWL5/6drgufL73es= | ||
github.com/sdcoffey/big v0.6.0 h1:0C+nB/91mHQGAxlgvDy/hFO3MMv3dTnCuNA3qfhEYYQ= | ||
github.com/sdcoffey/big v0.6.0/go.mod h1:spXh3ZRHdlXkg4SzauLC8ahWmHpxWL5/6drgufL73es= | ||
github.com/sdcoffey/big v0.7.0 h1:OnE7fcHq/C59WxWrMegftFa1nftCjsZLVf7PLXsxj2Y= | ||
github.com/sdcoffey/big v0.7.0/go.mod h1:2T05Q7Mt6F1kHHb+PFa0odPFwU67YnSAFYgiYy7krPU= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | ||
github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U= | ||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | ||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422 h1:QzoH/1pFpZguR8NrRHLcO6jKqfv2zpuSqZLgdm7ZmjI= | ||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | ||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= | ||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | ||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= | ||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= | ||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e h1:JgcxKXxCjrA2tyDP/aNU9K0Ck5Czfk6C7e2tMw7+bSI= | ||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= | ||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E= | ||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= | ||
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= | ||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd h1:/e+gpKk9r3dJobndpTytxS2gOy6m5uvpg+ISQoEcusQ= | ||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | ||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac h1:MQEvx39qSf8vyrx3XRaOe+j1UDIzKwkYOVObRgGPVqI= | ||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= | ||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7 h1:EBZoQjiKKPaLbPrbpssUfuHtwM6KV/vb4U85g/cigFY= | ||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= | ||
golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef h1:RHORRhs540cYZYrzgU2CPUyykkwZM78hGdzocOo9P8A= | ||
golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= | ||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= | ||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= | ||
honnef.co/go/tools v0.0.0-20190412205916-e87e8279b4cd h1:hnvxEW8n8IJasi4s1HJpanZ1ebTAdsjxzbZPO8Viw+s= | ||
honnef.co/go/tools v0.0.0-20190412205916-e87e8279b4cd/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | ||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= | ||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= | ||
honnef.co/go/tools v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75k= | ||
honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= | ||
honnef.co/go/tools v0.0.1-2020.1.6 h1:W18jzjh8mfPez+AwGLxmOImucz/IFjpNlrKVnaj2YVc= | ||
honnef.co/go/tools v0.0.1-2020.1.6/go.mod h1:pyyisuGw24ruLjrr1ddx39WE0y9OooInRzEYLhQB2YY= | ||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
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,32 @@ | ||
package techan | ||
|
||
import "github.com/sdcoffey/big" | ||
|
||
type averageTrueRangeIndicator struct { | ||
series *TimeSeries | ||
window int | ||
} | ||
|
||
// NewAverageTrueRangeIndicator returns a base indicator that calculates the average true range of the | ||
// underlying over a window | ||
// https://www.investopedia.com/terms/a/atr.asp | ||
func NewAverageTrueRangeIndicator(series *TimeSeries, window int) Indicator { | ||
return averageTrueRangeIndicator{ | ||
series: series, | ||
window: window, | ||
} | ||
} | ||
|
||
func (atr averageTrueRangeIndicator) Calculate(index int) big.Decimal { | ||
if index < atr.window { | ||
return big.ZERO | ||
} | ||
|
||
sum := big.ZERO | ||
|
||
for i := index; i > index-atr.window; i-- { | ||
sum = sum.Add(NewTrueRangeIndicator(atr.series).Calculate(i)) | ||
} | ||
|
||
return sum.Div(big.NewFromInt(atr.window)) | ||
} |
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,24 @@ | ||
package techan | ||
|
||
import "testing" | ||
|
||
func TestAverageTrueRangeIndicator(t *testing.T) { | ||
atrIndicator := NewAverageTrueRangeIndicator(mockedTimeSeries, 3) | ||
|
||
expectedValues := []float64{ | ||
0, | ||
0, | ||
0, | ||
2, | ||
2, | ||
2, | ||
2, | ||
2, | ||
2, | ||
2, | ||
2.3467, | ||
2.3467, | ||
} | ||
|
||
indicatorEquals(t, expectedValues, atrIndicator) | ||
} |
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,45 @@ | ||
package techan | ||
|
||
import "github.com/sdcoffey/big" | ||
|
||
type emaIndicator struct { | ||
indicator Indicator | ||
window int | ||
alpha big.Decimal | ||
resultCache resultCache | ||
} | ||
|
||
// NewEMAIndicator returns a derivative indicator which returns the average of the current and preceding values in | ||
// the given windowSize, with values closer to current index given more weight. A more in-depth explanation can be found here: | ||
// http://www.investopedia.com/terms/e/ema.asp | ||
func NewEMAIndicator(indicator Indicator, window int) Indicator { | ||
return &emaIndicator{ | ||
indicator: indicator, | ||
window: window, | ||
alpha: big.ONE.Frac(2).Div(big.NewFromInt(window + 1)), | ||
resultCache: make([]*big.Decimal, 1000), | ||
} | ||
} | ||
|
||
func (ema *emaIndicator) Calculate(index int) big.Decimal { | ||
if cachedValue := returnIfCached(ema, index, func(i int) big.Decimal { | ||
return NewSimpleMovingAverage(ema.indicator, ema.window).Calculate(i) | ||
}); cachedValue != nil { | ||
return *cachedValue | ||
} | ||
|
||
todayVal := ema.indicator.Calculate(index).Mul(ema.alpha) | ||
result := todayVal.Add(ema.Calculate(index - 1).Mul(ema.alpha)) | ||
|
||
cacheResult(ema, index, result) | ||
|
||
return result | ||
} | ||
|
||
func (ema emaIndicator) cache() resultCache { return ema.resultCache } | ||
|
||
func (ema *emaIndicator) setCache(newCache resultCache) { | ||
ema.resultCache = newCache | ||
} | ||
|
||
func (ema emaIndicator) windowSize() int { return ema.window } |
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,62 @@ | ||
package techan | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestExponentialMovingAverage(t *testing.T) { | ||
t.Run("Default Case", func(t *testing.T) { | ||
expectedValues := []float64{ | ||
0, | ||
0, | ||
64.09, | ||
63.91, | ||
63.73, | ||
63.46, | ||
63.685, | ||
63.7675, | ||
63.3588, | ||
63.3644, | ||
62.3472, | ||
61.9286, | ||
} | ||
|
||
closePriceIndicator := NewClosePriceIndicator(mockedTimeSeries) | ||
indicatorEquals(t, expectedValues, NewEMAIndicator(closePriceIndicator, 3)) | ||
}) | ||
|
||
t.Run("Expands Result Cache", func(t *testing.T) { | ||
closeIndicator := NewClosePriceIndicator(randomTimeSeries(1001)) | ||
ema := NewEMAIndicator(closeIndicator, 20) | ||
|
||
ema.Calculate(1000) | ||
|
||
emaStruct, ok := ema.(cachedIndicator) | ||
assert.True(t, ok) | ||
assert.EqualValues(t, 1001, len(emaStruct.cache())) | ||
}) | ||
} | ||
|
||
func BenchmarkExponetialMovingAverage(b *testing.B) { | ||
size := 10000 | ||
ts := randomTimeSeries(size) | ||
|
||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
ema := NewEMAIndicator(NewClosePriceIndicator(ts), 10) | ||
ema.Calculate(size - 1) | ||
} | ||
} | ||
|
||
func BenchmarkExponentialMovingAverage_Cached(b *testing.B) { | ||
size := 10000 | ||
ts := randomTimeSeries(size) | ||
ema := NewEMAIndicator(NewClosePriceIndicator(ts), 10) | ||
|
||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
ema.Calculate(size - 1) | ||
} | ||
} |
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,40 @@ | ||
package techan | ||
|
||
import ( | ||
"github.com/sdcoffey/big" | ||
) | ||
|
||
type keltnerChannelIndicator struct { | ||
ema Indicator | ||
atr Indicator | ||
mul big.Decimal | ||
window int | ||
} | ||
|
||
func NewKeltnerChannelUpperIndicator(series *TimeSeries, window int) Indicator { | ||
return keltnerChannelIndicator{ | ||
atr: NewAverageTrueRangeIndicator(series, window), | ||
ema: NewEMAIndicator(NewClosePriceIndicator(series), window), | ||
mul: big.ONE, | ||
window: window, | ||
} | ||
} | ||
|
||
func NewKeltnerChannelLowerIndicator(series *TimeSeries, window int) Indicator { | ||
return keltnerChannelIndicator{ | ||
atr: NewAverageTrueRangeIndicator(series, window), | ||
ema: NewEMAIndicator(NewClosePriceIndicator(series), window), | ||
mul: big.ONE.Neg(), | ||
window: window, | ||
} | ||
} | ||
|
||
func (kci keltnerChannelIndicator) Calculate(index int) big.Decimal { | ||
if index <= kci.window-1 { | ||
return big.ZERO | ||
} | ||
|
||
coefficient := big.NewFromInt(2).Mul(kci.mul) | ||
|
||
return kci.ema.Calculate(index).Add(kci.atr.Calculate(index).Mul(coefficient)) | ||
} |
Oops, something went wrong.