You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mop/day.go

298 lines
7.5 KiB

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
}