cumberland

package module
v0.0.0-...-227dadb Latest Latest
Warning

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

Go to latest
Published: Apr 29, 2020 License: BSD-3-Clause Imports: 16 Imported by: 0

README

= cumberland-go
:url-badge: https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square
:url-godev: https://pkg.go.dev/github.com/shuLhan/cumberland-go

image:{url-badge}[go.dev Reference, link={url-godev}]

This repository is non-official Go client for cumberland.io.

==  Testing

The actual test for API require Cumberland's identity (a combination of
counterparty ID and user ID), and certificate files.
Once all of required keys has been retrieved we can set the following
environment variables and then run the test,

* `CUMBERLAND_COUNTERPARTY_ID`, the counterparty ID given by Cumberland
* `CUMBERLAND_USER_ID`: the user ID in Cumberland
* `CUMBERLAND_CERT`: path to the certificate file
* `CUMBERLAND_KEY`: path to private key file

For example, lets say we store the certificate and key file in
"testdata/certificate.pem" and "testdata/private.pem",

----
$ export CUMBERLAND_COUNTERPARTY_ID=<UUID>
$ export CUMBERLAND_USER_ID=<username>
$ export CUMBERLAND_CERT=testdata/certificate.pem
$ export CUMBERLAND_KEY=testdata/private.pem
$ go test -v .
----

Documentation

Overview

Package cumberland provide a client library for cumberland.io

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Amount

type Amount struct {
	Amount   *big.Rat `json:"amount"`
	Currency string   `json:"currency"`
}

type Client

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

Client for Cumberland with HTTP and WebSocket.

func New

func New(identity ExternalIdentity, cert tls.Certificate) (cl *Client, err error)

New create and initialize new Cumberland client using registered user's ID and counter party ID as an ExternalIdentity and client's TLS certificate.

func NewFromEnvironment

func NewFromEnvironment() (cl *Client, err error)

NewFromEnvironment create a new client based on identity defined in environment variables "CUMBERLAND_USER_ID" and "CUMBERLAND_COUNTERPARTY_ID".

If environment variables "CUMBERLAND_CERT" and "CUMBERLAND_KEY" are also set, then the Client will use them when trying to open the WebSocket connection.

func (*Client) Close

func (cl *Client) Close()

Close the client's connection and clean up any resources.

func (*Client) GetClosingQuote

func (cl *Client) GetClosingQuote(req *ClosingQuoteRequest) (
	closingQuote *ClosingQuoteResponse, err error,
)

GetClosingQuote returns a two-sided closing quote marked at a closing time for a given notional value.

Example
cl, err := NewFromEnvironment()
if err != nil {
	log.Fatal(err)
}

req := &ClosingQuoteRequest{
	Ticker: "BTC_USD",
	Notional: Amount{
		Currency: "USD",
		Amount:   big.NewRat(10),
	},
	Date:     "2018-10-05",
	Time:     "16:00:00",
	TimeZone: "America/New_York",
}

closingQuote, err := cl.GetClosingQuote(req)
if err != nil {
	log.Fatal(err)
}

fmt.Printf("Closing quote for %s @ %s: %+v\n", req.Notional.Currency,
	req.Notional.Amount, closingQuote)
Output:

func (*Client) GetIndicativeQuote

func (cl *Client) GetIndicativeQuote(
	ticker, currency string, amount *big.Rat,
) (iquote *IndicativeQuoteResponse, err error)

GetIndicativeQuote returns a non-actionable two sided quote for an instrument at a notional value of $100,000 USD. You can optionally supply a custom notional value (amount) and currency to get adjusted quotes based on the supplied notional value.

NOTE: Indicative quote responses are not actionable and do not reflect the actionable price provided when making SubscribeQuote.

Example
cl, err := NewFromEnvironment()
if err != nil {
	log.Fatal(err)
}

var (
	ticker   string = "BTC_USD"
	amount          = big.NewRat(10)
	currency string = "USD"
)

iquote, err := cl.GetIndicativeQuote(ticker, currency, amount)
if err != nil {
	log.Fatal(err)
}

fmt.Printf("Indicative quote for %s@%s: %+v\n", currency, amount, iquote)
Output:

func (*Client) GetReferenceData

func (cl *Client) GetReferenceData() (refData *ReferenceData, err error)

GetReferenceData returns all instruments supported by the API.

Example
cl, err := NewFromEnvironment()
if err != nil {
	log.Fatal(err)
}

ref, err := cl.GetReferenceData()
if err != nil {
	log.Fatal(err)
}

fmt.Printf("Reference data: %+v\n", ref)
Output:

func (*Client) GetSystemStatus

func (cl *Client) GetSystemStatus() (systemStatus *SystemStatusResponse, err error)

GetSystemStatus returns the current status of all request types using REST API.

Example
cl, err := NewFromEnvironment()
if err != nil {
	log.Fatal(err)
}

systemStatus, err := cl.GetSystemStatus()
if err != nil {
	log.Fatal(err)
}

fmt.Printf("System status: %+v\n", systemStatus)
Output:

func (*Client) GetTime

func (cl *Client) GetTime() (timeRes *TimeResponse, err error)

GetTime returns the current time in milliseconds since epoch as observed by Cumberland's servers using REST API.

Example
cl, err := NewFromEnvironment()
if err != nil {
	log.Fatal(err)
}

timeRes, err := cl.GetTime()
if err != nil {
	log.Fatal(err)
}

timeServer := time.Unix(timeRes.Time, 0)

fmt.Printf("Local time: %s\n", time.Now())
fmt.Printf("Server time: %s\n", timeServer)
Output:

func (*Client) RequestIndicativeQuote

func (cl *Client) RequestIndicativeQuote(
	ticker string, amount *big.Rat, cb IndicativeQuoteCallback,
) (err error)

RequestIndicativeQuote send the WebSocket request to get IndicativeQuote based on specific ticker and amount.

On success, it will call the callback `cb` with IndicativeQuoteResponse.

Example
var wg sync.WaitGroup

cl, err := NewFromEnvironment()
if err != nil {
	log.Fatal(err)
}

wg.Add(1)
err = cl.RequestIndicativeQuote("BTC_USD", big.NewRat(10000),
	func(iquote IndicativeQuoteResponse) {
		fmt.Printf(">>> Indicative quote: %+v", iquote)
		wg.Done()
	},
)
if err != nil {
	log.Fatal(err)
}
wg.Wait()
Output:

func (*Client) RequestSystemStatus

func (cl *Client) RequestSystemStatus(cb SystemStatusCallback) (err error)

RequestSystemStatus send the WebSocket request to get the system status.

On success, it will call the callback and pass the response as SystemStatusResponse.

Example
var wg sync.WaitGroup

cl, err := NewFromEnvironment()
if err != nil {
	log.Println(err)
}

wg.Add(1)
err = cl.RequestSystemStatus(func(ss SystemStatusResponse) {
	fmt.Printf("SystemStatus: %+v\n", ss)
	wg.Done()
})
if err != nil {
	log.Fatal(err)
}

wg.Wait()
//nolint: lll
Output:

func (*Client) RequestTradeHistory

func (cl *Client) RequestTradeHistory(num int, cb TradeHistoryCallback) (err error)

RequestTradeHistory request the trade history using WebSocket with maximum records set to `num`.

On success, it will call the callback and pass the TradeHistoryResponse.

Example
var wg sync.WaitGroup

cl, err := NewFromEnvironment()
if err != nil {
	log.Fatal(err)
}

wg.Add(1)
err = cl.RequestTradeHistory(2, func(tradeHistory TradeHistoryResponse) {
	fmt.Printf(">>> Trade history: %+v", tradeHistory)
	wg.Done()
})
if err != nil {
	log.Fatal(err)
}
wg.Wait()
Output:

func (*Client) SubscribeNotionalExposure

func (cl *Client) SubscribeNotionalExposure() (stream *StreamNotionalExposure, err error)

SubscribeNotionalExposure start streaming the NotionalExposure, the absolute aggregate of Unsettled Position, expressed in USD.

Exposure will be netted within trades of the same coin, but additive across coins. Upon settlement, the value will reset to zero.

The fiat currency and stable coin elements of Unsettled Position do not count towards Notional Exposure.

Example
cl, err := NewFromEnvironment()
if err != nil {
	log.Fatal(err)
}

stream, err := cl.SubscribeNotionalExposure()
if err != nil {
	log.Fatal(err)
}

data, ok := <-stream.NotionalExposure
if ok {
	fmt.Printf(">>> NotionalExposure: %+v\n", data)
}

err = cl.UnsubscribeNotionalExposure(stream)
if err != nil {
	log.Fatal(err)
}

for ok {
	data, ok = <-stream.NotionalExposure
	if ok {
		fmt.Printf(">>> NotionalExposure: %+v\n", data)
	}
}
Output:

func (*Client) SubscribeQuote

func (cl *Client) SubscribeQuote(ticker string, quantity *big.Rat) (
	stream *StreamQuote, err error,
)

SubscribeQuote register specific ticker and amount on Cumberland to start streaming quotes.

On success, it will return the stream that can be used to read the latest quote and to unregister it later.

Example
cl, err := NewFromEnvironment()
if err != nil {
	log.Println(err)
	return
}

stream, err := cl.SubscribeQuote("BTC_USD", big.NewRat(1000))
if err != nil {
	log.Fatal(err)
}

quote, ok := <-stream.Quote
if ok {
	fmt.Printf(">>> Should receive quote:\n%+v\n", quote)
}

err = cl.UnsubscribeQuote(stream)
if err != nil {
	log.Fatal(err)
}

for ok {
	quote, ok = <-stream.Quote
	if ok {
		fmt.Printf(">>> Should receive close quote: %+v\n", quote)
	}
}
Output:

func (*Client) SubscribeReferenceData

func (cl *Client) SubscribeReferenceData() (stream *StreamReferenceData, err error)

SubscribeReferenceData register the Client to stream Cumberland's reference data.

Example
cl, err := NewFromEnvironment()
if err != nil {
	log.Println(err)
	return
}

stream, err := cl.SubscribeReferenceData()
if err != nil {
	log.Fatal(err)
}

refData, ok := <-stream.ReferenceData
if ok {
	fmt.Printf(">>> ReferenceData: %+v\n", refData)
}

err = cl.UnsubscribeReferenceData()
if err != nil {
	log.Fatal(err)
}

for ok {
	refData, ok = <-stream.ReferenceData
	if ok {
		fmt.Printf(">>> ReferenceData: %+v\n", refData)
	}
}
Output:

func (*Client) SubscribeUnsettledPosition

func (cl *Client) SubscribeUnsettledPosition() (stream *StreamUnsettledPosition, err error)

SubscribeUnsettledPosition start streaming the unsettled position data.

Example
cl, err := NewFromEnvironment()
if err != nil {
	log.Fatal(err)
}

stream, err := cl.SubscribeUnsettledPosition()
if err != nil {
	log.Fatal(err)
}

data, ok := <-stream.UnsettledPosition
if ok {
	fmt.Printf(">>> Unsettled position: %+v\n", data)
}

err = cl.UnsubscribeUnsettledPosition(stream)
if err != nil {
	log.Fatal(err)
}

for ok {
	data, ok = <-stream.UnsettledPosition
	if ok {
		fmt.Printf(">>> Unsettled position: %+v\n", data)
	}
}
Output:

func (*Client) TradeBuy

func (cl *Client) TradeBuy(
	quoteID IDWithVersion, quantity *Quantity, cb TradeCallback,
) (err error)

TradeBuy execute the buy order using the specific Quote's ID from the streaming Quote.

Optionally, a quantity may be specified in the trade request message. The quantity can be up to the full quantity of the initial streaming quote request but may not exceed it.

Making a trade request for the partial or total amount of the streaming quote will cause the streaming quote to be closed upon success.

func (*Client) TradeSell

func (cl *Client) TradeSell(
	quoteID IDWithVersion, quantity *Quantity, cb TradeCallback,
) (err error)

TradeSell execute the sell order using the specific Quote's ID from the streaming Quote.

Optionally, a quantity may be specified in the trade request message. The quantity can be up to the full quantity of the initial streaming quote request but may not exceed it.

Making a trade request for the partial or total amount of the streaming quote will cause the streaming quote to be closed upon success.

func (*Client) UnsubscribeNotionalExposure

func (cl *Client) UnsubscribeNotionalExposure(stream *StreamNotionalExposure) (err error)

UnsubscribeNotionalExposure stop streaming the NotionalExposure data.

func (*Client) UnsubscribeQuote

func (cl *Client) UnsubscribeQuote(stream *StreamQuote) (err error)

UnsubscribeQuote stop streaming quotes on specific registration ID.

func (*Client) UnsubscribeReferenceData

func (cl *Client) UnsubscribeReferenceData() (err error)

UnsubscribeReferenceData stop streaming ReferenceData from the WebSocket connection.

func (*Client) UnsubscribeUnsettledPosition

func (cl *Client) UnsubscribeUnsettledPosition(stream *StreamUnsettledPosition) (err error)

type ClosingQuoteRequest

type ClosingQuoteRequest struct {
	Message

	Ticker   string `json:"ticker"`
	Notional Amount `json:"notional"`
	Date     string `json:"date"`
	Time     string `json:"time"`
	TimeZone string `json:"timeZone"`
}

ClosingQuoteRequest define the required parameters for calling GetClosingQuote.

type ClosingQuoteResponse

type ClosingQuoteResponse struct {
	Response

	ID      IDWithVersion       `json:"closingQuoteResponseId"`
	Request ClosingQuoteRequest `json:"closingQuoteRequest"`

	Status   string `json:"status"`
	Ticker   string `json:"ticker"`
	Notional Amount `json:"notional"`
	Date     string `json:"date"`
	TimeZone string `json:"timeZone"`

	BuyUnitPrice  UnitPrice `json:"buyUnitPrice"`
	SellUnitPrice UnitPrice `json:"sellUnitPrice"`
}

ClosingQuoteResponse contains the data returned from GetClosingQuote request.

type ErrorResponse

type ErrorResponse Response

ErrorResponse message is returned for the following scenarios:

  • An exception has occurred in the system
  • The system is unavailable
  • The maximum number of connections has been exceeded
  • A close request was unable to be processed
  • An unsupported HTTP method was used in a request
  • A message was sent that does not conform to the schema

Message type: ERROR_RESPONSE

Reference: https://apidocs.cumberland.io/#error-response

type ExternalIdentity

type ExternalIdentity struct {
	UserID         string `json:"userId"`
	CounterpartyID string `json:"counterpartyId,omitempty"`
}

ExternalIdentity is your account's API identity in Cumberland.

type IDWithVersion

type IDWithVersion struct {
	ID      string `json:"id"`
	Version int    `json:"version"`
}

type IndicativeQuoteCallback

type IndicativeQuoteCallback func(iquote IndicativeQuoteResponse)

type IndicativeQuoteResponse

type IndicativeQuoteResponse struct {
	Response

	ID            IDWithVersion `json:"indicativeQuoteResponseId"`
	Reason        string        `json:"reason"`
	Ticker        string        `json:"ticker"`
	Notional      Amount        `json:"notional"`
	CreationTime  int64         `json:"creationTime"`
	Status        string        `json:"status"`
	BuyUnitPrice  UnitPrice     `json:"buyUnitPrice"`
	SellUnitPrice UnitPrice     `json:"sellUnitPrice"`

	Request Message `json:"indicativeQuoteRequest"`
}

Message type: INDICATIVE_QUOTE_RESPONSE

Reference: https://apidocs.cumberland.io/#indicative-quote-response

type Message

type Message struct {
	Type                  string `json:"messageType"`
	CounterpartyID        string `json:"counterpartyId,omitempty"`
	CounterpartyRequestID string `json:"counterpartyRequestId,omitempty"`
}

Message is generic type that contains common field and request and response. Message can be used to get the message type before we can unpack it to more specific response type.

type NotionalExposureResponse

type NotionalExposureResponse struct {
	Response

	ID               IDWithVersion `json:"notionalExposureResponseId"`
	Reason           string        `json:"reason,omitempty"`
	CreationTime     int64         `json:"creationTime"`
	Status           string        `json:"status"`
	NotionalExposure Amount        `json:"notionalExposure"`
	Limit            Amount        `json:"notionalExposureLimit"`
}

Message type: NOTIONAL_EXPOSURE_RESPONSE

Reference: https://apidocs.cumberland.io/#notional-exposure-response

type Quantity

type Quantity struct {
	Quantity *big.Rat `json:"quantity"`
	Currency string   `json:"currency"`
}

type ReferenceData

type ReferenceData struct {
	AvailableCurrencies []string      `json:"availableCurrencies"`
	AvailableTickers    []*TickerData `json:"availableTickers"`
}

ReferenceData contains available currencies and tickers.

func (*ReferenceData) GetTicker

func (ref *ReferenceData) GetTicker(id string) (ticker *TickerData)

GetTicker by ID.

type RequestTypes

type RequestTypes struct {
	ClosingQuoteRequest           string `json:"CLOSING_QUOTE_REQUEST"`
	IndicativeQuoteRequest        string `json:"INDICATIVE_QUOTE_REQUEST"`
	MarketSummaryCloseRequest     string `json:"MARKET_SUMMARY_CLOSE_REQUEST"`
	MarketSummaryRequest          string `json:"MARKET_SUMMARY_REQUEST"`
	NotionalExposureCloseRequest  string `json:"NOTIONAL_EXPOSURE_CLOSE_REQUEST"`
	NotionalExposureRequest       string `json:"NOTIONAL_EXPOSURE_REQUEST"`
	ReferenceDataCloseRequest     string `json:"REFERENCE_DATA_CLOSE_REQUEST"`
	ReferenceDataRequest          string `json:"REFERENCE_DATA_REQUEST"`
	StreamingQuoteCloseRequest    string `json:"STREAMING_QUOTE_CLOSE_REQUEST"`
	StreamingQuoteRequest         string `json:"STREAMING_QUOTE_REQUEST"`
	SystemStatusRequest           string `json:"SYSTEM_STATUS_REQUEST"`
	TradeHistoryRequest           string `json:"TRADE_HISTORY_REQUEST"`
	TradeRequest                  string `json:"TRADE_REQUEST"`
	UnsettledPositionCloseRequest string `json:"UNSETTLED_POSITION_CLOSE_REQUEST"`
	UnsettledPositionRequest      string `json:"UNSETTLED_POSITION_REQUEST"`
	WatchlistCloseRequest         string `json:"WATCHLIST_CLOSE_REQUEST"`
	WatchlistRequest              string `json:"WATCHLIST_REQUEST"`
}

RequestTypes contains status of system per end-points.

type Response

type Response struct {
	Message

	ErrorMessage string `json:"errorMessage"`
}

Response is generic type that wrap the Message and error message.

type StreamNotionalExposure

type StreamNotionalExposure struct {
	NotionalExposure <-chan NotionalExposureResponse
	// contains filtered or unexported fields
}

StreamNotionalExposure contains read-only channel that receive an up-to-date notional exposure data.

type StreamQuote

type StreamQuote struct {
	Quote <-chan StreamingQuoteResponse

	sync.Mutex
	// contains filtered or unexported fields
}

StreamQuote contains read-only channel that receive an up-to-date quote data.

type StreamReferenceData

type StreamReferenceData struct {
	ReferenceData <-chan ReferenceData
	// contains filtered or unexported fields
}

StreamReferenceData contains read-only channel that receive an up-to-date reference data.

type StreamUnsettledPosition

type StreamUnsettledPosition struct {
	UnsettledPosition <-chan UnsettledPositionResponse
	// contains filtered or unexported fields
}

StreamUnsettledPosition contains read-only channel that receive an up-to-date unsettled position.

type StreamingQuoteResponse

type StreamingQuoteResponse struct {
	Response

	ID               IDWithVersion    `json:"quoteResponseId"`
	ExternalIdentity ExternalIdentity `json:"externalIdentity,omitempty"`
	Reason           string           `json:"reason,omitempty"`

	CreationTime int64  `json:"creationTime"`
	TTL          int64  `json:"timeToLive"`
	ExpireTime   int64  `json:"expireTime"`
	Status       string `json:"status"`

	BuyQuantity    Quantity  `json:"buyQuantity"`
	BuyUnitPrice   UnitPrice `json:"buyUnitPrice"`
	BuyTotalAmount Amount    `json:"butTotalAmount"`

	SellQuantity    Quantity  `json:"sellQuantity"`
	SellUnitPrice   UnitPrice `json:"sellUnitPrice"`
	SellTotalAmount Amount    `json:"sellTotalAmount"`

	Request Message `json:"quoteRequest"`
}

Message type: STREAMING_QUOTE_RESPONSE

Reference: https://apidocs.cumberland.io/#streaming-quote-response

type SystemStatusCallback

type SystemStatusCallback func(systemStatus SystemStatusResponse)

type SystemStatusResponse

type SystemStatusResponse struct {
	Response

	Reason       string       `json:"reason,omitempty"`
	SystemStatus string       `json:"systemStatus"`
	RequestTypes RequestTypes `json:"requestTypes"`
}

Message type: SYSTEM_STATUS_RESPONSE

Reference: https://apidocs.cumberland.io/#system-status-response

type TickerData

type TickerData struct {
	ID             string `json:"id"`
	Base           string `json:"base"`
	Counter        string `json:"counter"`
	PriceScale     int    `json:"priceScale"`
	QuantityScale  int    `json:"quantityScale"`
	AmountScale    int    `json:"amountScale"`
	BigNumberStart int    `json:"bigNumberStart"`
	BigNumberWidth int    `json:"bigNumberWidth"`
	Status         string `json:"string"`
}

type TimeResponse

type TimeResponse struct {
	Response

	Time int64 `json:"time"`
}

Message type: TIME_RESPONSE

Reference: https://apidocs.cumberland.io/#time-response

type TradeCallback

type TradeCallback func(tradeResponse TradeResponse)

type TradeHistoryCallback

type TradeHistoryCallback func(tradeHistory TradeHistoryResponse)

type TradeHistoryResponse

type TradeHistoryResponse struct {
	Response

	ID               IDWithVersion    `json:"tradeHistoryResponseId"`
	ExternalIdentity ExternalIdentity `json:"externalIdentity"`
	HistoricalTrades []TradeResponse  `json:"historicalTrades"`
	Reason           string           `json:"reason"`
}

Message type: TRADE_HISTORY_RESPONSE

Reference: https://apidocs.cumberland.io/#trade-history-response

type TradeRequest

type TradeRequest struct {
	Message

	CounterpartyAction string           `json:"counterpartyAction"`
	QuoteResponseID    IDWithVersion    `json:"quoteResponseId"`
	ExternalIdentity   ExternalIdentity `json:"externalIdentity"`
	Quantity           *Quantity        `json:"quantity,omitempty"`
}

Message type: TRADE_REQUEST

Reference: https://apidocs.cumberland.io/#trade-request

type TradeResponse

type TradeResponse struct {
	Response

	ID                 IDWithVersion `json:"tradeResponseId"`
	CounterpartyAction string        `json:"counterpartyAction"`
	Request            TradeRequest  `json:"tradeRequest"`
	TradeTime          int64         `json:"tradeTime"`
	Status             string        `json:"status"`
	Quantity           Quantity      `json:"quantity"`
	UnitPrice          UnitPrice     `json:"unitPrice"`
	TotalAmount        Amount        `json:"totalAmount"`

	TradeID          string                 `json:"tradeId,omitempty"`
	Reason           string                 `json:"reason,omitempty"`
	ExternalIdentity ExternalIdentity       `json:"externalIdentity,omitempty"`
	QuoteResponse    StreamingQuoteResponse `json:"quoteResponse,omitempty"`
}

Message type: TRADE_RESPONSE

Reference: https://apidocs.cumberland.io/#trade-response

type UnitPrice

type UnitPrice struct {
	Price    *big.Rat `json:"price"`
	Ticker   string   `json:"ticker"`
	Currency string   `json:"currency"`
}

type UnsettledPositionResponse

type UnsettledPositionResponse struct {
	Response

	ID                 IDWithVersion `json:"unsettledPositionResponseId"`
	Reason             string        `json:"reason"`
	CreationTime       int64         `json:"creationTime"`
	Status             string        `json:"status"`
	UnsettledPositions []Quantity    `json:"unsettledPositions"`
}

Message type: UNSETTLED_POSITION_RESPONSE

Reference: https://apidocs.cumberland.io/#unsettled-position-response

Jump to

Keyboard shortcuts

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