193 lines
3.7 KiB
Go
193 lines
3.7 KiB
Go
|
package types
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"sort"
|
||
|
"strings"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type Interval string
|
||
|
|
||
|
func (i Interval) Minutes() int {
|
||
|
m, ok := SupportedIntervals[i]
|
||
|
if !ok {
|
||
|
return ParseInterval(i) / 60
|
||
|
}
|
||
|
return m / 60
|
||
|
}
|
||
|
|
||
|
func (i Interval) Seconds() int {
|
||
|
m, ok := SupportedIntervals[i]
|
||
|
if !ok {
|
||
|
return ParseInterval(i)
|
||
|
}
|
||
|
return m
|
||
|
}
|
||
|
|
||
|
// Milliseconds is specially handled, for better precision
|
||
|
// for ms level interval, calling Seconds and Minutes directly might trigger panic error
|
||
|
func (i Interval) Milliseconds() int {
|
||
|
t := 0
|
||
|
index := 0
|
||
|
for i, rn := range string(i) {
|
||
|
if rn >= '0' && rn <= '9' {
|
||
|
t = t*10 + int(rn-'0')
|
||
|
} else {
|
||
|
index = i
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
switch strings.ToLower(string(i[index:])) {
|
||
|
case "ms":
|
||
|
return t
|
||
|
case "s":
|
||
|
return t * 1000
|
||
|
case "m":
|
||
|
t *= 60
|
||
|
case "h":
|
||
|
t *= 60 * 60
|
||
|
case "d":
|
||
|
t *= 60 * 60 * 24
|
||
|
case "w":
|
||
|
t *= 60 * 60 * 24 * 7
|
||
|
case "mo":
|
||
|
t *= 60 * 60 * 24 * 30
|
||
|
default:
|
||
|
panic("unknown interval input: " + i)
|
||
|
}
|
||
|
return t * 1000
|
||
|
}
|
||
|
|
||
|
func (i Interval) Duration() time.Duration {
|
||
|
return time.Duration(i.Milliseconds()) * time.Millisecond
|
||
|
}
|
||
|
|
||
|
func (i *Interval) UnmarshalJSON(b []byte) (err error) {
|
||
|
var a string
|
||
|
err = json.Unmarshal(b, &a)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
*i = Interval(a)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (i Interval) String() string {
|
||
|
return string(i)
|
||
|
}
|
||
|
|
||
|
type IntervalSlice []Interval
|
||
|
|
||
|
func (s IntervalSlice) Sort() {
|
||
|
sort.Slice(s, func(i, j int) bool {
|
||
|
return s[i].Duration() < s[j].Duration()
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func (s IntervalSlice) StringSlice() (slice []string) {
|
||
|
for _, interval := range s {
|
||
|
slice = append(slice, `"`+interval.String()+`"`)
|
||
|
}
|
||
|
return slice
|
||
|
}
|
||
|
|
||
|
var Interval1s = Interval("1s")
|
||
|
var Interval1m = Interval("1m")
|
||
|
var Interval3m = Interval("3m")
|
||
|
var Interval5m = Interval("5m")
|
||
|
var Interval15m = Interval("15m")
|
||
|
var Interval30m = Interval("30m")
|
||
|
var Interval1h = Interval("1h")
|
||
|
var Interval2h = Interval("2h")
|
||
|
var Interval4h = Interval("4h")
|
||
|
var Interval6h = Interval("6h")
|
||
|
var Interval12h = Interval("12h")
|
||
|
var Interval1d = Interval("1d")
|
||
|
var Interval3d = Interval("3d")
|
||
|
var Interval1w = Interval("1w")
|
||
|
var Interval2w = Interval("2w")
|
||
|
var Interval1mo = Interval("1mo")
|
||
|
|
||
|
func ParseInterval(input Interval) int {
|
||
|
t := 0
|
||
|
index := 0
|
||
|
for i, rn := range string(input) {
|
||
|
if rn >= '0' && rn <= '9' {
|
||
|
t = t*10 + int(rn-'0')
|
||
|
} else {
|
||
|
index = i
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
switch strings.ToLower(string(input[index:])) {
|
||
|
case "s":
|
||
|
return t
|
||
|
case "m":
|
||
|
t *= 60
|
||
|
case "h":
|
||
|
t *= 60 * 60
|
||
|
case "d":
|
||
|
t *= 60 * 60 * 24
|
||
|
case "w":
|
||
|
t *= 60 * 60 * 24 * 7
|
||
|
case "mo":
|
||
|
t *= 60 * 60 * 24 * 30
|
||
|
default:
|
||
|
panic("unknown interval input: " + input)
|
||
|
}
|
||
|
return t
|
||
|
}
|
||
|
|
||
|
type IntervalMap map[Interval]int
|
||
|
|
||
|
func (m IntervalMap) Slice() (slice IntervalSlice) {
|
||
|
for interval := range m {
|
||
|
slice = append(slice, interval)
|
||
|
}
|
||
|
|
||
|
return slice
|
||
|
}
|
||
|
|
||
|
var SupportedIntervals = IntervalMap{
|
||
|
Interval1s: 1,
|
||
|
Interval1m: 1 * 60,
|
||
|
Interval3m: 3 * 60,
|
||
|
Interval5m: 5 * 60,
|
||
|
Interval15m: 15 * 60,
|
||
|
Interval30m: 30 * 60,
|
||
|
Interval1h: 60 * 60,
|
||
|
Interval2h: 60 * 60 * 2,
|
||
|
Interval4h: 60 * 60 * 4,
|
||
|
Interval6h: 60 * 60 * 6,
|
||
|
Interval12h: 60 * 60 * 12,
|
||
|
Interval1d: 60 * 60 * 24,
|
||
|
Interval3d: 60 * 60 * 24 * 3,
|
||
|
Interval1w: 60 * 60 * 24 * 7,
|
||
|
Interval2w: 60 * 60 * 24 * 14,
|
||
|
Interval1mo: 60 * 60 * 24 * 30,
|
||
|
}
|
||
|
|
||
|
// IntervalWindow is used by the indicators
|
||
|
type IntervalWindow struct {
|
||
|
// The interval of kline
|
||
|
Interval Interval `json:"interval"`
|
||
|
|
||
|
// The windows size of the indicator (for example, EWMA and SMA)
|
||
|
Window int `json:"window"`
|
||
|
|
||
|
// RightWindow is used by the pivot indicator
|
||
|
RightWindow *int `json:"rightWindow"`
|
||
|
}
|
||
|
|
||
|
type IntervalWindowBandWidth struct {
|
||
|
IntervalWindow
|
||
|
BandWidth float64 `json:"bandWidth"`
|
||
|
}
|
||
|
|
||
|
func (iw IntervalWindow) String() string {
|
||
|
return fmt.Sprintf("%s (%d)", iw.Interval, iw.Window)
|
||
|
}
|