Feature: Websocket order handling (#446)

* Initial changes, removing exchange name as an arg and puts it in the pointer struct. Adds case to ws routines

* Adds CancelAllOrders func, adds GetByExchangeAndID. Adds modify handler in routines.go

* initial poor attempts to have bitmex work with new datahandler handlers. fixes ordersides

* bitmex Completes new order

* Better bitmex handling, but not complete. Begins a gargantuan task of unifying order data structs. Sometimes an order update will contain lot's of information, so its best to be able to update all fields of our orders, rather than just an arbitrary subset. As a result, everything will be broken for the foreseeable future :glitch_crab:

* Removes old order handler which did nothing. Updates order properties for everything everywhere - now consistent. Changes order status. Adds asset type and wallet address to all order types

* Adds order updater to update only relevant fields since the object is generic, we don't know what fields are passed from what exchanges. Adds "lastupdated" field to order.Detail. Expands order cancellation for engine orders.

* Ensures that new orders are added to the ordermanager's order store. Saaa many comments. Internalises orderStore get func. Adds internalOrderID to orderdetail and adds websocket support for it

* Fixes a cancelAllOrders oopsie doopsie

* Adds potential func to update orderdetails from an orderdetail struct. Unsure if will keep.

* Begins btcmarkets implementation. Expands order "stringToOrder" funcs to allow for some more flexible string coversions. Removes order.Submit via websocket as it would cause unlimited order place issues :D

* Finishes btc markets without testing

* Adds untested ws auth func to btse

* Finises btse, fixes btcmarkets bug

* Adds coinbasepro support

* Fixes a few more fields in coinbase pro and readds the extra subs

* Begins work on coinbene. Plus theyve added a new ws connection yeee

* Wasted a bunch of time adding support to an additional websocket that isn't needed ;_; Fixed a bug in coinbasepro. Fully kitted out coinbene support. Updates order types with all fields

* Removes extra websocket connection ;_;

* Finishes gemini. Fixes order side unknown

* Adds okgroup support. Moves byte reading to another function to allow for unit testing. Updates routines to use pointers. Updates date update handling for order details

* Finishes order data for okgroup websocket, but starts the STRANGE process of converting all other websocket endpoints to be a little less silly

* Cleans up okroup websocket implementation. Fixes bug in Gemini

* Adds poloniex support. Updates ws order handling

* new bitmex support. Adds some tests now that its all in its own func. Fixes poloniex bug

* Begins work on authenticated binance websocket

* Attempts to track user data via binance websocket

* Maybe finishes Binance websocket support

* Begins adding test coverage to orders.go. Updates names of script properties to match updated

* Begins an experiment with code coverage. Fixes more rebase issues

* Completes orders coverage. Botches a few other things though. Fixes more scripting stuff

* All tests in engine package pass

* Adds some loevely routine tests

* Moves ordermanager to test Bot ordermanager
Adds lovely routine tests to ensure things that get sent to be handled the data handler are handled by the data handler by handling them

* Replaces "wsHandleData" with "wsReadData" as that's what its going to do now.

* Splits all wsHandleData into wsReadData and wsHandleData to allow for easy testing via sending []byte json examples to test proper functionality. Breaks so many tests

* Fixes majority of test issues. But data races which are tough on the engine package

* "Fixes" test by removing shutdown test. It interferes with too many things. Requires some thought

* Tests all the binance websocket points

* Adds better bitfinex websocket support.

* Adds testing for bitfinex, bitstamp and btcmarkets. Fixes websocket bugs encountered

* Adds BTSE ws tests. Fixes bugs in ws

* Adds coinbase pro tests. Fixes any issues

* Coinbene tests

* Starts to handle coinut. Runs into a problem conceptually regarding websocket roundtrip and orders. Both events need to happen without impacting eachother/racing

* Addresses a data race issue regarding websocket and bot order management submission - order submission locks at an earlier point to prevent routines.go from creating an order before order submission creates it. Updates rpcserver to use order management bot to submit orders.

* Finishes the hectic coinut testing

* Adds tests for gateio

* Fixes rebase issues. Updates tests to work without being overloaded

* Begins testing of gemini. fixes up minor issues

* ginishes gemini tests and fixes

* Adds hitbtc tests. Fixes all the many issues with hitbtc websocket

* Adds remaining tests. Increases default test channel limit again

* Begins work towards huobi tests

* Finishes huobi tests

* Fixed all mythical rebase adventures

* Begins kraken transformation

* Finishes kraken. Fixes coinbene leverage now that its changed

* Begins okgroup testing

* Adds okgroup ws tests

* Does some poloniex

* Fixes basic curreny issue by extracting to func

* Begins redesign of poloniex websocket datahandling. Completes authenticated handling, now onto unauth

* Finishes poloniex revision

* Finishes ZB additions

* Fixes data races

* Fixes rebase issues. Fixes bad kraken logic

* Fixes after reviewing code

* lint everywhere

* Fixes lingering lints

* lint

* Adds test coverage to order detail and modify updating

* Fixes linting

* Fixes huge int, fixes date tests

* Adds GetByExchange, adds test for it. Protects fakepass echange. Renames DisplayQty to DisplayQuantity. Removes verbose. Adds some websocket properties.  Updates bitmex asset type in test

* Addresses timestamps, type abbreviations, verbosity. Expands binance kline switch cases. Updates some websocket capabilities.

* Adds coverage to the stringToOrderType/Status functions introduced in PR

* Minor fixes addressing some time, error text and use of StringDataCompareInsensitive

* Introduces shiny new system which checks if there is an awaiting ID, if found, processes via wrapper method, else, goes through wsHandleData method. Removes weird locking system from wrapper/websocket data race. Updates bitfinex to properly handle websocket order requests and notifications

* Moves fakePassingExchange to test_helper. Fixes some order side implementations for trades. Botches a new error type

* Adds new error type to track and handle order classification errors separately

* Fully fleshes out ClassificationError for all instances of status conversion. Even in order trades and some wrapper functions

* Introduces common.SimpleTimeFormat for "2006-01-02 15:04:05". Fixes binance and bitfinex issues with auth endpoint use, map casting. Expands more order.ClassificationError usage. Fixes some more generic websocket response errors

* Future proofs order updating by utilising asset types. Expands testing to accomodate. Adds shiny new time type. Expands wrapper websocket functionality definitions

* minty linty

* Broken end of day code addressing basic nits on comments, returns and currency conversion

* Adds testing to btcmarkets websocket. Also updates websocket orderbook to use update instead

* Fixes fun rebase fun fun so fun

* Addresses minor nits regarding changed interface and comments

* Creates new function `GetRequestFormattedPairAndAssetType` to retrieve a currency pair and asset type based on a string. It will iterate over enabled pairs and compare them to formatted pairs and then return that pair if found.

* Fixes test

* Adds a single line to the end of the file, because that would be really bad if it wasn't there

* Updates fakepassexchange to not use params, updates test params, uses fatal in some tests where its important, updates order manager to have a rwmutex, removes some returns, improves ws key test for binance, updates properties to reflect their actual values, adds some more websocket properties

* Addresses binance switch linting

* Updates leverage property to int64

* Fixes what was broken
This commit is contained in:
Scott
2020-03-03 13:32:14 +11:00
committed by GitHub
parent 9d49184bc6
commit b686cf2e0e
142 changed files with 13867 additions and 6043 deletions

View File

@@ -258,38 +258,38 @@ func (p LeaderboardGetParams) IsNil() bool {
// OrderNewParams contains all the parameters to send to the API endpoint
type OrderNewParams struct {
// ClOrdID - [Optional] Client Order ID. This clOrdID will come back on the
// ClientOrderID - [Optional] Client Order ID. This clOrdID will come back on the
// order and any related executions.
ClOrdID string `json:"clOrdID,omitempty"`
ClientOrderID string `json:"clOrdID,omitempty"`
// ClOrdLinkID - [Optional] Client Order Link ID for contingent orders.
ClOrdLinkID string `json:"clOrdLinkID,omitempty"`
// ClientOrderLinkID - [Optional] Client Order Link ID for contingent orders.
ClientOrderLinkID string `json:"clOrdLinkID,omitempty"`
// ContingencyType - [Optional] contingency type for use with `clOrdLinkID`.
// Valid options: OneCancelsTheOther, OneTriggersTheOther,
// OneUpdatesTheOtherAbsolute, OneUpdatesTheOtherProportional.
ContingencyType string `json:"contingencyType,omitempty"`
// DisplayQty - [Optional] quantity to display in the book. Use 0 for a fully
// DisplayQuantity- [Optional] quantity to display in the book. Use 0 for a fully
// hidden order.
DisplayQty float64 `json:"displayQty,omitempty"`
DisplayQuantity float64 `json:"displayQty,omitempty"`
// ExecInst - [Optional] execution instructions. Valid options:
// ExecutionInstance - [Optional] execution instructions. Valid options:
// ParticipateDoNotInitiate, AllOrNone, MarkPrice, IndexPrice, LastPrice,
// Close, ReduceOnly, Fixed. 'AllOrNone' instruction requires `displayQty`
// to be 0. 'MarkPrice', 'IndexPrice' or 'LastPrice' instruction valid for
// 'Stop', 'StopLimit', 'MarketIfTouched', and 'LimitIfTouched' orders.
ExecInst string `json:"execInst,omitempty"`
// OrdType - Order type. Valid options: Market, Limit, Stop, StopLimit,
// OrderType - Order type. Valid options: Market, Limit, Stop, StopLimit,
// MarketIfTouched, LimitIfTouched, MarketWithLeftOverAsLimit, Pegged.
// Defaults to 'Limit' when `price` is specified. Defaults to 'Stop' when
// `stopPx` is specified. Defaults to 'StopLimit' when `price` and `stopPx`
// are specified.
OrdType string `json:"ordType,omitempty"`
OrderType string `json:"ordType,omitempty"`
// OrderQty Order quantity in units of the instrument (i.e. contracts).
OrderQty float64 `json:"orderQty,omitempty"`
// OrderQuantity Order quantity in units of the instrument (i.e. contracts).
OrderQuantity float64 `json:"orderQty,omitempty"`
// PegOffsetValue - [Optional] trailing offset from the current price for
// 'Stop', 'StopLimit', 'MarketIfTouched', and 'LimitIfTouched' orders; use a
@@ -309,11 +309,11 @@ type OrderNewParams struct {
// `orderQty` or `simpleOrderQty` is negative.
Side string `json:"side,omitempty"`
// SimpleOrderQty - Order quantity in units of the underlying instrument
// SimpleOrderQuantity - Order quantity in units of the underlying instrument
// (i.e. Bitcoin).
SimpleOrderQty float64 `json:"simpleOrderQty,omitempty"`
SimpleOrderQuantity float64 `json:"simpleOrderQty,omitempty"`
// StopPx - [Optional] trigger price for 'Stop', 'StopLimit',
// StopPrice - [Optional] trigger price for 'Stop', 'StopLimit',
// 'MarketIfTouched', and 'LimitIfTouched' orders. Use a price below the
// current price for stop-sell orders and buy-if-touched orders. Use
// `execInst` of 'MarkPrice' or 'LastPrice' to define the current price used
@@ -351,16 +351,16 @@ func (p *OrderNewParams) IsNil() bool {
// OrderAmendParams contains all the parameters to send to the API endpoint
// for the order amend operation
type OrderAmendParams struct {
// ClOrdID - [Optional] new Client Order ID, requires `origClOrdID`.
ClOrdID string `json:"clOrdID,omitempty"`
// ClientOrderID - [Optional] new Client Order ID, requires `origClOrdID`.
ClientOrderID string `json:"clOrdID,omitempty"`
// LeavesQty - [Optional] leaves quantity in units of the instrument
// LeavesQuantity - [Optional] leaves quantity in units of the instrument
// (i.e. contracts). Useful for amending partially filled orders.
LeavesQty int32 `json:"leavesQty,omitempty"`
LeavesQuantity int32 `json:"leavesQty,omitempty"`
OrderID string `json:"orderID,omitempty"`
// OrderQty - [Optional] order quantity in units of the instrument
// OrderQuantity - [Optional] order quantity in units of the instrument
// (i.e. contracts).
OrderQty int32 `json:"orderQty,omitempty"`
@@ -377,15 +377,15 @@ type OrderAmendParams struct {
// 'LimitIfTouched' orders.
Price float64 `json:"price,omitempty"`
// SimpleLeavesQty - [Optional] leaves quantity in units of the underlying
// SimpleLeavesQuantity - [Optional] leaves quantity in units of the underlying
// instrument (i.e. Bitcoin). Useful for amending partially filled orders.
SimpleLeavesQty float64 `json:"simpleLeavesQty,omitempty"`
SimpleLeavesQuantity float64 `json:"simpleLeavesQty,omitempty"`
// SimpleOrderQty - [Optional] order quantity in units of the underlying
// SimpleOrderQuantity - [Optional] order quantity in units of the underlying
// instrument (i.e. Bitcoin).
SimpleOrderQty float64 `json:"simpleOrderQty,omitempty"`
SimpleOrderQuantity float64 `json:"simpleOrderQty,omitempty"`
// StopPx - [Optional] trigger price for 'Stop', 'StopLimit',
// StopPrice - [Optional] trigger price for 'Stop', 'StopLimit',
// 'MarketIfTouched', and 'LimitIfTouched' orders. Use a price below the
// current price for stop-sell orders and buy-if-touched orders.
StopPx float64 `json:"stopPx,omitempty"`
@@ -397,7 +397,7 @@ type OrderAmendParams struct {
// VerifyData verifies outgoing data sets
func (p *OrderAmendParams) VerifyData() error {
if p.OrderID == "" {
return errors.New("verifydata() OrderNewParams error - OrderID not set")
return errors.New("verifydata() OrderNewParams error - ID not set")
}
return nil
}
@@ -415,8 +415,8 @@ func (p *OrderAmendParams) IsNil() bool {
// OrderCancelParams contains all the parameters to send to the API endpoint
type OrderCancelParams struct {
// ClOrdID - Client Order ID(s). See POST /order.
ClOrdID string `json:"clOrdID,omitempty"`
// ClientOrderID - Client Order ID(s). See POST /order.
ClientOrderID string `json:"clOrdID,omitempty"`
// OrderID - Order ID(s).
OrderID string `json:"orderID,omitempty"`

View File

@@ -50,6 +50,8 @@ func TestMain(m *testing.M) {
if err != nil {
log.Fatal("Bitmex setup error", err)
}
b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
b.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
os.Exit(m.Run())
}
@@ -231,9 +233,9 @@ func TestAmendOrder(t *testing.T) {
func TestCreateOrder(t *testing.T) {
_, err := b.CreateOrder(&OrderNewParams{Symbol: "XBTM15",
Price: 219.0,
ClOrdID: "mm_bitmex_1a/oemUeQ4CAJZgP3fjHsA",
OrderQty: 98})
Price: 219.0,
ClientOrderID: "mm_bitmex_1a/oemUeQ4CAJZgP3fjHsA",
OrderQuantity: 98})
if err == nil {
t.Error("CreateOrder() Expected error")
}
@@ -360,7 +362,7 @@ func TestGetStatSummary(t *testing.T) {
func TestGetTrade(t *testing.T) {
_, err := b.GetTrade(&GenericRequestParams{
Symbol: "XBTUSD",
Symbol: "ETHUSD",
StartTime: time.Now().Format(time.RFC3339),
Reverse: true})
if err != nil {
@@ -478,7 +480,7 @@ func TestFormatWithdrawPermissions(t *testing.T) {
func TestGetActiveOrders(t *testing.T) {
var getOrdersRequest = order.GetOrdersRequest{
OrderType: order.AnyType,
Type: order.AnyType,
}
_, err := b.GetActiveOrders(&getOrdersRequest)
@@ -491,8 +493,8 @@ func TestGetActiveOrders(t *testing.T) {
func TestGetOrderHistory(t *testing.T) {
var getOrdersRequest = order.GetOrdersRequest{
OrderType: order.AnyType,
Currencies: []currency.Pair{currency.NewPair(currency.LTC,
Type: order.AnyType,
Pairs: []currency.Pair{currency.NewPair(currency.LTC,
currency.BTC)},
}
@@ -520,11 +522,11 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.XBT,
Quote: currency.USD,
},
OrderSide: order.Buy,
OrderType: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
}
response, err := b.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -541,10 +543,10 @@ func TestCancelExchangeOrder(t *testing.T) {
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
var orderCancellation = &order.Cancel{
OrderID: "123456789012345678901234567890123456",
ID: "123456789012345678901234567890123456",
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
CurrencyPair: currencyPair,
Pair: currencyPair,
}
err := b.CancelOrder(orderCancellation)
@@ -563,10 +565,10 @@ func TestCancelAllExchangeOrders(t *testing.T) {
currencyPair := currency.NewPair(currency.LTC, currency.BTC)
var orderCancellation = &order.Cancel{
OrderID: "123456789012345678901234567890123456",
ID: "123456789012345678901234567890123456",
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
CurrencyPair: currencyPair,
Pair: currencyPair,
}
resp, err := b.CancelAllOrders(orderCancellation)
@@ -601,7 +603,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := b.ModifyOrder(&order.Modify{OrderID: "1337"})
_, err := b.ModifyOrder(&order.Modify{ID: "1337"})
if err == nil {
t.Error("ModifyOrder() error")
}
@@ -686,9 +688,8 @@ func TestWsAuth(t *testing.T) {
if err != nil {
t.Fatal(err)
}
b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
b.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
go b.wsHandleIncomingData()
go b.wsReadData()
err = b.websocketSendAuth()
if err != nil {
t.Fatal(err)
@@ -704,3 +705,229 @@ func TestWsAuth(t *testing.T) {
}
timer.Stop()
}
func TestWsPositionUpdate(t *testing.T) {
pressXToJSON := []byte(`{"table":"position",
"action":"update",
"data":[{
"account":2,"symbol":"ETHUSD","currency":"XBt",
"currentTimestamp":"2017-04-04T22:07:42.442Z", "currentQty":1,"markPrice":1136.88,"markValue":-87960,
"riskValue":87960,"homeNotional":0.0008796,"posState":"Liquidation","maintMargin":263,
"unrealisedGrossPnl":-677,"unrealisedPnl":-677,"unrealisedPnlPcnt":-0.0078,"unrealisedRoePcnt":-0.7756,
"simpleQty":0.001,"liquidationPrice":1140.1, "timestamp":"2017-04-04T22:07:45.442Z"
}]}`)
err := b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
}
func TestWsInsertExectuionUpdate(t *testing.T) {
pressXToJSON := []byte(`{"table":"execution",
"action":"insert",
"data":[{
"execID":"0193e879-cb6f-2891-d099-2c4eb40fee21",
"orderID":"00000000-0000-0000-0000-000000000000","clOrdID":"","clOrdLinkID":"","account":2,"symbol":"ETHUSD",
"side":"Sell","lastQty":1,"lastPx":1134.37,"underlyingLastPx":null,"lastMkt":"XBME",
"lastLiquidityInd":"RemovedLiquidity", "simpleOrderQty":null,"orderQty":1,"price":1134.37,"displayQty":null,
"stopPx":null,"pegOffsetValue":null,"pegPriceType":"","currency":"USD","settlCurrency":"XBt",
"execType":"Trade","ordType":"Limit","timeInForce":"ImmediateOrCancel","execInst":"",
"contingencyType":"","exDestination":"XBME","ordStatus":"Filled","triggered":"","workingIndicator":false,
"ordRejReason":"","simpleLeavesQty":0,"leavesQty":0,"simpleCumQty":0.001,"cumQty":1,"avgPx":1134.37,
"commission":0.00075,"tradePublishIndicator":"DoNotPublishTrade","multiLegReportingType":"SingleSecurity",
"text":"Liquidation","trdMatchID":"7f4ab7f6-0006-3234-76f4-ae1385aad00f","execCost":88155,"execComm":66,
"homeNotional":-0.00088155,"foreignNotional":1,"transactTime":"2017-04-04T22:07:46.035Z",
"timestamp":"2017-04-04T22:07:46.035Z"
}]}`)
err := b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
}
func TestWSConnectionHandling(t *testing.T) {
pressXToJSON := []byte(`{"info":"Welcome to the BitMEX Realtime API.","version":"1.1.0",
"timestamp":"2015-01-18T10:14:06.802Z","docs":"https://www.bitmex.com/app/wsAPI","heartbeatEnabled":false}`)
err := b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
}
func TestWSSubscriptionHandling(t *testing.T) {
pressXToJSON := []byte(`{"success":true,"subscribe":"trade:ETHUSD",
"request":{"op":"subscribe","args":["trade:ETHUSD","instrument:ETHUSD"]}}`)
err := b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
}
func TestWSPositionUpdateHandling(t *testing.T) {
pressXToJSON := []byte(`{"table":"position",
"action":"update",
"data":[{
"account":2,"symbol":"ETHUSD","currency":"XBt","currentQty":1,
"markPrice":1136.88,"posState":"Liquidated","simpleQty":0.001,"liquidationPrice":1140.1,"bankruptPrice":1134.37,
"timestamp":"2017-04-04T22:07:46.019Z"
}]}`)
err := b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
pressXToJSON = []byte(`{"table":"position",
"action":"update",
"data":[{
"account":2,"symbol":"ETHUSD","currency":"XBt",
"deleveragePercentile":null,"rebalancedPnl":1003,"prevRealisedPnl":-1003,"execSellQty":1,
"execSellCost":88155,"execQty":0,"execCost":872,"execComm":131,"currentTimestamp":"2017-04-04T22:07:46.140Z",
"currentQty":0,"currentCost":872,"currentComm":131,"realisedCost":872,"unrealisedCost":0,"grossExecCost":0,
"isOpen":false,"markPrice":null,"markValue":0,"riskValue":0,"homeNotional":0,"foreignNotional":0,"posState":"",
"posCost":0,"posCost2":0,"posInit":0,"posComm":0,"posMargin":0,"posMaint":0,"maintMargin":0,
"realisedGrossPnl":-872,"realisedPnl":-1003,"unrealisedGrossPnl":0,"unrealisedPnl":0,
"unrealisedPnlPcnt":0,"unrealisedRoePcnt":0,"simpleQty":0,"simpleCost":0,"simpleValue":0,"avgCostPrice":null,
"avgEntryPrice":null,"breakEvenPrice":null,"marginCallPrice":null,"liquidationPrice":null,"bankruptPrice":null,
"timestamp":"2017-04-04T22:07:46.140Z"
}]}`)
err = b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
}
func TestWSOrderbookHandling(t *testing.T) {
b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
pressXToJSON := []byte(`{
"table":"orderBookL2_25",
"keys":["symbol","id","side"],
"types":{"id":"long","price":"float","side":"symbol","size":"long","symbol":"symbol"},
"foreignKeys":{"side":"side","symbol":"instrument"},
"attributes":{"id":"sorted","symbol":"grouped"},
"action":"partial",
"data":[
{"symbol":"ETHUSD","id":17999992000,"side":"Sell","size":100,"price":80},
{"symbol":"ETHUSD","id":17999993000,"side":"Sell","size":20,"price":70},
{"symbol":"ETHUSD","id":17999994000,"side":"Sell","size":10,"price":60},
{"symbol":"ETHUSD","id":17999995000,"side":"Buy","size":10,"price":50},
{"symbol":"ETHUSD","id":17999996000,"side":"Buy","size":20,"price":40},
{"symbol":"ETHUSD","id":17999997000,"side":"Buy","size":100,"price":30}
]
}`)
err := b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
pressXToJSON = []byte(`{
"table":"orderBookL2_25",
"action":"update",
"data":[
{"symbol":"ETHUSD","id":17999995000,"side":"Buy","size":5}
]
}`)
err = b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
pressXToJSON = []byte(`{
"table":"orderBookL2_25",
"action":"update",
"data":[
]
}`)
err = b.wsHandleData(pressXToJSON)
if err == nil {
t.Error("Expected error")
}
pressXToJSON = []byte(`{
"table":"orderBookL2_25",
"action":"delete",
"data":[
{"symbol":"ETHUSD","id":17999995000,"side":"Buy"}
]
}`)
err = b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
pressXToJSON = []byte(`{
"table":"orderBookL2_25",
"action":"delete",
"data":[
{"symbol":"ETHUSD","id":17999995000,"side":"Buy"}
]
}`)
err = b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
}
func TestWSDeleveragePositionUpdateHandling(t *testing.T) {
b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
pressXToJSON := []byte(`{"table":"position",
"action":"update",
"data":[{
"account":2,"symbol":"ETHUSD","currency":"XBt","currentQty":2000,
"markPrice":1160.72,"posState":"Deleverage","simpleQty":1.746,"liquidationPrice":1140.1,
"timestamp":"2017-04-04T22:16:38.460Z"
}]}`)
err := b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
pressXToJSON = []byte(`{"table":"position",
"action":"update",
"data":[{
"account":2,"symbol":"ETHUSD","currency":"XBt",
"deleveragePercentile":null,"rebalancedPnl":-2171150,"prevRealisedPnl":2172153,"execSellQty":2001,
"execSellCost":172394155,"execQty":0,"execCost":-2259128,"execComm":87978,
"currentTimestamp":"2017-04-04T22:16:38.547Z","currentQty":0,"currentCost":-2259128,
"currentComm":87978,"realisedCost":-2259128,"unrealisedCost":0,"grossExecCost":0,"isOpen":false,
"markPrice":null,"markValue":0,"riskValue":0,"homeNotional":0,"foreignNotional":0,"posState":"","posCost":0,
"posCost2":0,"posInit":0,"posComm":0,"posMargin":0,"posMaint":0,"maintMargin":0,"realisedGrossPnl":2259128,
"realisedPnl":2171150,"unrealisedGrossPnl":0,"unrealisedPnl":0,"unrealisedPnlPcnt":0,"unrealisedRoePcnt":0,
"simpleQty":0,"simpleCost":0,"simpleValue":0,"simplePnl":0,"simplePnlPcnt":0,"avgCostPrice":null,
"avgEntryPrice":null,"breakEvenPrice":null,"marginCallPrice":null,"liquidationPrice":null,"bankruptPrice":null,
"timestamp":"2017-04-04T22:16:38.547Z"
}]}`)
err = b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
}
func TestWSDeleverageExecutionInsertHandling(t *testing.T) {
pressXToJSON := []byte(`{"table":"execution",
"action":"insert",
"data":[{
"execID":"20ad1ff4-c110-a4f2-dd31-f94eaa0701fd",
"orderID":"00000000-0000-0000-0000-000000000000","clOrdID":"","clOrdLinkID":"","account":2,"symbol":"ETHUSD",
"side":"Sell","lastQty":2000,"lastPx":1160.72,"underlyingLastPx":null,"lastMkt":"XBME",
"lastLiquidityInd":"AddedLiquidity","simpleOrderQty":null,"orderQty":2000,"price":1160.72,"displayQty":null,
"stopPx":null,"pegOffsetValue":null,"pegPriceType":"","currency":"USD","settlCurrency":"XBt","execType":"Trade",
"ordType":"Limit","timeInForce":"GoodTillCancel","execInst":"","contingencyType":"","exDestination":"XBME",
"ordStatus":"Filled","triggered":"","workingIndicator":false,"ordRejReason":"",
"simpleLeavesQty":0,"leavesQty":0,"simpleCumQty":1.746,"cumQty":2000,"avgPx":1160.72,"commission":-0.00025,
"tradePublishIndicator":"PublishTrade","multiLegReportingType":"SingleSecurity","text":"Deleverage",
"trdMatchID":"1e849b8a-7e88-3c67-a93f-cc654d40e8ba","execCost":172306000,"execComm":-43077,
"homeNotional":-1.72306,"foreignNotional":2000,"transactTime":"2017-04-04T22:16:38.472Z",
"timestamp":"2017-04-04T22:16:38.472Z"
}]}`)
err := b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
}
func TestWsTrades(t *testing.T) {
pressXToJSON := []byte(`{"table":"trade","action":"insert","data":[{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.3,"tickDirection":"MinusTick","trdMatchID":"c427f7a0-6b26-1e10-5c4e-1bd74daf2a73","grossValue":2583000,"homeNotional":0.9904912836767037,"foreignNotional":255.84389857369254},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.3,"tickDirection":"ZeroMinusTick","trdMatchID":"95eb9155-b58c-70e9-44b7-34efe50302e0","grossValue":2583000,"homeNotional":0.9904912836767037,"foreignNotional":255.84389857369254},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.3,"tickDirection":"ZeroMinusTick","trdMatchID":"e607c187-f25c-86bc-cb39-8afff7aaf2d9","grossValue":2583000,"homeNotional":0.9904912836767037,"foreignNotional":255.84389857369254},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":17,"price":258.3,"tickDirection":"ZeroMinusTick","trdMatchID":"0f076814-a57d-9a59-8063-ad6b823a80ac","grossValue":439110,"homeNotional":0.1683835182250396,"foreignNotional":43.49346275752773},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.25,"tickDirection":"MinusTick","trdMatchID":"f4ef3dfd-51c4-538f-37c1-e5071ba1c75d","grossValue":2582500,"homeNotional":0.9904912836767037,"foreignNotional":255.79437400950872},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.25,"tickDirection":"ZeroMinusTick","trdMatchID":"81ef136b-8f4a-b1cf-78a8-fffbfa89bf40","grossValue":2582500,"homeNotional":0.9904912836767037,"foreignNotional":255.79437400950872},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.25,"tickDirection":"ZeroMinusTick","trdMatchID":"65a87e8c-7563-34a4-d040-94e8513c5401","grossValue":2582500,"homeNotional":0.9904912836767037,"foreignNotional":255.79437400950872},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":15,"price":258.25,"tickDirection":"ZeroMinusTick","trdMatchID":"1d11a74e-a157-3f33-036d-35a101fba50b","grossValue":387375,"homeNotional":0.14857369255150554,"foreignNotional":38.369156101426306},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":1,"price":258.25,"tickDirection":"ZeroMinusTick","trdMatchID":"40d49df1-f018-f66f-4ca5-31d4997641d7","grossValue":25825,"homeNotional":0.009904912836767036,"foreignNotional":2.5579437400950873},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.2,"tickDirection":"MinusTick","trdMatchID":"36135b51-73e5-c007-362b-a55be5830c6b","grossValue":2582000,"homeNotional":0.9904912836767037,"foreignNotional":255.7448494453249},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.2,"tickDirection":"ZeroMinusTick","trdMatchID":"6ee19edb-99aa-3030-ba63-933ffb347ade","grossValue":2582000,"homeNotional":0.9904912836767037,"foreignNotional":255.7448494453249},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.2,"tickDirection":"ZeroMinusTick","trdMatchID":"d44be603-cdb8-d676-e3e2-f91fb12b2a70","grossValue":2582000,"homeNotional":0.9904912836767037,"foreignNotional":255.7448494453249},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":5,"price":258.2,"tickDirection":"ZeroMinusTick","trdMatchID":"a14b43b3-50b4-c075-c54d-dfb0165de33d","grossValue":129100,"homeNotional":0.04952456418383518,"foreignNotional":12.787242472266245},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":8,"price":258.2,"tickDirection":"ZeroMinusTick","trdMatchID":"3c30e175-5194-320c-8f8c-01636c2f4a32","grossValue":206560,"homeNotional":0.07923930269413629,"foreignNotional":20.45958795562599},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":50,"price":258.2,"tickDirection":"ZeroMinusTick","trdMatchID":"5b803378-760b-4919-21fc-bfb275d39ace","grossValue":1291000,"homeNotional":0.49524564183835185,"foreignNotional":127.87242472266244},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":244,"price":258.2,"tickDirection":"ZeroMinusTick","trdMatchID":"cf57fec1-c444-b9e5-5e2d-4fb643f4fdb7","grossValue":6300080,"homeNotional":2.416798732171157,"foreignNotional":624.0174326465927}]}`)
err := b.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
}
}

View File

@@ -62,62 +62,62 @@ type ConnectedUsers struct {
// 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"`
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"`
DisplayQuantity 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 time.Time `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"`
FundingInterval string `json:"fundingInterval"`
FundingRate float64 `json:"fundingRate"`
FundingRateDaily float64 `json:"fundingRateDaily"`
Symbol string `json:"symbol"`
Timestamp time.Time `json:"timestamp"`
}
// Instrument Tradeable Contracts, Indices, and History
@@ -129,7 +129,7 @@ type Instrument struct {
BuyLeg string `json:"buyLeg"`
CalcInterval string `json:"calcInterval"`
Capped bool `json:"capped"`
ClosingTimestamp string `json:"closingTimestamp"`
ClosingTimestamp time.Time `json:"closingTimestamp"`
Deleverage bool `json:"deleverage"`
Expiry string `json:"expiry"`
FairBasis float64 `json:"fairBasis"`
@@ -142,7 +142,7 @@ type Instrument struct {
FundingPremiumSymbol string `json:"fundingPremiumSymbol"`
FundingQuoteSymbol string `json:"fundingQuoteSymbol"`
FundingRate float64 `json:"fundingRate"`
FundingTimestamp string `json:"fundingTimestamp"`
FundingTimestamp time.Time `json:"fundingTimestamp"`
HasLiquidity bool `json:"hasLiquidity"`
HighPrice float64 `json:"highPrice"`
ImpactAskPrice float64 `json:"impactAskPrice"`
@@ -176,7 +176,7 @@ type Instrument struct {
Multiplier int64 `json:"multiplier"`
OpenInterest int64 `json:"openInterest"`
OpenValue int64 `json:"openValue"`
OpeningTimestamp string `json:"openingTimestamp"`
OpeningTimestamp time.Time `json:"openingTimestamp"`
OptionMultiplier float64 `json:"optionMultiplier"`
OptionStrikePcnt float64 `json:"optionStrikePcnt"`
OptionStrikePrice float64 `json:"optionStrikePrice"`
@@ -192,7 +192,7 @@ type Instrument struct {
QuoteCurrency string `json:"quoteCurrency"`
QuoteToSettleMultiplier int64 `json:"quoteToSettleMultiplier"`
RebalanceInterval string `json:"rebalanceInterval"`
RebalanceTimestamp string `json:"rebalanceTimestamp"`
RebalanceTimestamp time.Time `json:"rebalanceTimestamp"`
Reference string `json:"reference"`
ReferenceSymbol string `json:"referenceSymbol"`
RelistInterval string `json:"relistInterval"`
@@ -233,20 +233,20 @@ type InstrumentInterval struct {
// 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"`
IndexSymbol string `json:"indexSymbol"`
LastPrice float64 `json:"lastPrice"`
Logged string `json:"logged"`
Reference string `json:"reference"`
Symbol string `json:"symbol"`
Timestamp time.Time `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"`
Currency string `json:"currency"`
Timestamp time.Time `json:"timestamp"`
WalletBalance int64 `json:"walletBalance"`
}
// Leaderboard Information on Top Users
@@ -286,39 +286,39 @@ type Notification struct {
// 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 int64 `json:"ordType,string"`
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 int64 `json:"side,string"`
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"`
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"`
DisplayQuantity 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 int64 `json:"ordType,string"`
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 int64 `json:"side,string"`
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 time.Time `json:"timestamp"`
TransactTime string `json:"transactTime"`
Triggered string `json:"triggered"`
WorkingIndicator bool `json:"workingIndicator"`
}
// OrderBookL2 contains order book l2
@@ -332,120 +332,120 @@ type OrderBookL2 struct {
// 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"`
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 time.Time `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 time.Time `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 time.Time `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"`
AskPrice float64 `json:"askPrice"`
AskSize int64 `json:"askSize"`
BidPrice float64 `json:"bidPrice"`
BidSize int64 `json:"bidSize"`
Symbol string `json:"symbol"`
Timestamp time.Time `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"`
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 time.Time `json:"timestamp"`
}
// Stats Exchange Statistics
@@ -479,16 +479,16 @@ type StatsUSD struct {
// 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"`
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 time.Time `json:"timestamp"`
TrdMatchID string `json:"trdMatchID"`
}
// User Account Operations
@@ -544,37 +544,37 @@ type UserPreferences struct {
// 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"`
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 time.Time `json:"prevTimestamp"`
PrevTurnover int64 `json:"prevTurnover"`
ReferrerAccount float64 `json:"referrerAccount"`
Timestamp time.Time `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"`
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 time.Time `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
@@ -595,47 +595,47 @@ type ConfirmEmail struct {
// 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"`
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 time.Time `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
@@ -647,31 +647,31 @@ type MinWithdrawalFee struct {
// 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"`
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 time.Time `json:"prevTimestamp"`
PrevTransferIn int64 `json:"prevTransferIn"`
PrevTransferOut int64 `json:"prevTransferOut"`
PrevWithdrawn int64 `json:"prevWithdrawn"`
Script string `json:"script"`
Timestamp time.Time `json:"timestamp"`
TransferIn int64 `json:"transferIn"`
TransferOut int64 `json:"transferOut"`
WithdrawalLock []string `json:"withdrawalLock"`
Withdrawn int64 `json:"withdrawn"`
}
// orderTypeMap holds order type info based on Bitmex data

View File

@@ -33,6 +33,7 @@ const (
bitmexWSInsurance = "insurance"
bitmexWSLiquidation = "liquidation"
bitmexWSOrderbookL2 = "orderBookL2"
bitmexWSOrderbookL225 = "orderBookL2_25"
bitmexWSOrderbookL10 = "orderBook10"
bitmexWSPublicNotifications = "publicNotifications"
bitmexWSQuote = "quote"
@@ -93,7 +94,7 @@ func (b *Bitmex) WsConnect() error {
welcomeResp.Limit.Remaining)
}
go b.wsHandleIncomingData()
go b.wsReadData()
b.GenerateDefaultSubscriptions()
err = b.websocketSendAuth()
if err != nil {
@@ -103,8 +104,8 @@ func (b *Bitmex) WsConnect() error {
return nil
}
// wsHandleIncomingData services incoming data from the websocket connection
func (b *Bitmex) wsHandleIncomingData() {
// wsReadData receives and passes on websocket messages for processing
func (b *Bitmex) wsReadData() {
b.Websocket.Wg.Add(1)
defer func() {
@@ -123,203 +124,348 @@ func (b *Bitmex) wsHandleIncomingData() {
return
}
b.Websocket.TrafficAlert <- struct{}{}
quickCapture := make(map[string]interface{})
err = json.Unmarshal(resp.Raw, &quickCapture)
err = b.wsHandleData(resp.Raw)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
var respError WebsocketErrorResponse
if _, ok := quickCapture["status"]; ok {
err = json.Unmarshal(resp.Raw, &respError)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
b.Websocket.DataHandler <- errors.New(respError.Error)
continue
}
if _, ok := quickCapture["success"]; ok {
var decodedResp WebsocketSubscribeResp
err := json.Unmarshal(resp.Raw, &decodedResp)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
if decodedResp.Success {
b.Websocket.DataHandler <- decodedResp
if len(quickCapture) == 3 {
if b.Verbose {
log.Debugf(log.ExchangeSys, "%s websocket: Successfully subscribed to %s",
b.Name, decodedResp.Subscribe)
}
} else {
b.Websocket.SetCanUseAuthenticatedEndpoints(true)
if b.Verbose {
log.Debugf(log.ExchangeSys, "%s websocket: Successfully authenticated websocket connection",
b.Name)
}
}
continue
}
b.Websocket.DataHandler <- fmt.Errorf("%s websocket error: Unable to subscribe %s",
b.Name, decodedResp.Subscribe)
} else if _, ok := quickCapture["table"]; ok {
var decodedResp WebsocketMainResponse
err := json.Unmarshal(resp.Raw, &decodedResp)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
switch decodedResp.Table {
case bitmexWSOrderbookL2:
var orderbooks OrderBookData
err = json.Unmarshal(resp.Raw, &orderbooks)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
p := currency.NewPairFromString(orderbooks.Data[0].Symbol)
var a asset.Item
a, err = b.GetPairAssetType(p)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
err = b.processOrderbook(orderbooks.Data,
orderbooks.Action,
p,
a)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
case bitmexWSTrade:
var trades TradeData
err = json.Unmarshal(resp.Raw, &trades)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
if trades.Action == bitmexActionInitialData {
continue
}
for i := range trades.Data {
var timestamp time.Time
timestamp, err = time.Parse(time.RFC3339, trades.Data[i].Timestamp)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
// TODO: update this to support multiple asset types
b.Websocket.DataHandler <- wshandler.TradeData{
Timestamp: timestamp,
Price: trades.Data[i].Price,
Amount: float64(trades.Data[i].Size),
CurrencyPair: currency.NewPairFromString(trades.Data[i].Symbol),
Exchange: b.Name,
AssetType: "CONTRACT",
Side: trades.Data[i].Side,
}
}
case bitmexWSAnnouncement:
var announcement AnnouncementData
err = json.Unmarshal(resp.Raw, &announcement)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
if announcement.Action == bitmexActionInitialData {
continue
}
b.Websocket.DataHandler <- announcement.Data
case bitmexWSAffiliate:
var response WsAffiliateResponse
err = json.Unmarshal(resp.Raw, &response)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
b.Websocket.DataHandler <- response
case bitmexWSExecution:
var response WsExecutionResponse
err = json.Unmarshal(resp.Raw, &response)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
b.Websocket.DataHandler <- response
case bitmexWSOrder:
var response WsOrderResponse
err = json.Unmarshal(resp.Raw, &response)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
b.Websocket.DataHandler <- response
case bitmexWSMargin:
var response WsMarginResponse
err = json.Unmarshal(resp.Raw, &response)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
b.Websocket.DataHandler <- response
case bitmexWSPosition:
var response WsPositionResponse
err = json.Unmarshal(resp.Raw, &response)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
b.Websocket.DataHandler <- response
case bitmexWSPrivateNotifications:
var response WsPrivateNotificationsResponse
err = json.Unmarshal(resp.Raw, &response)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
b.Websocket.DataHandler <- response
case bitmexWSTransact:
var response WsTransactResponse
err = json.Unmarshal(resp.Raw, &response)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
b.Websocket.DataHandler <- response
case bitmexWSWallet:
var response WsWalletResponse
err = json.Unmarshal(resp.Raw, &response)
if err != nil {
b.Websocket.DataHandler <- err
continue
}
b.Websocket.DataHandler <- response
default:
b.Websocket.DataHandler <- fmt.Errorf("%s websocket error: Table unknown - %s",
b.Name, decodedResp.Table)
}
}
}
}
}
func (b *Bitmex) wsHandleData(respRaw []byte) error {
quickCapture := make(map[string]interface{})
err := json.Unmarshal(respRaw, &quickCapture)
if err != nil {
return err
}
var respError WebsocketErrorResponse
if _, ok := quickCapture["status"]; ok {
err = json.Unmarshal(respRaw, &respError)
if err != nil {
return err
}
}
if _, ok := quickCapture["success"]; ok {
var decodedResp WebsocketSubscribeResp
err = json.Unmarshal(respRaw, &decodedResp)
if err != nil {
return err
}
if decodedResp.Success {
if len(quickCapture) == 3 {
if b.Verbose {
log.Debugf(log.ExchangeSys, "%s websocket: Successfully subscribed to %s",
b.Name, decodedResp.Subscribe)
}
} else {
b.Websocket.SetCanUseAuthenticatedEndpoints(true)
if b.Verbose {
log.Debugf(log.ExchangeSys, "%s websocket: Successfully authenticated websocket connection",
b.Name)
}
}
return nil
}
b.Websocket.DataHandler <- fmt.Errorf("%s websocket error: Unable to subscribe %s",
b.Name, decodedResp.Subscribe)
} else if _, ok := quickCapture["table"]; ok {
var decodedResp WebsocketMainResponse
err = json.Unmarshal(respRaw, &decodedResp)
if err != nil {
return err
}
switch decodedResp.Table {
case bitmexWSOrderbookL2, bitmexWSOrderbookL225, bitmexWSOrderbookL10:
var orderbooks OrderBookData
err = json.Unmarshal(respRaw, &orderbooks)
if err != nil {
return err
}
if len(orderbooks.Data) == 0 {
return fmt.Errorf("%s - Empty orderbook data received: %s", b.Name, respRaw)
}
p := currency.NewPairFromString(orderbooks.Data[0].Symbol)
var a asset.Item
a, err = b.GetPairAssetType(p)
if err != nil {
return err
}
err = b.processOrderbook(orderbooks.Data,
orderbooks.Action,
p,
a)
if err != nil {
return err
}
case bitmexWSTrade:
var trades TradeData
err = json.Unmarshal(respRaw, &trades)
if err != nil {
return err
}
if trades.Action == bitmexActionInitialData {
return nil
}
for i := range trades.Data {
var a asset.Item
p := currency.NewPairFromString(trades.Data[i].Symbol)
a, err = b.GetPairAssetType(p)
if err != nil {
return err
}
var oSide order.Side
oSide, err = order.StringToOrderSide(trades.Data[i].Side)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
Err: err,
}
}
b.Websocket.DataHandler <- wshandler.TradeData{
Timestamp: trades.Data[i].Timestamp,
Price: trades.Data[i].Price,
Amount: float64(trades.Data[i].Size),
CurrencyPair: p,
Exchange: b.Name,
AssetType: a,
Side: oSide,
}
}
case bitmexWSAnnouncement:
var announcement AnnouncementData
err = json.Unmarshal(respRaw, &announcement)
if err != nil {
return err
}
if announcement.Action == bitmexActionInitialData {
return nil
}
b.Websocket.DataHandler <- announcement.Data
case bitmexWSAffiliate:
var response WsAffiliateResponse
err = json.Unmarshal(respRaw, &response)
if err != nil {
return err
}
b.Websocket.DataHandler <- response
case bitmexWSInstrument:
// ticker
case bitmexWSExecution:
// trades of an order
var response WsExecutionResponse
err = json.Unmarshal(respRaw, &response)
if err != nil {
return err
}
for i := range response.Data {
p := currency.NewPairFromString(response.Data[i].Symbol)
var a asset.Item
a, err = b.GetPairAssetType(p)
if err != nil {
return err
}
var oStatus order.Status
oStatus, err = order.StringToOrderStatus(response.Data[i].OrdStatus)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
OrderID: response.Data[i].OrderID,
Err: err,
}
}
var oSide order.Side
oSide, err = order.StringToOrderSide(response.Data[i].Side)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
OrderID: response.Data[i].OrderID,
Err: err,
}
}
b.Websocket.DataHandler <- &order.Modify{
Exchange: b.Name,
ID: response.Data[i].OrderID,
AccountID: strconv.FormatInt(response.Data[i].Account, 10),
AssetType: a,
Pair: p,
Status: oStatus,
Trades: []order.TradeHistory{
{
Price: response.Data[i].Price,
Amount: response.Data[i].OrderQuantity,
Exchange: b.Name,
TID: response.Data[i].ExecID,
Side: oSide,
Timestamp: response.Data[i].Timestamp,
IsMaker: false,
},
},
}
}
case bitmexWSOrder:
var response WsOrderResponse
err = json.Unmarshal(respRaw, &response)
if err != nil {
return err
}
switch response.Action {
case "update", "insert":
for x := range response.Data {
var p currency.Pair
var a asset.Item
p, a, err = b.GetRequestFormattedPairAndAssetType(response.Data[x].Symbol)
if err != nil {
return err
}
var oSide order.Side
oSide, err = order.StringToOrderSide(response.Data[x].Side)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
OrderID: response.Data[x].OrderID,
Err: err,
}
}
var oType order.Type
oType, err = order.StringToOrderType(response.Data[x].OrderType)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
OrderID: response.Data[x].OrderID,
Err: err,
}
}
var oStatus order.Status
oStatus, err = order.StringToOrderStatus(response.Data[x].OrderStatus)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
OrderID: response.Data[x].OrderID,
Err: err,
}
}
b.Websocket.DataHandler <- &order.Detail{
Price: response.Data[x].Price,
Amount: response.Data[x].OrderQuantity,
Exchange: b.Name,
ID: response.Data[x].OrderID,
AccountID: strconv.FormatInt(response.Data[x].Account, 10),
Type: oType,
Side: oSide,
Status: oStatus,
AssetType: a,
Date: response.Data[x].TransactTime,
Pair: p,
}
}
case "delete":
for x := range response.Data {
var p currency.Pair
var a asset.Item
p, a, err = b.GetRequestFormattedPairAndAssetType(response.Data[x].Symbol)
if err != nil {
return err
}
var oSide order.Side
oSide, err = order.StringToOrderSide(response.Data[x].Side)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
OrderID: response.Data[x].OrderID,
Err: err,
}
}
var oType order.Type
oType, err = order.StringToOrderType(response.Data[x].OrderType)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
OrderID: response.Data[x].OrderID,
Err: err,
}
}
var oStatus order.Status
oStatus, err = order.StringToOrderStatus(response.Data[x].OrderStatus)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
OrderID: response.Data[x].OrderID,
Err: err,
}
}
b.Websocket.DataHandler <- &order.Cancel{
Price: response.Data[x].Price,
Amount: response.Data[x].OrderQuantity,
Exchange: b.Name,
ID: response.Data[x].OrderID,
AccountID: strconv.FormatInt(response.Data[x].Account, 10),
Type: oType,
Side: oSide,
Status: oStatus,
AssetType: a,
Date: response.Data[x].TransactTime,
Pair: p,
}
}
default:
b.Websocket.DataHandler <- fmt.Errorf("%s - Unsupported order update %+v", b.Name, response)
}
case bitmexWSMargin:
var response WsMarginResponse
err = json.Unmarshal(respRaw, &response)
if err != nil {
return err
}
b.Websocket.DataHandler <- response
case bitmexWSPosition:
var response WsPositionResponse
err = json.Unmarshal(respRaw, &response)
if err != nil {
return err
}
case bitmexWSPrivateNotifications:
var response WsPrivateNotificationsResponse
err = json.Unmarshal(respRaw, &response)
if err != nil {
return err
}
b.Websocket.DataHandler <- response
case bitmexWSTransact:
var response WsTransactResponse
err = json.Unmarshal(respRaw, &response)
if err != nil {
return err
}
b.Websocket.DataHandler <- response
case bitmexWSWallet:
var response WsWalletResponse
err = json.Unmarshal(respRaw, &response)
if err != nil {
return err
}
b.Websocket.DataHandler <- response
default:
b.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: b.Name + wshandler.UnhandledMessage + string(respRaw)}
return nil
}
}
return nil
}
// ProcessOrderbook processes orderbook updates
func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, currencyPair currency.Pair, assetType asset.Item) error { // nolint: unparam
if len(data) < 1 {

View File

@@ -1,5 +1,7 @@
package bitmex
import "time"
// WebsocketRequest is the main request type
type WebsocketRequest struct {
Command string `json:"op"`
@@ -8,7 +10,7 @@ type WebsocketRequest struct {
// WebsocketErrorResponse main error response
type WebsocketErrorResponse struct {
Status int `json:"status"`
Status int64 `json:"status"`
Error string `json:"error"`
Meta interface{} `json:"meta"`
Request WebsocketRequest `json:"request"`
@@ -51,6 +53,7 @@ type WebsocketMainResponse struct {
ID string `json:"id"`
Symbol string `json:"symbol"`
} `json:"Attributes"`
Action string `json:"action,omitempty"`
}
// OrderBookData contains orderbook resp data with action to be taken
@@ -97,7 +100,58 @@ type WsOrderResponse struct {
ForeignKeys WsOrderResponseForeignKeys `json:"foreignKeys"`
Attributes WsOrderResponseAttributes `json:"attributes"`
Filter WsOrderResponseFilter `json:"filter"`
Data []interface{} `json:"data"`
Data []OrderInsertData `json:"data"`
}
// OrderInsertData holds order data from an order response
type OrderInsertData struct {
WorkingIndicator bool `json:"workingIndicator"`
Account int64 `json:"account"`
AveragePrice float64 `json:"avgPx"`
Commission float64 `json:"commission"`
FilledQuantity float64 `json:"cumQty"`
DisplayQuantity float64 `json:"displayQty"`
ExecComm float64 `json:"execComm"`
ExecCost float64 `json:"execCost"`
ForeignNotional float64 `json:"foreignNotional"`
HomeNotional float64 `json:"homeNotional"`
LastPrice float64 `json:"lastPx"`
LastQuantity float64 `json:"lastQty"`
LeavesQuantity float64 `json:"leavesQty"`
OrderQuantity float64 `json:"orderQty"`
PegOffsetValue float64 `json:"pegOffsetValue"`
Price float64 `json:"price"`
SimpleFilledQuantity float64 `json:"simpleCumQty"`
SimpleLeavesQuantity float64 `json:"simpleLeavesQty"`
SimpleOrderQuantity float64 `json:"simpleOrderQty"`
StopPrice float64 `json:"stopPx"`
ExDestination string `json:"exDestination"`
ContingencyType string `json:"contingencyType"`
Currency string `json:"currency"`
ExecutionID string `json:"execID"`
ExecutionInstance string `json:"execInst"`
ExecutionType string `json:"execType"`
LastLiquidityInd string `json:"lastLiquidityInd"`
LastMkt string `json:"lastMkt"`
UnderlyingLastPrice float64 `json:"underlyingLastPx"`
MultiLegReportingType string `json:"multiLegReportingType"`
OrderRejectedReason string `json:"ordRejReason"`
OrderStatus string `json:"ordStatus"`
OrderType string `json:"ordType"`
OrderID string `json:"orderID"`
PegPriceType string `json:"pegPriceType"`
ClientOrderID string `json:"clOrdID"`
ClientOrderLinkID string `json:"clOrdLinkID"`
Symbol string `json:"symbol"`
Text string `json:"text"`
TimeInForce string `json:"timeInForce"`
Timestamp time.Time `json:"timestamp"`
TradePublishIndicator string `json:"tradePublishIndicator"`
TransactTime time.Time `json:"transactTime"`
TradingMatchID string `json:"trdMatchID"`
Triggered string `json:"triggered"`
SettleCurrency string `json:"settlCurrency"`
Side string `json:"side"`
}
// WsOrderResponseAttributes private api data
@@ -195,7 +249,57 @@ type WsExecutionResponse struct {
ForeignKeys WsExecutionResponseForeignKeys `json:"foreignKeys"`
Attributes WsExecutionResponseAttributes `json:"attributes"`
Filter WsExecutionResponseFilter `json:"filter"`
Data []interface{} `json:"data"`
Data []wsExecutionData `json:"data"`
}
type wsExecutionData struct {
WorkingIndicator bool `json:"workingIndicator"`
Account int64 `json:"account"`
AvgPx float64 `json:"avgPx"`
Commission float64 `json:"commission"`
FilledQuantity float64 `json:"cumQty"`
DisplayQuantity float64 `json:"displayQty"`
ExecComm float64 `json:"execComm"`
ExecCost float64 `json:"execCost"`
ForeignNotional float64 `json:"foreignNotional"`
HomeNotional float64 `json:"homeNotional"`
LastPx float64 `json:"lastPx"`
LastQuantity float64 `json:"lastQty"`
LeavesQuantity float64 `json:"leavesQty"`
OrderQuantity float64 `json:"orderQty"`
PegOffsetValue float64 `json:"pegOffsetValue"`
Price float64 `json:"price"`
SimpleFilledQuantity float64 `json:"simpleCumQty"`
SimpleLeavesQuantity float64 `json:"simpleLeavesQty"`
SimpleOrderQuantity float64 `json:"simpleOrderQty"`
StopPx float64 `json:"stopPx"`
UnderlyingLastPx float64 `json:"underlyingLastPx"`
PegPriceType string `json:"pegPriceType"`
Symbol string `json:"symbol"`
Text string `json:"text"`
TimeInForce string `json:"timeInForce"`
Timestamp time.Time `json:"timestamp"`
TradePublishIndicator string `json:"tradePublishIndicator"`
TransactTime time.Time `json:"transactTime"`
TrdMatchID string `json:"trdMatchID"`
Triggered string `json:"triggered"`
ClOrdID string `json:"clOrdID"`
ClOrdLinkID string `json:"clOrdLinkID"`
SettlCurrency string `json:"settlCurrency"`
Side string `json:"side"`
MultiLegReportingType string `json:"multiLegReportingType"`
OrdRejReason string `json:"ordRejReason"`
OrdStatus string `json:"ordStatus"`
OrdType string `json:"ordType"`
OrderID string `json:"orderID"`
LastLiquidityInd string `json:"lastLiquidityInd"`
LastMkt string `json:"lastMkt"`
ExecID string `json:"execID"`
ExecInst string `json:"execInst"`
ExecType string `json:"execType"`
ExDestination string `json:"exDestination"`
Currency string `json:"currency"`
ContingencyType string `json:"contingencyType"`
}
// WsExecutionResponseAttributes private api data
@@ -282,7 +386,7 @@ type WsMarginResponseData struct {
ExcessMarginPcnt float64 `json:"excessMarginPcnt"`
AvailableMargin float64 `json:"availableMargin"`
WithdrawableMargin float64 `json:"withdrawableMargin"`
Timestamp string `json:"timestamp"`
Timestamp time.Time `json:"timestamp"`
GrossLastValue float64 `json:"grossLastValue"`
Commission interface{} `json:"commission"`
}
@@ -298,7 +402,58 @@ type WsPositionResponse struct {
ForeignKeys WsPositionResponseForeignKeys `json:"foreignKeys"`
Attributes WsPositionResponseAttributes `json:"attributes"`
Filter WsPositionResponseFilter `json:"filter"`
Data []interface{} `json:"data"`
Data []wsPositionData `json:"data"`
}
type wsPositionData struct {
IsOpen bool `json:"isOpen"`
Account int64 `json:"account"`
CurrentQuantity float64 `json:"currentQty"`
HomeNotional float64 `json:"homeNotional"`
LiquidationPrice float64 `json:"liquidationPrice"`
MaintMargin float64 `json:"maintMargin"`
MarkPrice float64 `json:"markPrice"`
MarkValue float64 `json:"markValue"`
RiskValue float64 `json:"riskValue"`
SimpleQuantity float64 `json:"simpleQty"`
UnrealisedGrossPnl float64 `json:"unrealisedGrossPnl"`
UnrealisedPnl float64 `json:"unrealisedPnl"`
UnrealisedPnlPcnt float64 `json:"unrealisedPnlPcnt"`
UnrealisedRoePcnt float64 `json:"unrealisedRoePcnt"`
BankruptPrice float64 `json:"bankruptPrice"`
AvgCostPrice float64 `json:"avgCostPrice"`
AvgEntryPrice float64 `json:"avgEntryPrice"`
BreakEvenPrice float64 `json:"breakEvenPrice"`
CurrentComm float64 `json:"currentComm"`
CurrentCost float64 `json:"currentCost"`
DeleveragePercentile float64 `json:"deleveragePercentile"`
ExecComm float64 `json:"execComm"`
ExecCost float64 `json:"execCost"`
ExecQuantity float64 `json:"execQty"`
ExecSellCost float64 `json:"execSellCost"`
ExecSellQuantity float64 `json:"execSellQty"`
ForeignNotional float64 `json:"foreignNotional"`
GrossExecCost float64 `json:"grossExecCost"`
MarginCallPrice float64 `json:"marginCallPrice"`
PosComm float64 `json:"posComm"`
PosCost float64 `json:"posCost"`
PosCost2 float64 `json:"posCost2"`
PosInit float64 `json:"posInit"`
PosMaint float64 `json:"posMaint"`
PosMargin float64 `json:"posMargin"`
PrevRealisedPnl float64 `json:"prevRealisedPnl"`
RealisedCost float64 `json:"realisedCost"`
RealisedGrossPnl float64 `json:"realisedGrossPnl"`
RealisedPnl float64 `json:"realisedPnl"`
RebalancedPnl float64 `json:"rebalancedPnl"`
SimpleCost float64 `json:"simpleCost"`
SimpleValue float64 `json:"simpleValue"`
UnrealisedCost float64 `json:"unrealisedCost"`
Currency string `json:"currency"`
CurrentTimestamp time.Time `json:"currentTimestamp"`
Symbol string `json:"symbol"`
Timestamp time.Time `json:"timestamp"`
PosState string `json:"posState"`
}
// WsPositionResponseAttributes private api data

View File

@@ -122,6 +122,8 @@ func (b *Bitmex) SetDefaults() {
AuthenticatedEndpoints: true,
AccountInfo: true,
DeadMansSwitch: true,
GetOrders: true,
GetOrder: true,
},
WithdrawPermissions: exchange.AutoWithdrawCryptoWithAPIPermission |
exchange.WithdrawCryptoWithEmail |
@@ -222,7 +224,7 @@ func (b *Bitmex) Run() {
}
// FetchTradablePairs returns a list of the exchanges tradable pairs
func (b *Bitmex) FetchTradablePairs(asset asset.Item) ([]string, error) {
func (b *Bitmex) FetchTradablePairs(_ asset.Item) ([]string, error) {
marketInfo, err := b.GetActiveInstruments(&GenericRequestParams{})
if err != nil {
return nil, err
@@ -435,13 +437,13 @@ func (b *Bitmex) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
}
var orderNewParams = OrderNewParams{
OrdType: s.OrderSide.String(),
Symbol: s.Pair.String(),
OrderQty: s.Amount,
Side: s.OrderSide.String(),
OrderType: s.Side.String(),
Symbol: s.Pair.String(),
OrderQuantity: s.Amount,
Side: s.Side.String(),
}
if s.OrderType == order.Limit {
if s.Type == order.Limit {
orderNewParams.Price = s.Price
}
@@ -452,7 +454,7 @@ func (b *Bitmex) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
if response.OrderID != "" {
submitOrderResponse.OrderID = response.OrderID
}
if s.OrderType == order.Market {
if s.Type == order.Market {
submitOrderResponse.FullyMatched = true
}
submitOrderResponse.IsOrderPlaced = true
@@ -469,7 +471,7 @@ func (b *Bitmex) ModifyOrder(action *order.Modify) (string, error) {
return "", errors.New("contract amount can not have decimals")
}
params.OrderID = action.OrderID
params.OrderID = action.ID
params.OrderQty = int32(action.Amount)
params.Price = action.Price
@@ -484,7 +486,7 @@ func (b *Bitmex) ModifyOrder(action *order.Modify) (string, error) {
// CancelOrder cancels an order by its corresponding ID number
func (b *Bitmex) CancelOrder(order *order.Cancel) error {
var params = OrderCancelParams{
OrderID: order.OrderID,
OrderID: order.ID,
}
_, err := b.CancelOrders(&params)
return err
@@ -587,18 +589,18 @@ func (b *Bitmex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
orderSide := orderSideMap[resp[i].Side]
orderType := orderTypeMap[resp[i].OrdType]
if orderType == "" {
orderType = order.Unknown
orderType = order.UnknownType
}
orderDetail := order.Detail{
Price: resp[i].Price,
Amount: float64(resp[i].OrderQty),
Exchange: b.Name,
ID: resp[i].OrderID,
OrderSide: orderSide,
OrderType: orderType,
Status: order.Status(resp[i].OrdStatus),
CurrencyPair: currency.NewPairWithDelimiter(resp[i].Symbol,
Price: resp[i].Price,
Amount: float64(resp[i].OrderQty),
Exchange: b.Name,
ID: resp[i].OrderID,
Side: orderSide,
Type: orderType,
Status: order.Status(resp[i].OrdStatus),
Pair: currency.NewPairWithDelimiter(resp[i].Symbol,
resp[i].SettlCurrency,
b.GetPairFormat(asset.PerpetualContract, false).Delimiter),
}
@@ -606,10 +608,10 @@ func (b *Bitmex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
orders = append(orders, orderDetail)
}
order.FilterOrdersBySide(&orders, req.OrderSide)
order.FilterOrdersByType(&orders, req.OrderType)
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByCurrencies(&orders, req.Currencies)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil
}
@@ -628,18 +630,18 @@ func (b *Bitmex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
orderSide := orderSideMap[resp[i].Side]
orderType := orderTypeMap[resp[i].OrdType]
if orderType == "" {
orderType = order.Unknown
orderType = order.UnknownType
}
orderDetail := order.Detail{
Price: resp[i].Price,
Amount: float64(resp[i].OrderQty),
Exchange: b.Name,
ID: resp[i].OrderID,
OrderSide: orderSide,
OrderType: orderType,
Status: order.Status(resp[i].OrdStatus),
CurrencyPair: currency.NewPairWithDelimiter(resp[i].Symbol,
Price: resp[i].Price,
Amount: float64(resp[i].OrderQty),
Exchange: b.Name,
ID: resp[i].OrderID,
Side: orderSide,
Type: orderType,
Status: order.Status(resp[i].OrdStatus),
Pair: currency.NewPairWithDelimiter(resp[i].Symbol,
resp[i].SettlCurrency,
b.GetPairFormat(asset.PerpetualContract, false).Delimiter),
}
@@ -647,10 +649,10 @@ func (b *Bitmex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
orders = append(orders, orderDetail)
}
order.FilterOrdersBySide(&orders, req.OrderSide)
order.FilterOrdersByType(&orders, req.OrderType)
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByCurrencies(&orders, req.Currencies)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil
}