mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
engine: Ticker REST/Websocket improvements (#345)
* Adds extra properties to Websocket ticker. Adds new properties to binance and bitfinex, but doesn't test anything yet. Changes names and properties of ticker package to make more streamlined * Adds support for coinbasepro, coinut, gateio, gitbtc, huobi, hadax, kraken, okex, okcoin. Adds quoteVolume * Adds poloniex and ZB ticker datas * Updates ANX, Binance, Bitfinex, Bistamp, Bittrex, BTCMarkets, BTSE, CoinbasePRo, Coinut, Exmo tickers. It looks like a whole bunch of stuff is wrong in how tickers are done though :/ * Updates tickers everywhere. Will revert batch ones * Re-Preseves ticker batching * Minor fixes to ticks and removal of comment * Logging errors instead of returning mid loop. Adds bitfinex batch ticker processing. Fixes unrelated okgroup wallet bug * Removes bad code I wrote preventing function from running if feature not enabled * Fixes issue with bitmex and rebase issues * Fixes bitmex iterator error, splits hitbtc ticker requests * Fixes okgroup currency pair formatting. Updates okgroup to use ticker batching. Fixes okgroup ticker issues due to assetTypes. Fixes okgroup ws pinging. Fixes Kraken's currency pairs formatting. Reverts ANXs auto parsing back to strings because ANX json makes me cry. Minor property improvements for coinut, coinbasepro, btse, exmo. Protects wshandler manageSubscriptions() from running and returning an error when feature not supported * Updates config example to reflect the underscore dash situation * Fixes a config delimiter oopsie. Simplifies ANX wrapper ticker parsing. Fixes bittrex date parsing. Simplifies okcoin switch to if. * Fixes super fun issue where kraken has updated their currency pair format and must add new delimiter support. Fixes super fun issue where okex has updated their currency pair format and must add new delimiter support. Fixes super fun issue where okcoin has updated their currency pair format and must add new delimiter support. * Updates config example for kraken * Adds lbank batch ticker support. Adds details to errors * Updates FetchTradablePairs to use the config delimiter to prevent issues if the delimiter ever changes * Fixes nil reference bug. Uses NAme not GetNAme * Fixes hardcoded delimiter in Binance. Expands bitfinex websocket ticker fields. Updates Bitstamp rate limits. Expands BTSE ticker data fields. Fixes typo in coibasepro. Expands Coinut ticker data. Renames currency to curr as it conflicts with package name. Expands GateIO websocket ticker data. Fixes ticker data implementation for huobi and huobi hadax. Reverts ticker map to string instead of assetType. Fixes real stupid bug I introduced which preveted subscriptions from running :glitch_crab: Adds Price ATH to ws ticker type. Adds quotevolume to yobit ticker. Uses delimiter in ZB rather than hardcoded field. * Fixes bug in syncer where if the websocket is already connected, then UsingWebsocket is not set * Updates broken tests * Simplifies poloniex frozen check * Updates configtest.json with new delimiters * Renames shorthand properties of structs. Fixes delimiter referencing * Fixes some bugs and nits around variable declaration, currency pairs and config upscaling * Adds config upgrade path for okcoin and okex. Reverts configtest.json. * Fixes okex futures currency formatting by no longer using global currency format. updates Run code to adapt. Removes BTSE value * Adds ":" as a delimiter for when a delimiter only shows up SOMETIMES * Adds support for optional delimiter
This commit is contained in:
@@ -1211,18 +1211,18 @@
|
||||
"apiUrlSecondary": "NON_DEFAULT_HTTP_LINK_TO_EXCHANGE_API",
|
||||
"proxyAddress": "",
|
||||
"websocketUrl": "NON_DEFAULT_HTTP_LINK_TO_WEBSOCKET_EXCHANGE_API",
|
||||
"availablePairs": "BTC_USD,LTC_USD,ETH_USD,ETC_USD,TUSD_USD,USDT_USD,ZEC_USD,ADA_USD,XLM_USD,ZRX_USD,XRP_USD,BAT_USD,PAX_USD,GUSD_USD,USDC_USD,BCH_USD,BSV_USD,TRX_USD,GRIN_USD,DCR_USD,EOS_USD,BTC_TUSD,BTC_USDT,BTC_PAX,BTC_GUSD,BTC_USDC",
|
||||
"enabledPairs": "BTC_USD",
|
||||
"availablePairs": "BTC-USD,LTC-USD,ETH-USD,ETC-USD,TUSD-USD,USDT-USD,ZEC-USD,ADA-USD,XLM-USD,ZRX-USD,XRP-USD,BAT-USD,PAX-USD,GUSD-USD,USDC-USD,BCH-USD,BSV-USD,TRX-USD,GRIN-USD,DCR-USD,EOS-USD,BTC-TUSD,BTC-USDT,BTC-PAX,BTC-GUSD,BTC-USDC",
|
||||
"enabledPairs": "BTC-USD",
|
||||
"baseCurrencies": "USD",
|
||||
"assetTypes": "SPOT",
|
||||
"supportsAutoPairUpdates": true,
|
||||
"configCurrencyPairFormat": {
|
||||
"uppercase": true,
|
||||
"delimiter": "_"
|
||||
"delimiter": "-"
|
||||
},
|
||||
"requestCurrencyPairFormat": {
|
||||
"uppercase": false,
|
||||
"delimiter": "_"
|
||||
"uppercase": true,
|
||||
"delimiter": "-"
|
||||
},
|
||||
"bankAccounts": [
|
||||
{
|
||||
@@ -1256,18 +1256,18 @@
|
||||
"apiUrlSecondary": "NON_DEFAULT_HTTP_LINK_TO_EXCHANGE_API",
|
||||
"proxyAddress": "",
|
||||
"websocketUrl": "NON_DEFAULT_HTTP_LINK_TO_WEBSOCKET_EXCHANGE_API",
|
||||
"availablePairs": "DASH_BTC,CTXC_BTC,ZIL_BTC,YOU_BTC,LBA_BTC,LSK_BTC,CAI_BTC,AE_BTC,SC_BTC,KAN_BTC,WIN_BTC,DCR_BTC,WAVES_BTC,ORS_BTC,NXT_BTC,ARDR_BTC,XAS_BTC,CVT_BTC,EGT_BTC,ZCO_BTC,LET_BTC,HPB_BTC,ADA_BTC,HYC_BTC,VITE_BTC,ABL_BTC,PAX_BTC,TUSD_BTC,USDC_BTC,GUSD_BTC,BCH_BTC,BSV_BTC,BTT_BTC,ATOM_BTC,BLOC_BTC,XRP_BTC,LRC_BTC,NULS_BTC,MCO_BTC,ELF_BTC,ZEC_BTC,CMT_BTC,ITC_BTC,SBTC_BTC,EDO_BTC,BCX_BTC,NEO_BTC,GAS_BTC,HC_BTC,QTUM_BTC,IOTA_BTC,XUC_BTC,EOS_BTC,SNT_BTC,OMG_BTC,LTC_BTC,ETH_BTC,ETC_BTC,BCD_BTC,BTG_BTC,ACT_BTC,PAY_BTC,BTM_BTC,DGD_BTC,GNT_BTC,LINK_BTC,WTC_BTC,ZRX_BTC,BNT_BTC,CVC_BTC,MANA_BTC,KNC_BTC,GNX_BTC,ICX_BTC,XEM_BTC,ARK_BTC,YOYO_BTC,FUN_BTC,ACE_BTC,TRX_BTC,DGB_BTC,SWFTC_BTC,XMR_BTC,XLM_BTC,KCASH_BTC,MDT_BTC,NAS_BTC,UGC_BTC,DPY_BTC,SSC_BTC,AAC_BTC,VIB_BTC,QUN_BTC,INT_BTC,IOST_BTC,INS_BTC,MOF_BTC,TCT_BTC,STC_BTC,THETA_BTC,PST_BTC,SNC_BTC,MKR_BTC,LIGHT_BTC,TRUE_BTC,OF_BTC,SOC_BTC,ZEN_BTC,HMC_BTC,ZIP_BTC,NANO_BTC,CIC_BTC,GTO_BTC,CHAT_BTC,INSUR_BTC,R_BTC,BEC_BTC,MITH_BTC,ABT_BTC,BKX_BTC,RFR_BTC,TRIO_BTC,DADI_BTC,ONT_BTC,OKB_BTC,CTXC_ETH,ZIL_ETH,YOU_ETH,LBA_ETH,LSK_ETH,CAI_ETH,SC_ETH,AE_ETH,KAN_ETH,WIN_ETH,DCR_ETH,WAVES_ETH,ORS_ETH,MVP_ETH,EGT_ETH,ZCO_ETH,LET_ETH,HPB_ETH,SDA_ETH,ADA_ETH,HYC_ETH,VITE_ETH,ABL_ETH,BTT_ETH,ATOM_ETH,ELF_ETH,LTC_ETH,CMT_ETH,ITC_ETH,PRA_ETH,EDO_ETH,LRC_ETH,NULS_ETH,MCO_ETH,STORJ_ETH,SNT_ETH,PAY_ETH,DGD_ETH,GNT_ETH,ACT_ETH,BTM_ETH,EOS_ETH,OMG_ETH,DASH_ETH,XRP_ETH,ZEC_ETH,NEO_ETH,GAS_ETH,HC_ETH,QTUM_ETH,IOTA_ETH,XUC_ETH,ETC_ETH,LINK_ETH,WTC_ETH,ZRX_ETH,BNT_ETH,CVC_ETH,MANA_ETH,GNX_ETH,ICX_ETH,XEM_ETH,ARK_ETH,YOYO_ETH,TRX_ETH,DGB_ETH,PPT_ETH,SWFTC_ETH,XMR_ETH,XLM_ETH,KCASH_ETH,MDT_ETH,NAS_ETH,RNT_ETH,UGC_ETH,DPY_ETH,SSC_ETH,AAC_ETH,FAIR_ETH,RCT_ETH,VIB_ETH,TOPC_ETH,QUN_ETH,INT_ETH,IOST_ETH,INS_ETH,MOF_ETH,REF_ETH,THETA_ETH,PST_ETH,SNC_ETH,MKR_ETH,LIGHT_ETH,TRUE_ETH,OF_ETH,SOC_ETH,ZEN_ETH,HMC_ETH,ZIP_ETH,NANO_ETH,CIC_ETH,GTO_ETH,INSUR_ETH,R_ETH,UCT_ETH,BEC_ETH,MITH_ETH,ABT_ETH,BKX_ETH,AUTO_ETH,RFR_ETH,TRIO_ETH,TRA_ETH,DADI_ETH,ONT_ETH,OKB_ETH,CTXC_USDT,ZIL_USDT,YOU_OKB,YOU_USDT,LBA_OKB,LBA_USDT,CAI_OKB,LSK_USDT,CAI_USDT,AE_OKB,SC_OKB,KAN_OKB,WIN_OKB,SC_USDT,AE_USDT,KAN_USDT,WIN_USDT,ORS_OKB,DCR_OKB,DCR_USDT,WAVES_OKB,WAVES_USDT,ORS_USDT,MVP_USDT,NAS_OKB,XAS_OKB,ZCO_OKB,EGT_OKB,XAS_USDT,CVT_USDT,EGT_USDT,LET_OKB,LET_USDT,HPB_OKB,HPB_USDT,SDA_OKB,ADA_OKB,ADA_USDT,HYC_USDT,VITE_OKB,TRX_OKB,PAX_USDT,TUSD_USDT,USDC_USDT,GUSD_USDT,BCH_USDT,BSV_USDT,BTT_USDT,BLOC_OKB,BLOC_USDT,ATOM_USDT,ELF_USDT,DASH_USDT,LRC_USDT,NULS_USDT,MCO_USDT,BTG_USDT,DASH_OKB,XRP_USDT,ZEC_USDT,NEO_USDT,GAS_USDT,HC_USDT,QTUM_USDT,IOTA_USDT,BTC_USDT,BCD_USDT,XUC_USDT,CMT_USDT,ITC_USDT,PRA_USDT,EDO_USDT,ETH_USDT,LTC_USDT,ETC_USDT,EOS_USDT,OMG_USDT,ACT_USDT,BTM_USDT,STORJ_USDT,PAY_USDT,DGD_USDT,GNT_USDT,SNT_USDT,LINK_USDT,WTC_USDT,ZRX_USDT,BNT_USDT,CVC_USDT,MANA_USDT,KNC_USDT,ICX_USDT,XEM_USDT,ARK_USDT,YOYO_USDT,AST_USDT,TRX_USDT,MDA_USDT,DGB_USDT,PPT_USDT,SWFTC_USDT,XMR_USDT,XLM_USDT,KCASH_USDT,MDT_USDT,NAS_USDT,RNT_USDT,UGC_USDT,DPY_USDT,SSC_USDT,AAC_USDT,FAIR_USDT,UBTC_USDT,SHOW_USDT,VIB_USDT,MOT_USDT,UTK_USDT,TOPC_USDT,QUN_USDT,INT_USDT,IPC_USDT,IOST_USDT,INS_USDT,YEE_USDT,MOF_USDT,TCT_USDT,STC_USDT,THETA_USDT,PST_USDT,MKR_USDT,LIGHT_USDT,TRUE_USDT,OF_USDT,SOC_USDT,ZEN_USDT,HMC_USDT,ZIP_USDT,NANO_USDT,CIC_USDT,GTO_USDT,CHAT_USDT,INSUR_USDT,R_USDT,BEC_USDT,MITH_USDT,ABT_USDT,BKX_USDT,RFR_USDT,TRIO_USDT,DADI_USDT,ONT_USDT,OKB_USDT,NEO_OKB,LTC_OKB,ETC_OKB,XRP_OKB,ZEC_OKB,QTUM_OKB,IOTA_OKB,EOS_OKB",
|
||||
"enabledPairs": "eos_usdt",
|
||||
"availablePairs": "DASH-BTC,CTXC-BTC,ZIL-BTC,YOU-BTC,LBA-BTC,LSK-BTC,CAI-BTC,AE-BTC,SC-BTC,KAN-BTC,WIN-BTC,DCR-BTC,WAVES-BTC,ORS-BTC,NXT-BTC,ARDR-BTC,XAS-BTC,CVT-BTC,EGT-BTC,ZCO-BTC,LET-BTC,HPB-BTC,ADA-BTC,HYC-BTC,VITE-BTC,ABL-BTC,PAX-BTC,TUSD-BTC,USDC-BTC,GUSD-BTC,BCH-BTC,BSV-BTC,BTT-BTC,ATOM-BTC,BLOC-BTC,XRP-BTC,LRC-BTC,NULS-BTC,MCO-BTC,ELF-BTC,ZEC-BTC,CMT-BTC,ITC-BTC,SBTC-BTC,EDO-BTC,BCX-BTC,NEO-BTC,GAS-BTC,HC-BTC,QTUM-BTC,IOTA-BTC,XUC-BTC,EOS-BTC,SNT-BTC,OMG-BTC,LTC-BTC,ETH-BTC,ETC-BTC,BCD-BTC,BTG-BTC,ACT-BTC,PAY-BTC,BTM-BTC,DGD-BTC,GNT-BTC,LINK-BTC,WTC-BTC,ZRX-BTC,BNT-BTC,CVC-BTC,MANA-BTC,KNC-BTC,GNX-BTC,ICX-BTC,XEM-BTC,ARK-BTC,YOYO-BTC,FUN-BTC,ACE-BTC,TRX-BTC,DGB-BTC,SWFTC-BTC,XMR-BTC,XLM-BTC,KCASH-BTC,MDT-BTC,NAS-BTC,UGC-BTC,DPY-BTC,SSC-BTC,AAC-BTC,VIB-BTC,QUN-BTC,INT-BTC,IOST-BTC,INS-BTC,MOF-BTC,TCT-BTC,STC-BTC,THETA-BTC,PST-BTC,SNC-BTC,MKR-BTC,LIGHT-BTC,TRUE-BTC,OF-BTC,SOC-BTC,ZEN-BTC,HMC-BTC,ZIP-BTC,NANO-BTC,CIC-BTC,GTO-BTC,CHAT-BTC,INSUR-BTC,R-BTC,BEC-BTC,MITH-BTC,ABT-BTC,BKX-BTC,RFR-BTC,TRIO-BTC,DADI-BTC,ONT-BTC,OKB-BTC,CTXC-ETH,ZIL-ETH,YOU-ETH,LBA-ETH,LSK-ETH,CAI-ETH,SC-ETH,AE-ETH,KAN-ETH,WIN-ETH,DCR-ETH,WAVES-ETH,ORS-ETH,MVP-ETH,EGT-ETH,ZCO-ETH,LET-ETH,HPB-ETH,SDA-ETH,ADA-ETH,HYC-ETH,VITE-ETH,ABL-ETH,BTT-ETH,ATOM-ETH,ELF-ETH,LTC-ETH,CMT-ETH,ITC-ETH,PRA-ETH,EDO-ETH,LRC-ETH,NULS-ETH,MCO-ETH,STORJ-ETH,SNT-ETH,PAY-ETH,DGD-ETH,GNT-ETH,ACT-ETH,BTM-ETH,EOS-ETH,OMG-ETH,DASH-ETH,XRP-ETH,ZEC-ETH,NEO-ETH,GAS-ETH,HC-ETH,QTUM-ETH,IOTA-ETH,XUC-ETH,ETC-ETH,LINK-ETH,WTC-ETH,ZRX-ETH,BNT-ETH,CVC-ETH,MANA-ETH,GNX-ETH,ICX-ETH,XEM-ETH,ARK-ETH,YOYO-ETH,TRX-ETH,DGB-ETH,PPT-ETH,SWFTC-ETH,XMR-ETH,XLM-ETH,KCASH-ETH,MDT-ETH,NAS-ETH,RNT-ETH,UGC-ETH,DPY-ETH,SSC-ETH,AAC-ETH,FAIR-ETH,RCT-ETH,VIB-ETH,TOPC-ETH,QUN-ETH,INT-ETH,IOST-ETH,INS-ETH,MOF-ETH,REF-ETH,THETA-ETH,PST-ETH,SNC-ETH,MKR-ETH,LIGHT-ETH,TRUE-ETH,OF-ETH,SOC-ETH,ZEN-ETH,HMC-ETH,ZIP-ETH,NANO-ETH,CIC-ETH,GTO-ETH,INSUR-ETH,R-ETH,UCT-ETH,BEC-ETH,MITH-ETH,ABT-ETH,BKX-ETH,AUTO-ETH,RFR-ETH,TRIO-ETH,TRA-ETH,DADI-ETH,ONT-ETH,OKB-ETH,CTXC-USDT,ZIL-USDT,YOU-OKB,YOU-USDT,LBA-OKB,LBA-USDT,CAI-OKB,LSK-USDT,CAI-USDT,AE-OKB,SC-OKB,KAN-OKB,WIN-OKB,SC-USDT,AE-USDT,KAN-USDT,WIN-USDT,ORS-OKB,DCR-OKB,DCR-USDT,WAVES-OKB,WAVES-USDT,ORS-USDT,MVP-USDT,NAS-OKB,XAS-OKB,ZCO-OKB,EGT-OKB,XAS-USDT,CVT-USDT,EGT-USDT,LET-OKB,LET-USDT,HPB-OKB,HPB-USDT,SDA-OKB,ADA-OKB,ADA-USDT,HYC-USDT,VITE-OKB,TRX-OKB,PAX-USDT,TUSD-USDT,USDC-USDT,GUSD-USDT,BCH-USDT,BSV-USDT,BTT-USDT,BLOC-OKB,BLOC-USDT,ATOM-USDT,ELF-USDT,DASH-USDT,LRC-USDT,NULS-USDT,MCO-USDT,BTG-USDT,DASH-OKB,XRP-USDT,ZEC-USDT,NEO-USDT,GAS-USDT,HC-USDT,QTUM-USDT,IOTA-USDT,BTC-USDT,BCD-USDT,XUC-USDT,CMT-USDT,ITC-USDT,PRA-USDT,EDO-USDT,ETH-USDT,LTC-USDT,ETC-USDT,EOS-USDT,OMG-USDT,ACT-USDT,BTM-USDT,STORJ-USDT,PAY-USDT,DGD-USDT,GNT-USDT,SNT-USDT,LINK-USDT,WTC-USDT,ZRX-USDT,BNT-USDT,CVC-USDT,MANA-USDT,KNC-USDT,ICX-USDT,XEM-USDT,ARK-USDT,YOYO-USDT,AST-USDT,TRX-USDT,MDA-USDT,DGB-USDT,PPT-USDT,SWFTC-USDT,XMR-USDT,XLM-USDT,KCASH-USDT,MDT-USDT,NAS-USDT,RNT-USDT,UGC-USDT,DPY-USDT,SSC-USDT,AAC-USDT,FAIR-USDT,UBTC-USDT,SHOW-USDT,VIB-USDT,MOT-USDT,UTK-USDT,TOPC-USDT,QUN-USDT,INT-USDT,IPC-USDT,IOST-USDT,INS-USDT,YEE-USDT,MOF-USDT,TCT-USDT,STC-USDT,THETA-USDT,PST-USDT,MKR-USDT,LIGHT-USDT,TRUE-USDT,OF-USDT,SOC-USDT,ZEN-USDT,HMC-USDT,ZIP-USDT,NANO-USDT,CIC-USDT,GTO-USDT,CHAT-USDT,INSUR-USDT,R-USDT,BEC-USDT,MITH-USDT,ABT-USDT,BKX-USDT,RFR-USDT,TRIO-USDT,DADI-USDT,ONT-USDT,OKB-USDT,NEO-OKB,LTC-OKB,ETC-OKB,XRP-OKB,ZEC-OKB,QTUM-OKB,IOTA-OKB,EOS-OKB",
|
||||
"enabledPairs": "EOS-USDT",
|
||||
"baseCurrencies": "USD",
|
||||
"assetTypes": "SPOT",
|
||||
"supportsAutoPairUpdates": true,
|
||||
"configCurrencyPairFormat": {
|
||||
"uppercase": true,
|
||||
"delimiter": "_"
|
||||
"delimiter": "-"
|
||||
},
|
||||
"requestCurrencyPairFormat": {
|
||||
"uppercase": false,
|
||||
"delimiter": "_"
|
||||
"uppercase": true,
|
||||
"delimiter": "-"
|
||||
},
|
||||
"bankAccounts": [
|
||||
{
|
||||
|
||||
@@ -62,7 +62,7 @@ func NewPairFromIndex(currencyPair, index string) (Pair, error) {
|
||||
// NewPairFromString converts currency string into a new CurrencyPair
|
||||
// with or without delimeter
|
||||
func NewPairFromString(currencyPair string) Pair {
|
||||
delimiters := []string{"_", "-", "/"}
|
||||
delimiters := []string{"_", "-", "/", ":"}
|
||||
var delimiter string
|
||||
for _, x := range delimiters {
|
||||
if strings.Contains(currencyPair, x) {
|
||||
|
||||
@@ -428,18 +428,27 @@ func WebsocketDataHandler(ws *wshandler.Websocket) {
|
||||
// }
|
||||
|
||||
tickerNew := ticker.Price{
|
||||
Last: d.Last,
|
||||
High: d.High,
|
||||
Low: d.Low,
|
||||
Bid: d.Bid,
|
||||
Ask: d.Ask,
|
||||
Volume: d.Volume,
|
||||
QuoteVolume: d.QuoteVolume,
|
||||
PriceATH: d.PriceATH,
|
||||
Open: d.Open,
|
||||
Close: d.Close,
|
||||
Pair: d.Pair,
|
||||
LastUpdated: d.Timestamp,
|
||||
Last: d.ClosePrice,
|
||||
High: d.HighPrice,
|
||||
Low: d.LowPrice,
|
||||
Volume: d.Quantity,
|
||||
}
|
||||
if Bot.Settings.EnableExchangeSyncManager && Bot.ExchangeCurrencyPairManager != nil {
|
||||
Bot.ExchangeCurrencyPairManager.update(ws.GetName(),
|
||||
d.Pair, d.AssetType, SyncItemTicker, nil)
|
||||
}
|
||||
ticker.ProcessTicker(ws.GetName(), &tickerNew, d.AssetType)
|
||||
err := ticker.ProcessTicker(ws.GetName(), &tickerNew, d.AssetType)
|
||||
if err != nil {
|
||||
log.Errorf(log.WebsocketMgr, "routines.go exchange %s websocket error - %s", ws.GetName(), err)
|
||||
}
|
||||
printTickerSummary(&tickerNew, tickerNew.Pair, d.AssetType, ws.GetName(), nil)
|
||||
case wshandler.KlineData:
|
||||
// Kline data
|
||||
|
||||
@@ -486,6 +486,8 @@ func (e *ExchangeCurrencyPairSyncer) Start() {
|
||||
} else {
|
||||
usingWebsocket = true
|
||||
}
|
||||
} else {
|
||||
usingWebsocket = true
|
||||
}
|
||||
} else if supportsREST {
|
||||
usingREST = true
|
||||
|
||||
@@ -161,16 +161,16 @@ type TickerComponent struct {
|
||||
type Ticker struct {
|
||||
Result string `json:"result"`
|
||||
Data struct {
|
||||
High TickerComponent `json:"high"`
|
||||
Low TickerComponent `json:"low"`
|
||||
Avg TickerComponent `json:"avg"`
|
||||
Vwap TickerComponent `json:"vwap"`
|
||||
Vol TickerComponent `json:"vol"`
|
||||
Last TickerComponent `json:"last"`
|
||||
Buy TickerComponent `json:"buy"`
|
||||
Sell TickerComponent `json:"sell"`
|
||||
Now string `json:"now"`
|
||||
UpdateTime string `json:"dataUpdateTime"`
|
||||
High TickerComponent `json:"high"`
|
||||
Low TickerComponent `json:"low"`
|
||||
Average TickerComponent `json:"avg"`
|
||||
VolumeWeightedAveragePrice TickerComponent `json:"vwap"`
|
||||
Volume TickerComponent `json:"vol"`
|
||||
Last TickerComponent `json:"last"`
|
||||
Buy TickerComponent `json:"buy"`
|
||||
Sell TickerComponent `json:"sell"`
|
||||
Now int64 `json:"now,string"`
|
||||
UpdateTime int64 `json:"dataUpdateTime,string"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@ package anx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
@@ -173,7 +173,7 @@ func (a *ANX) FetchTradablePairs(asset asset.Item) ([]string, error) {
|
||||
|
||||
var currencies []string
|
||||
for x := range result.CurrencyPairs {
|
||||
currencies = append(currencies, result.CurrencyPairs[x].TradedCcy+"_"+result.CurrencyPairs[x].SettlementCcy)
|
||||
currencies = append(currencies, fmt.Sprintf("%v%v%v", result.CurrencyPairs[x].TradedCcy, a.GetPairFormat(asset, false).Delimiter, result.CurrencyPairs[x].SettlementCcy))
|
||||
}
|
||||
|
||||
return currencies, nil
|
||||
@@ -186,61 +186,22 @@ func (a *ANX) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price,
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
last, _ := convert.FloatFromString(tick.Data.Last.Value)
|
||||
high, _ := convert.FloatFromString(tick.Data.High.Value)
|
||||
low, _ := convert.FloatFromString(tick.Data.Low.Value)
|
||||
bid, _ := convert.FloatFromString(tick.Data.Buy.Value)
|
||||
ask, _ := convert.FloatFromString(tick.Data.Sell.Value)
|
||||
volume, _ := convert.FloatFromString(tick.Data.Volume.Value)
|
||||
|
||||
tickerPrice.Pair = p
|
||||
|
||||
if tick.Data.Sell.Value != "" {
|
||||
tickerPrice.Ask, err = strconv.ParseFloat(tick.Data.Sell.Value, 64)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
} else {
|
||||
tickerPrice.Ask = 0
|
||||
}
|
||||
|
||||
if tick.Data.Buy.Value != "" {
|
||||
tickerPrice.Bid, err = strconv.ParseFloat(tick.Data.Buy.Value, 64)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
} else {
|
||||
tickerPrice.Bid = 0
|
||||
}
|
||||
|
||||
if tick.Data.Low.Value != "" {
|
||||
tickerPrice.Low, err = strconv.ParseFloat(tick.Data.Low.Value, 64)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
} else {
|
||||
tickerPrice.Low = 0
|
||||
}
|
||||
|
||||
if tick.Data.Last.Value != "" {
|
||||
tickerPrice.Last, err = strconv.ParseFloat(tick.Data.Last.Value, 64)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
} else {
|
||||
tickerPrice.Last = 0
|
||||
}
|
||||
|
||||
if tick.Data.Vol.Value != "" {
|
||||
tickerPrice.Volume, err = strconv.ParseFloat(tick.Data.Vol.Value, 64)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
} else {
|
||||
tickerPrice.Volume = 0
|
||||
}
|
||||
|
||||
if tick.Data.High.Value != "" {
|
||||
tickerPrice.High, err = strconv.ParseFloat(tick.Data.High.Value, 64)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
} else {
|
||||
tickerPrice.High = 0
|
||||
tickerPrice = ticker.Price{
|
||||
Last: last,
|
||||
High: high,
|
||||
Low: low,
|
||||
Bid: bid,
|
||||
Ask: ask,
|
||||
Volume: volume,
|
||||
Pair: p,
|
||||
LastUpdated: time.Unix(0, tick.Data.UpdateTime),
|
||||
}
|
||||
|
||||
err = ticker.ProcessTicker(a.GetName(), &tickerPrice, assetType)
|
||||
|
||||
@@ -167,29 +167,29 @@ type KlineStream struct {
|
||||
|
||||
// TickerStream holds the ticker stream data
|
||||
type TickerStream struct {
|
||||
EventType string `json:"e"`
|
||||
EventTime int64 `json:"E"`
|
||||
Symbol string `json:"s"`
|
||||
PriceChange string `json:"p"`
|
||||
PriceChangePercent string `json:"P"`
|
||||
WeightedAvgPrice string `json:"w"`
|
||||
PrevDayClose string `json:"x"`
|
||||
CurrDayClose string `json:"c"`
|
||||
CloseTradeQuantity string `json:"Q"`
|
||||
BestBidPrice string `json:"b"`
|
||||
BestBidQuantity string `json:"B"`
|
||||
BestAskPrice string `json:"a"`
|
||||
BestAskQuantity string `json:"A"`
|
||||
OpenPrice string `json:"o"`
|
||||
HighPrice string `json:"h"`
|
||||
LowPrice string `json:"l"`
|
||||
TotalTradedVolume string `json:"v"`
|
||||
TotalTradedQuoteVolume string `json:"q"`
|
||||
OpenTime int64 `json:"O"`
|
||||
CloseTime int64 `json:"C"`
|
||||
FirstTradeID int64 `json:"F"`
|
||||
LastTradeID int64 `json:"L"`
|
||||
NumberOfTrades int64 `json:"n"`
|
||||
EventType string `json:"e"`
|
||||
EventTime int64 `json:"E"`
|
||||
Symbol currency.Pair `json:"s"`
|
||||
PriceChange float64 `json:"p,string"`
|
||||
PriceChangePercent float64 `json:"P,string"`
|
||||
WeightedAvgPrice float64 `json:"w,string"`
|
||||
ClosePrice float64 `json:"x,string"`
|
||||
LastPrice float64 `json:"c,string"`
|
||||
LastPriceQuantity float64 `json:"Q,string"`
|
||||
BestBidPrice float64 `json:"b,string"`
|
||||
BestBidQuantity float64 `json:"B,string"`
|
||||
BestAskPrice float64 `json:"a,string"`
|
||||
BestAskQuantity float64 `json:"A,string"`
|
||||
OpenPrice float64 `json:"o,string"`
|
||||
HighPrice float64 `json:"h,string"`
|
||||
LowPrice float64 `json:"l,string"`
|
||||
TotalTradedVolume float64 `json:"v,string"`
|
||||
TotalTradedQuoteVolume float64 `json:"q,string"`
|
||||
OpenTime int64 `json:"O"`
|
||||
CloseTime int64 `json:"C"`
|
||||
FirstTradeID int64 `json:"F"`
|
||||
LastTradeID int64 `json:"L"`
|
||||
NumberOfTrades int64 `json:"n"`
|
||||
}
|
||||
|
||||
// HistoricalTrade holds recent trade data
|
||||
@@ -239,25 +239,25 @@ type AveragePrice struct {
|
||||
|
||||
// PriceChangeStats contains statistics for the last 24 hours trade
|
||||
type PriceChangeStats struct {
|
||||
Symbol string `json:"symbol"`
|
||||
PriceChange float64 `json:"priceChange,string"`
|
||||
PriceChangePercent float64 `json:"priceChangePercent,string"`
|
||||
WeightedAvgPrice float64 `json:"weightedAvgPrice,string"`
|
||||
PrevClosePrice float64 `json:"prevClosePrice,string"`
|
||||
LastPrice float64 `json:"lastPrice,string"`
|
||||
LastQty float64 `json:"lastQty,string"`
|
||||
BidPrice float64 `json:"bidPrice,string"`
|
||||
AskPrice float64 `json:"askPrice,string"`
|
||||
OpenPrice float64 `json:"openPrice,string"`
|
||||
HighPrice float64 `json:"highPrice,string"`
|
||||
LowPrice float64 `json:"lowPrice,string"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
QuoteVolume float64 `json:"quoteVolume,string"`
|
||||
OpenTime int64 `json:"openTime"`
|
||||
CloseTime int64 `json:"closeTime"`
|
||||
FirstID int64 `json:"fristId"`
|
||||
LastID int64 `json:"lastId"`
|
||||
Count int64 `json:"count"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
PriceChange float64 `json:"priceChange,string"`
|
||||
PriceChangePercent float64 `json:"priceChangePercent,string"`
|
||||
WeightedAvgPrice float64 `json:"weightedAvgPrice,string"`
|
||||
PrevClosePrice float64 `json:"prevClosePrice,string"`
|
||||
LastPrice float64 `json:"lastPrice,string"`
|
||||
LastQty float64 `json:"lastQty,string"`
|
||||
BidPrice float64 `json:"bidPrice,string"`
|
||||
AskPrice float64 `json:"askPrice,string"`
|
||||
OpenPrice float64 `json:"openPrice,string"`
|
||||
HighPrice float64 `json:"highPrice,string"`
|
||||
LowPrice float64 `json:"lowPrice,string"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
QuoteVolume float64 `json:"quoteVolume,string"`
|
||||
OpenTime int64 `json:"openTime"`
|
||||
CloseTime int64 `json:"closeTime"`
|
||||
FirstID int64 `json:"fristId"`
|
||||
LastID int64 `json:"lastId"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// SymbolPrice holds basic symbol price
|
||||
|
||||
@@ -147,18 +147,21 @@ func (b *Binance) WsHandleData() {
|
||||
continue
|
||||
}
|
||||
|
||||
var wsTicker wshandler.TickerData
|
||||
wsTicker.Timestamp = time.Unix(t.EventTime/1000, 0)
|
||||
wsTicker.Pair = currency.NewPairFromString(t.Symbol)
|
||||
wsTicker.AssetType = asset.Spot
|
||||
wsTicker.Exchange = b.GetName()
|
||||
wsTicker.ClosePrice, _ = strconv.ParseFloat(t.CurrDayClose, 64)
|
||||
wsTicker.Quantity, _ = strconv.ParseFloat(t.TotalTradedVolume, 64)
|
||||
wsTicker.OpenPrice, _ = strconv.ParseFloat(t.OpenPrice, 64)
|
||||
wsTicker.HighPrice, _ = strconv.ParseFloat(t.HighPrice, 64)
|
||||
wsTicker.LowPrice, _ = strconv.ParseFloat(t.LowPrice, 64)
|
||||
|
||||
b.Websocket.DataHandler <- wsTicker
|
||||
b.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Exchange: b.Name,
|
||||
Open: t.OpenPrice,
|
||||
Close: t.ClosePrice,
|
||||
Volume: t.TotalTradedVolume,
|
||||
QuoteVolume: t.TotalTradedQuoteVolume,
|
||||
High: t.HighPrice,
|
||||
Low: t.LowPrice,
|
||||
Bid: t.BestBidPrice,
|
||||
Ask: t.BestAskPrice,
|
||||
Last: t.LastPrice,
|
||||
Timestamp: time.Unix(0, t.EventTime),
|
||||
AssetType: asset.Spot,
|
||||
Pair: t.Symbol,
|
||||
}
|
||||
|
||||
continue
|
||||
case "kline":
|
||||
|
||||
@@ -163,9 +163,9 @@ func (b *Binance) Run() {
|
||||
}
|
||||
|
||||
forceUpdate := false
|
||||
if !common.StringDataContains(b.GetEnabledPairs(asset.Spot).Strings(), "-") ||
|
||||
!common.StringDataContains(b.GetAvailablePairs(asset.Spot).Strings(), "-") {
|
||||
enabledPairs := currency.NewPairsFromStrings([]string{"BTC-USDT"})
|
||||
if !common.StringDataContains(b.GetEnabledPairs(asset.Spot).Strings(), b.GetPairFormat(asset.Spot, false).Delimiter) ||
|
||||
!common.StringDataContains(b.GetAvailablePairs(asset.Spot).Strings(), b.GetPairFormat(asset.Spot, false).Delimiter) {
|
||||
enabledPairs := currency.NewPairsFromStrings([]string{fmt.Sprintf("BTC%vUSDT", b.GetPairFormat(asset.Spot, false).Delimiter)})
|
||||
log.Warn(log.ExchangeSys,
|
||||
"Available pairs for Binance reset due to config upgrade, please enable the ones you would like again")
|
||||
forceUpdate = true
|
||||
@@ -197,8 +197,10 @@ func (b *Binance) FetchTradablePairs(asset asset.Item) ([]string, error) {
|
||||
|
||||
for x := range info.Symbols {
|
||||
if info.Symbols[x].Status == "TRADING" {
|
||||
validCurrencyPairs = append(validCurrencyPairs,
|
||||
info.Symbols[x].BaseAsset+"-"+info.Symbols[x].QuoteAsset)
|
||||
validCurrencyPairs = append(validCurrencyPairs, fmt.Sprintf("%v%v%v",
|
||||
info.Symbols[x].BaseAsset,
|
||||
b.GetPairFormat(asset, false).Delimiter,
|
||||
info.Symbols[x].QuoteAsset))
|
||||
}
|
||||
}
|
||||
return validCurrencyPairs, nil
|
||||
@@ -222,21 +224,28 @@ func (b *Binance) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pr
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range b.GetEnabledPairs(assetType) {
|
||||
curr := b.FormatExchangeCurrency(x, assetType)
|
||||
pairs := b.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
for y := range tick {
|
||||
if tick[y].Symbol != curr.String() {
|
||||
if !tick[y].Symbol.Equal(pairs[i]) {
|
||||
continue
|
||||
}
|
||||
tickerPrice.Pair = x
|
||||
tickerPrice.Ask = tick[y].AskPrice
|
||||
tickerPrice.Bid = tick[y].BidPrice
|
||||
tickerPrice.High = tick[y].HighPrice
|
||||
tickerPrice.Last = tick[y].LastPrice
|
||||
tickerPrice.Low = tick[y].LowPrice
|
||||
tickerPrice.Volume = tick[y].Volume
|
||||
ticker.ProcessTicker(b.Name, &tickerPrice, assetType)
|
||||
tickerPrice := ticker.Price{
|
||||
Last: tick[y].LastPrice,
|
||||
High: tick[y].HighPrice,
|
||||
Low: tick[y].LowPrice,
|
||||
Bid: tick[y].BidPrice,
|
||||
Ask: tick[y].AskPrice,
|
||||
Volume: tick[y].Volume,
|
||||
QuoteVolume: tick[y].QuoteVolume,
|
||||
Open: tick[y].OpenPrice,
|
||||
Close: tick[y].PrevClosePrice,
|
||||
Pair: pairs[i],
|
||||
}
|
||||
err = ticker.ProcessTicker(b.Name, &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ticker.GetTicker(b.Name, p, assetType)
|
||||
|
||||
@@ -48,6 +48,20 @@ func TestSetup(t *testing.T) {
|
||||
b.Requester.SetRateLimit(false, time.Millisecond*300, 1)
|
||||
}
|
||||
|
||||
func TestAppendOptionalDelimiter(t *testing.T) {
|
||||
curr1 := currency.NewPairFromString("BTCUSD")
|
||||
b.appendOptionalDelimiter(&curr1)
|
||||
if curr1.Delimiter != "" {
|
||||
t.Errorf("Expected no delimiter, received %v", curr1.Delimiter)
|
||||
}
|
||||
curr2 := currency.NewPairFromString("DUSK:USD")
|
||||
curr2.Delimiter = ""
|
||||
b.appendOptionalDelimiter(&curr2)
|
||||
if curr2.Delimiter != ":" {
|
||||
t.Errorf("Expected \"-\" as a delimiter, received %v", curr2.Delimiter)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPlatformStatus(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package bitfinex
|
||||
|
||||
import "time"
|
||||
|
||||
// Ticker holds basic ticker information from the exchange
|
||||
type Ticker struct {
|
||||
Mid float64 `json:"mid,string"`
|
||||
@@ -28,6 +30,7 @@ type Tickerv2 struct {
|
||||
Volume float64
|
||||
High float64
|
||||
Low float64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
// Tickersv2 holds the version 2 tickers information
|
||||
|
||||
@@ -271,13 +271,15 @@ func (b *Bitfinex) WsDataHandler() {
|
||||
}
|
||||
case "ticker":
|
||||
b.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Quantity: chanData[8].(float64),
|
||||
ClosePrice: chanData[7].(float64),
|
||||
HighPrice: chanData[9].(float64),
|
||||
LowPrice: chanData[10].(float64),
|
||||
Pair: currency.NewPairFromString(chanInfo.Pair),
|
||||
Exchange: b.GetName(),
|
||||
AssetType: asset.Spot,
|
||||
Exchange: b.Name,
|
||||
Volume: chanData[8].(float64),
|
||||
High: chanData[9].(float64),
|
||||
Low: chanData[10].(float64),
|
||||
Bid: chanData[1].(float64),
|
||||
Ask: chanData[3].(float64),
|
||||
Last: chanData[7].(float64),
|
||||
AssetType: asset.Spot,
|
||||
Pair: currency.NewPairFromString(chanInfo.Pair),
|
||||
}
|
||||
|
||||
case "account":
|
||||
@@ -539,6 +541,7 @@ func (b *Bitfinex) GenerateDefaultSubscriptions() {
|
||||
for i := range channels {
|
||||
enabledPairs := b.GetEnabledPairs(asset.Spot)
|
||||
for j := range enabledPairs {
|
||||
b.appendOptionalDelimiter(&enabledPairs[j])
|
||||
params := make(map[string]interface{})
|
||||
if channels[i] == "book" {
|
||||
params["prec"] = "P0"
|
||||
|
||||
@@ -194,40 +194,39 @@ func (b *Bitfinex) UpdateTradablePairs(forceUpdate bool) error {
|
||||
func (b *Bitfinex) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
enabledPairs := b.GetEnabledPairs(assetType)
|
||||
|
||||
var pairs []string
|
||||
for x := range enabledPairs {
|
||||
b.appendOptionalDelimiter(&enabledPairs[x])
|
||||
pairs = append(pairs, "t"+enabledPairs[x].String())
|
||||
}
|
||||
|
||||
tickerNew, err := b.GetTickersV2(strings.Join(pairs, ","))
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for x := range tickerNew {
|
||||
newP := currency.NewPairFromStrings(tickerNew[x].Symbol[1:4],
|
||||
tickerNew[x].Symbol[4:])
|
||||
|
||||
var tick ticker.Price
|
||||
tick.Pair = newP
|
||||
tick.Ask = tickerNew[x].Ask
|
||||
tick.Bid = tickerNew[x].Bid
|
||||
tick.Low = tickerNew[x].Low
|
||||
tick.Last = tickerNew[x].Last
|
||||
tick.Volume = tickerNew[x].Volume
|
||||
tick.High = tickerNew[x].High
|
||||
|
||||
for i := range tickerNew {
|
||||
newP := tickerNew[i].Symbol[1:] // Remove the "t" prefix
|
||||
tick := ticker.Price{
|
||||
Last: tickerNew[i].Last,
|
||||
High: tickerNew[i].High,
|
||||
Low: tickerNew[i].Low,
|
||||
Bid: tickerNew[i].Bid,
|
||||
Ask: tickerNew[i].Ask,
|
||||
Volume: tickerNew[i].Volume,
|
||||
Pair: currency.NewPairFromString(newP),
|
||||
LastUpdated: tickerNew[i].Timestamp,
|
||||
}
|
||||
err = ticker.ProcessTicker(b.Name, &tick, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
|
||||
return ticker.GetTicker(b.Name, p, assetType)
|
||||
}
|
||||
|
||||
// FetchTicker returns the ticker for a currency pair
|
||||
func (b *Bitfinex) FetchTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
b.appendOptionalDelimiter(&p)
|
||||
tick, err := ticker.GetTicker(b.GetName(), p, asset.Spot)
|
||||
if err != nil {
|
||||
return b.UpdateTicker(p, assetType)
|
||||
@@ -237,6 +236,7 @@ func (b *Bitfinex) FetchTicker(p currency.Pair, assetType asset.Item) (ticker.Pr
|
||||
|
||||
// FetchOrderbook returns the orderbook for a currency pair
|
||||
func (b *Bitfinex) FetchOrderbook(p currency.Pair, assetType asset.Item) (orderbook.Base, error) {
|
||||
b.appendOptionalDelimiter(&p)
|
||||
ob, err := orderbook.Get(b.GetName(), p, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateOrderbook(p, assetType)
|
||||
@@ -246,6 +246,7 @@ func (b *Bitfinex) FetchOrderbook(p currency.Pair, assetType asset.Item) (orderb
|
||||
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (b *Bitfinex) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbook.Base, error) {
|
||||
b.appendOptionalDelimiter(&p)
|
||||
var orderBook orderbook.Base
|
||||
urlVals := url.Values{}
|
||||
urlVals.Set("limit_bids", "100")
|
||||
@@ -339,7 +340,7 @@ func (b *Bitfinex) SubmitOrder(order *exchange.OrderSubmission) (exchange.Submit
|
||||
if order.OrderSide == exchange.BuyOrderSide {
|
||||
isBuying = true
|
||||
}
|
||||
|
||||
b.appendOptionalDelimiter(&order.Pair)
|
||||
response, err := b.NewOrder(order.Pair.String(),
|
||||
order.Amount,
|
||||
order.Price,
|
||||
@@ -592,6 +593,9 @@ func (b *Bitfinex) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest)
|
||||
exchange.FilterOrdersBySide(&orders, getOrdersRequest.OrderSide)
|
||||
exchange.FilterOrdersByType(&orders, getOrdersRequest.OrderType)
|
||||
exchange.FilterOrdersByTickRange(&orders, getOrdersRequest.StartTicks, getOrdersRequest.EndTicks)
|
||||
for i := range getOrdersRequest.Currencies {
|
||||
b.appendOptionalDelimiter(&getOrdersRequest.Currencies[i])
|
||||
}
|
||||
exchange.FilterOrdersByCurrencies(&orders, getOrdersRequest.Currencies)
|
||||
return orders, nil
|
||||
}
|
||||
@@ -599,6 +603,9 @@ func (b *Bitfinex) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest)
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle subscribing
|
||||
func (b *Bitfinex) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
for i := range channels {
|
||||
b.appendOptionalDelimiter(&channels[i].Currency)
|
||||
}
|
||||
b.Websocket.SubscribeToChannels(channels)
|
||||
return nil
|
||||
}
|
||||
@@ -606,6 +613,9 @@ func (b *Bitfinex) SubscribeToWebsocketChannels(channels []wshandler.WebsocketCh
|
||||
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
|
||||
// which lets websocket.manageSubscriptions handle unsubscribing
|
||||
func (b *Bitfinex) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
|
||||
for i := range channels {
|
||||
b.appendOptionalDelimiter(&channels[i].Currency)
|
||||
}
|
||||
b.Websocket.RemoveSubscribedChannels(channels)
|
||||
return nil
|
||||
}
|
||||
@@ -619,3 +629,11 @@ func (b *Bitfinex) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription,
|
||||
func (b *Bitfinex) AuthenticateWebsocket() error {
|
||||
return b.WsSendAuth()
|
||||
}
|
||||
|
||||
// appendOptionalDelimiter ensures that a delimiter is present for long character currencies
|
||||
func (b *Bitfinex) appendOptionalDelimiter(p *currency.Pair) {
|
||||
if len(p.Quote.String()) > 3 ||
|
||||
len(p.Base.String()) > 3 {
|
||||
p.Delimiter = ":"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ func (b *Bitflyer) FetchTradablePairs(assetType asset.Item) ([]string, error) {
|
||||
for _, info := range pairs {
|
||||
if info.Alias != "" && assetType == asset.Futures {
|
||||
products = append(products, info.Alias)
|
||||
} else if info.Alias == "" && assetType == asset.Spot && strings.Contains(info.ProductCode, "_") {
|
||||
} else if info.Alias == "" && assetType == asset.Spot && strings.Contains(info.ProductCode, b.GetPairFormat(assetType, false).Delimiter) {
|
||||
products = append(products, info.ProductCode)
|
||||
}
|
||||
}
|
||||
@@ -177,10 +177,8 @@ func (b *Bitflyer) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.P
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.Ask = tickerNew.BestAsk
|
||||
tickerPrice.Bid = tickerNew.BestBid
|
||||
// tickerPrice.Low
|
||||
tickerPrice.Last = tickerNew.Last
|
||||
tickerPrice.Volume = tickerNew.Volume
|
||||
// tickerPrice.High
|
||||
err = ticker.ProcessTicker(b.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
|
||||
@@ -154,24 +154,27 @@ func (b *Bithumb) UpdateTradablePairs(forceUpdate bool) error {
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (b *Bithumb) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
|
||||
tickers, err := b.GetAllTickers()
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range b.GetEnabledPairs(assetType) {
|
||||
currency := x.Base.String()
|
||||
var tp ticker.Price
|
||||
tp.Pair = x
|
||||
tp.Low = tickers[currency].MinPrice
|
||||
tp.Last = tickers[currency].ClosingPrice
|
||||
tp.Volume = tickers[currency].UnitsTraded24Hr
|
||||
tp.High = tickers[currency].MaxPrice
|
||||
|
||||
pairs := b.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
curr := pairs[i].Base.String()
|
||||
if _, ok := tickers[curr]; !ok {
|
||||
continue
|
||||
}
|
||||
tp := ticker.Price{
|
||||
High: tickers[curr].MaxPrice,
|
||||
Low: tickers[curr].MinPrice,
|
||||
Volume: tickers[curr].UnitsTraded24Hr,
|
||||
Open: tickers[curr].OpeningPrice,
|
||||
Close: tickers[curr].ClosingPrice,
|
||||
Pair: pairs[i],
|
||||
}
|
||||
err = ticker.ProcessTicker(b.Name, &tp, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
return ticker.GetTicker(b.Name, p, assetType)
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package bitmex
|
||||
|
||||
import exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
// RequestError allows for a general error capture from requests
|
||||
type RequestError struct {
|
||||
@@ -117,107 +122,107 @@ type Funding struct {
|
||||
|
||||
// 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"`
|
||||
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 currency.Pair `json:"symbol"`
|
||||
TakerFee float64 `json:"takerFee"`
|
||||
Taxed bool `json:"taxed"`
|
||||
TickSize float64 `json:"tickSize"`
|
||||
Timestamp time.Time `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 float64 `json:"volume"`
|
||||
Volume24h float64 `json:"volume24h"`
|
||||
Vwap float64 `json:"vwap"`
|
||||
}
|
||||
|
||||
// InstrumentInterval instrument interval
|
||||
|
||||
@@ -2,7 +2,6 @@ package bitmex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -93,7 +92,7 @@ func (b *Bitmex) SetDefaults() {
|
||||
Websocket: true,
|
||||
RESTCapabilities: exchange.ProtocolFeatures{
|
||||
AutoPairUpdates: true,
|
||||
TickerBatching: false,
|
||||
TickerBatching: true,
|
||||
},
|
||||
WithdrawPermissions: exchange.AutoWithdrawCryptoWithAPIPermission |
|
||||
exchange.WithdrawCryptoWithEmail |
|
||||
@@ -205,7 +204,7 @@ func (b *Bitmex) FetchTradablePairs(asset asset.Item) ([]string, error) {
|
||||
|
||||
var products []string
|
||||
for x := range marketInfo {
|
||||
products = append(products, marketInfo[x].Symbol)
|
||||
products = append(products, marketInfo[x].Symbol.String())
|
||||
}
|
||||
|
||||
return products, nil
|
||||
@@ -260,24 +259,34 @@ func (b *Bitmex) UpdateTradablePairs(forceUpdate bool) error {
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (b *Bitmex) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
currency := b.FormatExchangeCurrency(p, assetType)
|
||||
|
||||
tick, err := b.GetTrade(&GenericRequestParams{
|
||||
Symbol: currency.String(),
|
||||
Reverse: true,
|
||||
Count: 1})
|
||||
tick, err := b.GetActiveInstruments(&GenericRequestParams{})
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
if len(tick) == 0 {
|
||||
return tickerPrice, fmt.Errorf("%s REST error: no ticker return", b.Name)
|
||||
pairs := b.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
for j := range tick {
|
||||
if !pairs[i].Equal(tick[j].Symbol) {
|
||||
continue
|
||||
}
|
||||
tickerPrice = ticker.Price{
|
||||
Last: tick[j].LastPrice,
|
||||
High: tick[j].HighPrice,
|
||||
Low: tick[j].LowPrice,
|
||||
Bid: tick[j].BidPrice,
|
||||
Ask: tick[j].AskPrice,
|
||||
Volume: tick[j].Volume24h,
|
||||
Close: tick[j].PrevClosePrice,
|
||||
Pair: tick[j].Symbol,
|
||||
LastUpdated: tick[j].Timestamp,
|
||||
}
|
||||
err = ticker.ProcessTicker(b.Name, &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.Last = tick[0].Price
|
||||
tickerPrice.Volume = float64(tick[0].Size)
|
||||
return tickerPrice, ticker.ProcessTicker(b.Name, &tickerPrice, assetType)
|
||||
return ticker.GetTicker(b.Name, p, assetType)
|
||||
}
|
||||
|
||||
// FetchTicker returns the ticker for a currency pair
|
||||
|
||||
@@ -51,8 +51,8 @@ const (
|
||||
bitstampAPIReturnType = "string"
|
||||
bitstampAPITradingPairsInfo = "trading-pairs-info"
|
||||
|
||||
bitstampAuthRate = 600
|
||||
bitstampUnauthRate = 600
|
||||
bitstampAuthRate = 8000
|
||||
bitstampUnauthRate = 8000
|
||||
)
|
||||
|
||||
// Bitstamp is the overarching type across the bitstamp package
|
||||
|
||||
@@ -71,7 +71,6 @@ func (b *Bitstamp) SetDefaults() {
|
||||
Websocket: true,
|
||||
RESTCapabilities: exchange.ProtocolFeatures{
|
||||
AutoPairUpdates: true,
|
||||
TickerBatching: false,
|
||||
},
|
||||
WithdrawPermissions: exchange.AutoWithdrawCrypto |
|
||||
exchange.AutoWithdrawFiat,
|
||||
@@ -206,15 +205,19 @@ func (b *Bitstamp) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.P
|
||||
tick, err := b.GetTicker(p.String(), false)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
|
||||
}
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.Ask = tick.Ask
|
||||
tickerPrice.Bid = tick.Bid
|
||||
tickerPrice.Low = tick.Low
|
||||
tickerPrice.Last = tick.Last
|
||||
tickerPrice.Volume = tick.Volume
|
||||
tickerPrice.High = tick.High
|
||||
|
||||
tickerPrice = ticker.Price{
|
||||
Last: tick.Last,
|
||||
High: tick.High,
|
||||
Low: tick.Low,
|
||||
Bid: tick.Bid,
|
||||
Ask: tick.Ask,
|
||||
Volume: tick.Volume,
|
||||
Open: tick.Open,
|
||||
Pair: p,
|
||||
LastUpdated: time.Unix(tick.Timestamp, 0),
|
||||
}
|
||||
|
||||
err = ticker.ProcessTicker(b.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package bittrex
|
||||
|
||||
import "encoding/json"
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// Response is the generalised response type for Bittrex
|
||||
type Response struct {
|
||||
|
||||
@@ -196,27 +196,36 @@ func (b *Bittrex) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (b *Bittrex) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
tick, err := b.GetMarketSummaries()
|
||||
ticks, err := b.GetMarketSummaries()
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range b.GetEnabledPairs(assetType) {
|
||||
curr := b.FormatExchangeCurrency(x, assetType)
|
||||
for y := range tick.Result {
|
||||
if tick.Result[y].MarketName != curr.String() {
|
||||
pairs := b.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
for j := range ticks.Result {
|
||||
if !strings.EqualFold(ticks.Result[j].MarketName, pairs[i].String()) {
|
||||
continue
|
||||
}
|
||||
tickerPrice.Pair = x
|
||||
tickerPrice.High = tick.Result[y].High
|
||||
tickerPrice.Low = tick.Result[y].Low
|
||||
tickerPrice.Ask = tick.Result[y].Ask
|
||||
tickerPrice.Bid = tick.Result[y].Bid
|
||||
tickerPrice.Last = tick.Result[y].Last
|
||||
tickerPrice.Volume = tick.Result[y].Volume
|
||||
ticker.ProcessTicker(b.GetName(), &tickerPrice, assetType)
|
||||
tickerTime, _ := time.Parse(time.RFC3339, ticks.Result[j].TimeStamp)
|
||||
tickerPrice = ticker.Price{
|
||||
Last: ticks.Result[j].Last,
|
||||
High: ticks.Result[j].High,
|
||||
Low: ticks.Result[j].Low,
|
||||
Bid: ticks.Result[j].Bid,
|
||||
Ask: ticks.Result[j].Ask,
|
||||
Volume: ticks.Result[j].BaseVolume,
|
||||
QuoteVolume: ticks.Result[j].Volume,
|
||||
Close: ticks.Result[j].PrevDay,
|
||||
Pair: pairs[i],
|
||||
LastUpdated: tickerTime,
|
||||
}
|
||||
err = ticker.ProcessTicker(b.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ticker.GetTicker(b.Name, p, assetType)
|
||||
}
|
||||
|
||||
|
||||
@@ -30,13 +30,16 @@ type Market struct {
|
||||
|
||||
// Ticker holds ticker information
|
||||
type Ticker struct {
|
||||
BestBID float64 `json:"bestBid"`
|
||||
BestAsk float64 `json:"bestAsk"`
|
||||
LastPrice float64 `json:"lastPrice"`
|
||||
Currency string `json:"currency"`
|
||||
Instrument string `json:"instrument"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Volume float64 `json:"volume24h"`
|
||||
BestAsk float64 `json:"bestAsk"`
|
||||
BestBid float64 `json:"bestBid"`
|
||||
Currency currency.Code `json:"currency"`
|
||||
High24h float64 `json:"high24h"`
|
||||
Instrument currency.Pair `json:"instrument"`
|
||||
LastPrice float64 `json:"lastPrice"`
|
||||
Low24h float64 `json:"low24h"`
|
||||
Price24h float64 `json:"price24h"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Volume24h float64 `json:"volume24h"`
|
||||
}
|
||||
|
||||
// Orderbook holds current orderbook information returned from the exchange
|
||||
|
||||
@@ -147,7 +147,7 @@ func (b *BTCMarkets) FetchTradablePairs(asset asset.Item) ([]string, error) {
|
||||
|
||||
var pairs []string
|
||||
for x := range markets {
|
||||
pairs = append(pairs, markets[x].Instrument+"-"+markets[x].Currency)
|
||||
pairs = append(pairs, fmt.Sprintf("%v%v%v", markets[x].Instrument, b.GetPairFormat(asset, false).Delimiter, markets[x].Currency))
|
||||
}
|
||||
|
||||
return pairs, nil
|
||||
@@ -171,10 +171,17 @@ func (b *BTCMarkets) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.Ask = tick.BestAsk
|
||||
tickerPrice.Bid = tick.BestBID
|
||||
tickerPrice.Last = tick.LastPrice
|
||||
|
||||
tickerPrice = ticker.Price{
|
||||
Last: tick.LastPrice,
|
||||
High: tick.High24h,
|
||||
Low: tick.Low24h,
|
||||
Bid: tick.BestBid,
|
||||
Ask: tick.BestAsk,
|
||||
Volume: tick.Volume24h,
|
||||
Pair: p,
|
||||
LastUpdated: time.Unix(tick.Timestamp, 0),
|
||||
}
|
||||
|
||||
err = ticker.ProcessTicker(b.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
|
||||
@@ -43,12 +43,12 @@ type Ticker struct {
|
||||
|
||||
// MarketStatistics stores market statistics for a particular product
|
||||
type MarketStatistics struct {
|
||||
Open float64 `json:"open,string"`
|
||||
Low float64 `json:"low,string"`
|
||||
High float64 `json:"high,string"`
|
||||
Close float64 `json:"close,string"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
Time string `json:"time"`
|
||||
Open float64 `json:"open,string"`
|
||||
Low float64 `json:"low,string"`
|
||||
High float64 `json:"high,string"`
|
||||
Close float64 `json:"close,string"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
Time time.Time `json:"time"`
|
||||
}
|
||||
|
||||
// ServerTime stores the server time data
|
||||
|
||||
@@ -94,12 +94,12 @@ func (b *BTSE) WsHandleData() {
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Timestamp: time.Now(),
|
||||
Pair: currency.NewPairDelimiter(t.ProductID, "-"),
|
||||
AssetType: asset.Spot,
|
||||
Exchange: b.GetName(),
|
||||
ClosePrice: price,
|
||||
Quantity: t.LastSize,
|
||||
Exchange: b.Name,
|
||||
Close: price,
|
||||
Bid: t.BestBids,
|
||||
Ask: t.BestAsk,
|
||||
AssetType: asset.Spot,
|
||||
Pair: currency.NewPairDelimiter(t.ProductID, b.GetPairFormat(asset.Spot, false).Delimiter),
|
||||
}
|
||||
case "snapshot":
|
||||
snapshot := websocketOrderbookSnapshot{}
|
||||
|
||||
@@ -219,6 +219,7 @@ func (b *BTSE) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price
|
||||
tickerPrice.Last = t.Price
|
||||
tickerPrice.Volume = s.Volume
|
||||
tickerPrice.High = s.High
|
||||
tickerPrice.LastUpdated = s.Time
|
||||
|
||||
err = ticker.ProcessTicker(b.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package coinbasepro
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
// Product holds product information
|
||||
type Product struct {
|
||||
@@ -15,10 +19,13 @@ type Product struct {
|
||||
|
||||
// Ticker holds basic ticker information
|
||||
type Ticker struct {
|
||||
TradeID int64 `json:"trade_id"`
|
||||
Price float64 `json:"price,string"`
|
||||
Size float64 `json:"size,string"`
|
||||
Time string `json:"time"`
|
||||
TradeID int64 `json:"trade_id"`
|
||||
Ask float64 `json:"ask,string"`
|
||||
Bid float64 `json:"bid,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
Size float64 `json:"size,string"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
Time time.Time `json:"time"`
|
||||
}
|
||||
|
||||
// Trade holds executed trade information
|
||||
@@ -435,21 +442,21 @@ type WebsocketHeartBeat struct {
|
||||
|
||||
// WebsocketTicker defines ticker websocket response
|
||||
type WebsocketTicker struct {
|
||||
Type string `json:"type"`
|
||||
Sequence int64 `json:"sequence"`
|
||||
ProductID string `json:"product_id"`
|
||||
Price float64 `json:"price,string"`
|
||||
Open24H float64 `json:"open_24h,string"`
|
||||
Volume24H float64 `json:"volumen_24h,string"`
|
||||
Low24H float64 `json:"low_24h,string"`
|
||||
High24H float64 `json:"high_24h,string"`
|
||||
Volume30D float64 `json:"volume_30d,string"`
|
||||
BestBid float64 `json:"best_bid,string"`
|
||||
BestAsk float64 `json:"best_ask,string"`
|
||||
Side string `json:"side"`
|
||||
Time time.Time `json:"time,string"`
|
||||
TradeID int64 `json:"trade_id"`
|
||||
LastSize float64 `json:"last_size,string"`
|
||||
Type string `json:"type"`
|
||||
Sequence int64 `json:"sequence"`
|
||||
ProductID currency.Pair `json:"product_id"`
|
||||
Price float64 `json:"price,string"`
|
||||
Open24H float64 `json:"open_24h,string"`
|
||||
Volume24H float64 `json:"volume_24h,string"`
|
||||
Low24H float64 `json:"low_24h,string"`
|
||||
High24H float64 `json:"high_24h,string"`
|
||||
Volume30D float64 `json:"volume_30d,string"`
|
||||
BestBid float64 `json:"best_bid,string"`
|
||||
BestAsk float64 `json:"best_ask,string"`
|
||||
Side string `json:"side"`
|
||||
Time time.Time `json:"time,string"`
|
||||
TradeID int64 `json:"trade_id"`
|
||||
LastSize float64 `json:"last_size,string"`
|
||||
}
|
||||
|
||||
// WebsocketOrderbookSnapshot defines a snapshot response
|
||||
|
||||
@@ -89,15 +89,18 @@ func (c *CoinbasePro) WsHandleData() {
|
||||
}
|
||||
|
||||
c.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Timestamp: ticker.Time,
|
||||
Pair: currency.NewPairFromString(ticker.ProductID),
|
||||
AssetType: asset.Spot,
|
||||
Exchange: c.GetName(),
|
||||
OpenPrice: ticker.Open24H,
|
||||
HighPrice: ticker.High24H,
|
||||
LowPrice: ticker.Low24H,
|
||||
ClosePrice: ticker.Price,
|
||||
Quantity: ticker.Volume24H,
|
||||
Timestamp: ticker.Time,
|
||||
Pair: ticker.ProductID,
|
||||
AssetType: asset.Spot,
|
||||
Exchange: c.Name,
|
||||
Open: ticker.Open24H,
|
||||
High: ticker.High24H,
|
||||
Low: ticker.Low24H,
|
||||
Close: ticker.Price,
|
||||
Volume: ticker.Volume24H,
|
||||
Bid: ticker.BestBid,
|
||||
Ask: ticker.BestAsk,
|
||||
Last: ticker.LastSize,
|
||||
}
|
||||
|
||||
case "snapshot":
|
||||
|
||||
@@ -232,18 +232,22 @@ func (c *CoinbasePro) UpdateTicker(p currency.Pair, assetType asset.Item) (ticke
|
||||
if err != nil {
|
||||
return ticker.Price{}, err
|
||||
}
|
||||
|
||||
stats, err := c.GetStats(c.FormatExchangeCurrency(p, assetType).String())
|
||||
|
||||
if err != nil {
|
||||
return ticker.Price{}, err
|
||||
}
|
||||
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.Volume = stats.Volume
|
||||
tickerPrice.Last = tick.Price
|
||||
tickerPrice.High = stats.High
|
||||
tickerPrice.Low = stats.Low
|
||||
tickerPrice = ticker.Price{
|
||||
Last: tick.Size,
|
||||
High: stats.High,
|
||||
Low: stats.Low,
|
||||
Bid: tick.Bid,
|
||||
Ask: tick.Ask,
|
||||
Volume: tick.Volume,
|
||||
Open: stats.Open,
|
||||
Pair: p,
|
||||
LastUpdated: tick.Time,
|
||||
}
|
||||
|
||||
err = ticker.ProcessTicker(c.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
|
||||
@@ -33,7 +33,7 @@ type Ticker struct {
|
||||
Last float64 `json:"last,string"`
|
||||
LowestSell float64 `json:"lowest_sell,string"`
|
||||
OpenInterest float64 `json:"open_interest,string"`
|
||||
Timestamp float64 `json:"timestamp"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
TransID int64 `json:"trans_id"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
Volume24 float64 `json:"volume24,string"`
|
||||
@@ -280,16 +280,23 @@ type wsHeartbeatResp struct {
|
||||
|
||||
// WsTicker defines the resp for ticker updates from the websocket connection
|
||||
type WsTicker struct {
|
||||
HighestBuy float64 `json:"highest_buy,string"`
|
||||
InstID int64 `json:"inst_id"`
|
||||
Last float64 `json:"last,string"`
|
||||
LowestSell float64 `json:"lowest_sell,string"`
|
||||
OpenInterest float64 `json:"open_interest,string"`
|
||||
Reply string `json:"reply"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
TransID int64 `json:"trans_id"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
Volume24H float64 `json:"volume24,string"`
|
||||
High24 float64 `json:"high24,string"`
|
||||
HighestBuy float64 `json:"highest_buy,string"`
|
||||
InstID int64 `json:"inst_id"`
|
||||
Last float64 `json:"last,string"`
|
||||
Low24 float64 `json:"low24,string"`
|
||||
LowestSell float64 `json:"lowest_sell,string"`
|
||||
Nonce int64 `json:"nonce"`
|
||||
PrevTransID int64 `json:"prev_trans_id"`
|
||||
PriceChange24 float64 `json:"price_change_24,string"`
|
||||
Reply string `json:"reply"`
|
||||
Status []string `json:"status"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
TransID int64 `json:"trans_id"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
Volume24 float64 `json:"volume24,string"`
|
||||
Volume24Quote float64 `json:"volume24_quote,string"`
|
||||
VolumeQuote float64 `json:"volume_quote,string"`
|
||||
}
|
||||
|
||||
// WsOrderbookSnapshot defines the resp for orderbook snapshot updates from
|
||||
|
||||
@@ -139,14 +139,15 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
}
|
||||
currencyPair := instrumentListByCode[ticker.InstID]
|
||||
c.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Timestamp: time.Unix(0, ticker.Timestamp),
|
||||
Pair: currency.NewPairFromString(currencyPair),
|
||||
Exchange: c.GetName(),
|
||||
AssetType: asset.Spot,
|
||||
HighPrice: ticker.HighestBuy,
|
||||
LowPrice: ticker.LowestSell,
|
||||
ClosePrice: ticker.Last,
|
||||
Quantity: ticker.Volume,
|
||||
Exchange: c.Name,
|
||||
Volume: ticker.Volume,
|
||||
QuoteVolume: ticker.VolumeQuote,
|
||||
High: ticker.HighestBuy,
|
||||
Low: ticker.LowestSell,
|
||||
Last: ticker.Last,
|
||||
Timestamp: time.Unix(0, ticker.Timestamp),
|
||||
AssetType: asset.Spot,
|
||||
Pair: currency.NewPairFromString(currencyPair),
|
||||
}
|
||||
|
||||
case "inst_order_book":
|
||||
@@ -245,9 +246,9 @@ func (c *COINUT) WsSetInstrumentList() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for currency, data := range list.Spot {
|
||||
instrumentListByString[currency] = data[0].InstID
|
||||
instrumentListByCode[data[0].InstID] = currency
|
||||
for curr, data := range list.Spot {
|
||||
instrumentListByString[curr] = data[0].InstID
|
||||
instrumentListByCode[data[0].InstID] = curr
|
||||
}
|
||||
if len(instrumentListByString) == 0 || len(instrumentListByCode) == 0 {
|
||||
return errors.New("instrument lists failed to populate")
|
||||
@@ -414,11 +415,11 @@ func (c *COINUT) wsSubmitOrder(order *WsSubmitOrderParameters) (*WsStandardOrder
|
||||
if !c.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return nil, fmt.Errorf("%v not authorised to submit order", c.Name)
|
||||
}
|
||||
currency := c.FormatExchangeCurrency(order.Currency, asset.Spot).String()
|
||||
curr := c.FormatExchangeCurrency(order.Currency, asset.Spot).String()
|
||||
var orderSubmissionRequest WsSubmitOrderRequest
|
||||
orderSubmissionRequest.Request = "new_order"
|
||||
orderSubmissionRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
orderSubmissionRequest.InstID = instrumentListByString[currency]
|
||||
orderSubmissionRequest.InstID = instrumentListByString[curr]
|
||||
orderSubmissionRequest.Qty = order.Amount
|
||||
orderSubmissionRequest.Price = order.Price
|
||||
orderSubmissionRequest.Side = string(order.Side)
|
||||
@@ -523,13 +524,13 @@ func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) ([]WsStandardO
|
||||
}
|
||||
orderRequest := WsSubmitOrdersRequest{}
|
||||
for i := range orders {
|
||||
currency := c.FormatExchangeCurrency(orders[i].Currency, asset.Spot).String()
|
||||
curr := c.FormatExchangeCurrency(orders[i].Currency, asset.Spot).String()
|
||||
orderRequest.Orders = append(orderRequest.Orders,
|
||||
WsSubmitOrdersRequestData{
|
||||
Qty: orders[i].Amount,
|
||||
Price: orders[i].Price,
|
||||
Side: string(orders[i].Side),
|
||||
InstID: instrumentListByString[currency],
|
||||
InstID: instrumentListByString[curr],
|
||||
ClientOrdID: i + 1,
|
||||
})
|
||||
}
|
||||
@@ -582,11 +583,11 @@ func (c *COINUT) wsGetOpenOrders(p currency.Pair) error {
|
||||
if !c.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authorised to get open orders", c.Name)
|
||||
}
|
||||
currency := c.FormatExchangeCurrency(p, asset.Spot).String()
|
||||
curr := c.FormatExchangeCurrency(p, asset.Spot).String()
|
||||
var openOrdersRequest WsGetOpenOrdersRequest
|
||||
openOrdersRequest.Request = "user_open_orders"
|
||||
openOrdersRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
openOrdersRequest.InstID = instrumentListByString[currency]
|
||||
openOrdersRequest.InstID = instrumentListByString[curr]
|
||||
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(openOrdersRequest.Nonce, openOrdersRequest)
|
||||
if err != nil {
|
||||
@@ -679,10 +680,10 @@ func (c *COINUT) wsGetTradeHistory(p currency.Pair, start, limit int64) error {
|
||||
if !c.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
return fmt.Errorf("%v not authorised to get trade history", c.Name)
|
||||
}
|
||||
currency := c.FormatExchangeCurrency(p, asset.Spot).String()
|
||||
curr := c.FormatExchangeCurrency(p, asset.Spot).String()
|
||||
var request WsTradeHistoryRequest
|
||||
request.Request = "trade_history"
|
||||
request.InstID = instrumentListByString[currency]
|
||||
request.InstID = instrumentListByString[curr]
|
||||
request.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
request.Start = start
|
||||
request.Limit = limit
|
||||
|
||||
@@ -278,17 +278,18 @@ func (c *COINUT) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (c *COINUT) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
tick, err := c.GetInstrumentTicker(c.InstrumentMap[p.String()])
|
||||
tick, err := c.GetInstrumentTicker(c.InstrumentMap[c.FormatExchangeCurrency(p, assetType).String()])
|
||||
if err != nil {
|
||||
return ticker.Price{}, err
|
||||
return tickerPrice, err
|
||||
}
|
||||
tickerPrice = ticker.Price{
|
||||
Last: tick.Last,
|
||||
High: tick.HighestBuy,
|
||||
Low: tick.LowestSell,
|
||||
Volume: tick.Volume24,
|
||||
Pair: p,
|
||||
LastUpdated: time.Unix(0, tick.Timestamp),
|
||||
}
|
||||
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.Volume = tick.Volume
|
||||
tickerPrice.Last = tick.Last
|
||||
tickerPrice.High = tick.HighestBuy
|
||||
tickerPrice.Low = tick.LowestSell
|
||||
|
||||
err = ticker.ProcessTicker(c.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
|
||||
@@ -68,9 +68,8 @@ func (e *EXMO) GetOrderbook(symbol string) (map[string]Orderbook, error) {
|
||||
}
|
||||
|
||||
// GetTicker returns the ticker for a symbol or symbols
|
||||
func (e *EXMO) GetTicker(symbol string) (map[string]Ticker, error) {
|
||||
func (e *EXMO) GetTicker() (map[string]Ticker, error) {
|
||||
v := url.Values{}
|
||||
v.Set("pair", symbol)
|
||||
result := make(map[string]Ticker)
|
||||
urlPath := fmt.Sprintf("%s/v%s/%s", e.API.Endpoints.URL, exmoAPIVersion, exmoTicker)
|
||||
return result, e.SendHTTPRequest(common.EncodeURLValues(urlPath, v), &result)
|
||||
|
||||
@@ -56,7 +56,7 @@ func TestGetOrderbook(t *testing.T) {
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := e.GetTicker("BTC_USD")
|
||||
_, err := e.GetTicker()
|
||||
if err != nil {
|
||||
t.Errorf("Test failed. Err: %s", err)
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func (e *EXMO) SetDefaults() {
|
||||
Websocket: false,
|
||||
RESTCapabilities: exchange.ProtocolFeatures{
|
||||
AutoPairUpdates: true,
|
||||
TickerBatching: false,
|
||||
TickerBatching: true,
|
||||
},
|
||||
WithdrawPermissions: exchange.AutoWithdrawCryptoWithSetup |
|
||||
exchange.NoFiatWithdrawals,
|
||||
@@ -156,31 +156,32 @@ func (e *EXMO) UpdateTradablePairs(forceUpdate bool) error {
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (e *EXMO) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
pairsCollated, err := e.FormatExchangeCurrencies(e.GetEnabledPairs(assetType), assetType)
|
||||
result, err := e.GetTicker()
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
result, err := e.GetTicker(pairsCollated)
|
||||
if err != nil {
|
||||
if _, ok := result[p.String()]; !ok {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range e.GetEnabledPairs(assetType) {
|
||||
currency := e.FormatExchangeCurrency(x, assetType).String()
|
||||
var tickerPrice ticker.Price
|
||||
tickerPrice.Pair = x
|
||||
tickerPrice.Last = result[currency].Last
|
||||
tickerPrice.Ask = result[currency].Sell
|
||||
tickerPrice.High = result[currency].High
|
||||
tickerPrice.Bid = result[currency].Buy
|
||||
tickerPrice.Last = result[currency].Last
|
||||
tickerPrice.Low = result[currency].Low
|
||||
tickerPrice.Volume = result[currency].Volume
|
||||
|
||||
err = ticker.ProcessTicker(e.Name, &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
pairs := e.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
for j := range result {
|
||||
if !strings.EqualFold(pairs[i].String(), j) {
|
||||
continue
|
||||
}
|
||||
tickerPrice = ticker.Price{
|
||||
Pair: pairs[i],
|
||||
Last: result[j].Last,
|
||||
Ask: result[j].Sell,
|
||||
High: result[j].High,
|
||||
Bid: result[j].Buy,
|
||||
Low: result[j].Low,
|
||||
Volume: result[j].Volume,
|
||||
}
|
||||
err = ticker.ProcessTicker(e.Name, &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ticker.GetTicker(e.Name, p, assetType)
|
||||
|
||||
@@ -70,15 +70,15 @@ type KLineResponse struct {
|
||||
|
||||
// TickerResponse holds the ticker response data
|
||||
type TickerResponse struct {
|
||||
Result string `json:"result"`
|
||||
Volume float64 `json:"baseVolume,string"` // Trading volume
|
||||
High float64 `json:"high24hr,string"` // 24 hour high price
|
||||
Open float64 `json:"highestBid,string"` // Openening price
|
||||
Last float64 `json:"last,string"` // Last price
|
||||
Low float64 `json:"low24hr,string"` // 24 hour low price
|
||||
Close float64 `json:"lowestAsk,string"` // Closing price
|
||||
PercentChange float64 `json:"percentChange,string"` // Percentage change
|
||||
QuoteVolume float64 `json:"quoteVolume,string"` // Quote currency volume
|
||||
Period int64 `json:"period"`
|
||||
BaseVolume float64 `json:"baseVolume,string"`
|
||||
Change float64 `json:"change,string"`
|
||||
Close float64 `json:"close,string"`
|
||||
High float64 `json:"high,string"`
|
||||
Last float64 `json:"last,string"`
|
||||
Low float64 `json:"low,string"`
|
||||
Open float64 `json:"open,string"`
|
||||
QuoteVolume float64 `json:"quoteVolume,string"`
|
||||
}
|
||||
|
||||
// OrderbookResponse stores the orderbook data
|
||||
|
||||
@@ -136,15 +136,16 @@ func (g *Gateio) WsHandleData() {
|
||||
}
|
||||
|
||||
g.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Timestamp: time.Now(),
|
||||
Pair: currency.NewPairFromString(c),
|
||||
AssetType: asset.Spot,
|
||||
Exchange: g.GetName(),
|
||||
ClosePrice: ticker.Close,
|
||||
Quantity: ticker.BaseVolume,
|
||||
OpenPrice: ticker.Open,
|
||||
HighPrice: ticker.High,
|
||||
LowPrice: ticker.Low,
|
||||
Exchange: g.Name,
|
||||
Open: ticker.Open,
|
||||
Close: ticker.Close,
|
||||
Volume: ticker.BaseVolume,
|
||||
QuoteVolume: ticker.QuoteVolume,
|
||||
High: ticker.High,
|
||||
Low: ticker.Low,
|
||||
Last: ticker.Last,
|
||||
AssetType: asset.Spot,
|
||||
Pair: currency.NewPairFromString(c),
|
||||
}
|
||||
|
||||
case strings.Contains(result.Method, "trades"):
|
||||
@@ -238,7 +239,7 @@ func (g *Gateio) WsHandleData() {
|
||||
newOrderBook.Pair = currency.NewPairFromString(c)
|
||||
|
||||
err = g.Websocket.Orderbook.LoadSnapshot(&newOrderBook,
|
||||
false)
|
||||
true)
|
||||
if err != nil {
|
||||
g.Websocket.DataHandler <- err
|
||||
}
|
||||
|
||||
@@ -198,20 +198,26 @@ func (g *Gateio) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pri
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range g.GetEnabledPairs(assetType) {
|
||||
currency := g.FormatExchangeCurrency(x, assetType).String()
|
||||
var tp ticker.Price
|
||||
tp.Pair = x
|
||||
tp.High = result[currency].High
|
||||
tp.Last = result[currency].Last
|
||||
tp.Last = result[currency].Last
|
||||
tp.Low = result[currency].Low
|
||||
tp.Volume = result[currency].Volume
|
||||
|
||||
err = ticker.ProcessTicker(g.Name, &tp, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
pairs := g.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
for k := range result {
|
||||
if !strings.EqualFold(k, pairs[i].String()) {
|
||||
continue
|
||||
}
|
||||
tickerPrice = ticker.Price{
|
||||
Last: result[k].Last,
|
||||
High: result[k].High,
|
||||
Low: result[k].Low,
|
||||
Volume: result[k].BaseVolume,
|
||||
QuoteVolume: result[k].QuoteVolume,
|
||||
Open: result[k].Open,
|
||||
Close: result[k].Close,
|
||||
Pair: pairs[i],
|
||||
}
|
||||
err = ticker.ProcessTicker(g.Name, &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,48 +74,20 @@ func (g *Gemini) GetSymbols() ([]string, error) {
|
||||
}
|
||||
|
||||
// GetTicker returns information about recent trading activity for the symbol
|
||||
func (g *Gemini) GetTicker(currencyPair string) (Ticker, error) {
|
||||
type TickerResponse struct {
|
||||
Ask float64 `json:"ask,string"`
|
||||
Bid float64 `json:"bid,string"`
|
||||
Last float64 `json:"last,string"`
|
||||
Volume map[string]interface{}
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
ticker := Ticker{}
|
||||
resp := TickerResponse{}
|
||||
path := fmt.Sprintf("%s/v%s/%s/%s", g.API.Endpoints.URL, geminiAPIVersion, geminiTicker, currencyPair)
|
||||
|
||||
err := g.SendHTTPRequest(path, &resp)
|
||||
func (g *Gemini) GetTicker(currencyPair string) (TickerV2, error) {
|
||||
ticker := TickerV2{}
|
||||
path := fmt.Sprintf("%s/v2/ticker/%s", g.API.Endpoints.URL, currencyPair)
|
||||
err := g.SendHTTPRequest(path, &ticker)
|
||||
if err != nil {
|
||||
return ticker, err
|
||||
}
|
||||
|
||||
if resp.Message != "" {
|
||||
return ticker, errors.New(resp.Message)
|
||||
if ticker.Result == "error" {
|
||||
return ticker, fmt.Errorf("%v %v %v",
|
||||
g.Name,
|
||||
ticker.Reason,
|
||||
ticker.Message)
|
||||
}
|
||||
|
||||
ticker.Ask = resp.Ask
|
||||
ticker.Bid = resp.Bid
|
||||
ticker.Last = resp.Last
|
||||
ticker.Volume.Currency, _ = strconv.ParseFloat(resp.Volume[currencyPair[0:3]].(string), 64)
|
||||
|
||||
if strings.Contains(currencyPair, "USD") {
|
||||
ticker.Volume.USD, _ = strconv.ParseFloat(resp.Volume["USD"].(string), 64)
|
||||
} else {
|
||||
if resp.Volume["ETH"] != nil {
|
||||
ticker.Volume.ETH, _ = strconv.ParseFloat(resp.Volume["ETH"].(string), 64)
|
||||
}
|
||||
|
||||
if resp.Volume["BTC"] != nil {
|
||||
ticker.Volume.BTC, _ = strconv.ParseFloat(resp.Volume["BTC"].(string), 64)
|
||||
}
|
||||
}
|
||||
|
||||
time, _ := resp.Volume["timestamp"].(float64)
|
||||
ticker.Volume.Timestamp = int64(time)
|
||||
|
||||
return ticker, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,21 @@ type Ticker struct {
|
||||
}
|
||||
}
|
||||
|
||||
// TickerV2 holds returned ticker data from the exchange
|
||||
type TickerV2 struct {
|
||||
Ask float64 `json:"ask,string"`
|
||||
Bid float64 `json:"bid,string"`
|
||||
Changes []string `json:"changes"`
|
||||
Close float64 `json:"close,string"`
|
||||
High float64 `json:"high,string"`
|
||||
Low float64 `json:"low,string"`
|
||||
Open float64 `json:"open,string"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
Result string `json:"result,omitempty"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
}
|
||||
|
||||
// Orderbook contains orderbook information for both bid and ask side
|
||||
type Orderbook struct {
|
||||
Bids []OrderbookEntry `json:"bids"`
|
||||
|
||||
@@ -222,12 +222,15 @@ func (g *Gemini) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pri
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.Ask = tick.Ask
|
||||
tickerPrice.Bid = tick.Bid
|
||||
tickerPrice.Last = tick.Last
|
||||
tickerPrice.Volume = tick.Volume.USD
|
||||
|
||||
tickerPrice = ticker.Price{
|
||||
High: tick.High,
|
||||
Low: tick.Low,
|
||||
Bid: tick.Bid,
|
||||
Ask: tick.Ask,
|
||||
Open: tick.Open,
|
||||
Close: tick.Close,
|
||||
Pair: p,
|
||||
}
|
||||
err = ticker.ProcessTicker(g.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
|
||||
@@ -116,65 +116,17 @@ func (h *HitBTC) GetSymbolsDetailed() ([]Symbol, error) {
|
||||
}
|
||||
|
||||
// GetTicker returns ticker information
|
||||
func (h *HitBTC) GetTicker(symbol string) (map[string]Ticker, error) {
|
||||
var resp1 []TickerResponse
|
||||
resp2 := TickerResponse{}
|
||||
ret := make(map[string]TickerResponse)
|
||||
result := make(map[string]Ticker)
|
||||
func (h *HitBTC) GetTicker(symbol string) (TickerResponse, error) {
|
||||
var resp TickerResponse
|
||||
path := fmt.Sprintf("%s/%s/%s", h.API.Endpoints.URL, apiV2Ticker, symbol)
|
||||
var err error
|
||||
return resp, h.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
if symbol == "" {
|
||||
err = h.SendHTTPRequest(path, &resp1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range resp1 {
|
||||
if resp1[i].Symbol != "" {
|
||||
ret[resp1[i].Symbol] = resp1[i]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = h.SendHTTPRequest(path, &resp2)
|
||||
ret[resp2.Symbol] = resp2
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
for i := range ret {
|
||||
tick := Ticker{}
|
||||
|
||||
ask, _ := strconv.ParseFloat(ret[i].Ask, 64)
|
||||
tick.Ask = ask
|
||||
|
||||
bid, _ := strconv.ParseFloat(ret[i].Bid, 64)
|
||||
tick.Bid = bid
|
||||
|
||||
high, _ := strconv.ParseFloat(ret[i].High, 64)
|
||||
tick.High = high
|
||||
|
||||
last, _ := strconv.ParseFloat(ret[i].Last, 64)
|
||||
tick.Last = last
|
||||
|
||||
low, _ := strconv.ParseFloat(ret[i].Low, 64)
|
||||
tick.Low = low
|
||||
|
||||
open, _ := strconv.ParseFloat(ret[i].Open, 64)
|
||||
tick.Open = open
|
||||
|
||||
vol, _ := strconv.ParseFloat(ret[i].Volume, 64)
|
||||
tick.Volume = vol
|
||||
|
||||
volQuote, _ := strconv.ParseFloat(ret[i].VolumeQuote, 64)
|
||||
tick.VolumeQuote = volQuote
|
||||
|
||||
tick.Symbol = ret[i].Symbol
|
||||
tick.Timestamp = ret[i].Timestamp
|
||||
result[i] = tick
|
||||
}
|
||||
}
|
||||
|
||||
return result, err
|
||||
// GetTickers returns ticker information
|
||||
func (h *HitBTC) GetTickers() ([]TickerResponse, error) {
|
||||
var resp []TickerResponse
|
||||
path := fmt.Sprintf("%s/%s/", h.API.Endpoints.URL, apiV2Ticker)
|
||||
return resp, h.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetTrades returns trades from hitbtc
|
||||
|
||||
@@ -97,6 +97,20 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAllTickers(t *testing.T) {
|
||||
_, err := h.GetTickers()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSingularTicker(t *testing.T) {
|
||||
_, err := h.GetTicker("BTCUSD")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
h.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
@@ -6,32 +6,18 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
// Ticker holds ticker information
|
||||
type Ticker struct {
|
||||
Last float64
|
||||
Ask float64
|
||||
Bid float64
|
||||
Timestamp time.Time
|
||||
Volume float64
|
||||
VolumeQuote float64
|
||||
Symbol string
|
||||
High float64
|
||||
Low float64
|
||||
Open float64
|
||||
}
|
||||
|
||||
// TickerResponse is the response type
|
||||
type TickerResponse struct {
|
||||
Last string `json:"last"` // Last trade price
|
||||
Ask string `json:"ask"` // Best ask price
|
||||
Bid string `json:"bid"` // Best bid price
|
||||
Timestamp time.Time `json:"timestamp,string"` // Last update or refresh ticker timestamp
|
||||
Volume string `json:"volume"` // Total trading amount within 24 hours in base currency
|
||||
VolumeQuote string `json:"volumeQuote"` // Total trading amount within 24 hours in quote currency
|
||||
Symbol string `json:"symbol"`
|
||||
High string `json:"high"` // Highest trade price within 24 hours
|
||||
Low string `json:"low"` // Lowest trade price within 24 hours
|
||||
Open string `json:"open"` // Last trade price 24 hours ago
|
||||
Ask float64 `json:"ask,string"`
|
||||
Bid float64 `json:"bid,string"`
|
||||
High float64 `json:"high,string"`
|
||||
Last float64 `json:"last,string"`
|
||||
Low float64 `json:"low,string"`
|
||||
Open float64 `json:"open,string"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
VolumeQuote float64 `json:"volumeQuote,string"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
// Symbol holds symbol data
|
||||
@@ -336,16 +322,16 @@ type params struct {
|
||||
// WsTicker defines websocket ticker feed return params
|
||||
type WsTicker struct {
|
||||
Params struct {
|
||||
Ask float64 `json:"ask,string"`
|
||||
Bid float64 `json:"bid,string"`
|
||||
Last float64 `json:"last,string"`
|
||||
Open float64 `json:"open,string"`
|
||||
Low float64 `json:"low,string"`
|
||||
High float64 `json:"high,string"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
VolumeQuote float64 `json:"volumeQuote,string"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Symbol string `json:"symbol"`
|
||||
Ask float64 `json:"ask,string"`
|
||||
Bid float64 `json:"bid,string"`
|
||||
Last float64 `json:"last,string"`
|
||||
Open float64 `json:"open,string"`
|
||||
Low float64 `json:"low,string"`
|
||||
High float64 `json:"high,string"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
VolumeQuote float64 `json:"volumeQuote,string"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
} `json:"params"`
|
||||
}
|
||||
|
||||
|
||||
@@ -116,14 +116,18 @@ func (h *HitBTC) handleSubscriptionUpdates(resp wshandler.WebsocketResponse, ini
|
||||
return
|
||||
}
|
||||
h.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Exchange: h.GetName(),
|
||||
AssetType: asset.Spot,
|
||||
Pair: currency.NewPairFromString(ticker.Params.Symbol),
|
||||
Quantity: ticker.Params.Volume,
|
||||
Timestamp: ts,
|
||||
OpenPrice: ticker.Params.Open,
|
||||
HighPrice: ticker.Params.High,
|
||||
LowPrice: ticker.Params.Low,
|
||||
Exchange: h.Name,
|
||||
Open: ticker.Params.Open,
|
||||
Volume: ticker.Params.Volume,
|
||||
QuoteVolume: ticker.Params.VolumeQuote,
|
||||
High: ticker.Params.High,
|
||||
Low: ticker.Params.Low,
|
||||
Bid: ticker.Params.Bid,
|
||||
Ask: ticker.Params.Ask,
|
||||
Last: ticker.Params.Last,
|
||||
Timestamp: ts,
|
||||
AssetType: asset.Spot,
|
||||
Pair: ticker.Params.Symbol,
|
||||
}
|
||||
case "snapshotOrderbook":
|
||||
var obSnapshot WsOrderbook
|
||||
|
||||
@@ -196,7 +196,7 @@ func (h *HitBTC) FetchTradablePairs(asset asset.Item) ([]string, error) {
|
||||
|
||||
var pairs []string
|
||||
for x := range symbols {
|
||||
pairs = append(pairs, symbols[x].BaseCurrency+"-"+symbols[x].QuoteCurrency)
|
||||
pairs = append(pairs, fmt.Sprintf("%v%v%v", symbols[x].BaseCurrency, h.GetPairFormat(asset, false).Delimiter, symbols[x].QuoteCurrency))
|
||||
}
|
||||
return pairs, nil
|
||||
}
|
||||
@@ -214,25 +214,33 @@ func (h *HitBTC) UpdateTradablePairs(forceUpdate bool) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (h *HitBTC) UpdateTicker(currencyPair currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
tick, err := h.GetTicker("")
|
||||
var tickerPrice ticker.Price
|
||||
tick, err := h.GetTickers()
|
||||
if err != nil {
|
||||
return ticker.Price{}, err
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range h.GetEnabledPairs(assetType) {
|
||||
var tp ticker.Price
|
||||
curr := h.FormatExchangeCurrency(x, assetType).String()
|
||||
tp.Pair = x
|
||||
tp.Ask = tick[curr].Ask
|
||||
tp.Bid = tick[curr].Bid
|
||||
tp.High = tick[curr].High
|
||||
tp.Last = tick[curr].Last
|
||||
tp.Low = tick[curr].Low
|
||||
tp.Volume = tick[curr].Volume
|
||||
|
||||
err = ticker.ProcessTicker(h.GetName(), &tp, assetType)
|
||||
if err != nil {
|
||||
return ticker.Price{}, err
|
||||
pairs := h.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
for j := range tick {
|
||||
if !tick[j].Symbol.Equal(pairs[i]) {
|
||||
continue
|
||||
}
|
||||
tickerPrice := ticker.Price{
|
||||
Last: tick[j].Last,
|
||||
High: tick[j].High,
|
||||
Low: tick[j].Low,
|
||||
Bid: tick[j].Bid,
|
||||
Ask: tick[j].Ask,
|
||||
Volume: tick[j].Volume,
|
||||
QuoteVolume: tick[j].VolumeQuote,
|
||||
Open: tick[j].Open,
|
||||
Pair: pairs[i],
|
||||
LastUpdated: tick[j].Timestamp,
|
||||
}
|
||||
err = ticker.ProcessTicker(h.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ticker.GetTicker(h.Name, currencyPair, assetType)
|
||||
|
||||
@@ -32,6 +32,7 @@ const (
|
||||
huobiMarketDetailMerged = "market/detail/merged"
|
||||
huobiMarketDepth = "market/depth"
|
||||
huobiMarketTrade = "market/trade"
|
||||
huobiMarketTickers = "market/tickers"
|
||||
huobiMarketTradeHistory = "market/history/trade"
|
||||
huobiSymbols = "common/symbols"
|
||||
huobiCurrencies = "common/currencys"
|
||||
@@ -95,6 +96,13 @@ func (h *HUOBI) GetSpotKline(arg KlinesRequestParams) ([]KlineItem, error) {
|
||||
return result.Data, err
|
||||
}
|
||||
|
||||
// GetTickers returns the ticker for the specified symbol
|
||||
func (h *HUOBI) GetTickers() (Tickers, error) {
|
||||
var result Tickers
|
||||
urlPath := fmt.Sprintf("%s/%s", h.API.Endpoints.URL, huobiMarketTickers)
|
||||
return result, h.SendHTTPRequest(urlPath, &result)
|
||||
}
|
||||
|
||||
// GetMarketDetailMerged returns the ticker for the specified symbol
|
||||
func (h *HUOBI) GetMarketDetailMerged(symbol string) (DetailMerged, error) {
|
||||
vals := url.Values{}
|
||||
|
||||
@@ -170,6 +170,13 @@ func TestGetCurrencies(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
_, err := h.GetTickers()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTimestamp(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := h.GetTimestamp()
|
||||
|
||||
@@ -19,7 +19,7 @@ type KlineItem struct {
|
||||
Low float64 `json:"low"`
|
||||
High float64 `json:"high"`
|
||||
Amount float64 `json:"amount"`
|
||||
Vol float64 `json:"vol"`
|
||||
Volume float64 `json:"vol"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
@@ -42,6 +42,23 @@ type DetailMerged struct {
|
||||
Bid []float64 `json:"bid"`
|
||||
}
|
||||
|
||||
// Tickers contain all tickers
|
||||
type Tickers struct {
|
||||
Data []Ticker `json:"data"`
|
||||
}
|
||||
|
||||
// Ticker latest ticker data
|
||||
type Ticker struct {
|
||||
Amount float64 `json:"amount"`
|
||||
Close float64 `json:"close"`
|
||||
Count int64 `json:"count"`
|
||||
High float64 `json:"high"`
|
||||
Low float64 `json:"low"`
|
||||
Open float64 `json:"open"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
Volume float64 `json:"vol"`
|
||||
}
|
||||
|
||||
// OrderBookDataRequestParamsType var for request param types
|
||||
type OrderBookDataRequestParamsType string
|
||||
|
||||
@@ -322,6 +339,22 @@ type WsKline struct {
|
||||
}
|
||||
}
|
||||
|
||||
type WsTick struct {
|
||||
Channel string `json:"ch"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Tick struct {
|
||||
Amount float64 `json:"amount"`
|
||||
Close float64 `json:"close"`
|
||||
Count float64 `json:"count"`
|
||||
High float64 `json:"high"`
|
||||
ID float64 `json:"id"`
|
||||
Low float64 `json:"low"`
|
||||
Open float64 `json:"open"`
|
||||
Timestamp float64 `json:"ts"`
|
||||
Volume float64 `json:"vol"`
|
||||
} `json:"tick"`
|
||||
}
|
||||
|
||||
// WsTrade defines market trade websocket response
|
||||
type WsTrade struct {
|
||||
Channel string `json:"ch"`
|
||||
|
||||
@@ -23,10 +23,11 @@ import (
|
||||
const (
|
||||
baseWSURL = "wss://api.huobi.pro"
|
||||
|
||||
wsMarketURL = baseWSURL + "/ws"
|
||||
wsMarketKline = "market.%s.kline.1min"
|
||||
wsMarketDepth = "market.%s.depth.step0"
|
||||
wsMarketTrade = "market.%s.trade.detail"
|
||||
wsMarketURL = baseWSURL + "/ws"
|
||||
wsMarketKline = "market.%s.kline.1min"
|
||||
wsMarketDepth = "market.%s.depth.step0"
|
||||
wsMarketTrade = "market.%s.trade.detail"
|
||||
wsMarketTicker = "market.%s.detail"
|
||||
|
||||
wsAccountsOrdersEndPoint = "/ws/v1"
|
||||
wsAccountsList = "accounts.list"
|
||||
@@ -253,7 +254,7 @@ func (h *HUOBI) wsHandleMarketData(resp WsMessage) {
|
||||
LowPrice: kline.Tick.Low,
|
||||
Volume: kline.Tick.Volume,
|
||||
}
|
||||
case strings.Contains(init.Channel, "trade"):
|
||||
case strings.Contains(init.Channel, "trade.detail"):
|
||||
var trade WsTrade
|
||||
err := common.JSONDecode(resp.Raw, &trade)
|
||||
if err != nil {
|
||||
@@ -267,6 +268,26 @@ func (h *HUOBI) wsHandleMarketData(resp WsMessage) {
|
||||
CurrencyPair: currency.NewPairFromString(data[1]),
|
||||
Timestamp: time.Unix(0, trade.Tick.Timestamp),
|
||||
}
|
||||
case strings.Contains(init.Channel, "detail"):
|
||||
var ticker WsTick
|
||||
err := common.JSONDecode(resp.Raw, &ticker)
|
||||
if err != nil {
|
||||
h.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
data := strings.Split(ticker.Channel, ".")
|
||||
h.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Exchange: h.Name,
|
||||
Open: ticker.Tick.Open,
|
||||
Close: ticker.Tick.Close,
|
||||
Volume: ticker.Tick.Amount,
|
||||
QuoteVolume: ticker.Tick.Volume,
|
||||
High: ticker.Tick.High,
|
||||
Low: ticker.Tick.Low,
|
||||
Timestamp: time.Unix(0, ticker.Timestamp),
|
||||
AssetType: asset.Spot,
|
||||
Pair: currency.NewPairFromString(data[1]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,7 +324,7 @@ func (h *HUOBI) WsProcessOrderbook(update *WsDepth, symbol string) error {
|
||||
|
||||
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
|
||||
func (h *HUOBI) GenerateDefaultSubscriptions() {
|
||||
var channels = []string{wsMarketKline, wsMarketDepth, wsMarketTrade}
|
||||
var channels = []string{wsMarketKline, wsMarketDepth, wsMarketTrade, wsMarketTicker}
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
if h.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
channels = append(channels, "orders.%v", "orders.%v.update")
|
||||
|
||||
@@ -72,7 +72,7 @@ func (h *HUOBI) SetDefaults() {
|
||||
Websocket: true,
|
||||
RESTCapabilities: exchange.ProtocolFeatures{
|
||||
AutoPairUpdates: true,
|
||||
TickerBatching: false,
|
||||
TickerBatching: true,
|
||||
},
|
||||
WithdrawPermissions: exchange.AutoWithdrawCryptoWithSetup |
|
||||
exchange.NoFiatWithdrawals,
|
||||
@@ -228,7 +228,7 @@ func (h *HUOBI) FetchTradablePairs(asset asset.Item) ([]string, error) {
|
||||
|
||||
var pairs []string
|
||||
for x := range symbols {
|
||||
pairs = append(pairs, symbols[x].BaseCurrency+"-"+symbols[x].QuoteCurrency)
|
||||
pairs = append(pairs, fmt.Sprintf("%v%v%v", symbols[x].BaseCurrency, h.GetPairFormat(asset, false).Delimiter, symbols[x].QuoteCurrency))
|
||||
}
|
||||
|
||||
return pairs, nil
|
||||
@@ -248,28 +248,29 @@ func (h *HUOBI) UpdateTradablePairs(forceUpdate bool) error {
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (h *HUOBI) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
tick, err := h.GetMarketDetailMerged(h.FormatExchangeCurrency(p, assetType).String())
|
||||
tickers, err := h.GetTickers()
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.Low = tick.Low
|
||||
tickerPrice.Last = tick.Close
|
||||
tickerPrice.Volume = tick.Volume
|
||||
tickerPrice.High = tick.High
|
||||
|
||||
if len(tick.Ask) > 0 {
|
||||
tickerPrice.Ask = tick.Ask[0]
|
||||
}
|
||||
|
||||
if len(tick.Bid) > 0 {
|
||||
tickerPrice.Bid = tick.Bid[0]
|
||||
}
|
||||
|
||||
err = ticker.ProcessTicker(h.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
pairs := h.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
for j := range tickers.Data {
|
||||
if !pairs[i].Equal(tickers.Data[j].Symbol) {
|
||||
continue
|
||||
}
|
||||
tickerPrice := ticker.Price{
|
||||
High: tickers.Data[j].High,
|
||||
Low: tickers.Data[j].Low,
|
||||
Volume: tickers.Data[j].Volume,
|
||||
Open: tickers.Data[j].Open,
|
||||
Close: tickers.Data[j].Close,
|
||||
Pair: tickers.Data[j].Symbol,
|
||||
}
|
||||
err = ticker.ProcessTicker(h.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ticker.GetTicker(h.Name, p, assetType)
|
||||
|
||||
@@ -28,6 +28,7 @@ const (
|
||||
huobihadaxMarketDetail = "market/detail"
|
||||
huobihadaxMarketDetailMerged = "market/detail/merged"
|
||||
huobihadaxMarketDepth = "market/depth"
|
||||
huobihadaxMarketTicker = "market/tickers"
|
||||
huobihadaxMarketTrade = "market/trade"
|
||||
huobihadaxMarketTradeHistory = "market/history/trade"
|
||||
huobihadaxSymbols = "common/symbols"
|
||||
@@ -252,6 +253,13 @@ func (h *HUOBIHADAX) GetCurrencies() ([]string, error) {
|
||||
return result.Currencies, err
|
||||
}
|
||||
|
||||
// GetTickers returns the ticker for the specified symbol
|
||||
func (h *HUOBIHADAX) GetTickers() (Tickers, error) {
|
||||
var result Tickers
|
||||
urlPath := fmt.Sprintf("%s/%s", h.API.Endpoints.URL, huobihadaxMarketTicker)
|
||||
return result, h.SendHTTPRequest(urlPath, &result)
|
||||
}
|
||||
|
||||
// GetTimestamp returns the Huobi server time
|
||||
func (h *HUOBIHADAX) GetTimestamp() (int64, error) {
|
||||
type response struct {
|
||||
|
||||
@@ -215,6 +215,13 @@ func TestGetCurrencies(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
_, err := h.GetTickers()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTimestamp(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := h.GetTimestamp()
|
||||
|
||||
@@ -21,10 +21,43 @@ type KlineItem struct {
|
||||
Low float64 `json:"low"`
|
||||
High float64 `json:"high"`
|
||||
Amount float64 `json:"amount"`
|
||||
Vol float64 `json:"vol"`
|
||||
Volume float64 `json:"vol"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
type WsTick struct {
|
||||
Channel string `json:"ch"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Tick struct {
|
||||
Amount float64 `json:"amount"`
|
||||
Close float64 `json:"close"`
|
||||
Count float64 `json:"count"`
|
||||
High float64 `json:"high"`
|
||||
ID float64 `json:"id"`
|
||||
Low float64 `json:"low"`
|
||||
Open float64 `json:"open"`
|
||||
Timestamp float64 `json:"ts"`
|
||||
Volume float64 `json:"vol"`
|
||||
} `json:"tick"`
|
||||
}
|
||||
|
||||
// Tickers contain all tickers
|
||||
type Tickers struct {
|
||||
Data []Ticker `json:"data"`
|
||||
}
|
||||
|
||||
// Ticker latest ticker data
|
||||
type Ticker struct {
|
||||
Amount float64 `json:"amount"`
|
||||
Close float64 `json:"close"`
|
||||
Count int64 `json:"count"`
|
||||
High float64 `json:"high"`
|
||||
Low float64 `json:"low"`
|
||||
Open float64 `json:"open"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
Volume float64 `json:"vol"`
|
||||
}
|
||||
|
||||
// DetailMerged stores the ticker detail merged data
|
||||
type DetailMerged struct {
|
||||
Detail
|
||||
|
||||
@@ -25,6 +25,7 @@ const (
|
||||
wsMarketKline = "market.%s.kline.1min"
|
||||
wsMarketDepth = "market.%s.depth.step0"
|
||||
wsMarketTrade = "market.%s.trade.detail"
|
||||
wsMarketTicker = "market.%s.detail"
|
||||
|
||||
wsAccountsOrdersBaseURL = "wss://api.huobi.pro"
|
||||
wsAccountsOrdersEndPoint = "/ws/v1"
|
||||
@@ -254,7 +255,7 @@ func (h *HUOBIHADAX) wsHandleMarketData(resp WsMessage) {
|
||||
LowPrice: kline.Tick.Low,
|
||||
Volume: kline.Tick.Volume,
|
||||
}
|
||||
case strings.Contains(init.Channel, "trade"):
|
||||
case strings.Contains(init.Channel, "trade.detail"):
|
||||
var trade WsTrade
|
||||
err := common.JSONDecode(resp.Raw, &trade)
|
||||
if err != nil {
|
||||
@@ -268,6 +269,26 @@ func (h *HUOBIHADAX) wsHandleMarketData(resp WsMessage) {
|
||||
CurrencyPair: currency.NewPairFromString(data[1]),
|
||||
Timestamp: time.Unix(0, trade.Tick.Timestamp),
|
||||
}
|
||||
case strings.Contains(init.Channel, "detail"):
|
||||
var ticker WsTick
|
||||
err := common.JSONDecode(resp.Raw, &ticker)
|
||||
if err != nil {
|
||||
h.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
data := strings.Split(ticker.Channel, ".")
|
||||
h.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Exchange: h.Name,
|
||||
Open: ticker.Tick.Open,
|
||||
Close: ticker.Tick.Close,
|
||||
Volume: ticker.Tick.Amount,
|
||||
QuoteVolume: ticker.Tick.Volume,
|
||||
High: ticker.Tick.High,
|
||||
Low: ticker.Tick.Low,
|
||||
Timestamp: time.Unix(0, ticker.Timestamp),
|
||||
AssetType: asset.Spot,
|
||||
Pair: currency.NewPairFromString(data[1]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,7 +325,7 @@ func (h *HUOBIHADAX) WsProcessOrderbook(update *WsDepth, symbol string) error {
|
||||
|
||||
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
|
||||
func (h *HUOBIHADAX) GenerateDefaultSubscriptions() {
|
||||
var channels = []string{wsMarketKline, wsMarketDepth, wsMarketTrade}
|
||||
var channels = []string{wsMarketKline, wsMarketDepth, wsMarketTrade, wsMarketTicker}
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
if h.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
channels = append(channels, "orders.%v", "orders.%v.update")
|
||||
|
||||
@@ -72,7 +72,7 @@ func (h *HUOBIHADAX) SetDefaults() {
|
||||
Websocket: true,
|
||||
RESTCapabilities: exchange.ProtocolFeatures{
|
||||
AutoPairUpdates: true,
|
||||
TickerBatching: false,
|
||||
TickerBatching: true,
|
||||
},
|
||||
WithdrawPermissions: exchange.AutoWithdrawCryptoWithSetup |
|
||||
exchange.NoFiatWithdrawals,
|
||||
@@ -191,7 +191,7 @@ func (h *HUOBIHADAX) FetchTradablePairs(asset asset.Item) ([]string, error) {
|
||||
|
||||
var pairs []string
|
||||
for x := range symbols {
|
||||
pairs = append(pairs, symbols[x].BaseCurrency+"-"+symbols[x].QuoteCurrency)
|
||||
pairs = append(pairs, fmt.Sprintf("%v%v%v", symbols[x].BaseCurrency, h.GetPairFormat(asset, false).Delimiter, symbols[x].QuoteCurrency))
|
||||
}
|
||||
|
||||
return pairs, nil
|
||||
@@ -211,28 +211,29 @@ func (h *HUOBIHADAX) UpdateTradablePairs(forceUpdate bool) error {
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (h *HUOBIHADAX) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
tick, err := h.GetMarketDetailMerged(h.FormatExchangeCurrency(p, assetType).String())
|
||||
tickers, err := h.GetTickers()
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.Low = tick.Low
|
||||
tickerPrice.Last = tick.Close
|
||||
tickerPrice.Volume = tick.Volume
|
||||
tickerPrice.High = tick.High
|
||||
|
||||
if len(tick.Ask) > 0 {
|
||||
tickerPrice.Ask = tick.Ask[0]
|
||||
}
|
||||
|
||||
if len(tick.Bid) > 0 {
|
||||
tickerPrice.Bid = tick.Bid[0]
|
||||
}
|
||||
|
||||
err = ticker.ProcessTicker(h.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
pairs := h.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
for j := range tickers.Data {
|
||||
if !pairs[i].Equal(tickers.Data[j].Symbol) {
|
||||
continue
|
||||
}
|
||||
tickerPrice := ticker.Price{
|
||||
High: tickers.Data[j].High,
|
||||
Low: tickers.Data[j].Low,
|
||||
Volume: tickers.Data[j].Volume,
|
||||
Open: tickers.Data[j].Open,
|
||||
Close: tickers.Data[j].Close,
|
||||
Pair: tickers.Data[j].Symbol,
|
||||
}
|
||||
err = ticker.ProcessTicker(h.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ticker.GetTicker(h.Name, p, assetType)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package itbit
|
||||
|
||||
import "time"
|
||||
|
||||
// GeneralReturn is a generalized return type to capture any errors
|
||||
type GeneralReturn struct {
|
||||
Code int `json:"code"`
|
||||
@@ -9,23 +11,23 @@ type GeneralReturn struct {
|
||||
|
||||
// Ticker holds returned ticker information
|
||||
type Ticker struct {
|
||||
Pair string `json:"pair"`
|
||||
Bid float64 `json:"bid,string"`
|
||||
BidAmt float64 `json:"bidAmt,string"`
|
||||
Ask float64 `json:"ask,string"`
|
||||
AskAmt float64 `json:"askAmt,string"`
|
||||
LastPrice float64 `json:"lastPrice,string"`
|
||||
LastAmt float64 `json:"lastAmt,string"`
|
||||
Volume24h float64 `json:"volume24h,string"`
|
||||
VolumeToday float64 `json:"volumeToday,string"`
|
||||
High24h float64 `json:"high24h,string"`
|
||||
Low24h float64 `json:"low24h,string"`
|
||||
HighToday float64 `json:"highToday,string"`
|
||||
LowToday float64 `json:"lowToday,string"`
|
||||
OpenToday float64 `json:"openToday,string"`
|
||||
VwapToday float64 `json:"vwapToday,string"`
|
||||
Vwap24h float64 `json:"vwap24h,string"`
|
||||
ServertimeUTC string `json:"serverTimeUTC"`
|
||||
Pair string `json:"pair"`
|
||||
Bid float64 `json:"bid,string"`
|
||||
BidAmt float64 `json:"bidAmt,string"`
|
||||
Ask float64 `json:"ask,string"`
|
||||
AskAmt float64 `json:"askAmt,string"`
|
||||
LastPrice float64 `json:"lastPrice,string"`
|
||||
LastAmt float64 `json:"lastAmt,string"`
|
||||
Volume24h float64 `json:"volume24h,string"`
|
||||
VolumeToday float64 `json:"volumeToday,string"`
|
||||
High24h float64 `json:"high24h,string"`
|
||||
Low24h float64 `json:"low24h,string"`
|
||||
HighToday float64 `json:"highToday,string"`
|
||||
LowToday float64 `json:"lowToday,string"`
|
||||
OpenToday float64 `json:"openToday,string"`
|
||||
VwapToday float64 `json:"vwapToday,string"`
|
||||
Vwap24h float64 `json:"vwap24h,string"`
|
||||
ServertimeUTC time.Time `json:"serverTimeUTC"`
|
||||
}
|
||||
|
||||
// OrderbookResponse contains multi-arrayed strings of bid and ask side
|
||||
|
||||
@@ -133,15 +133,17 @@ func (i *ItBit) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pric
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.Ask = tick.Ask
|
||||
tickerPrice.Bid = tick.Bid
|
||||
tickerPrice.Last = tick.LastPrice
|
||||
tickerPrice.High = tick.High24h
|
||||
tickerPrice.Low = tick.Low24h
|
||||
tickerPrice.Volume = tick.Volume24h
|
||||
|
||||
tickerPrice = ticker.Price{
|
||||
Last: tick.LastPrice,
|
||||
High: tick.High24h,
|
||||
Low: tick.Low24h,
|
||||
Bid: tick.Bid,
|
||||
Ask: tick.Ask,
|
||||
Volume: tick.Volume24h,
|
||||
Open: tick.OpenToday,
|
||||
Pair: p,
|
||||
LastUpdated: tick.ServertimeUTC,
|
||||
}
|
||||
err = ticker.ProcessTicker(i.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
|
||||
@@ -51,6 +51,8 @@ const (
|
||||
krakenUnauthRate = 0
|
||||
)
|
||||
|
||||
var assetPairMap map[string]string
|
||||
|
||||
// Kraken is the overarching type across the alphapoint package
|
||||
type Kraken struct {
|
||||
exchange.Base
|
||||
@@ -102,6 +104,12 @@ func (k *Kraken) GetAssetPairs() (map[string]AssetPairs, error) {
|
||||
if err := k.SendHTTPRequest(path, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
for i := range response.Result {
|
||||
if assetPairMap == nil {
|
||||
assetPairMap = make(map[string]string)
|
||||
}
|
||||
assetPairMap[i] = response.Result[i].Altname
|
||||
}
|
||||
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
@@ -134,7 +142,7 @@ func (k *Kraken) GetTicker(symbol string) (Ticker, error) {
|
||||
tick.Bid, _ = strconv.ParseFloat(resp.Data[i].Bid[0], 64)
|
||||
tick.Last, _ = strconv.ParseFloat(resp.Data[i].Last[0], 64)
|
||||
tick.Volume, _ = strconv.ParseFloat(resp.Data[i].Volume[1], 64)
|
||||
tick.VWAP, _ = strconv.ParseFloat(resp.Data[i].VWAP[1], 64)
|
||||
tick.VolumeWeightedAveragePrice, _ = strconv.ParseFloat(resp.Data[i].VolumeWeightedAveragePrice[1], 64)
|
||||
tick.Trades = resp.Data[i].Trades[1]
|
||||
tick.Low, _ = strconv.ParseFloat(resp.Data[i].Low[1], 64)
|
||||
tick.High, _ = strconv.ParseFloat(resp.Data[i].High[1], 64)
|
||||
@@ -175,7 +183,7 @@ func (k *Kraken) GetTickers(pairList string) (Tickers, error) {
|
||||
tick.Bid, _ = strconv.ParseFloat(resp.Data[i].Bid[0], 64)
|
||||
tick.Last, _ = strconv.ParseFloat(resp.Data[i].Last[0], 64)
|
||||
tick.Volume, _ = strconv.ParseFloat(resp.Data[i].Volume[1], 64)
|
||||
tick.VWAP, _ = strconv.ParseFloat(resp.Data[i].VWAP[1], 64)
|
||||
tick.VolumeWeightedAveragePrice, _ = strconv.ParseFloat(resp.Data[i].VolumeWeightedAveragePrice[1], 64)
|
||||
tick.Trades = resp.Data[i].Trades[1]
|
||||
tick.Low, _ = strconv.ParseFloat(resp.Data[i].Low[1], 64)
|
||||
tick.High, _ = strconv.ParseFloat(resp.Data[i].High[1], 64)
|
||||
@@ -224,7 +232,7 @@ func (k *Kraken) GetOHLC(symbol string) ([]OpenHighLowClose, error) {
|
||||
case 4:
|
||||
o.Close, _ = strconv.ParseFloat(x.(string), 64)
|
||||
case 5:
|
||||
o.Vwap, _ = strconv.ParseFloat(x.(string), 64)
|
||||
o.VolumeWeightedAveragePrice, _ = strconv.ParseFloat(x.(string), 64)
|
||||
case 6:
|
||||
o.Volume, _ = strconv.ParseFloat(x.(string), 64)
|
||||
case 7:
|
||||
@@ -767,8 +775,8 @@ func (k *Kraken) AddOrder(symbol, side, orderType string, volume, price, price2,
|
||||
params.Set("leverage", strconv.FormatFloat(leverage, 'f', -1, 64))
|
||||
}
|
||||
|
||||
if args.Oflags != "" {
|
||||
params.Set("oflags", args.Oflags)
|
||||
if args.OrderFlags != "" {
|
||||
params.Set("oflags", args.OrderFlags)
|
||||
}
|
||||
|
||||
if args.StartTm != "" {
|
||||
|
||||
@@ -235,7 +235,7 @@ func TestGetTradeVolume(t *testing.T) {
|
||||
// TestAddOrder API endpoint test
|
||||
func TestAddOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
args := AddOrderOptions{Oflags: "fcib"}
|
||||
args := AddOrderOptions{OrderFlags: "fcib"}
|
||||
_, err := k.AddOrder("XXBTZUSD",
|
||||
exchange.SellOrderSide.ToLower().ToString(), exchange.LimitOrderType.ToLower().ToString(),
|
||||
0.00000001, 0, 0, 0, &args)
|
||||
|
||||
@@ -38,15 +38,15 @@ type AssetPairs struct {
|
||||
|
||||
// Ticker is a standard ticker type
|
||||
type Ticker struct {
|
||||
Ask float64
|
||||
Bid float64
|
||||
Last float64
|
||||
Volume float64
|
||||
VWAP float64
|
||||
Trades int64
|
||||
Low float64
|
||||
High float64
|
||||
Open float64
|
||||
Ask float64
|
||||
Bid float64
|
||||
Last float64
|
||||
Volume float64
|
||||
VolumeWeightedAveragePrice float64
|
||||
Trades int64
|
||||
Low float64
|
||||
High float64
|
||||
Open float64
|
||||
}
|
||||
|
||||
// Tickers stores a map of tickers
|
||||
@@ -54,27 +54,27 @@ type Tickers map[string]Ticker
|
||||
|
||||
// TickerResponse holds ticker information before its put into the Ticker struct
|
||||
type TickerResponse struct {
|
||||
Ask []string `json:"a"`
|
||||
Bid []string `json:"b"`
|
||||
Last []string `json:"c"`
|
||||
Volume []string `json:"v"`
|
||||
VWAP []string `json:"p"`
|
||||
Trades []int64 `json:"t"`
|
||||
Low []string `json:"l"`
|
||||
High []string `json:"h"`
|
||||
Open string `json:"o"`
|
||||
Ask []string `json:"a"`
|
||||
Bid []string `json:"b"`
|
||||
Last []string `json:"c"`
|
||||
Volume []string `json:"v"`
|
||||
VolumeWeightedAveragePrice []string `json:"p"`
|
||||
Trades []int64 `json:"t"`
|
||||
Low []string `json:"l"`
|
||||
High []string `json:"h"`
|
||||
Open string `json:"o"`
|
||||
}
|
||||
|
||||
// OpenHighLowClose contains ticker event information
|
||||
type OpenHighLowClose struct {
|
||||
Time float64
|
||||
Open float64
|
||||
High float64
|
||||
Low float64
|
||||
Close float64
|
||||
Vwap float64
|
||||
Volume float64
|
||||
Count float64
|
||||
Time float64
|
||||
Open float64
|
||||
High float64
|
||||
Low float64
|
||||
Close float64
|
||||
VolumeWeightedAveragePrice float64
|
||||
Volume float64
|
||||
Count float64
|
||||
}
|
||||
|
||||
// RecentTrades holds recent trade data
|
||||
@@ -125,13 +125,13 @@ type TradeBalanceInfo struct {
|
||||
|
||||
// OrderInfo type
|
||||
type OrderInfo struct {
|
||||
RefID string `json:"refid"`
|
||||
UserRef int32 `json:"userref"`
|
||||
Status string `json:"status"`
|
||||
OpenTm float64 `json:"opentm"`
|
||||
StartTm float64 `json:"starttm"`
|
||||
ExpireTm float64 `json:"expiretm"`
|
||||
Descr struct {
|
||||
RefID string `json:"refid"`
|
||||
UserRef int32 `json:"userref"`
|
||||
Status string `json:"status"`
|
||||
OpenTime float64 `json:"opentm"`
|
||||
StartTime float64 `json:"starttm"`
|
||||
ExpireTime float64 `json:"expiretm"`
|
||||
Description struct {
|
||||
Pair string `json:"pair"`
|
||||
Type string `json:"type"`
|
||||
OrderType string `json:"ordertype"`
|
||||
@@ -141,16 +141,16 @@ type OrderInfo struct {
|
||||
Order string `json:"order"`
|
||||
Close string `json:"close"`
|
||||
} `json:"descr"`
|
||||
Vol float64 `json:"vol,string"`
|
||||
VolExec float64 `json:"vol_exec,string"`
|
||||
Cost float64 `json:"cost,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
StopPrice float64 `json:"stopprice,string"`
|
||||
LimitPrice float64 `json:"limitprice,string"`
|
||||
Misc string `json:"misc"`
|
||||
Oflags string `json:"oflags"`
|
||||
Trades []string `json:"trades"`
|
||||
Volume float64 `json:"vol,string"`
|
||||
VolumeExecuted float64 `json:"vol_exec,string"`
|
||||
Cost float64 `json:"cost,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
StopPrice float64 `json:"stopprice,string"`
|
||||
LimitPrice float64 `json:"limitprice,string"`
|
||||
Misc string `json:"misc"`
|
||||
OrderFlags string `json:"oflags"`
|
||||
Trades []string `json:"trades"`
|
||||
}
|
||||
|
||||
// OpenOrders type
|
||||
@@ -198,44 +198,44 @@ type TradesHistory struct {
|
||||
|
||||
// TradeInfo type
|
||||
type TradeInfo struct {
|
||||
OrderTxID string `json:"ordertxid"`
|
||||
Pair string `json:"pair"`
|
||||
Time float64 `json:"time"`
|
||||
Type string `json:"type"`
|
||||
OrderType string `json:"ordertype"`
|
||||
Price float64 `json:"price,string"`
|
||||
Cost float64 `json:"cost,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
Vol float64 `json:"vol,string"`
|
||||
Margin float64 `json:"margin,string"`
|
||||
Misc string `json:"misc"`
|
||||
PosTxID string `json:"postxid"`
|
||||
Cprice float64 `json:"cprice,string"`
|
||||
Cfee float64 `json:"cfee,string"`
|
||||
Cvol float64 `json:"cvol,string"`
|
||||
Cmargin float64 `json:"cmargin,string"`
|
||||
Trades []string `json:"trades"`
|
||||
PosStatus string `json:"posstatus"`
|
||||
OrderTxID string `json:"ordertxid"`
|
||||
Pair string `json:"pair"`
|
||||
Time float64 `json:"time"`
|
||||
Type string `json:"type"`
|
||||
OrderType string `json:"ordertype"`
|
||||
Price float64 `json:"price,string"`
|
||||
Cost float64 `json:"cost,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
Volume float64 `json:"vol,string"`
|
||||
Margin float64 `json:"margin,string"`
|
||||
Misc string `json:"misc"`
|
||||
PosTxID string `json:"postxid"`
|
||||
ClosedPositionAveragePrice float64 `json:"cprice,string"`
|
||||
ClosedPositionFee float64 `json:"cfee,string"`
|
||||
ClosedPositionVolume float64 `json:"cvol,string"`
|
||||
ClosedPositionMargin float64 `json:"cmargin,string"`
|
||||
Trades []string `json:"trades"`
|
||||
PosStatus string `json:"posstatus"`
|
||||
}
|
||||
|
||||
// Position holds the opened position
|
||||
type Position struct {
|
||||
Ordertxid string `json:"ordertxid"`
|
||||
Pair string `json:"pair"`
|
||||
Time float64 `json:"time"`
|
||||
Type string `json:"type"`
|
||||
OrderType string `json:"ordertype"`
|
||||
Cost float64 `json:"cost,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
Vol float64 `json:"vol,string"`
|
||||
VolClosed float64 `json:"vol_closed,string"`
|
||||
Margin float64 `json:"margin,string"`
|
||||
Rollovertm int64 `json:"rollovertm,string"`
|
||||
Misc string `json:"misc"`
|
||||
Oflags string `json:"oflags"`
|
||||
PosStatus string `json:"posstatus"`
|
||||
Net string `json:"net"`
|
||||
Terms string `json:"terms"`
|
||||
Ordertxid string `json:"ordertxid"`
|
||||
Pair string `json:"pair"`
|
||||
Time float64 `json:"time"`
|
||||
Type string `json:"type"`
|
||||
OrderType string `json:"ordertype"`
|
||||
Cost float64 `json:"cost,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
Volume float64 `json:"vol,string"`
|
||||
VolumeClosed float64 `json:"vol_closed,string"`
|
||||
Margin float64 `json:"margin,string"`
|
||||
RolloverTime int64 `json:"rollovertm,string"`
|
||||
Misc string `json:"misc"`
|
||||
OrderFlags string `json:"oflags"`
|
||||
PositionStatus string `json:"posstatus"`
|
||||
Net string `json:"net"`
|
||||
Terms string `json:"terms"`
|
||||
}
|
||||
|
||||
// GetLedgersOptions type
|
||||
@@ -314,7 +314,7 @@ type OrderDescription struct {
|
||||
// AddOrderOptions represents the AddOrder options
|
||||
type AddOrderOptions struct {
|
||||
UserRef int32
|
||||
Oflags string
|
||||
OrderFlags string
|
||||
StartTm string
|
||||
ExpireTm string
|
||||
CloseOrderType string
|
||||
|
||||
@@ -241,6 +241,8 @@ func getSubscriptionChannelData(id int64) WebsocketChannelData {
|
||||
// wsProcessTickers converts ticker data and sends it to the datahandler
|
||||
func (k *Kraken) wsProcessTickers(channelData *WebsocketChannelData, data interface{}) {
|
||||
tickerData := data.(map[string]interface{})
|
||||
askData := tickerData["a"].([]interface{})
|
||||
bidData := tickerData["b"].([]interface{})
|
||||
closeData := tickerData["c"].([]interface{})
|
||||
openData := tickerData["o"].([]interface{})
|
||||
lowData := tickerData["l"].([]interface{})
|
||||
@@ -251,17 +253,21 @@ func (k *Kraken) wsProcessTickers(channelData *WebsocketChannelData, data interf
|
||||
highPrice, _ := strconv.ParseFloat(highData[0].(string), 64)
|
||||
lowPrice, _ := strconv.ParseFloat(lowData[0].(string), 64)
|
||||
quantity, _ := strconv.ParseFloat(volumeData[0].(string), 64)
|
||||
ask, _ := strconv.ParseFloat(askData[0].(string), 64)
|
||||
bid, _ := strconv.ParseFloat(bidData[0].(string), 64)
|
||||
|
||||
k.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Timestamp: time.Now(),
|
||||
Exchange: k.Name,
|
||||
AssetType: asset.Spot,
|
||||
Pair: channelData.Pair,
|
||||
ClosePrice: closePrice,
|
||||
OpenPrice: openPrice,
|
||||
HighPrice: highPrice,
|
||||
LowPrice: lowPrice,
|
||||
Quantity: quantity,
|
||||
Exchange: k.Name,
|
||||
Open: openPrice,
|
||||
Close: closePrice,
|
||||
Volume: quantity,
|
||||
High: highPrice,
|
||||
Low: lowPrice,
|
||||
Bid: bid,
|
||||
Ask: ask,
|
||||
Timestamp: time.Now(),
|
||||
AssetType: asset.Spot,
|
||||
Pair: channelData.Pair,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,8 +62,9 @@ func (k *Kraken) SetDefaults() {
|
||||
Separator: ",",
|
||||
},
|
||||
ConfigFormat: ¤cy.PairFormat{
|
||||
Delimiter: "-",
|
||||
Uppercase: true,
|
||||
Delimiter: "-",
|
||||
Separator: ",",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -167,9 +168,9 @@ func (k *Kraken) Run() {
|
||||
}
|
||||
|
||||
forceUpdate := false
|
||||
if !common.StringDataContains(k.GetEnabledPairs(asset.Spot).Strings(), "-") ||
|
||||
!common.StringDataContains(k.GetAvailablePairs(asset.Spot).Strings(), "-") {
|
||||
enabledPairs := currency.NewPairsFromStrings([]string{"XBT-USD"})
|
||||
if !common.StringDataContains(k.GetEnabledPairs(asset.Spot).Strings(), k.GetPairFormat(asset.Spot, false).Delimiter) ||
|
||||
!common.StringDataContains(k.GetAvailablePairs(asset.Spot).Strings(), k.GetPairFormat(asset.Spot, false).Delimiter) {
|
||||
enabledPairs := currency.NewPairsFromStrings([]string{fmt.Sprintf("BTC%vUSD", k.GetPairFormat(asset.Spot, false).Delimiter)})
|
||||
log.Warn(log.ExchangeSys, "Available pairs for Kraken reset due to config upgrade, please enable the ones you would like again")
|
||||
forceUpdate = true
|
||||
|
||||
@@ -210,7 +211,7 @@ func (k *Kraken) FetchTradablePairs(asset asset.Item) ([]string, error) {
|
||||
if v.Quote[0] == 'Z' || v.Quote[0] == 'X' {
|
||||
v.Quote = v.Quote[1:]
|
||||
}
|
||||
products = append(products, v.Base+"-"+v.Quote)
|
||||
products = append(products, fmt.Sprintf("%v%v%v", v.Base, k.GetPairFormat(asset, false).Delimiter, v.Quote))
|
||||
}
|
||||
return products, nil
|
||||
}
|
||||
@@ -239,21 +240,33 @@ func (k *Kraken) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pri
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range pairs {
|
||||
for y, z := range tickers {
|
||||
if !strings.Contains(y, x.Base.Upper().String()) ||
|
||||
!strings.Contains(y, x.Quote.Upper().String()) {
|
||||
continue
|
||||
for i := range pairs {
|
||||
for curr, v := range tickers {
|
||||
if !strings.EqualFold(pairs[i].String(), curr) {
|
||||
var altCurrency string
|
||||
var ok bool
|
||||
if altCurrency, ok = assetPairMap[curr]; !ok {
|
||||
continue
|
||||
}
|
||||
if !strings.EqualFold(pairs[i].String(), altCurrency) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
tickerPrice = ticker.Price{
|
||||
Last: v.Last,
|
||||
High: v.High,
|
||||
Low: v.Low,
|
||||
Bid: v.Bid,
|
||||
Ask: v.Ask,
|
||||
Volume: v.Volume,
|
||||
Open: v.Open,
|
||||
Pair: pairs[i],
|
||||
}
|
||||
err = ticker.ProcessTicker(k.Name, &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
var tp ticker.Price
|
||||
tp.Pair = x
|
||||
tp.Last = z.Last
|
||||
tp.Ask = z.Ask
|
||||
tp.Bid = z.Bid
|
||||
tp.High = z.High
|
||||
tp.Low = z.Low
|
||||
tp.Volume = z.Volume
|
||||
ticker.ProcessTicker(k.GetName(), &tp, assetType)
|
||||
}
|
||||
}
|
||||
return ticker.GetTicker(k.GetName(), p, assetType)
|
||||
@@ -473,19 +486,19 @@ func (k *Kraken) GetActiveOrders(getOrdersRequest *exchange.GetOrdersRequest) ([
|
||||
|
||||
var orders []exchange.OrderDetail
|
||||
for i := range resp.Open {
|
||||
symbol := currency.NewPairFromString(resp.Open[i].Descr.Pair)
|
||||
orderDate := time.Unix(int64(resp.Open[i].StartTm), 0)
|
||||
side := exchange.OrderSide(strings.ToUpper(resp.Open[i].Descr.Type))
|
||||
orderType := exchange.OrderType(strings.ToUpper(resp.Open[i].Descr.OrderType))
|
||||
symbol := currency.NewPairFromString(resp.Open[i].Description.Pair)
|
||||
orderDate := time.Unix(int64(resp.Open[i].StartTime), 0)
|
||||
side := exchange.OrderSide(strings.ToUpper(resp.Open[i].Description.Type))
|
||||
orderType := exchange.OrderType(strings.ToUpper(resp.Open[i].Description.OrderType))
|
||||
|
||||
orders = append(orders, exchange.OrderDetail{
|
||||
ID: i,
|
||||
Amount: resp.Open[i].Vol,
|
||||
RemainingAmount: (resp.Open[i].Vol - resp.Open[i].VolExec),
|
||||
ExecutedAmount: resp.Open[i].VolExec,
|
||||
Amount: resp.Open[i].Volume,
|
||||
RemainingAmount: (resp.Open[i].Volume - resp.Open[i].VolumeExecuted),
|
||||
ExecutedAmount: resp.Open[i].VolumeExecuted,
|
||||
Exchange: k.Name,
|
||||
OrderDate: orderDate,
|
||||
Price: resp.Open[i].Descr.Price,
|
||||
Price: resp.Open[i].Description.Price,
|
||||
OrderSide: side,
|
||||
OrderType: orderType,
|
||||
CurrencyPair: symbol,
|
||||
@@ -517,19 +530,19 @@ func (k *Kraken) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest) ([
|
||||
|
||||
var orders []exchange.OrderDetail
|
||||
for i := range resp.Closed {
|
||||
symbol := currency.NewPairFromString(resp.Closed[i].Descr.Pair)
|
||||
orderDate := time.Unix(int64(resp.Closed[i].StartTm), 0)
|
||||
side := exchange.OrderSide(strings.ToUpper(resp.Closed[i].Descr.Type))
|
||||
orderType := exchange.OrderType(strings.ToUpper(resp.Closed[i].Descr.OrderType))
|
||||
symbol := currency.NewPairFromString(resp.Closed[i].Description.Pair)
|
||||
orderDate := time.Unix(int64(resp.Closed[i].StartTime), 0)
|
||||
side := exchange.OrderSide(strings.ToUpper(resp.Closed[i].Description.Type))
|
||||
orderType := exchange.OrderType(strings.ToUpper(resp.Closed[i].Description.OrderType))
|
||||
|
||||
orders = append(orders, exchange.OrderDetail{
|
||||
ID: i,
|
||||
Amount: resp.Closed[i].Vol,
|
||||
RemainingAmount: (resp.Closed[i].Vol - resp.Closed[i].VolExec),
|
||||
ExecutedAmount: resp.Closed[i].VolExec,
|
||||
Amount: resp.Closed[i].Volume,
|
||||
RemainingAmount: (resp.Closed[i].Volume - resp.Closed[i].VolumeExecuted),
|
||||
ExecutedAmount: resp.Closed[i].VolumeExecuted,
|
||||
Exchange: k.Name,
|
||||
OrderDate: orderDate,
|
||||
Price: resp.Closed[i].Descr.Price,
|
||||
Price: resp.Closed[i].Description.Price,
|
||||
OrderSide: side,
|
||||
OrderType: orderType,
|
||||
CurrencyPair: symbol,
|
||||
|
||||
@@ -239,13 +239,12 @@ func (l *LakeBTC) processTicker(ticker string) error {
|
||||
continue
|
||||
}
|
||||
l.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Timestamp: time.Now(),
|
||||
Pair: currency.NewPairFromString(k),
|
||||
Exchange: l.Name,
|
||||
Volume: vol,
|
||||
High: high,
|
||||
Low: low,
|
||||
AssetType: asset.Spot,
|
||||
Exchange: l.GetName(),
|
||||
Quantity: vol,
|
||||
HighPrice: high,
|
||||
LowPrice: low,
|
||||
Pair: currency.NewPairFromString(k),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -186,25 +186,29 @@ func (l *LakeBTC) UpdateTradablePairs(forceUpdate bool) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (l *LakeBTC) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
tick, err := l.GetTicker()
|
||||
ticks, err := l.GetTicker()
|
||||
if err != nil {
|
||||
return ticker.Price{}, err
|
||||
}
|
||||
|
||||
for _, x := range l.GetEnabledPairs(assetType) {
|
||||
currency := l.FormatExchangeCurrency(x, assetType).String()
|
||||
pairs := l.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
currency := l.FormatExchangeCurrency(pairs[i], assetType).String()
|
||||
if _, ok := ticks[currency]; !ok {
|
||||
continue
|
||||
}
|
||||
var tickerPrice ticker.Price
|
||||
tickerPrice.Pair = x
|
||||
tickerPrice.Ask = tick[currency].Ask
|
||||
tickerPrice.Bid = tick[currency].Bid
|
||||
tickerPrice.Volume = tick[currency].Volume
|
||||
tickerPrice.High = tick[currency].High
|
||||
tickerPrice.Low = tick[currency].Low
|
||||
tickerPrice.Last = tick[currency].Last
|
||||
tickerPrice.Pair = pairs[i]
|
||||
tickerPrice.Ask = ticks[currency].Ask
|
||||
tickerPrice.Bid = ticks[currency].Bid
|
||||
tickerPrice.Volume = ticks[currency].Volume
|
||||
tickerPrice.High = ticks[currency].High
|
||||
tickerPrice.Low = ticks[currency].Low
|
||||
tickerPrice.Last = ticks[currency].Last
|
||||
|
||||
err = ticker.ProcessTicker(l.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
return ticker.GetTicker(l.Name, p, assetType)
|
||||
|
||||
@@ -68,6 +68,15 @@ func (l *Lbank) GetTicker(symbol string) (TickerResponse, error) {
|
||||
return t, l.SendHTTPRequest(path, &t)
|
||||
}
|
||||
|
||||
// GetTickers returns all tickers
|
||||
func (l *Lbank) GetTickers() ([]TickerResponse, error) {
|
||||
var t []TickerResponse
|
||||
params := url.Values{}
|
||||
params.Set("symbol", "all")
|
||||
path := fmt.Sprintf("%s/v%s/%s?%s", l.API.Endpoints.URL, lbankAPIVersion, lbankTicker, params.Encode())
|
||||
return t, l.SendHTTPRequest(path, &t)
|
||||
}
|
||||
|
||||
// GetCurrencyPairs returns a list of supported currency pairs by the exchange
|
||||
func (l *Lbank) GetCurrencyPairs() ([]string, error) {
|
||||
path := fmt.Sprintf("%s/v%s/%s", l.API.Endpoints.URL, lbankAPIVersion,
|
||||
|
||||
@@ -59,6 +59,17 @@ func TestGetTicker(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTickers(t *testing.T) {
|
||||
TestSetup(t)
|
||||
tickers, err := l.GetTickers()
|
||||
if err != nil {
|
||||
t.Errorf("test failed: %v", err)
|
||||
}
|
||||
if len(tickers) <= 1 {
|
||||
t.Errorf("Expected multiple tickers, received %v", len(tickers))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCurrencyPairs(t *testing.T) {
|
||||
TestSetup(t)
|
||||
_, err := l.GetCurrencyPairs()
|
||||
|
||||
@@ -2,6 +2,8 @@ package lbank
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
// Ticker stores the ticker price data for a currency pair
|
||||
@@ -16,9 +18,9 @@ type Ticker struct {
|
||||
|
||||
// TickerResponse stores the ticker price data and timestamp for a currency pair
|
||||
type TickerResponse struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Ticker Ticker `json:"ticker"`
|
||||
Symbol currency.Pair `json:"symbol"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Ticker Ticker `json:"ticker"`
|
||||
}
|
||||
|
||||
// MarketDepthResponse stores arrays for asks, bids and a timestamp for a currecy pair
|
||||
|
||||
@@ -69,6 +69,7 @@ func (l *Lbank) SetDefaults() {
|
||||
REST: true,
|
||||
RESTCapabilities: exchange.ProtocolFeatures{
|
||||
AutoPairUpdates: true,
|
||||
TickerBatching: true,
|
||||
},
|
||||
WithdrawPermissions: exchange.AutoWithdrawCryptoWithAPIPermission |
|
||||
exchange.NoFiatWithdrawals,
|
||||
@@ -157,21 +158,30 @@ func (l *Lbank) UpdateTradablePairs(forceUpdate bool) error {
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (l *Lbank) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
tickerInfo, err := l.GetTicker(l.FormatExchangeCurrency(p, assetType).String())
|
||||
tickerInfo, err := l.GetTickers()
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
tickerPrice.Pair = p
|
||||
tickerPrice.Last = tickerInfo.Ticker.Latest
|
||||
tickerPrice.High = tickerInfo.Ticker.High
|
||||
tickerPrice.Volume = tickerInfo.Ticker.Volume
|
||||
tickerPrice.Low = tickerInfo.Ticker.Low
|
||||
|
||||
err = ticker.ProcessTicker(l.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
pairs := l.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
for j := range tickerInfo {
|
||||
if !pairs[i].Equal(tickerInfo[j].Symbol) {
|
||||
continue
|
||||
}
|
||||
tickerPrice = ticker.Price{
|
||||
Last: tickerInfo[j].Ticker.Latest,
|
||||
High: tickerInfo[j].Ticker.High,
|
||||
Low: tickerInfo[j].Ticker.Low,
|
||||
Volume: tickerInfo[j].Ticker.Volume,
|
||||
Pair: tickerInfo[j].Symbol,
|
||||
LastUpdated: time.Unix(0, tickerInfo[j].Timestamp),
|
||||
}
|
||||
err = ticker.ProcessTicker(l.GetName(), &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ticker.GetTicker(l.Name, p, assetType)
|
||||
}
|
||||
|
||||
|
||||
@@ -312,7 +312,8 @@ type WalletBalanceInfo struct {
|
||||
// Ticker contains ticker information
|
||||
type Ticker struct {
|
||||
Avg12h float64 `json:"avg_12h,string"`
|
||||
Avg1h float64 `json:"avg_1h,string"`
|
||||
Avg1h float64 `json:"avg_1h,string,omitempty"`
|
||||
Avg6h float64 `json:"avg_6h,string,omitempty"`
|
||||
Avg24h float64 `json:"avg_24h,string"`
|
||||
Rates struct {
|
||||
Last float64 `json:"last,string"`
|
||||
|
||||
@@ -160,16 +160,20 @@ func (l *LocalBitcoins) UpdateTicker(p currency.Pair, assetType asset.Item) (tic
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range l.GetEnabledPairs(assetType) {
|
||||
currency := x.Quote.String()
|
||||
pairs := l.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
curr := pairs[i].Quote.String()
|
||||
if _, ok := tick[curr]; !ok {
|
||||
continue
|
||||
}
|
||||
var tp ticker.Price
|
||||
tp.Pair = x
|
||||
tp.Last = tick[currency].Avg24h
|
||||
tp.Volume = tick[currency].VolumeBTC
|
||||
tp.Pair = pairs[i]
|
||||
tp.Last = tick[curr].Avg24h
|
||||
tp.Volume = tick[curr].VolumeBTC
|
||||
|
||||
err = ticker.ProcessTicker(l.GetName(), &tp, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package okcoin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
@@ -57,13 +59,13 @@ func (o *OKCoin) SetDefaults() {
|
||||
|
||||
UseGlobalFormat: true,
|
||||
RequestFormat: ¤cy.PairFormat{
|
||||
Uppercase: false,
|
||||
Delimiter: "_",
|
||||
Uppercase: true,
|
||||
Delimiter: "-",
|
||||
},
|
||||
|
||||
ConfigFormat: ¤cy.PairFormat{
|
||||
Uppercase: true,
|
||||
Delimiter: "_",
|
||||
Delimiter: "-",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -73,7 +75,7 @@ func (o *OKCoin) SetDefaults() {
|
||||
Websocket: true,
|
||||
RESTCapabilities: exchange.ProtocolFeatures{
|
||||
AutoPairUpdates: true,
|
||||
TickerBatching: false,
|
||||
TickerBatching: true,
|
||||
},
|
||||
WithdrawPermissions: exchange.AutoWithdrawCrypto |
|
||||
exchange.NoFiatWithdrawals,
|
||||
@@ -122,6 +124,28 @@ func (o *OKCoin) Run() {
|
||||
log.Debugf(log.ExchangeSys, "%s Websocket: %s. (url: %s).\n", o.GetName(), common.IsEnabled(o.Websocket.IsEnabled()), o.WebsocketURL)
|
||||
}
|
||||
|
||||
if o.Config.CurrencyPairs.ConfigFormat.Delimiter != o.CurrencyPairs.ConfigFormat.Delimiter {
|
||||
o.Config.CurrencyPairs.ConfigFormat.Delimiter = o.CurrencyPairs.ConfigFormat.Delimiter
|
||||
}
|
||||
if o.Config.CurrencyPairs.RequestFormat.Uppercase != o.CurrencyPairs.RequestFormat.Uppercase {
|
||||
o.Config.CurrencyPairs.RequestFormat.Uppercase = true
|
||||
}
|
||||
if o.Config.CurrencyPairs.RequestFormat.Delimiter != o.CurrencyPairs.RequestFormat.Delimiter {
|
||||
o.Config.CurrencyPairs.RequestFormat.Delimiter = o.CurrencyPairs.RequestFormat.Delimiter
|
||||
}
|
||||
|
||||
if !common.StringDataContains(o.Config.CurrencyPairs.Pairs[asset.Spot].Enabled.Strings(), o.CurrencyPairs.RequestFormat.Delimiter) {
|
||||
enabledPairs := currency.NewPairsFromStrings([]string{"BTC-USD"})
|
||||
log.Warnf(log.ExchangeSys,
|
||||
"Enabled pairs for %v reset due to config upgrade, please enable the ones you would like again.", o.Name)
|
||||
|
||||
err := o.UpdatePairs(enabledPairs, asset.Spot, true, true)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s failed to update currencies.\n", o.GetName())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !o.GetEnabledFeatures().AutoPairUpdates {
|
||||
return
|
||||
}
|
||||
@@ -141,7 +165,7 @@ func (o *OKCoin) FetchTradablePairs(asset asset.Item) ([]string, error) {
|
||||
|
||||
var pairs []string
|
||||
for x := range prods {
|
||||
pairs = append(pairs, prods[x].BaseCurrency+"_"+prods[x].QuoteCurrency)
|
||||
pairs = append(pairs, fmt.Sprintf("%v%v%v", prods[x].BaseCurrency, o.GetPairFormat(asset, false).Delimiter, prods[x].QuoteCurrency))
|
||||
}
|
||||
|
||||
return pairs, nil
|
||||
@@ -158,3 +182,48 @@ func (o *OKCoin) UpdateTradablePairs(forceUpdate bool) error {
|
||||
return o.UpdatePairs(currency.NewPairsFromStrings(pairs),
|
||||
asset.Spot, false, forceUpdate)
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (o *OKCoin) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
var tickerData ticker.Price
|
||||
if assetType == asset.Spot {
|
||||
resp, err := o.GetSpotAllTokenPairsInformation()
|
||||
if err != nil {
|
||||
return tickerData, err
|
||||
}
|
||||
pairs := o.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
for j := range resp {
|
||||
if !pairs[i].Equal(resp[j].InstrumentID) {
|
||||
continue
|
||||
}
|
||||
tickerData = ticker.Price{
|
||||
Last: resp[j].Last,
|
||||
High: resp[j].High24h,
|
||||
Low: resp[j].Low24h,
|
||||
Bid: resp[j].BestBid,
|
||||
Ask: resp[j].BestAsk,
|
||||
Volume: resp[j].BaseVolume24h,
|
||||
QuoteVolume: resp[j].QuoteVolume24h,
|
||||
Open: resp[j].Open24h,
|
||||
Pair: pairs[i],
|
||||
LastUpdated: resp[j].Timestamp,
|
||||
}
|
||||
err = ticker.ProcessTicker(o.Name, &tickerData, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ticker.GetTicker(o.GetName(), p, assetType)
|
||||
}
|
||||
|
||||
// FetchTicker returns the ticker for a currency pair
|
||||
func (o *OKCoin) FetchTicker(p currency.Pair, assetType asset.Item) (tickerData ticker.Price, err error) {
|
||||
tickerData, err = ticker.GetTicker(o.GetName(), p, assetType)
|
||||
if err != nil {
|
||||
return o.UpdateTicker(p, assetType)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
@@ -56,17 +57,34 @@ func (o *OKEX) SetDefaults() {
|
||||
asset.PerpetualSwap,
|
||||
asset.Index,
|
||||
},
|
||||
UseGlobalFormat: true,
|
||||
UseGlobalFormat: false,
|
||||
}
|
||||
// Same format used for perpetual swap and futures
|
||||
fmt1 := currency.PairStore{
|
||||
RequestFormat: ¤cy.PairFormat{
|
||||
Uppercase: false,
|
||||
Delimiter: "_",
|
||||
Uppercase: true,
|
||||
Delimiter: "-",
|
||||
},
|
||||
|
||||
ConfigFormat: ¤cy.PairFormat{
|
||||
Uppercase: true,
|
||||
Delimiter: "_",
|
||||
},
|
||||
}
|
||||
o.CurrencyPairs.Store(asset.PerpetualSwap, fmt1)
|
||||
o.CurrencyPairs.Store(asset.Futures, fmt1)
|
||||
|
||||
fmt2 := currency.PairStore{
|
||||
RequestFormat: ¤cy.PairFormat{
|
||||
Uppercase: true,
|
||||
Delimiter: "-",
|
||||
},
|
||||
ConfigFormat: ¤cy.PairFormat{
|
||||
Uppercase: true,
|
||||
Delimiter: "-",
|
||||
},
|
||||
}
|
||||
o.CurrencyPairs.Store(asset.Spot, fmt2)
|
||||
o.CurrencyPairs.Store(asset.Index, fmt2)
|
||||
|
||||
o.Features = exchange.Features{
|
||||
Supports: exchange.FeaturesSupported{
|
||||
@@ -74,6 +92,7 @@ func (o *OKEX) SetDefaults() {
|
||||
Websocket: true,
|
||||
RESTCapabilities: exchange.ProtocolFeatures{
|
||||
AutoPairUpdates: true,
|
||||
TickerBatching: true,
|
||||
},
|
||||
WithdrawPermissions: exchange.AutoWithdrawCrypto |
|
||||
exchange.NoFiatWithdrawals,
|
||||
@@ -121,6 +140,32 @@ func (o *OKEX) Run() {
|
||||
if o.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%s Websocket: %s. (url: %s).\n", o.GetName(), common.IsEnabled(o.Websocket.IsEnabled()), o.API.Endpoints.WebsocketURL)
|
||||
}
|
||||
if o.Config.CurrencyPairs.Pairs[asset.Spot].ConfigFormat == nil || o.Config.CurrencyPairs.Pairs[asset.Spot].RequestFormat == nil {
|
||||
fmt := currency.PairStore{
|
||||
RequestFormat: ¤cy.PairFormat{
|
||||
Uppercase: true,
|
||||
Delimiter: "-",
|
||||
},
|
||||
ConfigFormat: ¤cy.PairFormat{
|
||||
Uppercase: true,
|
||||
Delimiter: "-",
|
||||
},
|
||||
}
|
||||
o.CurrencyPairs.Store(asset.Spot, fmt)
|
||||
o.Config.CurrencyPairs.Store(asset.Spot, fmt)
|
||||
}
|
||||
|
||||
if !common.StringDataContains(o.Config.CurrencyPairs.Pairs[asset.Spot].Enabled.Strings(), o.CurrencyPairs.Pairs[asset.Spot].RequestFormat.Delimiter) {
|
||||
enabledPairs := currency.NewPairsFromStrings([]string{"EOS-USDT"})
|
||||
log.Warnf(log.ExchangeSys,
|
||||
"Enabled pairs for %v reset due to config upgrade, please enable the ones you would like again.", o.Name)
|
||||
|
||||
err := o.UpdatePairs(enabledPairs, asset.Spot, true, true)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s failed to update currencies.\n", o.GetName())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !o.GetEnabledFeatures().AutoPairUpdates {
|
||||
return
|
||||
@@ -143,7 +188,7 @@ func (o *OKEX) FetchTradablePairs(i asset.Item) ([]string, error) {
|
||||
}
|
||||
|
||||
for x := range prods {
|
||||
pairs = append(pairs, prods[x].BaseCurrency+"_"+prods[x].QuoteCurrency)
|
||||
pairs = append(pairs, fmt.Sprintf("%v%v%v", prods[x].BaseCurrency, o.GetPairFormat(i, false).Delimiter, prods[x].QuoteCurrency))
|
||||
}
|
||||
return pairs, nil
|
||||
case asset.Futures:
|
||||
@@ -154,7 +199,7 @@ func (o *OKEX) FetchTradablePairs(i asset.Item) ([]string, error) {
|
||||
|
||||
var pairs []string
|
||||
for x := range prods {
|
||||
pairs = append(pairs, prods[x].UnderlyingIndex+prods[x].QuoteCurrency+"_"+prods[x].Delivery)
|
||||
pairs = append(pairs, fmt.Sprintf("%v%v%v", prods[x].UnderlyingIndex+prods[x].QuoteCurrency, o.GetPairFormat(i, false).Delimiter, prods[x].Delivery))
|
||||
}
|
||||
return pairs, nil
|
||||
|
||||
@@ -166,11 +211,11 @@ func (o *OKEX) FetchTradablePairs(i asset.Item) ([]string, error) {
|
||||
|
||||
var pairs []string
|
||||
for x := range prods {
|
||||
pairs = append(pairs, prods[x].UnderlyingIndex+"_"+prods[x].QuoteCurrency+"_SWAP")
|
||||
pairs = append(pairs, fmt.Sprintf("%v%v%v%vSWAP", prods[x].UnderlyingIndex, o.GetPairFormat(i, false).Delimiter, prods[x].QuoteCurrency, o.GetPairFormat(i, false).Delimiter))
|
||||
}
|
||||
return pairs, nil
|
||||
case asset.Index:
|
||||
return []string{"BTC_USD"}, nil
|
||||
return []string{fmt.Sprintf("BTC%vUSD", o.GetPairFormat(i, false).Delimiter)}, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%s invalid asset type", o.Name)
|
||||
@@ -193,3 +238,104 @@ func (o *OKEX) UpdateTradablePairs(forceUpdate bool) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (o *OKEX) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
var tickerData ticker.Price
|
||||
switch assetType {
|
||||
case asset.Spot:
|
||||
resp, err := o.GetSpotAllTokenPairsInformation()
|
||||
if err != nil {
|
||||
return tickerData, err
|
||||
}
|
||||
pairs := o.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
for j := range resp {
|
||||
if !pairs[i].Equal(resp[j].InstrumentID) {
|
||||
continue
|
||||
}
|
||||
tickerData = ticker.Price{
|
||||
Last: resp[j].Last,
|
||||
High: resp[j].High24h,
|
||||
Low: resp[j].Low24h,
|
||||
Bid: resp[j].BestBid,
|
||||
Ask: resp[j].BestAsk,
|
||||
Volume: resp[j].BaseVolume24h,
|
||||
QuoteVolume: resp[j].QuoteVolume24h,
|
||||
Open: resp[j].Open24h,
|
||||
Pair: pairs[i],
|
||||
LastUpdated: resp[j].Timestamp,
|
||||
}
|
||||
err = ticker.ProcessTicker(o.Name, &tickerData, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
case asset.PerpetualSwap:
|
||||
resp, err := o.GetAllSwapTokensInformation()
|
||||
if err != nil {
|
||||
return tickerData, err
|
||||
}
|
||||
pairs := o.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
for j := range resp {
|
||||
if !pairs[i].Equal(resp[j].InstrumentID) {
|
||||
continue
|
||||
}
|
||||
tickerData = ticker.Price{
|
||||
Last: resp[j].Last,
|
||||
High: resp[j].High24H,
|
||||
Low: resp[j].Low24H,
|
||||
Bid: resp[j].BestBid,
|
||||
Ask: resp[j].BestAsk,
|
||||
Volume: resp[j].Volume24H,
|
||||
Pair: resp[j].InstrumentID,
|
||||
LastUpdated: resp[j].Timestamp,
|
||||
}
|
||||
err = ticker.ProcessTicker(o.Name, &tickerData, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
case asset.Futures:
|
||||
resp, err := o.GetAllFuturesTokenInfo()
|
||||
if err != nil {
|
||||
return tickerData, err
|
||||
}
|
||||
pairs := o.GetEnabledPairs(assetType)
|
||||
for i := range pairs {
|
||||
for j := range resp {
|
||||
if !pairs[i].Equal(resp[j].InstrumentID) {
|
||||
continue
|
||||
}
|
||||
tickerData = ticker.Price{
|
||||
Last: resp[j].Last,
|
||||
High: resp[j].High24h,
|
||||
Low: resp[j].Low24h,
|
||||
Bid: resp[j].BestBid,
|
||||
Ask: resp[j].BestAsk,
|
||||
Volume: resp[j].Volume24h,
|
||||
Pair: resp[j].InstrumentID,
|
||||
LastUpdated: resp[j].Timestamp,
|
||||
}
|
||||
err = ticker.ProcessTicker(o.Name, &tickerData, assetType)
|
||||
if err != nil {
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ticker.GetTicker(o.GetName(), p, assetType)
|
||||
}
|
||||
|
||||
// FetchTicker returns the ticker for a currency pair
|
||||
func (o *OKEX) FetchTicker(p currency.Pair, assetType asset.Item) (tickerData ticker.Price, err error) {
|
||||
tickerData, err = ticker.GetTicker(o.GetName(), p, assetType)
|
||||
if err != nil {
|
||||
return o.UpdateTicker(p, assetType)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package okgroup
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
// GetAccountCurrenciesResponse response data for GetAccountCurrencies
|
||||
@@ -288,16 +290,16 @@ type GetSpotOrderBookResponse struct {
|
||||
|
||||
// GetSpotTokenPairsInformationResponse response data for GetSpotTokenPairsInformation
|
||||
type GetSpotTokenPairsInformationResponse struct {
|
||||
BaseVolume24h float64 `json:"base_volume_24h,string"` // 24 trading volume of the base currency
|
||||
BestAsk float64 `json:"best_ask,string"` // best ask price
|
||||
BestBid float64 `json:"best_bid,string"` // best bid price
|
||||
High24h float64 `json:"high_24h,string"` // 24 hour high
|
||||
InstrumentID string `json:"instrument_id"` // trading pair
|
||||
Last float64 `json:"last,string"` // last traded price
|
||||
Low24h float64 `json:"low_24h,string"` // 24 hour low
|
||||
Open24h float64 `json:"open_24h,string"` // 24 hour open
|
||||
QuoteVolume24h float64 `json:"quote_volume_24h,string"` // 24 trading volume of the quote currency
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
BaseVolume24h float64 `json:"base_volume_24h,string"` // 24 trading volume of the base currency
|
||||
BestAsk float64 `json:"best_ask,string"` // best ask price
|
||||
BestBid float64 `json:"best_bid,string"` // best bid price
|
||||
High24h float64 `json:"high_24h,string"` // 24 hour high
|
||||
InstrumentID currency.Pair `json:"instrument_id"` // trading pair
|
||||
Last float64 `json:"last,string"` // last traded price
|
||||
Low24h float64 `json:"low_24h,string"` // 24 hour low
|
||||
Open24h float64 `json:"open_24h,string"` // 24 hour open
|
||||
QuoteVolume24h float64 `json:"quote_volume_24h,string"` // 24 trading volume of the quote currency
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
// GetSpotFilledOrdersInformationRequest request data for GetSpotFilledOrdersInformation
|
||||
@@ -699,14 +701,14 @@ type GetFuturesOrderBookResponse struct {
|
||||
|
||||
// GetFuturesTokenInfoResponse response data for GetFuturesOrderBook
|
||||
type GetFuturesTokenInfoResponse struct {
|
||||
BestAsk float64 `json:"best_ask,string"`
|
||||
BestBid float64 `json:"best_bid,string"`
|
||||
High24h float64 `json:"high_24h,string"`
|
||||
InstrumentID string `json:"instrument_id"`
|
||||
Last float64 `json:"last,string"`
|
||||
Low24h float64 `json:"low_24h,string"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Volume24h int64 `json:"volume_24h,string"`
|
||||
BestAsk float64 `json:"best_ask,string"`
|
||||
BestBid float64 `json:"best_bid,string"`
|
||||
High24h float64 `json:"high_24h,string"`
|
||||
InstrumentID currency.Pair `json:"instrument_id"`
|
||||
Last float64 `json:"last,string"`
|
||||
Low24h float64 `json:"low_24h,string"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Volume24h float64 `json:"volume_24h,string"`
|
||||
}
|
||||
|
||||
// GetFuturesFilledOrderRequest request data for GetFuturesFilledOrder
|
||||
@@ -1057,14 +1059,14 @@ type GetSwapOrderBookResponse struct {
|
||||
|
||||
// GetAllSwapTokensInformationResponse response data for GetAllSwapTokensInformation
|
||||
type GetAllSwapTokensInformationResponse struct {
|
||||
InstrumentID string `json:"instrument_id"`
|
||||
Last float64 `json:"last,string"`
|
||||
High24H float64 `json:"high_24h,string"`
|
||||
Low24H float64 `json:"low_24h,string"`
|
||||
BestBid float64 `json:"best_bid,string"`
|
||||
BestAsk float64 `json:"best_ask,string"`
|
||||
Volume24H float64 `json:"volume_24h,string"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
InstrumentID currency.Pair `json:"instrument_id"`
|
||||
Last float64 `json:"last,string"`
|
||||
High24H float64 `json:"high_24h,string"`
|
||||
Low24H float64 `json:"low_24h,string"`
|
||||
BestBid float64 `json:"best_bid,string"`
|
||||
BestAsk float64 `json:"best_ask,string"`
|
||||
Volume24H float64 `json:"volume_24h,string"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
// GetSwapFilledOrdersDataRequest request data for GetSwapFilledOrdersData
|
||||
@@ -1340,12 +1342,14 @@ type WebsocketDataWrapper struct {
|
||||
|
||||
// WebsocketTickerData contains formatted data for ticker related websocket responses
|
||||
type WebsocketTickerData struct {
|
||||
High24H float64 `json:"high_24h,string,omitempty"`
|
||||
Last float64 `json:"last,string,omitempty"`
|
||||
BestBid float64 `json:"best_bid,string,omitempty"`
|
||||
BestAsk float64 `json:"best_ask,string,omitempty"`
|
||||
Low24H float64 `json:"low_24h,string,omitempty"`
|
||||
Volume24H float64 `json:"volume_24h,string,omitempty"`
|
||||
BaseVolume24h float64 `json:"base_volume_24h,string,omitempty"`
|
||||
BestAsk float64 `json:"best_ask,string,omitempty"`
|
||||
BestBid float64 `json:"best_bid,string,omitempty"`
|
||||
High24h float64 `json:"high_24h,string,omitempty"`
|
||||
Last float64 `json:"last,string,omitempty"`
|
||||
Low24h float64 `json:"low_24h,string,omitempty"`
|
||||
Open24h float64 `json:"open_24h,string,omitempty"`
|
||||
QuoteVolume24h float64 `json:"quote_volume_24h,string,omitempty"`
|
||||
}
|
||||
|
||||
// WebsocketTradeResponse contains formatted data for trade related websocket responses
|
||||
|
||||
@@ -193,7 +193,7 @@ func (o *OKGroup) wsPingHandler(wg *sync.WaitGroup) {
|
||||
return
|
||||
|
||||
case <-ticker.C:
|
||||
err := o.WebsocketConn.SendMessage("ping")
|
||||
err := o.WebsocketConn.Connection.WriteMessage(websocket.TextMessage, []byte("ping"))
|
||||
if o.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%v sending ping", o.GetName())
|
||||
}
|
||||
@@ -361,13 +361,19 @@ func (o *OKGroup) wsProcessTickers(response *WebsocketDataResponse) {
|
||||
for i := range response.Data {
|
||||
instrument := currency.NewPairDelimiter(response.Data[i].InstrumentID, "-")
|
||||
o.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Timestamp: response.Data[i].Timestamp,
|
||||
Exchange: o.GetName(),
|
||||
AssetType: o.GetAssetTypeFromTableName(response.Table),
|
||||
HighPrice: response.Data[i].High24H,
|
||||
LowPrice: response.Data[i].Low24H,
|
||||
ClosePrice: response.Data[i].Last,
|
||||
Pair: instrument,
|
||||
Exchange: o.Name,
|
||||
Open: response.Data[i].Open24h,
|
||||
Close: response.Data[i].Last,
|
||||
Volume: response.Data[i].BaseVolume24h,
|
||||
QuoteVolume: response.Data[i].QuoteVolume24h,
|
||||
High: response.Data[i].High24h,
|
||||
Low: response.Data[i].Low24h,
|
||||
Bid: response.Data[i].BestBid,
|
||||
Ask: response.Data[i].BestAsk,
|
||||
Last: response.Data[i].Last,
|
||||
Timestamp: response.Data[i].Timestamp,
|
||||
AssetType: o.GetAssetTypeFromTableName(response.Table),
|
||||
Pair: instrument,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
@@ -65,36 +64,6 @@ func (o *OKGroup) Setup(exch *config.ExchangeConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (o *OKGroup) UpdateTicker(p currency.Pair, assetType asset.Item) (tickerData ticker.Price, err error) {
|
||||
resp, err := o.GetSpotAllTokenPairsInformationForCurrency(o.FormatExchangeCurrency(p, assetType).String())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tickerData = ticker.Price{
|
||||
Ask: resp.BestAsk,
|
||||
Bid: resp.BestBid,
|
||||
High: resp.High24h,
|
||||
Last: resp.Last,
|
||||
LastUpdated: resp.Timestamp,
|
||||
Low: resp.Low24h,
|
||||
Pair: o.FormatExchangeCurrency(p, assetType),
|
||||
Volume: resp.BaseVolume24h,
|
||||
}
|
||||
|
||||
err = ticker.ProcessTicker(o.Name, &tickerData, assetType)
|
||||
return
|
||||
}
|
||||
|
||||
// FetchTicker returns the ticker for a currency pair
|
||||
func (o *OKGroup) FetchTicker(p currency.Pair, assetType asset.Item) (tickerData ticker.Price, err error) {
|
||||
tickerData, err = ticker.GetTicker(o.GetName(), p, assetType)
|
||||
if err != nil {
|
||||
return o.UpdateTicker(p, assetType)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FetchOrderbook returns orderbook base on the currency pair
|
||||
func (o *OKGroup) FetchOrderbook(p currency.Pair, assetType asset.Item) (resp orderbook.Base, err error) {
|
||||
ob, err := orderbook.Get(o.GetName(), p, assetType)
|
||||
@@ -339,7 +308,7 @@ func (o *OKGroup) GetOrderInfo(orderID string) (resp exchange.OrderDetail, err e
|
||||
// GetDepositAddress returns a deposit address for a specified currency
|
||||
func (o *OKGroup) GetDepositAddress(p currency.Code, accountID string) (_ string, err error) {
|
||||
wallet, err := o.GetAccountDepositAddressForCurrency(p.Lower().String())
|
||||
if err != nil {
|
||||
if err != nil || len(wallet) == 0 {
|
||||
return
|
||||
}
|
||||
return wallet[0].Address, nil
|
||||
|
||||
@@ -210,23 +210,22 @@ func (p *Poloniex) wsHandleTickerData(data []interface{}) {
|
||||
t.PercentageChange, _ = strconv.ParseFloat(tickerData[4].(string), 64)
|
||||
t.BaseCurrencyVolume24H, _ = strconv.ParseFloat(tickerData[5].(string), 64)
|
||||
t.QuoteCurrencyVolume24H, _ = strconv.ParseFloat(tickerData[6].(string), 64)
|
||||
isFrozen := false
|
||||
if tickerData[7].(float64) == 1 {
|
||||
isFrozen = true
|
||||
}
|
||||
t.IsFrozen = isFrozen
|
||||
t.IsFrozen = tickerData[7].(float64) == 1
|
||||
t.HighestTradeIn24H, _ = strconv.ParseFloat(tickerData[8].(string), 64)
|
||||
t.LowestTradePrice24H, _ = strconv.ParseFloat(tickerData[9].(string), 64)
|
||||
|
||||
p.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Timestamp: time.Now(),
|
||||
Pair: currency.NewPairDelimiter(currencyPair, "_"),
|
||||
Exchange: p.GetName(),
|
||||
AssetType: asset.Spot,
|
||||
ClosePrice: t.LastPrice,
|
||||
LowPrice: t.LowestAsk,
|
||||
HighPrice: t.HighestBid,
|
||||
Quantity: t.QuoteCurrencyVolume24H,
|
||||
Exchange: p.Name,
|
||||
Volume: t.BaseCurrencyVolume24H,
|
||||
QuoteVolume: t.QuoteCurrencyVolume24H,
|
||||
High: t.HighestBid,
|
||||
Low: t.LowestAsk,
|
||||
Bid: t.HighestBid,
|
||||
Ask: t.LowestAsk,
|
||||
Last: t.LastPrice,
|
||||
Timestamp: time.Now(),
|
||||
AssetType: asset.Spot,
|
||||
Pair: currency.NewPairDelimiter(currencyPair, "_"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,7 +361,6 @@ func (p *Poloniex) WsProcessOrderbookUpdate(sequenceNumber int64, target []inter
|
||||
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
|
||||
func (p *Poloniex) GenerateDefaultSubscriptions() {
|
||||
var subscriptions []wshandler.WebsocketChannelSubscription
|
||||
// Tickerdata is its own channel
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: fmt.Sprintf("%v", wsTickerDataID),
|
||||
})
|
||||
|
||||
@@ -215,6 +215,9 @@ func (p *Poloniex) UpdateTicker(currencyPair currency.Pair, assetType asset.Item
|
||||
for _, x := range p.GetEnabledPairs(assetType) {
|
||||
var tp ticker.Price
|
||||
curr := p.FormatExchangeCurrency(x, assetType).String()
|
||||
if _, ok := tick[curr]; !ok {
|
||||
continue
|
||||
}
|
||||
tp.Pair = x
|
||||
tp.Ask = tick[curr].LowestAsk
|
||||
tp.Bid = tick[curr].HighestBid
|
||||
@@ -222,10 +225,11 @@ func (p *Poloniex) UpdateTicker(currencyPair currency.Pair, assetType asset.Item
|
||||
tp.Last = tick[curr].Last
|
||||
tp.Low = tick[curr].Low24Hr
|
||||
tp.Volume = tick[curr].BaseVolume
|
||||
tp.QuoteVolume = tick[curr].QuoteVolume
|
||||
|
||||
err = ticker.ProcessTicker(p.GetName(), &tp, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
return ticker.GetTicker(p.Name, currencyPair, assetType)
|
||||
|
||||
@@ -2,6 +2,7 @@ package ticker
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -28,14 +29,17 @@ var (
|
||||
|
||||
// Price struct stores the currency pair and pricing information
|
||||
type Price struct {
|
||||
Pair currency.Pair `json:"Pair"`
|
||||
Last float64 `json:"Last"`
|
||||
High float64 `json:"High"`
|
||||
Low float64 `json:"Low"`
|
||||
Bid float64 `json:"Bid"`
|
||||
Ask float64 `json:"Ask"`
|
||||
Volume float64 `json:"Volume"`
|
||||
QuoteVolume float64 `json:"QuoteVolume"`
|
||||
PriceATH float64 `json:"PriceATH"`
|
||||
Open float64 `json:"Open"`
|
||||
Close float64 `json:"Close"`
|
||||
Pair currency.Pair `json:"Pair"`
|
||||
LastUpdated time.Time
|
||||
}
|
||||
|
||||
@@ -151,11 +155,11 @@ func CreateNewTicker(exchangeName string, tickerNew *Price, tickerType asset.Ite
|
||||
// list
|
||||
func ProcessTicker(exchangeName string, tickerNew *Price, assetType asset.Item) error {
|
||||
if tickerNew.Pair.IsEmpty() {
|
||||
return errors.New(errPairNotSet)
|
||||
return fmt.Errorf("%v %v", exchangeName, errPairNotSet)
|
||||
}
|
||||
|
||||
if assetType == "" {
|
||||
return errors.New(errAssetTypeNotSet)
|
||||
return fmt.Errorf("%v %v %v", exchangeName, tickerNew.Pair.String(), errAssetTypeNotSet)
|
||||
}
|
||||
|
||||
if tickerNew.LastUpdated.IsZero() {
|
||||
@@ -178,6 +182,7 @@ func ProcessTicker(exchangeName string, tickerNew *Price, assetType asset.Item)
|
||||
}
|
||||
|
||||
m.Lock()
|
||||
|
||||
a := make(map[string]map[string]Price)
|
||||
b := make(map[string]Price)
|
||||
b[assetType.String()] = *tickerNew
|
||||
|
||||
@@ -103,7 +103,9 @@ func (w *Websocket) Connect() error {
|
||||
if !w.connectionMonitorRunning {
|
||||
go w.connectionMonitor()
|
||||
}
|
||||
go w.manageSubscriptions()
|
||||
if w.SupportsFunctionality(WebsocketSubscribeSupported) || w.SupportsFunctionality(WebsocketUnsubscribeSupported) {
|
||||
go w.manageSubscriptions()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -144,15 +144,20 @@ type TradeData struct {
|
||||
|
||||
// TickerData defines ticker feed
|
||||
type TickerData struct {
|
||||
Timestamp time.Time
|
||||
Pair currency.Pair
|
||||
AssetType asset.Item
|
||||
Exchange string
|
||||
ClosePrice float64
|
||||
Quantity float64
|
||||
OpenPrice float64
|
||||
HighPrice float64
|
||||
LowPrice float64
|
||||
Exchange string
|
||||
Open float64
|
||||
Close float64
|
||||
Volume float64
|
||||
QuoteVolume float64
|
||||
High float64
|
||||
Low float64
|
||||
Bid float64
|
||||
Ask float64
|
||||
Last float64
|
||||
PriceATH float64
|
||||
Timestamp time.Time
|
||||
AssetType asset.Item
|
||||
Pair currency.Pair
|
||||
}
|
||||
|
||||
// KlineData defines kline feed
|
||||
|
||||
@@ -170,19 +170,23 @@ func (y *Yobit) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pric
|
||||
}
|
||||
|
||||
for _, x := range y.GetEnabledPairs(assetType) {
|
||||
currency := y.FormatExchangeCurrency(x, assetType).Lower().String()
|
||||
curr := y.FormatExchangeCurrency(x, assetType).Lower().String()
|
||||
if _, ok := result[curr]; !ok {
|
||||
continue
|
||||
}
|
||||
var tickerPrice ticker.Price
|
||||
tickerPrice.Pair = x
|
||||
tickerPrice.Last = result[currency].Last
|
||||
tickerPrice.Ask = result[currency].Sell
|
||||
tickerPrice.Bid = result[currency].Buy
|
||||
tickerPrice.Last = result[currency].Last
|
||||
tickerPrice.Low = result[currency].Low
|
||||
tickerPrice.Volume = result[currency].VolumeCurrent
|
||||
tickerPrice.Last = result[curr].Last
|
||||
tickerPrice.Ask = result[curr].Sell
|
||||
tickerPrice.Bid = result[curr].Buy
|
||||
tickerPrice.Last = result[curr].Last
|
||||
tickerPrice.Low = result[curr].Low
|
||||
tickerPrice.QuoteVolume = result[curr].VolumeCurrent
|
||||
tickerPrice.Volume = result[curr].Vol
|
||||
|
||||
err = ticker.ProcessTicker(y.Name, &tickerPrice, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
return ticker.GetTicker(y.Name, p, assetType)
|
||||
|
||||
@@ -72,12 +72,12 @@ type TickerResponse struct {
|
||||
|
||||
// TickerChildResponse holds the ticker child response data
|
||||
type TickerChildResponse struct {
|
||||
Vol float64 `json:"vol,string"` // 成交量(最近的24小时)
|
||||
Last float64 `json:"last,string"` // 最新成交价
|
||||
Sell float64 `json:"sell,string"` // 卖一价
|
||||
Buy float64 `json:"buy,string"` // 买一价
|
||||
High float64 `json:"high,string"` // 最高价
|
||||
Low float64 `json:"low,string"` // 最低价
|
||||
Volume float64 `json:"vol,string"` // 成交量(最近的24小时)
|
||||
Last float64 `json:"last,string"` // 最新成交价
|
||||
Sell float64 `json:"sell,string"` // 卖一价
|
||||
Buy float64 `json:"buy,string"` // 买一价
|
||||
High float64 `json:"high,string"` // 最高价
|
||||
Low float64 `json:"low,string"` // 最低价
|
||||
}
|
||||
|
||||
// SpotNewOrderRequestParamsType ZB 交易类型
|
||||
|
||||
@@ -96,13 +96,17 @@ func (z *ZB) WsHandleData() {
|
||||
}
|
||||
|
||||
z.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Timestamp: time.Unix(0, ticker.Date),
|
||||
Pair: currency.NewPairFromString(cPair[0]),
|
||||
AssetType: asset.Spot,
|
||||
Exchange: z.GetName(),
|
||||
ClosePrice: ticker.Data.Last,
|
||||
HighPrice: ticker.Data.High,
|
||||
LowPrice: ticker.Data.Low,
|
||||
Exchange: z.Name,
|
||||
Close: ticker.Data.Last,
|
||||
Volume: ticker.Data.Volume24Hr,
|
||||
High: ticker.Data.High,
|
||||
Low: ticker.Data.Low,
|
||||
Last: ticker.Data.Last,
|
||||
Bid: ticker.Data.Buy,
|
||||
Ask: ticker.Data.Sell,
|
||||
Timestamp: time.Unix(0, ticker.Date),
|
||||
AssetType: asset.Spot,
|
||||
Pair: currency.NewPairFromString(cPair[0]),
|
||||
}
|
||||
|
||||
case strings.Contains(result.Channel, "depth"):
|
||||
|
||||
@@ -204,21 +204,23 @@ func (z *ZB) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price,
|
||||
}
|
||||
|
||||
for _, x := range z.GetEnabledPairs(assetType) {
|
||||
currencySplit := strings.Split(z.FormatExchangeCurrency(x, assetType).String(), "_")
|
||||
currency := currencySplit[0] + currencySplit[1]
|
||||
currencySplit := strings.Split(z.FormatExchangeCurrency(x, assetType).String(), z.GetPairFormat(assetType, false).Delimiter)
|
||||
curr := currencySplit[0] + currencySplit[1]
|
||||
if _, ok := result[curr]; !ok {
|
||||
continue
|
||||
}
|
||||
var tp ticker.Price
|
||||
tp.Pair = x
|
||||
tp.High = result[currency].High
|
||||
tp.Last = result[currency].Last
|
||||
tp.Ask = result[currency].Sell
|
||||
tp.Bid = result[currency].Buy
|
||||
tp.Last = result[currency].Last
|
||||
tp.Low = result[currency].Low
|
||||
tp.Volume = result[currency].Vol
|
||||
tp.High = result[curr].High
|
||||
tp.Last = result[curr].Last
|
||||
tp.Ask = result[curr].Sell
|
||||
tp.Bid = result[curr].Buy
|
||||
tp.Low = result[curr].Low
|
||||
tp.Volume = result[curr].Volume
|
||||
|
||||
err = ticker.ProcessTicker(z.Name, &tp, assetType)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
log.Error(log.Ticker, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
58
testdata/http_mock/gemini/gemini.json
vendored
58
testdata/http_mock/gemini/gemini.json
vendored
@@ -2729,6 +2729,64 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"/v2/ticker/BTCUSD": {
|
||||
"GET": [
|
||||
{
|
||||
"data": {
|
||||
"ask": "9663.28",
|
||||
"bid": "9662.94",
|
||||
"changes": [
|
||||
"9719",
|
||||
"9730.13",
|
||||
"9718.58",
|
||||
"9672.54",
|
||||
"9668.57",
|
||||
"9701.67",
|
||||
"10191.27",
|
||||
"10225.8",
|
||||
"10238.78",
|
||||
"10210.5",
|
||||
"10171.2",
|
||||
"10156.31",
|
||||
"10138.69",
|
||||
"10121.71",
|
||||
"10147.31",
|
||||
"10120.74",
|
||||
"10149.82",
|
||||
"10185.68",
|
||||
"10128.28",
|
||||
"10070.56",
|
||||
"10082.86",
|
||||
"10114",
|
||||
"10089.25",
|
||||
"10142.29"
|
||||
],
|
||||
"close": "9662.94",
|
||||
"high": "11000",
|
||||
"low": "9210",
|
||||
"open": "10148.67",
|
||||
"symbol": "BTCUSD"
|
||||
},
|
||||
"queryString": "",
|
||||
"bodyParams": "",
|
||||
"headers": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
"/v2/ticker/bla": {
|
||||
"GET": [
|
||||
{
|
||||
"data": {
|
||||
"message": "Supplied value 'bla' is not a valid symbol. Please correct your API request to use one of the supported symbols: [zecbch, bchbtc, zecusd, ethusd, zecbtc, bcheth, zecltc, ltcbch, bchusd, ethbtc, ltcbtc, ltceth, zeceth, ltcusd, btcusd]",
|
||||
"reason": "Bad Request",
|
||||
"result": "error"
|
||||
},
|
||||
"queryString": "",
|
||||
"bodyParams": "",
|
||||
"headers": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user