mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
Merge branch 'engine' of https://github.com/thrasher-corp/gocryptotrader into engine
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 {
|
||||
|
||||
@@ -55,12 +55,12 @@ type Orderbook 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ func (l *Logger) newLogEvent(data, header string, w io.Writer) error {
|
||||
if w == nil {
|
||||
return errors.New("io.Writer not set")
|
||||
}
|
||||
|
||||
e := eventPool.Get().(*LogEvent)
|
||||
e.output = w
|
||||
e.data = append(e.data, []byte(header)...)
|
||||
@@ -34,11 +35,12 @@ func (l *Logger) newLogEvent(data, header string, w io.Writer) error {
|
||||
if data == "" || data[len(data)-1] != '\n' {
|
||||
e.data = append(e.data, '\n')
|
||||
}
|
||||
e.output.Write(e.data)
|
||||
_, err := e.output.Write(e.data)
|
||||
|
||||
e.data = e.data[:0]
|
||||
eventPool.Put(e)
|
||||
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// CloseLogger is called on shutdown of application
|
||||
@@ -58,6 +60,7 @@ func validSubLogger(s string) (bool, *subLogger) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Level retries the current sublogger levels
|
||||
func Level(s string) (*Levels, error) {
|
||||
found, logger := validSubLogger(s)
|
||||
if !found {
|
||||
@@ -67,6 +70,7 @@ func Level(s string) (*Levels, error) {
|
||||
return &logger.Levels, nil
|
||||
}
|
||||
|
||||
// SetLevel sets sublogger levels
|
||||
func SetLevel(s, level string) (*Levels, error) {
|
||||
found, logger := validSubLogger(s)
|
||||
if !found {
|
||||
|
||||
@@ -11,7 +11,7 @@ func (mw *multiWriter) Add(writer io.Writer) {
|
||||
mw.mu.Unlock()
|
||||
}
|
||||
|
||||
// Remove removes exisiting writer from multiwriter slice
|
||||
// Remove removes existing writer from multiwriter slice
|
||||
func (mw *multiWriter) Remove(writer io.Writer) {
|
||||
mw.mu.Lock()
|
||||
|
||||
@@ -37,8 +37,10 @@ func (mw *multiWriter) Write(p []byte) (n int, err error) {
|
||||
n int
|
||||
err error
|
||||
}
|
||||
mw.mu.RLock()
|
||||
defer mw.mu.RUnlock()
|
||||
|
||||
results := make(chan data)
|
||||
results := make(chan data, len(mw.writers))
|
||||
|
||||
for _, wr := range mw.writers {
|
||||
go func(w io.Writer, p []byte, ch chan data) {
|
||||
@@ -51,10 +53,7 @@ func (mw *multiWriter) Write(p []byte) (n int, err error) {
|
||||
ch <- data{n, io.ErrShortWrite}
|
||||
return
|
||||
}
|
||||
select {
|
||||
case ch <- data{n, nil}:
|
||||
default:
|
||||
}
|
||||
ch <- data{n, nil}
|
||||
}(wr, p, results)
|
||||
}
|
||||
|
||||
|
||||
@@ -72,13 +72,12 @@ func (r *Rotate) openOrCreateFile(n int64) error {
|
||||
|
||||
func (r *Rotate) openNew() error {
|
||||
name := filepath.Join(LogPath, r.FileName)
|
||||
|
||||
t := time.Now()
|
||||
timestamp := t.Format("2006-01-02T15-04-05")
|
||||
newName := filepath.Join(LogPath, timestamp+"-"+r.FileName)
|
||||
_, err := os.Stat(name)
|
||||
|
||||
if err == nil {
|
||||
timestamp := time.Now().Format("2006-01-02T15-04-05")
|
||||
newName := filepath.Join(LogPath, timestamp+"-"+r.FileName)
|
||||
|
||||
err = os.Rename(name, newName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't rename log file: %s", err)
|
||||
@@ -105,6 +104,7 @@ func (r *Rotate) close() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Close handler for open file
|
||||
func (r *Rotate) Close() error {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
@@ -27,7 +27,6 @@ func getWriters(s *SubLoggerConfig) io.Writer {
|
||||
m.Add(ioutil.Discard)
|
||||
}
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ type Logger struct {
|
||||
Spacer string
|
||||
}
|
||||
|
||||
// Levels flags for each sub logger type
|
||||
type Levels struct {
|
||||
Info, Debug, Warn, Error bool
|
||||
}
|
||||
@@ -61,6 +62,7 @@ type subLogger struct {
|
||||
output io.Writer
|
||||
}
|
||||
|
||||
// LogEvent holds the data sent to the log and which multiwriter to send to
|
||||
type LogEvent struct {
|
||||
data []byte
|
||||
output io.Writer
|
||||
@@ -68,14 +70,17 @@ type LogEvent struct {
|
||||
|
||||
type multiWriter struct {
|
||||
writers []io.Writer
|
||||
mu sync.Mutex
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
var (
|
||||
logger = &Logger{}
|
||||
logger = &Logger{}
|
||||
// FileLoggingConfiguredCorrectly flag set during config check if file logging meets requirements
|
||||
FileLoggingConfiguredCorrectly bool
|
||||
GlobalLogConfig = &Config{} // GlobalLogConfig hold global configuration options for logger
|
||||
GlobalLogFile = &Rotate{}
|
||||
// GlobalLogConfig holds global configuration options for logger
|
||||
GlobalLogConfig = &Config{}
|
||||
// GlobalLogFile hold global configuration options for file logger
|
||||
GlobalLogFile = &Rotate{}
|
||||
|
||||
eventPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
@@ -85,5 +90,6 @@ var (
|
||||
},
|
||||
}
|
||||
|
||||
// LogPath system path to store log files in
|
||||
LogPath string
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@ package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
// Info takes a pointer subLogger struct and string sends to newLogEvent
|
||||
@@ -14,7 +15,7 @@ func Info(sl *subLogger, data string) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.newLogEvent(data, logger.InfoHeader, sl.output)
|
||||
displayError(logger.newLogEvent(data, logger.InfoHeader, sl.output))
|
||||
}
|
||||
|
||||
// Infoln takes a pointer subLogger struct and interface sends to newLogEvent
|
||||
@@ -27,7 +28,7 @@ func Infoln(sl *subLogger, v ...interface{}) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.newLogEvent(fmt.Sprintln(v...), logger.InfoHeader, sl.output)
|
||||
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.InfoHeader, sl.output))
|
||||
}
|
||||
|
||||
// Infof takes a pointer subLogger struct, string & interface formats and sends to Info()
|
||||
@@ -53,7 +54,7 @@ func Debug(sl *subLogger, data string) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.newLogEvent(data, logger.DebugHeader, sl.output)
|
||||
displayError(logger.newLogEvent(data, logger.DebugHeader, sl.output))
|
||||
}
|
||||
|
||||
// Debugln takes a pointer subLogger struct, string and interface sends to newLogEvent
|
||||
@@ -66,7 +67,7 @@ func Debugln(sl *subLogger, v ...interface{}) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.newLogEvent(fmt.Sprintln(v...), logger.DebugHeader, sl.output)
|
||||
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.DebugHeader, sl.output))
|
||||
}
|
||||
|
||||
// Debugf takes a pointer subLogger struct, string & interface formats and sends to Info()
|
||||
@@ -92,7 +93,7 @@ func Warn(sl *subLogger, data string) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.newLogEvent(data, logger.WarnHeader, sl.output)
|
||||
displayError(logger.newLogEvent(data, logger.WarnHeader, sl.output))
|
||||
}
|
||||
|
||||
// Warnln takes a pointer subLogger struct & interface formats and sends to newLogEvent()
|
||||
@@ -105,7 +106,7 @@ func Warnln(sl *subLogger, v ...interface{}) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.newLogEvent(fmt.Sprintln(v...), logger.WarnHeader, sl.output)
|
||||
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.WarnHeader, sl.output))
|
||||
}
|
||||
|
||||
// Warnf takes a pointer subLogger struct, string & interface formats and sends to Warn()
|
||||
@@ -131,7 +132,7 @@ func Error(sl *subLogger, data ...interface{}) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.newLogEvent(fmt.Sprint(data...), logger.ErrorHeader, sl.output)
|
||||
displayError(logger.newLogEvent(fmt.Sprint(data...), logger.ErrorHeader, sl.output))
|
||||
}
|
||||
|
||||
// Errorln takes a pointer subLogger struct, string & interface formats and sends to newLogEvent()
|
||||
@@ -144,7 +145,7 @@ func Errorln(sl *subLogger, v ...interface{}) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.newLogEvent(fmt.Sprintln(v...), logger.ErrorHeader, sl.output)
|
||||
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.ErrorHeader, sl.output))
|
||||
}
|
||||
|
||||
// Errorf takes a pointer subLogger struct, string & interface formats and sends to Debug()
|
||||
@@ -159,3 +160,9 @@ func Errorf(sl *subLogger, data string, v ...interface{}) {
|
||||
|
||||
Error(sl, fmt.Sprintf(data, v...))
|
||||
}
|
||||
|
||||
func displayError(err error) {
|
||||
if err != nil {
|
||||
log.Printf("Logger write error: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package logger
|
||||
|
||||
//nolint
|
||||
var (
|
||||
subLoggers = map[string]*subLogger{}
|
||||
|
||||
|
||||
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