Skip to content
Permalink
Browse files

Add nondynamic historical prices endpoints

  • Loading branch information...
redorb committed Mar 9, 2019
1 parent 40c5e3b commit 00cfc0528f4641f82238988baae3ffff18614347
Showing with 340 additions and 3 deletions.
  1. +3 −3 README.md
  2. +98 −0 client.go
  3. +131 −0 examples/iexcloud/cmd/historical.go
  4. +1 −0 go.mod
  5. +2 −0 go.sum
  6. +105 −0 historical.go
@@ -48,7 +48,8 @@ you want a particular API to be developed next, please open an issue.
- [x] Estimates
- [x] Financials
- [x] Fund Ownership
- [ ] Historical Prices
- [x] Nondynamic Historical Prices
- [ ] Dynamic Historical Prices
- [x] Income Statement
- [x] Insider Roster
- [x] Insider Summary
@@ -155,8 +156,7 @@ $ make cover
[iexcloud][] is released under the MIT license. Please see the
[LICENSE][] file for more information.


[1]:https://iexcloud.io
[1]: https://iexcloud.io
[2]: https://github.com/goinvest/iexcloud/blob/master/examples/iexcloud/README.md
[iexcloud]: https://github.com/goinvest/iexcloud
[godoc badge]: https://godoc.org/github.com/goinvest/iexcloud?status.svg
@@ -7,12 +7,16 @@ package iex

import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
"time"

"github.com/google/go-querystring/query"
)

const apiURL = "https://cloud.iexapis.com/beta"
@@ -695,6 +699,100 @@ func (c Client) IntradayStats(symbol string) (IntradayStats, error) {
return r, err
}

// # Historical Data related endpoints. #

// HistoricalPrices retrieves historically adjusted market-wide data
func (c Client) HistoricalPrices(symbol string, timeframe HistoricalTimeFrame, options *HistoricalOptions) ([]HistoricalDataPoint, error) {
h := make([]HistoricalDataPoint, 0)
if !timeframe.Valid() {
return h, errors.New("invalid timeframe passed to method")
}
endpoint := fmt.Sprintf("/stock/%s/chart/%s",
url.PathEscape(symbol), timeframe)

endpoint, err := c.historicalEndpointWithOpts(endpoint, options)
if err != nil {
return h, err
}
err = c.GetJSON(endpoint, &h)
return h, err
}

// HistoricalPricesByDay retrieves historically adjusted market-wide data for a given day
func (c Client) HistoricalPricesByDay(symbol string, day time.Time, options *HistoricalOptions) ([]HistoricalDataPoint, error) {
h := make([]HistoricalDataPoint, 0)
endpoint := fmt.Sprintf("/stock/%s/chart/date/%s",
url.PathEscape(symbol), day.Format("20060102"))
endpoint, err := c.historicalEndpointWithOpts(endpoint, options)
if err != nil {
return h, err
}

err = c.GetJSON(endpoint, &h)
return h, err
}

func (c Client) historicalEndpointWithOpts(endpoint string, opts *HistoricalOptions) (string, error) {
if opts == nil {
return endpoint, nil
}
v, err := query.Values(opts)
if err != nil {
return "", err
}
optParams := v.Encode()
if optParams != "" {
endpoint = fmt.Sprintf("%s?%s", endpoint, optParams)
}
return endpoint, nil
}

// IntradayHistoricalPrices retrieves intraday historical market-wide data
func (c Client) IntradayHistoricalPrices(symbol string, options *IntradayHistoricalOptions) ([]IntradayHistoricalDataPoint, error) {
h := make([]IntradayHistoricalDataPoint, 0)
endpoint := fmt.Sprintf("/stock/%s/chart/1d",
url.PathEscape(symbol))
endpoint, err := c.intradayHistoricalEndpointWithOpts(endpoint, options, false)
if err != nil {
return h, err
}

err = c.GetJSON(endpoint, &h)
return h, err
}

// IntradayHistoricalPricesByDay retrieves intraday historical market-wide data for a given day
func (c Client) IntradayHistoricalPricesByDay(symbol string, day time.Time, options *IntradayHistoricalOptions) ([]IntradayHistoricalDataPoint, error) {
h := make([]IntradayHistoricalDataPoint, 0)
endpoint := fmt.Sprintf("/stock/%s/chart/date/%s?chartByDay=true",
url.PathEscape(symbol), day.Format("20060102"))
endpoint, err := c.intradayHistoricalEndpointWithOpts(endpoint, options, true)
if err != nil {
return h, err
}
err = c.GetJSON(endpoint, &h)
return h, err
}

func (c Client) intradayHistoricalEndpointWithOpts(endpoint string, opts *IntradayHistoricalOptions, existingParams bool) (string, error) {
if opts == nil {
return endpoint, nil
}
v, err := query.Values(opts)
if err != nil {
return "", err
}
sep := "?"
if existingParams {
sep = "&"
}
optParams := v.Encode()
if optParams != "" {
endpoint = fmt.Sprintf("%s%s%s", endpoint, sep, optParams)
}
return endpoint, nil
}

// # API System Metadata related endpoints. #

// Status returns the IEX Cloud system status.
@@ -0,0 +1,131 @@
// Copyright (c) 2019 The iexcloud developers. All rights reserved.
// Project site: https://github.com/goinvest/iexcloud
// Use of this source code is governed by a MIT-style license that
// can be found in the LICENSE file for the project.

package cmd

import (
"encoding/json"
"fmt"
"log"
"time"

iex "github.com/goinvest/iexcloud"
"github.com/goinvest/iexcloud/examples/iexcloud/domain"
"github.com/spf13/cobra"
)

func init() {
rootCmd.AddCommand(historicalCmd)
rootCmd.AddCommand(historicalByDayCmd)
rootCmd.AddCommand(intradayHistoricalCmd)
rootCmd.AddCommand(intradayHistoricalByDayCmd)
}

var historicalCmd = &cobra.Command{
Use: "historical [stock] [timeframe]",
Short: "Retrieve the historical data for stock symbol in given timeframe",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
stock := args[0]
timeframe := iex.HistoricalTimeFrame(args[1])
cfg, err := domain.ReadConfig(configFileFlag)
if err != nil {
log.Fatalf("Error reading config file: %s", err)
}
client := iex.NewClient(cfg.Token, cfg.BaseURL)
histPrices, err := client.HistoricalPrices(stock, timeframe, nil)
if err != nil {
log.Fatalf("Error getting historical prices: %s", err)
}
b, err := json.MarshalIndent(histPrices, "", " ")
if err != nil {
log.Fatalf("Error marshaling into JSON: %s", err)
}
fmt.Println("## Historical Prices ##")
fmt.Println(string(b))
},
}

var historicalByDayCmd = &cobra.Command{
Use: "historicalbyday [stock] [day]",
Short: "Retrieve the historical data for stock symbol for given day yyyymmddd",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
stock := args[0]
day, err := time.Parse("20060102", args[1])
if err != nil {
log.Fatalf("Error parsing date: %s", err)
}

cfg, err := domain.ReadConfig(configFileFlag)
if err != nil {
log.Fatalf("Error reading config file: %s", err)
}
client := iex.NewClient(cfg.Token, cfg.BaseURL)
histPrices, err := client.HistoricalPricesByDay(stock, day, nil)
if err != nil {
log.Fatalf("Error getting intraday historical prices: %s", err)
}
b, err := json.MarshalIndent(histPrices, "", " ")
if err != nil {
log.Fatalf("Error marshaling into JSON: %s", err)
}
fmt.Printf("## Historical Prices For %s ##\n", args[1])
fmt.Println(string(b))
},
}

var intradayHistoricalCmd = &cobra.Command{
Use: "intradayhistorical [stock]",
Short: "Retrieve the intraday data for stock symbol",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
stock := args[0]
cfg, err := domain.ReadConfig(configFileFlag)
if err != nil {
log.Fatalf("Error reading config file: %s", err)
}
client := iex.NewClient(cfg.Token, cfg.BaseURL)
histPrices, err := client.IntradayHistoricalPrices(stock, nil)
if err != nil {
log.Fatalf("Error getting intraday historical prices: %s", err)
}
b, err := json.MarshalIndent(histPrices, "", " ")
if err != nil {
log.Fatalf("Error marshaling into JSON: %s", err)
}
fmt.Println("## Intraday Historical Prices ##")
fmt.Println(string(b))
},
}

var intradayHistoricalByDayCmd = &cobra.Command{
Use: "intradayhistoricalbyday [stock] [day]",
Short: "Retrieve the intraday data for stock symbol for given day yyyymmddd",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
stock := args[0]
day, err := time.Parse("20060102", args[1])
if err != nil {
log.Fatalf("Error parsing date: %s", err)
}

cfg, err := domain.ReadConfig(configFileFlag)
if err != nil {
log.Fatalf("Error reading config file: %s", err)
}
client := iex.NewClient(cfg.Token, cfg.BaseURL)
histPrices, err := client.IntradayHistoricalPricesByDay(stock, day, nil)
if err != nil {
log.Fatalf("Error getting intraday historical prices: %s", err)
}
b, err := json.MarshalIndent(histPrices, "", " ")
if err != nil {
log.Fatalf("Error marshaling into JSON: %s", err)
}
fmt.Printf("## Intraday Historical Prices For %s ##\n", args[1])
fmt.Println(string(b))
},
}
1 go.mod
@@ -2,6 +2,7 @@ module github.com/goinvest/iexcloud

require (
github.com/BurntSushi/toml v0.3.1
github.com/google/go-querystring v1.0.0
github.com/spf13/cobra v0.0.3
github.com/spf13/pflag v1.0.3 // indirect
)
2 go.sum
@@ -1,5 +1,7 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
@@ -0,0 +1,105 @@
// Copyright (c) 2019 The iexcloud developers. All rights reserved.
// Project site: https://github.com/goinvest/iexcloud
// Use of this source code is governed by a MIT-style license that
// can be found in the LICENSE file for the project.
package iex

// HistoricalTimeFrame enum for selecting time frame of historical data
type HistoricalTimeFrame string

const (
// OneMonthHistorical One month (default) historically adjusted market-wide data
OneMonthHistorical HistoricalTimeFrame = "1m"
// ThreeMonthHistorical Three months historically adjusted market-wide data
ThreeMonthHistorical HistoricalTimeFrame = "3m"
// SixMonthHistorical Six months historically adjusted market-wide data
SixMonthHistorical HistoricalTimeFrame = "6m"
// OneYearHistorical One year historically adjusted market-wide data
OneYearHistorical HistoricalTimeFrame = "1y"
// TwoYearHistorical Two year historically adjusted market-wide data
TwoYearHistorical HistoricalTimeFrame = "2y"
// FiveYearHistorical Five year historically adjusted market-wide data
FiveYearHistorical HistoricalTimeFrame = "5y"
// YearToDateHistorical Year to date historically adjusted market-wide data
YearToDateHistorical HistoricalTimeFrame = "ytd"
// MaxHistorical All available historically adjusted market-wide data up to 15 years
MaxHistorical HistoricalTimeFrame = "max"
)

// Valid Determines if HistoricalTimeFrame is a defined constant
func (htf HistoricalTimeFrame) Valid() bool {
switch htf {
case OneMonthHistorical, ThreeMonthHistorical,
SixMonthHistorical, OneYearHistorical,
TwoYearHistorical, FiveYearHistorical,
YearToDateHistorical, MaxHistorical:
return true
default:
return false
}
}

// IntradayHistoricalDataPoint Represents a single intraday data point for a stock
type IntradayHistoricalDataPoint struct {
Date string `json:"date"`
Minute string `json:"minute"`
Label string `json:"label"`
High float64 `json:"high"`
Low float64 `json:"low"`
Average float64 `json:"average"`
Volume int `json:"volume"`
Notional float64 `json:"notional"`
NumberOfTrades int `json:"numberOfTrades"`
MarketHigh float64 `json:"marketHigh"`
MarketLow float64 `json:"marketLow"`
MarketAverage float64 `json:"marketAverage"`
MarketVolume int `json:"marketVolume"`
MarketNotional float64 `json:"marketNotional"`
MarketNumberOfTrades int `json:"marketNumberOfTrades"`
Open float64 `json:"open"`
Close float64 `json:"close"`
MarketOpen float64 `json:"marketOpen"`
MarketClose float64 `json:"marketClose"`
ChangeOverTime float64 `json:"changeOverTime"`
MarketChangeOverTime float64 `json:"marketChangeOverTime"`
}

// HistoricalOptions optional query params to pass to historical endpoint
// If values are false or 0 they aren't passed.
type HistoricalOptions struct {
ChartCloseOnly bool `url:"chartCloseOnly,omitempty"`
ChartSimplify bool `url:"chartSimplify,omitempty"`
ChartInterval int `url:"chartInterval,omitempty"`
ChangeFromClose bool `url:"changeFromClose,omitempty"`
ChartLast int `url:"chartLast,omitempty"`
}

// IntradayHistoricalOptions optional query params to pass to intraday historical endpoint
// If values are false or 0 they aren't passed.
type IntradayHistoricalOptions struct {
ChartIEXOnly bool `url:"chartIEXOnly,omitempty"`
ChartReset bool `url:"chartReset,omitempty"`
ChartSimplify bool `url:"chartSimplify,omitempty"`
ChartInterval int `url:"chartInterval,omitempty"`
ChangeFromClose bool `url:"changeFromClose,omitempty"`
ChartLast int `url:"chartLast,omitempty"`
}

// HistoricalDataPoint Represents a single historical data point for a stock
type HistoricalDataPoint struct {
Date string `json:"date"`
Open float64 `json:"open"`
Close float64 `json:"close"`
High float64 `json:"high"`
Low float64 `json:"low"`
Volume int `json:"volume"`
UOpen float64 `json:"uOpen"`
UClose float64 `json:"uClose"`
UHigh float64 `json:"uHigh"`
ULow float64 `json:"uLow"`
UVolume int `json:"uVolume"`
Change float64 `json:"change"`
ChangePercent float64 `json:"changePercent"`
Label string `json:"label"`
ChangeOverTime float64 `json:"changeOverTime"`
}

0 comments on commit 00cfc05

Please sign in to comment.
You can’t perform that action at this time.