package future_good import ( "errors" "fmt" "github.com/shopspring/decimal" "hongze/hongze_yb/models/request" "hongze/hongze_yb/models/response/chart_info" chartEdbMappingModel "hongze/hongze_yb/models/tables/chart_edb_mapping" edbDataModel "hongze/hongze_yb/models/tables/edb_data" "hongze/hongze_yb/models/tables/future_good_edb_data" "hongze/hongze_yb/models/tables/future_good_edb_info" "hongze/hongze_yb/services/alarm_msg" "hongze/hongze_yb/services/chart" "hongze/hongze_yb/utils" "sort" "strconv" "time" ) // GetChartEdbData 获取图表的指标数据 func GetChartEdbData(chartInfoId int, startDate, endDate string, edbInfoMapping, futureGoodEdbInfoMapping *chartEdbMappingModel.ChartEdbInfoMappingList, barChartInfoDateList []request.BarChartInfoDateReq) (barConfigEdbInfoIdList []request.BarChartInfoEdbItemReq, edbList []*chartEdbMappingModel.ChartEdbInfoMappingList, xEdbIdValue []int, xDataList []chart_info.XData, yDataList []chart_info.YData, sourceArr []string, err error) { edbList = make([]*chartEdbMappingModel.ChartEdbInfoMappingList, 0) sourceArr = make([]string, 0) if futureGoodEdbInfoMapping == nil { err = errors.New("商品指标未选取") return } if edbInfoMapping == nil { err = errors.New("ETA指标未选取") return } // 指标对应的所有数据 edbDataListMap := make(map[int][]*edbDataModel.EdbDataList) item := new(chartEdbMappingModel.ChartEdbInfoMappingList) edbInfoMapping.FrequencyEn = chart.GetFrequencyEn(edbInfoMapping.Frequency) if edbInfoMapping.Unit == `无` { edbInfoMapping.Unit = `` } if futureGoodEdbInfoMapping.Unit == `无` { futureGoodEdbInfoMapping.Unit = `` } if chartInfoId <= 0 { edbInfoMapping.IsAxis = 1 edbInfoMapping.LeadValue = 0 edbInfoMapping.LeadUnit = "" edbInfoMapping.ChartEdbMappingId = 0 edbInfoMapping.ChartInfoId = 0 edbInfoMapping.IsOrder = false edbInfoMapping.EdbInfoType = 1 edbInfoMapping.ChartStyle = "" edbInfoMapping.ChartColor = "" edbInfoMapping.ChartWidth = 0 futureGoodEdbInfoMapping.IsAxis = 1 futureGoodEdbInfoMapping.LeadValue = 0 futureGoodEdbInfoMapping.LeadUnit = "" futureGoodEdbInfoMapping.ChartEdbMappingId = 0 futureGoodEdbInfoMapping.ChartInfoId = 0 futureGoodEdbInfoMapping.IsOrder = false futureGoodEdbInfoMapping.EdbInfoType = 1 futureGoodEdbInfoMapping.ChartStyle = "" futureGoodEdbInfoMapping.ChartColor = "" futureGoodEdbInfoMapping.ChartWidth = 0 } else { edbInfoMapping.LeadUnitEn = chart.GetLeadUnitEn(edbInfoMapping.LeadUnit) futureGoodEdbInfoMapping.LeadUnitEn = chart.GetLeadUnitEn(futureGoodEdbInfoMapping.LeadUnit) } // 普通的指标数据 { dataList := make([]*edbDataModel.EdbDataList, 0) dataList, err = edbDataModel.GetEdbDataList(edbInfoMapping.Source, edbInfoMapping.SubSource, edbInfoMapping.EdbInfoId, startDate, endDate) edbDataListMap[edbInfoMapping.EdbInfoId] = dataList item.DataList = dataList edbList = append(edbList, edbInfoMapping) barConfigEdbInfoIdList = append(barConfigEdbInfoIdList, request.BarChartInfoEdbItemReq{ EdbInfoId: edbInfoMapping.EdbInfoId, //Name: edbInfoMapping.EdbName, Name: "现货价", NameEn: "Spot Price", Source: edbInfoMapping.Source, }) if !utils.InArray(edbInfoMapping.Source, utils.SystemSourceList) { //来源于系统的指标,都展示为弘则研究 if !utils.InArray(edbInfoMapping.SourceName, sourceArr) { sourceArr = append(sourceArr, edbInfoMapping.SourceName) } } } // 获取主力合约和最新日期 var zlFutureGoodEdbInfo *future_good_edb_info.FutureGoodEdbInfo var latestDate string // 最新日期是这个 var regionType string // 交易所来源:“国内”,“海外” var futureGoodEdbType int { // 寻找主力合约 zlFutureGoodEdbInfo, err = future_good_edb_info.GetFutureGoodEdbInfo(futureGoodEdbInfoMapping.EdbInfoId) if err != nil { return } regionType = zlFutureGoodEdbInfo.RegionType futureGoodEdbType = int(zlFutureGoodEdbInfo.FutureGoodEdbType) // 如果当前合约配置的 "画图时,日期来源的指标id" 并不是自己的话,那么就去查找对应配置的合约 if uint64(zlFutureGoodEdbInfo.DateSourceID) != zlFutureGoodEdbInfo.FutureGoodEdbInfoID { sourceDateFutureGoodEdbInfo, tmpErr := future_good_edb_info.GetFutureGoodEdbInfo(int(zlFutureGoodEdbInfo.DateSourceID)) if tmpErr != nil { err = tmpErr return } latestDate = sourceDateFutureGoodEdbInfo.EndDate.Format(utils.FormatDate) // 最新日期是这个 } else { latestDate = zlFutureGoodEdbInfo.EndDate.Format(utils.FormatDate) // 最新日期是这个 } if latestDate == `0000-00-00` { err = errors.New("日期异常") return } } // 获取期货指标以及期货数据 tmpFutureGoodEdbInfoList, err := future_good_edb_info.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfoMapping.EdbInfoId) if err != nil { return } latestDateTime, _ := time.ParseInLocation(utils.FormatDate, latestDate, time.Local) _, futureGoodEdbInfoList, err := getFutureGoodEdbInfoList(latestDateTime, tmpFutureGoodEdbInfoList, barChartInfoDateList) if err != nil { return } futureGoodMappingList := make([]*chartEdbMappingModel.ChartEdbInfoMappingList, 0) for k, v := range futureGoodEdbInfoList { newMappingInfo := &chartEdbMappingModel.ChartEdbInfoMappingList{ ChartEdbInfoMapping: chartEdbMappingModel.ChartEdbInfoMapping{ EdbInfoId: int(v.FutureGoodEdbInfoID), SourceName: v.Exchange, Source: utils.CHART_SOURCE_FUTURE_GOOD, EdbCode: v.FutureGoodEdbCode, EdbName: v.FutureGoodEdbName, EdbAliasName: v.FutureGoodEdbName, EdbNameEn: v.FutureGoodEdbNameEn, EdbType: edbInfoMapping.EdbType, Frequency: edbInfoMapping.Frequency, FrequencyEn: edbInfoMapping.FrequencyEn, Unit: edbInfoMapping.Unit, UnitEn: edbInfoMapping.UnitEn, StartDate: v.StartDate.Format(utils.FormatDateTime), EndDate: v.EndDate.Format(utils.FormatDateTime), ModifyTime: v.ModifyTime.Format(utils.FormatDateTime), ChartEdbMappingId: int(v.FutureGoodEdbInfoID), ChartInfoId: edbInfoMapping.ChartInfoId, MaxData: v.MaxValue, MinData: v.MinValue, IsOrder: edbInfoMapping.IsOrder, IsAxis: edbInfoMapping.IsAxis, EdbInfoType: edbInfoMapping.EdbInfoType, EdbInfoCategoryType: edbInfoMapping.EdbInfoCategoryType, LeadValue: edbInfoMapping.LeadValue, LeadUnit: edbInfoMapping.LeadUnit, LeadUnitEn: edbInfoMapping.LeadUnitEn, ChartStyle: edbInfoMapping.ChartStyle, ChartColor: edbInfoMapping.ChartColor, PredictChartColor: edbInfoMapping.PredictChartColor, ChartWidth: edbInfoMapping.ChartWidth, ChartType: edbInfoMapping.ChartType, LatestDate: v.LatestDate, LatestValue: v.LatestValue, UniqueCode: futureGoodEdbInfoMapping.UniqueCode + "1" + strconv.Itoa(k), MinValue: v.MinValue, MaxValue: v.MaxValue, }, DataList: nil, IsNullData: false, } futureGoodMappingList = append(futureGoodMappingList, newMappingInfo) barConfigEdbInfoIdList = append(barConfigEdbInfoIdList, request.BarChartInfoEdbItemReq{ EdbInfoId: newMappingInfo.EdbInfoId, Name: fmt.Sprint("M+", v.Month), NameEn: fmt.Sprint("M+", v.Month), Source: newMappingInfo.Source, }) } // 获取数据 for _, v := range futureGoodMappingList { dataList := make([]*edbDataModel.EdbDataList, 0) tmpDataList, tmpErr := future_good_edb_data.GetFutureGoodEdbDataListByDate(v.EdbInfoId, startDate, endDate) if tmpErr != nil { return } for _, tmpData := range tmpDataList { dataList = append(dataList, &edbDataModel.EdbDataList{ EdbDataId: int(tmpData.FutureGoodEdbDataID), EdbInfoId: int(tmpData.FutureGoodEdbInfoID), DataTime: tmpData.DataTime.Format(utils.FormatDate), DataTimestamp: tmpData.DataTimestamp, Value: tmpData.Close, }) } edbDataListMap[v.EdbInfoId] = dataList v.DataList = dataList } edbList = append(edbList, futureGoodMappingList...) xEdbIdValue, yDataList, err = BarChartData(edbList[0], futureGoodEdbInfoList, edbDataListMap, barChartInfoDateList, regionType, edbInfoMapping.EndDate) xDataList = []chart_info.XData{ { Name: "现货价", NameEn: "Spot Price", }, } //yDataList =make([]chart_info.YData,0) //chart_info.YData{ // Date: "", // Color: "", // Name: "", // NameEn: "", // Value: nil, // NoDataEdbList: nil, // XEdbInfoIdList: nil, //} futureGoodEdbInfoIndexMap := make(map[int]int) for index, v := range futureGoodEdbInfoList { futureGoodEdbInfoIndexMap[int(v.FutureGoodEdbInfoID)] = index } nMap := make(map[int]int) maxIndex := 0 // 最大x轴的下标 for k, tmpYData := range yDataList { yDataMap := tmpYData.EdbValMap edbInfoIdList := make([]int, 0) noDataEdbInfoIdList := make([]int, 0) valueList := make([]float64, 0) noDataEdbIdMap := make(map[int]int) // 所有的N值 for _, n := range tmpYData.M { nMap[n] = n } // 基础指标 { baseEdbInfId := edbList[0].EdbInfoId edbInfoIdList = append(edbInfoIdList, baseEdbInfId) tmpVal, ok := yDataMap[baseEdbInfId] valueList = append(valueList, tmpVal) if !ok || tmpVal == 0 { noDataEdbInfoIdList = append(noDataEdbInfoIdList, baseEdbInfId) noDataEdbIdMap[baseEdbInfId] = baseEdbInfId } } for _, futureGoodEdbInfo := range futureGoodEdbInfoList { tmpEdbInfId := int(futureGoodEdbInfo.FutureGoodEdbInfoID) edbInfoIdList = append(edbInfoIdList, tmpEdbInfId) tmpVal, ok := yDataMap[tmpEdbInfId] valueList = append(valueList, tmpVal) if !ok || tmpVal == 0 { noDataEdbInfoIdList = append(noDataEdbInfoIdList, tmpEdbInfId) noDataEdbIdMap[tmpEdbInfId] = tmpEdbInfId } } //tmpYData.Value = valueList tmpYData.NoDataEdbList = noDataEdbInfoIdList yDataList[k] = tmpYData lenEdbId := len(edbInfoIdList) tmpMaxIndex := lenEdbId - 1 // 当前数据的最大x轴的下标 for i := lenEdbId - 1; i >= 0; i-- { // 如果没有在无数据的指标列表中找到,那么就找到了最大x轴的下标 if _, ok := noDataEdbIdMap[edbInfoIdList[i]]; !ok { // 如果最大x轴的下标 小于 当前下标,那么就重新赋值 if maxIndex < i-1 { maxIndex = i - 1 } break } tmpMaxIndex = i - 1 } // 如果最大x轴的下标 小于 当前下标,那么就重新赋值 if maxIndex < tmpMaxIndex { maxIndex = tmpMaxIndex } } //xEdbIdValue = xEdbIdValue[0:maxIndex] // 找出所有的N值,并进行正序排列 nList := make([]int, 0) for _, n := range nMap { nList = append(nList, n) } sort.Slice(nList, func(i, j int) bool { return nList[i] < nList[j] }) for k, v := range yDataList { if len(v.XEdbInfoIdList) >= maxIndex+1 { yDataList[k].XEdbInfoIdList = v.XEdbInfoIdList[0 : maxIndex+1] } if len(v.Value) >= maxIndex+1 { yDataList[k].Value = v.Value[0 : maxIndex+1] } } tmpXDataList, newYDataList, err := handleResultData(regionType, futureGoodEdbType, yDataList, futureGoodEdbInfoList, maxIndex) if err != nil { return } xDataList = append(xDataList, tmpXDataList...) yDataList = newYDataList return } // BarChartData 获取数据 func BarChartData(edbInfoMapping *chartEdbMappingModel.ChartEdbInfoMappingList, futureGoodMappingList []*future_good_edb_info.FutureGoodEdbInfo, edbDataListMap map[int][]*edbDataModel.EdbDataList, barChartInfoDateList []request.BarChartInfoDateReq, regionType, latestDate string) (edbIdList []int, yDataList []chart_info.YData, err error) { // 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3}) edbDataMap := make(map[int]map[string]float64) for edbInfoId, edbDataList := range edbDataListMap { edbDateData := make(map[string]float64) for _, edbData := range edbDataList { edbDateData[edbData.DataTime] = edbData.Value } edbDataMap[edbInfoId] = edbDateData } // edbIdList 指标展示顺序;x轴的指标顺序 edbIdList = make([]int, 0) edbIdList = append(edbIdList, edbInfoMapping.EdbInfoId) for _, v := range futureGoodMappingList { edbIdList = append(edbIdList, int(v.FutureGoodEdbInfoID)) } latestDateTime, _ := time.ParseInLocation(utils.FormatDate, latestDate, time.Local) yDataList = make([]chart_info.YData, 0) //y轴的数据列表 for _, barChartInfoDate := range barChartInfoDateList { yDataMap := make(map[int]float64) var maxDate time.Time var findDateTime time.Time switch barChartInfoDate.Type { case 1: //最新值 findDateTime = latestDateTime case 2: //近期几天 findDateTime = latestDateTime.AddDate(0, 0, -barChartInfoDate.Value) case 3: // 固定日期 //寻找固定日期的数据 tmpFindDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local) if tmpErr != nil { err = tmpErr return } findDateTime = tmpFindDateTime default: err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type)) return } if findDateTime.IsZero() { err = errors.New("错误的日期") return } findDataList := make([]float64, 0) // 当前日期的数据值 noDataIdList := make([]int, 0) // 没有数据的指标id noDataIdMap := make(map[int]int, 0) // 没有数据的指标map xEdbInfoIdList := make([]int, 0) // 当前数据的指标id列表 // 现货指标 realDateTime, findDataValue, isFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[edbInfoMapping.EdbInfoId], edbDataMap[edbInfoMapping.EdbInfoId]) if tmpErr != nil { err = tmpErr return } findDataList = append(findDataList, findDataValue) yDataMap[edbInfoMapping.EdbInfoId] = findDataValue if isFind { maxDate = realDateTime } else { noDataIdList = append(noDataIdList, edbInfoMapping.EdbInfoId) noDataIdMap[edbInfoMapping.EdbInfoId] = edbInfoMapping.EdbInfoId } currMonth := findDateTime.Month() // 当前月份 currYear := findDateTime.Year() // 当前年份 xEdbInfoIdList = append(xEdbInfoIdList, edbInfoMapping.EdbInfoId) mList := make([]int, 0) // 间隔月份 indexList := make([]int, 0) if regionType == `国内` { for i := currMonth + 1; i <= 12; i++ { indexList = append(indexList, int(i)) mList = append(mList, int(i-currMonth)) } for i := 1; i < int(currMonth); i++ { indexList = append(indexList, i) mList = append(mList, 12+i-int(currMonth)) } } else { for i, v := range futureGoodMappingList { if v.FutureGoodEdbType == 2 { if i == 0 { continue } indexList = append(indexList, i) mList = append(mList, int(v.Month)) } else { if v.Year > currYear || (v.Year == currYear && int(v.Month) > int(currMonth)) { indexList = append(indexList, i) mList = append(mList, (v.Year-currYear)*12+int(v.Month)-int(currMonth)) } } } } for _, i := range indexList { futureGoodMapping := futureGoodMappingList[i] // 当前的期货指标 //tmpRealDateTime, tmpFindDataValue, tmpIsFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[futureGoodMapping.FutureGoodEdbInfoId], edbDataMap[futureGoodMapping.FutureGoodEdbInfoId]) //if tmpErr != nil { // err = tmpErr // return //} //tmpRealDateTime := findDateTime // 按照配置找到的日期 tmpRealDateTime := realDateTime // 实际现货的日期 tmpFindDataValue, tmpIsFind := edbDataMap[int(futureGoodMapping.FutureGoodEdbInfoID)][tmpRealDateTime.Format(utils.FormatDate)] yDataMap[int(futureGoodMapping.FutureGoodEdbInfoID)] = tmpFindDataValue findDataList = append(findDataList, tmpFindDataValue) if tmpIsFind { if maxDate.IsZero() || maxDate.Before(tmpRealDateTime) { maxDate = tmpRealDateTime } } else { noDataIdList = append(noDataIdList, int(futureGoodMapping.FutureGoodEdbInfoID)) noDataIdMap[int(futureGoodMapping.FutureGoodEdbInfoID)] = int(futureGoodMapping.FutureGoodEdbInfoID) } // 当前期货合约的指标 xEdbInfoIdList = append(xEdbInfoIdList, int(futureGoodMapping.FutureGoodEdbInfoID)) } yName := barChartInfoDate.Name yNameEn := barChartInfoDate.Name if yName == `` { if barChartInfoDate.Type == 2 { yName = strconv.Itoa(barChartInfoDate.Value) + "天前" if barChartInfoDate.Value == 1 { yNameEn = strconv.Itoa(barChartInfoDate.Value) + "day ago" } else { yNameEn = strconv.Itoa(barChartInfoDate.Value) + " days ago" } } else { yName = maxDate.Format(utils.FormatDate) yNameEn = maxDate.Format(utils.FormatDate) } } yDate := "0000-00-00" if !maxDate.IsZero() { yDate = maxDate.Format(utils.FormatDate) } // 数据处理,将没有数据的下标,赋值平均值 { hasDataIndexList := make([]int, 0) for dataK, edbInfoId := range xEdbInfoIdList { if _, ok := noDataIdMap[edbInfoId]; !ok { // 如果是没有数据的指标id hasDataIndexList = append(hasDataIndexList, dataK) } } lenHasDataIndex := len(hasDataIndexList) if lenHasDataIndex > 0 { for lenHasDataI := 1; lenHasDataI < lenHasDataIndex; lenHasDataI++ { perK := hasDataIndexList[lenHasDataI-1] //上一个有数据的指标下标 currK := hasDataIndexList[lenHasDataI] //当前有数据的指标下标 preVal := findDataList[perK] //上一个有数据的坐标的值 currVal := findDataList[currK] //当前有数据的指标的值 // 环差值 hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(currK - perK))) var tmpI int64 // 将两个中间的数据做平均值补全 for hcI := perK + 1; hcI < currK; hcI++ { tmpI++ findDataList[hcI], _ = decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(tmpI))).RoundCeil(4).Float64() } } } } yDataList = append(yDataList, chart_info.YData{ Date: yDate, ConfigDate: realDateTime, Value: findDataList, NoDataEdbList: noDataIdList, XEdbInfoIdList: xEdbInfoIdList, Color: barChartInfoDate.Color, Name: yName, NameEn: yNameEn, EdbValMap: yDataMap, M: mList, }) } return } // GetNeedDateData 获取合约内需要的日期数据 func GetNeedDateData(needDateTime time.Time, dataList []*edbDataModel.EdbDataList, edbDataMap map[string]float64) (findDateTime time.Time, findDataValue float64, isFind bool, err error) { //dataList := edbDataListMap[edbInfoId] //指标的所有数据值 if len(dataList) <= 0 { // 没有数据的指标id return } //最早的日期 minDateTime, err := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local) if err != nil { return } for tmpDateTime := needDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) { tmpDate := tmpDateTime.Format(utils.FormatDate) if tmpValue, ok := edbDataMap[tmpDate]; ok { //如果能找到数据,那么就返回 // 数据为0,也直接返回,做无值处理 if tmpValue == 0 { return } findDateTime, _ = time.ParseInLocation(utils.FormatDate, tmpDate, time.Local) findDataValue = tmpValue isFind = true return } } return } // FutureGoodChartInfoRefresh // @author Roc // @datetime 2023-2-2 18:44:46 // @description 商品价格曲线图表刷新 func FutureGoodChartInfoRefresh(chartInfoId int) (err error) { var errMsg string defer func() { if err != nil { go alarm_msg.SendAlarmMsg("ChartInfoRefresh:"+errMsg, 3) fmt.Println("ChartInfoRefresh Err:" + errMsg) } }() edbInfoMapping, err := chartEdbMappingModel.GetEtaEdbChartEdbMapping(chartInfoId) if err != nil { errMsg = "获取需要刷新的ETA指标失败:Err:" + err.Error() return } // 获取期货指标 futureGoodEdbInfoMapping, err := chartEdbMappingModel.GetFutureGoodEdbChartEdbMapping(chartInfoId) if err != nil { errMsg = "获取需要刷新的商品期货指标失败:Err:" + err.Error() return } // 获取期货指标以及期货数据 futureGoodEdbInfoList, err := future_good_edb_info.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfoMapping.EdbInfoId) if err != nil { return } // 批量刷新ETA指标 err, _ = chart.EdbInfoRefreshAllFromBase([]int{edbInfoMapping.EdbInfoId}, false) if err != nil { return } // 批量刷新期货指标 err = FutureGoodEdbInfoRefreshAllFromBase(futureGoodEdbInfoList, false) if err != nil { return } return } // handleResultData 处理成最终的结果数据 func handleResultData(regionType string, futureGoodEdbType int, yDataList []chart_info.YData, futureGoodEdbInfoList []*future_good_edb_info.FutureGoodEdbInfo, maxIndex int) (xDataList []chart_info.XData, newYDataList []chart_info.YData, err error) { xDataList = make([]chart_info.XData, 0) newYDataList = yDataList if regionType == `国内` { for i := 1; i < 12; i++ { if i > maxIndex { break } xDataList = append(xDataList, chart_info.XData{ Name: fmt.Sprint("M+", i), NameEn: fmt.Sprint("M+", i), }) } return } futureGoodEdbInfoMap := make(map[int]*future_good_edb_info.FutureGoodEdbInfo) for _, v := range futureGoodEdbInfoList { futureGoodEdbInfoMap[int(v.FutureGoodEdbInfoID)] = v } if futureGoodEdbType == 2 { // FutureGoodEdbType int `description:"指标类型,1:年月是固定的合约;2:只有M+N期的合约,未固定年月"` nList := []int{3, 15, 27} for _, i := range nList { xDataList = append(xDataList, chart_info.XData{ Name: fmt.Sprint("M+", i), NameEn: fmt.Sprint("M+", i), }) } for yIndex, yData := range yDataList { newYDataList[yIndex].XEdbInfoIdList = []int{} newYDataList[yIndex].Value = []float64{} tmpNList := nList //当前的主力合约 newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, yData.XEdbInfoIdList[0]) newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[0]) xEdbInfoIdList := yData.XEdbInfoIdList[1:] valIndex := 1 needNum := 0 for _, n := range tmpNList { if len(xEdbInfoIdList) > 0 { edbInfoId := xEdbInfoIdList[0] futureGoodEdbInfo, ok := futureGoodEdbInfoMap[edbInfoId] if !ok { err = errors.New("找不到指标") return } // 当前距离最早的日期相差的N数 if int(futureGoodEdbInfo.Month) == n { if needNum > 0 { currVal := yData.Value[valIndex] preVal := yData.Value[valIndex-1] hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(needNum + 1))) for tmpNum := 0; tmpNum < needNum; tmpNum++ { newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, 0) // 赋值平均值 tmpVal, _ := decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(int64(tmpNum + 1)))).RoundCeil(4).Float64() newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, tmpVal) } } newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, edbInfoId) newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[valIndex]) valIndex++ needNum = 0 if len(xEdbInfoIdList) > 0 { xEdbInfoIdList = xEdbInfoIdList[1:] } } else { needNum++ } } } } maxI := 0 for _, yData := range newYDataList { lenEdb := len(yData.XEdbInfoIdList) for i := 0; i < lenEdb; i++ { if yData.XEdbInfoIdList[i] != 0 && !utils.InArrayByInt(yData.NoDataEdbList, yData.XEdbInfoIdList[i]) { if maxI < i { maxI = i } } } } xDataList = xDataList[0:maxI] for yIndex, yData := range newYDataList { if len(yData.XEdbInfoIdList) > maxI+1 { newYDataList[yIndex].XEdbInfoIdList = yData.XEdbInfoIdList[0 : maxI+1] } if len(yData.Value) > maxI+1 { newYDataList[yIndex].Value = yData.Value[0 : maxI+1] } } return } nMap := make(map[int]int) for _, v := range yDataList { findDateTime := v.ConfigDate currMonth := findDateTime.Month() // 当前月份 currYear := findDateTime.Year() // 当前年份 //v.XEdbInfoIdList for edbInfoIndex, edbInfoId := range v.XEdbInfoIdList { // 第一个不处理 if edbInfoIndex == 0 { continue } futureGoodEdbInfo, ok := futureGoodEdbInfoMap[edbInfoId] if !ok { err = errors.New("找不到指标") return } n := (futureGoodEdbInfo.Year-currYear)*12 + int(futureGoodEdbInfo.Month) - int(currMonth) nMap[n] = n } } // 找出所有的N值,并进行正序排列 nList := make([]int, 0) for _, n := range nMap { nList = append(nList, n) } sort.Slice(nList, func(i, j int) bool { return nList[i] < nList[j] }) //prevMonth := 1 for _, n := range nList { xDataList = append(xDataList, chart_info.XData{ Name: fmt.Sprint("M+", n), NameEn: fmt.Sprint("M+", n), }) } for yIndex, yData := range yDataList { newYDataList[yIndex].XEdbInfoIdList = []int{} newYDataList[yIndex].Value = []float64{} tmpNList := nList //当前的主力合约 newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, yData.XEdbInfoIdList[0]) newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[0]) xEdbInfoIdList := yData.XEdbInfoIdList[1:] currDataTime := yData.ConfigDate valIndex := 1 needNum := 0 for _, n := range tmpNList { if len(xEdbInfoIdList) > 0 { edbInfoId := xEdbInfoIdList[0] futureGoodEdbInfo, ok := futureGoodEdbInfoMap[edbInfoId] if !ok { err = errors.New("找不到指标") return } // 当前距离最早的日期相差的N数 divMonth := (futureGoodEdbInfo.Year-currDataTime.Year())*12 + (int(futureGoodEdbInfo.Month) - int(currDataTime.Month())) if divMonth == n { if needNum > 0 { currVal := yData.Value[valIndex] preVal := yData.Value[valIndex-1] hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(needNum + 1))) for tmpNum := 0; tmpNum < needNum; tmpNum++ { newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, 0) // 赋值平均值 tmpVal, _ := decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(int64(tmpNum + 1)))).RoundCeil(4).Float64() newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, tmpVal) } } newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, edbInfoId) newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[valIndex]) valIndex++ needNum = 0 if len(xEdbInfoIdList) > 0 { xEdbInfoIdList = xEdbInfoIdList[1:] } } else { needNum++ } } } } maxI := 0 for _, yData := range newYDataList { lenEdb := len(yData.XEdbInfoIdList) for i := 0; i < lenEdb; i++ { if yData.XEdbInfoIdList[i] != 0 && !utils.InArrayByInt(yData.NoDataEdbList, yData.XEdbInfoIdList[i]) { if maxI < i { maxI = i } } } } xDataList = xDataList[0:maxI] for yIndex, yData := range newYDataList { if len(yData.XEdbInfoIdList) > maxI+1 { newYDataList[yIndex].XEdbInfoIdList = yData.XEdbInfoIdList[0 : maxI+1] } if len(yData.Value) > maxI+1 { newYDataList[yIndex].Value = yData.Value[0 : maxI+1] } } return } // getFutureGoodEdbInfoList 获取适用的指标列表 func getFutureGoodEdbInfoList(latestDateTime time.Time, tmpFutureGoodEdbInfoList []*future_good_edb_info.FutureGoodEdbInfo, barChartInfoDateList []request.BarChartInfoDateReq) (earliestDateTime time.Time, futureGoodEdbInfoList []*future_good_edb_info.FutureGoodEdbInfo, err error) { maxM := 36 //最大36期合约 futureGoodEdbInfoList = make([]*future_good_edb_info.FutureGoodEdbInfo, 0) earliestDateTime = latestDateTime // 数据的最早日期,目的是为了找出最早的合约 for _, barChartInfoDate := range barChartInfoDateList { var findDateTime time.Time switch barChartInfoDate.Type { case 1: //最新值 findDateTime = latestDateTime case 2: //近期几天 findDateTime = latestDateTime.AddDate(0, 0, -barChartInfoDate.Value) case 3: // 固定日期 //寻找固定日期的数据 tmpFindDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local) if tmpErr != nil { err = tmpErr return } findDateTime = tmpFindDateTime default: err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type)) return } if findDateTime.IsZero() { err = errors.New("错误的日期") return } if findDateTime.Before(earliestDateTime) { earliestDateTime = findDateTime } } for _, v := range tmpFutureGoodEdbInfoList { if v.RegionType == `国内` { futureGoodEdbInfoList = append(futureGoodEdbInfoList, v) continue } //海外的连续日期,目前 if v.FutureGoodEdbType == 2 { if int(v.Month) <= maxM { //addMonth := int(earliestDateTime.Month()) + int(v.Month) //v.Year = earliestDateTime.Year() + addMonth/12 //realMonth := addMonth % 12 //if realMonth == 0 { // realMonth = 12 //} //v.Month = uint32(realMonth) futureGoodEdbInfoList = append(futureGoodEdbInfoList, v) } continue } if v.Year < earliestDateTime.Year() { continue } // 小于等于当前年,那么就肯定是ok的 if v.Year <= earliestDateTime.Year() { futureGoodEdbInfoList = append(futureGoodEdbInfoList, v) continue } // 如果(当前年-最新日期的年份) * 12个月 + (当前月-最新日期的月份) 小于总月份 if (v.Year-earliestDateTime.Year())*12+(int(v.Month)-int(earliestDateTime.Month())) <= maxM { futureGoodEdbInfoList = append(futureGoodEdbInfoList, v) continue } } return }