112 lines
2.3 KiB
Go
112 lines
2.3 KiB
Go
package exchange
|
|
|
|
import (
|
|
"errors"
|
|
"sort"
|
|
"time"
|
|
|
|
. "git.qtrade.icu/coin-quant/trademodel"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
const (
|
|
WatchTypeCandle = "candle"
|
|
WatchTypeDepth = "depth"
|
|
WatchTypeTradeMarket = "trade_market"
|
|
WatchTypeTrade = "trade"
|
|
WatchTypePosition = "position"
|
|
WatchTypeBalance = "balance"
|
|
)
|
|
|
|
var (
|
|
ErrRetry = errors.New("need retry")
|
|
)
|
|
|
|
type WatchParam struct {
|
|
Type string
|
|
Param map[string]string
|
|
}
|
|
|
|
func WatchCandle(symbol, binSize string) WatchParam {
|
|
return WatchParam{
|
|
Type: WatchTypeCandle,
|
|
Param: map[string]string{"symbol": symbol, "bin": binSize},
|
|
}
|
|
}
|
|
|
|
type WatchFn func(interface{})
|
|
|
|
type FetchLimit struct {
|
|
Duration string
|
|
Limit int
|
|
}
|
|
|
|
// ExchangeInfo exchange info
|
|
type ExchangeInfo struct {
|
|
Name string
|
|
Value string
|
|
Desc string
|
|
KLineLimit FetchLimit
|
|
OrderLimit FetchLimit
|
|
}
|
|
|
|
type Exchange interface {
|
|
Info() ExchangeInfo
|
|
Symbols() ([]Symbol, error)
|
|
|
|
Start() error
|
|
Stop() error
|
|
|
|
// Watch exchange event, call multiple times for different event
|
|
Watch(WatchParam, WatchFn) error
|
|
|
|
// Kline get klines
|
|
GetKline(symbol, bSize string, start, end time.Time) (data []*Candle, err error)
|
|
|
|
// for trade
|
|
ProcessOrder(act TradeAction) (ret *Order, err error)
|
|
CancelAllOrders() (orders []*Order, err error)
|
|
CancelOrder(old *Order) (orders *Order, err error)
|
|
}
|
|
|
|
func KlineChan(e Exchange, symbol, bSize string, start, end time.Time) (dataCh chan *Candle, errCh chan error) {
|
|
dataCh = make(chan *Candle, 1024*10)
|
|
errCh = make(chan error, 1)
|
|
go func() {
|
|
defer func() {
|
|
close(dataCh)
|
|
close(errCh)
|
|
}()
|
|
tStart := start
|
|
tEnd := end
|
|
var nPrevStart int64
|
|
for {
|
|
klines, err := e.GetKline(symbol, bSize, tStart, tEnd)
|
|
if err != nil {
|
|
if errors.Is(err, ErrRetry) {
|
|
time.Sleep(time.Second * 5)
|
|
continue
|
|
}
|
|
errCh <- err
|
|
return
|
|
}
|
|
sort.Slice(klines, func(i, j int) bool {
|
|
return klines[i].Start < klines[j].Start
|
|
})
|
|
for _, v := range klines {
|
|
if v.Start <= nPrevStart {
|
|
continue
|
|
}
|
|
dataCh <- v
|
|
tStart = v.Time()
|
|
}
|
|
if tStart.Sub(tEnd) >= 0 || tStart.Unix() <= nPrevStart || len(klines) == 0 {
|
|
logrus.Info("KlineChan finished: [%s]-[%s], last datatime: %s", start, end, tStart)
|
|
break
|
|
}
|
|
nPrevStart = tStart.Unix()
|
|
}
|
|
}()
|
|
return
|
|
}
|