exchange/exchange.go

112 lines
2.3 KiB
Go
Raw Permalink Normal View History

2024-06-25 16:59:56 +00:00
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
}