Bitmex exchange (#160)

* Added REST support for Bitmex

* Added Bitmex documentation updates

* Update config_example.json

* Added final REST functions for user account operations.

* Added initial websocket support

* Change function access
Added reconnection logic

* Added initial routine management
Updated wrapper functions

* General fixes
This commit is contained in:
Ryan O'Hara-Reid
2018-08-09 16:31:29 +10:00
committed by Adrian Gallagher
parent a0de1b78a7
commit 06a0caec43
17 changed files with 10245 additions and 6 deletions

View File

@@ -24,6 +24,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
| Bitfinex | Yes | Yes | NA |
| Bitflyer | Yes | No | NA |
| Bithumb | Yes | NA | NA |
| BitMEX | Yes | No | NA |
| Bitstamp | Yes | Yes | No |
| Bittrex | Yes | No | NA |
| BTCC | Yes | Yes | No |
@@ -175,6 +176,3 @@ Binaries will be published once the codebase reaches a stable condition.
| askew- | https://github.com/askew- | 1 |
| whilei | https://github.com/whilei | 1 |
| snipesjr | https://github.com/snipesjr | 1 |

View File

@@ -206,7 +206,7 @@ func TestGetEnabledExchanges(t *testing.T) {
}
exchanges := cfg.GetEnabledExchanges()
if len(exchanges) != 29 {
if len(exchanges) != 30 {
t.Error(
"Test failed. TestGetEnabledExchanges. Enabled exchanges value mismatch",
)
@@ -258,7 +258,7 @@ func TestGetDisabledExchanges(t *testing.T) {
}
func TestCountEnabledExchanges(t *testing.T) {
defaultEnabledExchanges := 29
defaultEnabledExchanges := 30
GetConfigEnabledExchanges := GetConfig()
err := GetConfigEnabledExchanges.LoadConfig(ConfigTestFile)
if err != nil {

View File

@@ -307,6 +307,40 @@
}
]
},
{
"Name": "Bitmex",
"Enabled": true,
"Verbose": false,
"Websocket": false,
"UseSandbox": false,
"RESTPollingDelay": 10,
"HTTPTimeout": 15000000000,
"AuthenticatedAPISupport": false,
"APIKey": "Key",
"APISecret": "Secret",
"AvailablePairs": "XRPXBT",
"EnabledPairs": "XRPXBT",
"BaseCurrencies": "USD",
"AssetTypes": "SPOT",
"SupportsAutoPairUpdates": false,
"ConfigCurrencyPairFormat": {
"Uppercase": true
},
"RequestCurrencyPairFormat": {
"Uppercase": true
},
"BankAccounts": [
{
"BankName": "",
"BankAddress": "",
"AccountName": "",
"AccountNumber": "",
"SWIFTCode": "",
"IBAN": "",
"SupportedCurrencies": ""
}
]
},
{
"name": "Bitstamp",
"enabled": true,
@@ -1202,4 +1236,4 @@
"supportedExchanges": "ANX,Kraken"
}
]
}
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/thrasher-/gocryptotrader/exchanges/bitfinex"
"github.com/thrasher-/gocryptotrader/exchanges/bitflyer"
"github.com/thrasher-/gocryptotrader/exchanges/bithumb"
"github.com/thrasher-/gocryptotrader/exchanges/bitmex"
"github.com/thrasher-/gocryptotrader/exchanges/bitstamp"
"github.com/thrasher-/gocryptotrader/exchanges/bittrex"
"github.com/thrasher-/gocryptotrader/exchanges/btcc"
@@ -145,6 +146,8 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error {
exch = new(bitflyer.Bitflyer)
case "bithumb":
exch = new(bithumb.Bithumb)
case "bitmex":
exch = new(bitmex.Bitmex)
case "bitstamp":
exch = new(bitstamp.Bitstamp)
case "bittrex":

133
exchanges/bitmex/README.md Normal file
View File

@@ -0,0 +1,133 @@
# GoCryptoTrader package Bitmex
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bitmex)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
This bitmex package is part of the GoCryptoTrader codebase.
## This is still in active development
You can track ideas, planned features and what's in progresss on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader).
Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://gocryptotrader.herokuapp.com/)
## Bithumb Exchange
### Current Features
+ REST Support
### How to enable
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
+ Individual package example below:
```go
// Exchanges will be abstracted out in further updates and examples will be
// supplied then
```
### How to do REST public/private calls
+ If enabled via "configuration".json file the exchange will be added to the
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
the wrapper interface functions for accessing exchange data. View routines.go
for an example of integration usage with GoCryptoTrader. Rudimentary example
below:
main.go
```go
var b exchange.IBotExchange
for i := range bot.exchanges {
if bot.exchanges[i].GetName() == "Bitmex" {
b = bot.exchanges[i]
}
}
// Public calls - wrapper functions
// Fetches current ticker information
tick, err := b.GetTickerPrice()
if err != nil {
// Handle error
}
// Fetches current orderbook information
ob, err := b.GetOrderbookEx()
if err != nil {
// Handle error
}
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
// set and AuthenticatedAPISupport is set to true
// Fetches current account information
accountInfo, err := b.GetExchangeAccountInfo()
if err != nil {
// Handle error
}
```
+ If enabled via individually importing package, rudimentary example below:
```go
// Public calls
// Fetches current ticker information
ticker, err := b.GetTicker()
if err != nil {
// Handle error
}
// Fetches current orderbook information
ob, err := b.GetOrderBook()
if err != nil {
// Handle error
}
// Private calls - make sure your APIKEY and APISECRET are set and
// AuthenticatedAPISupport is set to true
// GetUserInfo returns account info
accountInfo, err := b.GetUserInfo(...)
if err != nil {
// Handle error
}
// Submits an order and the exchange and returns its tradeID
tradeID, err := b.Trade(...)
if err != nil {
// Handle error
}
```
### Please click GoDocs chevron above to view current GoDoc information for this package
## Contribution
Please feel free to submit any pull requests or suggest any desired features to be added.
When submitting a PR, please abide by our coding guidelines:
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
+ Pull requests need to be based on and opened against the `master` branch.
## Donations
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
***1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB***

893
exchanges/bitmex/bitmex.go Normal file
View File

@@ -0,0 +1,893 @@
package bitmex
import (
"bytes"
"encoding/json"
"fmt"
"log"
"strconv"
"time"
"github.com/gorilla/websocket"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/request"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
)
// Bitmex is the overarching type across this package
type Bitmex struct {
exchange.Base
WebsocketConn *websocket.Conn
shutdown *Shutdown
}
const (
bitmexAPIVersion = "v1"
bitmexAPIURL = "https://www.bitmex.com/api/v1"
bitmexAPItestnetURL = "https://testnet.bitmex.com/api/v1"
// Public endpoints
bitmexEndpointAnnouncement = "/announcement"
bitmexEndpointAnnouncementUrgent = "/announcement/urgent"
bitmexEndpointOrderbookL2 = "/orderBook/L2"
bitmexEndpointTrollbox = "/chat"
bitmexEndpointTrollboxChannels = "/chat/channels"
bitmexEndpointTrollboxConnected = "/chat/connected"
bitmexEndpointFundingHistory = "/funding"
bitmexEndpointInstruments = "/instrument"
bitmexEndpointActiveInstruments = "/instrument/active"
bitmexEndpointActiveAndIndexInstruments = "/instrument/activeAndIndices"
bitmexEndpointActiveIntervals = "/instrument/activeIntervals"
bitmexEndpointCompositeIndex = "/instrument/compositeIndex"
bitmexEndpointIndices = "/instrument/indices"
bitmexEndpointInsuranceHistory = "/insurance"
bitmexEndpointLiquidation = "/liquidation"
bitmexEndpointLeader = "/leaderboard"
bitmexEndpointAlias = "/leaderboard/name"
bitmexEndpointQuote = "/quote"
bitmexEndpointQuoteBucketed = "/quote/bucketed"
bitmexEndpointSettlement = "/settlement"
bitmexEndpointStats = "/stats"
bitmexEndpointStatsHistory = "/stats/history"
bitmexEndpointStatsSummary = "/stats/historyUSD"
bitmexEndpointTrade = "/trade"
bitmexEndpointTradeBucketed = "/trade/bucketed"
bitmexEndpointUserCheckReferralCode = "/user/checkReferralCode"
bitmexEndpointUserMinWithdrawalFee = "/user/minWithdrawalFee"
// Authenticated endpoints
bitmexEndpointAPIkeys = "/apiKey"
bitmexEndpointDisableAPIkey = "/apiKey/disable"
bitmexEndpointEnableAPIkey = "/apiKey/enable"
bitmexEndpointTrollboxSend = "/chat"
bitmexEndpointExecution = "/execution"
bitmexEndpointExecutionTradeHistory = "/execution/tradeHistory"
bitmexEndpointNotifications = "/notification"
bitmexEndpointOrder = "/order"
bitmexEndpointCancelAllOrders = "/order/all"
bitmexEndpointBulk = "/order/bulk"
bitmexEndpointCancelOrderAfter = "/order/cancelAllAfter"
bitmexEndpointClosePosition = "/order/closePosition"
bitmexEndpointPosition = "/position"
bitmexEndpointIsolatePosition = "/position/isolate"
bitmexEndpointLeveragePosition = "/position/leverage"
bitmexEndpointAdjustRiskLimit = "/position/riskLimit"
bitmexEndpointTransferMargin = "/position/transferMargin"
bitmexEndpointUser = "/user"
bitmexEndpointUserAffiliate = "/user/affiliateStatus"
bitmexEndpointUserCancelWithdraw = "/user/cancelWithdrawal"
bitmexEndpointUserCommision = "/user/commission"
bitmexEndpointUserConfirmEmail = "/user/confirmEmail"
bitmexEndpointUserConfirmTFA = "/user/confirmEnableTFA"
bitmexEndpointUserConfirmWithdrawal = "/user/confirmWithdrawal"
bitmexEndpointUserDepositAddress = "/user/depositAddress"
bitmexEndpointUserDisableTFA = "/user/disableTFA"
bitmexEndpointUserLogout = "/user/logout"
bitmexEndpointUserLogoutAll = "/user/logoutAll"
bitmexEndpointUserMargin = "/user/margin"
bitmexEndpointUserPreferences = "/user/preferences"
bitmexEndpointUserRequestTFA = "/user/requestEnableTFA"
bitmexEndpointUserWallet = "/user/wallet"
bitmexEndpointUserWalletHistory = "/user/walletHistory"
bitmexEndpointUserWalletSummary = "/user/walletSummary"
bitmexEndpointUserRequestWithdraw = "/user/requestWithdrawal"
// Rate limits - 150 requests per 5 minutes
bitmexUnauthRate = 30
// 300 requests per 5 minutes
bitmexAuthRate = 40
// ContractPerpetual perpetual contract type
ContractPerpetual = iota
// ContractFutures futures contract type
ContractFutures
// ContractDownsideProfit downside profit contract type
ContractDownsideProfit
// ContractUpsideProfit upside profit contract type
ContractUpsideProfit
)
// SetDefaults sets the basic defaults for Bitmex
func (b *Bitmex) SetDefaults() {
b.Name = "Bitmex"
b.Enabled = false
b.Verbose = false
b.Websocket = false
b.RESTPollingDelay = 10
b.RequestCurrencyPairFormat.Delimiter = ""
b.RequestCurrencyPairFormat.Uppercase = true
b.ConfigCurrencyPairFormat.Delimiter = ""
b.ConfigCurrencyPairFormat.Uppercase = true
b.AssetTypes = []string{ticker.Spot}
b.Requester = request.New(b.Name,
request.NewRateLimit(time.Second, bitmexAuthRate),
request.NewRateLimit(time.Second, bitmexUnauthRate),
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
b.shutdown = b.NewRoutineManagement()
}
// Setup takes in the supplied exchange configuration details and sets params
func (b *Bitmex) Setup(exch config.ExchangeConfig) {
if !exch.Enabled {
b.SetEnabled(false)
} else {
b.Enabled = true
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
b.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
b.RESTPollingDelay = exch.RESTPollingDelay
b.Verbose = exch.Verbose
b.Websocket = exch.Websocket
b.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
b.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
b.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
err := b.SetCurrencyPairFormat()
if err != nil {
log.Fatal(err)
}
err = b.SetAssetTypes()
if err != nil {
log.Fatal(err)
}
}
}
// GetAnnouncement returns the general announcements from Bitmex
func (b *Bitmex) GetAnnouncement() ([]Announcement, error) {
var announcement []Announcement
return announcement, b.SendHTTPRequest(bitmexEndpointAnnouncement,
nil,
&announcement)
}
// GetUrgentAnnouncement returns an urgent announcement for your account
func (b *Bitmex) GetUrgentAnnouncement() ([]Announcement, error) {
var announcement []Announcement
return announcement, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointAnnouncementUrgent,
nil,
&announcement)
}
// GetAPIKeys returns the APIkeys from bitmex
func (b *Bitmex) GetAPIKeys() ([]APIKey, error) {
var keys []APIKey
return keys, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointAPIkeys,
nil,
&keys)
}
// RemoveAPIKey removes an Apikey from the bitmex trading engine
func (b *Bitmex) RemoveAPIKey(params APIKeyParams) (bool, error) {
var keyDeleted bool
return keyDeleted, b.SendAuthenticatedHTTPRequest("DELETE",
bitmexEndpointAPIkeys,
params,
&keyDeleted)
}
// DisableAPIKey disables an Apikey from the bitmex trading engine
func (b *Bitmex) DisableAPIKey(params APIKeyParams) (APIKey, error) {
var keyInfo APIKey
return keyInfo, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointDisableAPIkey,
params,
&keyInfo)
}
// EnableAPIKey enables an Apikey from the bitmex trading engine
func (b *Bitmex) EnableAPIKey(params APIKeyParams) (APIKey, error) {
var keyInfo APIKey
return keyInfo, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointEnableAPIkey,
params,
&keyInfo)
}
// GetTrollboxMessages returns messages from the bitmex trollbox
func (b *Bitmex) GetTrollboxMessages(params ChatGetParams) ([]Chat, error) {
var messages []Chat
return messages, b.SendHTTPRequest(bitmexEndpointTrollbox, params, &messages)
}
// SendTrollboxMessage sends a message to the bitmex trollbox
func (b *Bitmex) SendTrollboxMessage(params ChatSendParams) ([]Chat, error) {
var messages []Chat
return messages, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointTrollboxSend,
params,
&messages)
}
// GetTrollboxChannels the channels from the the bitmex trollbox
func (b *Bitmex) GetTrollboxChannels() ([]ChatChannel, error) {
var channels []ChatChannel
return channels, b.SendHTTPRequest(bitmexEndpointTrollboxChannels,
nil,
&channels)
}
// GetTrollboxConnectedUsers the channels from the the bitmex trollbox
func (b *Bitmex) GetTrollboxConnectedUsers() (ConnectedUsers, error) {
var users ConnectedUsers
return users, b.SendHTTPRequest(bitmexEndpointTrollboxConnected, nil, &users)
}
// GetAccountExecutions returns all raw transactions, which includes order
// opening and cancelation, and order status changes. It can be quite noisy.
// More focused information is available at /execution/tradeHistory.
func (b *Bitmex) GetAccountExecutions(params GenericRequestParams) ([]Execution, error) {
var executionList []Execution
return executionList, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointExecution,
params,
&executionList)
}
// GetAccountExecutionTradeHistory returns all balance-affecting executions.
// This includes each trade, insurance charge, and settlement.
func (b *Bitmex) GetAccountExecutionTradeHistory(params GenericRequestParams) ([]Execution, error) {
var tradeHistory []Execution
return tradeHistory, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointExecutionTradeHistory,
params,
&tradeHistory)
}
// GetFundingHistory returns funding history
func (b *Bitmex) GetFundingHistory() ([]Funding, error) {
var fundingHistory []Funding
return fundingHistory, b.SendHTTPRequest(bitmexEndpointFundingHistory,
nil,
&fundingHistory)
}
// GetInstruments returns instrument data
func (b *Bitmex) GetInstruments(params GenericRequestParams) ([]Instrument, error) {
var instruments []Instrument
return instruments, b.SendHTTPRequest(bitmexEndpointInstruments,
params,
&instruments)
}
// GetActiveInstruments returns active instruments
func (b *Bitmex) GetActiveInstruments(params GenericRequestParams) ([]Instrument, error) {
var activeInstruments []Instrument
return activeInstruments, b.SendHTTPRequest(bitmexEndpointActiveInstruments,
params,
&activeInstruments)
}
// GetActiveAndIndexInstruments returns all active instruments and all indices
func (b *Bitmex) GetActiveAndIndexInstruments() ([]Instrument, error) {
var activeAndIndices []Instrument
return activeAndIndices,
b.SendHTTPRequest(bitmexEndpointActiveAndIndexInstruments,
nil,
&activeAndIndices)
}
// GetActiveIntervals returns funding history
func (b *Bitmex) GetActiveIntervals() (InstrumentInterval, error) {
var interval InstrumentInterval
return interval, b.SendHTTPRequest(bitmexEndpointActiveIntervals,
nil,
&interval)
}
// GetCompositeIndex returns composite index
func (b *Bitmex) GetCompositeIndex(params GenericRequestParams) ([]IndexComposite, error) {
var compositeIndices []IndexComposite
return compositeIndices, b.SendHTTPRequest(bitmexEndpointCompositeIndex,
params,
&compositeIndices)
}
// GetIndices returns all price indices
func (b *Bitmex) GetIndices() ([]Instrument, error) {
var indices []Instrument
return indices, b.SendHTTPRequest(bitmexEndpointIndices, nil, &indices)
}
// GetInsuranceFundHistory returns insurance fund history
func (b *Bitmex) GetInsuranceFundHistory(params GenericRequestParams) ([]Insurance, error) {
var history []Insurance
return history, b.SendHTTPRequest(bitmexEndpointIndices, params, &history)
}
// GetLeaderboard returns leaderboard information
func (b *Bitmex) GetLeaderboard(params LeaderboardGetParams) ([]Leaderboard, error) {
var leader []Leaderboard
return leader, b.SendHTTPRequest(bitmexEndpointLeader, params, &leader)
}
// GetAliasOnLeaderboard returns your alias on the leaderboard
func (b *Bitmex) GetAliasOnLeaderboard() (Alias, error) {
var alias Alias
return alias, b.SendHTTPRequest(bitmexEndpointAlias, nil, &alias)
}
// GetLiquidationOrders returns liquidation orders
func (b *Bitmex) GetLiquidationOrders(params GenericRequestParams) ([]Liquidation, error) {
var orders []Liquidation
return orders, b.SendHTTPRequest(bitmexEndpointLiquidation,
params,
&orders)
}
// GetCurrentNotifications returns your current notifications
func (b *Bitmex) GetCurrentNotifications() ([]Notification, error) {
var notifications []Notification
return notifications, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointNotifications,
nil,
&notifications)
}
// GetOrders returns all the orders, open and closed
func (b *Bitmex) GetOrders(params GenericRequestParams) ([]Order, error) {
var orders []Order
return orders, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointOrder,
params,
&orders)
}
// AmendOrder amends the quantity or price of an open order
func (b *Bitmex) AmendOrder(params OrderAmendParams) ([]Order, error) {
var orders []Order
return orders, b.SendAuthenticatedHTTPRequest("PUT",
bitmexEndpointOrder,
params,
&orders)
}
// CreateOrder creates a new order
func (b *Bitmex) CreateOrder(params OrderNewParams) (Order, error) {
var orderInfo Order
return orderInfo, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointOrder,
params,
&orderInfo)
}
// CancelOrders cancels one or a batch of orders on the exchange and returns
// a cancelled order list
func (b *Bitmex) CancelOrders(params OrderCancelParams) ([]Order, error) {
var cancelledOrders []Order
return cancelledOrders, b.SendAuthenticatedHTTPRequest("DELETE",
bitmexEndpointOrder,
params,
&cancelledOrders)
}
// CancelAllOrders cancels all open orders on the exchange
func (b *Bitmex) CancelAllOrders(params OrderCancelAllParams) ([]Order, error) {
var cancelledOrders []Order
return cancelledOrders, b.SendAuthenticatedHTTPRequest("DELETE",
bitmexEndpointCancelAllOrders,
params,
&cancelledOrders)
}
// AmendBulkOrders amends multiple orders for the same symbol
func (b *Bitmex) AmendBulkOrders(params OrderAmendBulkParams) ([]Order, error) {
var amendedOrders []Order
return amendedOrders, b.SendAuthenticatedHTTPRequest("PUT",
bitmexEndpointBulk,
params,
&amendedOrders)
}
// CreateBulkOrders creates multiple orders for the same symbol
func (b *Bitmex) CreateBulkOrders(params OrderNewBulkParams) ([]Order, error) {
var orders []Order
return orders, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointBulk,
params,
&orders)
}
// CancelAllOrdersAfterTime closes all positions after a certain time period
func (b *Bitmex) CancelAllOrdersAfterTime(params OrderCancelAllAfterParams) ([]Order, error) {
var cancelledOrder []Order
return cancelledOrder, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointCancelOrderAfter,
params,
&cancelledOrder)
}
// ClosePosition closes a position WARNING deprecated use /order endpoint
func (b *Bitmex) ClosePosition(params OrderClosePositionParams) ([]Order, error) {
var closedPositions []Order
return closedPositions, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointOrder,
params,
&closedPositions)
}
// GetOrderbook returns layer two orderbook data
func (b *Bitmex) GetOrderbook(params OrderBookGetL2Params) ([]OrderBookL2, error) {
var orderBooks []OrderBookL2
return orderBooks, b.SendHTTPRequest(bitmexEndpointOrderbookL2,
params,
&orderBooks)
}
// GetPositions returns positions
func (b *Bitmex) GetPositions(params PositionGetParams) ([]Position, error) {
var positions []Position
return positions, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointPosition,
params,
&positions)
}
// IsolatePosition enables isolated margin or cross margin per-position
func (b *Bitmex) IsolatePosition(params PositionIsolateMarginParams) (Position, error) {
var position Position
return position, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointIsolatePosition,
params,
&position)
}
// LeveragePosition chooses leverage for a position
func (b *Bitmex) LeveragePosition(params PositionUpdateLeverageParams) (Position, error) {
var position Position
return position, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointLeveragePosition,
params,
&position)
}
// UpdateRiskLimit updates risk limit on a position
func (b *Bitmex) UpdateRiskLimit(params PositionUpdateRiskLimitParams) (Position, error) {
var position Position
return position, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointAdjustRiskLimit,
params,
&position)
}
// TransferMargin transfers equity in or out of a position
func (b *Bitmex) TransferMargin(params PositionTransferIsolatedMarginParams) (Position, error) {
var position Position
return position, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointTransferMargin,
params,
&position)
}
// GetQuotes returns quotations
func (b *Bitmex) GetQuotes(params GenericRequestParams) ([]Quote, error) {
var quotations []Quote
return quotations, b.SendHTTPRequest(bitmexEndpointQuote,
params,
&quotations)
}
// GetQuotesByBuckets returns previous quotes in time buckets
func (b *Bitmex) GetQuotesByBuckets(params QuoteGetBucketedParams) ([]Quote, error) {
var quotations []Quote
return quotations, b.SendHTTPRequest(bitmexEndpointQuoteBucketed,
params,
&quotations)
}
// GetSettlementHistory returns settlement history
func (b *Bitmex) GetSettlementHistory(params GenericRequestParams) ([]Settlement, error) {
var history []Settlement
return history, b.SendHTTPRequest(bitmexEndpointSettlement,
params,
&history)
}
// GetStats returns exchange wide per series turnover and volume statistics
func (b *Bitmex) GetStats() ([]Stats, error) {
var stats []Stats
return stats, b.SendHTTPRequest(bitmexEndpointStats, nil, &stats)
}
// GetStatsHistorical historic stats
func (b *Bitmex) GetStatsHistorical() ([]StatsHistory, error) {
var history []StatsHistory
return history, b.SendHTTPRequest(bitmexEndpointStatsHistory, nil, &history)
}
// GetStatSummary returns the stats summary in USD terms
func (b *Bitmex) GetStatSummary() ([]StatsUSD, error) {
var summary []StatsUSD
return summary, b.SendHTTPRequest(bitmexEndpointStatsSummary, nil, &summary)
}
// GetTrade returns executed trades on the desk
func (b *Bitmex) GetTrade(params GenericRequestParams) ([]Trade, error) {
var trade []Trade
return trade, b.SendHTTPRequest(bitmexEndpointTrade, params, &trade)
}
// GetPreviousTrades previous trade history in time buckets
func (b *Bitmex) GetPreviousTrades(params TradeGetBucketedParams) ([]Trade, error) {
var trade []Trade
return trade, b.SendHTTPRequest(bitmexEndpointTradeBucketed,
params,
&trade)
}
// GetUserInfo returns your user information
func (b *Bitmex) GetUserInfo() (User, error) {
var userInfo User
return userInfo, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointUser,
nil,
&userInfo)
}
// UpdateUserInfo updates user information
func (b *Bitmex) UpdateUserInfo(params UserUpdateParams) (User, error) {
var userInfo User
return userInfo, b.SendAuthenticatedHTTPRequest("PUT",
bitmexEndpointUser,
params,
&userInfo)
}
// GetAffiliateStatus returns your affiliate status
func (b *Bitmex) GetAffiliateStatus() (AffiliateStatus, error) {
var status AffiliateStatus
return status, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointUserAffiliate,
nil,
&status)
}
// CancelWithdraw cancels a current withdrawal
func (b *Bitmex) CancelWithdraw(token string) (TransactionInfo, error) {
var info TransactionInfo
return info, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointUserCancelWithdraw,
UserTokenParams{Token: token},
&info)
}
// CheckReferalCode checks a code, will return a percentage eg 0.1 for 10% or
// if err a 404
func (b *Bitmex) CheckReferalCode(referralCode string) (float64, error) {
var percentage float64
return percentage, b.SendHTTPRequest(bitmexEndpointUserCheckReferralCode,
UserCheckReferralCodeParams{ReferralCode: referralCode},
&percentage)
}
// GetUserCommision returns your account's commission status.
func (b *Bitmex) GetUserCommision(token string) (UserCommission, error) {
var commissionInfo UserCommission
return commissionInfo, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointUserCommision,
nil,
&commissionInfo)
}
// ConfirmEmail confirms email address with a token
func (b *Bitmex) ConfirmEmail(token string) (ConfirmEmail, error) {
var confirmation ConfirmEmail
return confirmation, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointUserConfirmEmail,
UserTokenParams{Token: token},
&confirmation)
}
// ConfirmTwoFactorAuth confirmas 2FA for this account.
func (b *Bitmex) ConfirmTwoFactorAuth(token, typ string) (bool, error) {
var working bool
return working, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointUserConfirmTFA,
UserConfirmTFAParams{Token: token, Type: typ},
&working)
}
// ConfirmWithdrawal confirmas a withdrawal
func (b *Bitmex) ConfirmWithdrawal(token string) (TransactionInfo, error) {
var info TransactionInfo
return info, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointUserCancelWithdraw,
UserTokenParams{Token: token},
&info)
}
// GetDepositAddress returns a deposit address for a cryptocurency
func (b *Bitmex) GetDepositAddress(currency string) (string, error) {
var address string
return address, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointUserDepositAddress,
UserCurrencyParams{Currency: currency},
&address)
}
// DisableTFA dsiables 2 factor authentication for your account
func (b *Bitmex) DisableTFA(token, typ string) (bool, error) {
var disabled bool
return disabled, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointUserDisableTFA,
UserConfirmTFAParams{Token: token, Type: typ},
&disabled)
}
// UserLogOut logs you out of BitMEX
func (b *Bitmex) UserLogOut() error {
return b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointUserLogout,
nil,
nil)
}
// UserLogOutAll logs you out of all systems for BitMEX
func (b *Bitmex) UserLogOutAll() (int64, error) {
var status int64
return status, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointUserLogoutAll,
nil,
&status)
}
// GetUserMargin returns user margin information
func (b *Bitmex) GetUserMargin(currency string) (UserMargin, error) {
var info UserMargin
return info, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointUserMargin,
UserCurrencyParams{Currency: currency},
&info)
}
// GetMinimumWithdrawalFee returns minimum withdrawal fee information
func (b *Bitmex) GetMinimumWithdrawalFee(currency string) (MinWithdrawalFee, error) {
var fee MinWithdrawalFee
return fee, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointUserMinWithdrawalFee,
UserCurrencyParams{Currency: currency},
&fee)
}
// GetUserPreferences returns user preferences
func (b *Bitmex) GetUserPreferences(params UserPreferencesParams) (User, error) {
var userInfo User
return userInfo, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointUserPreferences,
params,
&userInfo)
}
// EnableTFA enables 2 factor authentication
func (b *Bitmex) EnableTFA(typ string) (bool, error) {
var enabled bool
return enabled, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointUserRequestTFA,
UserConfirmTFAParams{Type: typ},
&enabled)
}
// UserRequestWithdrawal This will send a confirmation email to the email
// address on record, unless requested via an API Key with the withdraw
// permission.
func (b *Bitmex) UserRequestWithdrawal(params UserRequestWithdrawalParams) (TransactionInfo, error) {
var info TransactionInfo
return info, b.SendAuthenticatedHTTPRequest("POST",
bitmexEndpointUserRequestWithdraw,
params,
&info)
}
// GetWalletInfo returns user wallet information
func (b *Bitmex) GetWalletInfo(currency string) (WalletInfo, error) {
var info WalletInfo
return info, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointUserWallet,
UserCurrencyParams{Currency: currency},
&info)
}
// GetWalletHistory returns user wallet history transaction data
func (b *Bitmex) GetWalletHistory(currency string) ([]TransactionInfo, error) {
var info []TransactionInfo
return info, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointUserWalletHistory,
UserCurrencyParams{Currency: currency},
&info)
}
// GetWalletSummary returns user wallet summary
func (b *Bitmex) GetWalletSummary(currency string) ([]TransactionInfo, error) {
var info []TransactionInfo
return info, b.SendAuthenticatedHTTPRequest("GET",
bitmexEndpointUserWalletSummary,
UserCurrencyParams{Currency: currency},
&info)
}
// SendHTTPRequest sends an unauthenticated HTTP request
func (b *Bitmex) SendHTTPRequest(path string, params Parameter, result interface{}) error {
var respCheck interface{}
path = bitmexAPIURL + path
if params != nil {
if !params.IsNil() {
encodedPath, err := params.ToURLVals(path)
if err != nil {
return err
}
err = b.SendPayload("GET", encodedPath, nil, nil, &respCheck, false, b.Verbose)
if err != nil {
return err
}
return b.CaptureError(respCheck, result)
}
}
err := b.SendPayload("GET", path, nil, nil, &respCheck, false, b.Verbose)
if err != nil {
return err
}
return b.CaptureError(respCheck, result)
}
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to bitmex
func (b *Bitmex) SendAuthenticatedHTTPRequest(verb, path string, params Parameter, result interface{}) error {
if !b.AuthenticatedAPISupport {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
b.Name)
}
timestamp := time.Now().Add(time.Second * 10).UnixNano()
timestampStr := strconv.FormatInt(timestamp, 10)
timestampNew := timestampStr[:13]
headers := make(map[string]string)
headers["Content-Type"] = "application/json"
headers["api-expires"] = timestampNew
headers["api-key"] = b.APIKey
var payload string
if params != nil {
err := params.VerifyData()
if err != nil {
return err
}
data, err := common.JSONEncode(params)
if err != nil {
return err
}
payload = string(data)
}
hmac := common.GetHMAC(common.HashSHA256,
[]byte(verb+"/api/v1"+path+timestampNew+payload),
[]byte(b.APISecret))
headers["api-signature"] = common.HexEncodeToString(hmac)
var respCheck interface{}
err := b.SendPayload(verb,
bitmexAPIURL+path,
headers,
bytes.NewBuffer([]byte(payload)),
&respCheck,
true,
b.Verbose)
if err != nil {
return err
}
return b.CaptureError(respCheck, result)
}
// CaptureError little hack that captures an error
func (b *Bitmex) CaptureError(resp, reType interface{}) error {
var Error RequestError
marshalled, err := json.Marshal(resp)
if err != nil {
return err
}
err = common.JSONDecode(marshalled, &Error)
if err == nil {
return fmt.Errorf("bitmex error %s: %s",
Error.Error.Name,
Error.Error.Message)
}
err = common.JSONDecode(marshalled, reType)
if err != nil {
return err
}
return nil
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,365 @@
package bitmex
import (
"sync"
"testing"
"time"
"github.com/thrasher-/gocryptotrader/config"
)
// Please supply your own keys here for due diligence testing
const (
testAPIKey = ""
testAPISecret = ""
)
var b Bitmex
func TestSetDefaults(t *testing.T) {
b.SetDefaults()
}
func TestSetup(t *testing.T) {
cfg := config.GetConfig()
cfg.LoadConfig("../../testdata/configtest.json")
bitmexConfig, err := cfg.GetExchangeConfig("Bitmex")
if err != nil {
t.Error("Test Failed - Bitmex Setup() init error")
}
bitmexConfig.AuthenticatedAPISupport = true
bitmexConfig.APIKey = testAPIKey
bitmexConfig.APISecret = testAPISecret
b.Setup(bitmexConfig)
}
func TestStart(t *testing.T) {
var testWg sync.WaitGroup
b.Start(&testWg)
testWg.Wait()
}
func TestGetUrgentAnnouncement(t *testing.T) {
_, err := b.GetUrgentAnnouncement()
if err == nil {
t.Error("test failed - GetUrgentAnnouncement() error", err)
}
}
func TestGetAPIKeys(t *testing.T) {
_, err := b.GetAPIKeys()
if err == nil {
t.Error("test failed - GetAPIKeys() error", err)
}
}
func TestRemoveAPIKey(t *testing.T) {
_, err := b.RemoveAPIKey(APIKeyParams{APIKeyID: "1337"})
if err == nil {
t.Error("test failed - RemoveAPIKey() error", err)
}
}
func TestDisableAPIKey(t *testing.T) {
_, err := b.DisableAPIKey(APIKeyParams{APIKeyID: "1337"})
if err == nil {
t.Error("test failed - DisableAPIKey() error", err)
}
}
func TestEnableAPIKey(t *testing.T) {
_, err := b.EnableAPIKey(APIKeyParams{APIKeyID: "1337"})
if err == nil {
t.Error("test failed - EnableAPIKey() error", err)
}
}
func TestGetTrollboxMessages(t *testing.T) {
_, err := b.GetTrollboxMessages(ChatGetParams{Count: 5})
if err != nil {
t.Error("test failed - GetTrollboxMessages() error", err)
}
}
func TestSendTrollboxMessage(t *testing.T) {
_, err := b.SendTrollboxMessage(ChatSendParams{
ChannelID: 1337,
Message: "Hello,World!"})
if err == nil {
t.Error("test failed - SendTrollboxMessage() error", err)
}
}
func TestGetTrollboxChannels(t *testing.T) {
_, err := b.GetTrollboxChannels()
if err != nil {
t.Error("test failed - GetTrollboxChannels() error", err)
}
}
func TestGetTrollboxConnectedUsers(t *testing.T) {
_, err := b.GetTrollboxConnectedUsers()
if err == nil {
t.Error("test failed - GetTrollboxConnectedUsers() error", err)
}
}
func TestGetAccountExecutions(t *testing.T) {
_, err := b.GetAccountExecutions(GenericRequestParams{})
if err == nil {
t.Error("test failed - GetAccountExecutions() error", err)
}
}
func TestGetAccountExecutionTradeHistory(t *testing.T) {
_, err := b.GetAccountExecutionTradeHistory(GenericRequestParams{})
if err == nil {
t.Error("test failed - GetAccountExecutionTradeHistory() error", err)
}
}
func TestGetFundingHistory(t *testing.T) {
_, err := b.GetFundingHistory()
if err != nil {
t.Error("test failed - GetFundingHistory() error", err)
}
}
func TestGetInstruments(t *testing.T) {
_, err := b.GetInstruments(GenericRequestParams{})
if err != nil {
t.Error("test failed - GetInstruments() error", err)
}
}
func TestGetActiveInstruments(t *testing.T) {
_, err := b.GetActiveInstruments(GenericRequestParams{})
if err != nil {
t.Error("test failed - GetActiveInstruments() error", err)
}
}
func TestGetActiveAndIndexInstruments(t *testing.T) {
_, err := b.GetActiveAndIndexInstruments()
if err != nil {
t.Error("test failed - GetActiveAndIndexInstruments() error", err)
}
}
func TestGetActiveIntervals(t *testing.T) {
_, err := b.GetActiveIntervals()
if err == nil {
t.Error("test failed - GetActiveIntervals() error", err)
}
}
func TestGetCompositeIndex(t *testing.T) {
_, err := b.GetCompositeIndex(GenericRequestParams{})
if err == nil {
t.Error("test failed - GetCompositeIndex() error", err)
}
}
func TestGetIndices(t *testing.T) {
_, err := b.GetIndices()
if err != nil {
t.Error("test failed - GetIndices() error", err)
}
}
func TestGetInsuranceFundHistory(t *testing.T) {
_, err := b.GetInsuranceFundHistory(GenericRequestParams{})
if err != nil {
t.Error("test failed - GetInsuranceFundHistory() error", err)
}
}
func TestGetLeaderboard(t *testing.T) {
_, err := b.GetLeaderboard(LeaderboardGetParams{})
if err != nil {
t.Error("test failed - GetLeaderboard() error", err)
}
}
func TestGetAliasOnLeaderboard(t *testing.T) {
_, err := b.GetAliasOnLeaderboard()
if err == nil {
t.Error("test failed - GetAliasOnLeaderboard() error", err)
}
}
func TestGetLiquidationOrders(t *testing.T) {
_, err := b.GetLiquidationOrders(GenericRequestParams{})
if err != nil {
t.Error("test failed - GetLiquidationOrders() error", err)
}
}
func TestGetCurrentNotifications(t *testing.T) {
_, err := b.GetCurrentNotifications()
if err == nil {
t.Error("test failed - GetCurrentNotifications() error", err)
}
}
func TestGetOrders(t *testing.T) {
_, err := b.GetOrders(GenericRequestParams{})
if err == nil {
t.Error("test failed - GetOrders() error", err)
}
}
func TestAmendOrder(t *testing.T) {
_, err := b.AmendOrder(OrderAmendParams{})
if err == nil {
t.Error("test failed - AmendOrder() error", err)
}
}
func TestCreateOrder(t *testing.T) {
_, err := b.CreateOrder(OrderNewParams{Symbol: "XBTM15",
Price: 219.0,
ClOrdID: "mm_bitmex_1a/oemUeQ4CAJZgP3fjHsA",
OrderQty: 98})
if err == nil {
t.Error("test failed - CreateOrder() error", err)
}
}
func TestCancelOrders(t *testing.T) {
_, err := b.CancelOrders(OrderCancelParams{})
if err == nil {
t.Error("test failed - CancelOrders() error", err)
}
}
func TestCancelAllOrders(t *testing.T) {
_, err := b.CancelAllOrders(OrderCancelAllParams{})
if err == nil {
t.Error("test failed - CancelAllOrders() error", err)
}
}
func TestAmendBulkOrders(t *testing.T) {
_, err := b.AmendBulkOrders(OrderAmendBulkParams{})
if err == nil {
t.Error("test failed - AmendBulkOrders() error", err)
}
}
func TestCreateBulkOrders(t *testing.T) {
_, err := b.CreateBulkOrders(OrderNewBulkParams{})
if err == nil {
t.Error("test failed - CreateBulkOrders() error", err)
}
}
func TestCancelAllOrdersAfterTime(t *testing.T) {
_, err := b.CancelAllOrdersAfterTime(OrderCancelAllAfterParams{})
if err == nil {
t.Error("test failed - CancelAllOrdersAfterTime() error", err)
}
}
func TestClosePosition(t *testing.T) {
_, err := b.ClosePosition(OrderClosePositionParams{})
if err == nil {
t.Error("test failed - ClosePosition() error", err)
}
}
func TestGetOrderbook(t *testing.T) {
_, err := b.GetOrderbook(OrderBookGetL2Params{Symbol: "XBT"})
if err != nil {
t.Error("test failed - GetOrderbook() error", err)
}
}
func TestGetPositions(t *testing.T) {
_, err := b.GetPositions(PositionGetParams{})
if err == nil {
t.Error("test failed - GetPositions() error", err)
}
}
func TestIsolatePosition(t *testing.T) {
_, err := b.IsolatePosition(PositionIsolateMarginParams{Symbol: "XBT"})
if err == nil {
t.Error("test failed - IsolatePosition() error", err)
}
}
func TestLeveragePosition(t *testing.T) {
_, err := b.LeveragePosition(PositionUpdateLeverageParams{})
if err == nil {
t.Error("test failed - LeveragePosition() error", err)
}
}
func TestUpdateRiskLimit(t *testing.T) {
_, err := b.UpdateRiskLimit(PositionUpdateRiskLimitParams{})
if err == nil {
t.Error("test failed - UpdateRiskLimit() error", err)
}
}
func TestTransferMargin(t *testing.T) {
_, err := b.TransferMargin(PositionTransferIsolatedMarginParams{})
if err == nil {
t.Error("test failed - TransferMargin() error", err)
}
}
func TestGetQuotesByBuckets(t *testing.T) {
_, err := b.GetQuotesByBuckets(QuoteGetBucketedParams{})
if err == nil {
t.Error("test failed - GetQuotesByBuckets() error", err)
}
}
func TestGetSettlementHistory(t *testing.T) {
_, err := b.GetSettlementHistory(GenericRequestParams{})
if err != nil {
t.Error("test failed - GetSettlementHistory() error", err)
}
}
func TestGetStats(t *testing.T) {
_, err := b.GetStats()
if err != nil {
t.Error("test failed - GetStats() error", err)
}
}
func TestGetStatsHistorical(t *testing.T) {
_, err := b.GetStatsHistorical()
if err != nil {
t.Error("test failed - GetStatsHistorical() error", err)
}
}
func TestGetStatSummary(t *testing.T) {
_, err := b.GetStatSummary()
if err != nil {
t.Error("test failed - GetStatSummary() error", err)
}
}
func TestGetTrade(t *testing.T) {
_, err := b.GetTrade(GenericRequestParams{
Symbol: "XBTUSD",
StartTime: time.Now().Format(time.RFC3339),
Reverse: true})
if err != nil {
t.Error("test failed - GetTrade() error", err)
}
}
func TestGetPreviousTrades(t *testing.T) {
_, err := b.GetPreviousTrades(TradeGetBucketedParams{})
if err == nil {
t.Error("test failed - GetPreviousTrades() error", err)
}
}

View File

@@ -0,0 +1,668 @@
package bitmex
// RequestError allows for a general error capture from requests
type RequestError struct {
Error struct {
Message string `json:"message"`
Name string `json:"name"`
} `json:"error"`
}
// Announcement General Announcements
type Announcement struct {
Content string `json:"content"`
Date string `json:"date"`
ID int32 `json:"id"`
Link string `json:"link"`
Title string `json:"title"`
}
// APIKey Persistent API Keys for Developers
type APIKey struct {
Cidr string `json:"cidr"`
Created string `json:"created"`
Enabled bool `json:"enabled"`
ID string `json:"id"`
Name string `json:"name"`
Nonce int64 `json:"nonce"`
Permissions []interface{} `json:"permissions"`
Secret string `json:"secret"`
UserID int32 `json:"userId"`
}
// Chat Trollbox Data
type Chat struct {
ChannelID float64 `json:"channelID"`
Date string `json:"date"`
FromBot bool `json:"fromBot"`
HTML string `json:"html"`
ID int32 `json:"id"`
Message string `json:"message"`
User string `json:"user"`
}
// ChatChannel chat channel
type ChatChannel struct {
ID int32 `json:"id"`
Name string `json:"name"`
}
// ConnectedUsers connected users
type ConnectedUsers struct {
Bots int32 `json:"bots"`
Users int32 `json:"users"`
}
// Execution Raw Order and Balance Data
type Execution struct {
Account int64 `json:"account"`
AvgPx float64 `json:"avgPx"`
ClOrdID string `json:"clOrdID"`
ClOrdLinkID string `json:"clOrdLinkID"`
Commission float64 `json:"commission"`
ContingencyType string `json:"contingencyType"`
CumQty int64 `json:"cumQty"`
Currency string `json:"currency"`
DisplayQty int64 `json:"displayQty"`
ExDestination string `json:"exDestination"`
ExecComm int64 `json:"execComm"`
ExecCost int64 `json:"execCost"`
ExecID string `json:"execID"`
ExecInst string `json:"execInst"`
ExecType string `json:"execType"`
ForeignNotional float64 `json:"foreignNotional"`
HomeNotional float64 `json:"homeNotional"`
LastLiquidityInd string `json:"lastLiquidityInd"`
LastMkt string `json:"lastMkt"`
LastPx float64 `json:"lastPx"`
LastQty int64 `json:"lastQty"`
LeavesQty int64 `json:"leavesQty"`
MultiLegReportingType string `json:"multiLegReportingType"`
OrdRejReason string `json:"ordRejReason"`
OrdStatus string `json:"ordStatus"`
OrdType string `json:"ordType"`
OrderID string `json:"orderID"`
OrderQty int64 `json:"orderQty"`
PegOffsetValue float64 `json:"pegOffsetValue"`
PegPriceType string `json:"pegPriceType"`
Price float64 `json:"price"`
SettlCurrency string `json:"settlCurrency"`
Side string `json:"side"`
SimpleCumQty float64 `json:"simpleCumQty"`
SimpleLeavesQty float64 `json:"simpleLeavesQty"`
SimpleOrderQty float64 `json:"simpleOrderQty"`
StopPx float64 `json:"stopPx"`
Symbol string `json:"symbol"`
Text string `json:"text"`
TimeInForce string `json:"timeInForce"`
Timestamp string `json:"timestamp"`
TradePublishIndicator string `json:"tradePublishIndicator"`
TransactTime string `json:"transactTime"`
TrdMatchID string `json:"trdMatchID"`
Triggered string `json:"triggered"`
UnderlyingLastPx float64 `json:"underlyingLastPx"`
WorkingIndicator bool `json:"workingIndicator"`
}
// Funding Swap Funding History
type Funding struct {
FundingInterval string `json:"fundingInterval"`
FundingRate float64 `json:"fundingRate"`
FundingRateDaily float64 `json:"fundingRateDaily"`
Symbol string `json:"symbol"`
Timestamp string `json:"timestamp"`
}
// Instrument Tradeable Contracts, Indices, and History
type Instrument struct {
AskPrice float64 `json:"askPrice"`
BankruptLimitDownPrice float64 `json:"bankruptLimitDownPrice"`
BankruptLimitUpPrice float64 `json:"bankruptLimitUpPrice"`
BidPrice float64 `json:"bidPrice"`
BuyLeg string `json:"buyLeg"`
CalcInterval string `json:"calcInterval"`
Capped bool `json:"capped"`
ClosingTimestamp string `json:"closingTimestamp"`
Deleverage bool `json:"deleverage"`
Expiry string `json:"expiry"`
FairBasis float64 `json:"fairBasis"`
FairBasisRate float64 `json:"fairBasisRate"`
FairMethod string `json:"fairMethod"`
FairPrice float64 `json:"fairPrice"`
Front string `json:"front"`
FundingBaseSymbol string `json:"fundingBaseSymbol"`
FundingInterval string `json:"fundingInterval"`
FundingPremiumSymbol string `json:"fundingPremiumSymbol"`
FundingQuoteSymbol string `json:"fundingQuoteSymbol"`
FundingRate float64 `json:"fundingRate"`
FundingTimestamp string `json:"fundingTimestamp"`
HasLiquidity bool `json:"hasLiquidity"`
HighPrice float64 `json:"highPrice"`
ImpactAskPrice float64 `json:"impactAskPrice"`
ImpactBidPrice float64 `json:"impactBidPrice"`
ImpactMidPrice float64 `json:"impactMidPrice"`
IndicativeFundingRate float64 `json:"indicativeFundingRate"`
IndicativeSettlePrice float64 `json:"indicativeSettlePrice"`
IndicativeTaxRate float64 `json:"indicativeTaxRate"`
InitMargin float64 `json:"initMargin"`
InsuranceFee float64 `json:"insuranceFee"`
InverseLeg string `json:"inverseLeg"`
IsInverse bool `json:"isInverse"`
IsQuanto bool `json:"isQuanto"`
LastChangePcnt float64 `json:"lastChangePcnt"`
LastPrice float64 `json:"lastPrice"`
LastPriceProtected float64 `json:"lastPriceProtected"`
LastTickDirection string `json:"lastTickDirection"`
Limit float64 `json:"limit"`
LimitDownPrice float64 `json:"limitDownPrice"`
LimitUpPrice float64 `json:"limitUpPrice"`
Listing string `json:"listing"`
LotSize int64 `json:"lotSize"`
LowPrice float64 `json:"lowPrice"`
MaintMargin float64 `json:"maintMargin"`
MakerFee float64 `json:"makerFee"`
MarkMethod string `json:"markMethod"`
MarkPrice float64 `json:"markPrice"`
MaxOrderQty int64 `json:"maxOrderQty"`
MaxPrice float64 `json:"maxPrice"`
MidPrice float64 `json:"midPrice"`
Multiplier int64 `json:"multiplier"`
OpenInterest int64 `json:"openInterest"`
OpenValue int64 `json:"openValue"`
OpeningTimestamp string `json:"openingTimestamp"`
OptionMultiplier float64 `json:"optionMultiplier"`
OptionStrikePcnt float64 `json:"optionStrikePcnt"`
OptionStrikePrice float64 `json:"optionStrikePrice"`
OptionStrikeRound float64 `json:"optionStrikeRound"`
OptionUnderlyingPrice float64 `json:"optionUnderlyingPrice"`
PositionCurrency string `json:"positionCurrency"`
PrevClosePrice float64 `json:"prevClosePrice"`
PrevPrice24h float64 `json:"prevPrice24h"`
PrevTotalTurnover int64 `json:"prevTotalTurnover"`
PrevTotalVolume int64 `json:"prevTotalVolume"`
PublishInterval string `json:"publishInterval"`
PublishTime string `json:"publishTime"`
QuoteCurrency string `json:"quoteCurrency"`
QuoteToSettleMultiplier int64 `json:"quoteToSettleMultiplier"`
RebalanceInterval string `json:"rebalanceInterval"`
RebalanceTimestamp string `json:"rebalanceTimestamp"`
Reference string `json:"reference"`
ReferenceSymbol string `json:"referenceSymbol"`
RelistInterval string `json:"relistInterval"`
RiskLimit int64 `json:"riskLimit"`
RiskStep int64 `json:"riskStep"`
RootSymbol string `json:"rootSymbol"`
SellLeg string `json:"sellLeg"`
SessionInterval string `json:"sessionInterval"`
SettlCurrency string `json:"settlCurrency"`
Settle string `json:"settle"`
SettledPrice float64 `json:"settledPrice"`
SettlementFee float64 `json:"settlementFee"`
State string `json:"state"`
Symbol string `json:"symbol"`
TakerFee float64 `json:"takerFee"`
Taxed bool `json:"taxed"`
TickSize float64 `json:"tickSize"`
Timestamp string `json:"timestamp"`
TotalTurnover int64 `json:"totalTurnover"`
TotalVolume int64 `json:"totalVolume"`
Turnover int64 `json:"turnover"`
Turnover24h int64 `json:"turnover24h"`
Typ string `json:"typ"`
Underlying string `json:"underlying"`
UnderlyingSymbol string `json:"underlyingSymbol"`
UnderlyingToPositionMultiplier int64 `json:"underlyingToPositionMultiplier"`
UnderlyingToSettleMultiplier int64 `json:"underlyingToSettleMultiplier"`
Volume int64 `json:"volume"`
Volume24h int64 `json:"volume24h"`
Vwap float64 `json:"vwap"`
}
// InstrumentInterval instrument interval
type InstrumentInterval struct {
Intervals []string `json:"intervals"`
Symbols []string `json:"symbols"`
}
// IndexComposite index composite
type IndexComposite struct {
IndexSymbol string `json:"indexSymbol"`
LastPrice float64 `json:"lastPrice"`
Logged string `json:"logged"`
Reference string `json:"reference"`
Symbol string `json:"symbol"`
Timestamp string `json:"timestamp"`
Weight float64 `json:"weight"`
}
// Insurance Insurance Fund Data
type Insurance struct {
Currency string `json:"currency"`
Timestamp string `json:"timestamp"`
WalletBalance int64 `json:"walletBalance"`
}
// Leaderboard Information on Top Users
type Leaderboard struct {
IsRealName bool `json:"isRealName"`
Name string `json:"name"`
Profit float64 `json:"profit"`
}
// Alias Name refers to Trollbox client name
type Alias struct {
Name string `json:"name"`
}
// Liquidation Active Liquidations
type Liquidation struct {
LeavesQty int64 `json:"leavesQty"`
OrderID string `json:"orderID"`
Price float64 `json:"price"`
Side string `json:"side"`
Symbol string `json:"symbol"`
}
// Notification Account Notifications
type Notification struct {
Body string `json:"body"`
Closable bool `json:"closable"`
Date string `json:"date"`
ID int32 `json:"id"`
Persist bool `json:"persist"`
Sound string `json:"sound"`
Title string `json:"title"`
TTL int32 `json:"ttl"`
Type string `json:"type"`
WaitForVisibility bool `json:"waitForVisibility"`
}
// Order Placement, Cancellation, Amending, and History
type Order struct {
Account int64 `json:"account"`
AvgPx float64 `json:"avgPx"`
ClOrdID string `json:"clOrdID"`
ClOrdLinkID string `json:"clOrdLinkID"`
ContingencyType string `json:"contingencyType"`
CumQty int64 `json:"cumQty"`
Currency string `json:"currency"`
DisplayQty int64 `json:"displayQty"`
ExDestination string `json:"exDestination"`
ExecInst string `json:"execInst"`
LeavesQty int64 `json:"leavesQty"`
MultiLegReportingType string `json:"multiLegReportingType"`
OrdRejReason string `json:"ordRejReason"`
OrdStatus string `json:"ordStatus"`
OrdType string `json:"ordType"`
OrderID string `json:"orderID"`
OrderQty int64 `json:"orderQty"`
PegOffsetValue float64 `json:"pegOffsetValue"`
PegPriceType string `json:"pegPriceType"`
Price float64 `json:"price"`
SettlCurrency string `json:"settlCurrency"`
Side string `json:"side"`
SimpleCumQty float64 `json:"simpleCumQty"`
SimpleLeavesQty float64 `json:"simpleLeavesQty"`
SimpleOrderQty float64 `json:"simpleOrderQty"`
StopPx float64 `json:"stopPx"`
Symbol string `json:"symbol"`
Text string `json:"text"`
TimeInForce string `json:"timeInForce"`
Timestamp string `json:"timestamp"`
TransactTime string `json:"transactTime"`
Triggered string `json:"triggered"`
WorkingIndicator bool `json:"workingIndicator"`
}
// OrderBookL2 contains order book l2
type OrderBookL2 struct {
ID int64 `json:"id"`
Price float64 `json:"price"`
Side string `json:"side"`
Size int64 `json:"size"`
Symbol string `json:"symbol"`
}
// Position Summary of Open and Closed Positions
type Position struct {
Account int64 `json:"account"`
AvgCostPrice float64 `json:"avgCostPrice"`
AvgEntryPrice float64 `json:"avgEntryPrice"`
BankruptPrice float64 `json:"bankruptPrice"`
BreakEvenPrice float64 `json:"breakEvenPrice"`
Commission float64 `json:"commission"`
CrossMargin bool `json:"crossMargin"`
Currency string `json:"currency"`
CurrentComm int64 `json:"currentComm"`
CurrentCost int64 `json:"currentCost"`
CurrentQty int64 `json:"currentQty"`
CurrentTimestamp string `json:"currentTimestamp"`
DeleveragePercentile float64 `json:"deleveragePercentile"`
ExecBuyCost int64 `json:"execBuyCost"`
ExecBuyQty int64 `json:"execBuyQty"`
ExecComm int64 `json:"execComm"`
ExecCost int64 `json:"execCost"`
ExecQty int64 `json:"execQty"`
ExecSellCost int64 `json:"execSellCost"`
ExecSellQty int64 `json:"execSellQty"`
ForeignNotional float64 `json:"foreignNotional"`
GrossExecCost int64 `json:"grossExecCost"`
GrossOpenCost int64 `json:"grossOpenCost"`
GrossOpenPremium int64 `json:"grossOpenPremium"`
HomeNotional float64 `json:"homeNotional"`
IndicativeTax int64 `json:"indicativeTax"`
IndicativeTaxRate float64 `json:"indicativeTaxRate"`
InitMargin int64 `json:"initMargin"`
InitMarginReq float64 `json:"initMarginReq"`
IsOpen bool `json:"isOpen"`
LastPrice float64 `json:"lastPrice"`
LastValue int64 `json:"lastValue"`
Leverage float64 `json:"leverage"`
LiquidationPrice float64 `json:"liquidationPrice"`
LongBankrupt int64 `json:"longBankrupt"`
MaintMargin int64 `json:"maintMargin"`
MaintMarginReq float64 `json:"maintMarginReq"`
MarginCallPrice float64 `json:"marginCallPrice"`
MarkPrice float64 `json:"markPrice"`
MarkValue int64 `json:"markValue"`
OpenOrderBuyCost int64 `json:"openOrderBuyCost"`
OpenOrderBuyPremium int64 `json:"openOrderBuyPremium"`
OpenOrderBuyQty int64 `json:"openOrderBuyQty"`
OpenOrderSellCost int64 `json:"openOrderSellCost"`
OpenOrderSellPremium int64 `json:"openOrderSellPremium"`
OpenOrderSellQty int64 `json:"openOrderSellQty"`
OpeningComm int64 `json:"openingComm"`
OpeningCost int64 `json:"openingCost"`
OpeningQty int64 `json:"openingQty"`
OpeningTimestamp string `json:"openingTimestamp"`
PosAllowance int64 `json:"posAllowance"`
PosComm int64 `json:"posComm"`
PosCost int64 `json:"posCost"`
PosCost2 int64 `json:"posCost2"`
PosCross int64 `json:"posCross"`
PosInit int64 `json:"posInit"`
PosLoss int64 `json:"posLoss"`
PosMaint int64 `json:"posMaint"`
PosMargin int64 `json:"posMargin"`
PosState string `json:"posState"`
PrevClosePrice float64 `json:"prevClosePrice"`
PrevRealisedPnl int64 `json:"prevRealisedPnl"`
PrevUnrealisedPnl int64 `json:"prevUnrealisedPnl"`
QuoteCurrency string `json:"quoteCurrency"`
RealisedCost int64 `json:"realisedCost"`
RealisedGrossPnl int64 `json:"realisedGrossPnl"`
RealisedPnl int64 `json:"realisedPnl"`
RealisedTax int64 `json:"realisedTax"`
RebalancedPnl int64 `json:"rebalancedPnl"`
RiskLimit int64 `json:"riskLimit"`
RiskValue int64 `json:"riskValue"`
SessionMargin int64 `json:"sessionMargin"`
ShortBankrupt int64 `json:"shortBankrupt"`
SimpleCost float64 `json:"simpleCost"`
SimplePnl float64 `json:"simplePnl"`
SimplePnlPcnt float64 `json:"simplePnlPcnt"`
SimpleQty float64 `json:"simpleQty"`
SimpleValue float64 `json:"simpleValue"`
Symbol string `json:"symbol"`
TargetExcessMargin int64 `json:"targetExcessMargin"`
TaxBase int64 `json:"taxBase"`
TaxableMargin int64 `json:"taxableMargin"`
Timestamp string `json:"timestamp"`
Underlying string `json:"underlying"`
UnrealisedCost int64 `json:"unrealisedCost"`
UnrealisedGrossPnl int64 `json:"unrealisedGrossPnl"`
UnrealisedPnl int64 `json:"unrealisedPnl"`
UnrealisedPnlPcnt float64 `json:"unrealisedPnlPcnt"`
UnrealisedRoePcnt float64 `json:"unrealisedRoePcnt"`
UnrealisedTax int64 `json:"unrealisedTax"`
VarMargin int64 `json:"varMargin"`
}
// Quote Best Bid/Offer Snapshots & Historical Bins
type Quote struct {
AskPrice float64 `json:"askPrice"`
AskSize int64 `json:"askSize"`
BidPrice float64 `json:"bidPrice"`
BidSize int64 `json:"bidSize"`
Symbol string `json:"symbol"`
Timestamp string `json:"timestamp"`
}
// Settlement Historical Settlement Data
type Settlement struct {
Bankrupt int64 `json:"bankrupt"`
OptionStrikePrice float64 `json:"optionStrikePrice"`
OptionUnderlyingPrice float64 `json:"optionUnderlyingPrice"`
SettledPrice float64 `json:"settledPrice"`
SettlementType string `json:"settlementType"`
Symbol string `json:"symbol"`
TaxBase int64 `json:"taxBase"`
TaxRate float64 `json:"taxRate"`
Timestamp string `json:"timestamp"`
}
// Stats Exchange Statistics
type Stats struct {
Currency string `json:"currency"`
OpenInterest int64 `json:"openInterest"`
OpenValue int64 `json:"openValue"`
RootSymbol string `json:"rootSymbol"`
Turnover24h int64 `json:"turnover24h"`
Volume24h int64 `json:"volume24h"`
}
// StatsHistory stats history
type StatsHistory struct {
Currency string `json:"currency"`
Date string `json:"date"`
RootSymbol string `json:"rootSymbol"`
Turnover int64 `json:"turnover"`
Volume int64 `json:"volume"`
}
// StatsUSD contains summary of exchange stats
type StatsUSD struct {
Currency string `json:"currency"`
RootSymbol string `json:"rootSymbol"`
Turnover int64 `json:"turnover"`
Turnover24h int64 `json:"turnover24h"`
Turnover30d int64 `json:"turnover30d"`
Turnover365d int64 `json:"turnover365d"`
}
// Trade Individual & Bucketed Trades
type Trade struct {
ForeignNotional float64 `json:"foreignNotional"`
GrossValue int64 `json:"grossValue"`
HomeNotional float64 `json:"homeNotional"`
Price float64 `json:"price"`
Side string `json:"side"`
Size int64 `json:"size"`
Symbol string `json:"symbol"`
TickDirection string `json:"tickDirection"`
Timestamp string `json:"timestamp"`
TrdMatchID string `json:"trdMatchID"`
}
// User Account Operations
type User struct {
TFAEnabled string `json:"TFAEnabled"`
AffiliateID string `json:"affiliateID"`
Country string `json:"country"`
Created string `json:"created"`
Email string `json:"email"`
Firstname string `json:"firstname"`
GeoipCountry string `json:"geoipCountry"`
GeoipRegion string `json:"geoipRegion"`
ID int32 `json:"id"`
LastUpdated string `json:"lastUpdated"`
Lastname string `json:"lastname"`
OwnerID int32 `json:"ownerId"`
PgpPubKey string `json:"pgpPubKey"`
Phone string `json:"phone"`
Preferences UserPreferences `json:"preferences"`
Typ string `json:"typ"`
Username string `json:"username"`
}
// UserPreferences user preferences
type UserPreferences struct {
AlertOnLiquidations bool `json:"alertOnLiquidations"`
AnimationsEnabled bool `json:"animationsEnabled"`
AnnouncementsLastSeen string `json:"announcementsLastSeen"`
ChatChannelID float64 `json:"chatChannelID"`
ColorTheme string `json:"colorTheme"`
Currency string `json:"currency"`
Debug bool `json:"debug"`
DisableEmails []string `json:"disableEmails"`
HideConfirmDialogs []string `json:"hideConfirmDialogs"`
HideConnectionModal bool `json:"hideConnectionModal"`
HideFromLeaderboard bool `json:"hideFromLeaderboard"`
HideNameFromLeaderboard bool `json:"hideNameFromLeaderboard"`
HideNotifications []string `json:"hideNotifications"`
Locale string `json:"locale"`
MsgsSeen []string `json:"msgsSeen"`
OrderBookBinning interface{} `json:"orderBookBinning"`
OrderBookType string `json:"orderBookType"`
OrderClearImmediate bool `json:"orderClearImmediate"`
OrderControlsPlusMinus bool `json:"orderControlsPlusMinus"`
ShowLocaleNumbers bool `json:"showLocaleNumbers"`
Sounds []string `json:"sounds"`
StrictIPCheck bool `json:"strictIPCheck"`
StrictTimeout bool `json:"strictTimeout"`
TickerGroup string `json:"tickerGroup"`
TickerPinned bool `json:"tickerPinned"`
TradeLayout string `json:"tradeLayout"`
}
// AffiliateStatus affiliate Status details
type AffiliateStatus struct {
Account int64 `json:"account"`
Currency string `json:"currency"`
ExecComm int64 `json:"execComm"`
ExecTurnover int64 `json:"execTurnover"`
PayoutPcnt float64 `json:"payoutPcnt"`
PendingPayout int64 `json:"pendingPayout"`
PrevComm int64 `json:"prevComm"`
PrevPayout int64 `json:"prevPayout"`
PrevTimestamp string `json:"prevTimestamp"`
PrevTurnover int64 `json:"prevTurnover"`
ReferrerAccount float64 `json:"referrerAccount"`
Timestamp string `json:"timestamp"`
TotalComm int64 `json:"totalComm"`
TotalReferrals int64 `json:"totalReferrals"`
TotalTurnover int64 `json:"totalTurnover"`
}
// TransactionInfo Information
type TransactionInfo struct {
Account int64 `json:"account"`
Address string `json:"address"`
Amount int64 `json:"amount"`
Currency string `json:"currency"`
Fee int64 `json:"fee"`
Text string `json:"text"`
Timestamp string `json:"timestamp"`
TransactID string `json:"transactID"`
TransactStatus string `json:"transactStatus"`
TransactTime string `json:"transactTime"`
TransactType string `json:"transactType"`
Tx string `json:"tx"`
}
// UserCommission user commission
type UserCommission struct {
MakerFee float64 `json:"makerFee"`
MaxFee float64 `json:"maxFee"`
SettlementFee float64 `json:"settlementFee"`
TakerFee float64 `json:"takerFee"`
}
// ConfirmEmail confirmatin email endpoint data
type ConfirmEmail struct {
ID string `json:"id"`
TTL int64 `json:"ttl"`
Created string `json:"created"`
UserID int64 `json:"userId"`
}
// UserMargin margin information
type UserMargin struct {
Account int64 `json:"account"`
Action string `json:"action"`
Amount int64 `json:"amount"`
AvailableMargin int64 `json:"availableMargin"`
Commission float64 `json:"commission"`
ConfirmedDebit int64 `json:"confirmedDebit"`
Currency string `json:"currency"`
ExcessMargin int64 `json:"excessMargin"`
ExcessMarginPcnt float64 `json:"excessMarginPcnt"`
GrossComm int64 `json:"grossComm"`
GrossExecCost int64 `json:"grossExecCost"`
GrossLastValue int64 `json:"grossLastValue"`
GrossMarkValue int64 `json:"grossMarkValue"`
GrossOpenCost int64 `json:"grossOpenCost"`
GrossOpenPremium int64 `json:"grossOpenPremium"`
IndicativeTax int64 `json:"indicativeTax"`
InitMargin int64 `json:"initMargin"`
MaintMargin int64 `json:"maintMargin"`
MarginBalance int64 `json:"marginBalance"`
MarginBalancePcnt float64 `json:"marginBalancePcnt"`
MarginLeverage float64 `json:"marginLeverage"`
MarginUsedPcnt float64 `json:"marginUsedPcnt"`
PendingCredit int64 `json:"pendingCredit"`
PendingDebit int64 `json:"pendingDebit"`
PrevRealisedPnl int64 `json:"prevRealisedPnl"`
PrevState string `json:"prevState"`
PrevUnrealisedPnl int64 `json:"prevUnrealisedPnl"`
RealisedPnl int64 `json:"realisedPnl"`
RiskLimit int64 `json:"riskLimit"`
RiskValue int64 `json:"riskValue"`
SessionMargin int64 `json:"sessionMargin"`
State string `json:"state"`
SyntheticMargin int64 `json:"syntheticMargin"`
TargetExcessMargin int64 `json:"targetExcessMargin"`
TaxableMargin int64 `json:"taxableMargin"`
Timestamp string `json:"timestamp"`
UnrealisedPnl int64 `json:"unrealisedPnl"`
UnrealisedProfit int64 `json:"unrealisedProfit"`
VarMargin int64 `json:"varMargin"`
WalletBalance int64 `json:"walletBalance"`
WithdrawableMargin int64 `json:"withdrawableMargin"`
}
// MinWithdrawalFee minimum withdrawal fee information
type MinWithdrawalFee struct {
Currency string `json:"currency"`
Fee int64 `json:"fee"`
MinFee int64 `json:"minFee"`
}
// WalletInfo wallet information
type WalletInfo struct {
Account int64 `json:"account"`
Addr string `json:"addr"`
Amount int64 `json:"amount"`
ConfirmedDebit int64 `json:"confirmedDebit"`
Currency string `json:"currency"`
DeltaAmount int64 `json:"deltaAmount"`
DeltaDeposited int64 `json:"deltaDeposited"`
DeltaTransferIn int64 `json:"deltaTransferIn"`
DeltaTransferOut int64 `json:"deltaTransferOut"`
DeltaWithdrawn int64 `json:"deltaWithdrawn"`
Deposited int64 `json:"deposited"`
PendingCredit int64 `json:"pendingCredit"`
PendingDebit int64 `json:"pendingDebit"`
PrevAmount int64 `json:"prevAmount"`
PrevDeposited int64 `json:"prevDeposited"`
PrevTimestamp string `json:"prevTimestamp"`
PrevTransferIn int64 `json:"prevTransferIn"`
PrevTransferOut int64 `json:"prevTransferOut"`
PrevWithdrawn int64 `json:"prevWithdrawn"`
Script string `json:"script"`
Timestamp string `json:"timestamp"`
TransferIn int64 `json:"transferIn"`
TransferOut int64 `json:"transferOut"`
WithdrawalLock []string `json:"withdrawalLock"`
Withdrawn int64 `json:"withdrawn"`
}

View File

@@ -0,0 +1,494 @@
package bitmex
import (
"errors"
"fmt"
"log"
"strconv"
"time"
"github.com/gorilla/websocket"
"github.com/thrasher-/gocryptotrader/common"
)
const (
bitmexWSURL = "wss://www.bitmex.com/realtime"
// Public Subscription Channels
bitmexWSAnnouncement = "announcement"
bitmexWSChat = "chat"
bitmexWSConnected = "connected"
bitmexWSFunding = "funding"
bitmexWSInstrument = "instrument"
bitmexWSInsurance = "insurance"
bitmexWSLiquidation = "liquidation"
bitmexWSOrderbookL2 = "orderBookL2"
bitmexWSOrderbookL10 = "orderBook10"
bitmexWSPublicNotifications = "publicNotifications"
bitmexWSQuote = "quote"
bitmexWSQuote1m = "quoteBin1m"
bitmexWSQuote5m = "quoteBin5m"
bitmexWSQuote1h = "quoteBin1h"
bitmexWSQuote1d = "quoteBin1d"
bitmexWSSettlement = "settlement"
bitmexWSTrade = "trade"
bitmexWSTrade1m = "tradeBin1m"
bitmexWSTrade5m = "tradeBin5m"
bitmexWSTrade1h = "tradeBin1h"
bitmexWSTrade1d = "tradeBin1d"
// Authenticated Subscription Channels
bitmexWSAffiliate = "affiliate"
bitmexWSExecution = "execution"
bitmexWSOrder = "order"
bitmexWSMargin = "margin"
bitmexWSPosition = "position"
bitmexWSPrivateNotifications = "privateNotifications"
bitmexWSTransact = "transact"
bitmexWSWallet = "wallet"
bitmexActionInitialData = "partial"
bitmexActionInsertData = "insert"
bitmexActionDeleteData = "delete"
bitmexActionUpdateData = "update"
)
var (
pongChan = make(chan int, 1)
timer *time.Timer
)
// WebsocketConnect initiates a new websocket connection
func (b *Bitmex) WebsocketConnect() error {
var dialer websocket.Dialer
var err error
b.WebsocketConn, _, err = dialer.Dial(bitmexWSURL, nil)
if err != nil {
return err
}
_, p, err := b.WebsocketConn.ReadMessage()
if err != nil {
return err
}
var welcomeResp WebsocketWelcome
err = common.JSONDecode(p, &welcomeResp)
if err != nil {
return err
}
go b.connectionHandler()
if b.Verbose {
log.Printf("Successfully connected to Bitmex %s at time: %s Limit: %d",
welcomeResp.Info,
welcomeResp.Timestamp,
welcomeResp.Limit.Remaining)
}
go b.handleIncomingData()
err = b.websocketSubscribe()
if err != nil {
b.WebsocketConn.Close()
return err
}
if b.AuthenticatedAPISupport {
err := b.websocketSendAuth()
if err != nil {
log.Fatal(err)
}
}
return nil
}
// Timer handles connection loss or failure
func (b *Bitmex) connectionHandler() {
defer func() {
if b.Verbose {
log.Println("Bitmex websocket: Connection handler routine shutdown")
}
}()
shutdown := b.shutdown.addRoutine()
timer = time.NewTimer(5 * time.Second)
for {
select {
case <-timer.C:
timeout := time.After(5 * time.Second)
err := b.WebsocketConn.WriteJSON("ping")
if err != nil {
b.reconnect()
return
}
for {
select {
case <-pongChan:
if b.Verbose {
log.Println("Bitmex websocket: PONG received")
}
break
case <-timeout:
log.Println("Bitmex websocket: Connection timed out - Closing connection....")
b.WebsocketConn.Close()
log.Println("Bitmex websocket: Connection timed out - Reconnecting...")
b.reconnect()
return
}
}
case <-shutdown:
log.Println("Bitmex websocket: shutdown requested - Closing connection....")
b.WebsocketConn.Close()
log.Println("Bitmex websocket: Sending shutdown message")
b.shutdown.routineShutdown()
return
}
}
}
// Reconnect handles reconnections to websocket API
func (b *Bitmex) reconnect() {
for {
err := b.WebsocketConnect()
if err != nil {
log.Println("Bitmex websocket: Connection timed out - Failed to connect, sleeping...")
time.Sleep(time.Second * 2)
continue
}
return
}
}
// handleIncomingData services incoming data from the websocket connection
func (b *Bitmex) handleIncomingData() {
defer func() {
if b.Verbose {
log.Println("Bitmex websocket: Response data handler routine shutdown")
}
}()
for {
_, resp, err := b.WebsocketConn.ReadMessage()
if err != nil {
if b.Verbose {
log.Println("Bitmex websocket: Connection error", err)
}
return
}
message := string(resp)
if common.StringContains(message, "pong") {
if b.Verbose {
log.Println("Bitmex websocket: PONG receieved")
}
pongChan <- 1
continue
}
if common.StringContains(message, "ping") {
err = b.WebsocketConn.WriteJSON("pong")
if err != nil {
if b.Verbose {
log.Println("Bitmex websocket error: ", err)
}
return
}
}
if !timer.Reset(5 * time.Second) {
log.Fatal("Bitmex websocket: Timer failed to set")
}
quickCapture := make(map[string]interface{})
err = common.JSONDecode(resp, &quickCapture)
if err != nil {
log.Fatal(err)
}
var respError WebsocketErrorResponse
if _, ok := quickCapture["status"]; ok {
err = common.JSONDecode(resp, &respError)
if err != nil {
log.Fatal(err)
}
log.Printf("Bitmex websocket error: %s", respError.Error)
continue
}
if _, ok := quickCapture["success"]; ok {
var decodedResp WebsocketSubscribeResp
err := common.JSONDecode(resp, &decodedResp)
if err != nil {
log.Fatal(err)
}
if decodedResp.Success {
if b.Verbose {
if len(quickCapture) == 3 {
log.Printf("Bitmex Websocket: Successfully subscribed to %s",
decodedResp.Subscribe)
} else {
log.Println("Bitmex Websocket: Successfully authenticated websocket connection")
}
}
continue
}
log.Printf("Bitmex websocket error: Unable to subscribe %s",
decodedResp.Subscribe)
} else if _, ok := quickCapture["table"]; ok {
var decodedResp WebsocketMainResponse
err := common.JSONDecode(resp, &decodedResp)
if err != nil {
log.Fatal(err)
}
switch decodedResp.Table {
case bitmexWSOrderbookL2:
var orderbooks OrderBookData
err = common.JSONDecode(resp, &orderbooks)
if err != nil {
log.Fatal(err)
}
err = b.processOrderbook(orderbooks.Data, orderbooks.Action)
if err != nil {
log.Fatal(err)
}
case bitmexWSTrade:
var trades TradeData
err = common.JSONDecode(resp, &trades)
if err != nil {
log.Fatal(err)
}
err = b.processTrades(trades.Data, trades.Action)
if err != nil {
log.Fatal(err)
}
case bitmexWSAnnouncement:
var announcement AnnouncementData
err = common.JSONDecode(resp, &announcement)
if err != nil {
log.Fatal(err)
}
err = b.processAnnouncement(announcement.Data, announcement.Action)
if err != nil {
log.Fatal(err)
}
default:
log.Fatal("Bitmex websocket error: Table unknown -", decodedResp.Table)
}
}
}
}
// Temporary local cache of Announcements
var localAnnouncements []Announcement
var partialLoadedAnnouncement bool
// ProcessAnnouncement process announcements
func (b *Bitmex) processAnnouncement(data []Announcement, action string) error {
switch action {
case bitmexActionInitialData:
if !partialLoadedAnnouncement {
localAnnouncements = data
}
partialLoadedAnnouncement = true
default:
return fmt.Errorf("Bitmex websocket error: ProcessAnnouncement() unallocated action - %s",
action)
}
return nil
}
// Temporary local cache of orderbooks
var localOb []OrderBookL2
var partialLoaded bool
// ProcessOrderbook processes orderbook updates
func (b *Bitmex) processOrderbook(data []OrderBookL2, action string) error {
switch action {
case bitmexActionInitialData:
if !partialLoaded {
localOb = data
}
partialLoaded = true
case bitmexActionUpdateData:
if partialLoaded {
updated := len(data)
for _, elem := range data {
for i := range localOb {
if localOb[i].ID == elem.ID && localOb[i].Symbol == elem.Symbol {
localOb[i].Side = elem.Side
localOb[i].Size = elem.Size
updated--
break
}
}
}
if updated != 0 {
return errors.New("Bitmex websocket error: Elements not updated correctly")
}
}
case bitmexActionInsertData:
if partialLoaded {
updated := len(data)
for _, elem := range data {
localOb = append(localOb, OrderBookL2{
Symbol: elem.Symbol,
ID: elem.ID,
Side: elem.Side,
Size: elem.Size,
Price: elem.Price,
})
updated--
}
if updated != 0 {
return errors.New("Bitmex websocket error: Elements not updated correctly")
}
}
case bitmexActionDeleteData:
if partialLoaded {
updated := len(data)
for _, elem := range data {
for i := range localOb {
if localOb[i].ID == elem.ID && localOb[i].Symbol == elem.Symbol {
localOb[i] = localOb[len(localOb)-1]
localOb = localOb[:len(localOb)-1]
updated--
break
}
}
}
if updated != 0 {
return errors.New("Bitmex websocket error: Elements not updated correctly")
}
}
}
return nil
}
// Temporary local cache of orderbooks
var localTrades []Trade
var partialLoadedTrades bool
// ProcessTrades processes new trades that have occured
func (b *Bitmex) processTrades(data []Trade, action string) error {
switch action {
case bitmexActionInitialData:
if !partialLoadedTrades {
localTrades = data
}
partialLoadedTrades = true
case bitmexActionInsertData:
if partialLoadedTrades {
localTrades = append(localTrades, data...)
}
default:
return fmt.Errorf("Bitmex websocket error: ProcessTrades() unallocated action - %s",
action)
}
return nil
}
// WebsocketSubscribe subscribes to a websocket channel
func (b *Bitmex) websocketSubscribe() error {
contracts := b.GetEnabledCurrencies()
// Subscriber
var subscriber WebsocketRequest
subscriber.Command = "subscribe"
// Announcement subscribe
subscriber.Arguments = append(subscriber.Arguments, bitmexWSAnnouncement)
for _, contract := range contracts {
// Orderbook subscribe
subscriber.Arguments = append(subscriber.Arguments,
bitmexWSOrderbookL2+":"+contract.Pair().String())
// Trade subscribe
subscriber.Arguments = append(subscriber.Arguments,
bitmexWSTrade+":"+contract.Pair().String())
// NOTE more added here in future
}
err := b.WebsocketConn.WriteJSON(subscriber)
if err != nil {
return err
}
return nil
}
// WebsocketSendAuth sends an authenticated subscription
func (b *Bitmex) websocketSendAuth() error {
timestamp := time.Now().Add(time.Hour * 1).Unix()
newTimestamp := strconv.FormatInt(timestamp, 10)
hmac := common.GetHMAC(common.HashSHA256,
[]byte("GET/realtime"+newTimestamp),
[]byte(b.APISecret))
signature := common.HexEncodeToString(hmac)
var sendAuth WebsocketRequest
sendAuth.Command = "authKeyExpires"
sendAuth.Arguments = append(sendAuth.Arguments, b.APIKey)
sendAuth.Arguments = append(sendAuth.Arguments, timestamp)
sendAuth.Arguments = append(sendAuth.Arguments, signature)
return b.WebsocketConn.WriteJSON(sendAuth)
}
// Shutdown to monitor and shut down routines package specific
type Shutdown struct {
c chan int
routineCount int
finishC chan int
}
// NewRoutineManagement returns an new initial routine management system
func (b *Bitmex) NewRoutineManagement() *Shutdown {
return &Shutdown{
c: make(chan int, 1),
finishC: make(chan int, 1),
}
}
// AddRoutine adds a routine to the monitor and returns a channel
func (r *Shutdown) addRoutine() chan int {
log.Println("Bitmex Websocket: Routine added to monitor")
r.routineCount++
return r.c
}
// RoutineShutdown sends a message to the finisher channel
func (r *Shutdown) routineShutdown() {
log.Println("Bitmex Websocket: Routine is shutting down")
r.finishC <- 1
}
// SignalShutdown signals a shutdown across routines
func (r *Shutdown) SignalShutdown() {
log.Println("Bitmex Websocket: Shutdown signal sending..")
for i := 0; i < r.routineCount; i++ {
log.Printf("Bitmex Websocket: Shutdown signal sent to routine %d", i+1)
r.c <- 1
}
for {
<-r.finishC
r.routineCount--
if r.routineCount <= 0 {
close(r.c)
close(r.finishC)
log.Println("Bitmex Websocket: All routines stopped")
return
}
}
}

View File

@@ -0,0 +1,72 @@
package bitmex
// WebsocketRequest is the main request type
type WebsocketRequest struct {
Command string `json:"op"`
Arguments []interface{} `json:"args"`
}
// WebsocketErrorResponse main error response
type WebsocketErrorResponse struct {
Status int `json:"status"`
Error string `json:"error"`
Meta interface{} `json:"meta"`
Request WebsocketRequest `json:"request"`
}
// WebsocketWelcome initial welcome type
type WebsocketWelcome struct {
Info string `json:"info"`
Version string `json:"version"`
Timestamp string `json:"timestamp"`
Docs string `json:"docs"`
Limit struct {
Remaining int64 `json:"remaining"`
} `json:"limit"`
}
// WebsocketSubscribeResp is a response that occurs after a subscription
type WebsocketSubscribeResp struct {
Success bool `json:"success"`
Subscribe string `json:"subscribe"`
Request WebsocketRequest `json:"request"`
}
// WebsocketMainResponse main table defined response
type WebsocketMainResponse struct {
Table string `json:"table"`
Keys []string `json:"keys"`
Types struct {
ID string `json:"id"`
Price string `json:"price"`
Side string `json:"side"`
Size string `json:"size"`
Symbol string `json:"symbol"`
} `json:"types"`
ForeignKeys struct {
Side string `json:"side"`
Symbol string `json:"symbol"`
} `json:"foreignKeys"`
Attributes struct {
ID string `json:"id"`
Symbol string `json:"symbol"`
} `json:"Attributes"`
}
// OrderBookData contains orderbook resp data with action to be taken
type OrderBookData struct {
Data []OrderBookL2 `json:"data"`
Action string `json:"action"`
}
// TradeData contains trade resp data with action to be taken
type TradeData struct {
Data []Trade `json:"data"`
Action string `json:"action"`
}
// AnnouncementData contains announcement resp data with action to be taken
type AnnouncementData struct {
Data []Announcement `json:"data"`
Action string `json:"action"`
}

View File

@@ -0,0 +1,195 @@
package bitmex
import (
"errors"
"log"
"sync"
"time"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/currency/pair"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
)
// Start starts the Bitmex go routine
func (b *Bitmex) Start(wg *sync.WaitGroup) {
wg.Add(1)
go func() {
b.Run()
wg.Done()
}()
}
// Run implements the Bitmex wrapper
func (b *Bitmex) Run() {
if b.Verbose {
log.Printf("%s Websocket: %s. (url: %s).\n", b.GetName(), common.IsEnabled(b.Websocket), b.WebsocketURL)
log.Printf("%s polling delay: %ds.\n", b.GetName(), b.RESTPollingDelay)
log.Printf("%s %d currencies enabled: %s.\n", b.GetName(), len(b.EnabledPairs), b.EnabledPairs)
}
marketInfo, err := b.GetActiveInstruments(GenericRequestParams{})
if err != nil {
log.Printf("%s Failed to get available symbols.\n", b.GetName())
} else {
var exchangeProducts []string
for _, info := range marketInfo {
exchangeProducts = append(exchangeProducts, info.Symbol)
}
err = b.UpdateCurrencies(exchangeProducts, false, false)
if err != nil {
log.Printf("%s Failed to update available currencies.\n", b.GetName())
}
}
}
// UpdateTicker updates and returns the ticker for a currency pair
func (b *Bitmex) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
var tickerPrice ticker.Price
currency := exchange.FormatExchangeCurrency(b.Name, p)
tick, err := b.GetTrade(GenericRequestParams{
Symbol: currency.String(),
StartTime: time.Now().Format(time.RFC3339),
Reverse: true,
Count: 1})
if err != nil {
return tickerPrice, err
}
if len(tick) == 0 {
return tickerPrice, errors.New("Bitmex REST error: no ticker return")
}
tickerPrice.Pair = p
tickerPrice.LastUpdated = time.Now()
tickerPrice.CurrencyPair = tick[0].Symbol
tickerPrice.Last = tick[0].Price
tickerPrice.Volume = float64(tick[0].Size)
ticker.ProcessTicker(b.Name, p, tickerPrice, assetType)
return tickerPrice, nil
}
// GetTickerPrice returns the ticker for a currency pair
func (b *Bitmex) GetTickerPrice(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
tickerNew, err := ticker.GetTicker(b.GetName(), p, assetType)
if err != nil {
return b.UpdateTicker(p, assetType)
}
return tickerNew, nil
}
// GetOrderbookEx returns orderbook base on the currency pair
func (b *Bitmex) GetOrderbookEx(currency pair.CurrencyPair, assetType string) (orderbook.Base, error) {
ob, err := orderbook.GetOrderbook(b.GetName(), currency, assetType)
if err != nil {
return b.UpdateOrderbook(currency, assetType)
}
return ob, nil
}
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (b *Bitmex) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.Base, error) {
var orderBook orderbook.Base
orderbookNew, err := b.GetOrderbook(OrderBookGetL2Params{
Symbol: exchange.FormatExchangeCurrency(b.Name, p).String(),
Depth: 500})
if err != nil {
return orderBook, err
}
for _, ob := range orderbookNew {
if ob.Side == "Sell" {
orderBook.Asks = append(orderBook.Asks,
orderbook.Item{Amount: float64(ob.Size), Price: ob.Price})
continue
}
if ob.Side == "Buy" {
orderBook.Bids = append(orderBook.Bids,
orderbook.Item{Amount: float64(ob.Size), Price: ob.Price})
continue
}
}
orderbook.ProcessOrderbook(b.GetName(), p, orderBook, assetType)
return orderbook.GetOrderbook(b.Name, p, assetType)
}
// GetExchangeAccountInfo retrieves balances for all enabled currencies for the
// Bitmex exchange
func (b *Bitmex) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
return response, errors.New("not implemented")
}
// GetExchangeFundTransferHistory returns funding history, deposits and
// withdrawals
func (b *Bitmex) GetExchangeFundTransferHistory() ([]exchange.FundHistory, error) {
var fundHistory []exchange.FundHistory
return fundHistory, errors.New("not supported on exchange")
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (b *Bitmex) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}
// SubmitExchangeOrder submits a new order
func (b *Bitmex) SubmitExchangeOrder(p pair.CurrencyPair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (int64, error) {
return 0, errors.New("not yet implemented")
}
// ModifyExchangeOrder will allow of changing orderbook placement and limit to
// market conversion
func (b *Bitmex) ModifyExchangeOrder(orderID int64, action exchange.ModifyOrder) (int64, error) {
return 0, errors.New("not yet implemented")
}
// CancelExchangeOrder cancels an order by its corresponding ID number
func (b *Bitmex) CancelExchangeOrder(orderID int64) error {
return errors.New("not yet implemented")
}
// CancelAllExchangeOrders cancels all orders associated with a currency pair
func (b *Bitmex) CancelAllExchangeOrders() error {
return errors.New("not yet implemented")
}
// GetExchangeOrderInfo returns information on a current open order
func (b *Bitmex) GetExchangeOrderInfo(orderID int64) (exchange.OrderDetail, error) {
var orderDetail exchange.OrderDetail
return orderDetail, errors.New("not yet implemented")
}
// GetExchangeDepositAddress returns a deposit address for a specified currency
func (b *Bitmex) GetExchangeDepositAddress(cryptocurrency pair.CurrencyItem) (string, error) {
return "", errors.New("not yet implemented")
}
// WithdrawCryptoExchangeFunds returns a withdrawal ID when a withdrawal is
// submitted
func (b *Bitmex) WithdrawCryptoExchangeFunds(address string, cryptocurrency pair.CurrencyItem, amount float64) (string, error) {
return "", errors.New("not yet implemented")
}
// WithdrawFiatExchangeFunds returns a withdrawal ID when a withdrawal is
// submitted
func (b *Bitmex) WithdrawFiatExchangeFunds(currency pair.CurrencyItem, amount float64) (string, error) {
return "", errors.New("not yet implemented")
}
// WithdrawExchangeFiatFundsToInternationalBank returns a withdrawal ID when a withdrawal is
// submitted
func (b *Bitmex) WithdrawExchangeFiatFundsToInternationalBank(currency pair.CurrencyItem, amount float64) (string, error) {
return "", errors.New("not yet implemented")
}

File diff suppressed because one or more lines are too long

View File

@@ -1197,6 +1197,41 @@
"supportedCurrencies": ""
}
]
},
{
"name": "Bitmex",
"enabled": true,
"verbose": false,
"websocket": false,
"useSandbox": false,
"restPollingDelay": 10,
"httpTimeout": 10,
"httpUserAgent": "",
"authenticatedApiSupport": false,
"apiKey": "Key",
"apiSecret": "Secret",
"availablePairs": "XRPXBT",
"enabledPairs": "XRPXBT",
"baseCurrencies": "USD",
"assetTypes": "SPOT",
"supportsAutoPairUpdates": false,
"configCurrencyPairFormat": {
"uppercase": false
},
"requestCurrencyPairFormat": {
"uppercase": true
},
"bankAccounts": [
{
"bankName": "",
"bankAddress": "",
"accountName": "",
"accountNumber": "",
"swiftCode": "",
"iban": "",
"supportedCurrencies": ""
}
]
}
],
"bankAccounts": [

View File

@@ -52,6 +52,7 @@ const (
bitfinex = "..%s..%sexchanges%sbitfinex%s"
bitflyer = "..%s..%sexchanges%sbitflyer%s"
bithumb = "..%s..%sexchanges%sbithumb%s"
bitmex = "..%s..%sexchanges%sbitmex%s"
bitstamp = "..%s..%sexchanges%sbitstamp%s"
bittrex = "..%s..%sexchanges%sbittrex%s"
btcc = "..%s..%sexchanges%sbtcc%s"
@@ -226,6 +227,7 @@ func addPaths() {
codebasePaths["exchanges bitfinex"] = fmt.Sprintf(bitfinex, path, path, path, path)
codebasePaths["exchanges bitflyer"] = fmt.Sprintf(bitflyer, path, path, path, path)
codebasePaths["exchanges bithumb"] = fmt.Sprintf(bithumb, path, path, path, path)
codebasePaths["exchanges bitmex"] = fmt.Sprintf(bitmex, path, path, path, path)
codebasePaths["exchanges bitstamp"] = fmt.Sprintf(bitstamp, path, path, path, path)
codebasePaths["exchanges bittrex"] = fmt.Sprintf(bittrex, path, path, path, path)
codebasePaths["exchanges btcc"] = fmt.Sprintf(btcc, path, path, path, path)

View File

@@ -0,0 +1,98 @@
{{define "exchanges bitmex" -}}
{{template "header" .}}
## Bithumb Exchange
### Current Features
+ REST Support
### How to enable
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
+ Individual package example below:
```go
// Exchanges will be abstracted out in further updates and examples will be
// supplied then
```
### How to do REST public/private calls
+ If enabled via "configuration".json file the exchange will be added to the
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
the wrapper interface functions for accessing exchange data. View routines.go
for an example of integration usage with GoCryptoTrader. Rudimentary example
below:
main.go
```go
var b exchange.IBotExchange
for i := range bot.exchanges {
if bot.exchanges[i].GetName() == "Bitmex" {
b = bot.exchanges[i]
}
}
// Public calls - wrapper functions
// Fetches current ticker information
tick, err := b.GetTickerPrice()
if err != nil {
// Handle error
}
// Fetches current orderbook information
ob, err := b.GetOrderbookEx()
if err != nil {
// Handle error
}
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
// set and AuthenticatedAPISupport is set to true
// Fetches current account information
accountInfo, err := b.GetExchangeAccountInfo()
if err != nil {
// Handle error
}
```
+ If enabled via individually importing package, rudimentary example below:
```go
// Public calls
// Fetches current ticker information
ticker, err := b.GetTicker()
if err != nil {
// Handle error
}
// Fetches current orderbook information
ob, err := b.GetOrderBook()
if err != nil {
// Handle error
}
// Private calls - make sure your APIKEY and APISECRET are set and
// AuthenticatedAPISupport is set to true
// GetUserInfo returns account info
accountInfo, err := b.GetUserInfo(...)
if err != nil {
// Handle error
}
// Submits an order and the exchange and returns its tradeID
tradeID, err := b.Trade(...)
if err != nil {
// Handle error
}
```
### Please click GoDocs chevron above to view current GoDoc information for this package
{{template "contributions"}}
{{template "donations"}}
{{end}}

View File

@@ -25,6 +25,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
| Bitfinex | Yes | Yes | NA |
| Bitflyer | Yes | No | NA |
| Bithumb | Yes | NA | NA |
| BitMEX | Yes | No | NA |
| Bitstamp | Yes | Yes | No |
| Bittrex | Yes | No | NA |
| BTCC | Yes | Yes | No |