mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-16 23:16:48 +00:00
Bitmex exchange (#160)
* Added REST support for Bitmex * Added Bitmex documentation updates * Update config_example.json * Added final REST functions for user account operations. * Added initial websocket support * Change function access Added reconnection logic * Added initial routine management Updated wrapper functions * General fixes
This commit is contained in:
committed by
Adrian Gallagher
parent
a0de1b78a7
commit
06a0caec43
@@ -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 |
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/bitfinex"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/bitflyer"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/bithumb"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/bitmex"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/bitstamp"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/bittrex"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/btcc"
|
||||
@@ -145,6 +146,8 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error {
|
||||
exch = new(bitflyer.Bitflyer)
|
||||
case "bithumb":
|
||||
exch = new(bithumb.Bithumb)
|
||||
case "bitmex":
|
||||
exch = new(bitmex.Bitmex)
|
||||
case "bitstamp":
|
||||
exch = new(bitstamp.Bitstamp)
|
||||
case "bittrex":
|
||||
|
||||
133
exchanges/bitmex/README.md
Normal file
133
exchanges/bitmex/README.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# GoCryptoTrader package Bitmex
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](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
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
***1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB***
|
||||
|
||||
893
exchanges/bitmex/bitmex.go
Normal file
893
exchanges/bitmex/bitmex.go
Normal file
@@ -0,0 +1,893 @@
|
||||
package bitmex
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
// Bitmex is the overarching type across this package
|
||||
type Bitmex struct {
|
||||
exchange.Base
|
||||
WebsocketConn *websocket.Conn
|
||||
shutdown *Shutdown
|
||||
}
|
||||
|
||||
const (
|
||||
bitmexAPIVersion = "v1"
|
||||
bitmexAPIURL = "https://www.bitmex.com/api/v1"
|
||||
bitmexAPItestnetURL = "https://testnet.bitmex.com/api/v1"
|
||||
|
||||
// Public endpoints
|
||||
bitmexEndpointAnnouncement = "/announcement"
|
||||
bitmexEndpointAnnouncementUrgent = "/announcement/urgent"
|
||||
bitmexEndpointOrderbookL2 = "/orderBook/L2"
|
||||
bitmexEndpointTrollbox = "/chat"
|
||||
bitmexEndpointTrollboxChannels = "/chat/channels"
|
||||
bitmexEndpointTrollboxConnected = "/chat/connected"
|
||||
bitmexEndpointFundingHistory = "/funding"
|
||||
bitmexEndpointInstruments = "/instrument"
|
||||
bitmexEndpointActiveInstruments = "/instrument/active"
|
||||
bitmexEndpointActiveAndIndexInstruments = "/instrument/activeAndIndices"
|
||||
bitmexEndpointActiveIntervals = "/instrument/activeIntervals"
|
||||
bitmexEndpointCompositeIndex = "/instrument/compositeIndex"
|
||||
bitmexEndpointIndices = "/instrument/indices"
|
||||
bitmexEndpointInsuranceHistory = "/insurance"
|
||||
bitmexEndpointLiquidation = "/liquidation"
|
||||
bitmexEndpointLeader = "/leaderboard"
|
||||
bitmexEndpointAlias = "/leaderboard/name"
|
||||
bitmexEndpointQuote = "/quote"
|
||||
bitmexEndpointQuoteBucketed = "/quote/bucketed"
|
||||
bitmexEndpointSettlement = "/settlement"
|
||||
bitmexEndpointStats = "/stats"
|
||||
bitmexEndpointStatsHistory = "/stats/history"
|
||||
bitmexEndpointStatsSummary = "/stats/historyUSD"
|
||||
bitmexEndpointTrade = "/trade"
|
||||
bitmexEndpointTradeBucketed = "/trade/bucketed"
|
||||
bitmexEndpointUserCheckReferralCode = "/user/checkReferralCode"
|
||||
bitmexEndpointUserMinWithdrawalFee = "/user/minWithdrawalFee"
|
||||
|
||||
// Authenticated endpoints
|
||||
bitmexEndpointAPIkeys = "/apiKey"
|
||||
bitmexEndpointDisableAPIkey = "/apiKey/disable"
|
||||
bitmexEndpointEnableAPIkey = "/apiKey/enable"
|
||||
bitmexEndpointTrollboxSend = "/chat"
|
||||
bitmexEndpointExecution = "/execution"
|
||||
bitmexEndpointExecutionTradeHistory = "/execution/tradeHistory"
|
||||
bitmexEndpointNotifications = "/notification"
|
||||
bitmexEndpointOrder = "/order"
|
||||
bitmexEndpointCancelAllOrders = "/order/all"
|
||||
bitmexEndpointBulk = "/order/bulk"
|
||||
bitmexEndpointCancelOrderAfter = "/order/cancelAllAfter"
|
||||
bitmexEndpointClosePosition = "/order/closePosition"
|
||||
bitmexEndpointPosition = "/position"
|
||||
bitmexEndpointIsolatePosition = "/position/isolate"
|
||||
bitmexEndpointLeveragePosition = "/position/leverage"
|
||||
bitmexEndpointAdjustRiskLimit = "/position/riskLimit"
|
||||
bitmexEndpointTransferMargin = "/position/transferMargin"
|
||||
bitmexEndpointUser = "/user"
|
||||
bitmexEndpointUserAffiliate = "/user/affiliateStatus"
|
||||
bitmexEndpointUserCancelWithdraw = "/user/cancelWithdrawal"
|
||||
bitmexEndpointUserCommision = "/user/commission"
|
||||
bitmexEndpointUserConfirmEmail = "/user/confirmEmail"
|
||||
bitmexEndpointUserConfirmTFA = "/user/confirmEnableTFA"
|
||||
bitmexEndpointUserConfirmWithdrawal = "/user/confirmWithdrawal"
|
||||
bitmexEndpointUserDepositAddress = "/user/depositAddress"
|
||||
bitmexEndpointUserDisableTFA = "/user/disableTFA"
|
||||
bitmexEndpointUserLogout = "/user/logout"
|
||||
bitmexEndpointUserLogoutAll = "/user/logoutAll"
|
||||
bitmexEndpointUserMargin = "/user/margin"
|
||||
bitmexEndpointUserPreferences = "/user/preferences"
|
||||
bitmexEndpointUserRequestTFA = "/user/requestEnableTFA"
|
||||
bitmexEndpointUserWallet = "/user/wallet"
|
||||
bitmexEndpointUserWalletHistory = "/user/walletHistory"
|
||||
bitmexEndpointUserWalletSummary = "/user/walletSummary"
|
||||
bitmexEndpointUserRequestWithdraw = "/user/requestWithdrawal"
|
||||
|
||||
// Rate limits - 150 requests per 5 minutes
|
||||
bitmexUnauthRate = 30
|
||||
// 300 requests per 5 minutes
|
||||
bitmexAuthRate = 40
|
||||
|
||||
// ContractPerpetual perpetual contract type
|
||||
ContractPerpetual = iota
|
||||
// ContractFutures futures contract type
|
||||
ContractFutures
|
||||
// ContractDownsideProfit downside profit contract type
|
||||
ContractDownsideProfit
|
||||
// ContractUpsideProfit upside profit contract type
|
||||
ContractUpsideProfit
|
||||
)
|
||||
|
||||
// SetDefaults sets the basic defaults for Bitmex
|
||||
func (b *Bitmex) SetDefaults() {
|
||||
b.Name = "Bitmex"
|
||||
b.Enabled = false
|
||||
b.Verbose = false
|
||||
b.Websocket = false
|
||||
b.RESTPollingDelay = 10
|
||||
b.RequestCurrencyPairFormat.Delimiter = ""
|
||||
b.RequestCurrencyPairFormat.Uppercase = true
|
||||
b.ConfigCurrencyPairFormat.Delimiter = ""
|
||||
b.ConfigCurrencyPairFormat.Uppercase = true
|
||||
b.AssetTypes = []string{ticker.Spot}
|
||||
b.Requester = request.New(b.Name,
|
||||
request.NewRateLimit(time.Second, bitmexAuthRate),
|
||||
request.NewRateLimit(time.Second, bitmexUnauthRate),
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
|
||||
b.shutdown = b.NewRoutineManagement()
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
func (b *Bitmex) Setup(exch config.ExchangeConfig) {
|
||||
if !exch.Enabled {
|
||||
b.SetEnabled(false)
|
||||
} else {
|
||||
b.Enabled = true
|
||||
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
b.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
b.RESTPollingDelay = exch.RESTPollingDelay
|
||||
b.Verbose = exch.Verbose
|
||||
b.Websocket = exch.Websocket
|
||||
b.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
|
||||
b.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
|
||||
b.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
|
||||
err := b.SetCurrencyPairFormat()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = b.SetAssetTypes()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetAnnouncement returns the general announcements from Bitmex
|
||||
func (b *Bitmex) GetAnnouncement() ([]Announcement, error) {
|
||||
var announcement []Announcement
|
||||
|
||||
return announcement, b.SendHTTPRequest(bitmexEndpointAnnouncement,
|
||||
nil,
|
||||
&announcement)
|
||||
}
|
||||
|
||||
// GetUrgentAnnouncement returns an urgent announcement for your account
|
||||
func (b *Bitmex) GetUrgentAnnouncement() ([]Announcement, error) {
|
||||
var announcement []Announcement
|
||||
|
||||
return announcement, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointAnnouncementUrgent,
|
||||
nil,
|
||||
&announcement)
|
||||
}
|
||||
|
||||
// GetAPIKeys returns the APIkeys from bitmex
|
||||
func (b *Bitmex) GetAPIKeys() ([]APIKey, error) {
|
||||
var keys []APIKey
|
||||
|
||||
return keys, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointAPIkeys,
|
||||
nil,
|
||||
&keys)
|
||||
}
|
||||
|
||||
// RemoveAPIKey removes an Apikey from the bitmex trading engine
|
||||
func (b *Bitmex) RemoveAPIKey(params APIKeyParams) (bool, error) {
|
||||
var keyDeleted bool
|
||||
|
||||
return keyDeleted, b.SendAuthenticatedHTTPRequest("DELETE",
|
||||
bitmexEndpointAPIkeys,
|
||||
params,
|
||||
&keyDeleted)
|
||||
}
|
||||
|
||||
// DisableAPIKey disables an Apikey from the bitmex trading engine
|
||||
func (b *Bitmex) DisableAPIKey(params APIKeyParams) (APIKey, error) {
|
||||
var keyInfo APIKey
|
||||
|
||||
return keyInfo, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointDisableAPIkey,
|
||||
params,
|
||||
&keyInfo)
|
||||
}
|
||||
|
||||
// EnableAPIKey enables an Apikey from the bitmex trading engine
|
||||
func (b *Bitmex) EnableAPIKey(params APIKeyParams) (APIKey, error) {
|
||||
var keyInfo APIKey
|
||||
|
||||
return keyInfo, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointEnableAPIkey,
|
||||
params,
|
||||
&keyInfo)
|
||||
}
|
||||
|
||||
// GetTrollboxMessages returns messages from the bitmex trollbox
|
||||
func (b *Bitmex) GetTrollboxMessages(params ChatGetParams) ([]Chat, error) {
|
||||
var messages []Chat
|
||||
|
||||
return messages, b.SendHTTPRequest(bitmexEndpointTrollbox, params, &messages)
|
||||
}
|
||||
|
||||
// SendTrollboxMessage sends a message to the bitmex trollbox
|
||||
func (b *Bitmex) SendTrollboxMessage(params ChatSendParams) ([]Chat, error) {
|
||||
var messages []Chat
|
||||
|
||||
return messages, b.SendAuthenticatedHTTPRequest("POST",
|
||||
bitmexEndpointTrollboxSend,
|
||||
params,
|
||||
&messages)
|
||||
}
|
||||
|
||||
// GetTrollboxChannels the channels from the the bitmex trollbox
|
||||
func (b *Bitmex) GetTrollboxChannels() ([]ChatChannel, error) {
|
||||
var channels []ChatChannel
|
||||
|
||||
return channels, b.SendHTTPRequest(bitmexEndpointTrollboxChannels,
|
||||
nil,
|
||||
&channels)
|
||||
}
|
||||
|
||||
// GetTrollboxConnectedUsers the channels from the the bitmex trollbox
|
||||
func (b *Bitmex) GetTrollboxConnectedUsers() (ConnectedUsers, error) {
|
||||
var users ConnectedUsers
|
||||
|
||||
return users, b.SendHTTPRequest(bitmexEndpointTrollboxConnected, nil, &users)
|
||||
}
|
||||
|
||||
// GetAccountExecutions returns all raw transactions, which includes order
|
||||
// opening and cancelation, and order status changes. It can be quite noisy.
|
||||
// More focused information is available at /execution/tradeHistory.
|
||||
func (b *Bitmex) GetAccountExecutions(params GenericRequestParams) ([]Execution, error) {
|
||||
var executionList []Execution
|
||||
|
||||
return executionList, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointExecution,
|
||||
params,
|
||||
&executionList)
|
||||
}
|
||||
|
||||
// GetAccountExecutionTradeHistory returns all balance-affecting executions.
|
||||
// This includes each trade, insurance charge, and settlement.
|
||||
func (b *Bitmex) GetAccountExecutionTradeHistory(params GenericRequestParams) ([]Execution, error) {
|
||||
var tradeHistory []Execution
|
||||
|
||||
return tradeHistory, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointExecutionTradeHistory,
|
||||
params,
|
||||
&tradeHistory)
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history
|
||||
func (b *Bitmex) GetFundingHistory() ([]Funding, error) {
|
||||
var fundingHistory []Funding
|
||||
|
||||
return fundingHistory, b.SendHTTPRequest(bitmexEndpointFundingHistory,
|
||||
nil,
|
||||
&fundingHistory)
|
||||
}
|
||||
|
||||
// GetInstruments returns instrument data
|
||||
func (b *Bitmex) GetInstruments(params GenericRequestParams) ([]Instrument, error) {
|
||||
var instruments []Instrument
|
||||
|
||||
return instruments, b.SendHTTPRequest(bitmexEndpointInstruments,
|
||||
params,
|
||||
&instruments)
|
||||
}
|
||||
|
||||
// GetActiveInstruments returns active instruments
|
||||
func (b *Bitmex) GetActiveInstruments(params GenericRequestParams) ([]Instrument, error) {
|
||||
var activeInstruments []Instrument
|
||||
|
||||
return activeInstruments, b.SendHTTPRequest(bitmexEndpointActiveInstruments,
|
||||
params,
|
||||
&activeInstruments)
|
||||
}
|
||||
|
||||
// GetActiveAndIndexInstruments returns all active instruments and all indices
|
||||
func (b *Bitmex) GetActiveAndIndexInstruments() ([]Instrument, error) {
|
||||
var activeAndIndices []Instrument
|
||||
|
||||
return activeAndIndices,
|
||||
b.SendHTTPRequest(bitmexEndpointActiveAndIndexInstruments,
|
||||
nil,
|
||||
&activeAndIndices)
|
||||
}
|
||||
|
||||
// GetActiveIntervals returns funding history
|
||||
func (b *Bitmex) GetActiveIntervals() (InstrumentInterval, error) {
|
||||
var interval InstrumentInterval
|
||||
|
||||
return interval, b.SendHTTPRequest(bitmexEndpointActiveIntervals,
|
||||
nil,
|
||||
&interval)
|
||||
}
|
||||
|
||||
// GetCompositeIndex returns composite index
|
||||
func (b *Bitmex) GetCompositeIndex(params GenericRequestParams) ([]IndexComposite, error) {
|
||||
var compositeIndices []IndexComposite
|
||||
|
||||
return compositeIndices, b.SendHTTPRequest(bitmexEndpointCompositeIndex,
|
||||
params,
|
||||
&compositeIndices)
|
||||
}
|
||||
|
||||
// GetIndices returns all price indices
|
||||
func (b *Bitmex) GetIndices() ([]Instrument, error) {
|
||||
var indices []Instrument
|
||||
|
||||
return indices, b.SendHTTPRequest(bitmexEndpointIndices, nil, &indices)
|
||||
}
|
||||
|
||||
// GetInsuranceFundHistory returns insurance fund history
|
||||
func (b *Bitmex) GetInsuranceFundHistory(params GenericRequestParams) ([]Insurance, error) {
|
||||
var history []Insurance
|
||||
|
||||
return history, b.SendHTTPRequest(bitmexEndpointIndices, params, &history)
|
||||
}
|
||||
|
||||
// GetLeaderboard returns leaderboard information
|
||||
func (b *Bitmex) GetLeaderboard(params LeaderboardGetParams) ([]Leaderboard, error) {
|
||||
var leader []Leaderboard
|
||||
|
||||
return leader, b.SendHTTPRequest(bitmexEndpointLeader, params, &leader)
|
||||
}
|
||||
|
||||
// GetAliasOnLeaderboard returns your alias on the leaderboard
|
||||
func (b *Bitmex) GetAliasOnLeaderboard() (Alias, error) {
|
||||
var alias Alias
|
||||
|
||||
return alias, b.SendHTTPRequest(bitmexEndpointAlias, nil, &alias)
|
||||
}
|
||||
|
||||
// GetLiquidationOrders returns liquidation orders
|
||||
func (b *Bitmex) GetLiquidationOrders(params GenericRequestParams) ([]Liquidation, error) {
|
||||
var orders []Liquidation
|
||||
|
||||
return orders, b.SendHTTPRequest(bitmexEndpointLiquidation,
|
||||
params,
|
||||
&orders)
|
||||
}
|
||||
|
||||
// GetCurrentNotifications returns your current notifications
|
||||
func (b *Bitmex) GetCurrentNotifications() ([]Notification, error) {
|
||||
var notifications []Notification
|
||||
|
||||
return notifications, b.SendAuthenticatedHTTPRequest("GET",
|
||||
bitmexEndpointNotifications,
|
||||
nil,
|
||||
¬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
|
||||
}
|
||||
1123
exchanges/bitmex/bitmex_parameters.go
Normal file
1123
exchanges/bitmex/bitmex_parameters.go
Normal file
File diff suppressed because it is too large
Load Diff
365
exchanges/bitmex/bitmex_test.go
Normal file
365
exchanges/bitmex/bitmex_test.go
Normal file
@@ -0,0 +1,365 @@
|
||||
package bitmex
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
)
|
||||
|
||||
// Please supply your own keys here for due diligence testing
|
||||
const (
|
||||
testAPIKey = ""
|
||||
testAPISecret = ""
|
||||
)
|
||||
|
||||
var b Bitmex
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
cfg.LoadConfig("../../testdata/configtest.json")
|
||||
bitmexConfig, err := cfg.GetExchangeConfig("Bitmex")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - Bitmex Setup() init error")
|
||||
}
|
||||
|
||||
bitmexConfig.AuthenticatedAPISupport = true
|
||||
bitmexConfig.APIKey = testAPIKey
|
||||
bitmexConfig.APISecret = testAPISecret
|
||||
|
||||
b.Setup(bitmexConfig)
|
||||
}
|
||||
|
||||
func TestStart(t *testing.T) {
|
||||
var testWg sync.WaitGroup
|
||||
b.Start(&testWg)
|
||||
testWg.Wait()
|
||||
}
|
||||
|
||||
func TestGetUrgentAnnouncement(t *testing.T) {
|
||||
_, err := b.GetUrgentAnnouncement()
|
||||
if err == nil {
|
||||
t.Error("test failed - GetUrgentAnnouncement() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAPIKeys(t *testing.T) {
|
||||
_, err := b.GetAPIKeys()
|
||||
if err == nil {
|
||||
t.Error("test failed - GetAPIKeys() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveAPIKey(t *testing.T) {
|
||||
_, err := b.RemoveAPIKey(APIKeyParams{APIKeyID: "1337"})
|
||||
if err == nil {
|
||||
t.Error("test failed - RemoveAPIKey() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisableAPIKey(t *testing.T) {
|
||||
_, err := b.DisableAPIKey(APIKeyParams{APIKeyID: "1337"})
|
||||
if err == nil {
|
||||
t.Error("test failed - DisableAPIKey() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnableAPIKey(t *testing.T) {
|
||||
_, err := b.EnableAPIKey(APIKeyParams{APIKeyID: "1337"})
|
||||
if err == nil {
|
||||
t.Error("test failed - EnableAPIKey() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTrollboxMessages(t *testing.T) {
|
||||
_, err := b.GetTrollboxMessages(ChatGetParams{Count: 5})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetTrollboxMessages() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendTrollboxMessage(t *testing.T) {
|
||||
_, err := b.SendTrollboxMessage(ChatSendParams{
|
||||
ChannelID: 1337,
|
||||
Message: "Hello,World!"})
|
||||
if err == nil {
|
||||
t.Error("test failed - SendTrollboxMessage() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTrollboxChannels(t *testing.T) {
|
||||
_, err := b.GetTrollboxChannels()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetTrollboxChannels() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTrollboxConnectedUsers(t *testing.T) {
|
||||
_, err := b.GetTrollboxConnectedUsers()
|
||||
if err == nil {
|
||||
t.Error("test failed - GetTrollboxConnectedUsers() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccountExecutions(t *testing.T) {
|
||||
_, err := b.GetAccountExecutions(GenericRequestParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetAccountExecutions() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccountExecutionTradeHistory(t *testing.T) {
|
||||
_, err := b.GetAccountExecutionTradeHistory(GenericRequestParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetAccountExecutionTradeHistory() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFundingHistory(t *testing.T) {
|
||||
_, err := b.GetFundingHistory()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetFundingHistory() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInstruments(t *testing.T) {
|
||||
_, err := b.GetInstruments(GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetInstruments() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveInstruments(t *testing.T) {
|
||||
_, err := b.GetActiveInstruments(GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetActiveInstruments() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveAndIndexInstruments(t *testing.T) {
|
||||
_, err := b.GetActiveAndIndexInstruments()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetActiveAndIndexInstruments() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveIntervals(t *testing.T) {
|
||||
_, err := b.GetActiveIntervals()
|
||||
if err == nil {
|
||||
t.Error("test failed - GetActiveIntervals() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCompositeIndex(t *testing.T) {
|
||||
_, err := b.GetCompositeIndex(GenericRequestParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetCompositeIndex() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetIndices(t *testing.T) {
|
||||
_, err := b.GetIndices()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetIndices() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInsuranceFundHistory(t *testing.T) {
|
||||
_, err := b.GetInsuranceFundHistory(GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetInsuranceFundHistory() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLeaderboard(t *testing.T) {
|
||||
_, err := b.GetLeaderboard(LeaderboardGetParams{})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetLeaderboard() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAliasOnLeaderboard(t *testing.T) {
|
||||
_, err := b.GetAliasOnLeaderboard()
|
||||
if err == nil {
|
||||
t.Error("test failed - GetAliasOnLeaderboard() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLiquidationOrders(t *testing.T) {
|
||||
_, err := b.GetLiquidationOrders(GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetLiquidationOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCurrentNotifications(t *testing.T) {
|
||||
_, err := b.GetCurrentNotifications()
|
||||
if err == nil {
|
||||
t.Error("test failed - GetCurrentNotifications() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrders(t *testing.T) {
|
||||
_, err := b.GetOrders(GenericRequestParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAmendOrder(t *testing.T) {
|
||||
_, err := b.AmendOrder(OrderAmendParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - AmendOrder() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateOrder(t *testing.T) {
|
||||
_, err := b.CreateOrder(OrderNewParams{Symbol: "XBTM15",
|
||||
Price: 219.0,
|
||||
ClOrdID: "mm_bitmex_1a/oemUeQ4CAJZgP3fjHsA",
|
||||
OrderQty: 98})
|
||||
if err == nil {
|
||||
t.Error("test failed - CreateOrder() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelOrders(t *testing.T) {
|
||||
_, err := b.CancelOrders(OrderCancelParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - CancelOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelAllOrders(t *testing.T) {
|
||||
_, err := b.CancelAllOrders(OrderCancelAllParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - CancelAllOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAmendBulkOrders(t *testing.T) {
|
||||
_, err := b.AmendBulkOrders(OrderAmendBulkParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - AmendBulkOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateBulkOrders(t *testing.T) {
|
||||
_, err := b.CreateBulkOrders(OrderNewBulkParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - CreateBulkOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelAllOrdersAfterTime(t *testing.T) {
|
||||
_, err := b.CancelAllOrdersAfterTime(OrderCancelAllAfterParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - CancelAllOrdersAfterTime() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClosePosition(t *testing.T) {
|
||||
_, err := b.ClosePosition(OrderClosePositionParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - ClosePosition() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderbook(t *testing.T) {
|
||||
_, err := b.GetOrderbook(OrderBookGetL2Params{Symbol: "XBT"})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetOrderbook() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPositions(t *testing.T) {
|
||||
_, err := b.GetPositions(PositionGetParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetPositions() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsolatePosition(t *testing.T) {
|
||||
_, err := b.IsolatePosition(PositionIsolateMarginParams{Symbol: "XBT"})
|
||||
if err == nil {
|
||||
t.Error("test failed - IsolatePosition() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLeveragePosition(t *testing.T) {
|
||||
_, err := b.LeveragePosition(PositionUpdateLeverageParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - LeveragePosition() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateRiskLimit(t *testing.T) {
|
||||
_, err := b.UpdateRiskLimit(PositionUpdateRiskLimitParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - UpdateRiskLimit() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransferMargin(t *testing.T) {
|
||||
_, err := b.TransferMargin(PositionTransferIsolatedMarginParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - TransferMargin() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetQuotesByBuckets(t *testing.T) {
|
||||
_, err := b.GetQuotesByBuckets(QuoteGetBucketedParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetQuotesByBuckets() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSettlementHistory(t *testing.T) {
|
||||
_, err := b.GetSettlementHistory(GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetSettlementHistory() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStats(t *testing.T) {
|
||||
_, err := b.GetStats()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetStats() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStatsHistorical(t *testing.T) {
|
||||
_, err := b.GetStatsHistorical()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetStatsHistorical() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStatSummary(t *testing.T) {
|
||||
_, err := b.GetStatSummary()
|
||||
if err != nil {
|
||||
t.Error("test failed - GetStatSummary() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTrade(t *testing.T) {
|
||||
_, err := b.GetTrade(GenericRequestParams{
|
||||
Symbol: "XBTUSD",
|
||||
StartTime: time.Now().Format(time.RFC3339),
|
||||
Reverse: true})
|
||||
if err != nil {
|
||||
t.Error("test failed - GetTrade() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPreviousTrades(t *testing.T) {
|
||||
_, err := b.GetPreviousTrades(TradeGetBucketedParams{})
|
||||
if err == nil {
|
||||
t.Error("test failed - GetPreviousTrades() error", err)
|
||||
}
|
||||
}
|
||||
668
exchanges/bitmex/bitmex_types.go
Normal file
668
exchanges/bitmex/bitmex_types.go
Normal file
@@ -0,0 +1,668 @@
|
||||
package bitmex
|
||||
|
||||
// RequestError allows for a general error capture from requests
|
||||
type RequestError struct {
|
||||
Error struct {
|
||||
Message string `json:"message"`
|
||||
Name string `json:"name"`
|
||||
} `json:"error"`
|
||||
}
|
||||
|
||||
// Announcement General Announcements
|
||||
type Announcement struct {
|
||||
Content string `json:"content"`
|
||||
Date string `json:"date"`
|
||||
ID int32 `json:"id"`
|
||||
Link string `json:"link"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
// APIKey Persistent API Keys for Developers
|
||||
type APIKey struct {
|
||||
Cidr string `json:"cidr"`
|
||||
Created string `json:"created"`
|
||||
Enabled bool `json:"enabled"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Nonce int64 `json:"nonce"`
|
||||
Permissions []interface{} `json:"permissions"`
|
||||
Secret string `json:"secret"`
|
||||
UserID int32 `json:"userId"`
|
||||
}
|
||||
|
||||
// Chat Trollbox Data
|
||||
type Chat struct {
|
||||
ChannelID float64 `json:"channelID"`
|
||||
Date string `json:"date"`
|
||||
FromBot bool `json:"fromBot"`
|
||||
HTML string `json:"html"`
|
||||
ID int32 `json:"id"`
|
||||
Message string `json:"message"`
|
||||
User string `json:"user"`
|
||||
}
|
||||
|
||||
// ChatChannel chat channel
|
||||
type ChatChannel struct {
|
||||
ID int32 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// ConnectedUsers connected users
|
||||
type ConnectedUsers struct {
|
||||
Bots int32 `json:"bots"`
|
||||
Users int32 `json:"users"`
|
||||
}
|
||||
|
||||
// Execution Raw Order and Balance Data
|
||||
type Execution struct {
|
||||
Account int64 `json:"account"`
|
||||
AvgPx float64 `json:"avgPx"`
|
||||
ClOrdID string `json:"clOrdID"`
|
||||
ClOrdLinkID string `json:"clOrdLinkID"`
|
||||
Commission float64 `json:"commission"`
|
||||
ContingencyType string `json:"contingencyType"`
|
||||
CumQty int64 `json:"cumQty"`
|
||||
Currency string `json:"currency"`
|
||||
DisplayQty int64 `json:"displayQty"`
|
||||
ExDestination string `json:"exDestination"`
|
||||
ExecComm int64 `json:"execComm"`
|
||||
ExecCost int64 `json:"execCost"`
|
||||
ExecID string `json:"execID"`
|
||||
ExecInst string `json:"execInst"`
|
||||
ExecType string `json:"execType"`
|
||||
ForeignNotional float64 `json:"foreignNotional"`
|
||||
HomeNotional float64 `json:"homeNotional"`
|
||||
LastLiquidityInd string `json:"lastLiquidityInd"`
|
||||
LastMkt string `json:"lastMkt"`
|
||||
LastPx float64 `json:"lastPx"`
|
||||
LastQty int64 `json:"lastQty"`
|
||||
LeavesQty int64 `json:"leavesQty"`
|
||||
MultiLegReportingType string `json:"multiLegReportingType"`
|
||||
OrdRejReason string `json:"ordRejReason"`
|
||||
OrdStatus string `json:"ordStatus"`
|
||||
OrdType string `json:"ordType"`
|
||||
OrderID string `json:"orderID"`
|
||||
OrderQty int64 `json:"orderQty"`
|
||||
PegOffsetValue float64 `json:"pegOffsetValue"`
|
||||
PegPriceType string `json:"pegPriceType"`
|
||||
Price float64 `json:"price"`
|
||||
SettlCurrency string `json:"settlCurrency"`
|
||||
Side string `json:"side"`
|
||||
SimpleCumQty float64 `json:"simpleCumQty"`
|
||||
SimpleLeavesQty float64 `json:"simpleLeavesQty"`
|
||||
SimpleOrderQty float64 `json:"simpleOrderQty"`
|
||||
StopPx float64 `json:"stopPx"`
|
||||
Symbol string `json:"symbol"`
|
||||
Text string `json:"text"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TradePublishIndicator string `json:"tradePublishIndicator"`
|
||||
TransactTime string `json:"transactTime"`
|
||||
TrdMatchID string `json:"trdMatchID"`
|
||||
Triggered string `json:"triggered"`
|
||||
UnderlyingLastPx float64 `json:"underlyingLastPx"`
|
||||
WorkingIndicator bool `json:"workingIndicator"`
|
||||
}
|
||||
|
||||
// Funding Swap Funding History
|
||||
type Funding struct {
|
||||
FundingInterval string `json:"fundingInterval"`
|
||||
FundingRate float64 `json:"fundingRate"`
|
||||
FundingRateDaily float64 `json:"fundingRateDaily"`
|
||||
Symbol string `json:"symbol"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
}
|
||||
|
||||
// Instrument Tradeable Contracts, Indices, and History
|
||||
type Instrument struct {
|
||||
AskPrice float64 `json:"askPrice"`
|
||||
BankruptLimitDownPrice float64 `json:"bankruptLimitDownPrice"`
|
||||
BankruptLimitUpPrice float64 `json:"bankruptLimitUpPrice"`
|
||||
BidPrice float64 `json:"bidPrice"`
|
||||
BuyLeg string `json:"buyLeg"`
|
||||
CalcInterval string `json:"calcInterval"`
|
||||
Capped bool `json:"capped"`
|
||||
ClosingTimestamp string `json:"closingTimestamp"`
|
||||
Deleverage bool `json:"deleverage"`
|
||||
Expiry string `json:"expiry"`
|
||||
FairBasis float64 `json:"fairBasis"`
|
||||
FairBasisRate float64 `json:"fairBasisRate"`
|
||||
FairMethod string `json:"fairMethod"`
|
||||
FairPrice float64 `json:"fairPrice"`
|
||||
Front string `json:"front"`
|
||||
FundingBaseSymbol string `json:"fundingBaseSymbol"`
|
||||
FundingInterval string `json:"fundingInterval"`
|
||||
FundingPremiumSymbol string `json:"fundingPremiumSymbol"`
|
||||
FundingQuoteSymbol string `json:"fundingQuoteSymbol"`
|
||||
FundingRate float64 `json:"fundingRate"`
|
||||
FundingTimestamp string `json:"fundingTimestamp"`
|
||||
HasLiquidity bool `json:"hasLiquidity"`
|
||||
HighPrice float64 `json:"highPrice"`
|
||||
ImpactAskPrice float64 `json:"impactAskPrice"`
|
||||
ImpactBidPrice float64 `json:"impactBidPrice"`
|
||||
ImpactMidPrice float64 `json:"impactMidPrice"`
|
||||
IndicativeFundingRate float64 `json:"indicativeFundingRate"`
|
||||
IndicativeSettlePrice float64 `json:"indicativeSettlePrice"`
|
||||
IndicativeTaxRate float64 `json:"indicativeTaxRate"`
|
||||
InitMargin float64 `json:"initMargin"`
|
||||
InsuranceFee float64 `json:"insuranceFee"`
|
||||
InverseLeg string `json:"inverseLeg"`
|
||||
IsInverse bool `json:"isInverse"`
|
||||
IsQuanto bool `json:"isQuanto"`
|
||||
LastChangePcnt float64 `json:"lastChangePcnt"`
|
||||
LastPrice float64 `json:"lastPrice"`
|
||||
LastPriceProtected float64 `json:"lastPriceProtected"`
|
||||
LastTickDirection string `json:"lastTickDirection"`
|
||||
Limit float64 `json:"limit"`
|
||||
LimitDownPrice float64 `json:"limitDownPrice"`
|
||||
LimitUpPrice float64 `json:"limitUpPrice"`
|
||||
Listing string `json:"listing"`
|
||||
LotSize int64 `json:"lotSize"`
|
||||
LowPrice float64 `json:"lowPrice"`
|
||||
MaintMargin float64 `json:"maintMargin"`
|
||||
MakerFee float64 `json:"makerFee"`
|
||||
MarkMethod string `json:"markMethod"`
|
||||
MarkPrice float64 `json:"markPrice"`
|
||||
MaxOrderQty int64 `json:"maxOrderQty"`
|
||||
MaxPrice float64 `json:"maxPrice"`
|
||||
MidPrice float64 `json:"midPrice"`
|
||||
Multiplier int64 `json:"multiplier"`
|
||||
OpenInterest int64 `json:"openInterest"`
|
||||
OpenValue int64 `json:"openValue"`
|
||||
OpeningTimestamp string `json:"openingTimestamp"`
|
||||
OptionMultiplier float64 `json:"optionMultiplier"`
|
||||
OptionStrikePcnt float64 `json:"optionStrikePcnt"`
|
||||
OptionStrikePrice float64 `json:"optionStrikePrice"`
|
||||
OptionStrikeRound float64 `json:"optionStrikeRound"`
|
||||
OptionUnderlyingPrice float64 `json:"optionUnderlyingPrice"`
|
||||
PositionCurrency string `json:"positionCurrency"`
|
||||
PrevClosePrice float64 `json:"prevClosePrice"`
|
||||
PrevPrice24h float64 `json:"prevPrice24h"`
|
||||
PrevTotalTurnover int64 `json:"prevTotalTurnover"`
|
||||
PrevTotalVolume int64 `json:"prevTotalVolume"`
|
||||
PublishInterval string `json:"publishInterval"`
|
||||
PublishTime string `json:"publishTime"`
|
||||
QuoteCurrency string `json:"quoteCurrency"`
|
||||
QuoteToSettleMultiplier int64 `json:"quoteToSettleMultiplier"`
|
||||
RebalanceInterval string `json:"rebalanceInterval"`
|
||||
RebalanceTimestamp string `json:"rebalanceTimestamp"`
|
||||
Reference string `json:"reference"`
|
||||
ReferenceSymbol string `json:"referenceSymbol"`
|
||||
RelistInterval string `json:"relistInterval"`
|
||||
RiskLimit int64 `json:"riskLimit"`
|
||||
RiskStep int64 `json:"riskStep"`
|
||||
RootSymbol string `json:"rootSymbol"`
|
||||
SellLeg string `json:"sellLeg"`
|
||||
SessionInterval string `json:"sessionInterval"`
|
||||
SettlCurrency string `json:"settlCurrency"`
|
||||
Settle string `json:"settle"`
|
||||
SettledPrice float64 `json:"settledPrice"`
|
||||
SettlementFee float64 `json:"settlementFee"`
|
||||
State string `json:"state"`
|
||||
Symbol string `json:"symbol"`
|
||||
TakerFee float64 `json:"takerFee"`
|
||||
Taxed bool `json:"taxed"`
|
||||
TickSize float64 `json:"tickSize"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TotalTurnover int64 `json:"totalTurnover"`
|
||||
TotalVolume int64 `json:"totalVolume"`
|
||||
Turnover int64 `json:"turnover"`
|
||||
Turnover24h int64 `json:"turnover24h"`
|
||||
Typ string `json:"typ"`
|
||||
Underlying string `json:"underlying"`
|
||||
UnderlyingSymbol string `json:"underlyingSymbol"`
|
||||
UnderlyingToPositionMultiplier int64 `json:"underlyingToPositionMultiplier"`
|
||||
UnderlyingToSettleMultiplier int64 `json:"underlyingToSettleMultiplier"`
|
||||
Volume int64 `json:"volume"`
|
||||
Volume24h int64 `json:"volume24h"`
|
||||
Vwap float64 `json:"vwap"`
|
||||
}
|
||||
|
||||
// InstrumentInterval instrument interval
|
||||
type InstrumentInterval struct {
|
||||
Intervals []string `json:"intervals"`
|
||||
Symbols []string `json:"symbols"`
|
||||
}
|
||||
|
||||
// IndexComposite index composite
|
||||
type IndexComposite struct {
|
||||
IndexSymbol string `json:"indexSymbol"`
|
||||
LastPrice float64 `json:"lastPrice"`
|
||||
Logged string `json:"logged"`
|
||||
Reference string `json:"reference"`
|
||||
Symbol string `json:"symbol"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Weight float64 `json:"weight"`
|
||||
}
|
||||
|
||||
// Insurance Insurance Fund Data
|
||||
type Insurance struct {
|
||||
Currency string `json:"currency"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
WalletBalance int64 `json:"walletBalance"`
|
||||
}
|
||||
|
||||
// Leaderboard Information on Top Users
|
||||
type Leaderboard struct {
|
||||
IsRealName bool `json:"isRealName"`
|
||||
Name string `json:"name"`
|
||||
Profit float64 `json:"profit"`
|
||||
}
|
||||
|
||||
// Alias Name refers to Trollbox client name
|
||||
type Alias struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// Liquidation Active Liquidations
|
||||
type Liquidation struct {
|
||||
LeavesQty int64 `json:"leavesQty"`
|
||||
OrderID string `json:"orderID"`
|
||||
Price float64 `json:"price"`
|
||||
Side string `json:"side"`
|
||||
Symbol string `json:"symbol"`
|
||||
}
|
||||
|
||||
// Notification Account Notifications
|
||||
type Notification struct {
|
||||
Body string `json:"body"`
|
||||
Closable bool `json:"closable"`
|
||||
Date string `json:"date"`
|
||||
ID int32 `json:"id"`
|
||||
Persist bool `json:"persist"`
|
||||
Sound string `json:"sound"`
|
||||
Title string `json:"title"`
|
||||
TTL int32 `json:"ttl"`
|
||||
Type string `json:"type"`
|
||||
WaitForVisibility bool `json:"waitForVisibility"`
|
||||
}
|
||||
|
||||
// Order Placement, Cancellation, Amending, and History
|
||||
type Order struct {
|
||||
Account int64 `json:"account"`
|
||||
AvgPx float64 `json:"avgPx"`
|
||||
ClOrdID string `json:"clOrdID"`
|
||||
ClOrdLinkID string `json:"clOrdLinkID"`
|
||||
ContingencyType string `json:"contingencyType"`
|
||||
CumQty int64 `json:"cumQty"`
|
||||
Currency string `json:"currency"`
|
||||
DisplayQty int64 `json:"displayQty"`
|
||||
ExDestination string `json:"exDestination"`
|
||||
ExecInst string `json:"execInst"`
|
||||
LeavesQty int64 `json:"leavesQty"`
|
||||
MultiLegReportingType string `json:"multiLegReportingType"`
|
||||
OrdRejReason string `json:"ordRejReason"`
|
||||
OrdStatus string `json:"ordStatus"`
|
||||
OrdType string `json:"ordType"`
|
||||
OrderID string `json:"orderID"`
|
||||
OrderQty int64 `json:"orderQty"`
|
||||
PegOffsetValue float64 `json:"pegOffsetValue"`
|
||||
PegPriceType string `json:"pegPriceType"`
|
||||
Price float64 `json:"price"`
|
||||
SettlCurrency string `json:"settlCurrency"`
|
||||
Side string `json:"side"`
|
||||
SimpleCumQty float64 `json:"simpleCumQty"`
|
||||
SimpleLeavesQty float64 `json:"simpleLeavesQty"`
|
||||
SimpleOrderQty float64 `json:"simpleOrderQty"`
|
||||
StopPx float64 `json:"stopPx"`
|
||||
Symbol string `json:"symbol"`
|
||||
Text string `json:"text"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TransactTime string `json:"transactTime"`
|
||||
Triggered string `json:"triggered"`
|
||||
WorkingIndicator bool `json:"workingIndicator"`
|
||||
}
|
||||
|
||||
// OrderBookL2 contains order book l2
|
||||
type OrderBookL2 struct {
|
||||
ID int64 `json:"id"`
|
||||
Price float64 `json:"price"`
|
||||
Side string `json:"side"`
|
||||
Size int64 `json:"size"`
|
||||
Symbol string `json:"symbol"`
|
||||
}
|
||||
|
||||
// Position Summary of Open and Closed Positions
|
||||
type Position struct {
|
||||
Account int64 `json:"account"`
|
||||
AvgCostPrice float64 `json:"avgCostPrice"`
|
||||
AvgEntryPrice float64 `json:"avgEntryPrice"`
|
||||
BankruptPrice float64 `json:"bankruptPrice"`
|
||||
BreakEvenPrice float64 `json:"breakEvenPrice"`
|
||||
Commission float64 `json:"commission"`
|
||||
CrossMargin bool `json:"crossMargin"`
|
||||
Currency string `json:"currency"`
|
||||
CurrentComm int64 `json:"currentComm"`
|
||||
CurrentCost int64 `json:"currentCost"`
|
||||
CurrentQty int64 `json:"currentQty"`
|
||||
CurrentTimestamp string `json:"currentTimestamp"`
|
||||
DeleveragePercentile float64 `json:"deleveragePercentile"`
|
||||
ExecBuyCost int64 `json:"execBuyCost"`
|
||||
ExecBuyQty int64 `json:"execBuyQty"`
|
||||
ExecComm int64 `json:"execComm"`
|
||||
ExecCost int64 `json:"execCost"`
|
||||
ExecQty int64 `json:"execQty"`
|
||||
ExecSellCost int64 `json:"execSellCost"`
|
||||
ExecSellQty int64 `json:"execSellQty"`
|
||||
ForeignNotional float64 `json:"foreignNotional"`
|
||||
GrossExecCost int64 `json:"grossExecCost"`
|
||||
GrossOpenCost int64 `json:"grossOpenCost"`
|
||||
GrossOpenPremium int64 `json:"grossOpenPremium"`
|
||||
HomeNotional float64 `json:"homeNotional"`
|
||||
IndicativeTax int64 `json:"indicativeTax"`
|
||||
IndicativeTaxRate float64 `json:"indicativeTaxRate"`
|
||||
InitMargin int64 `json:"initMargin"`
|
||||
InitMarginReq float64 `json:"initMarginReq"`
|
||||
IsOpen bool `json:"isOpen"`
|
||||
LastPrice float64 `json:"lastPrice"`
|
||||
LastValue int64 `json:"lastValue"`
|
||||
Leverage float64 `json:"leverage"`
|
||||
LiquidationPrice float64 `json:"liquidationPrice"`
|
||||
LongBankrupt int64 `json:"longBankrupt"`
|
||||
MaintMargin int64 `json:"maintMargin"`
|
||||
MaintMarginReq float64 `json:"maintMarginReq"`
|
||||
MarginCallPrice float64 `json:"marginCallPrice"`
|
||||
MarkPrice float64 `json:"markPrice"`
|
||||
MarkValue int64 `json:"markValue"`
|
||||
OpenOrderBuyCost int64 `json:"openOrderBuyCost"`
|
||||
OpenOrderBuyPremium int64 `json:"openOrderBuyPremium"`
|
||||
OpenOrderBuyQty int64 `json:"openOrderBuyQty"`
|
||||
OpenOrderSellCost int64 `json:"openOrderSellCost"`
|
||||
OpenOrderSellPremium int64 `json:"openOrderSellPremium"`
|
||||
OpenOrderSellQty int64 `json:"openOrderSellQty"`
|
||||
OpeningComm int64 `json:"openingComm"`
|
||||
OpeningCost int64 `json:"openingCost"`
|
||||
OpeningQty int64 `json:"openingQty"`
|
||||
OpeningTimestamp string `json:"openingTimestamp"`
|
||||
PosAllowance int64 `json:"posAllowance"`
|
||||
PosComm int64 `json:"posComm"`
|
||||
PosCost int64 `json:"posCost"`
|
||||
PosCost2 int64 `json:"posCost2"`
|
||||
PosCross int64 `json:"posCross"`
|
||||
PosInit int64 `json:"posInit"`
|
||||
PosLoss int64 `json:"posLoss"`
|
||||
PosMaint int64 `json:"posMaint"`
|
||||
PosMargin int64 `json:"posMargin"`
|
||||
PosState string `json:"posState"`
|
||||
PrevClosePrice float64 `json:"prevClosePrice"`
|
||||
PrevRealisedPnl int64 `json:"prevRealisedPnl"`
|
||||
PrevUnrealisedPnl int64 `json:"prevUnrealisedPnl"`
|
||||
QuoteCurrency string `json:"quoteCurrency"`
|
||||
RealisedCost int64 `json:"realisedCost"`
|
||||
RealisedGrossPnl int64 `json:"realisedGrossPnl"`
|
||||
RealisedPnl int64 `json:"realisedPnl"`
|
||||
RealisedTax int64 `json:"realisedTax"`
|
||||
RebalancedPnl int64 `json:"rebalancedPnl"`
|
||||
RiskLimit int64 `json:"riskLimit"`
|
||||
RiskValue int64 `json:"riskValue"`
|
||||
SessionMargin int64 `json:"sessionMargin"`
|
||||
ShortBankrupt int64 `json:"shortBankrupt"`
|
||||
SimpleCost float64 `json:"simpleCost"`
|
||||
SimplePnl float64 `json:"simplePnl"`
|
||||
SimplePnlPcnt float64 `json:"simplePnlPcnt"`
|
||||
SimpleQty float64 `json:"simpleQty"`
|
||||
SimpleValue float64 `json:"simpleValue"`
|
||||
Symbol string `json:"symbol"`
|
||||
TargetExcessMargin int64 `json:"targetExcessMargin"`
|
||||
TaxBase int64 `json:"taxBase"`
|
||||
TaxableMargin int64 `json:"taxableMargin"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Underlying string `json:"underlying"`
|
||||
UnrealisedCost int64 `json:"unrealisedCost"`
|
||||
UnrealisedGrossPnl int64 `json:"unrealisedGrossPnl"`
|
||||
UnrealisedPnl int64 `json:"unrealisedPnl"`
|
||||
UnrealisedPnlPcnt float64 `json:"unrealisedPnlPcnt"`
|
||||
UnrealisedRoePcnt float64 `json:"unrealisedRoePcnt"`
|
||||
UnrealisedTax int64 `json:"unrealisedTax"`
|
||||
VarMargin int64 `json:"varMargin"`
|
||||
}
|
||||
|
||||
// Quote Best Bid/Offer Snapshots & Historical Bins
|
||||
type Quote struct {
|
||||
AskPrice float64 `json:"askPrice"`
|
||||
AskSize int64 `json:"askSize"`
|
||||
BidPrice float64 `json:"bidPrice"`
|
||||
BidSize int64 `json:"bidSize"`
|
||||
Symbol string `json:"symbol"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
}
|
||||
|
||||
// Settlement Historical Settlement Data
|
||||
type Settlement struct {
|
||||
Bankrupt int64 `json:"bankrupt"`
|
||||
OptionStrikePrice float64 `json:"optionStrikePrice"`
|
||||
OptionUnderlyingPrice float64 `json:"optionUnderlyingPrice"`
|
||||
SettledPrice float64 `json:"settledPrice"`
|
||||
SettlementType string `json:"settlementType"`
|
||||
Symbol string `json:"symbol"`
|
||||
TaxBase int64 `json:"taxBase"`
|
||||
TaxRate float64 `json:"taxRate"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
}
|
||||
|
||||
// Stats Exchange Statistics
|
||||
type Stats struct {
|
||||
Currency string `json:"currency"`
|
||||
OpenInterest int64 `json:"openInterest"`
|
||||
OpenValue int64 `json:"openValue"`
|
||||
RootSymbol string `json:"rootSymbol"`
|
||||
Turnover24h int64 `json:"turnover24h"`
|
||||
Volume24h int64 `json:"volume24h"`
|
||||
}
|
||||
|
||||
// StatsHistory stats history
|
||||
type StatsHistory struct {
|
||||
Currency string `json:"currency"`
|
||||
Date string `json:"date"`
|
||||
RootSymbol string `json:"rootSymbol"`
|
||||
Turnover int64 `json:"turnover"`
|
||||
Volume int64 `json:"volume"`
|
||||
}
|
||||
|
||||
// StatsUSD contains summary of exchange stats
|
||||
type StatsUSD struct {
|
||||
Currency string `json:"currency"`
|
||||
RootSymbol string `json:"rootSymbol"`
|
||||
Turnover int64 `json:"turnover"`
|
||||
Turnover24h int64 `json:"turnover24h"`
|
||||
Turnover30d int64 `json:"turnover30d"`
|
||||
Turnover365d int64 `json:"turnover365d"`
|
||||
}
|
||||
|
||||
// Trade Individual & Bucketed Trades
|
||||
type Trade struct {
|
||||
ForeignNotional float64 `json:"foreignNotional"`
|
||||
GrossValue int64 `json:"grossValue"`
|
||||
HomeNotional float64 `json:"homeNotional"`
|
||||
Price float64 `json:"price"`
|
||||
Side string `json:"side"`
|
||||
Size int64 `json:"size"`
|
||||
Symbol string `json:"symbol"`
|
||||
TickDirection string `json:"tickDirection"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TrdMatchID string `json:"trdMatchID"`
|
||||
}
|
||||
|
||||
// User Account Operations
|
||||
type User struct {
|
||||
TFAEnabled string `json:"TFAEnabled"`
|
||||
AffiliateID string `json:"affiliateID"`
|
||||
Country string `json:"country"`
|
||||
Created string `json:"created"`
|
||||
Email string `json:"email"`
|
||||
Firstname string `json:"firstname"`
|
||||
GeoipCountry string `json:"geoipCountry"`
|
||||
GeoipRegion string `json:"geoipRegion"`
|
||||
ID int32 `json:"id"`
|
||||
LastUpdated string `json:"lastUpdated"`
|
||||
Lastname string `json:"lastname"`
|
||||
OwnerID int32 `json:"ownerId"`
|
||||
PgpPubKey string `json:"pgpPubKey"`
|
||||
Phone string `json:"phone"`
|
||||
Preferences UserPreferences `json:"preferences"`
|
||||
Typ string `json:"typ"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// UserPreferences user preferences
|
||||
type UserPreferences struct {
|
||||
AlertOnLiquidations bool `json:"alertOnLiquidations"`
|
||||
AnimationsEnabled bool `json:"animationsEnabled"`
|
||||
AnnouncementsLastSeen string `json:"announcementsLastSeen"`
|
||||
ChatChannelID float64 `json:"chatChannelID"`
|
||||
ColorTheme string `json:"colorTheme"`
|
||||
Currency string `json:"currency"`
|
||||
Debug bool `json:"debug"`
|
||||
DisableEmails []string `json:"disableEmails"`
|
||||
HideConfirmDialogs []string `json:"hideConfirmDialogs"`
|
||||
HideConnectionModal bool `json:"hideConnectionModal"`
|
||||
HideFromLeaderboard bool `json:"hideFromLeaderboard"`
|
||||
HideNameFromLeaderboard bool `json:"hideNameFromLeaderboard"`
|
||||
HideNotifications []string `json:"hideNotifications"`
|
||||
Locale string `json:"locale"`
|
||||
MsgsSeen []string `json:"msgsSeen"`
|
||||
OrderBookBinning interface{} `json:"orderBookBinning"`
|
||||
OrderBookType string `json:"orderBookType"`
|
||||
OrderClearImmediate bool `json:"orderClearImmediate"`
|
||||
OrderControlsPlusMinus bool `json:"orderControlsPlusMinus"`
|
||||
ShowLocaleNumbers bool `json:"showLocaleNumbers"`
|
||||
Sounds []string `json:"sounds"`
|
||||
StrictIPCheck bool `json:"strictIPCheck"`
|
||||
StrictTimeout bool `json:"strictTimeout"`
|
||||
TickerGroup string `json:"tickerGroup"`
|
||||
TickerPinned bool `json:"tickerPinned"`
|
||||
TradeLayout string `json:"tradeLayout"`
|
||||
}
|
||||
|
||||
// AffiliateStatus affiliate Status details
|
||||
type AffiliateStatus struct {
|
||||
Account int64 `json:"account"`
|
||||
Currency string `json:"currency"`
|
||||
ExecComm int64 `json:"execComm"`
|
||||
ExecTurnover int64 `json:"execTurnover"`
|
||||
PayoutPcnt float64 `json:"payoutPcnt"`
|
||||
PendingPayout int64 `json:"pendingPayout"`
|
||||
PrevComm int64 `json:"prevComm"`
|
||||
PrevPayout int64 `json:"prevPayout"`
|
||||
PrevTimestamp string `json:"prevTimestamp"`
|
||||
PrevTurnover int64 `json:"prevTurnover"`
|
||||
ReferrerAccount float64 `json:"referrerAccount"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TotalComm int64 `json:"totalComm"`
|
||||
TotalReferrals int64 `json:"totalReferrals"`
|
||||
TotalTurnover int64 `json:"totalTurnover"`
|
||||
}
|
||||
|
||||
// TransactionInfo Information
|
||||
type TransactionInfo struct {
|
||||
Account int64 `json:"account"`
|
||||
Address string `json:"address"`
|
||||
Amount int64 `json:"amount"`
|
||||
Currency string `json:"currency"`
|
||||
Fee int64 `json:"fee"`
|
||||
Text string `json:"text"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TransactID string `json:"transactID"`
|
||||
TransactStatus string `json:"transactStatus"`
|
||||
TransactTime string `json:"transactTime"`
|
||||
TransactType string `json:"transactType"`
|
||||
Tx string `json:"tx"`
|
||||
}
|
||||
|
||||
// UserCommission user commission
|
||||
type UserCommission struct {
|
||||
MakerFee float64 `json:"makerFee"`
|
||||
MaxFee float64 `json:"maxFee"`
|
||||
SettlementFee float64 `json:"settlementFee"`
|
||||
TakerFee float64 `json:"takerFee"`
|
||||
}
|
||||
|
||||
// ConfirmEmail confirmatin email endpoint data
|
||||
type ConfirmEmail struct {
|
||||
ID string `json:"id"`
|
||||
TTL int64 `json:"ttl"`
|
||||
Created string `json:"created"`
|
||||
UserID int64 `json:"userId"`
|
||||
}
|
||||
|
||||
// UserMargin margin information
|
||||
type UserMargin struct {
|
||||
Account int64 `json:"account"`
|
||||
Action string `json:"action"`
|
||||
Amount int64 `json:"amount"`
|
||||
AvailableMargin int64 `json:"availableMargin"`
|
||||
Commission float64 `json:"commission"`
|
||||
ConfirmedDebit int64 `json:"confirmedDebit"`
|
||||
Currency string `json:"currency"`
|
||||
ExcessMargin int64 `json:"excessMargin"`
|
||||
ExcessMarginPcnt float64 `json:"excessMarginPcnt"`
|
||||
GrossComm int64 `json:"grossComm"`
|
||||
GrossExecCost int64 `json:"grossExecCost"`
|
||||
GrossLastValue int64 `json:"grossLastValue"`
|
||||
GrossMarkValue int64 `json:"grossMarkValue"`
|
||||
GrossOpenCost int64 `json:"grossOpenCost"`
|
||||
GrossOpenPremium int64 `json:"grossOpenPremium"`
|
||||
IndicativeTax int64 `json:"indicativeTax"`
|
||||
InitMargin int64 `json:"initMargin"`
|
||||
MaintMargin int64 `json:"maintMargin"`
|
||||
MarginBalance int64 `json:"marginBalance"`
|
||||
MarginBalancePcnt float64 `json:"marginBalancePcnt"`
|
||||
MarginLeverage float64 `json:"marginLeverage"`
|
||||
MarginUsedPcnt float64 `json:"marginUsedPcnt"`
|
||||
PendingCredit int64 `json:"pendingCredit"`
|
||||
PendingDebit int64 `json:"pendingDebit"`
|
||||
PrevRealisedPnl int64 `json:"prevRealisedPnl"`
|
||||
PrevState string `json:"prevState"`
|
||||
PrevUnrealisedPnl int64 `json:"prevUnrealisedPnl"`
|
||||
RealisedPnl int64 `json:"realisedPnl"`
|
||||
RiskLimit int64 `json:"riskLimit"`
|
||||
RiskValue int64 `json:"riskValue"`
|
||||
SessionMargin int64 `json:"sessionMargin"`
|
||||
State string `json:"state"`
|
||||
SyntheticMargin int64 `json:"syntheticMargin"`
|
||||
TargetExcessMargin int64 `json:"targetExcessMargin"`
|
||||
TaxableMargin int64 `json:"taxableMargin"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
UnrealisedPnl int64 `json:"unrealisedPnl"`
|
||||
UnrealisedProfit int64 `json:"unrealisedProfit"`
|
||||
VarMargin int64 `json:"varMargin"`
|
||||
WalletBalance int64 `json:"walletBalance"`
|
||||
WithdrawableMargin int64 `json:"withdrawableMargin"`
|
||||
}
|
||||
|
||||
// MinWithdrawalFee minimum withdrawal fee information
|
||||
type MinWithdrawalFee struct {
|
||||
Currency string `json:"currency"`
|
||||
Fee int64 `json:"fee"`
|
||||
MinFee int64 `json:"minFee"`
|
||||
}
|
||||
|
||||
// WalletInfo wallet information
|
||||
type WalletInfo struct {
|
||||
Account int64 `json:"account"`
|
||||
Addr string `json:"addr"`
|
||||
Amount int64 `json:"amount"`
|
||||
ConfirmedDebit int64 `json:"confirmedDebit"`
|
||||
Currency string `json:"currency"`
|
||||
DeltaAmount int64 `json:"deltaAmount"`
|
||||
DeltaDeposited int64 `json:"deltaDeposited"`
|
||||
DeltaTransferIn int64 `json:"deltaTransferIn"`
|
||||
DeltaTransferOut int64 `json:"deltaTransferOut"`
|
||||
DeltaWithdrawn int64 `json:"deltaWithdrawn"`
|
||||
Deposited int64 `json:"deposited"`
|
||||
PendingCredit int64 `json:"pendingCredit"`
|
||||
PendingDebit int64 `json:"pendingDebit"`
|
||||
PrevAmount int64 `json:"prevAmount"`
|
||||
PrevDeposited int64 `json:"prevDeposited"`
|
||||
PrevTimestamp string `json:"prevTimestamp"`
|
||||
PrevTransferIn int64 `json:"prevTransferIn"`
|
||||
PrevTransferOut int64 `json:"prevTransferOut"`
|
||||
PrevWithdrawn int64 `json:"prevWithdrawn"`
|
||||
Script string `json:"script"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TransferIn int64 `json:"transferIn"`
|
||||
TransferOut int64 `json:"transferOut"`
|
||||
WithdrawalLock []string `json:"withdrawalLock"`
|
||||
Withdrawn int64 `json:"withdrawn"`
|
||||
}
|
||||
494
exchanges/bitmex/bitmex_websocket.go
Normal file
494
exchanges/bitmex/bitmex_websocket.go
Normal file
@@ -0,0 +1,494 @@
|
||||
package bitmex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
)
|
||||
|
||||
const (
|
||||
bitmexWSURL = "wss://www.bitmex.com/realtime"
|
||||
|
||||
// Public Subscription Channels
|
||||
bitmexWSAnnouncement = "announcement"
|
||||
bitmexWSChat = "chat"
|
||||
bitmexWSConnected = "connected"
|
||||
bitmexWSFunding = "funding"
|
||||
bitmexWSInstrument = "instrument"
|
||||
bitmexWSInsurance = "insurance"
|
||||
bitmexWSLiquidation = "liquidation"
|
||||
bitmexWSOrderbookL2 = "orderBookL2"
|
||||
bitmexWSOrderbookL10 = "orderBook10"
|
||||
bitmexWSPublicNotifications = "publicNotifications"
|
||||
bitmexWSQuote = "quote"
|
||||
bitmexWSQuote1m = "quoteBin1m"
|
||||
bitmexWSQuote5m = "quoteBin5m"
|
||||
bitmexWSQuote1h = "quoteBin1h"
|
||||
bitmexWSQuote1d = "quoteBin1d"
|
||||
bitmexWSSettlement = "settlement"
|
||||
bitmexWSTrade = "trade"
|
||||
bitmexWSTrade1m = "tradeBin1m"
|
||||
bitmexWSTrade5m = "tradeBin5m"
|
||||
bitmexWSTrade1h = "tradeBin1h"
|
||||
bitmexWSTrade1d = "tradeBin1d"
|
||||
|
||||
// Authenticated Subscription Channels
|
||||
bitmexWSAffiliate = "affiliate"
|
||||
bitmexWSExecution = "execution"
|
||||
bitmexWSOrder = "order"
|
||||
bitmexWSMargin = "margin"
|
||||
bitmexWSPosition = "position"
|
||||
bitmexWSPrivateNotifications = "privateNotifications"
|
||||
bitmexWSTransact = "transact"
|
||||
bitmexWSWallet = "wallet"
|
||||
|
||||
bitmexActionInitialData = "partial"
|
||||
bitmexActionInsertData = "insert"
|
||||
bitmexActionDeleteData = "delete"
|
||||
bitmexActionUpdateData = "update"
|
||||
)
|
||||
|
||||
var (
|
||||
pongChan = make(chan int, 1)
|
||||
timer *time.Timer
|
||||
)
|
||||
|
||||
// WebsocketConnect initiates a new websocket connection
|
||||
func (b *Bitmex) WebsocketConnect() error {
|
||||
var dialer websocket.Dialer
|
||||
var err error
|
||||
|
||||
b.WebsocketConn, _, err = dialer.Dial(bitmexWSURL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, p, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var welcomeResp WebsocketWelcome
|
||||
err = common.JSONDecode(p, &welcomeResp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go b.connectionHandler()
|
||||
|
||||
if b.Verbose {
|
||||
log.Printf("Successfully connected to Bitmex %s at time: %s Limit: %d",
|
||||
welcomeResp.Info,
|
||||
welcomeResp.Timestamp,
|
||||
welcomeResp.Limit.Remaining)
|
||||
}
|
||||
|
||||
go b.handleIncomingData()
|
||||
|
||||
err = b.websocketSubscribe()
|
||||
if err != nil {
|
||||
b.WebsocketConn.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
if b.AuthenticatedAPISupport {
|
||||
err := b.websocketSendAuth()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timer handles connection loss or failure
|
||||
func (b *Bitmex) connectionHandler() {
|
||||
defer func() {
|
||||
if b.Verbose {
|
||||
log.Println("Bitmex websocket: Connection handler routine shutdown")
|
||||
}
|
||||
}()
|
||||
|
||||
shutdown := b.shutdown.addRoutine()
|
||||
|
||||
timer = time.NewTimer(5 * time.Second)
|
||||
for {
|
||||
select {
|
||||
case <-timer.C:
|
||||
timeout := time.After(5 * time.Second)
|
||||
err := b.WebsocketConn.WriteJSON("ping")
|
||||
if err != nil {
|
||||
b.reconnect()
|
||||
return
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case <-pongChan:
|
||||
if b.Verbose {
|
||||
log.Println("Bitmex websocket: PONG received")
|
||||
}
|
||||
break
|
||||
case <-timeout:
|
||||
log.Println("Bitmex websocket: Connection timed out - Closing connection....")
|
||||
b.WebsocketConn.Close()
|
||||
|
||||
log.Println("Bitmex websocket: Connection timed out - Reconnecting...")
|
||||
b.reconnect()
|
||||
return
|
||||
}
|
||||
}
|
||||
case <-shutdown:
|
||||
log.Println("Bitmex websocket: shutdown requested - Closing connection....")
|
||||
b.WebsocketConn.Close()
|
||||
log.Println("Bitmex websocket: Sending shutdown message")
|
||||
b.shutdown.routineShutdown()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reconnect handles reconnections to websocket API
|
||||
func (b *Bitmex) reconnect() {
|
||||
for {
|
||||
err := b.WebsocketConnect()
|
||||
if err != nil {
|
||||
log.Println("Bitmex websocket: Connection timed out - Failed to connect, sleeping...")
|
||||
time.Sleep(time.Second * 2)
|
||||
continue
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// handleIncomingData services incoming data from the websocket connection
|
||||
func (b *Bitmex) handleIncomingData() {
|
||||
defer func() {
|
||||
if b.Verbose {
|
||||
log.Println("Bitmex websocket: Response data handler routine shutdown")
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
_, resp, err := b.WebsocketConn.ReadMessage()
|
||||
if err != nil {
|
||||
if b.Verbose {
|
||||
log.Println("Bitmex websocket: Connection error", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
message := string(resp)
|
||||
if common.StringContains(message, "pong") {
|
||||
if b.Verbose {
|
||||
log.Println("Bitmex websocket: PONG receieved")
|
||||
}
|
||||
pongChan <- 1
|
||||
continue
|
||||
}
|
||||
|
||||
if common.StringContains(message, "ping") {
|
||||
err = b.WebsocketConn.WriteJSON("pong")
|
||||
if err != nil {
|
||||
if b.Verbose {
|
||||
log.Println("Bitmex websocket error: ", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !timer.Reset(5 * time.Second) {
|
||||
log.Fatal("Bitmex websocket: Timer failed to set")
|
||||
}
|
||||
|
||||
quickCapture := make(map[string]interface{})
|
||||
err = common.JSONDecode(resp, &quickCapture)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var respError WebsocketErrorResponse
|
||||
if _, ok := quickCapture["status"]; ok {
|
||||
err = common.JSONDecode(resp, &respError)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Printf("Bitmex websocket error: %s", respError.Error)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := quickCapture["success"]; ok {
|
||||
var decodedResp WebsocketSubscribeResp
|
||||
err := common.JSONDecode(resp, &decodedResp)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if decodedResp.Success {
|
||||
if b.Verbose {
|
||||
if len(quickCapture) == 3 {
|
||||
log.Printf("Bitmex Websocket: Successfully subscribed to %s",
|
||||
decodedResp.Subscribe)
|
||||
} else {
|
||||
log.Println("Bitmex Websocket: Successfully authenticated websocket connection")
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
log.Printf("Bitmex websocket error: Unable to subscribe %s",
|
||||
decodedResp.Subscribe)
|
||||
|
||||
} else if _, ok := quickCapture["table"]; ok {
|
||||
var decodedResp WebsocketMainResponse
|
||||
err := common.JSONDecode(resp, &decodedResp)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
switch decodedResp.Table {
|
||||
case bitmexWSOrderbookL2:
|
||||
var orderbooks OrderBookData
|
||||
err = common.JSONDecode(resp, &orderbooks)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = b.processOrderbook(orderbooks.Data, orderbooks.Action)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
case bitmexWSTrade:
|
||||
var trades TradeData
|
||||
err = common.JSONDecode(resp, &trades)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = b.processTrades(trades.Data, trades.Action)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
case bitmexWSAnnouncement:
|
||||
var announcement AnnouncementData
|
||||
err = common.JSONDecode(resp, &announcement)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = b.processAnnouncement(announcement.Data, announcement.Action)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
default:
|
||||
log.Fatal("Bitmex websocket error: Table unknown -", decodedResp.Table)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Temporary local cache of Announcements
|
||||
var localAnnouncements []Announcement
|
||||
var partialLoadedAnnouncement bool
|
||||
|
||||
// ProcessAnnouncement process announcements
|
||||
func (b *Bitmex) processAnnouncement(data []Announcement, action string) error {
|
||||
switch action {
|
||||
case bitmexActionInitialData:
|
||||
if !partialLoadedAnnouncement {
|
||||
localAnnouncements = data
|
||||
}
|
||||
partialLoadedAnnouncement = true
|
||||
default:
|
||||
return fmt.Errorf("Bitmex websocket error: ProcessAnnouncement() unallocated action - %s",
|
||||
action)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Temporary local cache of orderbooks
|
||||
var localOb []OrderBookL2
|
||||
var partialLoaded bool
|
||||
|
||||
// ProcessOrderbook processes orderbook updates
|
||||
func (b *Bitmex) processOrderbook(data []OrderBookL2, action string) error {
|
||||
switch action {
|
||||
case bitmexActionInitialData:
|
||||
if !partialLoaded {
|
||||
localOb = data
|
||||
}
|
||||
partialLoaded = true
|
||||
case bitmexActionUpdateData:
|
||||
if partialLoaded {
|
||||
updated := len(data)
|
||||
for _, elem := range data {
|
||||
for i := range localOb {
|
||||
if localOb[i].ID == elem.ID && localOb[i].Symbol == elem.Symbol {
|
||||
localOb[i].Side = elem.Side
|
||||
localOb[i].Size = elem.Size
|
||||
updated--
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if updated != 0 {
|
||||
return errors.New("Bitmex websocket error: Elements not updated correctly")
|
||||
}
|
||||
}
|
||||
case bitmexActionInsertData:
|
||||
if partialLoaded {
|
||||
updated := len(data)
|
||||
for _, elem := range data {
|
||||
localOb = append(localOb, OrderBookL2{
|
||||
Symbol: elem.Symbol,
|
||||
ID: elem.ID,
|
||||
Side: elem.Side,
|
||||
Size: elem.Size,
|
||||
Price: elem.Price,
|
||||
})
|
||||
updated--
|
||||
}
|
||||
if updated != 0 {
|
||||
return errors.New("Bitmex websocket error: Elements not updated correctly")
|
||||
}
|
||||
}
|
||||
case bitmexActionDeleteData:
|
||||
if partialLoaded {
|
||||
updated := len(data)
|
||||
for _, elem := range data {
|
||||
for i := range localOb {
|
||||
if localOb[i].ID == elem.ID && localOb[i].Symbol == elem.Symbol {
|
||||
localOb[i] = localOb[len(localOb)-1]
|
||||
localOb = localOb[:len(localOb)-1]
|
||||
updated--
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if updated != 0 {
|
||||
return errors.New("Bitmex websocket error: Elements not updated correctly")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Temporary local cache of orderbooks
|
||||
var localTrades []Trade
|
||||
var partialLoadedTrades bool
|
||||
|
||||
// ProcessTrades processes new trades that have occured
|
||||
func (b *Bitmex) processTrades(data []Trade, action string) error {
|
||||
switch action {
|
||||
case bitmexActionInitialData:
|
||||
if !partialLoadedTrades {
|
||||
localTrades = data
|
||||
}
|
||||
partialLoadedTrades = true
|
||||
case bitmexActionInsertData:
|
||||
if partialLoadedTrades {
|
||||
localTrades = append(localTrades, data...)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("Bitmex websocket error: ProcessTrades() unallocated action - %s",
|
||||
action)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WebsocketSubscribe subscribes to a websocket channel
|
||||
func (b *Bitmex) websocketSubscribe() error {
|
||||
contracts := b.GetEnabledCurrencies()
|
||||
|
||||
// Subscriber
|
||||
var subscriber WebsocketRequest
|
||||
subscriber.Command = "subscribe"
|
||||
|
||||
// Announcement subscribe
|
||||
subscriber.Arguments = append(subscriber.Arguments, bitmexWSAnnouncement)
|
||||
|
||||
for _, contract := range contracts {
|
||||
// Orderbook subscribe
|
||||
subscriber.Arguments = append(subscriber.Arguments,
|
||||
bitmexWSOrderbookL2+":"+contract.Pair().String())
|
||||
|
||||
// Trade subscribe
|
||||
subscriber.Arguments = append(subscriber.Arguments,
|
||||
bitmexWSTrade+":"+contract.Pair().String())
|
||||
|
||||
// NOTE more added here in future
|
||||
}
|
||||
|
||||
err := b.WebsocketConn.WriteJSON(subscriber)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WebsocketSendAuth sends an authenticated subscription
|
||||
func (b *Bitmex) websocketSendAuth() error {
|
||||
timestamp := time.Now().Add(time.Hour * 1).Unix()
|
||||
newTimestamp := strconv.FormatInt(timestamp, 10)
|
||||
hmac := common.GetHMAC(common.HashSHA256,
|
||||
[]byte("GET/realtime"+newTimestamp),
|
||||
[]byte(b.APISecret))
|
||||
|
||||
signature := common.HexEncodeToString(hmac)
|
||||
|
||||
var sendAuth WebsocketRequest
|
||||
sendAuth.Command = "authKeyExpires"
|
||||
sendAuth.Arguments = append(sendAuth.Arguments, b.APIKey)
|
||||
sendAuth.Arguments = append(sendAuth.Arguments, timestamp)
|
||||
sendAuth.Arguments = append(sendAuth.Arguments, signature)
|
||||
|
||||
return b.WebsocketConn.WriteJSON(sendAuth)
|
||||
}
|
||||
|
||||
// Shutdown to monitor and shut down routines package specific
|
||||
type Shutdown struct {
|
||||
c chan int
|
||||
routineCount int
|
||||
finishC chan int
|
||||
}
|
||||
|
||||
// NewRoutineManagement returns an new initial routine management system
|
||||
func (b *Bitmex) NewRoutineManagement() *Shutdown {
|
||||
return &Shutdown{
|
||||
c: make(chan int, 1),
|
||||
finishC: make(chan int, 1),
|
||||
}
|
||||
}
|
||||
|
||||
// AddRoutine adds a routine to the monitor and returns a channel
|
||||
func (r *Shutdown) addRoutine() chan int {
|
||||
log.Println("Bitmex Websocket: Routine added to monitor")
|
||||
r.routineCount++
|
||||
return r.c
|
||||
}
|
||||
|
||||
// RoutineShutdown sends a message to the finisher channel
|
||||
func (r *Shutdown) routineShutdown() {
|
||||
log.Println("Bitmex Websocket: Routine is shutting down")
|
||||
r.finishC <- 1
|
||||
}
|
||||
|
||||
// SignalShutdown signals a shutdown across routines
|
||||
func (r *Shutdown) SignalShutdown() {
|
||||
log.Println("Bitmex Websocket: Shutdown signal sending..")
|
||||
for i := 0; i < r.routineCount; i++ {
|
||||
log.Printf("Bitmex Websocket: Shutdown signal sent to routine %d", i+1)
|
||||
r.c <- 1
|
||||
}
|
||||
|
||||
for {
|
||||
<-r.finishC
|
||||
r.routineCount--
|
||||
if r.routineCount <= 0 {
|
||||
close(r.c)
|
||||
close(r.finishC)
|
||||
log.Println("Bitmex Websocket: All routines stopped")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
72
exchanges/bitmex/bitmex_websocket_types.go
Normal file
72
exchanges/bitmex/bitmex_websocket_types.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package bitmex
|
||||
|
||||
// WebsocketRequest is the main request type
|
||||
type WebsocketRequest struct {
|
||||
Command string `json:"op"`
|
||||
Arguments []interface{} `json:"args"`
|
||||
}
|
||||
|
||||
// WebsocketErrorResponse main error response
|
||||
type WebsocketErrorResponse struct {
|
||||
Status int `json:"status"`
|
||||
Error string `json:"error"`
|
||||
Meta interface{} `json:"meta"`
|
||||
Request WebsocketRequest `json:"request"`
|
||||
}
|
||||
|
||||
// WebsocketWelcome initial welcome type
|
||||
type WebsocketWelcome struct {
|
||||
Info string `json:"info"`
|
||||
Version string `json:"version"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Docs string `json:"docs"`
|
||||
Limit struct {
|
||||
Remaining int64 `json:"remaining"`
|
||||
} `json:"limit"`
|
||||
}
|
||||
|
||||
// WebsocketSubscribeResp is a response that occurs after a subscription
|
||||
type WebsocketSubscribeResp struct {
|
||||
Success bool `json:"success"`
|
||||
Subscribe string `json:"subscribe"`
|
||||
Request WebsocketRequest `json:"request"`
|
||||
}
|
||||
|
||||
// WebsocketMainResponse main table defined response
|
||||
type WebsocketMainResponse struct {
|
||||
Table string `json:"table"`
|
||||
Keys []string `json:"keys"`
|
||||
Types struct {
|
||||
ID string `json:"id"`
|
||||
Price string `json:"price"`
|
||||
Side string `json:"side"`
|
||||
Size string `json:"size"`
|
||||
Symbol string `json:"symbol"`
|
||||
} `json:"types"`
|
||||
ForeignKeys struct {
|
||||
Side string `json:"side"`
|
||||
Symbol string `json:"symbol"`
|
||||
} `json:"foreignKeys"`
|
||||
Attributes struct {
|
||||
ID string `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
} `json:"Attributes"`
|
||||
}
|
||||
|
||||
// OrderBookData contains orderbook resp data with action to be taken
|
||||
type OrderBookData struct {
|
||||
Data []OrderBookL2 `json:"data"`
|
||||
Action string `json:"action"`
|
||||
}
|
||||
|
||||
// TradeData contains trade resp data with action to be taken
|
||||
type TradeData struct {
|
||||
Data []Trade `json:"data"`
|
||||
Action string `json:"action"`
|
||||
}
|
||||
|
||||
// AnnouncementData contains announcement resp data with action to be taken
|
||||
type AnnouncementData struct {
|
||||
Data []Announcement `json:"data"`
|
||||
Action string `json:"action"`
|
||||
}
|
||||
195
exchanges/bitmex/bitmex_wrapper.go
Normal file
195
exchanges/bitmex/bitmex_wrapper.go
Normal file
@@ -0,0 +1,195 @@
|
||||
package bitmex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency/pair"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
// Start starts the Bitmex go routine
|
||||
func (b *Bitmex) Start(wg *sync.WaitGroup) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
b.Run()
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
// Run implements the Bitmex wrapper
|
||||
func (b *Bitmex) Run() {
|
||||
if b.Verbose {
|
||||
log.Printf("%s Websocket: %s. (url: %s).\n", b.GetName(), common.IsEnabled(b.Websocket), b.WebsocketURL)
|
||||
log.Printf("%s polling delay: %ds.\n", b.GetName(), b.RESTPollingDelay)
|
||||
log.Printf("%s %d currencies enabled: %s.\n", b.GetName(), len(b.EnabledPairs), b.EnabledPairs)
|
||||
}
|
||||
|
||||
marketInfo, err := b.GetActiveInstruments(GenericRequestParams{})
|
||||
if err != nil {
|
||||
log.Printf("%s Failed to get available symbols.\n", b.GetName())
|
||||
} else {
|
||||
|
||||
var exchangeProducts []string
|
||||
|
||||
for _, info := range marketInfo {
|
||||
exchangeProducts = append(exchangeProducts, info.Symbol)
|
||||
}
|
||||
|
||||
err = b.UpdateCurrencies(exchangeProducts, false, false)
|
||||
if err != nil {
|
||||
log.Printf("%s Failed to update available currencies.\n", b.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (b *Bitmex) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
currency := exchange.FormatExchangeCurrency(b.Name, p)
|
||||
|
||||
tick, err := b.GetTrade(GenericRequestParams{
|
||||
Symbol: currency.String(),
|
||||
StartTime: time.Now().Format(time.RFC3339),
|
||||
Reverse: true,
|
||||
Count: 1})
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
if len(tick) == 0 {
|
||||
return tickerPrice, errors.New("Bitmex REST error: no ticker return")
|
||||
}
|
||||
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.LastUpdated = time.Now()
|
||||
tickerPrice.CurrencyPair = tick[0].Symbol
|
||||
tickerPrice.Last = tick[0].Price
|
||||
tickerPrice.Volume = float64(tick[0].Size)
|
||||
|
||||
ticker.ProcessTicker(b.Name, p, tickerPrice, assetType)
|
||||
|
||||
return tickerPrice, nil
|
||||
}
|
||||
|
||||
// GetTickerPrice returns the ticker for a currency pair
|
||||
func (b *Bitmex) GetTickerPrice(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
tickerNew, err := ticker.GetTicker(b.GetName(), p, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateTicker(p, assetType)
|
||||
}
|
||||
return tickerNew, nil
|
||||
}
|
||||
|
||||
// GetOrderbookEx returns orderbook base on the currency pair
|
||||
func (b *Bitmex) GetOrderbookEx(currency pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
ob, err := orderbook.GetOrderbook(b.GetName(), currency, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateOrderbook(currency, assetType)
|
||||
}
|
||||
return ob, nil
|
||||
}
|
||||
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (b *Bitmex) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
|
||||
orderbookNew, err := b.GetOrderbook(OrderBookGetL2Params{
|
||||
Symbol: exchange.FormatExchangeCurrency(b.Name, p).String(),
|
||||
Depth: 500})
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
|
||||
for _, ob := range orderbookNew {
|
||||
if ob.Side == "Sell" {
|
||||
orderBook.Asks = append(orderBook.Asks,
|
||||
orderbook.Item{Amount: float64(ob.Size), Price: ob.Price})
|
||||
continue
|
||||
}
|
||||
if ob.Side == "Buy" {
|
||||
orderBook.Bids = append(orderBook.Bids,
|
||||
orderbook.Item{Amount: float64(ob.Size), Price: ob.Price})
|
||||
continue
|
||||
}
|
||||
}
|
||||
orderbook.ProcessOrderbook(b.GetName(), p, orderBook, assetType)
|
||||
|
||||
return orderbook.GetOrderbook(b.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetExchangeAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Bitmex exchange
|
||||
func (b *Bitmex) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
return response, errors.New("not implemented")
|
||||
}
|
||||
|
||||
// GetExchangeFundTransferHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (b *Bitmex) GetExchangeFundTransferHistory() ([]exchange.FundHistory, error) {
|
||||
var fundHistory []exchange.FundHistory
|
||||
return fundHistory, errors.New("not supported on exchange")
|
||||
}
|
||||
|
||||
// GetExchangeHistory returns historic trade data since exchange opening.
|
||||
func (b *Bitmex) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
|
||||
var resp []exchange.TradeHistory
|
||||
|
||||
return resp, errors.New("trade history not yet implemented")
|
||||
}
|
||||
|
||||
// SubmitExchangeOrder submits a new order
|
||||
func (b *Bitmex) SubmitExchangeOrder(p pair.CurrencyPair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (int64, error) {
|
||||
return 0, errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// ModifyExchangeOrder will allow of changing orderbook placement and limit to
|
||||
// market conversion
|
||||
func (b *Bitmex) ModifyExchangeOrder(orderID int64, action exchange.ModifyOrder) (int64, error) {
|
||||
return 0, errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// CancelExchangeOrder cancels an order by its corresponding ID number
|
||||
func (b *Bitmex) CancelExchangeOrder(orderID int64) error {
|
||||
return errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// CancelAllExchangeOrders cancels all orders associated with a currency pair
|
||||
func (b *Bitmex) CancelAllExchangeOrders() error {
|
||||
return errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// GetExchangeOrderInfo returns information on a current open order
|
||||
func (b *Bitmex) GetExchangeOrderInfo(orderID int64) (exchange.OrderDetail, error) {
|
||||
var orderDetail exchange.OrderDetail
|
||||
return orderDetail, errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// GetExchangeDepositAddress returns a deposit address for a specified currency
|
||||
func (b *Bitmex) GetExchangeDepositAddress(cryptocurrency pair.CurrencyItem) (string, error) {
|
||||
return "", errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// WithdrawCryptoExchangeFunds returns a withdrawal ID when a withdrawal is
|
||||
// submitted
|
||||
func (b *Bitmex) WithdrawCryptoExchangeFunds(address string, cryptocurrency pair.CurrencyItem, amount float64) (string, error) {
|
||||
return "", errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// WithdrawFiatExchangeFunds returns a withdrawal ID when a withdrawal is
|
||||
// submitted
|
||||
func (b *Bitmex) WithdrawFiatExchangeFunds(currency pair.CurrencyItem, amount float64) (string, error) {
|
||||
return "", errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// WithdrawExchangeFiatFundsToInternationalBank returns a withdrawal ID when a withdrawal is
|
||||
// submitted
|
||||
func (b *Bitmex) WithdrawExchangeFiatFundsToInternationalBank(currency pair.CurrencyItem, amount float64) (string, error) {
|
||||
return "", errors.New("not yet implemented")
|
||||
}
|
||||
6125
exchanges/bitmex/swagger/swagger.json
Normal file
6125
exchanges/bitmex/swagger/swagger.json
Normal file
File diff suppressed because one or more lines are too long
35
testdata/configtest.json
vendored
35
testdata/configtest.json
vendored
@@ -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": [
|
||||
|
||||
@@ -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)
|
||||
|
||||
98
tools/documentation/exchanges_templates/bitmex.tmpl
Normal file
98
tools/documentation/exchanges_templates/bitmex.tmpl
Normal file
@@ -0,0 +1,98 @@
|
||||
{{define "exchanges bitmex" -}}
|
||||
{{template "header" .}}
|
||||
## Bithumb Exchange
|
||||
|
||||
### Current Features
|
||||
|
||||
+ REST Support
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### How to do REST public/private calls
|
||||
|
||||
+ If enabled via "configuration".json file the exchange will be added to the
|
||||
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
|
||||
the wrapper interface functions for accessing exchange data. View routines.go
|
||||
for an example of integration usage with GoCryptoTrader. Rudimentary example
|
||||
below:
|
||||
|
||||
main.go
|
||||
```go
|
||||
var b exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Bitmex" {
|
||||
b = bot.exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := b.GetTickerPrice()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderbookEx()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
|
||||
// set and AuthenticatedAPISupport is set to true
|
||||
|
||||
// Fetches current account information
|
||||
accountInfo, err := b.GetExchangeAccountInfo()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
+ If enabled via individually importing package, rudimentary example below:
|
||||
|
||||
```go
|
||||
// Public calls
|
||||
|
||||
// Fetches current ticker information
|
||||
ticker, err := b.GetTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderBook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - make sure your APIKEY and APISECRET are set and
|
||||
// AuthenticatedAPISupport is set to true
|
||||
|
||||
// GetUserInfo returns account info
|
||||
accountInfo, err := b.GetUserInfo(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Submits an order and the exchange and returns its tradeID
|
||||
tradeID, err := b.Trade(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### Please click GoDocs chevron above to view current GoDoc information for this package
|
||||
{{template "contributions"}}
|
||||
{{template "donations"}}
|
||||
{{end}}
|
||||
@@ -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 |
|
||||
|
||||
Reference in New Issue
Block a user