Skip to content

Commit

Permalink
chore: some tweaks when getting OHCLData
Browse files Browse the repository at this point in the history
  • Loading branch information
jferrl committed Sep 12, 2023
1 parent bf029bb commit d97ed88
Show file tree
Hide file tree
Showing 5 changed files with 212 additions and 39 deletions.
29 changes: 17 additions & 12 deletions market.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,11 @@ func (o OHCLDataOpts) String() string {
return v.Encode()
}

type ohclData map[string]any

// OHCLData retrieves the last entry in the OHLC array is for the current,
// not-yet-committed frame and will always be present, regardless of the value of since
// not-yet-committed frame and will always be present, regardless of the value of since.
// Docs: https://docs.kraken.com/rest/#tag/Market-Data/operation/getOHLCData
func (m *MarketData) OHCLData(ctx context.Context, opts OHCLDataOpts) (*OHCL, error) {
if opts.Pair == "" {
return nil, errors.New("pair is required")
Expand All @@ -145,25 +148,27 @@ func (m *MarketData) OHCLData(ctx context.Context, opts OHCLDataOpts) (*OHCL, er
return nil, err
}

var v OHCLData
var v ohclData
if err := m.client.do(req, &v); err != nil {
return nil, err
}

var last int64
if v, ok := v["last"].(float64); ok {
last = int64(v)
if l, ok := v["last"].(float64); ok {
last = int64(l)
}

var pair TickData
if v, ok := v[string(opts.Pair)].([]interface{}); ok {
pair = TickData{v}
var ticks Ticks
if p, ok := v[string(opts.Pair)].([]any); ok {
for _, t := range p {
if pv, ok := t.([]any); ok {
ticks = append(ticks, pv)
}
}
}

ohcl := &OHCL{
return &OHCL{
Last: last,
Pair: pair,
}

return ohcl, nil
Pair: ticks,
}, nil
}
27 changes: 23 additions & 4 deletions market_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,27 @@ func TestMarketData_OHCLData(t *testing.T) {
},
want: &OHCL{
Last: 1688672160,
Pair: TickData{
[]any{},
Pair: Ticks{
{
float64(1688671200),
"30306.1",
"30306.2",
"30305.7",
"30305.7",
"30306.1",
"3.39243896",
float64(23),
},
{
float64(1688671260),
"30304.5",
"30304.5",
"30300.0",
"30300.0",
"30300.0",
"4.42996871",
float64(18),
},
},
},
},
Expand All @@ -320,8 +339,8 @@ func TestMarketData_OHCLData(t *testing.T) {
return
}

if !reflect.DeepEqual(got.Last, tt.want.Last) {
t.Errorf("MarketData.OHCLData().Last = %v, want %v", got, tt.want)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("MarketData.OHCLData() = %v, want %v", got, tt.want)
}
})
}
Expand Down
20 changes: 0 additions & 20 deletions testdata/ohcl_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,6 @@
"30300.0",
"4.42996871",
18
],
[
1688671320,
"30300.3",
"30300.4",
"30291.4",
"30291.4",
"30294.7",
"2.13024789",
25
],
[
1688671380,
"30291.8",
"30295.1",
"30291.8",
"30295.0",
"30293.8",
"1.01836275",
9
]
],
"last": 1688672160
Expand Down
122 changes: 119 additions & 3 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,127 @@ type WebsocketsToken struct {
Expires int64 `json:"expires"`
}

type TickData [][]any
// Tick represents a tick.
type Tick []any

type OHCLData map[string]any
// TickValues represents the values of a tick.
type TickValues struct {
Open string
High string
Low string
Close string
Vwap string
Volume string
Count int64
Time int64
}

// Valid returns true if the tick is valid.
func (t Tick) Valid() bool {
return len(t) == 8
}

// Time returns the time of the tick.
func (t Tick) Time() int64 {
v := t[0]
switch value := v.(type) {
case float64:
return int64(value)
case int64:
return value
case int:
return int64(value)
default:
return 0
}
}

// Open returns the open price of the tick.
func (t Tick) Open() string {
if v, ok := t[1].(string); ok {
return v
}
return ""
}

// High returns the high price of the tick.
func (t Tick) High() string {
if v, ok := t[2].(string); ok {
return v
}
return ""
}

// Low returns the low price of the tick.
func (t Tick) Low() string {
if v, ok := t[3].(string); ok {
return v
}
return ""
}

// Close returns the close price of the tick.
func (t Tick) Close() string {
if v, ok := t[4].(string); ok {
return v
}
return ""
}

// Vwap returns the vwap of the tick.
func (t Tick) Vwap() string {
if v, ok := t[5].(string); ok {
return v
}
return ""
}

// Volume returns the volume of the tick.
func (t Tick) Volume() string {
if v, ok := t[6].(string); ok {
return v
}
return ""
}

// Count returns the count of the tick.
func (t Tick) Count() int64 {
v := t[7]
switch value := v.(type) {
case float64:
return int64(value)
case int64:
return value
case int:
return int64(value)
default:
return 0
}
}

// Values returns the values of the tick.
func (t Tick) Values() TickValues {
if !t.Valid() {
return TickValues{}
}

return TickValues{
Open: t.Open(),
High: t.High(),
Low: t.Low(),
Close: t.Close(),
Vwap: t.Vwap(),
Volume: t.Volume(),
Count: t.Count(),
Time: t.Time(),
}
}

// Ticks is a slice of Tick.
type Ticks []Tick

// OHCL represents the OHCL data.
type OHCL struct {
Last int64
Pair TickData
Pair Ticks
}
53 changes: 53 additions & 0 deletions types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package kraken

import (
"reflect"
"testing"
)

func TestTick_Values(t *testing.T) {
tests := []struct {
name string
tr Tick
wantTick TickValues
}{
{
name: "invalid tick",
tr: Tick{},
},
{
name: "tick with invalid values",
tr: Tick{"0", 1, 2, 3, 4, 5, 6, "7"},
},
{
name: "tick with valid values",
tr: Tick{
1688671200,
"30306.1",
"30306.2",
"30305.7",
"30305.7",
"30306.1",
"3.39243896",
23,
},
wantTick: TickValues{
Time: 1688671200,
Open: "30306.1",
High: "30306.2",
Low: "30305.7",
Close: "30305.7",
Vwap: "30306.1",
Volume: "3.39243896",
Count: 23,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.tr.Values(); !reflect.DeepEqual(got, tt.wantTick) {
t.Errorf("tick = %v, want %v", got, tt.wantTick)
}
})
}
}

0 comments on commit d97ed88

Please sign in to comment.