Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds options and futures quotes. #6

Merged
merged 4 commits into from
Jul 15, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Adds options and futures quotes.
  • Loading branch information
ackleymi committed Jul 15, 2018
commit 0aa526e0283a6bc0e21d026ca92f7e72125f28d5
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ cache:

env:
global:
- FINANCE_MOCK_VERSION=0.0.4
- FINANCE_MOCK_VERSION=0.0.5

go:
- "1.9"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Status | Description | Source
[x] | ETF quote(s) | Yahoo finance
[x] | Mutual fund quote(s) | Yahoo finance
[x] | Historical quotes | Yahoo finance
[x] | Options straddles | Yahoo finance
[ ] | Options chains | Yahoo finance
[ ] | Symbols list | BATS

Expand Down
51 changes: 30 additions & 21 deletions examples/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,47 @@ package main
import (
"fmt"

"github.com/piquette/finance-go/chart"
"github.com/piquette/finance-go/datetime"
"github.com/piquette/finance-go/quote"
"github.com/piquette/finance-go/options"
)

// This file lists several usage examples of this library
// and can be used to verify behavior.
func main() {

// Basic quote example.
// --------------------
q, err := quote.Get("SPY")
if err != nil {
fmt.Println(err)
} else {
fmt.Println(q)
}
iter := options.GetStraddle("TWTR")

// Basic chart example.
// --------------------
params := &chart.Params{
Symbol: "TWTR",
Interval: datetime.OneHour,
}
iter := chart.Get(params)
fmt.Println(iter.Meta())

for iter.Next() {
b := iter.Bar()
fmt.Println(datetime.FromUnix(b.Timestamp))

fmt.Println(iter.Straddle().Strike)
}
if iter.Err() != nil {
fmt.Println(iter.Err())
}

// Basic quote example.
// --------------------
// q, err := quote.Get("SPY")
// if err != nil {
// fmt.Println(err)
// } else {
// fmt.Println(q)
// }

// Basic chart example.
// --------------------
// params := &chart.Params{
// Symbol: "TWTR",
// Interval: datetime.OneHour,
// }
// iter := chart.Get(params)
//
// for iter.Next() {
// b := iter.Bar()
// fmt.Println(datetime.FromUnix(b.Timestamp))
//
// }
// if iter.Err() != nil {
// fmt.Println(iter.Err())
// }
}
108 changes: 108 additions & 0 deletions future/client.go
Original file line number Diff line number Diff line change
@@ -1 +1,109 @@
package future

import (
"context"
"strings"

finance "github.com/piquette/finance-go"
form "github.com/piquette/finance-go/form"
"github.com/piquette/finance-go/iter"
)

// Client is used to invoke quote APIs.
type Client struct {
B finance.Backend
}

func getC() Client {
return Client{finance.GetBackend(finance.YFinBackend)}
}

// Params carries a context and symbols information.
type Params struct {
finance.Params `form:"-"`
// Symbols are the symbols for which a
// quote is requested.
Symbols []string `form:"-"`
sym string `form:"symbols"`
}

// Iter is an iterator for a list of quotes.
// The embedded Iter carries methods with it;
// see its documentation for details.
type Iter struct {
*iter.Iter
}

// Future returns the most recent future
// visited by a call to Next.
func (i *Iter) Future() *finance.Future {
return i.Current().(*finance.Future)
}

// Get returns an Future quote that matches the parameters specified.
func Get(symbol string) (*finance.Future, error) {
i := List([]string{symbol})

if !i.Next() {
return nil, i.Err()
}

return i.Future(), nil
}

// List returns several quotes.
func List(symbols []string) *Iter {
return ListP(&Params{Symbols: symbols})
}

// ListP returns a quote iterator and requires a params
// struct as an argument.
func ListP(params *Params) *Iter {
return getC().ListP(params)
}

// ListP returns a quote iterator.
func (c Client) ListP(params *Params) *Iter {

if params.Context == nil {
ctx := context.TODO()
params.Context = &ctx
}

// Validate input.
// TODO: validate symbols..
if params == nil || len(params.Symbols) == 0 {
return &Iter{iter.NewE(finance.CreateArgumentError())}
}
params.sym = strings.Join(params.Symbols, ",")

body := &form.Values{}
form.AppendTo(body, params)

return &Iter{iter.New(body, func(b *form.Values) (interface{}, []interface{}, error) {

resp := response{}
err := c.B.Call("/v7/finance/quote", body, params.Context, &resp)
if err != nil {
err = finance.CreateRemoteError(err)
}

ret := make([]interface{}, len(resp.Inner.Result))
for i, v := range resp.Inner.Result {
ret[i] = v
}
if resp.Inner.Error != nil {
err = finance.CreateRemoteError(resp.Inner.Error)
}

return nil, ret, err
})}
}

// response is a yfin quote response.
type response struct {
Inner struct {
Result []*finance.Future `json:"result"`
Error *finance.YfinError `json:"error"`
} `json:"quoteResponse"`
}
19 changes: 19 additions & 0 deletions future/client_test.go
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
package future

import (
"testing"

finance "github.com/piquette/finance-go"
tests "github.com/piquette/finance-go/testing"
"github.com/stretchr/testify/assert"
)

func TestGetFuture(t *testing.T) {
tests.SetMarket(finance.MarketStateRegular)

q, err := Get(tests.TestFutureSymbol)

assert.Nil(t, err)
assert.NotNil(t, q)
assert.Equal(t, finance.MarketStateRegular, q.MarketState)
assert.Equal(t, tests.TestFutureSymbol, q.Symbol)
}
108 changes: 108 additions & 0 deletions option/client.go
Original file line number Diff line number Diff line change
@@ -1 +1,109 @@
package option

import (
"context"
"strings"

finance "github.com/piquette/finance-go"
form "github.com/piquette/finance-go/form"
"github.com/piquette/finance-go/iter"
)

// Client is used to invoke quote APIs.
type Client struct {
B finance.Backend
}

func getC() Client {
return Client{finance.GetBackend(finance.YFinBackend)}
}

// Params carries a context and symbols information.
type Params struct {
finance.Params `form:"-"`
// Symbols are the symbols for which a
// quote is requested.
Symbols []string `form:"-"`
sym string `form:"symbols"`
}

// Iter is an iterator for a list of quotes.
// The embedded Iter carries methods with it;
// see its documentation for details.
type Iter struct {
*iter.Iter
}

// Option returns the most recent option
// visited by a call to Next.
func (i *Iter) Option() *finance.Option {
return i.Current().(*finance.Option)
}

// Get returns an option quote that matches the parameters specified.
func Get(symbol string) (*finance.Option, error) {
i := List([]string{symbol})

if !i.Next() {
return nil, i.Err()
}

return i.Option(), nil
}

// List returns several quotes.
func List(symbols []string) *Iter {
return ListP(&Params{Symbols: symbols})
}

// ListP returns a quote iterator and requires a params
// struct as an argument.
func ListP(params *Params) *Iter {
return getC().ListP(params)
}

// ListP returns a quote iterator.
func (c Client) ListP(params *Params) *Iter {

if params.Context == nil {
ctx := context.TODO()
params.Context = &ctx
}

// Validate input.
// TODO: validate symbols..
if params == nil || len(params.Symbols) == 0 {
return &Iter{iter.NewE(finance.CreateArgumentError())}
}
params.sym = strings.Join(params.Symbols, ",")

body := &form.Values{}
form.AppendTo(body, params)

return &Iter{iter.New(body, func(b *form.Values) (interface{}, []interface{}, error) {

resp := response{}
err := c.B.Call("/v7/finance/quote", body, params.Context, &resp)
if err != nil {
err = finance.CreateRemoteError(err)
}

ret := make([]interface{}, len(resp.Inner.Result))
for i, v := range resp.Inner.Result {
ret[i] = v
}
if resp.Inner.Error != nil {
err = finance.CreateRemoteError(resp.Inner.Error)
}

return nil, ret, err
})}
}

// response is a yfin quote response.
type response struct {
Inner struct {
Result []*finance.Option `json:"result"`
Error *finance.YfinError `json:"error"`
} `json:"quoteResponse"`
}
19 changes: 19 additions & 0 deletions option/client_test.go
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
package option

import (
"testing"

finance "github.com/piquette/finance-go"
tests "github.com/piquette/finance-go/testing"
"github.com/stretchr/testify/assert"
)

func TestGetOption(t *testing.T) {
tests.SetMarket(finance.MarketStateRegular)

q, err := Get(tests.TestOptionSymbol)

assert.Nil(t, err)
assert.NotNil(t, q)
assert.Equal(t, finance.MarketStateRegular, q.MarketState)
assert.Equal(t, tests.TestOptionSymbol, q.Symbol)
}
Loading