493 lines
17 KiB
Go
493 lines
17 KiB
Go
|
|
package tastytrade
|
||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/json"
|
||
|
|
"fmt"
|
||
|
|
"net/url"
|
||
|
|
)
|
||
|
|
|
||
|
|
type FutureETFEquivalent struct {
|
||
|
|
Symbol string `json:"symbol"`
|
||
|
|
ShareQuantity int `json:"share-quantity"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureProduct struct {
|
||
|
|
RootSymbol string `json:"root-symbol"`
|
||
|
|
Code string `json:"code"`
|
||
|
|
Description string `json:"description"`
|
||
|
|
ClearingCode string `json:"clearing-code"`
|
||
|
|
ClearingExchangeCode string `json:"clearing-exchange-code"`
|
||
|
|
ClearportCode string `json:"clearport-code"`
|
||
|
|
LegacyCode string `json:"legacy-code"`
|
||
|
|
Exchange string `json:"exchange"`
|
||
|
|
LegacyExchangeCode string `json:"legacy-exchange-code"`
|
||
|
|
ProductType string `json:"product-type"`
|
||
|
|
ListedMonths []string `json:"listed-months"`
|
||
|
|
ActiveMonths []string `json:"active-months"`
|
||
|
|
NotionalMultiplier string `json:"notional-multiplier"`
|
||
|
|
TickSize string `json:"tick-size"`
|
||
|
|
DisplayFactor string `json:"display-factor"`
|
||
|
|
StreamerExchangeCode string `json:"streamer-exchange-code"`
|
||
|
|
SmallNotional bool `json:"small-notional"`
|
||
|
|
BackMonthFirstCalendarSymbol bool `json:"back-month-first-calendar-symbol"`
|
||
|
|
FirstNotice bool `json:"first-notice"`
|
||
|
|
CashSettled bool `json:"cash-settled"`
|
||
|
|
SecurityGroup string `json:"security-group"`
|
||
|
|
MarketSector string `json:"market-sector"`
|
||
|
|
Roll struct {
|
||
|
|
Name string `json:"name"`
|
||
|
|
ActiveCount int `json:"active-count"`
|
||
|
|
CashSettled bool `json:"cash-settled"`
|
||
|
|
BusinessDaysOffset int `json:"business-days-offset"`
|
||
|
|
FirstNotice bool `json:"first-notice"`
|
||
|
|
} `json:"roll"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type TickSize struct {
|
||
|
|
Value string `json:"value"`
|
||
|
|
Threshold string `json:"threshold,omitempty"`
|
||
|
|
Symbol string `json:"symbol,omitempty"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type Future struct {
|
||
|
|
Symbol string `json:"symbol"`
|
||
|
|
ProductCode string `json:"product-code"`
|
||
|
|
ContractSize string `json:"contract-size"`
|
||
|
|
TickSize string `json:"tick-size"`
|
||
|
|
NotionalMultiplier string `json:"notional-multiplier"`
|
||
|
|
MainFraction string `json:"main-fraction"`
|
||
|
|
SubFraction string `json:"sub-fraction"`
|
||
|
|
DisplayFactor string `json:"display-factor"`
|
||
|
|
LastTradeDate string `json:"last-trade-date"`
|
||
|
|
ExpirationDate string `json:"expiration-date"`
|
||
|
|
ClosingOnlyDate string `json:"closing-only-date"`
|
||
|
|
Active bool `json:"active"`
|
||
|
|
ActiveMonth bool `json:"active-month"`
|
||
|
|
NextActiveMonth bool `json:"next-active-month"`
|
||
|
|
IsClosingOnly bool `json:"is-closing-only"`
|
||
|
|
StopsTradingAt string `json:"stops-trading-at"`
|
||
|
|
ExpiresAt string `json:"expires-at"`
|
||
|
|
ProductGroup string `json:"product-group"`
|
||
|
|
Exchange string `json:"exchange"`
|
||
|
|
RollTargetSymbol string `json:"roll-target-symbol"`
|
||
|
|
StreamerExchangeCode string `json:"streamer-exchange-code"`
|
||
|
|
StreamerSymbol string `json:"streamer-symbol"`
|
||
|
|
BackMonthFirstCalendarSymbol bool `json:"back-month-first-calendar-symbol"`
|
||
|
|
IsTradeable bool `json:"is-tradeable"`
|
||
|
|
FutureETFEquivalent FutureETFEquivalent `json:"future-etf-equivalent"`
|
||
|
|
FutureProduct FutureProduct `json:"future-product"`
|
||
|
|
TickSizes []TickSize `json:"tick-sizes"`
|
||
|
|
OptionTickSizes []TickSize `json:"option-tick-sizes"`
|
||
|
|
SpreadTickSizes []TickSize `json:"spread-tick-sizes"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FuturesQueryResponse struct {
|
||
|
|
Data struct {
|
||
|
|
Items []Future `json:"items"`
|
||
|
|
} `json:"data"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FuturesQueryParams struct {
|
||
|
|
Symbol []string `json:"symbol"`
|
||
|
|
ProductCode []string `json:"product-code"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureResponse struct {
|
||
|
|
Data Future `json:"data"`
|
||
|
|
Context string `json:"context"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureOptionProduct struct {
|
||
|
|
RootSymbol string `json:"root-symbol"`
|
||
|
|
CashSettled bool `json:"cash-settled"`
|
||
|
|
Code string `json:"code"`
|
||
|
|
LegacyCode string `json:"legacy-code"`
|
||
|
|
ClearportCode string `json:"clearport-code"`
|
||
|
|
ClearingCode string `json:"clearing-code"`
|
||
|
|
ClearingExchangeCode string `json:"clearing-exchange-code"`
|
||
|
|
ClearingPriceMultiplier string `json:"clearing-price-multiplier"`
|
||
|
|
DisplayFactor string `json:"display-factor"`
|
||
|
|
Exchange string `json:"exchange"`
|
||
|
|
ProductType string `json:"product-type"`
|
||
|
|
ExpirationType string `json:"expiration-type"`
|
||
|
|
SettlementDelayDays int `json:"settlement-delay-days"`
|
||
|
|
IsRollover bool `json:"is-rollover"`
|
||
|
|
MarketSector string `json:"market-sector"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureProductsResponse struct {
|
||
|
|
Data struct {
|
||
|
|
Items []FutureProduct `json:"items"`
|
||
|
|
} `json:"data"`
|
||
|
|
Context string `json:"context"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureProductResponse struct {
|
||
|
|
Data FutureProduct `json:"data"`
|
||
|
|
Context string `json:"context"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FuturesOptionExpirationNested struct {
|
||
|
|
UnderlyingSymbol string `json:"underlying-symbol"`
|
||
|
|
RootSymbol string `json:"root-symbol"`
|
||
|
|
OptionRootSymbol string `json:"option-root-symbol"`
|
||
|
|
OptionContractSymbol string `json:"option-contract-symbol"`
|
||
|
|
Asset string `json:"asset"`
|
||
|
|
ExpirationDate string `json:"expiration-date"`
|
||
|
|
DaysToExpiration int `json:"days-to-expiration"`
|
||
|
|
ExpirationType string `json:"expiration-type"`
|
||
|
|
SettlementType string `json:"settlement-type"`
|
||
|
|
NotionalValue string `json:"notional-value"`
|
||
|
|
DisplayFactor string `json:"display-factor"`
|
||
|
|
StrikeFactor string `json:"strike-factor"`
|
||
|
|
StopsTradingAt string `json:"stops-trading-at"`
|
||
|
|
ExpiresAt string `json:"expires-at"`
|
||
|
|
TickSizes []TickSize `json:"tick-sizes"`
|
||
|
|
Strikes []StrikeNested `json:"strikes"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type OptionChain struct {
|
||
|
|
UnderlyingSymbol string `json:"underlying-symbol"`
|
||
|
|
RootSymbol string `json:"root-symbol"`
|
||
|
|
ExerciseStyle string `json:"exercise-style"`
|
||
|
|
Expirations []FuturesOptionExpirationNested `json:"expirations"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureOptionChainsNestedData struct {
|
||
|
|
Futures []Future `json:"futures"`
|
||
|
|
OptionChains []OptionChain `json:"option-chains"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureOptionChainsNestedResponse struct {
|
||
|
|
Data FutureOptionChainsNestedData `json:"data"`
|
||
|
|
Context string `json:"context"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureOption struct {
|
||
|
|
Symbol string `json:"symbol"`
|
||
|
|
UnderlyingSymbol string `json:"underlying-symbol"`
|
||
|
|
ProductCode string `json:"product-code"`
|
||
|
|
ExpirationDate string `json:"expiration-date"`
|
||
|
|
RootSymbol string `json:"root-symbol"`
|
||
|
|
OptionRootSymbol string `json:"option-root-symbol"`
|
||
|
|
StrikePrice string `json:"strike-price"`
|
||
|
|
Exchange string `json:"exchange"`
|
||
|
|
ExchangeSymbol string `json:"exchange-symbol"`
|
||
|
|
StreamerSymbol string `json:"streamer-symbol"`
|
||
|
|
OptionType string `json:"option-type"`
|
||
|
|
ExerciseStyle string `json:"exercise-style"`
|
||
|
|
IsVanilla bool `json:"is-vanilla"`
|
||
|
|
IsPrimaryDeliverable bool `json:"is-primary-deliverable"`
|
||
|
|
FuturePriceRatio string `json:"future-price-ratio"`
|
||
|
|
Multiplier string `json:"multiplier"`
|
||
|
|
UnderlyingCount string `json:"underlying-count"`
|
||
|
|
IsConfirmed bool `json:"is-confirmed"`
|
||
|
|
NotionalValue string `json:"notional-value"`
|
||
|
|
DisplayFactor string `json:"display-factor"`
|
||
|
|
SecurityExchange string `json:"security-exchange"`
|
||
|
|
SxID string `json:"sx-id"`
|
||
|
|
SettlementType string `json:"settlement-type"`
|
||
|
|
StrikeFactor string `json:"strike-factor"`
|
||
|
|
MaturityDate string `json:"maturity-date"`
|
||
|
|
IsExercisableWeekly bool `json:"is-exercisable-weekly"`
|
||
|
|
LastTradeTime string `json:"last-trade-time"`
|
||
|
|
DaysToExpiration int `json:"days-to-expiration"`
|
||
|
|
IsClosingOnly bool `json:"is-closing-only"`
|
||
|
|
Active bool `json:"active"`
|
||
|
|
StopsTradingAt string `json:"stops-trading-at"`
|
||
|
|
ExpiresAt string `json:"expires-at"`
|
||
|
|
FutureOptionProduct FutureOptionProduct `json:"future-option-product"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureOptionChainsDetailedResponse struct {
|
||
|
|
Data struct {
|
||
|
|
Items []FutureOption `json:"items"`
|
||
|
|
} `json:"data"`
|
||
|
|
Context string `json:"context"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureOptionsDetailedResponse struct {
|
||
|
|
Data struct {
|
||
|
|
Items []FutureOption `json:"items"`
|
||
|
|
} `json:"data"`
|
||
|
|
Context string `json:"context"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureOptionProductsResponse struct {
|
||
|
|
Data struct {
|
||
|
|
Items []FutureOptionProduct `json:"items"`
|
||
|
|
} `json:"data"`
|
||
|
|
Context string `json:"context"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureOptionProductDetailedResponse struct {
|
||
|
|
Data FutureOptionProduct `json:"data"`
|
||
|
|
Context string `json:"context"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureOptionsQueryParams struct {
|
||
|
|
Symbol []string `json:"symbol"`
|
||
|
|
OptionRootSymbol string `json:"option-root-symbol"`
|
||
|
|
ExpirationDate string `json:"expiration-date"`
|
||
|
|
OptionType string `json:"option-type"`
|
||
|
|
StrikePrice float64 `json:"strike-price"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type FutureOptionDetailedResponse struct {
|
||
|
|
Data FutureOption `json:"data"`
|
||
|
|
Context string `json:"context"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// QueryFutures retrieves a list of futures
|
||
|
|
func (api *TastytradeAPI) QueryFutures(params *FuturesQueryParams) (FuturesQueryResponse, error) {
|
||
|
|
urlVal := fmt.Sprintf("%s/instruments/futures", api.host)
|
||
|
|
|
||
|
|
if params != nil {
|
||
|
|
queryParams := url.Values{}
|
||
|
|
for _, symbol := range params.Symbol {
|
||
|
|
queryParams.Add("symbol[]", symbol)
|
||
|
|
}
|
||
|
|
for _, productCode := range params.ProductCode {
|
||
|
|
queryParams.Add("product-code[]", productCode)
|
||
|
|
}
|
||
|
|
urlVal = fmt.Sprintf("%s?%s", urlVal, queryParams.Encode())
|
||
|
|
}
|
||
|
|
|
||
|
|
data, err := api.fetchData(urlVal)
|
||
|
|
if err != nil {
|
||
|
|
return FuturesQueryResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
var response FuturesQueryResponse
|
||
|
|
jsonData, err := json.Marshal(data)
|
||
|
|
if err != nil {
|
||
|
|
return FuturesQueryResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
err = json.Unmarshal(jsonData, &response)
|
||
|
|
if err != nil {
|
||
|
|
return FuturesQueryResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return response, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetFuture retrieves data for a specific future symbol
|
||
|
|
func (api *TastytradeAPI) GetFuture(symbol string) (FutureResponse, error) {
|
||
|
|
urlVal := fmt.Sprintf("%s/instruments/futures/%s", api.host, url.PathEscape(symbol))
|
||
|
|
data, err := api.fetchData(urlVal)
|
||
|
|
if err != nil {
|
||
|
|
return FutureResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
var response FutureResponse
|
||
|
|
jsonData, err := json.Marshal(data)
|
||
|
|
if err != nil {
|
||
|
|
return FutureResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
err = json.Unmarshal(jsonData, &response)
|
||
|
|
if err != nil {
|
||
|
|
return FutureResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return response, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ListFutureProducts retrieves a list of future products
|
||
|
|
func (api *TastytradeAPI) ListFutureProducts() (FutureProductsResponse, error) {
|
||
|
|
urlVal := fmt.Sprintf("%s/instruments/future-products", api.host)
|
||
|
|
data, err := api.fetchData(urlVal)
|
||
|
|
if err != nil {
|
||
|
|
return FutureProductsResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
var response FutureProductsResponse
|
||
|
|
jsonData, err := json.Marshal(data)
|
||
|
|
if err != nil {
|
||
|
|
return FutureProductsResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
err = json.Unmarshal(jsonData, &response)
|
||
|
|
if err != nil {
|
||
|
|
return FutureProductsResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return response, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetFutureProduct retrieves data for a specific future product
|
||
|
|
func (api *TastytradeAPI) GetFutureProduct(exchange string, symbol string) (FutureProductResponse, error) {
|
||
|
|
urlVal := fmt.Sprintf("%s/instruments/future-products/%s/%s", api.host, exchange, url.PathEscape(symbol))
|
||
|
|
data, err := api.fetchData(urlVal)
|
||
|
|
if err != nil {
|
||
|
|
return FutureProductResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
var response FutureProductResponse
|
||
|
|
jsonData, err := json.Marshal(data)
|
||
|
|
if err != nil {
|
||
|
|
return FutureProductResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
err = json.Unmarshal(jsonData, &response)
|
||
|
|
if err != nil {
|
||
|
|
return FutureProductResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return response, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ListFutureOptionChainsNested retrieves nested future option chain data for a specific symbol
|
||
|
|
func (api *TastytradeAPI) ListFutureOptionChainsNested(symbol string) (FutureOptionChainsNestedResponse, error) {
|
||
|
|
urlVal := fmt.Sprintf("%s/futures-option-chains/%s/nested", api.host, symbol)
|
||
|
|
data, err := api.fetchData(urlVal)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionChainsNestedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
var response FutureOptionChainsNestedResponse
|
||
|
|
jsonData, err := json.Marshal(data)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionChainsNestedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
err = json.Unmarshal(jsonData, &response)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionChainsNestedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return response, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ListFutureOptionChainsDetailed retrieves detailed future option chain data for a specific symbol
|
||
|
|
func (api *TastytradeAPI) ListFutureOptionChainsDetailed(symbol string) (FutureOptionChainsDetailedResponse, error) {
|
||
|
|
urlVal := fmt.Sprintf("%s/futures-option-chains/%s", api.host, symbol)
|
||
|
|
data, err := api.fetchData(urlVal)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionChainsDetailedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
var response FutureOptionChainsDetailedResponse
|
||
|
|
jsonData, err := json.Marshal(data)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionChainsDetailedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
err = json.Unmarshal(jsonData, &response)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionChainsDetailedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return response, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ListFutureOptions retrieves future option data for a specific symbol with query parameters
|
||
|
|
func (api *TastytradeAPI) ListFutureOptions(params *FutureOptionsQueryParams) (FutureOptionsDetailedResponse, error) {
|
||
|
|
urlVal := fmt.Sprintf("%s/instruments/future-options", api.host)
|
||
|
|
|
||
|
|
if params != nil {
|
||
|
|
queryParams := url.Values{}
|
||
|
|
for _, symbol := range params.Symbol {
|
||
|
|
queryParams.Add("symbol[]", symbol)
|
||
|
|
}
|
||
|
|
if params.OptionRootSymbol != "" {
|
||
|
|
queryParams.Add("option-root-symbol", params.OptionRootSymbol)
|
||
|
|
}
|
||
|
|
if params.ExpirationDate != "" {
|
||
|
|
queryParams.Add("expiration-date", params.ExpirationDate)
|
||
|
|
}
|
||
|
|
if params.OptionType != "" {
|
||
|
|
queryParams.Add("option-type", params.OptionType)
|
||
|
|
}
|
||
|
|
if params.StrikePrice != 0 {
|
||
|
|
queryParams.Add("strike-price", fmt.Sprintf("%.2f", params.StrikePrice))
|
||
|
|
}
|
||
|
|
urlVal = fmt.Sprintf("%s?%s", urlVal, queryParams.Encode())
|
||
|
|
}
|
||
|
|
|
||
|
|
data, err := api.fetchData(urlVal)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionsDetailedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
var response FutureOptionsDetailedResponse
|
||
|
|
jsonData, err := json.Marshal(data)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionsDetailedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
err = json.Unmarshal(jsonData, &response)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionsDetailedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return response, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetFutureOption retrieves data for a specific future option symbol
|
||
|
|
func (api *TastytradeAPI) GetFutureOption(symbol string) (FutureOptionDetailedResponse, error) {
|
||
|
|
urlVal := fmt.Sprintf("%s/instruments/future-options/%s", api.host, url.PathEscape(symbol))
|
||
|
|
data, err := api.fetchData(urlVal)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionDetailedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
var response FutureOptionDetailedResponse
|
||
|
|
jsonData, err := json.Marshal(data)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionDetailedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
err = json.Unmarshal(jsonData, &response)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionDetailedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return response, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ListFutureOptionProducts retrieves a list of future option products
|
||
|
|
func (api *TastytradeAPI) ListFutureOptionProducts() (FutureOptionProductsResponse, error) {
|
||
|
|
urlVal := fmt.Sprintf("%s/instruments/future-option-products", api.host)
|
||
|
|
data, err := api.fetchData(urlVal)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionProductsResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
var response FutureOptionProductsResponse
|
||
|
|
jsonData, err := json.Marshal(data)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionProductsResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
err = json.Unmarshal(jsonData, &response)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionProductsResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return response, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetFutureOptionProduct retrieves data for a specific future option product
|
||
|
|
func (api *TastytradeAPI) GetFutureOptionProduct(exchange string, rootSymbol string) (FutureOptionProductDetailedResponse, error) {
|
||
|
|
urlVal := fmt.Sprintf("%s/instruments/future-option-products/%s/%s", api.host, exchange, rootSymbol)
|
||
|
|
data, err := api.fetchData(urlVal)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionProductDetailedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
var response FutureOptionProductDetailedResponse
|
||
|
|
jsonData, err := json.Marshal(data)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionProductDetailedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
err = json.Unmarshal(jsonData, &response)
|
||
|
|
if err != nil {
|
||
|
|
return FutureOptionProductDetailedResponse{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return response, nil
|
||
|
|
}
|