From 0fabde412a2c663b271f19184b8e73292a807d14 Mon Sep 17 00:00:00 2001 From: Gergely Novak Date: Thu, 25 Apr 2024 14:58:30 +0200 Subject: [PATCH] Update option snapshots with filters, greeks and pagination --- examples/marketdata/marketdata.go | 75 ++++--- marketdata/entities.go | 24 ++- marketdata/entities_easyjson.go | 333 +++++++++++++++++++++--------- marketdata/options.go | 133 ++++++++++-- marketdata/options_test.go | 62 +++++- 5 files changed, 473 insertions(+), 154 deletions(-) diff --git a/examples/marketdata/marketdata.go b/examples/marketdata/marketdata.go index 3ff9c0e..af5d107 100644 --- a/examples/marketdata/marketdata.go +++ b/examples/marketdata/marketdata.go @@ -125,7 +125,10 @@ func cryptoQuote() { } func optionChain() { - chain, err := marketdata.GetOptionChain("AAPL", marketdata.GetOptionSnapshotRequest{}) + chain, err := marketdata.GetOptionChain("AAPL", marketdata.GetOptionChainRequest{ + Type: marketdata.Call, + ExpirationDateLte: civil.DateOf(time.Now()).AddDays(5), + }) if err != nil { panic(err) } @@ -133,42 +136,48 @@ func optionChain() { marketdata.OptionSnapshot Symbol string } - calls, puts := []snap{}, []snap{} + snaps := []snap{} for symbol, snapshot := range chain { - if strings.Contains(symbol, "C") { - calls = append(calls, snap{OptionSnapshot: snapshot, Symbol: symbol}) - } else { - puts = append(puts, snap{OptionSnapshot: snapshot, Symbol: symbol}) - } + snaps = append(snaps, snap{OptionSnapshot: snapshot, Symbol: symbol}) } - sort.Slice(calls, func(i, j int) bool { return calls[i].Symbol < calls[j].Symbol }) - sort.Slice(puts, func(i, j int) bool { return puts[i].Symbol < puts[j].Symbol }) - printSnaps := func(snaps []snap) { - tw := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) - fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%s\n", "Contract name", "Last trade time", "Price", "Bid", "Ask") - for _, s := range snaps { - ts := "" - if s.LatestTrade != nil { - ts = s.LatestTrade.Timestamp.Format(time.RFC3339) - } - price := float64(0) - if s.LatestTrade != nil { - price = s.LatestTrade.Price - } - bid, ask := float64(0), float64(0) - if s.LatestQuote != nil { - bid = s.LatestQuote.BidPrice - ask = s.LatestQuote.AskPrice - } - fmt.Fprintf(tw, "%s\t%s\t%g\t%g\t%g\n", s.Symbol, ts, price, bid, ask) + sort.Slice(snaps, func(i, j int) bool { return snaps[i].Symbol < snaps[j].Symbol }) + + tw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + columns := []any{ + "Contract name", "Last trade time", "Price", "Bid", "Ask", + "IV", "Delta", "Gamma", "Rho", "Theta", "Vega", + } + fmt.Fprintf(tw, strings.Repeat("%s\t", len(columns))+"\n", columns...) + for _, s := range snaps { + ts := "" + if s.LatestTrade != nil { + ts = s.LatestTrade.Timestamp.Format(time.RFC3339) + } + price := float64(0) + if s.LatestTrade != nil { + price = s.LatestTrade.Price } - tw.Flush() + bid, ask := float64(0), float64(0) + if s.LatestQuote != nil { + bid = s.LatestQuote.BidPrice + ask = s.LatestQuote.AskPrice + } + iv := "" + if s.ImpliedVolatility != 0 { + iv = strconv.FormatFloat(s.ImpliedVolatility, 'f', 4, 64) + } + var delta, gamma, rho, theta, vega string + if s.Greeks != nil { + delta = strconv.FormatFloat(s.Greeks.Delta, 'f', 4, 64) + gamma = strconv.FormatFloat(s.Greeks.Gamma, 'f', 4, 64) + rho = strconv.FormatFloat(s.Greeks.Rho, 'f', 4, 64) + theta = strconv.FormatFloat(s.Greeks.Theta, 'f', 4, 64) + vega = strconv.FormatFloat(s.Greeks.Vega, 'f', 4, 64) + } + fmt.Fprintf(tw, "%s\t%s\t%g\t%g\t%g\t%s\t%s\t%s\t%s\t%s\t%s\n", + s.Symbol, ts, price, bid, ask, iv, delta, gamma, rho, theta, vega) } - fmt.Println("CALLS") - printSnaps(calls) - fmt.Println() - fmt.Println("PUTS") - printSnaps(puts) + tw.Flush() } func corporateActions() { diff --git a/marketdata/entities.go b/marketdata/entities.go index f411729..763816e 100644 --- a/marketdata/entities.go +++ b/marketdata/entities.go @@ -41,6 +41,13 @@ const ( Indicative Feed = "indicative" ) +type OptionType = string + +const ( + Call OptionType = "call" + Put OptionType = "put" +) + // TakerSide is the taker's side: one of B, S or -. B is buy, S is sell and - is unknown. type TakerSide = string @@ -391,9 +398,19 @@ type OptionQuote struct { Condition string `json:"c"` } +type OptionGreeks struct { + Delta float64 `json:"delta"` + Gamma float64 `json:"gamma"` + Rho float64 `json:"rho"` + Theta float64 `json:"theta"` + Vega float64 `json:"vega"` +} + type OptionSnapshot struct { - LatestTrade *OptionTrade `json:"latestTrade"` - LatestQuote *OptionQuote `json:"latestQuote"` + LatestTrade *OptionTrade `json:"latestTrade"` + LatestQuote *OptionQuote `json:"latestQuote"` + ImpliedVolatility float64 `json:"impliedVolatility,omitempty` + Greeks *OptionGreeks `json:"greeks,omitempty` } type multiTradeResponse struct { NextPageToken *string `json:"next_page_token"` @@ -483,5 +500,6 @@ type latestOptionQuotesResponse struct { } type optionSnapshotsResponse struct { - Snapshots map[string]OptionSnapshot `json:"snapshots"` + NextPageToken *string `json:"next_page_token"` + Snapshots map[string]OptionSnapshot `json:"snapshots"` } diff --git a/marketdata/entities_easyjson.go b/marketdata/entities_easyjson.go index 74385d7..8a5e4d2 100644 --- a/marketdata/entities_easyjson.go +++ b/marketdata/entities_easyjson.go @@ -113,6 +113,16 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata1(in *jl continue } switch key { + case "next_page_token": + if in.IsNull() { + in.Skip() + out.NextPageToken = nil + } else { + if out.NextPageToken == nil { + out.NextPageToken = new(string) + } + *out.NextPageToken = string(in.String()) + } case "snapshots": if in.IsNull() { in.Skip() @@ -144,8 +154,17 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata1(out *j first := true _ = first { - const prefix string = ",\"snapshots\":" + const prefix string = ",\"next_page_token\":" out.RawString(prefix[1:]) + if in.NextPageToken == nil { + out.RawString("null") + } else { + out.String(string(*in.NextPageToken)) + } + } + { + const prefix string = ",\"snapshots\":" + out.RawString(prefix) if in.Snapshots == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 { out.RawString(`null`) } else { @@ -4124,6 +4143,18 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata34(in *j } (*out.LatestQuote).UnmarshalEasyJSON(in) } + case "impliedVolatility": + out.ImpliedVolatility = float64(in.Float64()) + case "greeks": + if in.IsNull() { + in.Skip() + out.Greeks = nil + } else { + if out.Greeks == nil { + out.Greeks = new(OptionGreeks) + } + (*out.Greeks).UnmarshalEasyJSON(in) + } default: in.SkipRecursive() } @@ -4156,6 +4187,20 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata34(out * (*in.LatestQuote).MarshalEasyJSON(out) } } + { + const prefix string = ",\"impliedVolatility\":" + out.RawString(prefix) + out.Float64(float64(in.ImpliedVolatility)) + } + { + const prefix string = ",\"greeks\":" + out.RawString(prefix) + if in.Greeks == nil { + out.RawString("null") + } else { + (*in.Greeks).MarshalEasyJSON(out) + } + } out.RawByte('}') } @@ -4299,7 +4344,101 @@ func (v *OptionQuote) UnmarshalJSON(data []byte) error { func (v *OptionQuote) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata35(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(in *jlexer.Lexer, out *OptionBar) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(in *jlexer.Lexer, out *OptionGreeks) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "delta": + out.Delta = float64(in.Float64()) + case "gamma": + out.Gamma = float64(in.Float64()) + case "rho": + out.Rho = float64(in.Float64()) + case "theta": + out.Theta = float64(in.Float64()) + case "vega": + out.Vega = float64(in.Float64()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(out *jwriter.Writer, in OptionGreeks) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"delta\":" + out.RawString(prefix[1:]) + out.Float64(float64(in.Delta)) + } + { + const prefix string = ",\"gamma\":" + out.RawString(prefix) + out.Float64(float64(in.Gamma)) + } + { + const prefix string = ",\"rho\":" + out.RawString(prefix) + out.Float64(float64(in.Rho)) + } + { + const prefix string = ",\"theta\":" + out.RawString(prefix) + out.Float64(float64(in.Theta)) + } + { + const prefix string = ",\"vega\":" + out.RawString(prefix) + out.Float64(float64(in.Vega)) + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v OptionGreeks) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v OptionGreeks) MarshalEasyJSON(w *jwriter.Writer) { + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *OptionGreeks) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *OptionGreeks) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(l, v) +} +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(in *jlexer.Lexer, out *OptionBar) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -4346,7 +4485,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(out *jwriter.Writer, in OptionBar) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(out *jwriter.Writer, in OptionBar) { out.RawByte('{') first := true _ = first @@ -4396,27 +4535,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(out * // MarshalJSON supports json.Marshaler interface func (v OptionBar) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v OptionBar) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *OptionBar) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *OptionBar) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata36(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(in *jlexer.Lexer, out *NewsImage) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(in *jlexer.Lexer, out *NewsImage) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -4449,7 +4588,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(out *jwriter.Writer, in NewsImage) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(out *jwriter.Writer, in NewsImage) { out.RawByte('{') first := true _ = first @@ -4469,27 +4608,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(out * // MarshalJSON supports json.Marshaler interface func (v NewsImage) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v NewsImage) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *NewsImage) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *NewsImage) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata37(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(in *jlexer.Lexer, out *News) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(in *jlexer.Lexer, out *News) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -4584,7 +4723,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(out *jwriter.Writer, in News) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(out *jwriter.Writer, in News) { out.RawByte('{') first := true _ = first @@ -4666,27 +4805,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(out * // MarshalJSON supports json.Marshaler interface func (v News) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v News) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *News) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *News) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata38(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(in *jlexer.Lexer, out *NameChange) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(in *jlexer.Lexer, out *NameChange) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -4723,7 +4862,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(out *jwriter.Writer, in NameChange) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(out *jwriter.Writer, in NameChange) { out.RawByte('{') first := true _ = first @@ -4748,27 +4887,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(out * // MarshalJSON supports json.Marshaler interface func (v NameChange) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v NameChange) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *NameChange) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *NameChange) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata39(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(in *jlexer.Lexer, out *ForwardSplit) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(in *jlexer.Lexer, out *ForwardSplit) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -4847,7 +4986,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(out *jwriter.Writer, in ForwardSplit) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(out *jwriter.Writer, in ForwardSplit) { out.RawByte('{') first := true _ = first @@ -4897,27 +5036,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(out * // MarshalJSON supports json.Marshaler interface func (v ForwardSplit) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v ForwardSplit) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *ForwardSplit) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *ForwardSplit) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata40(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(in *jlexer.Lexer, out *DailyAuctions) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(in *jlexer.Lexer, out *DailyAuctions) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -4996,7 +5135,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(out *jwriter.Writer, in DailyAuctions) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(out *jwriter.Writer, in DailyAuctions) { out.RawByte('{') first := true _ = first @@ -5043,27 +5182,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(out * // MarshalJSON supports json.Marshaler interface func (v DailyAuctions) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v DailyAuctions) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *DailyAuctions) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *DailyAuctions) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata41(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(in *jlexer.Lexer, out *CryptoTrade) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(in *jlexer.Lexer, out *CryptoTrade) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -5104,7 +5243,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(out *jwriter.Writer, in CryptoTrade) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(out *jwriter.Writer, in CryptoTrade) { out.RawByte('{') first := true _ = first @@ -5139,27 +5278,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(out * // MarshalJSON supports json.Marshaler interface func (v CryptoTrade) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v CryptoTrade) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *CryptoTrade) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *CryptoTrade) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata42(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(in *jlexer.Lexer, out *CryptoSnapshots) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(in *jlexer.Lexer, out *CryptoSnapshots) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -5204,7 +5343,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(out *jwriter.Writer, in CryptoSnapshots) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(out *jwriter.Writer, in CryptoSnapshots) { out.RawByte('{') first := true _ = first @@ -5235,27 +5374,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(out * // MarshalJSON supports json.Marshaler interface func (v CryptoSnapshots) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v CryptoSnapshots) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *CryptoSnapshots) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *CryptoSnapshots) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata43(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(in *jlexer.Lexer, out *CryptoSnapshot) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(in *jlexer.Lexer, out *CryptoSnapshot) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -5334,7 +5473,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(out *jwriter.Writer, in CryptoSnapshot) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(out *jwriter.Writer, in CryptoSnapshot) { out.RawByte('{') first := true _ = first @@ -5389,27 +5528,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(out * // MarshalJSON supports json.Marshaler interface func (v CryptoSnapshot) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v CryptoSnapshot) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *CryptoSnapshot) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *CryptoSnapshot) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata44(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(in *jlexer.Lexer, out *CryptoQuote) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(in *jlexer.Lexer, out *CryptoQuote) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -5450,7 +5589,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(out *jwriter.Writer, in CryptoQuote) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(out *jwriter.Writer, in CryptoQuote) { out.RawByte('{') first := true _ = first @@ -5485,27 +5624,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(out * // MarshalJSON supports json.Marshaler interface func (v CryptoQuote) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v CryptoQuote) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *CryptoQuote) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *CryptoQuote) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata45(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(in *jlexer.Lexer, out *CryptoBar) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(in *jlexer.Lexer, out *CryptoBar) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -5552,7 +5691,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(out *jwriter.Writer, in CryptoBar) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(out *jwriter.Writer, in CryptoBar) { out.RawByte('{') first := true _ = first @@ -5602,27 +5741,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(out * // MarshalJSON supports json.Marshaler interface func (v CryptoBar) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v CryptoBar) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *CryptoBar) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *CryptoBar) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata46(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(in *jlexer.Lexer, out *CorporateActions) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(in *jlexer.Lexer, out *CorporateActions) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -5927,7 +6066,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(out *jwriter.Writer, in CorporateActions) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(out *jwriter.Writer, in CorporateActions) { out.RawByte('{') first := true _ = first @@ -6161,27 +6300,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(out * // MarshalJSON supports json.Marshaler interface func (v CorporateActions) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v CorporateActions) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *CorporateActions) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *CorporateActions) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata47(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(in *jlexer.Lexer, out *CashMerger) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(in *jlexer.Lexer, out *CashMerger) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -6244,7 +6383,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(out *jwriter.Writer, in CashMerger) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(out *jwriter.Writer, in CashMerger) { out.RawByte('{') first := true _ = first @@ -6290,27 +6429,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(out * // MarshalJSON supports json.Marshaler interface func (v CashMerger) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v CashMerger) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *CashMerger) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *CashMerger) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata48(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(in *jlexer.Lexer, out *CashDividend) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(in *jlexer.Lexer, out *CashDividend) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -6403,7 +6542,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(out *jwriter.Writer, in CashDividend) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(out *jwriter.Writer, in CashDividend) { out.RawByte('{') first := true _ = first @@ -6463,27 +6602,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(out * // MarshalJSON supports json.Marshaler interface func (v CashDividend) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v CashDividend) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *CashDividend) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *CashDividend) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata49(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(in *jlexer.Lexer, out *Bar) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(in *jlexer.Lexer, out *Bar) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -6530,7 +6669,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(out *jwriter.Writer, in Bar) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(out *jwriter.Writer, in Bar) { out.RawByte('{') first := true _ = first @@ -6580,27 +6719,27 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(out * // MarshalJSON supports json.Marshaler interface func (v Bar) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v Bar) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *Bar) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *Bar) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata50(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(l, v) } -func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(in *jlexer.Lexer, out *Auction) { +func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata52(in *jlexer.Lexer, out *Auction) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -6641,7 +6780,7 @@ func easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(in *j in.Consumed() } } -func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(out *jwriter.Writer, in Auction) { +func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata52(out *jwriter.Writer, in Auction) { out.RawByte('{') first := true _ = first @@ -6676,23 +6815,23 @@ func easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(out * // MarshalJSON supports json.Marshaler interface func (v Auction) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(&w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata52(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v Auction) MarshalEasyJSON(w *jwriter.Writer) { - easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(w, v) + easyjson3e8ab7adEncodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata52(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *Auction) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(&r, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata52(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *Auction) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata51(l, v) + easyjson3e8ab7adDecodeGithubComAlpacahqAlpacaTradeApiGoV3Marketdata52(l, v) } diff --git a/marketdata/options.go b/marketdata/options.go index 795e8bf..0d7bbfc 100644 --- a/marketdata/options.go +++ b/marketdata/options.go @@ -3,7 +3,10 @@ package marketdata import ( "fmt" "net/url" + "strconv" "time" + + "cloud.google.com/go/civil" ) const optionPrefix = "v1beta1/options" @@ -231,7 +234,13 @@ func (c *Client) GetLatestOptionQuotes(symbols []string, req GetLatestOptionQuot } type GetOptionSnapshotRequest struct { + // Feed is the source of the data: opra or indicative. Feed OptionFeed + // TotalLimit is the limit of the total number of the returned snapshots. + // If missing, all snapshots will be returned. + TotalLimit int + // PageLimit is the pagination size. If empty, the default page size will be used. + PageLimit int } // GetOptionSnapshot returns the snapshot for a given symbol @@ -258,36 +267,122 @@ func (c *Client) GetOptionSnapshots(symbols []string, req GetOptionSnapshotReque Feed: req.Feed, }) - resp, err := c.get(u) - if err != nil { - return nil, err - } + q := u.Query() + c.setBaseQuery(q, baseRequest{ + Symbols: symbols, + Feed: req.Feed, + }) - var snapshots optionSnapshotsResponse - if err = unmarshal(resp, &snapshots); err != nil { - return nil, err + snapshots := make(map[string]OptionSnapshot, len(symbols)) + received := 0 + for req.TotalLimit == 0 || received < req.TotalLimit { + setQueryLimit(q, req.TotalLimit, req.PageLimit, received, v2MaxLimit) + u.RawQuery = q.Encode() + + resp, err := c.get(u) + if err != nil { + return nil, err + } + + var snapshotsResp optionSnapshotsResponse + if err := unmarshal(resp, &snapshotsResp); err != nil { + return nil, err + } + + for symbol, s := range snapshotsResp.Snapshots { + snapshots[symbol] = s + received++ + } + if snapshotsResp.NextPageToken == nil { + break + } + q.Set("page_token", *snapshotsResp.NextPageToken) } - return snapshots.Snapshots, nil + return snapshots, nil +} + +type GetOptionChainRequest struct { + // Feed is the source of the data: opra or indicative. + Feed OptionFeed + // TotalLimit is the limit of the total number of the returned snapshots. + // If missing, all snapshots will be returned. + TotalLimit int + // PageLimit is the pagination size. If empty, the default page size will be used. + PageLimit int + // Type filters contracts by the type (call or put). + Type OptionType + // StrikePriceGte filters contracts with strike price greater than or equal to the specified value. + StrikePriceGte float64 + // StrikePriceLte filters contracts with strike price less than or equal to the specified value. + StrikePriceLte float64 + // ExpirationDate filters contracts by the exact expiration date + ExpirationDate civil.Date + // ExpirationDateGte filters contracts with expiration date greater than or equal to the specified date. + ExpirationDateGte civil.Date + // ExpirationDateLte filters contracts with expiration date less than or equal to the specified date. + ExpirationDateLte civil.Date + // RootSymbol filters contracts by the root symbol (e.g. AAPL1) + RootSymbol string } // GetOptionChain returns the snapshot chain for an underlying symbol (e.g. AAPL) -func (c *Client) GetOptionChain(underlyingSymbol string, req GetOptionSnapshotRequest) (map[string]OptionSnapshot, error) { +func (c *Client) GetOptionChain(underlyingSymbol string, req GetOptionChainRequest) (map[string]OptionSnapshot, error) { u, err := url.Parse(fmt.Sprintf("%s/%s/snapshots/%s", c.opts.BaseURL, optionPrefix, underlyingSymbol)) if err != nil { return nil, err } - c.setLatestQueryRequest(u, baseLatestRequest{Feed: req.Feed}) - - resp, err := c.get(u) - if err != nil { - return nil, err + q := u.Query() + c.setBaseQuery(q, baseRequest{ + Feed: req.Feed, + }) + if req.Type != "" { + q.Set("type", req.Type) + } + if req.StrikePriceGte != 0 { + q.Set("strike_price_gte", strconv.FormatFloat(req.StrikePriceGte, 'f', -1, 64)) + } + if req.StrikePriceLte != 0 { + q.Set("strike_price_lte", strconv.FormatFloat(req.StrikePriceLte, 'f', -1, 64)) + } + if !req.ExpirationDate.IsZero() { + q.Set("expiration_date", req.ExpirationDate.String()) + } + if !req.ExpirationDateLte.IsZero() { + q.Set("expiration_date_lte", req.ExpirationDateLte.String()) + } + if !req.ExpirationDateGte.IsZero() { + q.Set("expiration_date_gte", req.ExpirationDateGte.String()) + } + if req.RootSymbol != "" { + q.Set("root_symbol", req.RootSymbol) } - var snapshots optionSnapshotsResponse - if err = unmarshal(resp, &snapshots); err != nil { - return nil, err + snapshots := make(map[string]OptionSnapshot) + received := 0 + for req.TotalLimit == 0 || received < req.TotalLimit { + setQueryLimit(q, req.TotalLimit, req.PageLimit, received, v2MaxLimit) + u.RawQuery = q.Encode() + + resp, err := c.get(u) + if err != nil { + return nil, err + } + + var snapshotsResp optionSnapshotsResponse + if err := unmarshal(resp, &snapshotsResp); err != nil { + return nil, err + } + + for symbol, s := range snapshotsResp.Snapshots { + snapshots[symbol] = s + received++ + } + if snapshotsResp.NextPageToken == nil { + break + } + q.Set("page_token", *snapshotsResp.NextPageToken) } - return snapshots.Snapshots, nil + return snapshots, nil } // GetOptionTrades returns the option trades for the given symbol. @@ -341,6 +436,6 @@ func GetOptionSnapshots(symbols []string, req GetOptionSnapshotRequest) (map[str } // GetOptionChain returns the snapshot chain for an underlying symbol (e.g. AAPL) -func GetOptionChain(underlyingSymbol string, req GetOptionSnapshotRequest) (map[string]OptionSnapshot, error) { +func GetOptionChain(underlyingSymbol string, req GetOptionChainRequest) (map[string]OptionSnapshot, error) { return DefaultClient.GetOptionChain(underlyingSymbol, req) } diff --git a/marketdata/options_test.go b/marketdata/options_test.go index f4ef4ca..a42af0f 100644 --- a/marketdata/options_test.go +++ b/marketdata/options_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "cloud.google.com/go/civil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -146,12 +147,69 @@ func TestGetOptionChain(t *testing.T) { DefaultClient = NewClient(ClientOpts{}) }() DefaultClient.do = mockResp(`{"snapshots":{"NIO240719P00002000":{"latestQuote":{"ap":1.24,"as":2183,"ax":"A","bp":0.03,"bs":1143,"bx":"A","c":"A","t":"2024-03-06T20:59:05.378523136Z"}},"NIO240405P00004000":{"latestQuote":{"ap":0.05,"as":3041,"ax":"D","bp":0.03,"bs":1726,"bx":"D","c":"C","t":"2024-03-06T20:59:59.678798848Z"},"latestTrade":{"c":"f","p":0.05,"s":17,"t":"2024-03-07T15:53:37.134486784Z","x":"I"}}}}`) //nolint:lll - got, err := GetOptionChain("NIO", GetOptionSnapshotRequest{}) + got, err := GetOptionChain("NIO", GetOptionChainRequest{}) require.NoError(t, err) require.NotNil(t, got) - assert.Len(t, got, 2) + require.Len(t, got, 2) + require.Contains(t, got, "NIO240719P00002000") + require.Contains(t, got, "NIO240405P00004000") assert.Nil(t, got["NIO240719P00002000"].LatestTrade) assert.Equal(t, 1.24, got["NIO240719P00002000"].LatestQuote.AskPrice) assert.EqualValues(t, 1726, got["NIO240405P00004000"].LatestQuote.BidSize) assert.EqualValues(t, 17, got["NIO240405P00004000"].LatestTrade.Size) } + +func TestGetOptionChainWithFilters(t *testing.T) { + c := DefaultClient + //nolint:lll + firstResp := `{"next_page_token":"QUFQTDI0MDQyNkMwMDE1MjUwMA==","snapshots":{"AAPL240426C00152500":{"latestQuote":{"ap":17,"as":91,"ax":"B","bp":16.25,"bs":80,"bx":"B","c":" ","t":"2024-04-24T19:59:59.782060288Z"},"latestTrade":{"c":"a","p":15.87,"s":1,"t":"2024-04-24T16:46:16.763406848Z","x":"I"}}}}` + secondResp := `{"next_page_token":null,"snapshots":{"AAPL240426C00155000":{"greeks":{"delta":0.9567110374646104,"gamma":0.010515010903989475,"rho":0.004041091409185355,"theta":-0.42275702792812153,"vega":0.008131530784084512},"impliedVolatility":0.9871160931510816,"latestQuote":{"ap":14.5,"as":86,"ax":"Q","bp":13.6,"bs":91,"bx":"B","c":" ","t":"2024-04-24T19:59:59.794910976Z"},"latestTrade":{"c":"a","p":14.28,"s":1,"t":"2024-04-24T19:42:55.36938496Z","x":"X"}}}}` //nolint:lll + c.do = func(c *Client, req *http.Request) (*http.Response, error) { + assert.Equal(t, "/v1beta1/options/snapshots/AAPL", req.URL.Path) + q := req.URL.Query() + assert.Equal(t, "1", q.Get("limit")) + assert.Equal(t, "151.123", q.Get("strike_price_gte")) + assert.Equal(t, "155", q.Get("strike_price_lte")) + assert.Equal(t, "1", q.Get("limit")) + assert.Equal(t, "call", q.Get("type")) + assert.Equal(t, "2024-04-26", q.Get("expiration_date_lte")) + pageToken := q.Get("page_token") + var resp string + switch pageToken { + case "": + resp = firstResp + case "QUFQTDI0MDQyNkMwMDE1MjUwMA==": + resp = secondResp + default: + require.Fail(t, "unexpected page token: "+pageToken) + } + return &http.Response{ + Body: io.NopCloser(strings.NewReader(resp)), + }, nil + } + got, err := c.GetOptionChain("AAPL", GetOptionChainRequest{ + PageLimit: 1, + Type: Call, + StrikePriceGte: 151.123, + StrikePriceLte: 155, + ExpirationDateLte: civil.Date{Year: 2024, Month: 4, Day: 26}, + }) + require.NoError(t, err) + require.NotNil(t, got) + require.Len(t, got, 2) + require.Contains(t, got, "AAPL240426C00152500") + s := got["AAPL240426C00152500"] + assert.EqualValues(t, 17, s.LatestQuote.AskPrice) + assert.EqualValues(t, 15.87, s.LatestTrade.Price) + require.Contains(t, got, "AAPL240426C00155000") + s = got["AAPL240426C00155000"] + d := 0.1 + assert.InDelta(t, 0.9871, s.ImpliedVolatility, d) + if assert.NotNil(t, s.Greeks) { + assert.InDelta(t, 0.9567, s.Greeks.Delta, d) + assert.InDelta(t, 0.0105, s.Greeks.Gamma, 0.1) + assert.InDelta(t, 0.004, s.Greeks.Rho, 0.1) + assert.InDelta(t, -0.422, s.Greeks.Theta, 0.1) + assert.InDelta(t, 0.0081, s.Greeks.Vega, 0.1) + } +}