package future_good import ( "errors" "eta/eta_api/models/data_manage" "eta/eta_api/models/data_manage/future_good" "eta/eta_api/models/data_manage/future_good/request" "eta/eta_api/services/data" "eta/eta_api/utils" "fmt" "github.com/shopspring/decimal" "github.com/yidane/formula" "sort" "strconv" "strings" "time" ) // GetProfitChartEdbData 获取利润图表的指标数据 func GetProfitChartEdbData(baseEdbInfo *data_manage.EdbInfo, edbInfoList []*data_manage.EdbInfo, zlFutureGoodEdbInfoList []*future_good.FutureGoodEdbInfo, chartInfoDateList []request.ChartInfoDateReq, formulaStr string, edbInfoFromTagList []data_manage.EdbInfoFromTag, reqXDataList []data_manage.XData) (barConfigEdbInfoIdList []data_manage.BarChartInfoEdbItemReq, edbList []*data_manage.ChartEdbInfoMapping, xEdbIdValue []int, xDataList []data_manage.XData, yDataList []data_manage.YData, err error) { edbList = make([]*data_manage.ChartEdbInfoMapping, 0) if baseEdbInfo == nil { err = errors.New("ETA指标未选取") return } if len(edbInfoList) == 0 { edbInfoList = append(edbInfoList, baseEdbInfo) } if len(zlFutureGoodEdbInfoList) <= 0 { err = errors.New("商品指标未选取") return } // 标签与期货商品指标的关联关系 tagEdbIdMap := make(map[string]int) // 有效的期货商品指标 futureGoodEdbInfoIdMap := make(map[int]int) { tmpTagEdbIdMap := make(map[string]int) for _, v := range edbInfoFromTagList { tmpTagEdbIdMap[v.FromTag] = v.EdbInfoId } formulaMap := CheckFormula(formulaStr) for _, tag := range formulaMap { tagEdbIdMap[tag] = tmpTagEdbIdMap[tag] futureGoodEdbInfoIdMap[tmpTagEdbIdMap[tag]] = tmpTagEdbIdMap[tag] } } // 指标对应的所有数据 //edbDataListMap := make(map[int][]*data_manage.EdbDataList) item := new(data_manage.ChartEdbInfoMapping) item.FrequencyEn = data.GetFrequencyEn(baseEdbInfo.Frequency) if baseEdbInfo.Unit == `无` { item.Unit = `` } // 普通的指标数据 baseDataListMap := make(map[int][]*data_manage.EdbDataList) for _, v := range edbInfoList { baseDataList := make([]*data_manage.EdbDataList, 0) baseDataList, err = data_manage.GetEdbDataList(v.Source, v.SubSource, v.EdbInfoId, "", "") if err != nil { return } baseDataListMap[v.EdbInfoId] = baseDataList } latestDate := zlFutureGoodEdbInfoList[0].EndDate latestDateTime, _ := time.ParseInLocation(utils.FormatDate, latestDate, time.Local) earliestDateTime := latestDateTime // 数据的最早日期,目的是为了找出最早的合约 for _, barChartInfoDate := range chartInfoDateList { 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 } } monthNum := (latestDateTime.Year()-earliestDateTime.Year())*12 + int(latestDateTime.Month()-earliestDateTime.Month()) // 存储主力合约下的所有月份合约 futureGoodEdbInfoDateMap := make(map[int]map[string]*future_good.FutureGoodEdbInfo) futureGoodDataListMap := make(map[int][]*data_manage.EdbDataList, 0) // 特殊的商品期货合约(只有M+N的合约,没有固定日期的合约) specialFutureGoodEdbInfoMap := make(map[int]map[int]*future_good.FutureGoodEdbInfo, 0) isAllChina := true // 是否都是国内的期货合约 for _, v := range zlFutureGoodEdbInfoList { if v.RegionType != "国内" { isAllChina = false break } } nMap := make(map[string]string) var maxN int // 最大N值 for _, v := range zlFutureGoodEdbInfoList { // 如果不是有效的商品期货指标,那么就过滤掉,不做数据查询处理,避免没必要的请求 if _, ok := futureGoodEdbInfoIdMap[v.FutureGoodEdbInfoId]; !ok { continue } // 获取期货指标以及期货数据 tmpFutureGoodEdbInfoList, tmpErr := future_good.GetChildFutureGoodEdbInfoListByParentId(v.FutureGoodEdbInfoId) if tmpErr != nil { err = tmpErr return } childFutureGoodEdbInfoMap, tmpMaxN, tmpErr := getProfitFutureGoodEdbInfoList(earliestDateTime, v, tmpFutureGoodEdbInfoList, isAllChina, monthNum) if tmpErr != nil { err = tmpErr return } if maxN < tmpMaxN { maxN = tmpMaxN } futureGoodEdbInfoDateMap[v.FutureGoodEdbInfoId] = childFutureGoodEdbInfoMap if v.FutureGoodEdbType == 2 { specialFutureGoodEdbInfoMap[v.FutureGoodEdbInfoId] = make(map[int]*future_good.FutureGoodEdbInfo) } // 获取数据 for date, childFutureGoodEdbInfo := range childFutureGoodEdbInfoMap { nMap[date] = date dataList := make([]*data_manage.EdbDataList, 0) tmpDataList, tmpErr := future_good.GetFutureGoodEdbDataListByDate(childFutureGoodEdbInfo.FutureGoodEdbInfoId, "", "") if tmpErr != nil { return } for _, tmpData := range tmpDataList { dataList = append(dataList, &data_manage.EdbDataList{ EdbDataId: tmpData.FutureGoodEdbDataId, EdbInfoId: tmpData.FutureGoodEdbInfoId, DataTime: tmpData.DataTime.Format(utils.FormatDate), DataTimestamp: tmpData.DataTimestamp, Value: tmpData.Close, }) } futureGoodDataListMap[childFutureGoodEdbInfo.FutureGoodEdbInfoId] = dataList if childFutureGoodEdbInfo.FutureGoodEdbType == 2 { specialFutureGoodEdbInfoMap[v.FutureGoodEdbInfoId][childFutureGoodEdbInfo.Month] = childFutureGoodEdbInfo } } } // 找出所有的N值,并进行正序排列 dateList := make([]string, 0) for _, n := range nMap { dateList = append(dateList, n) } sort.Slice(dateList, func(i, j int) bool { return dateList[i] < dateList[j] }) var reqEdbInfoIds []int for _, v := range edbInfoList { reqEdbInfoIds = append(reqEdbInfoIds, v.EdbInfoId) tmp := data_manage.XData{ Name: v.EdbName, NameEn: v.EdbNameEn, } xDataList = append(xDataList, tmp) } var edbIdList []int edbIdList, yDataList, err = ProfitChartChartData(baseEdbInfo, baseDataListMap, futureGoodEdbInfoDateMap, futureGoodDataListMap, chartInfoDateList, baseEdbInfo.EndDate, specialFutureGoodEdbInfoMap, formulaStr, tagEdbIdMap, dateList, maxN, reqEdbInfoIds) // todo 最后处理数据 tmpXDataList, newYDataList, err := handleProfitResultData(xDataList, baseEdbInfo, yDataList, earliestDateTime, edbIdList) if err != nil { return } if len(reqXDataList) == 0 { xDataList = tmpXDataList } else { xDataList = reqXDataList } yDataList = newYDataList return } // ProfitChartChartData 获取数据 func ProfitChartChartData(baseEdbInfo *data_manage.EdbInfo, baseDataListMap map[int][]*data_manage.EdbDataList, futureGoodEdbInfoMap map[int]map[string]*future_good.FutureGoodEdbInfo, futureGoodEdbDataListMap map[int][]*data_manage.EdbDataList, chartInfoDateList []request.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 []data_manage.YData, err error) { // 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3}) //earliestDateTime time.Time // ETA指标数据 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 } // 商品指标数据 edbDataMap := make(map[int]map[string]float64) for edbInfoId, edbDataList := range futureGoodEdbDataListMap { edbDateData := make(map[string]float64) for _, edbData := range edbDataList { edbDateData[edbData.DataTime] = edbData.Value } edbDataMap[edbInfoId] = edbDateData } latestDateTime, _ := time.ParseInLocation(utils.FormatDate, latestDate, time.Local) yDataList = make([]data_manage.YData, 0) //y轴的数据列表 // 将计算公式中的字母转大写 formulaStr = strings.ToUpper(formulaStr) for _, barChartInfoDate := range chartInfoDateList { 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列表 // 现货指标 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 } 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, edbInfoId) edbIdList = append(edbIdList, edbInfoId) index += 1 } mList := make([]int, 0) // 间隔月份 // 最小开始的n值 //minN := (findDateTime.Year()-earliestDateTime.Year())*12 + int(findDateTime.Month()-earliestDateTime.Month()) for _, date := range dateList { currDate, _ := time.ParseInLocation(utils.FormatYearMonthDate, date, time.Local) // 如果当前的n值小于最小开始的n值,那么就不处理 //if n < minN { // continue //} //findDateTime // 获取当前日期相对开始日期的期数 tmpN := (currDate.Year()-realDateTime.Year())*12 + int(currDate.Month()-realDateTime.Month()) if tmpN <= 0 { continue } // 如果期数大于最大期数,那么就退出当前匹配 if tmpN >= maxN { break } zlAndChildEdbId := make(map[int]int) childFutureGoodEdbInfoIdList := make([]int, 0) for zlFutureGoodEdbInfoId, futureGoodEdbInfoList := range futureGoodEdbInfoMap { // 判断是否特殊合约 if childFutureGoodEdbInfoIdMap, ok := specialFutureGoodEdbInfoMap[zlFutureGoodEdbInfoId]; ok { if childFutureGoodEdbInfo, ok2 := childFutureGoodEdbInfoIdMap[tmpN]; ok2 { childFutureGoodEdbInfoIdList = append(childFutureGoodEdbInfoIdList, childFutureGoodEdbInfo.FutureGoodEdbInfoId) zlAndChildEdbId[zlFutureGoodEdbInfoId] = childFutureGoodEdbInfo.FutureGoodEdbInfoId } } else { if childFutureGoodEdbInfo, ok2 := futureGoodEdbInfoList[date]; ok2 { childFutureGoodEdbInfoIdList = append(childFutureGoodEdbInfoIdList, childFutureGoodEdbInfo.FutureGoodEdbInfoId) zlAndChildEdbId[zlFutureGoodEdbInfoId] = childFutureGoodEdbInfo.FutureGoodEdbInfoId } } } // 合约不全,不参与计算 //if len(childFutureGoodEdbInfoIdList) != lenZlFutureGoodEdbInfo { // continue //} calculateMap := make(map[int]float64) for _, childFutureGoodEdbInfoId := range childFutureGoodEdbInfoIdList { tmpFindDataValue, tmpIsFind := edbDataMap[childFutureGoodEdbInfoId][realDateTime.Format(utils.FormatDate)] if tmpIsFind && tmpFindDataValue != 0 { calculateMap[childFutureGoodEdbInfoId] = tmpFindDataValue } } // 合约的数据不全,不参与计算 //if len(calculateMap) != lenZlFutureGoodEdbInfo { // continue //} newTagEdbIdMap := make(map[string]int) for tag, zlEdbId := range tagEdbIdMap { newTagEdbIdMap[tag] = zlAndChildEdbId[zlEdbId] } //, formulaStr string, tagEdbIdMap map[string]int formulaFormStr := ReplaceFormula(newTagEdbIdMap, calculateMap, formulaStr) //计算公式异常,那么就移除该指标 if formulaFormStr == `` { //removeDateList = append(removeDateList, sk) 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 } //yDataMap[n] = calVal //xEdbInfoIdList = append(xEdbInfoIdList, n) calVal, _ = decimal.NewFromFloat(calVal).Round(4).Float64() yDataMap[tmpN] = calVal xEdbInfoIdList = append(xEdbInfoIdList, tmpN) findDataList = append(findDataList, calVal) } 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, data_manage.YData{ Date: yDate, ConfigDate: realDateTime, Value: findDataList, NoDataEdbList: noDataIdList, XEdbInfoIdList: xEdbInfoIdList, Color: barChartInfoDate.Color, Name: yName, NameEn: yNameEn, EdbValMap: yDataMap, M: mList, }) } return } // getFutureGoodEdbInfoList 获取适用的指标列表 func getProfitFutureGoodEdbInfoList(earliestDateTime time.Time, zlFutureGoodEdbInfo *future_good.FutureGoodEdbInfo, tmpFutureGoodEdbInfoList []*future_good.FutureGoodEdbInfo, isAllChina bool, monthNum int) (futureGoodEdbInfoDateMap map[string]*future_good.FutureGoodEdbInfo, newMaxN int, err error) { maxN := 36 //最大36期合约 futureGoodEdbInfoList := make([]*future_good.FutureGoodEdbInfo, 0) futureGoodEdbInfoDateMap = make(map[string]*future_good.FutureGoodEdbInfo) earliestDateTime = time.Date(earliestDateTime.Year(), earliestDateTime.Month(), 1, 0, 0, 0, 0, time.Local) if zlFutureGoodEdbInfo.RegionType == "国内" { startMonth := int(earliestDateTime.Month()) if startMonth == 1 { futureGoodEdbInfoList = tmpFutureGoodEdbInfoList } else { // 因为是下标,所以对应想下标是需要-1的 index := startMonth - 1 futureGoodEdbInfoList = tmpFutureGoodEdbInfoList[index:] futureGoodEdbInfoList = append(futureGoodEdbInfoList, tmpFutureGoodEdbInfoList[:index]...) } lenFutureGoodEdbInfoList := len(futureGoodEdbInfoList) //futureGoodEdbInfoList //if isAllChina { //} // 如果全是国内指标,那么只需要拼上多出的几期合约即可 maxN = lenFutureGoodEdbInfoList + monthNum for i := 1; i < maxN; i++ { k := i % lenFutureGoodEdbInfoList futureGoodEdbInfoDateMap[earliestDateTime.AddDate(0, i, 0).Format(utils.FormatYearMonthDate)] = futureGoodEdbInfoList[k] } //需求池604,只要是国内合约,最大必须是12期 newMaxN = 12 return } for _, v := range tmpFutureGoodEdbInfoList { //海外的连续日期,目前 if v.FutureGoodEdbType == 2 { if v.Month <= maxN { futureGoodEdbInfoDateMap[earliestDateTime.AddDate(0, v.Month, 0).Format(utils.FormatYearMonthDate)] = v if v.Month > newMaxN { newMaxN = v.Month } } continue } if v.Year < earliestDateTime.Year() { continue } // 小于等于当前年,那么就肯定是ok的 if v.Year == earliestDateTime.Year() && v.Month <= int(earliestDateTime.Month()) { continue } subYear := v.Year - earliestDateTime.Year() subMonth := v.Month - int(earliestDateTime.Month()) // 如果(当前年-最新日期的年份) * 12个月 + (当前月-最新日期的月份) 小于总月份 tmpN := subYear*12 + subMonth 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 { newMaxN = tmpN } continue } } return } // handleProfitResultData 处理成最终的结果数据 func handleProfitResultData(xDataListInit []data_manage.XData, baseEdbInfo *data_manage.EdbInfo, yDataList []data_manage.YData, earliestDateTime time.Time, allEdbInfoIds []int) (xDataList []data_manage.XData, newYDataList []data_manage.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 { if utils.InArrayByInt(allEdbInfoIds, n) { if _, ok := nListEdbMap[n]; !ok { nList = append(nList, n) nListEdbMap[n] = struct{}{} } } else { nMap[n] = n } } } // 找出所有的N值,并进行正序排列 nListTmp := make([]int, 0) for _, n := range nMap { nListTmp = append(nListTmp, n) } sort.Slice(nListTmp, func(i, j int) bool { return nListTmp[i] < nListTmp[j] }) nList = append(nList, nListTmp...) for _, n := range nList { if utils.InArrayByInt(allEdbInfoIds, n) { continue } xDataList = append(xDataList, data_manage.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 xEdbInfoIdList := yData.XEdbInfoIdList valIndex := 0 needNum := 0 for _, n := range tmpNList { if len(xEdbInfoIdList) > 0 { currN := xEdbInfoIdList[0] // 当前距离最早的日期相差的N数 if n == currN { // todo 改成所有的基础现货指标 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) } } 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].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 } } } } earliestDateTime = time.Date(earliestDateTime.Year(), earliestDateTime.Month(), 1, 0, 0, 0, 0, time.Local) xDataList = xDataList[0 : maxI+1] 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] } currDate, _ := time.ParseInLocation(utils.FormatDate, yData.Date, time.Local) nameList := make([]string, 0) enNameList := make([]string, 0) 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) } } newYDataList[yIndex].NameList = nameList newYDataList[yIndex].EnNameList = enNameList } return } func CheckFormula(formula string) map[string]string { mathFormula := []string{"MAX", "MIN", "ABS", "ACOS", "ASIN", "CEIL", "MOD", "POW", "ROUND", "SIGN", "SIN", "TAN", "LOG10", "LOG2", "LOG", "LN"} str := strings.ToUpper(formula) for _, v := range mathFormula { str = strings.Replace(str, v, "", -1) } str = strings.Replace(str, "(", "", -1) str = strings.Replace(str, ")", "", -1) byteMap := make(map[string]string) for i := 0; i < len(str); i++ { byteInt := str[i] if byteInt >= 65 && byteInt <= 90 { byteStr := string(byteInt) if _, ok := byteMap[byteStr]; !ok { byteMap[byteStr] = byteStr } } } return byteMap } func ReplaceFormula(tagEdbIdMap map[string]int, valArr map[int]float64, formulaStr string) string { funMap := GetFormulaMap() for k, v := range funMap { formulaStr = strings.Replace(formulaStr, k, v, -1) } replaceCount := 0 for tag, edbInfoId := range tagEdbIdMap { if val, valOk := valArr[edbInfoId]; valOk { //值存在 dvStr := fmt.Sprintf("%v", val) formulaStr = strings.Replace(formulaStr, tag, dvStr, -1) replaceCount++ } } for k, v := range funMap { formulaStr = strings.Replace(formulaStr, v, k, -1) } fmt.Println(formulaStr) if replaceCount == len(tagEdbIdMap) { return formulaStr } else { return "" } } func GetFormulaMap() map[string]string { funMap := make(map[string]string) funMap["MAX"] = "[@@]" funMap["MIN"] = "[@!]" funMap["ABS"] = "[@#]" funMap["CEIL"] = "[@$]" funMap["COS"] = "[@%]" funMap["FLOOR"] = "[@^]" funMap["MOD"] = "[@&]" funMap["POW"] = "[@*]" funMap["ROUND"] = "[@(]" return funMap }