package mop import ( "encoding/json" "fmt" "io/ioutil" "net/http" "strconv" "strings" "time" //"github.com/markcheno/go-talib" ) type KLineData struct { Day string `json:"day"` Open float64 `json:"open,string"` High float64 `json:"high,string"` Low float64 `json:"low,string"` Close float64 `json:"close,string"` Volume float64 `json:"volume,string"` } func getURL(code string, ts int, count int) string { return fmt.Sprintf("http://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol=%s&scale=%d&ma=5&datalen=%d", code, ts, count) } func getKLineData(url string) ([]KLineData, error) { resp, err := http.Get(url) if err != nil { return nil, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } var data []KLineData err = json.Unmarshal(body, &data) if err != nil { return nil, err } return data, nil } func get_price_sina(code string, end_date string, count int, frequency string, startdate string) ([]KLineData, error) { frequency = strings.Replace(frequency, "1d", "240m", 1) frequency = strings.Replace(frequency, "1w", "1200m", 1) frequency = strings.Replace(frequency, "1M", "7200m", 1) ts, err := strconv.Atoi(strings.TrimSuffix(frequency, "m")) if err != nil { return nil, err } if end_date != "" && (frequency == "240m" || frequency == "1200m" || frequency == "7200m") { endDate, err := time.Parse("2006-01-02", end_date) if err != nil { return nil, err } unit := 1 if frequency == "1200m" { unit = 4 } else if frequency == "7200m" { unit = 29 } days := int(time.Since(endDate).Hours() / 24) count = count + days/unit } url := getURL(code, ts, count) //fmt.Printf("url: %s\n", url) data, err := getKLineData(url) if err != nil { return nil, err } //fmt.Printf("data: %v\n", data) if startdate != "" && (frequency == "240m" || frequency == "1200m" || frequency == "7200m") { endDate := time.Now() //endDate, err := time.Parse("2006-01-02", end_date) //if err != nil { // return nil, err //} start_date, err := time.Parse("2006-01-02", startdate) if err != nil { return nil, err } filteredData := []KLineData{} for _, d := range data { day, err := time.Parse("2006-01-02", d.Day) if err != nil { return nil, err } if day.After(start_date) && (day.Before(endDate) || day.Equal(endDate)) { filteredData = append(filteredData, d) } } return filteredData, nil } return data, nil } func findMaxHighAndMinLow(data []KLineData) (float64, float64) { maxHigh := data[0].High minLow := data[0].Low for _, d := range data { if d.High > maxHigh { maxHigh = d.High } if d.Low < minLow { minLow = d.Low } } return maxHigh, minLow } // 将interface{}类型转换为float64类型 func convertToFloat64(value interface{}) float64 { if floatValue, ok := value.(float64); ok { return floatValue } if stringValue, ok := value.(string); ok { floatValue, err := strconv.ParseFloat(stringValue, 64) if err == nil { return floatValue } } return 0 } func getURLTencent(code string, start string, count int) string { // 给定的日期 datestr := "" date, err := time.Parse("2006-01-02", start) if err != nil { fmt.Println("解析日期失败:", err) }else{ futureDate := date.AddDate(0, 0, 10) if futureDate.Before(time.Now()){ datestr = futureDate.Format("2006-01-02") fmt.Println(datestr) } } return fmt.Sprintf("https://web.ifzq.gtimg.cn/appstock/app/fqkline/get?param=%s,day,,%s,%d,qfq", code, datestr, count) } func getKLineTencent(url string, code string)([]KLineData, error){ resp, err := http.Get(url) if err != nil { return nil, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } var dataMap map[string]interface{} err = json.Unmarshal(body, &dataMap) if err != nil { fmt.Println("解析JSON字符串失败", err) return nil, err } klineData := make([]KLineData, 0) // 获取K线数据 if shData, ok := dataMap["data"].(map[string]interface{})[code].(map[string]interface{}); ok { if qfqday, ok := shData["qfqday"].([]interface{}); ok { for _, item := range qfqday { if data, ok := item.([]interface{}); ok { klineData = append(klineData, KLineData{ Day: data[0].(string), Open: convertToFloat64(data[1]), High: convertToFloat64(data[3]), Low: convertToFloat64(data[4]), Close: convertToFloat64(data[2]), Volume: convertToFloat64(data[5]), }) } } //fmt.Println(klineData) return klineData,nil }else if day, ok := shData["day"].([]interface{}); ok { for _, item := range day { if data, ok := item.([]interface{}); ok { klineData = append(klineData, KLineData{ Day: data[0].(string), Open: convertToFloat64(data[1]), High: convertToFloat64(data[3]), Low: convertToFloat64(data[4]), Close: convertToFloat64(data[2]), Volume: convertToFloat64(data[5]), }) } } return klineData,nil } } return klineData,nil } func get_price_tencent(code string, end_date string, count int, frequency string, startdate string) ([]KLineData, error) { frequency = strings.Replace(frequency, "1d", "240m", 1) frequency = strings.Replace(frequency, "1w", "1200m", 1) frequency = strings.Replace(frequency, "1M", "7200m", 1) if end_date != "" && (frequency == "240m" || frequency == "1200m" || frequency == "7200m") { endDate, err := time.Parse("2006-01-02", end_date) if err != nil { return nil, err } unit := 1 if frequency == "1200m" { unit = 4 } else if frequency == "7200m" { unit = 29 } days := int(time.Since(endDate).Hours() / 24) count = count + days/unit } /* url := getURL(code, ts, count) fmt.Printf("url: %s\n", url) data, err := getKLineData(url) */ url := getURLTencent(code, startdate, 10) //fmt.Printf("url: %s\n", url) data, err := getKLineTencent(url, code) if err != nil { return nil, err } //fmt.Printf("data: %v\n", data) if startdate != "" && (frequency == "240m" || frequency == "1200m" || frequency == "7200m") { endDate := time.Now() //endDate, err := time.Parse("2006-01-02", end_date) //if err != nil { // return nil, err //} start_date, err := time.Parse("2006-01-02", startdate) if err != nil { return nil, err } filteredData := []KLineData{} for _, d := range data { day, err := time.Parse("2006-01-02", d.Day) if err != nil { return nil, err } //fmt.Println(start_date, endDate, day) if day.After(start_date) && (day.Before(endDate) || day.Equal(endDate)) { filteredData = append(filteredData, d) } } return filteredData, nil } return data, nil } func getnextdaysHL(code string, start_date string) (float64, float64, float64, float64 ,int) { //data, err := get_price_sina(code, "", 30, "240m", start_date) data, err := get_price_tencent(code, "", 30, "240m", start_date) if err != nil { return 0, 0, 0, 0, 0 } pre := 3 if len(data) < 3 { pre = len(data) } //fmt.Printf("data: %v\n", data[:3]) caldata := data[:pre] maxHigh, minLow := findMaxHighAndMinLow(caldata) //fmt.Println(maxHigh, minLow) return caldata[0].Open, caldata[pre-1].Close, maxHigh, minLow, pre }