Files
big-qmt/go-client/sdk/data.go
2026-08-25 18:59:18 +08:00

375 lines
13 KiB
Go

package sdk
import (
"context"
"strconv"
"strings"
)
type Tick struct {
LastPrice float64
LastClose float64
Raw map[string]any
}
type HistoryDataRequest struct {
Len int
Period string
Field string
DividendType int
SkipPaused *bool
}
type MarketDataRequest struct {
Fields []string
Stocks []string
StartTime string
EndTime string
Period string
DividendType string
Count int
}
type SubscribeResult struct {
Status string `json:"status"`
SubID any `json:"sub_id"`
}
func (c *Client) StockName(ctx context.Context, stockcode string) (any, error) {
return c.postField(ctx, "/api/data/stock_name", map[string]any{"stockcode": stockcode}, "name")
}
func (c *Client) OpenDate(ctx context.Context, stockcode string) (any, error) {
return c.postField(ctx, "/api/data/open_date", map[string]any{"stockcode": stockcode}, "open_date")
}
func (c *Client) LastVolume(ctx context.Context, stockcode string) (any, error) {
return c.postField(ctx, "/api/data/last_volume", map[string]any{"stockcode": stockcode}, "last_volume")
}
func (c *Client) BarTimetag(ctx context.Context, index int) (any, error) {
return c.postField(ctx, "/api/data/bar_timetag", map[string]any{"index": index}, "timetag")
}
func (c *Client) TickTimetag(ctx context.Context) (any, error) {
return c.getField(ctx, "/api/data/tick_timetag", "timetag")
}
func (c *Client) Sector(ctx context.Context, sector string, realtime int) ([]any, error) {
var out struct {
Stocks []any `json:"stocks"`
}
if err := c.post(ctx, "/api/data/sector", map[string]any{"sector": sector, "realtime": realtime}, &out); err != nil {
return nil, err
}
return out.Stocks, nil
}
func (c *Client) Industry(ctx context.Context, industry string) ([]any, error) {
var out struct {
Stocks []any `json:"stocks"`
}
if err := c.post(ctx, "/api/data/industry", map[string]any{"industry": industry}, &out); err != nil {
return nil, err
}
return out.Stocks, nil
}
func (c *Client) StockListInSector(ctx context.Context, sectorname string) ([]any, error) {
var out struct {
Stocks []any `json:"stocks"`
}
if err := c.post(ctx, "/api/data/stock_list_in_sector", map[string]any{"sectorname": sectorname}, &out); err != nil {
return nil, err
}
return out.Stocks, nil
}
func (c *Client) WeightInIndex(ctx context.Context, indexcode, stockcode string) (any, error) {
return c.postField(ctx, "/api/data/weight_in_index", map[string]any{"indexcode": indexcode, "stockcode": stockcode}, "weight")
}
func (c *Client) ContractMultiplier(ctx context.Context, contractcode string) (any, error) {
return c.postField(ctx, "/api/data/contract_multiplier", map[string]any{"contractcode": contractcode}, "multiplier")
}
func (c *Client) RiskFreeRate(ctx context.Context, index int) (any, error) {
return c.postField(ctx, "/api/data/risk_free_rate", map[string]any{"index": index}, "risk_free_rate")
}
func (c *Client) DateLocation(ctx context.Context, strdate string) (any, error) {
return c.postField(ctx, "/api/data/date_location", map[string]any{"strdate": strdate}, "location")
}
func (c *Client) HistoryData(ctx context.Context, req HistoryDataRequest) (any, error) {
if req.Len == 0 {
req.Len = 10
}
skip := "true"
if req.SkipPaused != nil {
skip = strconv.FormatBool(*req.SkipPaused)
}
return c.postField(ctx, "/api/data/history_data", map[string]any{
"len": req.Len, "period": req.Period, "field": req.Field,
"dividend_type": req.DividendType, "skip_paused": skip,
}, "data")
}
func (c *Client) marketDataBody(req MarketDataRequest) map[string]any {
return map[string]any{
"fields": csvJoin(req.Fields),
"stock_code": csvJoin(req.Stocks),
"start_time": req.StartTime,
"end_time": req.EndTime,
"period": req.Period,
"dividend_type": req.DividendType,
"count": req.Count,
}
}
func (c *Client) MarketData(ctx context.Context, req MarketDataRequest) (any, error) {
return c.postField(ctx, "/api/data/market_data", c.marketDataBody(req), "data")
}
func (c *Client) MarketDataEx(ctx context.Context, req MarketDataRequest) (any, error) {
return c.postField(ctx, "/api/data/market_data_ex", c.marketDataBody(req), "data")
}
func (c *Client) FullTick(ctx context.Context, stocks []string) (map[string]Tick, error) {
raw := map[string]any{}
if err := c.post(ctx, "/api/data/full_tick", map[string]any{"stocks": stocks}, &raw); err != nil {
return nil, err
}
out := make(map[string]Tick, len(raw))
for code, v := range raw {
tick := Tick{Raw: map[string]any{}}
if m, ok := v.(map[string]any); ok {
tick.Raw = m
tick.LastPrice = asFloat(mapField(m, "lastPrice", "last_price", "LastPrice"))
tick.LastClose = asFloat(mapField(m, "lastClose", "last_close", "LastClose"))
}
out[code] = tick
}
return out, nil
}
func (c *Client) DividFactors(ctx context.Context, stockcode string) (any, error) {
return c.postField(ctx, "/api/data/divid_factors", map[string]any{"stockcode": stockcode}, "factors")
}
func (c *Client) MainContract(ctx context.Context, codemarket string) (any, error) {
return c.postField(ctx, "/api/data/main_contract", map[string]any{"codemarket": codemarket}, "main_contract")
}
func (c *Client) TimetagToDatetime(ctx context.Context, timetag int64, format string) (any, error) {
body := map[string]any{"timetag": timetag}
if format != "" {
body["format"] = format
}
return c.postField(ctx, "/api/data/timetag_to_datetime", body, "datetime")
}
func (c *Client) TotalShare(ctx context.Context, stockcode string) (any, error) {
return c.postField(ctx, "/api/data/total_share", map[string]any{"stockcode": stockcode}, "total_share")
}
func (c *Client) TradingDates(ctx context.Context, stockcode, startDate, endDate, period string, count int) ([]any, error) {
body := map[string]any{"stockcode": stockcode, "start_date": startDate, "end_date": endDate, "period": period}
if count != 0 {
body["count"] = count
}
var out struct {
Dates []any `json:"dates"`
}
if err := c.post(ctx, "/api/data/trading_dates", body, &out); err != nil {
return nil, err
}
return out.Dates, nil
}
func (c *Client) Svol(ctx context.Context, stockcode string) (any, error) {
return c.postField(ctx, "/api/data/svol", map[string]any{"stockcode": stockcode}, "svol")
}
func (c *Client) Bvol(ctx context.Context, stockcode string) (any, error) {
return c.postField(ctx, "/api/data/bvol", map[string]any{"stockcode": stockcode}, "bvol")
}
func (c *Client) Longhubang(ctx context.Context, stockList []string, startTime, endTime string) (any, error) {
return c.postField(ctx, "/api/data/longhubang", map[string]any{
"stock_list": csvJoin(stockList), "startTime": startTime, "endTime": endTime,
}, "data")
}
func (c *Client) Top10ShareHolder(ctx context.Context, stockList []string, dataName, startTime, endTime string) (any, error) {
return c.postField(ctx, "/api/data/top10_share_holder", map[string]any{
"stock_list": csvJoin(stockList), "data_name": dataName, "start_time": startTime, "end_time": endTime,
}, "data")
}
func (c *Client) OptionDetail(ctx context.Context, optioncode string) (any, error) {
return c.postField(ctx, "/api/data/option_detail", map[string]any{"optioncode": optioncode}, "detail")
}
func (c *Client) TurnoverRate(ctx context.Context, stockList []string, startTime, endTime string) (any, error) {
return c.postField(ctx, "/api/data/turnover_rate", map[string]any{
"stock_list": csvJoin(stockList), "startTime": startTime, "endTime": endTime,
}, "data")
}
func (c *Client) ETFInfo(ctx context.Context, stockcode string) (any, error) {
return c.postField(ctx, "/api/data/etf_info", map[string]any{"stockcode": stockcode}, "info")
}
func (c *Client) ETFIOPV(ctx context.Context, stockcode string) (any, error) {
return c.postField(ctx, "/api/data/etf_iopv", map[string]any{"stockcode": stockcode}, "iopv")
}
func (c *Client) InstrumentDetail(ctx context.Context, stockcode string) (any, error) {
return c.postField(ctx, "/api/data/instrumentdetail", map[string]any{"stockcode": stockcode}, "detail")
}
func (c *Client) ContractExpireDate(ctx context.Context, codemarket string) (any, error) {
return c.postField(ctx, "/api/data/contract_expire_date", map[string]any{"codemarket": codemarket}, "expire_date")
}
func (c *Client) OptionUndlData(ctx context.Context, undlCodeRef string) (any, error) {
return c.postField(ctx, "/api/data/option_undl_data", map[string]any{"undl_code_ref": undlCodeRef}, "data")
}
type FinancialDataRequest struct {
Tabname string
Colname string
Market string
Code string
ReportType string
Barpos int
FieldList []string
StockList []string
StartDate string
EndDate string
}
func (c *Client) FinancialData(ctx context.Context, req FinancialDataRequest) (any, error) {
body := map[string]any{
"tabname": req.Tabname, "colname": req.Colname, "market": req.Market, "code": req.Code,
"report_type": req.ReportType, "barpos": req.Barpos,
"fieldList": csvJoin(req.FieldList), "stockList": csvJoin(req.StockList),
"startDate": req.StartDate, "endDate": req.EndDate,
}
return c.postField(ctx, "/api/data/financial_data", body, "data")
}
type FactorDataRequest struct {
FieldList []string
StockList []string
StockCode string
StartDate string
EndDate string
}
func (c *Client) FactorData(ctx context.Context, req FactorDataRequest) (any, error) {
body := map[string]any{
"fieldList": csvJoin(req.FieldList), "stockList": csvJoin(req.StockList),
"stockCode": req.StockCode, "startDate": req.StartDate, "endDate": req.EndDate,
}
return c.postField(ctx, "/api/data/factor_data", body, "data")
}
func (c *Client) HisSTData(ctx context.Context, stockCode string) (any, error) {
return c.postField(ctx, "/api/data/his_st_data", map[string]any{"stockCode": stockCode}, "data")
}
func (c *Client) HisIndexData(ctx context.Context, index string) (any, error) {
return c.postField(ctx, "/api/data/his_index_data", map[string]any{"index": index}, "data")
}
func (c *Client) AllSubscription(ctx context.Context) (any, error) {
return c.getField(ctx, "/api/data/all_subscription", "subscriptions")
}
func (c *Client) OptionList(ctx context.Context, undlCode, dedate, opttype string, isavailable bool) (any, error) {
body := map[string]any{
"undl_code": undlCode, "dedate": dedate, "opttype": opttype,
"isavailable": strconv.FormatBool(isavailable),
}
return c.postField(ctx, "/api/data/option_list", body, "option_list")
}
func (c *Client) HisContractList(ctx context.Context, market string) (any, error) {
return c.postField(ctx, "/api/data/his_contract_list", map[string]any{"market": market}, "contracts")
}
func (c *Client) OptionIV(ctx context.Context, optioncode string) (any, error) {
return c.postField(ctx, "/api/data/option_iv", map[string]any{"optioncode": optioncode}, "iv")
}
type BSMPriceRequest struct {
OptionType string
ObjectPrices any // float64 或 []float64
StrikePrice float64
RiskFree float64
Sigma float64
Days int
Dividend float64
}
func (c *Client) BSMPrice(ctx context.Context, req BSMPriceRequest) (any, error) {
prices := req.ObjectPrices
if vals, ok := req.ObjectPrices.([]float64); ok {
parts := make([]string, len(vals))
for i, v := range vals {
parts[i] = strconv.FormatFloat(v, 'f', -1, 64)
}
prices = strings.Join(parts, ",")
}
return c.postField(ctx, "/api/data/bsm_price", map[string]any{
"optionType": req.OptionType, "objectPrices": prices, "strikePrice": req.StrikePrice,
"riskFree": req.RiskFree, "sigma": req.Sigma, "days": req.Days, "dividend": req.Dividend,
}, "price")
}
type BSMIVRequest struct {
OptionType string `json:"optionType"`
ObjectPrices float64 `json:"objectPrices"`
StrikePrice float64 `json:"strikePrice"`
OptionPrice float64 `json:"optionPrice"`
RiskFree float64 `json:"riskFree"`
Days int `json:"days"`
Dividend float64 `json:"dividend"`
}
func (c *Client) BSMIV(ctx context.Context, req BSMIVRequest) (any, error) {
return c.postField(ctx, "/api/data/bsm_iv", req, "iv")
}
type LocalDataRequest struct {
StockCode string `json:"stock_code"`
StartTime string `json:"start_time,omitempty"`
EndTime string `json:"end_time,omitempty"`
Period string `json:"period,omitempty"`
DividType string `json:"divid_type,omitempty"`
Count int `json:"count"`
}
func (c *Client) LocalData(ctx context.Context, req LocalDataRequest) (any, error) {
return c.postField(ctx, "/api/data/local_data", req, "data")
}
func (c *Client) SubscribeQuote(ctx context.Context, stockCode, period, dividendType string) (*SubscribeResult, error) {
var out SubscribeResult
body := map[string]any{"stock_code": stockCode, "period": period, "dividend_type": dividendType}
if err := c.post(ctx, "/api/data/subscribe_quote", body, &out); err != nil {
return nil, err
}
return &out, nil
}
func (c *Client) UnsubscribeQuote(ctx context.Context, subID int) (*SubscribeResult, error) {
var out SubscribeResult
if err := c.post(ctx, "/api/data/unsubscribe_quote", map[string]any{"sub_id": subID}, &out); err != nil {
return nil, err
}
return &out, nil
}