123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- package services
- import (
- "encoding/json"
- "eta/eta_index_lib/models"
- "eta/eta_index_lib/utils"
- "fmt"
- "github.com/rdlucklib/rdluck_tools/http"
- "net/url"
- "strings"
- "time"
- )
- const (
- ThsHfApiUrl = "https://quantapi.51ifind.com/api/v1/high_frequency"
- )
- // GetEdbDataFromThsHf 获取高频数据
- func GetEdbDataFromThsHf(thsParams models.ThsHfSearchEdbReq, terminalCode string) (indexes []*models.ThsHfIndexWithData, err error) {
- terminal, e := GetTerminal(utils.DATA_SOURCE_THS, terminalCode)
- if e != nil {
- err = fmt.Errorf("获取同花顺终端配置失败, %v", e)
- return
- }
- // 走API
- if utils.ThsDataMethod == "" || utils.ThsDataMethod == "api" {
- var token string
- token, e = GetAccessToken(false, terminal.Value)
- if e != nil {
- err = fmt.Errorf("获取同花顺API-AccessToken失败, %v", e)
- return
- }
- // TEST
- //token = "9eba1634116ea2aed9a5b12b6e12b0b5fcbe0847.signs_NTc2NjQ4MTA5"
- return getEdbDataFromThsHfHttp(thsParams, terminal.Value, token)
- }
- // 走公用机
- if terminal.ServerUrl == "" {
- err = fmt.Errorf("同花顺终端地址未配置")
- return
- }
- return getEdbDataFromThsHfApp(thsParams, 0, terminal.ServerUrl)
- }
- // getEdbDataFromThsHfHttp API-获取高频指标数据
- func getEdbDataFromThsHfHttp(thsParams models.ThsHfSearchEdbReq, refreshToken, accessToken string) (indexes []*models.ThsHfIndexWithData, err error) {
- defer func() {
- if err != nil {
- tips := fmt.Sprintf("同花顺高频指标API-getEdbDataFromThsHfHttp err: %v", err)
- utils.FileLog.Info(tips)
- }
- }()
- // 请求参数参考
- //dataMap := map[string]interface{}{
- // "codes": "CU2407.SHF,CU2408.SHF",
- // "indicators": "pct_chg",
- // "starttime": "2024-06-06 09:15:00",
- // "endtime": "2024-06-11 15:15:00",
- // "functionpara": map[string]interface {
- // }{
- // "Limitstart": "10:00:00",
- // "Limitend": "14:15:00",
- // "Interval": 60,
- // "Fill": "Previous",
- // "CPS": "forward4",
- // "Timeformat": "LocalTime",
- // "BaseDate": "2024-01-01",
- // },
- //}
- // 额外参数
- funcParams := map[string]interface{}{}
- funcParams["Interval"] = thsParams.Interval
- if thsParams.Fill != "" {
- funcParams["Fill"] = thsParams.Fill
- }
- if thsParams.CPS != "" {
- funcParams["CPS"] = thsParams.CPS
- }
- if thsParams.BaseDate != "" {
- funcParams["BaseDate"] = thsParams.BaseDate
- }
- // TEST
- //funcParams["Limitstart"] = "10:00:00"
- //funcParams["Limitend"] = "14:15:00"
- //funcParams["Fill"] = "Previous"
- //funcParams["CPS"] = "forward4"
- //funcParams["Timeformat"] = "LocalTime"
- //funcParams["BaseDate"] = "2024-01-01"
- dataMap := map[string]interface{}{
- "codes": thsParams.StockCode,
- "indicators": thsParams.EdbCode,
- "starttime": thsParams.StartTime,
- "endtime": thsParams.EndTime,
- "functionpara": funcParams,
- }
- // 请求接口
- body, e, _ := postCurl(ThsHfApiUrl, dataMap, 0, refreshToken, accessToken)
- if e != nil {
- utils.FileLog.Info(string(body))
- err = fmt.Errorf("同花顺API-请求失败, %v", e)
- return
- }
- apiResp := new(models.ThsHfApiResp)
- if e = json.Unmarshal(body, &apiResp); e != nil {
- err = fmt.Errorf("同花顺API-解析响应失败, %v", e)
- return
- }
- if apiResp.ErrorCode != 0 {
- err = fmt.Errorf("同花顺高频API-状态码: %d, 提示信息: %s", apiResp.ErrorCode, apiResp.ErrMsg)
- return
- }
- indexes = make([]*models.ThsHfIndexWithData, 0)
- if len(apiResp.Tables) == 0 {
- utils.FileLog.Info("同花顺高频API-无数据")
- return
- }
- // 结果示例
- // {
- // "errorcode": 0,
- // "errmsg": "Success!",
- // "tables": [{
- // "thscode": "CU2407.SHF",
- // "time": ["2024-07-01 10:00", "2024-07-01 11:15", "2024-07-01 14:15", "2024-07-01 15:00"],
- // "table": {
- // "open": [77930.000000, 77980.000000, 77910.000000, 77850.000000],
- // "close": [77980.000000, 77920.000000, 77850.000000, 77780.000000]
- // }
- // }, {
- // "thscode": "CU2408.SHF",
- // "time": ["2024-07-01 10:00", "2024-07-01 11:15", "2024-07-01 14:15", "2024-07-01 15:00"],
- // "table": {
- // "open": [78180.000000, 78280.000000, 78220.000000, 78110.000000],
- // "close": [78280.000000, 78220.000000, 78110.000000, 78060.000000]
- // }
- // }]
- // }
- // Tables中的每一个对应一个证券代码
- for _, v := range apiResp.Tables {
- if len(v.Time) == 0 || len(v.Table) == 0 {
- continue
- }
- // Table中的K-V对应指标代码-数据值序列
- for tk, tv := range v.Table {
- index := new(models.ThsHfIndexWithData)
- index.StockCode = v.ThsCode
- index.EdbCode = tk
- td := make([]*models.ThsHfIndexData, 0)
- tvl := len(tv)
- for k, t := range v.Time {
- if k >= tvl {
- continue
- }
- dt, e := time.ParseInLocation("2006-01-02 15:04", t, time.Local)
- if e != nil {
- utils.FileLog.Info(fmt.Sprintf("同花顺API-time parse t: %s, err: %v", t, e))
- continue
- }
- td = append(td, &models.ThsHfIndexData{
- DataTime: dt,
- Value: tv[k],
- })
- }
- index.IndexData = td
- indexes = append(indexes, index)
- }
- }
- return
- }
- // getEdbDataFromThsHfApp 公用机-获取高频指标数据
- func getEdbDataFromThsHfApp(thsParams models.ThsHfSearchEdbReq, num int, serverUrl string) (indexes []*models.ThsHfIndexWithData, err error) {
- var requestUrl string
- defer func() {
- if err != nil {
- utils.FileLog.Info(fmt.Sprintf("requestUrl: %s", requestUrl))
- utils.FileLog.Info(fmt.Sprintf("getEdbDataFromThsHfApp: %v", err))
- }
- }()
- //serverUrl = "http://wxmsgsen1.hzinsights.com:8040/"
- baseUrl := fmt.Sprintf("%s%s", serverUrl, "edbInfo/ths/hf?")
- // 额外参数
- var funcParam string
- if thsParams.Interval > 0 {
- funcParam += fmt.Sprintf("Interval:%d,", thsParams.Interval)
- }
- if thsParams.Fill != "" {
- funcParam += fmt.Sprintf("Fill:%s,", thsParams.Fill)
- }
- if thsParams.CPS != "" {
- funcParam += fmt.Sprintf("CPS:%s,", thsParams.CPS)
- }
- if thsParams.BaseDate != "" {
- funcParam += fmt.Sprintf("BaseDate:%s,", thsParams.BaseDate)
- }
- funcParam = strings.TrimRight(funcParam, ",")
- params := url.Values{}
- params.Add("codes", thsParams.StockCode)
- params.Add("indicators", thsParams.EdbCode)
- params.Add("function_para", funcParam)
- params.Add("start_time", thsParams.StartTime)
- params.Add("end_time", thsParams.EndTime)
- // 请求终端
- requestUrl = baseUrl + params.Encode()
- body, e := http.Get(requestUrl)
- if e != nil {
- err = fmt.Errorf("")
- return
- }
- dataBody := strings.TrimLeft(string(body), `"`)
- dataBody = strings.TrimRight(dataBody, `"`)
- dataBody = strings.ReplaceAll(dataBody, `\`, ``)
- //utils.FileLog.Info(dataBody)
- appResp := new(TerminalResponse)
- if e = json.Unmarshal([]byte(dataBody), &appResp); e != nil {
- err = fmt.Errorf("同花顺APP-解析响应失败, %v", e)
- return
- }
- if appResp.ErrorCode != 0 {
- //如果是同花顺登录session失效了,那么就重新请求获取数据
- if appResp.ErrorCode == -1020 && num == 0 {
- return getEdbDataFromThsHfApp(thsParams, 1, serverUrl)
- }
- err = fmt.Errorf("同花顺APP-状态码: %d, 提示信息: %s", appResp.ErrorCode, appResp.ErrMsg)
- return
- }
- // 响应结果示例
- // {
- // "errorcode": 0,
- // "errmsg": "Success!",
- // "data": [{
- // "time": "2024-06-04 09:30",
- // "thscode": "CU2406.SHF",
- // "open": 81900.0,
- // "close": 81820.0
- // }, {
- // "time": "2024-06-04 10:00",
- // "thscode": "CU2406.SHF",
- // "open": 81820.0,
- // "close": 81790.0
- // }, {
- // "time": "2024-06-04 10:45",
- // "thscode": "CU2406.SHF",
- // "open": 81820.0,
- // "close": 81950.0
- // }]
- // }
- indexes = make([]*models.ThsHfIndexWithData, 0)
- indexMap := make(map[string]*models.ThsHfIndexWithData)
- for _, stockData := range appResp.Data {
- strTime := stockData["time"].(string)
- dataTime, e := time.ParseInLocation("2006-01-02 15:04", strTime, time.Local)
- if e != nil {
- utils.FileLog.Info("数据日期格式有误, time: %s, %v", strTime, e)
- continue
- }
- stockCode := stockData["thscode"].(string)
- // 指标代码+数据
- for k, v := range stockData {
- if k == "time" || k == "thscode" {
- continue
- }
- if v == nil {
- continue
- }
- val, ok := v.(float64)
- if !ok {
- continue
- }
- mk := fmt.Sprintf("%s-%s", stockCode, k)
- if indexMap[mk] == nil {
- indexMap[mk] = new(models.ThsHfIndexWithData)
- indexMap[mk].StockCode = stockCode
- indexMap[mk].EdbCode = k
- indexMap[mk].IndexData = make([]*models.ThsHfIndexData, 0)
- }
- indexMap[mk].IndexData = append(indexMap[mk].IndexData, &models.ThsHfIndexData{
- DataTime: dataTime,
- Value: val,
- })
- }
- }
- for _, v := range indexMap {
- indexes = append(indexes, v)
- }
- return
- }
|