-
Notifications
You must be signed in to change notification settings - Fork 0
/
atr.go
101 lines (95 loc) · 1.98 KB
/
atr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package shingo
import (
"fmt"
"math"
)
// AppendATR appends Average True Range to candlesticks
func (cs *Candlesticks) AppendATR(arg IndicatorInputArg) error {
limit := arg.Limit
period := arg.Period
len := cs.Total()
if len < 1 {
return nil
}
if limit < 1 {
limit = len
}
if period < 1 {
return fmt.Errorf("period must be larger than 0")
}
var count int = 1
startIdx := (len - 1) - limit - period
if startIdx < 0 {
startIdx = 0
}
var firstTRTotal float64
for i := startIdx; i < len; i++ {
p := cs.ItemAtIndex(i - 1)
v := cs.ItemAtIndex(i)
var tr float64
if p != nil {
tr = findHighestValue(v.High-v.Low, math.Abs(v.High-p.Close), math.Abs(v.Low-p.Close))
prev := p.GetATR(period)
if count < period {
firstTRTotal += tr
} else if count == period {
v.setATR(period, (firstTRTotal+tr)/float64(period), 0)
} else {
tr = (prev.Value*float64(period-1) + tr) / float64(period)
var chg float64
if prev.Value > 0.0 {
chg = tr/prev.Value - 1
} else {
chg = 0
}
v.setATR(period, tr, chg)
}
} else {
firstTRTotal = v.High - v.Low
}
count++
}
return nil
}
func findHighestValue(vals ...float64) float64 {
if len(vals) < 1 {
return 0
}
f := vals[0]
for _, v := range vals {
if v > f {
f = v
}
}
return f
}
func findLowestValue(vals ...float64) float64 {
if len(vals) < 1 {
return 0
}
f := vals[0]
for _, v := range vals {
if v < f {
f = v
}
}
return f
}
// GetSMA returns SMA value for this candlestick for given period
func (c *Candlestick) GetATR(period int) *ATRDelta {
if c.Indicators == nil || c.Indicators.ATRs == nil {
return nil
}
return c.Indicators.ATRs[period]
}
func (c *Candlestick) setATR(period int, val float64, chg float64) {
if c.Indicators == nil {
c.Indicators = &Indicators{}
}
if c.Indicators.ATRs == nil {
c.Indicators.ATRs = make(map[int]*ATRDelta)
}
if c.Indicators.ATRs[period] == nil {
c.Indicators.ATRs[period] = &ATRDelta{Value: val, Change: chg}
}
}