2021-05-22 19:34:40 +00:00
|
|
|
package okex
|
|
|
|
|
|
|
|
import (
|
2021-05-25 18:11:02 +00:00
|
|
|
"context"
|
|
|
|
"math"
|
|
|
|
|
|
|
|
"github.com/c9s/bbgo/pkg/exchange/okex/okexapi"
|
|
|
|
"github.com/c9s/bbgo/pkg/types"
|
2021-05-22 19:34:40 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
2021-05-25 18:13:59 +00:00
|
|
|
// OKB is the platform currency of OKEx, pre-allocate static string here
|
|
|
|
const OKB = "OKB"
|
|
|
|
|
2021-05-22 19:34:40 +00:00
|
|
|
var log = logrus.WithFields(logrus.Fields{
|
|
|
|
"exchange": "okex",
|
|
|
|
})
|
|
|
|
|
|
|
|
type Exchange struct {
|
2021-05-25 18:11:02 +00:00
|
|
|
key, secret, passphrase string
|
|
|
|
|
|
|
|
client *okexapi.RestClient
|
|
|
|
}
|
|
|
|
|
|
|
|
func New(key, secret, passphrase string) *Exchange {
|
|
|
|
client := okexapi.NewClient()
|
|
|
|
client.Auth(key, secret, passphrase)
|
|
|
|
|
|
|
|
return &Exchange{
|
|
|
|
key: key,
|
|
|
|
secret: secret,
|
|
|
|
passphrase: passphrase,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Exchange) Name() types.ExchangeName {
|
|
|
|
return types.ExchangeOKEx
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Exchange) QueryMarkets(ctx context.Context) (types.MarketMap, error) {
|
|
|
|
instruments, err := e.client.PublicDataService.NewGetInstrumentsRequest().
|
|
|
|
InstrumentType(okexapi.InstrumentTypeSpot).
|
|
|
|
Do(ctx)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
markets := types.MarketMap{}
|
|
|
|
for _, instrument := range instruments {
|
|
|
|
symbol := toGlobalSymbol(instrument.InstrumentID)
|
|
|
|
market := types.Market{
|
2021-05-25 18:13:59 +00:00
|
|
|
Symbol: symbol,
|
|
|
|
LocalSymbol: instrument.InstrumentID,
|
|
|
|
|
2021-05-25 18:11:02 +00:00
|
|
|
QuoteCurrency: instrument.QuoteCurrency,
|
|
|
|
BaseCurrency: instrument.BaseCurrency,
|
|
|
|
|
|
|
|
// convert tick size OKEx to precision
|
|
|
|
PricePrecision: int(-math.Log10(instrument.TickSize.Float64())),
|
|
|
|
VolumePrecision: int(-math.Log10(instrument.LotSize.Float64())),
|
|
|
|
|
|
|
|
// TickSize: OKEx's price tick, for BTC-USDT it's "0.1"
|
|
|
|
TickSize: instrument.TickSize.Float64(),
|
|
|
|
|
|
|
|
// Quantity step size, for BTC-USDT, it's "0.00000001"
|
|
|
|
StepSize: instrument.LotSize.Float64(),
|
|
|
|
|
|
|
|
// for BTC-USDT, it's "0.00001"
|
|
|
|
MinQuantity: instrument.MinSize.Float64(),
|
|
|
|
|
|
|
|
// OKEx does not offer minimal notional, use 1 USD here.
|
|
|
|
MinNotional: 1.0,
|
|
|
|
MinAmount: 1.0,
|
|
|
|
}
|
|
|
|
markets[symbol] = market
|
|
|
|
}
|
|
|
|
|
|
|
|
return markets, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Exchange) QueryTicker(ctx context.Context, symbol string) (*types.Ticker, error) {
|
2021-05-25 18:44:03 +00:00
|
|
|
symbol = toLocalSymbol(symbol)
|
|
|
|
|
|
|
|
marketTicker, err := e.client.MarketTicker(symbol)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &types.Ticker{
|
|
|
|
Time: marketTicker.Timestamp.Time(),
|
|
|
|
Volume: marketTicker.Volume24H.Float64(),
|
|
|
|
Last: marketTicker.Last.Float64(),
|
|
|
|
Open: marketTicker.Open24H.Float64(),
|
|
|
|
High: marketTicker.High24H.Float64(),
|
|
|
|
Low: marketTicker.Low24H.Float64(),
|
|
|
|
Buy: marketTicker.BidPrice.Float64(),
|
|
|
|
Sell: marketTicker.AskPrice.Float64(),
|
|
|
|
}, nil
|
2021-05-25 18:11:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Exchange) QueryTickers(ctx context.Context, symbol string) (*types.Ticker, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Exchange) PlatformFeeCurrency() string {
|
2021-05-25 18:13:59 +00:00
|
|
|
return OKB
|
2021-05-22 19:34:40 +00:00
|
|
|
}
|