package okx import ( "context" "errors" "fmt" "net/http" "net/url" "sig-pub/pkg/types" "strings" "time" "github.com/go-resty/resty/v2" "golang.org/x/time/rate" ) const ( HttpBaseUrl = "https://www.okx.com" KlineBefore0 int64 = 1672502400000 // k线开始数据 2023-01-01 00:00:00 GMT+8 ) type OkxFetcher struct { client *resty.Client httpProxy string historyKlineLimiter *rate.Limiter } func NewOkxFetcher(httpProxy string) (f *OkxFetcher) { client := resty.New() client.SetTimeout(30 * time.Second) client.SetTransport(&http.Transport{ MaxIdleConns: 100, MaxConnsPerHost: 10, IdleConnTimeout: 90 * time.Second, TLSHandshakeTimeout: 10 * time.Second, }) if httpProxy != "" { client.SetProxy(httpProxy) } f = &OkxFetcher{ client: client, httpProxy: httpProxy, historyKlineLimiter: rate.NewLimiter(rate.Every(100*time.Millisecond), 20), // rate: 20次/2s } return } // FetchHistoryKlines 获取交易产品历史K线数据 // https://my.okx.com/docs-v5/zh/#order-book-trading-market-data-get-candlesticks-history // 周期区间 after > before, (after, before) func (f *OkxFetcher) FetchHistoryKlines(ctx context.Context, okxInstId string, interval types.Interval, after, before int64) (klines []*types.Kline, err error) { if okxInstId == "" { err = errors.New("instid is empty") return } if after <= 0 && before <= 0 { err = errors.New("time range zero") return } if err = f.historyKlineLimiter.Wait(ctx); err != nil { return } var params []string params = append(params, fmt.Sprintf("instId=%s", url.QueryEscape(okxInstId))) params = append(params, "limit=100") // 最大为100 if v, ok := subscribeCandles[interval]; ok { params = append(params, "bar="+v) } if after > 0 { params = append(params, fmt.Sprintf("after=%d", after)) } if before > 0 { params = append(params, fmt.Sprintf("before=%d", before)) } url := fmt.Sprintf("%s/api/v5/market/history-candles?%s", HttpBaseUrl, strings.Join(params, "&")) resp, err := f.client.R().Get(url) if err != nil { return } status := resp.StatusCode() if status != 200 { err = fmt.Errorf("request history klines status error: %s, %s", url, resp.Status()) return } fmt.Println(string(resp.Body())) return }