diff --git a/README.md b/README.md
index cff95dac..ce920da5 100644
--- a/README.md
+++ b/README.md
@@ -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 |
-
-
-
diff --git a/config/config_test.go b/config/config_test.go
index 3f50be99..cd7d7738 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -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 {
diff --git a/config_example.json b/config_example.json
index af6156b8..f74a71f7 100644
--- a/config_example.json
+++ b/config_example.json
@@ -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"
}
]
-}
\ No newline at end of file
+}
diff --git a/exchange.go b/exchange.go
index 41a5b00a..c0fe5c65 100644
--- a/exchange.go
+++ b/exchange.go
@@ -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":
diff --git a/exchanges/bitmex/README.md b/exchanges/bitmex/README.md
new file mode 100644
index 00000000..04bd5c71
--- /dev/null
+++ b/exchanges/bitmex/README.md
@@ -0,0 +1,133 @@
+# GoCryptoTrader package Bitmex
+
+
+
+
+[](https://travis-ci.org/thrasher-/gocryptotrader)
+[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
+[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/bitmex)
+[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
+[](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
+
+
+
+If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
+
+***1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB***
+
diff --git a/exchanges/bitmex/bitmex.go b/exchanges/bitmex/bitmex.go
new file mode 100644
index 00000000..60b45553
--- /dev/null
+++ b/exchanges/bitmex/bitmex.go
@@ -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,
+ ¬ifications)
+}
+
+// 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,
+ "ations)
+}
+
+// GetQuotesByBuckets returns previous quotes in time buckets
+func (b *Bitmex) GetQuotesByBuckets(params QuoteGetBucketedParams) ([]Quote, error) {
+ var quotations []Quote
+
+ return quotations, b.SendHTTPRequest(bitmexEndpointQuoteBucketed,
+ params,
+ "ations)
+}
+
+// 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
+}
diff --git a/exchanges/bitmex/bitmex_parameters.go b/exchanges/bitmex/bitmex_parameters.go
new file mode 100644
index 00000000..79a652ad
--- /dev/null
+++ b/exchanges/bitmex/bitmex_parameters.go
@@ -0,0 +1,1123 @@
+package bitmex
+
+import (
+ "errors"
+ "net/url"
+ "reflect"
+ "strconv"
+
+ "github.com/thrasher-/gocryptotrader/common"
+)
+
+// Parameter just enforces a check on all outgoing data
+type Parameter interface {
+ VerifyData() error
+ ToURLVals(path string) (string, error)
+ IsNil() bool
+}
+
+// StructValsToURLVals converts a struct into url.values for easy encoding
+// can set json tags for outgoing naming conventions.
+func StructValsToURLVals(v interface{}) (url.Values, error) {
+ values := url.Values{}
+
+ if reflect.ValueOf(v).Kind() != reflect.Ptr {
+ return nil, errors.New("address of struct needs to be passed in")
+ }
+
+ structVal := reflect.ValueOf(v).Elem()
+ structType := structVal.Type()
+
+ for i := 0; i < structVal.NumField(); i++ {
+ structField := structVal.Field(i)
+
+ var outgoingTag string
+ if structType.Field(i).Tag != "" {
+ jsonTag := structType.Field(i).Tag.Get("json")
+ if jsonTag != "" {
+ split := common.SplitStrings(jsonTag, ",")
+ outgoingTag = split[0]
+ }
+ }
+
+ if outgoingTag == "" {
+ outgoingTag = structType.Field(i).Name
+ }
+
+ var v string
+ switch structField.Interface().(type) {
+ case int, int8, int16, int32, int64:
+ if structField.Int() == 0 {
+ continue
+ }
+ v = strconv.FormatInt(structField.Int(), 10)
+ case uint, uint8, uint16, uint32, uint64:
+ if structField.Uint() == 0 {
+ continue
+ }
+ v = strconv.FormatUint(structField.Uint(), 10)
+ case float32:
+ if structField.Float() == 0 {
+ continue
+ }
+ v = strconv.FormatFloat(structField.Float(), 'f', 4, 32)
+ case float64:
+ if structField.Float() == 0 {
+ continue
+ }
+ v = strconv.FormatFloat(structField.Float(), 'f', 4, 64)
+ case []byte:
+ if structField.Bytes() == nil {
+ continue
+ }
+ v = string(structField.Bytes())
+ case string:
+ if structField.String() == "" {
+ continue
+ }
+ v = structField.String()
+ case bool:
+ v = strconv.FormatBool(structField.Bool())
+ }
+ values.Set(outgoingTag, v)
+ }
+ return values, nil
+}
+
+// APIKeyParams contains all the parameters to send to the API endpoint
+type APIKeyParams struct {
+ //API Key ID (public component).
+ APIKeyID string `json:"apiKeyID,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p APIKeyParams) VerifyData() error {
+ if p.APIKeyID == "" {
+ return errors.New("verifydata APIKeyParams error - APIKeyID not set")
+ }
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p APIKeyParams) ToURLVals(path string) (string, error) {
+ values, err := StructValsToURLVals(&p)
+ if err != nil {
+ return "", err
+ }
+ return common.EncodeURLValues(path, values), nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p APIKeyParams) IsNil() bool {
+ if p == (APIKeyParams{}) {
+ return true
+ }
+ return false
+}
+
+// ChatGetParams contains all the parameters to send to the API endpoint
+type ChatGetParams struct {
+ // ChannelID - [Optional] Leave blank for all.
+ ChannelID float64 `json:"channelID,omitempty"`
+
+ // Count - [Optional] Number of results to fetch.
+ Count int32 `json:"count,omitempty"`
+
+ // Reverse - [Optional] If true, will sort results newest first.
+ Reverse bool `json:"reverse,omitempty"`
+
+ // Start - [Optional] Starting ID for results.
+ Start int32 `json:"start,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p ChatGetParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p ChatGetParams) ToURLVals(path string) (string, error) {
+ values, err := StructValsToURLVals(&p)
+ if err != nil {
+ return "", err
+ }
+ return common.EncodeURLValues(path, values), nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p ChatGetParams) IsNil() bool {
+ if p == (ChatGetParams{}) {
+ return true
+ }
+ return false
+}
+
+// ChatSendParams contains all the parameters to send to the API endpoint
+type ChatSendParams struct {
+ // ChannelID - Channel to post to. Default 1 (English).
+ ChannelID float64 `json:"channelID,omitempty"`
+
+ // Message to send
+ Message string `json:"message,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p ChatSendParams) VerifyData() error {
+ if p.ChannelID == 0 || p.Message == "" {
+ return errors.New("ChatSendParams error params not correctly set")
+ }
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p ChatSendParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p ChatSendParams) IsNil() bool {
+ if p == (ChatSendParams{}) {
+ return true
+ }
+ return false
+}
+
+// GenericRequestParams contains all the parameters for some general functions
+type GenericRequestParams struct {
+ // Columns - [Optional] Array of column names to fetch. If omitted, will
+ // return all columns.
+ // NOTE that this method will always return item keys, even when not
+ // specified, so you may receive more columns that you expect.
+ Columns string `json:"columns,omitempty"`
+
+ // Count - Number of results to fetch.
+ Count int32 `json:"count,omitempty"`
+
+ // EndTime - Ending date filter for results.
+ EndTime string `json:"endTime,omitempty"`
+
+ // Filter - Generic table filter. Send JSON key/value pairs, such as
+ // `{"key": "value"}`. You can key on individual fields, and do more advanced
+ // querying on timestamps. See the
+ // [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters)
+ // for more details.
+ Filter string `json:"filter,omitempty"`
+
+ // Reverse - If true, will sort results newest first.
+ Reverse bool `json:"reverse,omitempty"`
+
+ // Start - Starting point for results.
+ Start int32 `json:"start,omitempty"`
+
+ // StartTime - Starting date filter for results.
+ StartTime string `json:"startTime,omitempty"`
+
+ // Symbol - Instrument symbol. Send a bare series (e.g. XBU) to get data for
+ // the nearest expiring contract in that series.
+ // You can also send a timeframe, e.g. `XBU:monthly`. Timeframes are `daily`,
+ // `weekly`, `monthly`, `quarterly`, and `biquarterly`.
+ Symbol string `json:"symbol,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p GenericRequestParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p GenericRequestParams) ToURLVals(path string) (string, error) {
+ values, err := StructValsToURLVals(&p)
+ if err != nil {
+ return "", err
+ }
+ return common.EncodeURLValues(path, values), nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p GenericRequestParams) IsNil() bool {
+ if p == (GenericRequestParams{}) {
+ return true
+ }
+ return false
+}
+
+// LeaderboardGetParams contains all the parameters to send to the API endpoint
+type LeaderboardGetParams struct {
+ // MethodRanking - [Optional] type. Options: "notional", "ROE"
+ Method string `json:"method,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p LeaderboardGetParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p LeaderboardGetParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p LeaderboardGetParams) IsNil() bool {
+ if p == (LeaderboardGetParams{}) {
+ return true
+ }
+ return false
+}
+
+// OrderNewParams contains all the parameters to send to the API endpoint
+type OrderNewParams struct {
+ // ClOrdID - [Optional] Client Order ID. This clOrdID will come back on the
+ // order and any related executions.
+ ClOrdID string `json:"clOrdID,omitempty"`
+
+ // ClOrdLinkID - [Optional] Client Order Link ID for contingent orders.
+ ClOrdLinkID string `json:"clOrdLinkID,omitempty"`
+
+ // ContingencyType - [Optional] contingency type for use with `clOrdLinkID`.
+ // Valid options: OneCancelsTheOther, OneTriggersTheOther,
+ // OneUpdatesTheOtherAbsolute, OneUpdatesTheOtherProportional.
+ ContingencyType string `json:"contingencyType,omitempty"`
+
+ // DisplayQty - [Optional] quantity to display in the book. Use 0 for a fully
+ // hidden order.
+ DisplayQty int32 `json:"displayQty,omitempty"`
+
+ // ExecInst - [Optional] execution instructions. Valid options:
+ // ParticipateDoNotInitiate, AllOrNone, MarkPrice, IndexPrice, LastPrice,
+ // Close, ReduceOnly, Fixed. 'AllOrNone' instruction requires `displayQty`
+ // to be 0. 'MarkPrice', 'IndexPrice' or 'LastPrice' instruction valid for
+ // 'Stop', 'StopLimit', 'MarketIfTouched', and 'LimitIfTouched' orders.
+ ExecInst string `json:"execInst,omitempty"`
+
+ // OrdType - Order type. Valid options: Market, Limit, Stop, StopLimit,
+ // MarketIfTouched, LimitIfTouched, MarketWithLeftOverAsLimit, Pegged.
+ // Defaults to 'Limit' when `price` is specified. Defaults to 'Stop' when
+ // `stopPx` is specified. Defaults to 'StopLimit' when `price` and `stopPx`
+ // are specified.
+ OrdType string `json:"ordType,omitempty"`
+
+ //OrderQty Order quantity in units of the instrument (i.e. contracts).
+ OrderQty int32 `json:"orderQty,omitempty"`
+
+ // PegOffsetValue - [Optional] trailing offset from the current price for
+ // 'Stop', 'StopLimit', 'MarketIfTouched', and 'LimitIfTouched' orders; use a
+ // negative offset for stop-sell orders and buy-if-touched orders. [Optional]
+ // offset from the peg price for 'Pegged' orders.
+ PegOffsetValue float64 `json:"pegOffsetValue,omitempty"`
+
+ // PegPriceType - [Optional] peg price type. Valid options: LastPeg,
+ // MidPricePeg, MarketPeg, PrimaryPeg, TrailingStopPeg.
+ PegPriceType string `json:"pegPriceType,omitempty"`
+
+ // Price - [Optional] limit price for 'Limit', 'StopLimit', and
+ // 'LimitIfTouched' orders.
+ Price float64 `json:"price,omitempty"`
+
+ // Side - Order side. Valid options: Buy, Sell. Defaults to 'Buy' unless
+ // `orderQty` or `simpleOrderQty` is negative.
+ Side string `json:"side,omitempty"`
+
+ // SimpleOrderQty - Order quantity in units of the underlying instrument
+ // (i.e. Bitcoin).
+ SimpleOrderQty float64 `json:"simpleOrderQty,omitempty"`
+
+ // StopPx - [Optional] trigger price for 'Stop', 'StopLimit',
+ // 'MarketIfTouched', and 'LimitIfTouched' orders. Use a price below the
+ // current price for stop-sell orders and buy-if-touched orders. Use
+ // `execInst` of 'MarkPrice' or 'LastPrice' to define the current price used
+ // for triggering.
+ StopPx float64 `json:"stopPx,omitempty"`
+
+ // Symbol - Instrument symbol. e.g. 'XBTUSD'.
+ Symbol string `json:"symbol,omitempty"`
+
+ // Text - [Optional] order annotation. e.g. 'Take profit'.
+ Text string `json:"text,omitempty"`
+
+ // TimeInForce - Valid options: Day, GoodTillCancel, ImmediateOrCancel,
+ // FillOrKill. Defaults to 'GoodTillCancel' for 'Limit', 'StopLimit',
+ // 'LimitIfTouched', and 'MarketWithLeftOverAsLimit' orders.
+ TimeInForce string `json:"timeInForce,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p OrderNewParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p OrderNewParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p OrderNewParams) IsNil() bool {
+ if p == (OrderNewParams{}) {
+ return true
+ }
+ return false
+}
+
+// OrderAmendParams contains all the parameters to send to the API endpoint
+// for the order amend operation
+type OrderAmendParams struct {
+ // ClOrdID - [Optional] new Client Order ID, requires `origClOrdID`.
+ ClOrdID string `json:"clOrdID,omitempty"`
+
+ // LeavesQty - [Optional] leaves quantity in units of the instrument
+ // (i.e. contracts). Useful for amending partially filled orders.
+ LeavesQty int32 `json:"leavesQty,omitempty"`
+
+ OrderID string `json:"orderID,omitempty"`
+
+ // OrderQty - [Optional] order quantity in units of the instrument
+ // (i.e. contracts).
+ OrderQty int32 `json:"orderQty,omitempty"`
+
+ // OrigClOrdID - Client Order ID. See POST /order.
+ OrigClOrdID string `json:"origClOrdID,omitempty"`
+
+ // PegOffsetValue - [Optional] trailing offset from the current price for
+ // 'Stop', 'StopLimit', 'MarketIfTouched', and 'LimitIfTouched' orders; use a
+ // negative offset for stop-sell orders and buy-if-touched orders. [Optional]
+ // offset from the peg price for 'Pegged' orders.
+ PegOffsetValue float64 `json:"pegOffsetValue,omitempty"`
+
+ // Price - [Optional] limit price for 'Limit', 'StopLimit', and
+ // 'LimitIfTouched' orders.
+ Price float64 `json:"price,omitempty"`
+
+ // SimpleLeavesQty - [Optional] leaves quantity in units of the underlying
+ // instrument (i.e. Bitcoin). Useful for amending partially filled orders.
+ SimpleLeavesQty float64 `json:"simpleLeavesQty,omitempty"`
+
+ // SimpleOrderQty - [Optional] order quantity in units of the underlying
+ // instrument (i.e. Bitcoin).
+ SimpleOrderQty float64 `json:"simpleOrderQty,omitempty"`
+
+ // StopPx - [Optional] trigger price for 'Stop', 'StopLimit',
+ // 'MarketIfTouched', and 'LimitIfTouched' orders. Use a price below the
+ // current price for stop-sell orders and buy-if-touched orders.
+ StopPx float64 `json:"stopPx,omitempty"`
+
+ // Text - [Optional] amend annotation. e.g. 'Adjust skew'.
+ Text string `json:"text,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p OrderAmendParams) VerifyData() error {
+ if p.OrderID == "" {
+ return errors.New("verifydata() OrderNewParams error - OrderID not set")
+ }
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p OrderAmendParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p OrderAmendParams) IsNil() bool {
+ if p == (OrderAmendParams{}) {
+ return true
+ }
+ return false
+}
+
+// OrderCancelParams contains all the parameters to send to the API endpoint
+type OrderCancelParams struct {
+ // ClOrdID - Client Order ID(s). See POST /order.
+ ClOrdID string `json:"clOrdID,omitempty"`
+
+ // OrderID - Order ID(s).
+ OrderID string `json:"orderID,omitempty"`
+
+ // Text - [Optional] cancellation annotation. e.g. 'Spread Exceeded'.
+ Text string `json:"text,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p OrderCancelParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p OrderCancelParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p OrderCancelParams) IsNil() bool {
+ if p == (OrderCancelParams{}) {
+ return true
+ }
+ return false
+}
+
+// OrderCancelAllParams contains all the parameters to send to the API endpoint
+// for cancelling all your orders
+type OrderCancelAllParams struct {
+ // Filter - [Optional] filter for cancellation. Use to only cancel some
+ // orders, e.g. `{"side": "Buy"}`.
+ Filter string `json:"filter,omitempty"`
+
+ // Symbol - [Optional] symbol. If provided, only cancels orders for that
+ // symbol.
+ Symbol string `json:"symbol,omitempty"`
+
+ // Text - [Optional] cancellation annotation. e.g. 'Spread Exceeded'
+ Text string `json:"text,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p OrderCancelAllParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p OrderCancelAllParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p OrderCancelAllParams) IsNil() bool {
+ if p == (OrderCancelAllParams{}) {
+ return true
+ }
+ return false
+}
+
+// OrderAmendBulkParams contains all the parameters to send to the API endpoint
+type OrderAmendBulkParams struct {
+ // Orders - An array of orders.
+ Orders []OrderAmendParams `json:"orders,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p OrderAmendBulkParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p OrderAmendBulkParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p OrderAmendBulkParams) IsNil() bool {
+ if len(p.Orders) == 0 {
+ return true
+ }
+ return false
+}
+
+// OrderNewBulkParams contains all the parameters to send to the API endpoint
+type OrderNewBulkParams struct {
+ // Orders - An array of orders.
+ Orders []OrderNewParams `json:"orders,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p OrderNewBulkParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p OrderNewBulkParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p OrderNewBulkParams) IsNil() bool {
+ if len(p.Orders) == 0 {
+ return true
+ }
+ return false
+}
+
+// OrderCancelAllAfterParams contains all the parameters to send to the API
+// endpoint
+type OrderCancelAllAfterParams struct {
+ // Timeout in ms. Set to 0 to cancel this timer.
+ Timeout float64 `json:"timeout,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p OrderCancelAllAfterParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p OrderCancelAllAfterParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p OrderCancelAllAfterParams) IsNil() bool {
+ if p == (OrderCancelAllAfterParams{}) {
+ return true
+ }
+ return false
+}
+
+// OrderClosePositionParams contains all the parameters to send to the API
+// endpoint
+type OrderClosePositionParams struct {
+ // Price - [Optional] limit price.
+ Price float64 `json:"price,omitempty"`
+
+ // Symbol of position to close.
+ Symbol string `json:"symbol,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p OrderClosePositionParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p OrderClosePositionParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p OrderClosePositionParams) IsNil() bool {
+ if p == (OrderClosePositionParams{}) {
+ return true
+ }
+ return false
+}
+
+// OrderBookGetL2Params contains all the parameters to send to the API endpoint
+type OrderBookGetL2Params struct {
+ // Depth - Orderbook depth per side. Send 0 for full depth.
+ Depth int32 `json:"depth,omitempty"`
+
+ // Symbol -Instrument symbol. Send a series (e.g. XBT) to get data for the
+ // nearest contract in that series.
+ Symbol string `json:"symbol,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p OrderBookGetL2Params) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p OrderBookGetL2Params) ToURLVals(path string) (string, error) {
+ values, err := StructValsToURLVals(&p)
+ if err != nil {
+ return "", err
+ }
+ return common.EncodeURLValues(path, values), nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p OrderBookGetL2Params) IsNil() bool {
+ if p == (OrderBookGetL2Params{}) {
+ return true
+ }
+ return false
+}
+
+// PositionGetParams contains all the parameters to send to the API endpoint
+type PositionGetParams struct {
+
+ // Columns - Which columns to fetch. For example, send ["columnName"].
+ Columns string `json:"columns,omitempty"`
+
+ // Count - Number of rows to fetch.
+ Count int32 `json:"count,omitempty"`
+
+ // Filter - Table filter. For example, send {"symbol": "XBTUSD"}.
+ Filter string `json:"filter,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p PositionGetParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p PositionGetParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p PositionGetParams) IsNil() bool {
+ if p == (PositionGetParams{}) {
+ return true
+ }
+ return false
+}
+
+// PositionIsolateMarginParams contains all the parameters to send to the API
+// endpoint
+type PositionIsolateMarginParams struct {
+ // Enabled - True for isolated margin, false for cross margin.
+ Enabled bool `json:"enabled,omitempty"`
+
+ // Symbol - Position symbol to isolate.
+ Symbol string `json:"symbol,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p PositionIsolateMarginParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p PositionIsolateMarginParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p PositionIsolateMarginParams) IsNil() bool {
+ if p == (PositionIsolateMarginParams{}) {
+ return true
+ }
+ return false
+}
+
+// PositionUpdateLeverageParams contains all the parameters to send to the API
+// endpoint
+type PositionUpdateLeverageParams struct {
+ // Leverage - Leverage value. Send a number between 0.01 and 100 to enable
+ // isolated margin with a fixed leverage. Send 0 to enable cross margin.
+ Leverage float64 `json:"leverage,omitempty"`
+
+ // Symbol - Symbol of position to adjust.
+ Symbol string `json:"symbol,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p PositionUpdateLeverageParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p PositionUpdateLeverageParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p PositionUpdateLeverageParams) IsNil() bool {
+ if p == (PositionUpdateLeverageParams{}) {
+ return true
+ }
+ return false
+}
+
+// PositionUpdateRiskLimitParams contains all the parameters to send to the API
+// endpoint
+type PositionUpdateRiskLimitParams struct {
+ // RiskLimit - New Risk Limit, in Satoshis.
+ RiskLimit int64 `json:"riskLimit,omitempty"`
+
+ // Symbol - Symbol of position to update risk limit on.
+ Symbol string `json:"symbol,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p PositionUpdateRiskLimitParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p PositionUpdateRiskLimitParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p PositionUpdateRiskLimitParams) IsNil() bool {
+ if p == (PositionUpdateRiskLimitParams{}) {
+ return true
+ }
+ return false
+}
+
+// PositionTransferIsolatedMarginParams contains all the parameters to send to
+// the API endpoint
+type PositionTransferIsolatedMarginParams struct {
+ // Amount - Amount to transfer, in Satoshis. May be negative.
+ Amount int64 `json:"amount,omitempty"`
+
+ // Symbol - Symbol of position to isolate.
+ Symbol string `json:"symbol,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p PositionTransferIsolatedMarginParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p PositionTransferIsolatedMarginParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p PositionTransferIsolatedMarginParams) IsNil() bool {
+ if p == (PositionTransferIsolatedMarginParams{}) {
+ return true
+ }
+ return false
+}
+
+// QuoteGetBucketedParams contains all the parameters to send to the API
+// endpoint
+type QuoteGetBucketedParams struct {
+ // BinSize - Time interval to bucket by. Available options: [1m,5m,1h,1d].
+ BinSize string `json:"binSize,omitempty"`
+
+ // Columns - Array of column names to fetch. If omitted, will return all
+ // columns. NOTE that this method will always return item keys, even when not
+ // specified, so you may receive more columns that you expect.
+ Columns string `json:"columns,omitempty"`
+
+ // Count - Number of results to fetch.
+ Count int32 `json:"count,omitempty"`
+
+ // EndTime - Ending date filter for results.
+ EndTime string `json:"endTime,omitempty"`
+
+ // Filter - Generic table filter. Send JSON key/value pairs, such as
+ // `{"key": "value"}`. You can key on individual fields, and do more advanced
+ // querying on timestamps. See the
+ // [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters)
+ // for more details.
+ Filter string `json:"filter,omitempty"`
+
+ // Partial - If true, will send in-progress (incomplete) bins for the current
+ // time period.
+ Partial bool `json:"partial,omitempty"`
+
+ // Reverse - If true, will sort results newest first.
+ Reverse bool `json:"reverse,omitempty"`
+
+ // Start - Starting point for results.
+ Start int32 `json:"start,omitempty"`
+
+ // StartTime - Starting date filter for results.
+ StartTime string `json:"startTime,omitempty"`
+
+ // Symbol - Instrument symbol. Send a bare series (e.g. XBU) to get data for
+ // the nearest expiring contract in that series.You can also send a timeframe,
+ // e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`,
+ // `quarterly`, and `biquarterly`.
+ Symbol string `json:"symbol,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p QuoteGetBucketedParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p QuoteGetBucketedParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p QuoteGetBucketedParams) IsNil() bool {
+ if p == (QuoteGetBucketedParams{}) {
+ return true
+ }
+ return false
+}
+
+// TradeGetBucketedParams contains all the parameters to send to the API
+// endpoint
+type TradeGetBucketedParams struct {
+ // BinSize - Time interval to bucket by. Available options: [1m,5m,1h,1d].
+ BinSize string `json:"binSize,omitempty"`
+
+ // Columns - Array of column names to fetch. If omitted, will return all
+ // columns.
+ // Note that this method will always return item keys, even when not
+ // specified, so you may receive more columns that you expect.
+ Columns string `json:"columns,omitempty"`
+
+ // Count - Number of results to fetch.
+ Count int32 `json:"count,omitempty"`
+
+ // EndTime - Ending date filter for results.
+ EndTime string `json:"endTime,omitempty"`
+
+ // Filter - Generic table filter. Send JSON key/value pairs, such as
+ // `{"key": "value"}`. You can key on individual fields, and do more advanced
+ // querying on timestamps. See the
+ // [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters)
+ // for more details.
+ Filter string `json:"filter,omitempty"`
+
+ // Partial - If true, will send in-progress (incomplete) bins for the current
+ // time period.
+ Partial bool `json:"partial,omitempty"`
+
+ // Reverse - If true, will sort results newest first.
+ Reverse bool `json:"reverse,omitempty"`
+
+ // Start - Starting point for results.
+ Start int32 `json:"start,omitempty"`
+
+ // StartTime - Starting date filter for results.
+ StartTime string `json:"symbol,omitempty"`
+
+ // Symbol - Instrument symbol. Send a bare series (e.g. XBU) to get data for
+ // the nearest expiring contract in that series.You can also send a timeframe,
+ // e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`,
+ // `quarterly`, and `biquarterly`.
+ Symbol string `json:"symbol,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p TradeGetBucketedParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p TradeGetBucketedParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p TradeGetBucketedParams) IsNil() bool {
+ if p == (TradeGetBucketedParams{}) {
+ return true
+ }
+ return false
+}
+
+// UserUpdateParams contains all the parameters to send to the API endpoint
+type UserUpdateParams struct {
+ // Country - Country of residence.
+ Country string `json:"country,omitempty"`
+
+ // New Password string
+ NewPassword string `json:"newPassword,omitempty"`
+
+ // Confirmation string - must match
+ NewPasswordConfirm string `json:"newPasswordConfirm,omitempty"`
+
+ // old password string
+ OldPassword string `json:"oldPassword,omitempty"`
+
+ // PGP Public Key. If specified, automated emails will be sent with this key.
+ PgpPubKey string `json:"pgpPubKey,omitempty"`
+
+ // Username can only be set once. To reset, email support.
+ Username string `json:"username,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p UserUpdateParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p UserUpdateParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p UserUpdateParams) IsNil() bool {
+ if p == (UserUpdateParams{}) {
+ return true
+ }
+ return false
+}
+
+// UserTokenParams contains all the parameters to send to the API endpoint
+type UserTokenParams struct {
+ Token string `json:"token,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p UserTokenParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p UserTokenParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p UserTokenParams) IsNil() bool {
+ if p == (UserTokenParams{}) {
+ return true
+ }
+ return false
+}
+
+// UserCheckReferralCodeParams contains all the parameters to send to the API
+// endpoint
+type UserCheckReferralCodeParams struct {
+ ReferralCode string `json:"referralCode,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p UserCheckReferralCodeParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p UserCheckReferralCodeParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p UserCheckReferralCodeParams) IsNil() bool {
+ if p == (UserCheckReferralCodeParams{}) {
+ return true
+ }
+ return false
+}
+
+// UserConfirmTFAParams contains all the parameters to send to the API endpoint
+type UserConfirmTFAParams struct {
+ // Token - Token from your selected TFA type.
+ Token string `json:"token,omitempty"`
+
+ // Type - Two-factor auth type. Supported types: 'GA' (Google Authenticator),
+ // 'Yubikey'
+ Type string `json:"type,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p UserConfirmTFAParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p UserConfirmTFAParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p UserConfirmTFAParams) IsNil() bool {
+ if p == (UserConfirmTFAParams{}) {
+ return true
+ }
+ return false
+}
+
+// UserCurrencyParams contains all the parameters to send to the API endpoint
+type UserCurrencyParams struct {
+ Currency string `json:"currency,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p UserCurrencyParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p UserCurrencyParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p UserCurrencyParams) IsNil() bool {
+ if p == (UserCurrencyParams{}) {
+ return true
+ }
+ return false
+}
+
+// UserPreferencesParams contains all the parameters to send to the API
+// endpoint
+type UserPreferencesParams struct {
+ // Overwrite - If true, will overwrite all existing preferences.
+ Overwrite bool `json:"overwrite,omitempty"`
+ // Prefs - preferences
+ Prefs string `json:"prefs,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p UserPreferencesParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p UserPreferencesParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p UserPreferencesParams) IsNil() bool {
+ if p == (UserPreferencesParams{}) {
+ return true
+ }
+ return false
+}
+
+// UserRequestWithdrawalParams contains all the parameters to send to the API
+// endpoint
+type UserRequestWithdrawalParams struct {
+ // Address - Destination Address.
+ Address string `json:"address,omitempty"`
+
+ // Amount - Amount of withdrawal currency.
+ Amount int64 `json:"amount,omitempty"`
+
+ // Currency - Currency you're withdrawing. Options: `XBt`
+ Currency string `json:"currency,omitempty"`
+
+ // Fee - Network fee for Bitcoin withdrawals. If not specified, a default
+ // value will be calculated based on Bitcoin network conditions. You will have
+ // a chance to confirm this via email.
+ Fee float64 `json:"fee,omitempty"`
+
+ // OtpToken - 2FA token. Required if 2FA is enabled on your account.
+ OtpToken string `json:"otpToken,omitempty"`
+}
+
+// VerifyData verifies outgoing data sets
+func (p UserRequestWithdrawalParams) VerifyData() error {
+ return nil
+}
+
+// ToURLVals converts struct values to url.values and encodes it on the supplied
+// path
+func (p UserRequestWithdrawalParams) ToURLVals(path string) (string, error) {
+ return "", nil
+}
+
+// IsNil checks to see if any values has been set for the paramater
+func (p UserRequestWithdrawalParams) IsNil() bool {
+ if p == (UserRequestWithdrawalParams{}) {
+ return true
+ }
+ return false
+}
diff --git a/exchanges/bitmex/bitmex_test.go b/exchanges/bitmex/bitmex_test.go
new file mode 100644
index 00000000..d0ac7dd7
--- /dev/null
+++ b/exchanges/bitmex/bitmex_test.go
@@ -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)
+ }
+}
diff --git a/exchanges/bitmex/bitmex_types.go b/exchanges/bitmex/bitmex_types.go
new file mode 100644
index 00000000..d6d4030b
--- /dev/null
+++ b/exchanges/bitmex/bitmex_types.go
@@ -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"`
+}
diff --git a/exchanges/bitmex/bitmex_websocket.go b/exchanges/bitmex/bitmex_websocket.go
new file mode 100644
index 00000000..0d199816
--- /dev/null
+++ b/exchanges/bitmex/bitmex_websocket.go
@@ -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
+ }
+ }
+}
diff --git a/exchanges/bitmex/bitmex_websocket_types.go b/exchanges/bitmex/bitmex_websocket_types.go
new file mode 100644
index 00000000..d895762e
--- /dev/null
+++ b/exchanges/bitmex/bitmex_websocket_types.go
@@ -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"`
+}
diff --git a/exchanges/bitmex/bitmex_wrapper.go b/exchanges/bitmex/bitmex_wrapper.go
new file mode 100644
index 00000000..f9141b64
--- /dev/null
+++ b/exchanges/bitmex/bitmex_wrapper.go
@@ -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")
+}
diff --git a/exchanges/bitmex/swagger/swagger.json b/exchanges/bitmex/swagger/swagger.json
new file mode 100644
index 00000000..e1232a61
--- /dev/null
+++ b/exchanges/bitmex/swagger/swagger.json
@@ -0,0 +1,6125 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "title": "BitMEX Testnet API",
+ "description": "## REST API for the BitMEX Trading Platform\n\n[View Changelog](/app/apiChangelog)\n\n----\n\n#### Getting Started\n\nBase URI: [https://testnet.bitmex.com/api/v1](/api/v1)\n\n##### Fetching Data\n\nAll REST endpoints are documented below. You can try out any query right from this interface.\n\nMost table queries accept `count`, `start`, and `reverse` params. Set `reverse=true` to get rows newest-first.\n\nAdditional documentation regarding filters, timestamps, and authentication\nis available in [the main API documentation](/app/restAPI).\n\n*All* table data is available via the [Websocket](/app/wsAPI). We highly recommend using the socket if you want\nto have the quickest possible data without being subject to ratelimits.\n\n##### Return Types\n\nBy default, all data is returned as JSON. Send `?_format=csv` to get CSV data or `?_format=xml` to get XML data.\n\n##### Trade Data Queries\n\n*This is only a small subset of what is available, to get you started.*\n\nFill in the parameters and click the `Try it out!` button to try any of these queries.\n\n* [Pricing Data](#!/Quote/Quote_get)\n\n* [Trade Data](#!/Trade/Trade_get)\n\n* [OrderBook Data](#!/OrderBook/OrderBook_getL2)\n\n* [Settlement Data](#!/Settlement/Settlement_get)\n\n* [Exchange Statistics](#!/Stats/Stats_history)\n\nEvery function of the BitMEX.com platform is exposed here and documented. Many more functions are available.\n\n##### Swagger Specification\n\n[⇩ Download Swagger JSON](swagger.json)\n\n----\n\n## All API Endpoints\n\nClick to expand a section.\n",
+ "termsOfService": "https://testnet.bitmex.com/app/terms",
+ "contact": {
+ "email": "support@bitmex.com"
+ },
+ "version": "1.2.0"
+ },
+ "basePath": "/api/v1",
+ "paths": {
+ "/announcement": {
+ "get": {
+ "tags": ["Announcement"],
+ "summary": "Get site announcements.",
+ "operationId": "Announcement.get",
+ "parameters": [{
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Announcement"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/announcement/urgent": {
+ "get": {
+ "tags": ["Announcement"],
+ "summary": "Get urgent (banner) announcements.",
+ "operationId": "Announcement.getUrgent",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Announcement"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/apiKey": {
+ "post": {
+ "tags": ["APIKey"],
+ "summary": "Create a new API Key.",
+ "description": "API Keys can only be created via the frontend.",
+ "operationId": "APIKey.new",
+ "parameters": [{
+ "name": "name",
+ "in": "formData",
+ "description": "Key name. This name is for reference only.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "cidr",
+ "in": "formData",
+ "description": "CIDR block to restrict this key to. To restrict to a single address, append \"/32\", e.g. 207.39.29.22/32. Leave blank or set to 0.0.0.0/0 to allow all IPs. Only one block may be set. More on CIDR blocks",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "permissions",
+ "in": "formData",
+ "description": "Key Permissions. All keys can read margin and position data. Additional permissions must be added. Available: [\"order\", \"orderCancel\", \"withdraw\"].",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "enabled",
+ "in": "formData",
+ "description": "Set to true to enable this key on creation. Otherwise, it must be explicitly enabled via /apiKey/enable.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "token",
+ "in": "formData",
+ "description": "OTP Token (YubiKey, Google Authenticator)",
+ "required": false,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/APIKey"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ },
+ "get": {
+ "tags": ["APIKey"],
+ "summary": "Get your API Keys.",
+ "operationId": "APIKey.get",
+ "parameters": [{
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/APIKey"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ },
+ "delete": {
+ "tags": ["APIKey"],
+ "summary": "Remove an API Key.",
+ "operationId": "APIKey.remove",
+ "parameters": [{
+ "name": "apiKeyID",
+ "in": "formData",
+ "description": "API Key ID (public component).",
+ "required": true,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "object",
+ "properties": {
+ "success": {
+ "type": "boolean"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/apiKey/disable": {
+ "post": {
+ "tags": ["APIKey"],
+ "summary": "Disable an API Key.",
+ "operationId": "APIKey.disable",
+ "parameters": [{
+ "name": "apiKeyID",
+ "in": "formData",
+ "description": "API Key ID (public component).",
+ "required": true,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/APIKey"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/apiKey/enable": {
+ "post": {
+ "tags": ["APIKey"],
+ "summary": "Enable an API Key.",
+ "operationId": "APIKey.enable",
+ "parameters": [{
+ "name": "apiKeyID",
+ "in": "formData",
+ "description": "API Key ID (public component).",
+ "required": true,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/APIKey"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/chat": {
+ "get": {
+ "tags": ["Chat"],
+ "summary": "Get chat messages.",
+ "operationId": "Chat.get",
+ "parameters": [{
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting ID for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": true,
+ "type": "boolean"
+ }, {
+ "name": "channelID",
+ "in": "query",
+ "description": "Channel id. GET /chat/channels for ids. Leave blank for all.",
+ "required": false,
+ "type": "number",
+ "format": "double"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Chat"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ },
+ "post": {
+ "tags": ["Chat"],
+ "summary": "Send a chat message.",
+ "operationId": "Chat.new",
+ "parameters": [{
+ "name": "message",
+ "in": "formData",
+ "required": true,
+ "type": "string"
+ }, {
+ "name": "channelID",
+ "in": "formData",
+ "description": "Channel to post to. Default 1 (English).",
+ "required": false,
+ "default": 1,
+ "type": "number",
+ "format": "double"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/Chat"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/chat/channels": {
+ "get": {
+ "tags": ["Chat"],
+ "summary": "Get available channels.",
+ "operationId": "Chat.getChannels",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/ChatChannel"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/chat/connected": {
+ "get": {
+ "tags": ["Chat"],
+ "summary": "Get connected users.",
+ "description": "Returns an array with browser users in the first position and API users (bots) in the second position.",
+ "operationId": "Chat.getConnected",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/ConnectedUsers"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/execution": {
+ "get": {
+ "tags": ["Execution"],
+ "summary": "Get all raw executions for your account.",
+ "description": "This returns all raw transactions, which includes order opening and cancelation, and order status\nchanges. It can be quite noisy. More focused information is available at `/execution/tradeHistory`.\n\nYou may also use the `filter` param to target your query. Specify an array as a filter value, such as\n`{\"execType\": [\"Settlement\", \"Trade\"]}` to filter on multiple values.\n\nSee [the FIX Spec](http://www.onixs.biz/fix-dictionary/5.0.SP2/msgType_8_8.html) for explanations of these fields.\n",
+ "operationId": "Execution.get",
+ "parameters": [{
+ "name": "symbol",
+ "in": "query",
+ "description": "Instrument symbol. Send a bare series (e.g. XBU) to get data for the nearest expiring contract in that series.\n\nYou can also send a timeframe, e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`, `quarterly`, and `biquarterly`.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "query",
+ "description": "Generic table filter. Send JSON key/value pairs, such as `{\"key\": \"value\"}`. You can key on individual fields, and do more advanced querying on timestamps. See the [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters) for more details.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.\n\nNote that this method will always return item keys, even when not specified, so you may receive more columns that you expect.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting point for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "startTime",
+ "in": "query",
+ "description": "Starting date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }, {
+ "name": "endTime",
+ "in": "query",
+ "description": "Ending date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Execution"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/execution/tradeHistory": {
+ "get": {
+ "tags": ["Execution"],
+ "summary": "Get all balance-affecting executions. This includes each trade, insurance charge, and settlement.",
+ "operationId": "Execution.getTradeHistory",
+ "parameters": [{
+ "name": "symbol",
+ "in": "query",
+ "description": "Instrument symbol. Send a bare series (e.g. XBU) to get data for the nearest expiring contract in that series.\n\nYou can also send a timeframe, e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`, `quarterly`, and `biquarterly`.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "query",
+ "description": "Generic table filter. Send JSON key/value pairs, such as `{\"key\": \"value\"}`. You can key on individual fields, and do more advanced querying on timestamps. See the [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters) for more details.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.\n\nNote that this method will always return item keys, even when not specified, so you may receive more columns that you expect.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting point for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "startTime",
+ "in": "query",
+ "description": "Starting date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }, {
+ "name": "endTime",
+ "in": "query",
+ "description": "Ending date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Execution"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/funding": {
+ "get": {
+ "tags": ["Funding"],
+ "summary": "Get funding history.",
+ "operationId": "Funding.get",
+ "parameters": [{
+ "name": "symbol",
+ "in": "query",
+ "description": "Instrument symbol. Send a bare series (e.g. XBU) to get data for the nearest expiring contract in that series.\n\nYou can also send a timeframe, e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`, `quarterly`, and `biquarterly`.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "query",
+ "description": "Generic table filter. Send JSON key/value pairs, such as `{\"key\": \"value\"}`. You can key on individual fields, and do more advanced querying on timestamps. See the [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters) for more details.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.\n\nNote that this method will always return item keys, even when not specified, so you may receive more columns that you expect.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting point for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "startTime",
+ "in": "query",
+ "description": "Starting date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }, {
+ "name": "endTime",
+ "in": "query",
+ "description": "Ending date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Funding"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/instrument": {
+ "get": {
+ "tags": ["Instrument"],
+ "summary": "Get instruments.",
+ "description": "This returns all instruments and indices, including those that have settled or are unlisted. Use this endpoint if you want to query for individual instruments or use a complex filter. Use `/instrument/active` to return active instruments, or use a filter like `{\"state\": \"Open\"}`.",
+ "operationId": "Instrument.get",
+ "parameters": [{
+ "name": "symbol",
+ "in": "query",
+ "description": "Instrument symbol. Send a bare series (e.g. XBU) to get data for the nearest expiring contract in that series.\n\nYou can also send a timeframe, e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`, `quarterly`, and `biquarterly`.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "query",
+ "description": "Generic table filter. Send JSON key/value pairs, such as `{\"key\": \"value\"}`. You can key on individual fields, and do more advanced querying on timestamps. See the [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters) for more details.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.\n\nNote that this method will always return item keys, even when not specified, so you may receive more columns that you expect.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting point for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "startTime",
+ "in": "query",
+ "description": "Starting date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }, {
+ "name": "endTime",
+ "in": "query",
+ "description": "Ending date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Instrument"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/instrument/active": {
+ "get": {
+ "tags": ["Instrument"],
+ "summary": "Get all active instruments and instruments that have expired in <24hrs.",
+ "operationId": "Instrument.getActive",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Instrument"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/instrument/indices": {
+ "get": {
+ "tags": ["Instrument"],
+ "summary": "Get all price indices.",
+ "operationId": "Instrument.getIndices",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Instrument"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/instrument/activeAndIndices": {
+ "get": {
+ "tags": ["Instrument"],
+ "summary": "Helper method. Gets all active instruments and all indices. This is a join of the result of /indices and /active.",
+ "operationId": "Instrument.getActiveAndIndices",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Instrument"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/instrument/activeIntervals": {
+ "get": {
+ "tags": ["Instrument"],
+ "summary": "Return all active contract series and interval pairs.",
+ "description": "This endpoint is useful for determining which pairs are live. It returns two arrays of strings. The first is intervals, such as `[\"XBT:perpetual\", \"XBT:monthly\", \"XBT:quarterly\", \"ETH:monthly\", ...]`. These identifiers are usable in any query's `symbol` param. The second array is the current resolution of these intervals. Results are mapped at the same index.",
+ "operationId": "Instrument.getActiveIntervals",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/InstrumentInterval"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/instrument/compositeIndex": {
+ "get": {
+ "tags": ["Instrument"],
+ "summary": "Show constituent parts of an index.",
+ "description": "Composite indices are built from multiple external price sources.\n\nUse this endpoint to get the underlying prices of an index. For example, send a `symbol` of `.XBT` to\nget the ticks and weights of the constituent exchanges that build the \".XBT\" index.\n\nA tick with reference `\"BMI\"` and weight `null` is the composite index tick.\n",
+ "operationId": "Instrument.getCompositeIndex",
+ "parameters": [{
+ "name": "symbol",
+ "in": "query",
+ "description": "The composite index symbol.",
+ "required": false,
+ "default": ".XBT",
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "query",
+ "description": "Generic table filter. Send JSON key/value pairs, such as `{\"key\": \"value\"}`. You can key on individual fields, and do more advanced querying on timestamps. See the [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters) for more details.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.\n\nNote that this method will always return item keys, even when not specified, so you may receive more columns that you expect.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting point for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "startTime",
+ "in": "query",
+ "description": "Starting date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }, {
+ "name": "endTime",
+ "in": "query",
+ "description": "Ending date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/IndexComposite"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/insurance": {
+ "get": {
+ "tags": ["Insurance"],
+ "summary": "Get insurance fund history.",
+ "operationId": "Insurance.get",
+ "parameters": [{
+ "name": "symbol",
+ "in": "query",
+ "description": "Instrument symbol. Send a bare series (e.g. XBU) to get data for the nearest expiring contract in that series.\n\nYou can also send a timeframe, e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`, `quarterly`, and `biquarterly`.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "query",
+ "description": "Generic table filter. Send JSON key/value pairs, such as `{\"key\": \"value\"}`. You can key on individual fields, and do more advanced querying on timestamps. See the [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters) for more details.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.\n\nNote that this method will always return item keys, even when not specified, so you may receive more columns that you expect.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting point for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "startTime",
+ "in": "query",
+ "description": "Starting date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }, {
+ "name": "endTime",
+ "in": "query",
+ "description": "Ending date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Insurance"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/leaderboard": {
+ "get": {
+ "tags": ["Leaderboard"],
+ "summary": "Get current leaderboard.",
+ "operationId": "Leaderboard.get",
+ "parameters": [{
+ "name": "method",
+ "in": "query",
+ "description": "Ranking type. Options: \"notional\", \"ROE\"",
+ "required": false,
+ "default": "notional",
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Leaderboard"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/leaderboard/name": {
+ "get": {
+ "tags": ["Leaderboard"],
+ "summary": "Get your alias on the leaderboard.",
+ "operationId": "Leaderboard.getName",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/liquidation": {
+ "get": {
+ "tags": ["Liquidation"],
+ "summary": "Get liquidation orders.",
+ "operationId": "Liquidation.get",
+ "parameters": [{
+ "name": "symbol",
+ "in": "query",
+ "description": "Instrument symbol. Send a bare series (e.g. XBU) to get data for the nearest expiring contract in that series.\n\nYou can also send a timeframe, e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`, `quarterly`, and `biquarterly`.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "query",
+ "description": "Generic table filter. Send JSON key/value pairs, such as `{\"key\": \"value\"}`. You can key on individual fields, and do more advanced querying on timestamps. See the [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters) for more details.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.\n\nNote that this method will always return item keys, even when not specified, so you may receive more columns that you expect.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting point for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "startTime",
+ "in": "query",
+ "description": "Starting date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }, {
+ "name": "endTime",
+ "in": "query",
+ "description": "Ending date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Liquidation"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/notification": {
+ "get": {
+ "tags": ["Notification"],
+ "summary": "Get your current notifications.",
+ "description": "This is an upcoming feature and currently does not return data.",
+ "operationId": "Notification.get",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Notification"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/order": {
+ "get": {
+ "tags": ["Order"],
+ "summary": "Get your orders.",
+ "description": "To get open orders only, send {\"open\": true} in the filter param.\n\nSee the FIX Spec for explanations of these fields.",
+ "operationId": "Order.getOrders",
+ "parameters": [{
+ "name": "symbol",
+ "in": "query",
+ "description": "Instrument symbol. Send a bare series (e.g. XBU) to get data for the nearest expiring contract in that series.\n\nYou can also send a timeframe, e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`, `quarterly`, and `biquarterly`.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "query",
+ "description": "Generic table filter. Send JSON key/value pairs, such as `{\"key\": \"value\"}`. You can key on individual fields, and do more advanced querying on timestamps. See the [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters) for more details.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.\n\nNote that this method will always return item keys, even when not specified, so you may receive more columns that you expect.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting point for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "startTime",
+ "in": "query",
+ "description": "Starting date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }, {
+ "name": "endTime",
+ "in": "query",
+ "description": "Ending date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Order"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ },
+ "post": {
+ "tags": ["Order"],
+ "summary": "Create a new order.",
+ "description": "## Placing Orders\n\nThis endpoint is used for placing orders. See individual fields below for more details on their use.\n\n#### Order Types\n\nAll orders require a `symbol`. All other fields are optional except when otherwise specified.\n\nThese are the valid `ordType`s:\n\n* **Limit**: The default order type. Specify an `orderQty` and `price`.\n* **Market**: A traditional Market order. A Market order will execute until filled or your bankruptcy price is reached, at\n which point it will cancel.\n* **MarketWithLeftOverAsLimit**: A market order that, after eating through the order book as far as\n permitted by available margin, will become a limit order. The difference between this type and `Market` only\n affects the behavior in thin books. Upon reaching the deepest possible price, if there is quantity left over,\n a `Market` order will cancel the remaining quantity. `MarketWithLeftOverAsLimit` will keep the remaining\n quantity in the books as a `Limit`.\n* **Stop**: A Stop Market order. Specify an `orderQty` and `stopPx`. When the `stopPx` is reached, the order will be entered\n into the book.\n * On sell orders, the order will trigger if the triggering price is lower than the `stopPx`. On buys, higher.\n * Note: Stop orders do not consume margin until triggered. Be sure that the required margin is available in your\n account so that it may trigger fully.\n * `Close` Stops don't require an `orderQty`. See Execution Instructions below.\n* **StopLimit**: Like a Stop Market, but enters a Limit order instead of a Market order. Specify an `orderQty`, `stopPx`,\n and `price`.\n* **MarketIfTouched**: Similar to a Stop, but triggers are done in the opposite direction. Useful for Take Profit orders.\n* **LimitIfTouched**: As above; use for Take Profit Limit orders.\n\n#### Execution Instructions\n\nThe following `execInst`s are supported. If using multiple, separate with a comma (e.g. `LastPrice,Close`).\n\n* **ParticipateDoNotInitiate**: Also known as a Post-Only order. If this order would have executed on placement,\n it will cancel instead.\n* **MarkPrice, LastPrice, IndexPrice**: Used by stop and if-touched orders to determine the triggering price.\n Use only one. By default, `'MarkPrice'` is used. Also used for Pegged orders to define the value of `'LastPeg'`.\n* **ReduceOnly**: A `'ReduceOnly'` order can only reduce your position, not increase it. If you have a `'ReduceOnly'`\n limit order that rests in the order book while the position is reduced by other orders, then its order quantity will\n be amended down or canceled. If there are multiple `'ReduceOnly'` orders the least aggressive will be amended first.\n* **Close**: `'Close'` implies `'ReduceOnly'`. A `'Close'` order will cancel other active limit orders with the same side\n and symbol if the open quantity exceeds the current position. This is useful for stops: by canceling these orders, a\n `'Close'` Stop is ensured to have the margin required to execute, and can only execute up to the full size of your\n position. If `orderQty` is not specified, a `'Close'` order has an `orderQty` equal to your current position's size.\n * Note that a `Close` order without an `orderQty` requires a `side`, so that BitMEX knows if it should trigger\n above or below the `stopPx`.\n\n#### Linked Orders\n\nLinked Orders are an advanced capability. It is very powerful, but its use requires careful coding and testing.\nPlease follow this document carefully and use the [Testnet Exchange](https://testnet.bitmex.com) while developing.\n\nBitMEX offers four advanced Linked Order types:\n\n* **OCO**: *One Cancels the Other*. A very flexible version of the standard Stop / Take Profit technique.\n Multiple orders may be linked together using a single `clOrdLinkID`. Send a `contingencyType` of\n `OneCancelsTheOther` on the orders. The first order that fully or partially executes (or activates\n for `Stop` orders) will cancel all other orders with the same `clOrdLinkID`.\n* **OTO**: *One Triggers the Other*. Send a `contingencyType` of `'OneTriggersTheOther'` on the primary order and\n then subsequent orders with the same `clOrdLinkID` will be not be triggered until the primary order fully executes.\n* **OUOA**: *One Updates the Other Absolute*. Send a `contingencyType` of `'OneUpdatesTheOtherAbsolute'` on the orders. Then\n as one order has a execution, other orders with the same `clOrdLinkID` will have their order quantity amended\n down by the execution quantity.\n* **OUOP**: *One Updates the Other Proportional*. Send a `contingencyType` of `'OneUpdatesTheOtherProportional'` on the orders. Then\n as one order has a execution, other orders with the same `clOrdLinkID` will have their order quantity reduced proportionally\n by the fill percentage.\n\n#### Trailing Stops\n\nYou may use `pegPriceType` of `'TrailingStopPeg'` to create Trailing Stops. The pegged `stopPx` will move as the market\nmoves away from the peg, and freeze as the market moves toward it.\n\nTo use, combine with `pegOffsetValue` to set the `stopPx` of your order. The peg is set to the triggering price\nspecified in the `execInst` (default `'MarkPrice'`). Use a negative offset for stop-sell and buy-if-touched orders.\n\nRequires `ordType`: `'Stop', 'StopLimit', 'MarketIfTouched', 'LimitIfTouched'`.\n\n#### Simple Quantities\n\nSend a `simpleOrderQty` instead of an `orderQty` to create an order denominated in the underlying currency.\nThis is useful for opening up a position with 1 XBT of exposure without having to calculate how many contracts it is.\n\n#### Rate Limits\n\nSee the [Bulk Order Documentation](#!/Order/Order_newBulk) if you need to place multiple orders at the same time.\nBulk orders require fewer risk checks in the trading engine and thus are ratelimited at **1/10** the normal rate.\n\nYou can also improve your reactivity to market movements while staying under your ratelimit by using the\n[Amend](#!/Order/Order_amend) and [Amend Bulk](#!/Order/Order_amendBulk) endpoints. This allows you to stay\nin the market and avoids the cancel/replace cycle.\n\n#### Tracking Your Orders\n\nIf you want to keep track of order IDs yourself, set a unique `clOrdID` per order.\nThis `clOrdID` will come back as a property on the order and any related executions (including on the WebSocket),\nand can be used to get or cancel the order. Max length is 36 characters.\n\nYou can also change the `clOrdID` by amending an order, supplying an `origClOrdID`, and your desired new\nID as the `clOrdID` param, like so:\n\n```\n# Amends an order's leavesQty, and updates its clOrdID to \"def-456\"\nPUT /api/v1/order {\"origClOrdID\": \"abc-123\", \"clOrdID\": \"def-456\", \"leavesQty\": 1000}\n```\n",
+ "operationId": "Order.new",
+ "parameters": [{
+ "name": "symbol",
+ "in": "formData",
+ "description": "Instrument symbol. e.g. 'XBTUSD'.",
+ "required": true,
+ "type": "string"
+ }, {
+ "name": "side",
+ "in": "formData",
+ "description": "Order side. Valid options: Buy, Sell. Defaults to 'Buy' unless `orderQty` or `simpleOrderQty` is negative.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "simpleOrderQty",
+ "in": "formData",
+ "description": "Order quantity in units of the underlying instrument (i.e. Bitcoin).",
+ "required": false,
+ "type": "number",
+ "format": "double"
+ }, {
+ "name": "orderQty",
+ "in": "formData",
+ "description": "Order quantity in units of the instrument (i.e. contracts).",
+ "required": false,
+ "format": "int32",
+ "type": "number"
+ }, {
+ "name": "price",
+ "in": "formData",
+ "description": "Optional limit price for 'Limit', 'StopLimit', and 'LimitIfTouched' orders.",
+ "required": false,
+ "type": "number",
+ "format": "double"
+ }, {
+ "name": "displayQty",
+ "in": "formData",
+ "description": "Optional quantity to display in the book. Use 0 for a fully hidden order.",
+ "required": false,
+ "format": "int32",
+ "type": "number"
+ }, {
+ "name": "stopPx",
+ "in": "formData",
+ "description": "Optional trigger price for 'Stop', 'StopLimit', 'MarketIfTouched', and 'LimitIfTouched' orders. Use a price below the current price for stop-sell orders and buy-if-touched orders. Use `execInst` of 'MarkPrice' or 'LastPrice' to define the current price used for triggering.",
+ "required": false,
+ "type": "number",
+ "format": "double"
+ }, {
+ "name": "clOrdID",
+ "in": "formData",
+ "description": "Optional Client Order ID. This clOrdID will come back on the order and any related executions.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "clOrdLinkID",
+ "in": "formData",
+ "description": "Optional Client Order Link ID for contingent orders.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "pegOffsetValue",
+ "in": "formData",
+ "description": "Optional trailing offset from the current price for 'Stop', 'StopLimit', 'MarketIfTouched', and 'LimitIfTouched' orders; use a negative offset for stop-sell orders and buy-if-touched orders. Optional offset from the peg price for 'Pegged' orders.",
+ "required": false,
+ "type": "number",
+ "format": "double"
+ }, {
+ "name": "pegPriceType",
+ "in": "formData",
+ "description": "Optional peg price type. Valid options: LastPeg, MidPricePeg, MarketPeg, PrimaryPeg, TrailingStopPeg.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "ordType",
+ "in": "formData",
+ "description": "Order type. Valid options: Market, Limit, Stop, StopLimit, MarketIfTouched, LimitIfTouched, MarketWithLeftOverAsLimit, Pegged. Defaults to 'Limit' when `price` is specified. Defaults to 'Stop' when `stopPx` is specified. Defaults to 'StopLimit' when `price` and `stopPx` are specified.",
+ "required": false,
+ "default": "Limit",
+ "type": "string"
+ }, {
+ "name": "timeInForce",
+ "in": "formData",
+ "description": "Time in force. Valid options: Day, GoodTillCancel, ImmediateOrCancel, FillOrKill. Defaults to 'GoodTillCancel' for 'Limit', 'StopLimit', 'LimitIfTouched', and 'MarketWithLeftOverAsLimit' orders.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "execInst",
+ "in": "formData",
+ "description": "Optional execution instructions. Valid options: ParticipateDoNotInitiate, AllOrNone, MarkPrice, IndexPrice, LastPrice, Close, ReduceOnly, Fixed. 'AllOrNone' instruction requires `displayQty` to be 0. 'MarkPrice', 'IndexPrice' or 'LastPrice' instruction valid for 'Stop', 'StopLimit', 'MarketIfTouched', and 'LimitIfTouched' orders.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "contingencyType",
+ "in": "formData",
+ "description": "Optional contingency type for use with `clOrdLinkID`. Valid options: OneCancelsTheOther, OneTriggersTheOther, OneUpdatesTheOtherAbsolute, OneUpdatesTheOtherProportional.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "text",
+ "in": "formData",
+ "description": "Optional order annotation. e.g. 'Take profit'.",
+ "required": false,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/Order"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ },
+ "put": {
+ "tags": ["Order"],
+ "summary": "Amend the quantity or price of an open order.",
+ "description": "Send an `orderID` or `origClOrdID` to identify the order you wish to amend.\n\nBoth order quantity and price can be amended. Only one `qty` field can be used to amend.\n\nUse the `leavesQty` field to specify how much of the order you wish to remain open. This can be useful\nif you want to adjust your position's delta by a certain amount, regardless of how much of the order has\nalready filled.\n\n> A `leavesQty` can be used to make a \"Filled\" order live again, if it is received within 60 seconds of the fill.\n\nUse the `simpleOrderQty` and `simpleLeavesQty` fields to specify order size in Bitcoin, rather than contracts.\nThese fields will round up to the nearest contract.\n\nLike order placement, amending can be done in bulk. Simply send a request to `PUT /api/v1/order/bulk` with\na JSON body of the shape: `{\"orders\": [{...}, {...}]}`, each object containing the fields used in this endpoint.\n",
+ "operationId": "Order.amend",
+ "parameters": [{
+ "name": "orderID",
+ "in": "formData",
+ "description": "Order ID",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "origClOrdID",
+ "in": "formData",
+ "description": "Client Order ID. See POST /order.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "clOrdID",
+ "in": "formData",
+ "description": "Optional new Client Order ID, requires `origClOrdID`.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "simpleOrderQty",
+ "in": "formData",
+ "description": "Optional order quantity in units of the underlying instrument (i.e. Bitcoin).",
+ "required": false,
+ "type": "number",
+ "format": "double"
+ }, {
+ "name": "orderQty",
+ "in": "formData",
+ "description": "Optional order quantity in units of the instrument (i.e. contracts).",
+ "required": false,
+ "format": "int32",
+ "type": "number"
+ }, {
+ "name": "simpleLeavesQty",
+ "in": "formData",
+ "description": "Optional leaves quantity in units of the underlying instrument (i.e. Bitcoin). Useful for amending partially filled orders.",
+ "required": false,
+ "type": "number",
+ "format": "double"
+ }, {
+ "name": "leavesQty",
+ "in": "formData",
+ "description": "Optional leaves quantity in units of the instrument (i.e. contracts). Useful for amending partially filled orders.",
+ "required": false,
+ "format": "int32",
+ "type": "number"
+ }, {
+ "name": "price",
+ "in": "formData",
+ "description": "Optional limit price for 'Limit', 'StopLimit', and 'LimitIfTouched' orders.",
+ "required": false,
+ "type": "number",
+ "format": "double"
+ }, {
+ "name": "stopPx",
+ "in": "formData",
+ "description": "Optional trigger price for 'Stop', 'StopLimit', 'MarketIfTouched', and 'LimitIfTouched' orders. Use a price below the current price for stop-sell orders and buy-if-touched orders.",
+ "required": false,
+ "type": "number",
+ "format": "double"
+ }, {
+ "name": "pegOffsetValue",
+ "in": "formData",
+ "description": "Optional trailing offset from the current price for 'Stop', 'StopLimit', 'MarketIfTouched', and 'LimitIfTouched' orders; use a negative offset for stop-sell orders and buy-if-touched orders. Optional offset from the peg price for 'Pegged' orders.",
+ "required": false,
+ "type": "number",
+ "format": "double"
+ }, {
+ "name": "text",
+ "in": "formData",
+ "description": "Optional amend annotation. e.g. 'Adjust skew'.",
+ "required": false,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/Order"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ },
+ "delete": {
+ "tags": ["Order"],
+ "summary": "Cancel order(s). Send multiple order IDs to cancel in bulk.",
+ "description": "Either an orderID or a clOrdID must be provided.",
+ "operationId": "Order.cancel",
+ "parameters": [{
+ "name": "orderID",
+ "in": "formData",
+ "description": "Order ID(s).",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "clOrdID",
+ "in": "formData",
+ "description": "Client Order ID(s). See POST /order.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "text",
+ "in": "formData",
+ "description": "Optional cancellation annotation. e.g. 'Spread Exceeded'.",
+ "required": false,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Order"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/order/bulk": {
+ "post": {
+ "tags": ["Order"],
+ "summary": "Create multiple new orders for the same symbol.",
+ "description": "This endpoint is used for placing bulk orders. Valid order types are Market, Limit, Stop, StopLimit, MarketIfTouched, LimitIfTouched, MarketWithLeftOverAsLimit, and Pegged.\n\nEach individual order object in the array should have the same properties as an individual POST /order call.\n\nThis endpoint is much faster for getting many orders into the book at once. Because it reduces load on BitMEX\nsystems, this endpoint is ratelimited at `ceil(0.1 * orders)`. Submitting 10 orders via a bulk order call\nwill only count as 1 request, 15 as 2, 32 as 4, and so on.\n\nFor now, only `application/json` is supported on this endpoint.\n",
+ "operationId": "Order.newBulk",
+ "parameters": [{
+ "name": "orders",
+ "in": "formData",
+ "description": "An array of orders.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Order"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ },
+ "put": {
+ "tags": ["Order"],
+ "summary": "Amend multiple orders for the same symbol.",
+ "description": "Similar to POST /amend, but with multiple orders. `application/json` only. Ratelimited at 10%.",
+ "operationId": "Order.amendBulk",
+ "parameters": [{
+ "name": "orders",
+ "in": "formData",
+ "description": "An array of orders.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Order"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/order/closePosition": {
+ "post": {
+ "tags": ["Order"],
+ "summary": "Close a position. [Deprecated, use POST /order with execInst: 'Close']",
+ "description": "If no `price` is specified, a market order will be submitted to close the whole of your position. This will also close all other open orders in this symbol.",
+ "operationId": "Order.closePosition",
+ "parameters": [{
+ "name": "symbol",
+ "in": "formData",
+ "description": "Symbol of position to close.",
+ "required": true,
+ "type": "string"
+ }, {
+ "name": "price",
+ "in": "formData",
+ "description": "Optional limit price.",
+ "required": false,
+ "type": "number",
+ "format": "double"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "description": "Resulting close order.",
+ "$ref": "#/definitions/Order"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/order/all": {
+ "delete": {
+ "tags": ["Order"],
+ "summary": "Cancels all of your orders.",
+ "operationId": "Order.cancelAll",
+ "parameters": [{
+ "name": "symbol",
+ "in": "formData",
+ "description": "Optional symbol. If provided, only cancels orders for that symbol.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "formData",
+ "description": "Optional filter for cancellation. Use to only cancel some orders, e.g. `{\"side\": \"Buy\"}`.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "text",
+ "in": "formData",
+ "description": "Optional cancellation annotation. e.g. 'Spread Exceeded'",
+ "required": false,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Order"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/order/cancelAllAfter": {
+ "post": {
+ "tags": ["Order"],
+ "summary": "Automatically cancel all your orders after a specified timeout.",
+ "description": "Useful as a dead-man's switch to ensure your orders are canceled in case of an outage.\nIf called repeatedly, the existing offset will be canceled and a new one will be inserted in its place.\n\nExample usage: call this route at 15s intervals with an offset of 60000 (60s).\nIf this route is not called within 60 seconds, all your orders will be automatically canceled.\n\nThis is also available via [WebSocket](https://testnet.bitmex.com/app/wsAPI#Dead-Mans-Switch-Auto-Cancel).\n",
+ "operationId": "Order.cancelAllAfter",
+ "parameters": [{
+ "name": "timeout",
+ "in": "formData",
+ "description": "Timeout in ms. Set to 0 to cancel this timer. ",
+ "required": true,
+ "type": "number",
+ "format": "double"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "object"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/orderBook/L2": {
+ "get": {
+ "tags": ["OrderBook"],
+ "summary": "Get current orderbook in vertical format.",
+ "operationId": "OrderBook.getL2",
+ "parameters": [{
+ "name": "symbol",
+ "in": "query",
+ "description": "Instrument symbol. Send a series (e.g. XBT) to get data for the nearest contract in that series.",
+ "required": true,
+ "type": "string"
+ }, {
+ "name": "depth",
+ "in": "query",
+ "description": "Orderbook depth per side. Send 0 for full depth.",
+ "required": false,
+ "minimum": 0,
+ "format": "int32",
+ "default": 25,
+ "type": "number"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/OrderBookL2"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/position": {
+ "get": {
+ "tags": ["Position"],
+ "summary": "Get your positions.",
+ "description": "This endpoint is used for retrieving position information. The fields largely follow the [FIX spec](http://www.onixs.biz/fix-dictionary/5.0.SP2/msgType_AP_6580.html) definitions. Some selected fields are explained in more detail below.\n\nThe fields _account_, _symbol_, _currency_ are unique to each position and form its key.\n\n* **account**: Your unique account ID.\n* **symbol**: The contract for this position.\n* **currency**: The margin currency for this position.\n* **underlying**: Meta data of the _symbol_.\n* **quoteCurrency**: Meta data of the _symbol_, All prices are in the _quoteCurrency_\n* **commission**: The maximum of the maker, taker, and settlement fee.\n* **initMarginReq**: The initial margin requirement. This will be at least the symbol's default initial maintenance margin, but can be higher if you choose lower leverage.\n* **maintMarginReq**: The maintenance margin requirement. This will be at least the symbol's default maintenance maintenance margin, but can be higher if you choose a higher risk limit.\n* **riskLimit**: This is a function of your _maintMarginReq_.\n* **leverage**: 1 / initMarginReq.\n* **crossMargin**: True/false depending on whether you set cross margin on this position.\n* **deleveragePercentile**: Indicates where your position is in the ADL queue.\n* **rebalancedPnl**: The value of realised PNL that has transferred to your wallet for this position.\n* **prevRebalancedPnl**: The value of realised PNL that has transferred to your wallet for this position since the position was closed.\n* **currentQty**: The current position amount in contracts.\n* **currentCost**: The current cost of the position in the settlement currency of the symbol (_currency_).\n* **currentComm**: The current commission of the position in the settlement currency of the symbol (_currency_).\n* **realisedCost**: The realised cost of this position calculated with regard to average cost accounting.\n* **unrealisedCost**: _currentCost_ - _realisedCost_.\n* **grossOpenCost**: The absolute value of your open orders for this symbol.\n* **grossOpenPremium**: The amount your bidding above the mark price in the settlement currency of the symbol (_currency_).\n* **markPrice**: The mark price of the symbol in _quoteCurrency_.\n* **markValue**: The _currentQty_ at the mark price in the settlement currency of the symbol (_currency_).\n* **homeNotional**: Value of position in units of _underlying_.\n* **foreignNotional**: Value of position in units of _quoteCurrency_.\n* **realisedPnl**: The negative of _realisedCost_.\n* **unrealisedGrossPnl**: _markValue_ - _unrealisedCost_.\n* **unrealisedPnl**: _unrealisedGrossPnl_.\n* **liquidationPrice**: Once markPrice reaches this price, this position will be liquidated.\n* **bankruptPrice**: Once markPrice reaches this price, this position will have no equity.\n",
+ "operationId": "Position.get",
+ "parameters": [{
+ "name": "filter",
+ "in": "query",
+ "description": "Table filter. For example, send {\"symbol\": \"XBTUSD\"}.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Which columns to fetch. For example, send [\"columnName\"].",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of rows to fetch.",
+ "required": false,
+ "format": "int32",
+ "type": "number"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Position"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/position/isolate": {
+ "post": {
+ "tags": ["Position"],
+ "summary": "Enable isolated margin or cross margin per-position.",
+ "operationId": "Position.isolateMargin",
+ "parameters": [{
+ "name": "symbol",
+ "in": "formData",
+ "description": "Position symbol to isolate.",
+ "required": true,
+ "type": "string"
+ }, {
+ "name": "enabled",
+ "in": "formData",
+ "description": "True for isolated margin, false for cross margin.",
+ "required": false,
+ "default": true,
+ "type": "boolean"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "description": "Affected position.",
+ "$ref": "#/definitions/Position"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/position/riskLimit": {
+ "post": {
+ "tags": ["Position"],
+ "summary": "Update your risk limit.",
+ "operationId": "Position.updateRiskLimit",
+ "parameters": [{
+ "name": "symbol",
+ "in": "formData",
+ "description": "Symbol of position to update risk limit on.",
+ "required": true,
+ "type": "string"
+ }, {
+ "name": "riskLimit",
+ "in": "formData",
+ "description": "New Risk Limit, in Satoshis.",
+ "required": true,
+ "format": "int64",
+ "type": "number"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "description": "Affected position.",
+ "$ref": "#/definitions/Position"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/position/transferMargin": {
+ "post": {
+ "tags": ["Position"],
+ "summary": "Transfer equity in or out of a position.",
+ "operationId": "Position.transferIsolatedMargin",
+ "parameters": [{
+ "name": "symbol",
+ "in": "formData",
+ "description": "Symbol of position to isolate.",
+ "required": true,
+ "type": "string"
+ }, {
+ "name": "amount",
+ "in": "formData",
+ "description": "Amount to transfer, in Satoshis. May be negative.",
+ "required": true,
+ "format": "int64",
+ "type": "number"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "description": "Affected position.",
+ "$ref": "#/definitions/Position"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/position/leverage": {
+ "post": {
+ "tags": ["Position"],
+ "summary": "Choose leverage for a position.",
+ "operationId": "Position.updateLeverage",
+ "parameters": [{
+ "name": "symbol",
+ "in": "formData",
+ "description": "Symbol of position to adjust.",
+ "required": true,
+ "type": "string"
+ }, {
+ "name": "leverage",
+ "in": "formData",
+ "description": "Leverage value. Send a number between 0.01 and 100 to enable isolated margin with a fixed leverage. Send 0 to enable cross margin.",
+ "required": true,
+ "type": "number",
+ "format": "double"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "description": "Affected position.",
+ "$ref": "#/definitions/Position"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/quote": {
+ "get": {
+ "tags": ["Quote"],
+ "summary": "Get Quotes.",
+ "operationId": "Quote.get",
+ "parameters": [{
+ "name": "symbol",
+ "in": "query",
+ "description": "Instrument symbol. Send a bare series (e.g. XBU) to get data for the nearest expiring contract in that series.\n\nYou can also send a timeframe, e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`, `quarterly`, and `biquarterly`.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "query",
+ "description": "Generic table filter. Send JSON key/value pairs, such as `{\"key\": \"value\"}`. You can key on individual fields, and do more advanced querying on timestamps. See the [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters) for more details.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.\n\nNote that this method will always return item keys, even when not specified, so you may receive more columns that you expect.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting point for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "startTime",
+ "in": "query",
+ "description": "Starting date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }, {
+ "name": "endTime",
+ "in": "query",
+ "description": "Ending date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Quote"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/quote/bucketed": {
+ "get": {
+ "tags": ["Quote"],
+ "summary": "Get previous quotes in time buckets.",
+ "operationId": "Quote.getBucketed",
+ "parameters": [{
+ "name": "binSize",
+ "in": "query",
+ "description": "Time interval to bucket by. Available options: [1m,5m,1h,1d].",
+ "required": false,
+ "default": "1m",
+ "type": "string"
+ }, {
+ "name": "partial",
+ "in": "query",
+ "description": "If true, will send in-progress (incomplete) bins for the current time period.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "symbol",
+ "in": "query",
+ "description": "Instrument symbol. Send a bare series (e.g. XBU) to get data for the nearest expiring contract in that series.\n\nYou can also send a timeframe, e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`, `quarterly`, and `biquarterly`.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "query",
+ "description": "Generic table filter. Send JSON key/value pairs, such as `{\"key\": \"value\"}`. You can key on individual fields, and do more advanced querying on timestamps. See the [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters) for more details.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.\n\nNote that this method will always return item keys, even when not specified, so you may receive more columns that you expect.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting point for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "startTime",
+ "in": "query",
+ "description": "Starting date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }, {
+ "name": "endTime",
+ "in": "query",
+ "description": "Ending date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Quote"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/schema": {
+ "get": {
+ "tags": ["Schema"],
+ "summary": "Get model schemata for data objects returned by this API.",
+ "operationId": "Schema.get",
+ "parameters": [{
+ "name": "model",
+ "in": "query",
+ "description": "Optional model filter. If omitted, will return all models.",
+ "required": false,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "object"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/schema/websocketHelp": {
+ "get": {
+ "tags": ["Schema"],
+ "summary": "Returns help text & subject list for websocket usage.",
+ "operationId": "Schema.websocketHelp",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "object"
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/settlement": {
+ "get": {
+ "tags": ["Settlement"],
+ "summary": "Get settlement history.",
+ "operationId": "Settlement.get",
+ "parameters": [{
+ "name": "symbol",
+ "in": "query",
+ "description": "Instrument symbol. Send a bare series (e.g. XBU) to get data for the nearest expiring contract in that series.\n\nYou can also send a timeframe, e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`, `quarterly`, and `biquarterly`.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "query",
+ "description": "Generic table filter. Send JSON key/value pairs, such as `{\"key\": \"value\"}`. You can key on individual fields, and do more advanced querying on timestamps. See the [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters) for more details.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.\n\nNote that this method will always return item keys, even when not specified, so you may receive more columns that you expect.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting point for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "startTime",
+ "in": "query",
+ "description": "Starting date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }, {
+ "name": "endTime",
+ "in": "query",
+ "description": "Ending date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Settlement"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/stats": {
+ "get": {
+ "tags": ["Stats"],
+ "summary": "Get exchange-wide and per-series turnover and volume statistics.",
+ "operationId": "Stats.get",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Stats"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/stats/history": {
+ "get": {
+ "tags": ["Stats"],
+ "summary": "Get historical exchange-wide and per-series turnover and volume statistics.",
+ "operationId": "Stats.history",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/StatsHistory"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/stats/historyUSD": {
+ "get": {
+ "tags": ["Stats"],
+ "summary": "Get a summary of exchange statistics in USD.",
+ "operationId": "Stats.historyUSD",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/StatsUSD"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/trade": {
+ "get": {
+ "tags": ["Trade"],
+ "summary": "Get Trades.",
+ "description": "Please note that indices (symbols starting with `.`) post trades at intervals to the trade feed. These have a `size` of 0 and are used only to indicate a changing price.\n\nSee [the FIX Spec](http://www.onixs.biz/fix-dictionary/5.0.SP2/msgType_AE_6569.html) for explanations of these fields.",
+ "operationId": "Trade.get",
+ "parameters": [{
+ "name": "symbol",
+ "in": "query",
+ "description": "Instrument symbol. Send a bare series (e.g. XBU) to get data for the nearest expiring contract in that series.\n\nYou can also send a timeframe, e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`, `quarterly`, and `biquarterly`.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "query",
+ "description": "Generic table filter. Send JSON key/value pairs, such as `{\"key\": \"value\"}`. You can key on individual fields, and do more advanced querying on timestamps. See the [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters) for more details.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.\n\nNote that this method will always return item keys, even when not specified, so you may receive more columns that you expect.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting point for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "startTime",
+ "in": "query",
+ "description": "Starting date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }, {
+ "name": "endTime",
+ "in": "query",
+ "description": "Ending date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Trade"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/trade/bucketed": {
+ "get": {
+ "tags": ["Trade"],
+ "summary": "Get previous trades in time buckets.",
+ "operationId": "Trade.getBucketed",
+ "parameters": [{
+ "name": "binSize",
+ "in": "query",
+ "description": "Time interval to bucket by. Available options: [1m,5m,1h,1d].",
+ "required": false,
+ "default": "1m",
+ "type": "string"
+ }, {
+ "name": "partial",
+ "in": "query",
+ "description": "If true, will send in-progress (incomplete) bins for the current time period.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "symbol",
+ "in": "query",
+ "description": "Instrument symbol. Send a bare series (e.g. XBU) to get data for the nearest expiring contract in that series.\n\nYou can also send a timeframe, e.g. `XBU:monthly`. Timeframes are `daily`, `weekly`, `monthly`, `quarterly`, and `biquarterly`.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "filter",
+ "in": "query",
+ "description": "Generic table filter. Send JSON key/value pairs, such as `{\"key\": \"value\"}`. You can key on individual fields, and do more advanced querying on timestamps. See the [Timestamp Docs](https://testnet.bitmex.com/app/restAPI#Timestamp-Filters) for more details.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "columns",
+ "in": "query",
+ "description": "Array of column names to fetch. If omitted, will return all columns.\n\nNote that this method will always return item keys, even when not specified, so you may receive more columns that you expect.",
+ "required": false,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "count",
+ "in": "query",
+ "description": "Number of results to fetch.",
+ "required": false,
+ "format": "int32",
+ "default": 100,
+ "type": "number"
+ }, {
+ "name": "start",
+ "in": "query",
+ "description": "Starting point for results.",
+ "required": false,
+ "format": "int32",
+ "default": 0,
+ "type": "number"
+ }, {
+ "name": "reverse",
+ "in": "query",
+ "description": "If true, will sort results newest first.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }, {
+ "name": "startTime",
+ "in": "query",
+ "description": "Starting date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }, {
+ "name": "endTime",
+ "in": "query",
+ "description": "Ending date filter for results.",
+ "required": false,
+ "type": "string",
+ "format": "date-time"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/TradeBin"
+ }
+ }
+ },
+ "400": {
+ "description": "Parameter Error",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "schema": {
+ "$ref": "#/definitions/Error"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/user/depositAddress": {
+ "get": {
+ "tags": ["User"],
+ "summary": "Get a deposit address.",
+ "operationId": "User.getDepositAddress",
+ "parameters": [{
+ "name": "currency",
+ "in": "query",
+ "required": false,
+ "default": "XBt",
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/user/wallet": {
+ "get": {
+ "tags": ["User"],
+ "summary": "Get your current wallet information.",
+ "operationId": "User.getWallet",
+ "parameters": [{
+ "name": "currency",
+ "in": "query",
+ "required": false,
+ "default": "XBt",
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/Wallet"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/user/walletHistory": {
+ "get": {
+ "tags": ["User"],
+ "summary": "Get a history of all of your wallet transactions (deposits, withdrawals, PNL).",
+ "operationId": "User.getWalletHistory",
+ "parameters": [{
+ "name": "currency",
+ "in": "query",
+ "required": false,
+ "default": "XBt",
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Transaction"
+ }
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/user/walletSummary": {
+ "get": {
+ "tags": ["User"],
+ "summary": "Get a summary of all of your wallet transactions (deposits, withdrawals, PNL).",
+ "operationId": "User.getWalletSummary",
+ "parameters": [{
+ "name": "currency",
+ "in": "query",
+ "required": false,
+ "default": "XBt",
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Transaction"
+ }
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/user/minWithdrawalFee": {
+ "get": {
+ "tags": ["User"],
+ "summary": "Get the minimum withdrawal fee for a currency.",
+ "description": "This is changed based on network conditions to ensure timely withdrawals. During network congestion, this may be high. The fee is returned in the same currency.",
+ "operationId": "User.minWithdrawalFee",
+ "parameters": [{
+ "name": "currency",
+ "in": "query",
+ "required": false,
+ "default": "XBt",
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "object"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/user/requestWithdrawal": {
+ "post": {
+ "tags": ["User"],
+ "summary": "Request a withdrawal to an external wallet.",
+ "description": "This will send a confirmation email to the email address on record, unless requested via an API Key with the `withdraw` permission.",
+ "operationId": "User.requestWithdrawal",
+ "parameters": [{
+ "name": "otpToken",
+ "in": "formData",
+ "description": "2FA token. Required if 2FA is enabled on your account.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "currency",
+ "in": "formData",
+ "description": "Currency you're withdrawing. Options: `XBt`",
+ "required": true,
+ "default": "XBt",
+ "type": "string"
+ }, {
+ "name": "amount",
+ "in": "formData",
+ "description": "Amount of withdrawal currency.",
+ "required": true,
+ "format": "int64",
+ "type": "number"
+ }, {
+ "name": "address",
+ "in": "formData",
+ "description": "Destination Address.",
+ "required": true,
+ "type": "string"
+ }, {
+ "name": "fee",
+ "in": "formData",
+ "description": "Network fee for Bitcoin withdrawals. If not specified, a default value will be calculated based on Bitcoin network conditions. You will have a chance to confirm this via email.",
+ "required": false,
+ "type": "number",
+ "format": "double"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/Transaction"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/user/cancelWithdrawal": {
+ "post": {
+ "tags": ["User"],
+ "summary": "Cancel a withdrawal.",
+ "operationId": "User.cancelWithdrawal",
+ "parameters": [{
+ "name": "token",
+ "in": "formData",
+ "required": true,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/Transaction"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/user/confirmWithdrawal": {
+ "post": {
+ "tags": ["User"],
+ "summary": "Confirm a withdrawal.",
+ "operationId": "User.confirmWithdrawal",
+ "parameters": [{
+ "name": "token",
+ "in": "formData",
+ "required": true,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/Transaction"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/user/requestEnableTFA": {
+ "post": {
+ "tags": ["User"],
+ "summary": "Get secret key for setting up two-factor auth.",
+ "description": "Use /confirmEnableTFA directly for Yubikeys. This fails if TFA is already enabled.",
+ "operationId": "User.requestEnableTFA",
+ "parameters": [{
+ "name": "type",
+ "in": "formData",
+ "description": "Two-factor auth type. Supported types: 'GA' (Google Authenticator)",
+ "required": false,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "boolean"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/user/confirmEnableTFA": {
+ "post": {
+ "tags": ["User"],
+ "summary": "Confirm two-factor auth for this account. If using a Yubikey, simply send a token to this endpoint.",
+ "operationId": "User.confirmEnableTFA",
+ "parameters": [{
+ "name": "type",
+ "in": "formData",
+ "description": "Two-factor auth type. Supported types: 'GA' (Google Authenticator), 'Yubikey'",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "token",
+ "in": "formData",
+ "description": "Token from your selected TFA type.",
+ "required": true,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "boolean"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/user/disableTFA": {
+ "post": {
+ "tags": ["User"],
+ "summary": "Disable two-factor auth for this account.",
+ "operationId": "User.disableTFA",
+ "parameters": [{
+ "name": "type",
+ "in": "formData",
+ "description": "Two-factor auth type. Supported types: 'GA' (Google Authenticator)",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "token",
+ "in": "formData",
+ "description": "Token from your selected TFA type.",
+ "required": true,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "boolean"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/user/confirmEmail": {
+ "post": {
+ "tags": ["User"],
+ "summary": "Confirm your email address with a token.",
+ "operationId": "User.confirm",
+ "parameters": [{
+ "name": "token",
+ "in": "formData",
+ "required": true,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/AccessToken"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/user/affiliateStatus": {
+ "get": {
+ "tags": ["User"],
+ "summary": "Get your current affiliate/referral status.",
+ "operationId": "User.getAffiliateStatus",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/Affiliate"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/user/checkReferralCode": {
+ "get": {
+ "tags": ["User"],
+ "summary": "Check if a referral code is valid.",
+ "description": "If the code is valid, responds with the referral code's discount (e.g. `0.1` for 10%). Otherwise, will return a 404.",
+ "operationId": "User.checkReferralCode",
+ "parameters": [{
+ "name": "referralCode",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "number",
+ "format": "double"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/user/logout": {
+ "post": {
+ "tags": ["User"],
+ "summary": "Log out of BitMEX.",
+ "operationId": "User.logout",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "null"
+ }
+ }
+ },
+ "deprecated": false,
+ "security": []
+ }
+ },
+ "/user/logoutAll": {
+ "post": {
+ "tags": ["User"],
+ "summary": "Log all systems out of BitMEX. This will revoke all of your account's access tokens, logging you out on all devices.",
+ "operationId": "User.logoutAll",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "number",
+ "format": "double"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/user/preferences": {
+ "post": {
+ "tags": ["User"],
+ "summary": "Save user preferences.",
+ "operationId": "User.savePreferences",
+ "parameters": [{
+ "name": "prefs",
+ "in": "formData",
+ "required": true,
+ "type": "string",
+ "format": "JSON"
+ }, {
+ "name": "overwrite",
+ "in": "formData",
+ "description": "If true, will overwrite all existing preferences.",
+ "required": false,
+ "default": false,
+ "type": "boolean"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/User"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/user": {
+ "get": {
+ "tags": ["User"],
+ "summary": "Get your user model.",
+ "operationId": "User.get",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/User"
+ }
+ }
+ },
+ "deprecated": false
+ },
+ "put": {
+ "tags": ["User"],
+ "summary": "Update your password, name, and other attributes.",
+ "operationId": "User.update",
+ "parameters": [{
+ "name": "oldPassword",
+ "in": "formData",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "newPassword",
+ "in": "formData",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "newPasswordConfirm",
+ "in": "formData",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "username",
+ "in": "formData",
+ "description": "Username can only be set once. To reset, email support.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "country",
+ "in": "formData",
+ "description": "Country of residence.",
+ "required": false,
+ "type": "string"
+ }, {
+ "name": "pgpPubKey",
+ "in": "formData",
+ "description": "PGP Public Key. If specified, automated emails will be sentwith this key.",
+ "required": false,
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/User"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/user/commission": {
+ "get": {
+ "tags": ["User"],
+ "summary": "Get your account's commission status.",
+ "operationId": "User.getCommission",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/UserCommission"
+ }
+ }
+ }
+ },
+ "deprecated": false
+ }
+ },
+ "/user/margin": {
+ "get": {
+ "tags": ["User"],
+ "summary": "Get your account's margin status. Send a currency of \"all\" to receive an array of all supported currencies.",
+ "operationId": "User.getMargin",
+ "parameters": [{
+ "name": "currency",
+ "in": "query",
+ "required": false,
+ "default": "XBt",
+ "type": "string"
+ }],
+ "responses": {
+ "200": {
+ "description": "Request was successful",
+ "schema": {
+ "$ref": "#/definitions/Margin"
+ }
+ }
+ },
+ "deprecated": false
+ }
+ }
+ },
+ "tags": [{
+ "name": "Announcement",
+ "description": "Public Announcements"
+ }, {
+ "name": "APIKey",
+ "description": "Persistent API Keys for Developers"
+ }, {
+ "name": "Chat",
+ "description": "Trollbox Data"
+ }, {
+ "name": "Execution",
+ "description": "Raw Order and Balance Data"
+ }, {
+ "name": "Funding",
+ "description": "Swap Funding History"
+ }, {
+ "name": "Instrument",
+ "description": "Tradeable Contracts, Indices, and History"
+ }, {
+ "name": "Insurance",
+ "description": "Insurance Fund Data"
+ }, {
+ "name": "Leaderboard",
+ "description": "Information on Top Users"
+ }, {
+ "name": "Liquidation",
+ "description": "Active Liquidations"
+ }, {
+ "name": "Notification",
+ "description": "Account Notifications"
+ }, {
+ "name": "Order",
+ "description": "Placement, Cancellation, Amending, and History"
+ }, {
+ "name": "OrderBook",
+ "description": "Level 2 Book Data"
+ }, {
+ "name": "Position",
+ "description": "Summary of Open and Closed Positions"
+ }, {
+ "name": "Quote",
+ "description": "Best Bid/Offer Snapshots & Historical Bins"
+ }, {
+ "name": "Schema",
+ "description": "Dynamic Schemata for Developers"
+ }, {
+ "name": "Settlement",
+ "description": "Historical Settlement Data"
+ }, {
+ "name": "Stats",
+ "description": "Exchange Statistics"
+ }, {
+ "name": "Trade",
+ "description": "Individual & Bucketed Trades"
+ }, {
+ "name": "User",
+ "description": "Account Operations"
+ }],
+ "consumes": ["application/json", "application/x-www-form-urlencoded"],
+ "produces": ["application/json", "application/xml", "text/xml", "application/javascript", "text/javascript"],
+ "definitions": {
+ "Announcement": {
+ "description": "Public Announcements",
+ "properties": {
+ "id": {
+ "format": "int32",
+ "type": "number"
+ },
+ "link": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "content": {
+ "type": "string"
+ },
+ "date": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "required": ["id"],
+ "type": "object"
+ },
+ "Error": {
+ "properties": {
+ "error": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "required": ["error"],
+ "type": "object"
+ },
+ "x-any": {
+ "properties": {},
+ "type": "object"
+ },
+ "APIKey": {
+ "description": "Persistent API Keys for Developers",
+ "properties": {
+ "id": {
+ "maxLength": 24,
+ "type": "string"
+ },
+ "secret": {
+ "maxLength": 48,
+ "type": "string"
+ },
+ "name": {
+ "maxLength": 64,
+ "type": "string"
+ },
+ "nonce": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "cidr": {
+ "maxLength": 18,
+ "type": "string"
+ },
+ "permissions": {
+ "default": [],
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/x-any"
+ }
+ },
+ "enabled": {
+ "default": false,
+ "type": "boolean"
+ },
+ "userId": {
+ "format": "int32",
+ "type": "number"
+ },
+ "created": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "required": ["id", "secret", "name", "nonce", "userId"],
+ "type": "object"
+ },
+ "Chat": {
+ "description": "Trollbox Data",
+ "properties": {
+ "id": {
+ "format": "int32",
+ "type": "number"
+ },
+ "date": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "user": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "html": {
+ "type": "string"
+ },
+ "fromBot": {
+ "default": false,
+ "type": "boolean"
+ },
+ "channelID": {
+ "type": "number",
+ "format": "double"
+ }
+ },
+ "required": ["date", "user", "message", "html"],
+ "type": "object"
+ },
+ "ChatChannel": {
+ "properties": {
+ "id": {
+ "format": "int32",
+ "type": "number"
+ },
+ "name": {
+ "type": "string"
+ }
+ },
+ "required": ["name"],
+ "type": "object"
+ },
+ "ConnectedUsers": {
+ "properties": {
+ "users": {
+ "format": "int32",
+ "type": "number"
+ },
+ "bots": {
+ "format": "int32",
+ "type": "number"
+ }
+ },
+ "type": "object"
+ },
+ "Execution": {
+ "description": "Raw Order and Balance Data",
+ "properties": {
+ "execID": {
+ "format": "guid",
+ "type": "string"
+ },
+ "orderID": {
+ "format": "guid",
+ "type": "string"
+ },
+ "clOrdID": {
+ "type": "string"
+ },
+ "clOrdLinkID": {
+ "type": "string"
+ },
+ "account": {
+ "format": "int64",
+ "type": "number"
+ },
+ "symbol": {
+ "type": "string"
+ },
+ "side": {
+ "type": "string"
+ },
+ "lastQty": {
+ "format": "int64",
+ "type": "number"
+ },
+ "lastPx": {
+ "format": "double",
+ "type": "number"
+ },
+ "underlyingLastPx": {
+ "format": "double",
+ "type": "number"
+ },
+ "lastMkt": {
+ "type": "string"
+ },
+ "lastLiquidityInd": {
+ "type": "string"
+ },
+ "simpleOrderQty": {
+ "format": "double",
+ "type": "number"
+ },
+ "orderQty": {
+ "format": "int64",
+ "type": "number"
+ },
+ "price": {
+ "format": "double",
+ "type": "number"
+ },
+ "displayQty": {
+ "format": "int64",
+ "type": "number"
+ },
+ "stopPx": {
+ "format": "double",
+ "type": "number"
+ },
+ "pegOffsetValue": {
+ "format": "double",
+ "type": "number"
+ },
+ "pegPriceType": {
+ "type": "string"
+ },
+ "currency": {
+ "type": "string"
+ },
+ "settlCurrency": {
+ "type": "string"
+ },
+ "execType": {
+ "type": "string"
+ },
+ "ordType": {
+ "type": "string"
+ },
+ "timeInForce": {
+ "type": "string"
+ },
+ "execInst": {
+ "type": "string"
+ },
+ "contingencyType": {
+ "type": "string"
+ },
+ "exDestination": {
+ "type": "string"
+ },
+ "ordStatus": {
+ "type": "string"
+ },
+ "triggered": {
+ "type": "string"
+ },
+ "workingIndicator": {
+ "type": "boolean"
+ },
+ "ordRejReason": {
+ "type": "string"
+ },
+ "simpleLeavesQty": {
+ "format": "double",
+ "type": "number"
+ },
+ "leavesQty": {
+ "format": "int64",
+ "type": "number"
+ },
+ "simpleCumQty": {
+ "format": "double",
+ "type": "number"
+ },
+ "cumQty": {
+ "format": "int64",
+ "type": "number"
+ },
+ "avgPx": {
+ "format": "double",
+ "type": "number"
+ },
+ "commission": {
+ "format": "double",
+ "type": "number"
+ },
+ "tradePublishIndicator": {
+ "type": "string"
+ },
+ "multiLegReportingType": {
+ "type": "string"
+ },
+ "text": {
+ "type": "string"
+ },
+ "trdMatchID": {
+ "format": "guid",
+ "type": "string"
+ },
+ "execCost": {
+ "format": "int64",
+ "type": "number"
+ },
+ "execComm": {
+ "format": "int64",
+ "type": "number"
+ },
+ "homeNotional": {
+ "format": "double",
+ "type": "number"
+ },
+ "foreignNotional": {
+ "format": "double",
+ "type": "number"
+ },
+ "transactTime": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ }
+ },
+ "required": ["execID"],
+ "type": "object"
+ },
+ "Funding": {
+ "description": "Swap Funding History",
+ "properties": {
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "symbol": {
+ "type": "string"
+ },
+ "fundingInterval": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "fundingRate": {
+ "format": "double",
+ "type": "number"
+ },
+ "fundingRateDaily": {
+ "format": "double",
+ "type": "number"
+ }
+ },
+ "required": ["timestamp", "symbol"],
+ "type": "object"
+ },
+ "Instrument": {
+ "description": "Tradeable Contracts, Indices, and History",
+ "properties": {
+ "symbol": {
+ "type": "string"
+ },
+ "rootSymbol": {
+ "type": "string"
+ },
+ "state": {
+ "type": "string"
+ },
+ "typ": {
+ "type": "string"
+ },
+ "listing": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "front": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "expiry": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "settle": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "relistInterval": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "inverseLeg": {
+ "type": "string"
+ },
+ "sellLeg": {
+ "type": "string"
+ },
+ "buyLeg": {
+ "type": "string"
+ },
+ "optionStrikePcnt": {
+ "format": "double",
+ "type": "number"
+ },
+ "optionStrikeRound": {
+ "format": "double",
+ "type": "number"
+ },
+ "optionStrikePrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "optionMultiplier": {
+ "format": "double",
+ "type": "number"
+ },
+ "positionCurrency": {
+ "type": "string"
+ },
+ "underlying": {
+ "type": "string"
+ },
+ "quoteCurrency": {
+ "type": "string"
+ },
+ "underlyingSymbol": {
+ "type": "string"
+ },
+ "reference": {
+ "type": "string"
+ },
+ "referenceSymbol": {
+ "type": "string"
+ },
+ "calcInterval": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "publishInterval": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "publishTime": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "maxOrderQty": {
+ "format": "int64",
+ "type": "number"
+ },
+ "maxPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "lotSize": {
+ "format": "int64",
+ "type": "number"
+ },
+ "tickSize": {
+ "format": "double",
+ "type": "number"
+ },
+ "multiplier": {
+ "format": "int64",
+ "type": "number"
+ },
+ "settlCurrency": {
+ "type": "string"
+ },
+ "underlyingToPositionMultiplier": {
+ "format": "int64",
+ "type": "number"
+ },
+ "underlyingToSettleMultiplier": {
+ "format": "int64",
+ "type": "number"
+ },
+ "quoteToSettleMultiplier": {
+ "format": "int64",
+ "type": "number"
+ },
+ "isQuanto": {
+ "type": "boolean"
+ },
+ "isInverse": {
+ "type": "boolean"
+ },
+ "initMargin": {
+ "format": "double",
+ "type": "number"
+ },
+ "maintMargin": {
+ "format": "double",
+ "type": "number"
+ },
+ "riskLimit": {
+ "format": "int64",
+ "type": "number"
+ },
+ "riskStep": {
+ "format": "int64",
+ "type": "number"
+ },
+ "limit": {
+ "format": "double",
+ "type": "number"
+ },
+ "capped": {
+ "type": "boolean"
+ },
+ "taxed": {
+ "type": "boolean"
+ },
+ "deleverage": {
+ "type": "boolean"
+ },
+ "makerFee": {
+ "format": "double",
+ "type": "number"
+ },
+ "takerFee": {
+ "format": "double",
+ "type": "number"
+ },
+ "settlementFee": {
+ "format": "double",
+ "type": "number"
+ },
+ "insuranceFee": {
+ "format": "double",
+ "type": "number"
+ },
+ "fundingBaseSymbol": {
+ "type": "string"
+ },
+ "fundingQuoteSymbol": {
+ "type": "string"
+ },
+ "fundingPremiumSymbol": {
+ "type": "string"
+ },
+ "fundingTimestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "fundingInterval": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "fundingRate": {
+ "format": "double",
+ "type": "number"
+ },
+ "indicativeFundingRate": {
+ "format": "double",
+ "type": "number"
+ },
+ "rebalanceTimestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "rebalanceInterval": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "openingTimestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "closingTimestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "sessionInterval": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "prevClosePrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "limitDownPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "limitUpPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "bankruptLimitDownPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "bankruptLimitUpPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "prevTotalVolume": {
+ "format": "int64",
+ "type": "number"
+ },
+ "totalVolume": {
+ "format": "int64",
+ "type": "number"
+ },
+ "volume": {
+ "format": "int64",
+ "type": "number"
+ },
+ "volume24h": {
+ "format": "int64",
+ "type": "number"
+ },
+ "prevTotalTurnover": {
+ "format": "int64",
+ "type": "number"
+ },
+ "totalTurnover": {
+ "format": "int64",
+ "type": "number"
+ },
+ "turnover": {
+ "format": "int64",
+ "type": "number"
+ },
+ "turnover24h": {
+ "format": "int64",
+ "type": "number"
+ },
+ "prevPrice24h": {
+ "format": "double",
+ "type": "number"
+ },
+ "vwap": {
+ "format": "double",
+ "type": "number"
+ },
+ "highPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "lowPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "lastPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "lastPriceProtected": {
+ "format": "double",
+ "type": "number"
+ },
+ "lastTickDirection": {
+ "type": "string"
+ },
+ "lastChangePcnt": {
+ "format": "double",
+ "type": "number"
+ },
+ "bidPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "midPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "askPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "impactBidPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "impactMidPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "impactAskPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "hasLiquidity": {
+ "type": "boolean"
+ },
+ "openInterest": {
+ "format": "int64",
+ "type": "number"
+ },
+ "openValue": {
+ "format": "int64",
+ "type": "number"
+ },
+ "fairMethod": {
+ "type": "string"
+ },
+ "fairBasisRate": {
+ "format": "double",
+ "type": "number"
+ },
+ "fairBasis": {
+ "format": "double",
+ "type": "number"
+ },
+ "fairPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "markMethod": {
+ "type": "string"
+ },
+ "markPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "indicativeTaxRate": {
+ "format": "double",
+ "type": "number"
+ },
+ "indicativeSettlePrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "optionUnderlyingPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "settledPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ }
+ },
+ "required": ["symbol"],
+ "type": "object"
+ },
+ "InstrumentInterval": {
+ "properties": {
+ "intervals": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "symbols": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "required": ["intervals", "symbols"],
+ "type": "object"
+ },
+ "IndexComposite": {
+ "properties": {
+ "timestamp": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "symbol": {
+ "type": "string"
+ },
+ "indexSymbol": {
+ "type": "string"
+ },
+ "reference": {
+ "type": "string"
+ },
+ "lastPrice": {
+ "type": "number",
+ "format": "double"
+ },
+ "weight": {
+ "type": "number",
+ "format": "double"
+ },
+ "logged": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "required": ["timestamp"],
+ "type": "object"
+ },
+ "Insurance": {
+ "description": "Insurance Fund Data",
+ "properties": {
+ "currency": {
+ "type": "string"
+ },
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "walletBalance": {
+ "format": "int64",
+ "type": "number"
+ }
+ },
+ "required": ["currency", "timestamp"],
+ "type": "object"
+ },
+ "Leaderboard": {
+ "description": "Information on Top Users",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "isRealName": {
+ "type": "boolean"
+ },
+ "profit": {
+ "type": "number",
+ "format": "double"
+ }
+ },
+ "required": ["name"],
+ "type": "object"
+ },
+ "Liquidation": {
+ "description": "Active Liquidations",
+ "properties": {
+ "orderID": {
+ "format": "guid",
+ "type": "string"
+ },
+ "symbol": {
+ "type": "string"
+ },
+ "side": {
+ "type": "string"
+ },
+ "price": {
+ "format": "double",
+ "type": "number"
+ },
+ "leavesQty": {
+ "format": "int64",
+ "type": "number"
+ }
+ },
+ "required": ["orderID"],
+ "type": "object"
+ },
+ "Notification": {
+ "description": "Account Notifications",
+ "properties": {
+ "id": {
+ "format": "int32",
+ "type": "number"
+ },
+ "date": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "title": {
+ "type": "string"
+ },
+ "body": {
+ "type": "string"
+ },
+ "ttl": {
+ "format": "int32",
+ "type": "number"
+ },
+ "type": {
+ "enum": ["success", "error", "info"],
+ "type": "string"
+ },
+ "closable": {
+ "default": true,
+ "type": "boolean"
+ },
+ "persist": {
+ "default": true,
+ "type": "boolean"
+ },
+ "waitForVisibility": {
+ "default": true,
+ "type": "boolean"
+ },
+ "sound": {
+ "type": "string"
+ }
+ },
+ "required": ["date", "title", "body", "ttl"],
+ "type": "object"
+ },
+ "Order": {
+ "description": "Placement, Cancellation, Amending, and History",
+ "properties": {
+ "orderID": {
+ "format": "guid",
+ "type": "string"
+ },
+ "clOrdID": {
+ "type": "string"
+ },
+ "clOrdLinkID": {
+ "type": "string"
+ },
+ "account": {
+ "format": "int64",
+ "type": "number"
+ },
+ "symbol": {
+ "type": "string"
+ },
+ "side": {
+ "type": "string"
+ },
+ "simpleOrderQty": {
+ "format": "double",
+ "type": "number"
+ },
+ "orderQty": {
+ "format": "int64",
+ "type": "number"
+ },
+ "price": {
+ "format": "double",
+ "type": "number"
+ },
+ "displayQty": {
+ "format": "int64",
+ "type": "number"
+ },
+ "stopPx": {
+ "format": "double",
+ "type": "number"
+ },
+ "pegOffsetValue": {
+ "format": "double",
+ "type": "number"
+ },
+ "pegPriceType": {
+ "type": "string"
+ },
+ "currency": {
+ "type": "string"
+ },
+ "settlCurrency": {
+ "type": "string"
+ },
+ "ordType": {
+ "type": "string"
+ },
+ "timeInForce": {
+ "type": "string"
+ },
+ "execInst": {
+ "type": "string"
+ },
+ "contingencyType": {
+ "type": "string"
+ },
+ "exDestination": {
+ "type": "string"
+ },
+ "ordStatus": {
+ "type": "string"
+ },
+ "triggered": {
+ "type": "string"
+ },
+ "workingIndicator": {
+ "type": "boolean"
+ },
+ "ordRejReason": {
+ "type": "string"
+ },
+ "simpleLeavesQty": {
+ "format": "double",
+ "type": "number"
+ },
+ "leavesQty": {
+ "format": "int64",
+ "type": "number"
+ },
+ "simpleCumQty": {
+ "format": "double",
+ "type": "number"
+ },
+ "cumQty": {
+ "format": "int64",
+ "type": "number"
+ },
+ "avgPx": {
+ "format": "double",
+ "type": "number"
+ },
+ "multiLegReportingType": {
+ "type": "string"
+ },
+ "text": {
+ "type": "string"
+ },
+ "transactTime": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ }
+ },
+ "required": ["orderID"],
+ "type": "object"
+ },
+ "OrderBookL2": {
+ "properties": {
+ "symbol": {
+ "type": "string"
+ },
+ "id": {
+ "format": "int64",
+ "type": "number"
+ },
+ "side": {
+ "type": "string"
+ },
+ "size": {
+ "format": "int64",
+ "type": "number"
+ },
+ "price": {
+ "format": "double",
+ "type": "number"
+ }
+ },
+ "required": ["symbol", "id", "side"],
+ "type": "object"
+ },
+ "Position": {
+ "description": "Summary of Open and Closed Positions",
+ "properties": {
+ "account": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "symbol": {
+ "type": "string"
+ },
+ "currency": {
+ "type": "string"
+ },
+ "underlying": {
+ "type": "string"
+ },
+ "quoteCurrency": {
+ "type": "string"
+ },
+ "commission": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "initMarginReq": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "maintMarginReq": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "riskLimit": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "leverage": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "crossMargin": {
+ "type": "boolean"
+ },
+ "deleveragePercentile": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "rebalancedPnl": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "prevRealisedPnl": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "prevUnrealisedPnl": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "prevClosePrice": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "openingTimestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "openingQty": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "openingCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "openingComm": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "openOrderBuyQty": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "openOrderBuyCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "openOrderBuyPremium": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "openOrderSellQty": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "openOrderSellCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "openOrderSellPremium": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "execBuyQty": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "execBuyCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "execSellQty": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "execSellCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "execQty": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "execCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "execComm": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "currentTimestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "currentQty": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "currentCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "currentComm": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "realisedCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "unrealisedCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "grossOpenCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "grossOpenPremium": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "grossExecCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "isOpen": {
+ "type": "boolean"
+ },
+ "markPrice": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "markValue": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "riskValue": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "homeNotional": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "foreignNotional": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "posState": {
+ "type": "string"
+ },
+ "posCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "posCost2": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "posCross": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "posInit": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "posComm": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "posLoss": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "posMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "posMaint": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "posAllowance": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "taxableMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "initMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "maintMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "sessionMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "targetExcessMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "varMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "realisedGrossPnl": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "realisedTax": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "realisedPnl": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "unrealisedGrossPnl": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "longBankrupt": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "shortBankrupt": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "taxBase": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "indicativeTaxRate": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "indicativeTax": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "unrealisedTax": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "unrealisedPnl": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "unrealisedPnlPcnt": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "unrealisedRoePcnt": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "simpleQty": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "simpleCost": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "simpleValue": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "simplePnl": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "simplePnlPcnt": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "avgCostPrice": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "avgEntryPrice": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "breakEvenPrice": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "marginCallPrice": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "liquidationPrice": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "bankruptPrice": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "lastPrice": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "lastValue": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ }
+ },
+ "required": ["account", "symbol", "currency"],
+ "type": "object"
+ },
+ "Quote": {
+ "description": "Best Bid/Offer Snapshots & Historical Bins",
+ "properties": {
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "symbol": {
+ "type": "string"
+ },
+ "bidSize": {
+ "format": "int64",
+ "type": "number"
+ },
+ "bidPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "askPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "askSize": {
+ "format": "int64",
+ "type": "number"
+ }
+ },
+ "required": ["timestamp", "symbol"],
+ "type": "object"
+ },
+ "Settlement": {
+ "description": "Historical Settlement Data",
+ "properties": {
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "symbol": {
+ "type": "string"
+ },
+ "settlementType": {
+ "type": "string"
+ },
+ "settledPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "optionStrikePrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "optionUnderlyingPrice": {
+ "format": "double",
+ "type": "number"
+ },
+ "bankrupt": {
+ "format": "int64",
+ "type": "number"
+ },
+ "taxBase": {
+ "format": "int64",
+ "type": "number"
+ },
+ "taxRate": {
+ "format": "double",
+ "type": "number"
+ }
+ },
+ "required": ["timestamp", "symbol"],
+ "type": "object"
+ },
+ "Stats": {
+ "description": "Exchange Statistics",
+ "properties": {
+ "rootSymbol": {
+ "type": "string"
+ },
+ "currency": {
+ "type": "string"
+ },
+ "volume24h": {
+ "format": "int64",
+ "type": "number"
+ },
+ "turnover24h": {
+ "format": "int64",
+ "type": "number"
+ },
+ "openInterest": {
+ "format": "int64",
+ "type": "number"
+ },
+ "openValue": {
+ "format": "int64",
+ "type": "number"
+ }
+ },
+ "required": ["rootSymbol"],
+ "type": "object"
+ },
+ "StatsHistory": {
+ "properties": {
+ "date": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "rootSymbol": {
+ "type": "string"
+ },
+ "currency": {
+ "type": "string"
+ },
+ "volume": {
+ "format": "int64",
+ "type": "number"
+ },
+ "turnover": {
+ "format": "int64",
+ "type": "number"
+ }
+ },
+ "required": ["date", "rootSymbol"],
+ "type": "object"
+ },
+ "StatsUSD": {
+ "properties": {
+ "rootSymbol": {
+ "type": "string"
+ },
+ "currency": {
+ "type": "string"
+ },
+ "turnover24h": {
+ "format": "int64",
+ "type": "number"
+ },
+ "turnover30d": {
+ "format": "int64",
+ "type": "number"
+ },
+ "turnover365d": {
+ "format": "int64",
+ "type": "number"
+ },
+ "turnover": {
+ "format": "int64",
+ "type": "number"
+ }
+ },
+ "required": ["rootSymbol"],
+ "type": "object"
+ },
+ "Trade": {
+ "description": "Individual & Bucketed Trades",
+ "properties": {
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "symbol": {
+ "type": "string"
+ },
+ "side": {
+ "type": "string"
+ },
+ "size": {
+ "format": "int64",
+ "type": "number"
+ },
+ "price": {
+ "format": "double",
+ "type": "number"
+ },
+ "tickDirection": {
+ "type": "string"
+ },
+ "trdMatchID": {
+ "format": "guid",
+ "type": "string"
+ },
+ "grossValue": {
+ "format": "int64",
+ "type": "number"
+ },
+ "homeNotional": {
+ "format": "double",
+ "type": "number"
+ },
+ "foreignNotional": {
+ "format": "double",
+ "type": "number"
+ }
+ },
+ "required": ["timestamp", "symbol"],
+ "type": "object"
+ },
+ "TradeBin": {
+ "properties": {
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "symbol": {
+ "type": "string"
+ },
+ "open": {
+ "format": "double",
+ "type": "number"
+ },
+ "high": {
+ "format": "double",
+ "type": "number"
+ },
+ "low": {
+ "format": "double",
+ "type": "number"
+ },
+ "close": {
+ "format": "double",
+ "type": "number"
+ },
+ "trades": {
+ "format": "int64",
+ "type": "number"
+ },
+ "volume": {
+ "format": "int64",
+ "type": "number"
+ },
+ "vwap": {
+ "format": "double",
+ "type": "number"
+ },
+ "lastSize": {
+ "format": "int64",
+ "type": "number"
+ },
+ "turnover": {
+ "format": "int64",
+ "type": "number"
+ },
+ "homeNotional": {
+ "format": "double",
+ "type": "number"
+ },
+ "foreignNotional": {
+ "format": "double",
+ "type": "number"
+ }
+ },
+ "required": ["timestamp", "symbol"],
+ "type": "object"
+ },
+ "Wallet": {
+ "properties": {
+ "account": {
+ "format": "int64",
+ "type": "number"
+ },
+ "currency": {
+ "type": "string"
+ },
+ "prevDeposited": {
+ "format": "int64",
+ "type": "number"
+ },
+ "prevWithdrawn": {
+ "format": "int64",
+ "type": "number"
+ },
+ "prevTransferIn": {
+ "format": "int64",
+ "type": "number"
+ },
+ "prevTransferOut": {
+ "format": "int64",
+ "type": "number"
+ },
+ "prevAmount": {
+ "format": "int64",
+ "type": "number"
+ },
+ "prevTimestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "deltaDeposited": {
+ "format": "int64",
+ "type": "number"
+ },
+ "deltaWithdrawn": {
+ "format": "int64",
+ "type": "number"
+ },
+ "deltaTransferIn": {
+ "format": "int64",
+ "type": "number"
+ },
+ "deltaTransferOut": {
+ "format": "int64",
+ "type": "number"
+ },
+ "deltaAmount": {
+ "format": "int64",
+ "type": "number"
+ },
+ "deposited": {
+ "format": "int64",
+ "type": "number"
+ },
+ "withdrawn": {
+ "format": "int64",
+ "type": "number"
+ },
+ "transferIn": {
+ "format": "int64",
+ "type": "number"
+ },
+ "transferOut": {
+ "format": "int64",
+ "type": "number"
+ },
+ "amount": {
+ "format": "int64",
+ "type": "number"
+ },
+ "pendingCredit": {
+ "format": "int64",
+ "type": "number"
+ },
+ "pendingDebit": {
+ "format": "int64",
+ "type": "number"
+ },
+ "confirmedDebit": {
+ "format": "int64",
+ "type": "number"
+ },
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "addr": {
+ "type": "string"
+ },
+ "script": {
+ "type": "string"
+ },
+ "withdrawalLock": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "required": ["account", "currency"],
+ "type": "object"
+ },
+ "Transaction": {
+ "properties": {
+ "transactID": {
+ "format": "guid",
+ "type": "string"
+ },
+ "account": {
+ "format": "int64",
+ "type": "number"
+ },
+ "currency": {
+ "type": "string"
+ },
+ "transactType": {
+ "type": "string"
+ },
+ "amount": {
+ "format": "int64",
+ "type": "number"
+ },
+ "fee": {
+ "format": "int64",
+ "type": "number"
+ },
+ "transactStatus": {
+ "type": "string"
+ },
+ "address": {
+ "type": "string"
+ },
+ "tx": {
+ "type": "string"
+ },
+ "text": {
+ "type": "string"
+ },
+ "transactTime": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ }
+ },
+ "required": ["transactID"],
+ "type": "object"
+ },
+ "AccessToken": {
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "ttl": {
+ "default": 1209600,
+ "description": "time to live in seconds (2 weeks by default)",
+ "type": "number",
+ "format": "double"
+ },
+ "created": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "userId": {
+ "type": "number",
+ "format": "double"
+ }
+ },
+ "required": ["id"],
+ "type": "object"
+ },
+ "Affiliate": {
+ "properties": {
+ "account": {
+ "format": "int64",
+ "type": "number"
+ },
+ "currency": {
+ "type": "string"
+ },
+ "prevPayout": {
+ "format": "int64",
+ "type": "number"
+ },
+ "prevTurnover": {
+ "format": "int64",
+ "type": "number"
+ },
+ "prevComm": {
+ "format": "int64",
+ "type": "number"
+ },
+ "prevTimestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "execTurnover": {
+ "format": "int64",
+ "type": "number"
+ },
+ "execComm": {
+ "format": "int64",
+ "type": "number"
+ },
+ "totalReferrals": {
+ "format": "int64",
+ "type": "number"
+ },
+ "totalTurnover": {
+ "format": "int64",
+ "type": "number"
+ },
+ "totalComm": {
+ "format": "int64",
+ "type": "number"
+ },
+ "payoutPcnt": {
+ "format": "double",
+ "type": "number"
+ },
+ "pendingPayout": {
+ "format": "int64",
+ "type": "number"
+ },
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "referrerAccount": {
+ "type": "number",
+ "format": "double"
+ }
+ },
+ "required": ["account", "currency"],
+ "type": "object"
+ },
+ "User": {
+ "description": "Account Operations",
+ "properties": {
+ "id": {
+ "format": "int32",
+ "type": "number"
+ },
+ "ownerId": {
+ "format": "int32",
+ "type": "number"
+ },
+ "firstname": {
+ "type": "string"
+ },
+ "lastname": {
+ "type": "string"
+ },
+ "username": {
+ "type": "string"
+ },
+ "email": {
+ "type": "string"
+ },
+ "phone": {
+ "type": "string"
+ },
+ "created": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "lastUpdated": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "preferences": {
+ "default": null,
+ "$ref": "#/definitions/UserPreferences"
+ },
+ "TFAEnabled": {
+ "type": "string"
+ },
+ "affiliateID": {
+ "maxLength": 6,
+ "type": "string"
+ },
+ "pgpPubKey": {
+ "maxLength": 16384,
+ "type": "string"
+ },
+ "country": {
+ "maxLength": 3,
+ "type": "string"
+ },
+ "geoipCountry": {
+ "maxLength": 2,
+ "type": "string"
+ },
+ "geoipRegion": {
+ "maxLength": 2,
+ "type": "string"
+ },
+ "typ": {
+ "type": "string"
+ }
+ },
+ "required": ["username", "email"],
+ "type": "object"
+ },
+ "UserCommission": {
+ "properties": {
+ "makerFee": {
+ "type": "number",
+ "format": "double"
+ },
+ "takerFee": {
+ "type": "number",
+ "format": "double"
+ },
+ "settlementFee": {
+ "type": "number",
+ "format": "double"
+ },
+ "maxFee": {
+ "type": "number",
+ "format": "double"
+ }
+ },
+ "type": "object"
+ },
+ "Margin": {
+ "properties": {
+ "account": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "currency": {
+ "type": "string"
+ },
+ "riskLimit": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "prevState": {
+ "type": "string"
+ },
+ "state": {
+ "type": "string"
+ },
+ "action": {
+ "type": "string"
+ },
+ "amount": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "pendingCredit": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "pendingDebit": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "confirmedDebit": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "prevRealisedPnl": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "prevUnrealisedPnl": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "grossComm": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "grossOpenCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "grossOpenPremium": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "grossExecCost": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "grossMarkValue": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "riskValue": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "taxableMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "initMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "maintMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "sessionMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "targetExcessMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "varMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "realisedPnl": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "unrealisedPnl": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "indicativeTax": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "unrealisedProfit": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "syntheticMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "walletBalance": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "marginBalance": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "marginBalancePcnt": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "marginLeverage": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "marginUsedPcnt": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "excessMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "excessMarginPcnt": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ },
+ "availableMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "withdrawableMargin": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "timestamp": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "grossLastValue": {
+ "format": "int64",
+ "default": 0,
+ "type": "number"
+ },
+ "commission": {
+ "format": "double",
+ "default": 0,
+ "type": "number"
+ }
+ },
+ "required": ["account", "currency"],
+ "type": "object"
+ },
+ "UserPreferences": {
+ "properties": {
+ "alertOnLiquidations": {
+ "type": "boolean"
+ },
+ "animationsEnabled": {
+ "type": "boolean"
+ },
+ "announcementsLastSeen": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "chatChannelID": {
+ "type": "number",
+ "format": "double"
+ },
+ "colorTheme": {
+ "type": "string"
+ },
+ "currency": {
+ "type": "string"
+ },
+ "debug": {
+ "type": "boolean"
+ },
+ "disableEmails": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "hideConfirmDialogs": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "hideConnectionModal": {
+ "type": "boolean"
+ },
+ "hideFromLeaderboard": {
+ "default": false,
+ "type": "boolean"
+ },
+ "hideNameFromLeaderboard": {
+ "default": true,
+ "type": "boolean"
+ },
+ "hideNotifications": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "locale": {
+ "default": "en-US",
+ "type": "string"
+ },
+ "msgsSeen": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "orderBookBinning": {
+ "type": "object"
+ },
+ "orderBookType": {
+ "type": "string"
+ },
+ "orderClearImmediate": {
+ "default": false,
+ "type": "boolean"
+ },
+ "orderControlsPlusMinus": {
+ "type": "boolean"
+ },
+ "showLocaleNumbers": {
+ "default": true,
+ "type": "boolean"
+ },
+ "sounds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "strictIPCheck": {
+ "default": false,
+ "type": "boolean"
+ },
+ "strictTimeout": {
+ "default": true,
+ "type": "boolean"
+ },
+ "tickerGroup": {
+ "type": "string"
+ },
+ "tickerPinned": {
+ "type": "boolean"
+ },
+ "tradeLayout": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "securityDefinitions": {
+ "apiKey": {
+ "type": "apiKey",
+ "in": "header",
+ "name": "api-key"
+ },
+ "apiSignature": {
+ "type": "apiKey",
+ "in": "header",
+ "name": "api-signature"
+ },
+ "apiNonce": {
+ "type": "apiKey",
+ "in": "header",
+ "name": "api-nonce"
+ }
+ },
+ "security": [{
+ "apiKey": [],
+ "apiSignature": [],
+ "apiNonce": []
+ }]
+}
diff --git a/testdata/configtest.json b/testdata/configtest.json
index 7884871d..65bd5c9c 100644
--- a/testdata/configtest.json
+++ b/testdata/configtest.json
@@ -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": [
diff --git a/tools/documentation/documentation.go b/tools/documentation/documentation.go
index efe21a92..bbef42af 100644
--- a/tools/documentation/documentation.go
+++ b/tools/documentation/documentation.go
@@ -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)
diff --git a/tools/documentation/exchanges_templates/bitmex.tmpl b/tools/documentation/exchanges_templates/bitmex.tmpl
new file mode 100644
index 00000000..0aba53ac
--- /dev/null
+++ b/tools/documentation/exchanges_templates/bitmex.tmpl
@@ -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}}
diff --git a/tools/documentation/root_templates/root_readme.tmpl b/tools/documentation/root_templates/root_readme.tmpl
index b36b8105..078c0d71 100644
--- a/tools/documentation/root_templates/root_readme.tmpl
+++ b/tools/documentation/root_templates/root_readme.tmpl
@@ -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 |