Bladeren bron

Merge branch 'feature/pool255_future_good' of eta_server/eta_index_lib into master

xyxie 3 maanden geleden
bovenliggende
commit
dfc1264879
3 gewijzigde bestanden met toevoegingen van 205 en 152 verwijderingen
  1. 10 40
      controllers/future_good/future_good_edb_info.go
  2. 190 112
      logic/profit_chart_info.go
  3. 5 0
      models/future_good/future_good_edb_data.go

+ 10 - 40
controllers/future_good/future_good_edb_info.go

@@ -8,7 +8,7 @@ import (
 	"eta/eta_index_lib/models/future_good"
 	"eta/eta_index_lib/services"
 	"eta/eta_index_lib/utils"
-	"fmt"
+	"strconv"
 	"time"
 )
 
@@ -206,19 +206,19 @@ func (this *FutureGoodEdbInfoController) RefreshRelation() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	var req future_good.RefreshFutureEdbEdbInfoReq
+	var req future_good.RefreshFutureChartInfoReq
 	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
 	if err != nil {
 		br.Msg = "参数解析异常!"
 		br.ErrMsg = "参数解析失败,Err:" + err.Error()
 		return
 	}
-	if req.FutureGoodEdbInfoId <= 0 {
-		br.Msg = "请输入指标ID!"
-		br.ErrMsg = "请输入指标ID"
+	if req.ChartInfoId <= 0 {
+		br.Msg = "请输入图表ID!"
+		br.ErrMsg = "请输入图表ID"
 		return
 	}
-	cacheKey = utils.CACHE_EDB_DATA_REFRESH + "_futuregood_relation_" + req.FutureGoodEdbCode
+	cacheKey = utils.CACHE_EDB_DATA_REFRESH + "_futuregood_relation_chart" + strconv.Itoa(req.ChartInfoId)
 
 	if utils.Rc.IsExist(cacheKey) {
 		br.Ret = 501
@@ -227,47 +227,17 @@ func (this *FutureGoodEdbInfoController) RefreshRelation() {
 		return
 	}
 
-	utils.Rc.SetNX(cacheKey, 1, 1*time.Minute)
+	utils.Rc.SetNX(cacheKey, 1, 10*time.Minute)
 	defer func() {
 		utils.Rc.Delete(cacheKey)
 	}()
-
-	//获取指标信息
-	futureGoodEdbInfo, err := future_good.GetFutureGoodEdbInfo(req.FutureGoodEdbInfoId)
+	err, errMsg := logic.RefreshByChartId(req.ChartInfoId)
 	if err != nil {
-		if err.Error() != utils.ErrNoRow() {
-			br.Msg = "系统内找不到该指标"
-		} else {
-			br.Msg = "刷新失败"
-			br.ErrMsg = "添加失败,ERR:" + err.Error()
-		}
+		br.Msg = "利润曲线图表刷新失败"
+		br.ErrMsg = "利润曲线图表刷新失败,Err:" + errMsg
 		return
 	}
 
-	// 获取相关图表
-	list, err := models.GetGroupChartEdbMappingListByEdbInfoId(futureGoodEdbInfo.FutureGoodEdbInfoId, 2)
-	if err != nil {
-		br.Msg = "查找相关图表id失败"
-		br.ErrMsg = "添加失败,ERR:" + err.Error()
-		return
-	}
-
-	go func() {
-		errMsgList := make([]string, 0)
-		for _, v := range list {
-			err, errMsg := logic.RefreshByChartId(v.ChartInfoId)
-			if err != nil {
-				errMsgList = append(errMsgList, fmt.Sprint(v.ChartInfoId, "更新失败,"+errMsg))
-			}
-		}
-
-		if len(errMsgList) > 0 {
-			//br.Msg = "部分刷新失败"
-			//br.ErrMsg = "部分刷新失败,Err:" + strings.Join(errMsgList, ";")
-			return
-		}
-	}()
-
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "刷新成功"

+ 190 - 112
logic/profit_chart_info.go

@@ -105,6 +105,8 @@ type ChartInfoReq struct {
 	BaseEdbInfoId           int                     `description:"基础的指标id"`
 	DateList                []ChartInfoDateReq      `description:"日期配置"`
 	ProfitNameEn            string                  `description:"利润英文名称"`
+	EdbInfoIdList           []int                   `description:"现货指标ID列表"`
+	XDataList               []XData                 `description:"横轴配置"`
 }
 
 // RefreshByChartId 根据图表id刷新图表
@@ -136,12 +138,34 @@ func RefreshByChartId(chartInfoId int) (err error, errMsg string) {
 		}
 		return
 	}
+	if len(extraConf.EdbInfoIdList) == 0 {
+		extraConf.EdbInfoIdList = append(extraConf.EdbInfoIdList, extraConf.BaseEdbInfoId)
+	}
 
-	baseEdbInfo, err := models.GetEdbInfoById(extraConf.BaseEdbInfoId)
+	baseEdbInfo := new(models.EdbInfo)
+	// ETA指标
+	edbInfoListTmp, err := models.GetEdbInfoByIdList(extraConf.EdbInfoIdList)
 	if err != nil {
 		errMsg = "获取失败"
 		return
 	}
+	//按照请求顺序排序
+	edbInfoMap := make(map[int]*models.EdbInfo)
+	for _, v := range edbInfoListTmp {
+		edbInfoMap[v.EdbInfoId] = v
+	}
+	edbInfoList := make([]*models.EdbInfo, 0)
+	for _, v := range extraConf.EdbInfoIdList {
+		edbInfoList = append(edbInfoList, edbInfoMap[v])
+	}
+	edbInfoListMap := make(map[int]*models.EdbInfo)
+	for k, v := range edbInfoList {
+		edbInfoList[k].EdbNameSource = v.EdbName
+		edbInfoListMap[v.EdbInfoId] = v
+		if v.EdbInfoId == extraConf.BaseEdbInfoId {
+			baseEdbInfo = v
+		}
+	}
 	// 商品数据库指标
 	futureGoodEdbInfoMap := make(map[int]*future_good.FutureGoodEdbInfo)
 	zlFutureGoodEdbInfoList := make([]*future_good.FutureGoodEdbInfo, 0)
@@ -160,9 +184,7 @@ func RefreshByChartId(chartInfoId int) (err error, errMsg string) {
 		futureGoodEdbInfoMap[v.EdbInfoId] = zlFutureGoodEdbInfo
 		zlFutureGoodEdbInfoList = append(zlFutureGoodEdbInfoList, zlFutureGoodEdbInfo)
 	}
-
-	xDataList, yDataList, err := GetProfitChartEdbData(baseEdbInfo, zlFutureGoodEdbInfoList, extraConf.DateList, extraConf.CalculateFormula, extraConf.FutureGoodEdbInfoIdList)
-
+	xDataList, yDataList, err := GetProfitChartEdbData(baseEdbInfo, edbInfoList, zlFutureGoodEdbInfoList, extraConf.DateList, extraConf.CalculateFormula, extraConf.FutureGoodEdbInfoIdList, extraConf.XDataList)
 	xDataListByte, err := json.Marshal(xDataList)
 	if err != nil {
 		errMsg = "保存失败"
@@ -179,7 +201,7 @@ func RefreshByChartId(chartInfoId int) (err error, errMsg string) {
 	extraUpdateCol := make([]string, 0)
 	chartInfoFutureGoodProfit.XValue = string(xDataListByte)
 	chartInfoFutureGoodProfit.YValue = string(yDataListByte)
-	chartInfoFutureGoodProfit.ProfitName = zlFutureGoodEdbInfoList[0].FutureGoodEdbName + "盘面利润"
+	//chartInfoFutureGoodProfit.ProfitName = zlFutureGoodEdbInfoList[0].FutureGoodEdbName + "盘面利润"
 	chartInfoFutureGoodProfit.ModifyTime = time.Now()
 	extraUpdateCol = []string{"XValue", "YValue", "ProfitName", "ModifyTime"}
 	err = chartInfoFutureGoodProfit.Update(extraUpdateCol)
@@ -188,11 +210,15 @@ func RefreshByChartId(chartInfoId int) (err error, errMsg string) {
 }
 
 // GetProfitChartEdbData 获取利润图表的指标数据
-func GetProfitChartEdbData(baseEdbInfo *models.EdbInfo, zlFutureGoodEdbInfoList []*future_good.FutureGoodEdbInfo, chartInfoDateList []ChartInfoDateReq, formulaStr string, edbInfoFromTagList []models.EdbInfoFromTag) (xDataList []XData, yDataList []YData, err error) {
+func GetProfitChartEdbData(baseEdbInfo *models.EdbInfo, edbInfoList []*models.EdbInfo, zlFutureGoodEdbInfoList []*future_good.FutureGoodEdbInfo, chartInfoDateList []ChartInfoDateReq, formulaStr string, edbInfoFromTagList []models.EdbInfoFromTag, reqXDataList []XData) (xDataList []XData, yDataList []YData, err error) {
+
 	if baseEdbInfo == nil {
 		err = errors.New("ETA指标未选取")
 		return
 	}
+	if len(edbInfoList) == 0 {
+		edbInfoList = append(edbInfoList, baseEdbInfo)
+	}
 	if len(zlFutureGoodEdbInfoList) <= 0 {
 		err = errors.New("商品指标未选取")
 		return
@@ -213,12 +239,17 @@ func GetProfitChartEdbData(baseEdbInfo *models.EdbInfo, zlFutureGoodEdbInfoList
 			futureGoodEdbInfoIdMap[tmpTagEdbIdMap[tag]] = tmpTagEdbIdMap[tag]
 		}
 	}
-
+	// 指标对应的所有数据
+	//edbDataListMap := make(map[int][]*models.EdbDataList)
 	// 普通的指标数据
-	baseDataList := make([]*models.EdbDataList, 0)
-	baseDataList, err = models.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, "", "")
-	if err != nil {
-		return
+	baseDataListMap := make(map[int][]*models.EdbDataList)
+	for _, v := range edbInfoList {
+		baseDataList := make([]*models.EdbDataList, 0)
+		baseDataList, err = models.GetEdbDataList(v.Source, v.SubSource, v.EdbInfoId, "", "")
+		if err != nil {
+			return
+		}
+		baseDataListMap[v.EdbInfoId] = baseDataList
 	}
 
 	latestDate := zlFutureGoodEdbInfoList[0].EndDate
@@ -330,36 +361,47 @@ func GetProfitChartEdbData(baseEdbInfo *models.EdbInfo, zlFutureGoodEdbInfoList
 	sort.Slice(dateList, func(i, j int) bool {
 		return dateList[i] < dateList[j]
 	})
-
-	_, yDataList, err = ProfitChartChartData(baseDataList, futureGoodEdbInfoDateMap, futureGoodDataListMap, chartInfoDateList, baseEdbInfo.EndDate, specialFutureGoodEdbInfoMap, formulaStr, tagEdbIdMap, dateList, maxN)
-	if err != nil {
-		return
+	var reqEdbInfoIds []int
+	for _, v := range edbInfoList {
+		reqEdbInfoIds = append(reqEdbInfoIds, v.EdbInfoId)
+		tmp := XData{
+			Name:   v.EdbName,
+			NameEn: v.EdbNameEn,
+		}
+		xDataList = append(xDataList, tmp)
 	}
+	var edbIdList []int
+	futureGoodNameMap := make(map[int]map[int]string)
+	edbIdList, yDataList, futureGoodNameMap, err = ProfitChartChartData(baseEdbInfo, baseDataListMap, futureGoodEdbInfoDateMap, futureGoodDataListMap, chartInfoDateList, baseEdbInfo.EndDate, specialFutureGoodEdbInfoMap, formulaStr, tagEdbIdMap, dateList, maxN, reqEdbInfoIds)
 
-	tmpXDataList, newYDataList, err := handleProfitResultData(baseEdbInfo, yDataList, earliestDateTime)
+	// todo 最后处理数据
+	tmpXDataList, newYDataList, err := handleProfitResultData(xDataList, futureGoodNameMap, yDataList, earliestDateTime, edbIdList)
 	if err != nil {
 		return
 	}
-	xDataList = []XData{
-		{
-			Name:   "现货利润",
-			NameEn: "Spot Price",
-		},
+	if len(reqXDataList) == 0 {
+		xDataList = tmpXDataList
+	} else {
+		xDataList = reqXDataList
 	}
-	xDataList = append(xDataList, tmpXDataList...)
+
 	yDataList = newYDataList
 
 	return
 }
 
 // ProfitChartChartData 获取数据
-func ProfitChartChartData(baseDataList []*models.EdbDataList, futureGoodEdbInfoMap map[int]map[string]*future_good.FutureGoodEdbInfo, futureGoodEdbDataListMap map[int][]*models.EdbDataList, chartInfoDateList []ChartInfoDateReq, latestDate string, specialFutureGoodEdbInfoMap map[int]map[int]*future_good.FutureGoodEdbInfo, formulaStr string, tagEdbIdMap map[string]int, dateList []string, maxN int) (edbIdList []int, yDataList []YData, err error) {
+func ProfitChartChartData(baseEdbInfo *models.EdbInfo, baseDataListMap map[int][]*models.EdbDataList, futureGoodEdbInfoMap map[int]map[string]*future_good.FutureGoodEdbInfo, futureGoodEdbDataListMap map[int][]*models.EdbDataList, chartInfoDateList []ChartInfoDateReq, latestDate string, specialFutureGoodEdbInfoMap map[int]map[int]*future_good.FutureGoodEdbInfo, formulaStr string, tagEdbIdMap map[string]int, dateList []string, maxN int, reqEdbInfoIds []int) (edbIdList []int, yDataList []YData, futureGoodNameMap map[int]map[int]string, err error) {
 	// 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
 	//earliestDateTime time.Time
 	// ETA指标数据
-	baseEdbDateData := make(map[string]float64)
-	for _, edbData := range baseDataList {
-		baseEdbDateData[edbData.DataTime] = edbData.Value
+	allBaseEdbDateDataMap := make(map[int]map[string]float64)
+	for edbInfoId, baseDataList := range baseDataListMap {
+		baseEdbDateData := make(map[string]float64)
+		for _, edbData := range baseDataList {
+			baseEdbDateData[edbData.DataTime] = edbData.Value
+		}
+		allBaseEdbDateDataMap[edbInfoId] = baseEdbDateData
 	}
 
 	// 商品指标数据
@@ -378,8 +420,8 @@ func ProfitChartChartData(baseDataList []*models.EdbDataList, futureGoodEdbInfoM
 
 	// 将计算公式中的字母转大写
 	formulaStr = strings.ToUpper(formulaStr)
-
-	for _, barChartInfoDate := range chartInfoDateList {
+	futureGoodNameMap = make(map[int]map[int]string)
+	for tmpk, barChartInfoDate := range chartInfoDateList {
 		yDataMap := make(map[int]float64)
 		var maxDate time.Time
 
@@ -406,26 +448,59 @@ func ProfitChartChartData(baseDataList []*models.EdbDataList, futureGoodEdbInfoM
 			return
 		}
 
-		findDataList := make([]float64, 0) // 当前日期的数据值
-		noDataIdList := make([]int, 0)     // 没有数据的指标id
-		xEdbInfoIdList := make([]int, 0)   // 当前数据的指标id列表
+		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, baseDataList, baseEdbDateData, edbDataMap)
+		index := 0
+		var realDateTime time.Time
+		// 现货指标
+		baseEdbDateData, ok := allBaseEdbDateDataMap[baseEdbInfo.EdbInfoId]
+		if !ok {
+			err = fmt.Errorf("指标id: %d 没有数据", baseEdbInfo.EdbInfoId)
+			return
+		}
+		realDateTime, findDataValue, isFind, tmpErr := GetNeedDateData(findDateTime, baseDataListMap[baseEdbInfo.EdbInfoId], baseEdbDateData, edbDataMap)
 		if tmpErr != nil {
 			err = tmpErr
 			return
 		}
-		findDataList = append(findDataList, findDataValue)
-		yDataMap[0] = findDataValue
 		if isFind {
 			maxDate = realDateTime
 		}
+		edbIdList = make([]int, 0) //普通指标ID
+		for _, edbInfoId := range reqEdbInfoIds {
+			if edbInfoId == baseEdbInfo.EdbInfoId {
+				findDataList = append(findDataList, findDataValue)
+				yDataMap[index] = findDataValue
+				xEdbInfoIdList = append(xEdbInfoIdList, edbInfoId)
+				edbIdList = append(edbIdList, edbInfoId)
+				index += 1
+				continue
+			}
+			baseEdbDateDataTmp, ok := allBaseEdbDateDataMap[edbInfoId]
+			if !ok {
+				err = fmt.Errorf("指标id: %d 没有数据", edbInfoId)
+				return
+			}
+			findDataValueTmp, isFindTmp := baseEdbDateDataTmp[realDateTime.Format(utils.FormatDate)]
+			if !isFindTmp {
+				noDataIdList = append(noDataIdList, edbInfoId)
+				noDataIdMap[edbInfoId] = edbInfoId
+			}
+			findDataList = append(findDataList, findDataValueTmp)
+			yDataMap[index] = findDataValueTmp
 
-		xEdbInfoIdList = append(xEdbInfoIdList, 0)
+			xEdbInfoIdList = append(xEdbInfoIdList, edbInfoId)
+			edbIdList = append(edbIdList, edbInfoId)
+			index += 1
+		}
 
 		mList := make([]int, 0) // 间隔月份
 
+		tmpNameMap := make(map[int]string)
 		// 最小开始的n值
 		//minN := (findDateTime.Year()-earliestDateTime.Year())*12 + int(findDateTime.Month()-earliestDateTime.Month())
 		for _, date := range dateList {
@@ -437,8 +512,6 @@ func ProfitChartChartData(baseDataList []*models.EdbDataList, futureGoodEdbInfoM
 			//findDateTime
 
 			// 获取当前日期相对开始日期的期数
-			//tmpN := (currDate.Year()-findDateTime.Year())*12 + int(currDate.Month()-findDateTime.Month())
-			// 用实际日期的月份作为基准,往前推12个月(2024-5-13 16:26:43修改)
 			tmpN := (currDate.Year()-realDateTime.Year())*12 + int(currDate.Month()-realDateTime.Month())
 			if tmpN <= 0 {
 				continue
@@ -486,7 +559,17 @@ func ProfitChartChartData(baseDataList []*models.EdbDataList, futureGoodEdbInfoM
 			//}
 
 			newTagEdbIdMap := make(map[string]int)
+
 			for tag, zlEdbId := range tagEdbIdMap {
+				if tag == "A" {
+					nameTmp := strings.Split(futureGoodEdbInfoMap[zlEdbId][date].FutureGoodEdbName, "(")
+					nameTmpEn := strings.Split(futureGoodEdbInfoMap[zlEdbId][date].FutureGoodEdbNameEn, "(")
+					if len(nameTmp) > 1 && len(nameTmpEn) > 1 {
+						nameTmp[1] = strings.Trim(nameTmp[1], ")")
+						nameTmpEn[1] = strings.Trim(nameTmpEn[1], ")")
+						tmpNameMap[tmpN+1] = nameTmp[1] + "-" + nameTmpEn[1]
+					}
+				}
 				newTagEdbIdMap[tag] = zlAndChildEdbId[zlEdbId]
 			}
 			//, formulaStr string, tagEdbIdMap map[string]int
@@ -494,52 +577,19 @@ func ProfitChartChartData(baseDataList []*models.EdbDataList, futureGoodEdbInfoM
 			//计算公式异常,那么就移除该指标
 			if formulaFormStr == `` {
 				//removeDateList = append(removeDateList, sk)
-				//fmt.Println("异常了")
+				fmt.Println("异常了")
 				continue
 			}
 
-			//expression := formula.NewExpression(formulaFormStr)
-			//calResult, evaluateErr := expression.Evaluate()
-			//if evaluateErr != nil {
-			//	// 分母为0的报错
-			//	if strings.Contains(evaluateErr.Error(), "divide by zero") {
-			//		//removeDateList = append(removeDateList, sk)
-			//		continue
-			//	}
-			//	err = errors.New("计算失败:Err:" + evaluateErr.Error() + ";formulaStr:" + formulaFormStr)
-			//	fmt.Println(err)
-			//	continue
-			//}
-			//// 如果计算结果是NAN,那么就退出当前循环
-			//if calResult.IsNan() {
-			//	continue
-			//}
-			//calVal, tmpErr := calResult.Float64()
-			//if tmpErr != nil {
-			//	err = errors.New("计算失败:获取计算值失败 Err:" + tmpErr.Error() + ";formulaStr:" + formulaFormStr)
-			//	fmt.Println(err)
-			//	continue
-			//}
-			calVal, err := engine.ParseAndExec(formulaFormStr)
+			calVal, e := engine.ParseAndExec(formulaFormStr)
 			//calVal, err := calResult.Float64()
-			if err != nil {
-				// 分母为0的报错,忽略该循环
-				if utils.IsDivideZero(err) {
-					//removeDateList = append(removeDateList, sk)
-					continue
-				}
-				err = errors.New("计算失败:获取计算值失败 Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
+			if e != nil {
+				err = errors.New("计算失败:获取计算值失败 Err:" + e.Error() + ";formulaStr:" + formulaFormStr)
 				fmt.Println(err)
-				return nil, nil, err
+				return
 			}
-			//nanCheck := fmt.Sprintf("%0.f", calVal)
 			//yDataMap[n] = calVal
 			//xEdbInfoIdList = append(xEdbInfoIdList, n)
-			nanCheck := fmt.Sprintf("%0.f", calVal)
-			// 分母为0.0的报错
-			if nanCheck == "NaN" || nanCheck == "+Inf" || nanCheck == "-Inf" {
-				continue
-			}
 			calVal, _ = decimal.NewFromFloat(calVal).Round(4).Float64()
 			yDataMap[tmpN] = calVal
 			xEdbInfoIdList = append(xEdbInfoIdList, tmpN)
@@ -565,6 +615,33 @@ func ProfitChartChartData(baseDataList []*models.EdbDataList, futureGoodEdbInfoM
 			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()
+					}
+				}
+			}
+		}
+		futureGoodNameMap[tmpk] = tmpNameMap
 		yDataList = append(yDataList, YData{
 			Date:           yDate,
 			ConfigDate:     realDateTime,
@@ -603,8 +680,6 @@ func getProfitFutureGoodEdbInfoList(earliestDateTime time.Time, zlFutureGoodEdbI
 		lenFutureGoodEdbInfoList := len(futureGoodEdbInfoList)
 		//futureGoodEdbInfoList
 		//if isAllChina {
-		//	// 如果全是国内指标,那么只需要拼上多出的几期合约即可
-		//	maxN = lenFutureGoodEdbInfoList + monthNum
 		//}
 		// 如果全是国内指标,那么只需要拼上多出的几期合约即可
 		maxN = lenFutureGoodEdbInfoList + monthNum
@@ -612,9 +687,6 @@ func getProfitFutureGoodEdbInfoList(earliestDateTime time.Time, zlFutureGoodEdbI
 		for i := 1; i < maxN; i++ {
 			k := i % lenFutureGoodEdbInfoList
 			futureGoodEdbInfoDateMap[earliestDateTime.AddDate(0, i, 0).Format(utils.FormatYearMonthDate)] = futureGoodEdbInfoList[k]
-			if i > newMaxN {
-				newMaxN = i
-			}
 		}
 
 		//需求池604,只要是国内合约,最大必须是12期
@@ -626,7 +698,7 @@ func getProfitFutureGoodEdbInfoList(earliestDateTime time.Time, zlFutureGoodEdbI
 	for _, v := range tmpFutureGoodEdbInfoList {
 		//海外的连续日期,目前
 		if v.FutureGoodEdbType == 2 {
-			if v.Month <= newMaxN {
+			if v.Month <= maxN {
 				futureGoodEdbInfoDateMap[earliestDateTime.AddDate(0, v.Month, 0).Format(utils.FormatYearMonthDate)] = v
 				if v.Month > newMaxN {
 					newMaxN = v.Month
@@ -647,7 +719,7 @@ func getProfitFutureGoodEdbInfoList(earliestDateTime time.Time, zlFutureGoodEdbI
 		subMonth := v.Month - int(earliestDateTime.Month())
 		// 如果(当前年-最新日期的年份) * 12个月 + (当前月-最新日期的月份) 小于总月份
 		tmpN := subYear*12 + subMonth
-		if tmpN < newMaxN {
+		if tmpN < maxN {
 			tmpDateTime := time.Date(v.Year, time.Month(v.Month), 0, 0, 0, 0, 0, time.Local)
 			futureGoodEdbInfoDateMap[tmpDateTime.Format(utils.FormatYearMonthDate)] = v
 			if tmpN > newMaxN {
@@ -661,29 +733,37 @@ func getProfitFutureGoodEdbInfoList(earliestDateTime time.Time, zlFutureGoodEdbI
 }
 
 // handleProfitResultData 处理成最终的结果数据
-func handleProfitResultData(baseEdbInfo *models.EdbInfo, yDataList []YData, earliestDateTime time.Time) (xDataList []XData, newYDataList []YData, err error) {
-	xDataList = make([]XData, 0)
+func handleProfitResultData(xDataListInit []XData, futureNameMap map[int]map[int]string, yDataList []YData, earliestDateTime time.Time, allEdbInfoIds []int) (xDataList []XData, newYDataList []YData, err error) {
 	newYDataList = yDataList
+	xDataList = xDataListInit
 
 	nMap := make(map[int]int)
-
+	nList := make([]int, 0)
+	nListEdbMap := make(map[int]struct{})
 	for _, v := range yDataList {
 		for _, n := range v.XEdbInfoIdList {
-			nMap[n] = n
+			if utils.InArrayByInt(allEdbInfoIds, n) {
+				if _, ok := nListEdbMap[n]; !ok {
+					nList = append(nList, n)
+					nListEdbMap[n] = struct{}{}
+				}
+			} else {
+				nMap[n] = n
+			}
 		}
 	}
 
 	// 找出所有的N值,并进行正序排列
-	nList := make([]int, 0)
+	nListTmp := make([]int, 0)
 	for _, n := range nMap {
-		nList = append(nList, n)
+		nListTmp = append(nListTmp, n)
 	}
-	sort.Slice(nList, func(i, j int) bool {
-		return nList[i] < nList[j]
+	sort.Slice(nListTmp, func(i, j int) bool {
+		return nListTmp[i] < nListTmp[j]
 	})
-
+	nList = append(nList, nListTmp...)
 	for _, n := range nList {
-		if n == 0 {
+		if utils.InArrayByInt(allEdbInfoIds, n) {
 			continue
 		}
 		xDataList = append(xDataList, XData{
@@ -704,7 +784,7 @@ func handleProfitResultData(baseEdbInfo *models.EdbInfo, yDataList []YData, earl
 			if len(xEdbInfoIdList) > 0 {
 				currN := xEdbInfoIdList[0]
 				// 当前距离最早的日期相差的N数
-				if n == currN {
+				if n == currN { // todo 改成所有的基础现货指标
 					if needNum > 0 {
 						currVal := yData.Value[valIndex]
 						preVal := yData.Value[valIndex-1]
@@ -714,12 +794,16 @@ func handleProfitResultData(baseEdbInfo *models.EdbInfo, yDataList []YData, earl
 							newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, 0)
 
 							// 赋值平均值
-							tmpVal, _ := decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(int64(tmpNum + 1)))).Round(4).Float64()
+							tmpVal, _ := decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(int64(tmpNum + 1)))).RoundCeil(4).Float64()
 							newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, tmpVal)
 						}
 					}
+					if utils.InArrayByInt(allEdbInfoIds, currN) {
+						newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, currN)
+					} else {
+						newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, currN+1)
+					}
 
-					newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, currN+1)
 					newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[valIndex])
 					valIndex++
 					needNum = 0
@@ -746,7 +830,7 @@ func handleProfitResultData(baseEdbInfo *models.EdbInfo, yDataList []YData, earl
 	}
 
 	earliestDateTime = time.Date(earliestDateTime.Year(), earliestDateTime.Month(), 1, 0, 0, 0, 0, time.Local)
-	xDataList = xDataList[0:maxI]
+	xDataList = xDataList[0 : maxI+1]
 	for yIndex, yData := range newYDataList {
 		if len(yData.XEdbInfoIdList) > maxI+1 {
 			newYDataList[yIndex].XEdbInfoIdList = yData.XEdbInfoIdList[0 : maxI+1]
@@ -755,30 +839,23 @@ func handleProfitResultData(baseEdbInfo *models.EdbInfo, yDataList []YData, earl
 			newYDataList[yIndex].Value = yData.Value[0 : maxI+1]
 		}
 
-		currDate, _ := time.ParseInLocation(utils.FormatDate, yData.Date, time.Local)
-
 		nameList := make([]string, 0)
 		enNameList := make([]string, 0)
-		for _, n := range newYDataList[yIndex].XEdbInfoIdList {
-			if n == 1 { // 现货价不处理
-				nameList = append(nameList, baseEdbInfo.EdbName)
-				enNameList = append(enNameList, baseEdbInfo.EdbNameEn)
+		for k1, n := range newYDataList[yIndex].XEdbInfoIdList {
+			if utils.InArrayByInt(allEdbInfoIds, n) { // 现货价不处理
+				tmpItem := xDataListInit[k1]
+				nameList = append(nameList, tmpItem.Name)
+				enNameList = append(enNameList, tmpItem.NameEn)
 				continue
 			}
 			if n <= 0 {
 				nameList = append(nameList, `无合约`)
 				enNameList = append(enNameList, `no contract`)
 			} else {
-				var date string
-
-				currDateTime := currDate.AddDate(0, n-1, 0)
-				month := int(currDateTime.Month())
-				date = fmt.Sprintf("%d%d", currDateTime.Year(), month)
-				if month < 10 {
-					date = fmt.Sprintf("%d0%d", currDateTime.Year(), month)
-				}
-				nameList = append(nameList, date)
-				enNameList = append(enNameList, date)
+				nameTmp := futureNameMap[yIndex][n]
+				nameTmpSlice := strings.Split(nameTmp, "-")
+				nameList = append(nameList, nameTmpSlice[0])
+				enNameList = append(enNameList, nameTmpSlice[1])
 			}
 		}
 		newYDataList[yIndex].NameList = nameList
@@ -827,6 +904,7 @@ func ReplaceFormula(tagEdbIdMap map[string]int, valArr map[int]float64, formulaS
 	for k, v := range funMap {
 		formulaStr = strings.Replace(formulaStr, v, k, -1)
 	}
+	fmt.Println(formulaStr)
 	if replaceCount == len(tagEdbIdMap) {
 		return formulaStr
 	} else {

+ 5 - 0
models/future_good/future_good_edb_data.go

@@ -134,6 +134,11 @@ type RefreshFutureEdbEdbInfoReq struct {
 	StartDate           string `description:"开始日期"`
 }
 
+// RefreshFutureChartInfoReq 刷新商品指标请求
+type RefreshFutureChartInfoReq struct {
+	ChartInfoId int `description:"图表ID"`
+}
+
 // RefreshFutureGoodEdbDataFromThs 刷新wind期货指标数据
 func RefreshFutureGoodEdbDataFromThs(futureGoodEdbInfoId int, edbCode, startDate string, item FutureGoodDataFromThs) (err error) {
 	o := orm.NewOrm()