tiingo

package module
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 30, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

README

Go Reference Apache 2.0 License

Go Tiingo SDK

This is the official Go SDK for the Tiingo API. It provides a convenient and easy-to-use interface for accessing both REST and WebSocket APIs for stock, forex, and crypto data.

Features

  • REST Client: A simple, authenticated HTTP client for all Tiingo REST endpoints.
  • WebSocket Client: A robust, auto-reconnecting WebSocket client for real-time data feeds (IEX, Forex, Crypto).
  • Flexible Configuration: Use functional options to configure client behavior.
  • Callback-Based: Asynchronous, non-blocking handling of WebSocket messages using callbacks.
  • Connection Management: Automatic reconnection with exponential backoff, and health monitoring.
  • Thread-Safe: Safe for concurrent use.

Installation

To use the SDK in your project, you can use go get:

go get github.com/condrove10/go-tiingo-sdk

Usage

First, you need to get your API key from the Tiingo website.

REST Client

The REST client provides access to all of Tiingo's REST API endpoints.

Example: Fetching End-of-Day Prices

This example demonstrates how to fetch daily price data for a specific stock ticker.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/condrove10/go-tiingo-sdk"
)

func main() {
	apiKey := "YOUR_API_KEY"

	// Create a new REST client
	client, err := tiingo.NewRestClient(context.Background(), apiKey)
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}

	// Fetch end-of-day prices for Apple Inc.
	prices, err := client.GetEndOfDayPrices(context.Background(), "AAPL", &tiingo.EndOfDayPricesOptions{
		StartDate: "2023-01-01",
	})
	if err != nil {
		log.Fatalf("Error: %v", err)
	}

	fmt.Printf("Success: Retrieved %d records for AAPL\n", len(prices))
}
WebSocket Client

The WebSocket client allows you to subscribe to real-time data feeds for stocks (IEX), forex, and crypto.

Example: Subscribing to IEX Data

This example shows how to subscribe to real-time IEX data for a stock ticker.

package main

import (
	"context"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/condrove10/go-tiingo-sdk"
)

func main() {
	apiKey := os.Getenv("TIINGO_API_KEY")
	if apiKey == "" {
		log.Fatal("TIINGO_API_KEY environment variable not set")
	}

	// Create a new client for the IEX feed
	client := tiingo.NewWebsocketClient(
		apiKey,
		tiingo.EndpointTypeIEX,
		tiingo.WithThresholdLevel(5),
	)

	// Define an error handler for the connection
	onError := func(err error) {
		log.Printf("Connection Error: %v", err)
	}

	// Connect to the WebSocket
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	
	if err := client.Connect(ctx, onError); err != nil {
		log.Fatalf("Failed to connect: %v", err)
	}
	defer client.Close()

	// Define a subscription handler for the data
	onData := func(msg []byte, err error) {
		if err != nil {
			log.Printf("Subscription error: %v", err)
			return
		}
		log.Printf("Received data: %s", string(msg))
	}

	// Subscribe to the AAPL ticker
	if err := client.Subscribe("AAPL", onData); err != nil {
		log.Printf("Failed to subscribe to AAPL: %v", err)
	}

	// Wait for a shutdown signal to gracefully close the connection
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	log.Println("Shutting down...")
}
Example: Handling Crypto Data

This example demonstrates how to subscribe to real-time crypto data.

package main

import (
	"context"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/condrove10/go-tiingo-sdk"
)

func main() {
	apiKey := os.Getenv("TIINGO_API_KEY")
	if apiKey == "" {
		log.Fatal("TIINGO_API_KEY environment variable not set")
	}

	// Create a client for the Crypto feed
	client := tiingo.NewWebsocketClient(
		apiKey,
		tiingo.EndpointTypeCrypto,
		tiingo.WithThresholdLevel(2),
	)

	onError := func(err error) {
		log.Printf("Connection Error: %v", err)
	}
	
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	
	if err := client.Connect(ctx, onError); err != nil {
		log.Fatalf("Failed to connect: %v", err)
	}
	defer client.Close()

	onData := func(msg []byte, err error) {
		if err != nil {
			log.Printf("Subscription error: %v", err)
			return
		}
		log.Printf("Received Crypto Data: %s", string(msg))
	}

	if err := client.Subscribe("btcusd", onData); err != nil {
		log.Printf("Failed to subscribe: %v", err)
	}

	// Wait for a shutdown signal to gracefully close the connection
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	log.Println("Shutting down...")
}

Contributing

Contributions are welcome! If you find any issues or have suggestions for improvements, please open an issue or create a pull request.

License

This project is licensed under the Apache 2.0 License. See the LICENSE file for more details.

Documentation

Index

Constants

View Source
const (
	StrategyLinear      = backoffpolicy.StrategyLinear
	StrategyExponential = backoffpolicy.StrategyExponential
)

Variables

View Source
var (
	ErrAlreadySubscribed = errors.New("already subscribed to ticker")
	ErrNotConnected      = errors.New("websocket not connected")
	ErrAlreadyConnected  = errors.New("already connected")
)

WebSocket client errors

Functions

func ParseMessage

func ParseMessage(rawMsg []byte) (interface{}, error)

ParseMessage routes to appropriate parser

Types

type CryptoPrice

type CryptoPrice struct {
	Ticker         string  `json:"ticker"`
	BaseCurrency   string  `json:"baseCurrency"`
	QuoteCurrency  string  `json:"quoteCurrency"`
	Exchange       string  `json:"exchange"`
	Date           Time    `json:"date"`
	Open           float64 `json:"open"`
	High           float64 `json:"high"`
	Low            float64 `json:"low"`
	Close          float64 `json:"close"`
	Volume         float64 `json:"volume"`
	VolumeNotional float64 `json:"volumeNotional"`
	TradesDone     int     `json:"tradesDone"`
}

type CryptoPricesOptions

type CryptoPricesOptions struct {
	Tickers                  string `url:"tickers,omitempty"`
	StartDate                string `url:"startDate,omitempty"`
	EndDate                  string `url:"endDate,omitempty"`
	ResampleFreq             string `url:"resampleFreq,omitempty"`
	Exchanges                string `url:"exchanges,omitempty"`
	ConsolidatedBaseCurrency bool   `url:"consolidatedBaseCurrency,omitempty"`
	ConvertCurrency          string `url:"convertCurrency,omitempty"`
}

type CryptoQuote

type CryptoQuote struct {
	UpdateType string
	Ticker     string
	Date       time.Time
	Exchange   string
	BidSize    float64
	BidPrice   float64
	MidPrice   float64
	AskSize    float64
	AskPrice   float64
}

func ParseCryptoQuote

func ParseCryptoQuote(data []interface{}) (*CryptoQuote, error)

type CryptoTrade

type CryptoTrade struct {
	UpdateType string
	Ticker     string
	Date       time.Time
	Exchange   string
	LastSize   float64
	LastPrice  float64
}

Crypto types

func ParseCryptoTrade

func ParseCryptoTrade(data []interface{}) (*CryptoTrade, error)

type EndOfDayPricesOptions

type EndOfDayPricesOptions struct {
	StartDate    string `url:"startDate,omitempty"`
	EndDate      string `url:"endDate,omitempty"`
	Format       string `url:"format,omitempty"`
	ResampleFreq string `url:"resampleFreq,omitempty"`
	Columns      string `url:"columns,omitempty"`
	Sort         string `url:"sort,omitempty"`
}

type EndpointType

type EndpointType string

EndpointType defines the type for WebSocket endpoints.

const (
	EndpointTypeIEX    EndpointType = "iex"
	EndpointTypeCrypto EndpointType = "crypto"
	EndpointTypeForex  EndpointType = "fx"
)

Constants for Tiingo WebSocket endpoints.

type ForexPricesOptions

type ForexPricesOptions struct {
	StartDate    string `url:"startDate,omitempty"`
	EndDate      string `url:"endDate,omitempty"`
	ResampleFreq string `url:"resampleFreq,omitempty"`
}

type ForexQuote

type ForexQuote struct {
	UpdateType string
	Ticker     string
	Date       time.Time
	BidSize    float64
	BidPrice   float64
	MidPrice   float64
	AskSize    float64
	AskPrice   float64
}

Forex types

func ParseForexQuote

func ParseForexQuote(data []interface{}) (*ForexQuote, error)

type FundamentalsDailyOptions

type FundamentalsDailyOptions struct {
	StartDate string `url:"startDate,omitempty"`
	EndDate   string `url:"endDate,omitempty"`
	Format    string `url:"format,omitempty"`
}

type FundamentalsStatement

type FundamentalsStatement struct {
	Ticker        string             `json:"ticker"`
	StatementType string             `json:"statementType"`
	Quarter       int                `json:"quarter"`
	Year          int                `json:"year"`
	Date          Time               `json:"date"`
	DataCode      map[string]float64 `json:"dataCode"`
}

type FundamentalsStatementsOptions

type FundamentalsStatementsOptions struct {
	StartDate  string `url:"startDate,omitempty"`
	EndDate    string `url:"endDate,omitempty"`
	AsReported bool   `url:"asReported,omitempty"`
	Format     string `url:"format,omitempty"`
}

type IEXPrice

type IEXPrice struct {
	Ticker            string  `json:"ticker"`
	Timestamp         Time    `json:"timestamp"`
	QuoteTimestamp    Time    `json:"quoteTimestamp"`
	LastSaleTimestamp Time    `json:"lastSaleTimestamp"`
	Last              float64 `json:"last"`
	LastSize          float64 `json:"lastSize"`
	BidSize           float64 `json:"bidSize"`
	BidPrice          float64 `json:"bidPrice"`
	AskSize           float64 `json:"askSize"`
	AskPrice          float64 `json:"askPrice"`
	Volume            float64 `json:"volume"`
	High              float64 `json:"high"`
	Low               float64 `json:"low"`
	Open              float64 `json:"open"`
	PrevClose         float64 `json:"prevClose"`
	Mid               float64 `json:"mid"`
}

type IEXQuote

type IEXQuote struct {
	UpdateType       string
	Date             time.Time
	Nanoseconds      int64
	Ticker           string
	BidSize          *int32
	BidPrice         *float64
	MidPrice         *float64
	AskPrice         *float64
	AskSize          *int32
	LastPrice        *float64
	LastSize         *int32
	Halted           int32
	AfterHours       int32
	IntermarketSweep *int32
	Oddlot           *int32
	NMSRule611       *int32
}

func ParseIEXQuote

func ParseIEXQuote(data []interface{}) (*IEXQuote, error)

type IEXRealTimePricesOptions

type IEXRealTimePricesOptions struct {
	Tickers                string `url:"tickers,omitempty"`
	ResampleFreq           string `url:"resampleFreq,omitempty"`
	Columns                string `url:"columns,omitempty"`
	AfterHours             bool   `url:"afterHours,omitempty"`
	ForceFill              bool   `url:"forceFill,omitempty"`
	IncludeRawExchangeData bool   `url:"includeRawExchangeData,omitempty"`
}

type IEXTrade

type IEXTrade struct {
	UpdateType       string
	Date             time.Time
	Nanoseconds      int64
	Ticker           string
	BidSize          *int32
	BidPrice         *float64
	MidPrice         *float64
	AskPrice         *float64
	AskSize          *int32
	LastPrice        *float64
	LastSize         *int32
	Halted           int32
	AfterHours       int32
	IntermarketSweep int32
	Oddlot           int32
	NMSRule611       int32
}

IEX types

func ParseIEXTrade

func ParseIEXTrade(data []interface{}) (*IEXTrade, error)

type IEXWebSocketData

type IEXWebSocketData struct {
	Ticker    string  `json:"ticker"`
	Timestamp Time    `json:"timestamp"`
	Last      float64 `json:"last"`
	LastSize  float64 `json:"lastSize"`
	TngoLast  float64 `json:"tngoLast"`
	BidSize   float64 `json:"bidSize"`
	BidPrice  float64 `json:"bidPrice"`
	AskSize   float64 `json:"askSize"`
	AskPrice  float64 `json:"askPrice"`
}

type NewsFeedOptions

type NewsFeedOptions struct {
	Tickers   string `url:"tickers,omitempty"`
	Tags      string `url:"tags,omitempty"`
	Sources   string `url:"sources,omitempty"`
	StartDate string `url:"startDate,omitempty"`
	EndDate   string `url:"endDate,omitempty"`
	Limit     int    `url:"limit,omitempty"`
	Offset    int    `url:"offset,omitempty"`
	SortBy    string `url:"sortBy,omitempty"`
}

type NewsItem

type NewsItem struct {
	ID            int64    `json:"id"`
	Title         string   `json:"title"`
	URL           string   `json:"url"`
	Description   string   `json:"description"`
	PublishedDate Time     `json:"publishedDate"`
	CrawlDate     Time     `json:"crawlDate"`
	Source        string   `json:"source"`
	Tags          []string `json:"tags"`
	Tickers       []string `json:"tickers"`
}

type Option

type Option func(*WebsocketClient)

Option is a functional option for configuring the WebsocketClient.

func WithLivenessCheck

func WithLivenessCheck(interval time.Duration) Option

WithLivenessCheck sets the interval for checking liveness.

func WithLivenessTimeout

func WithLivenessTimeout(timeout time.Duration) Option

WithLivenessTimeout sets the duration after which an inactive connection is considered stale.

func WithThresholdLevel

func WithThresholdLevel(level int) Option

WithThresholdLevel sets the subscription threshold level.

type PriceData

type PriceData struct {
	Date        Time    `json:"date"`
	Close       float64 `json:"close"`
	High        float64 `json:"high"`
	Low         float64 `json:"low"`
	Open        float64 `json:"open"`
	Volume      float64 `json:"volume"`
	AdjClose    float64 `json:"adjClose"`
	AdjHigh     float64 `json:"adjHigh"`
	AdjLow      float64 `json:"adjLow"`
	AdjOpen     float64 `json:"adjOpen"`
	AdjVolume   float64 `json:"adjVolume"`
	DivCash     float64 `json:"divCash"`
	SplitFactor float64 `json:"splitFactor"`
}

type RawMessage

type RawMessage struct {
	MessageType string        `json:"messageType"`
	Service     string        `json:"service"`
	Data        []interface{} `json:"data"`
}

RawMessage from WebSocket

type Response

type Response struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

type RestClient

type RestClient struct {
	// contains filtered or unexported fields
}

RestClient handles communication with the Tiingo REST API.

func NewRestClient

func NewRestClient(ctx context.Context, apiKey string, options ...RestOption) (*RestClient, error)

NewRestClient creates a new client for the REST API.

func (*RestClient) GetCryptoPrices

func (c *RestClient) GetCryptoPrices(ctx context.Context, opts *CryptoPricesOptions) ([]*CryptoPrice, error)

GetCryptoPrices retrieves cryptocurrency price data.

func (*RestClient) GetEndOfDayPrices

func (c *RestClient) GetEndOfDayPrices(ctx context.Context, ticker string, opts *EndOfDayPricesOptions) ([]*PriceData, error)

GetEndOfDayPrices retrieves end-of-day price data for a ticker.

func (*RestClient) GetForexPrices

func (c *RestClient) GetForexPrices(ctx context.Context, ticker string, opts *ForexPricesOptions) ([]*PriceData, error)

GetForexPrices retrieves forex price data.

func (*RestClient) GetFundamentalsDaily

func (c *RestClient) GetFundamentalsDaily(ctx context.Context, ticker string, opts *FundamentalsDailyOptions) ([]*FundamentalsStatement, error)

GetFundamentalsDaily retrieves daily fundamental data for a ticker.

func (*RestClient) GetFundamentalsStatements

func (c *RestClient) GetFundamentalsStatements(ctx context.Context, ticker string, opts *FundamentalsStatementsOptions) ([]*FundamentalsStatement, error)

GetFundamentalsStatements retrieves fundamental statements for a ticker.

func (*RestClient) GetIEXRealTimePrices

func (c *RestClient) GetIEXRealTimePrices(ctx context.Context, opts *IEXRealTimePricesOptions) ([]*IEXPrice, error)

GetIEXRealTimePrices retrieves IEX real-time price data.

func (*RestClient) GetNewsFeed

func (c *RestClient) GetNewsFeed(ctx context.Context, opts *NewsFeedOptions) ([]*NewsItem, error)

GetNewsFeed retrieves news articles.

func (*RestClient) GetTickerMetadata

func (c *RestClient) GetTickerMetadata(ctx context.Context, ticker string) (*TickerMetadata, error)

GetTickerMetadata retrieves metadata for a given stock ticker.

func (*RestClient) Search

func (c *RestClient) Search(ctx context.Context, opts *SearchOptions) ([]*SearchResult, error)

Search retrieves search results for a query.

type RestConfig

type RestConfig struct {
	BaseURL        string
	RequestsPerSec int
	RetryMax       uint32
	RetryDelay     time.Duration
	Timeout        time.Duration
	HTTPClient     *http.Client
	RetryPolicy    func(resp *http.Response, err error) error
	RetryStrategy  backoffpolicy.Strategy
}

RestConfig holds configuration for the REST client.

type RestOption

type RestOption func(*RestConfig)

RestOption is a functional option for configuring the RestClient.

func WithBaseURL

func WithBaseURL(baseURL string) RestOption

WithBaseURL sets a custom base URL.

func WithHTTPClient

func WithHTTPClient(client *http.Client) RestOption

WithHTTPClient sets a custom HTTP client.

func WithRequestsPerSecond

func WithRequestsPerSecond(rps int) RestOption

WithRequestsPerSecond sets the rate limit for requests.

func WithRetryDelay

func WithRetryDelay(delay time.Duration) RestOption

WithRetryDelay sets the delay between retry attempts.

func WithRetryMax

func WithRetryMax(max uint32) RestOption

WithRetryMax sets the maximum number of retry attempts.

func WithRetryPolicy

func WithRetryPolicy(policy func(resp *http.Response, err error) error) RestOption

WithRetryPolicy sets a custom retry policy.

func WithStrategy

func WithStrategy(strategy backoffpolicy.Strategy) RestOption

WithStrategy sets the backoff strategy for retries.

func WithTimeout

func WithTimeout(timeout time.Duration) RestOption

WithTimeout sets the HTTP request timeout.

type SearchOptions

type SearchOptions struct {
	Query string `url:"query,omitempty"`
	Limit int    `url:"limit,omitempty"`
}

type SearchResult

type SearchResult struct {
	Ticker      string `json:"ticker"`
	Name        string `json:"name"`
	AssetType   string `json:"assetType"`
	PermaTicker string `json:"permaTicker"`
	Exchange    string `json:"exchange"`
}

type SubscribeRequest

type SubscribeRequest struct {
	EventName     string                 `json:"eventName"`
	Authorization string                 `json:"authorization"`
	EventData     map[string]interface{} `json:"eventData,omitempty"`
}

SubscribeRequest is the payload for subscribing/unsubscribing.

type SubscriptionConfirmation

type SubscriptionConfirmation struct {
	SubscriptionID int      `json:"subscriptionId"`
	Tickers        []string `json:"tickers"`
	ThresholdLevel string   `json:"thresholdLevel"`
}

SubscriptionConfirmation defines the structure of the subscription confirmation message.

type TickerMetadata

type TickerMetadata struct {
	Ticker       string `json:"ticker"`
	Name         string `json:"name"`
	ExchangeCode string `json:"exchangeCode"`
	StartDate    Time   `json:"startDate"`
	EndDate      Time   `json:"endDate"`
	Description  string `json:"description"`
}

type Time

type Time time.Time

Custom Time type for flexible unmarshaling

func (*Time) UnmarshalJSON

func (t *Time) UnmarshalJSON(b []byte) error

type WebSocketMessage

type WebSocketMessage struct {
	MessageType string          `json:"messageType"`
	Service     string          `json:"service"`
	Response    *Response       `json:"response"`
	Data        json.RawMessage `json:"data"`
}

WebSocketMessage represents the generic wrapper for all incoming messages.

type WebsocketClient

type WebsocketClient struct {
	// contains filtered or unexported fields
}

WebsocketClient handles the WebSocket connection and data stream.

func NewWebsocketClient

func NewWebsocketClient(apiKey string, endpointType EndpointType, options ...Option) *WebsocketClient

NewWebsocketClient creates a new client for the WebSocket API.

func (*WebsocketClient) Close

func (c *WebsocketClient) Close() error

Close gracefully disconnects the websocket connection and waits for all routines to finish.

func (*WebsocketClient) Connect

func (c *WebsocketClient) Connect(ctx context.Context, onError func(error)) error

Connect establishes a websocket connection with an error callback for connection-level errors.

func (*WebsocketClient) Subscribe

func (c *WebsocketClient) Subscribe(ticker string, handler func(message []byte, err error)) error

func (*WebsocketClient) SubscribeCryptoEndpointWithHandlers

func (c *WebsocketClient) SubscribeCryptoEndpointWithHandlers(ticker string, cryptoQuoteHandler func(msg *CryptoQuote, err error), cryptoTradeHandler func(msg *CryptoTrade, err error)) error

func (*WebsocketClient) SubscribeForexEndpointWithHandler

func (c *WebsocketClient) SubscribeForexEndpointWithHandler(ticker string, forexQuoteHandler func(msg *ForexQuote, err error)) error

func (*WebsocketClient) SubscribeIEXEndpointWithHandlers

func (c *WebsocketClient) SubscribeIEXEndpointWithHandlers(ticker string, iexQuoteHandler func(msg *IEXQuote, err error), iexTradeHandler func(msg *IEXTrade, err error)) error

func (*WebsocketClient) Unsubscribe

func (c *WebsocketClient) Unsubscribe(ticker string) error

Unsubscribe removes a subscription for a ticker.

type WebsocketConfig

type WebsocketConfig struct {
	ThresholdLevel  int
	LivenessTimeout time.Duration
	LivenessCheck   time.Duration
}

WebsocketConfig holds configuration for the WebSocket client.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL