Browse Source

Merge branch 'master' into feature/eta1.2.2_edb_source

# Conflicts:
#	models/edb_info.go
xyxie 1 year ago
parent
commit
1ca63333b9

+ 1 - 20
controllers/base_auth.go

@@ -3,7 +3,6 @@ package controllers
 import (
 	"encoding/json"
 	"fmt"
-	"github.com/sirupsen/logrus"
 	"net/http"
 	"net/url"
 
@@ -133,26 +132,8 @@ func (c *BaseAuthController) JSON(data interface{}, hasIndent bool, coding bool)
 	if authorization == "" {
 		authorization = c.Ctx.Input.Header("Authorization")
 	}
-	var reqData interface{}
-	err = json.Unmarshal([]byte(requestBody), &reqData)
-	if err != nil {
-		utils.ApiLog.WithFields(logrus.Fields{
-			"uri":           c.Ctx.Input.URI(),
-			"authorization": authorization,
-			"requestBody":   requestBody,
-			"responseBody":  data,
-			"ip":            ip,
-		}).Info("请求详情")
-	} else {
-		utils.ApiLog.WithFields(logrus.Fields{
-			"uri":           c.Ctx.Input.URI(),
-			"authorization": authorization,
-			"requestBody":   reqData,
-			"responseBody":  data,
-			"ip":            ip,
-		}).Info("请求详情")
-	}
 
+	utils.ApiLog.Info("uri:%s, authorization:%s, requestBody:%s, responseBody:%s, ip:%s", c.Ctx.Input.URI(), authorization, requestBody, content, ip)
 	if coding {
 		content = []byte(utils.StringsToJSON(string(content)))
 	}

+ 103 - 4
controllers/base_from_calculate.go

@@ -2,6 +2,7 @@ package controllers
 
 import (
 	"encoding/json"
+	"errors"
 	"eta/eta_index_lib/logic"
 	"eta/eta_index_lib/models"
 	"eta/eta_index_lib/services"
@@ -1214,10 +1215,6 @@ func (this *CalculateController) BatchEdit() {
 		sourName = utils.DATA_SOURCE_NAME_CALCULATE_JP
 		err = models.EditCalculateJp(edbInfo, &req, fromEdbInfo)
 	case utils.DATA_SOURCE_CALCULATE_NH:
-		if !models.CheckFrequency(fromEdbInfo.Frequency, req.Frequency) {
-			br.Msg = "频度异常,不允许低频降频到高频"
-			return
-		}
 		sourName = utils.DATA_SOURCE_NAME_CALCULATE_NH
 		err = models.EditCalculateNh(edbInfo, &req, fromEdbInfo)
 	case utils.DATA_SOURCE_CALCULATE_KSZS:
@@ -2060,3 +2057,105 @@ func (this *CalculateController) ResetCustomAnalysisData() {
 	br.Data = resp
 	br.IsAddLog = true
 }
+
+// Calculate
+// @Title 基础数据计算
+// @Description 拟合残差计算相关性接口
+// @Param request body models.EdbInfoCalculateBatchSaveReq true "type json string"
+// @Success Ret=200 返回指标id
+// @router /base [post]
+func (this *CalculateController) Calculate() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	var req models.BaseCalculateBySearchData
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	dateDataMap := make(map[time.Time]float64)
+	var errMsg string
+
+	dataList, err := models.EdbInfoSearchDataToData(req.DataList)
+	if err != nil {
+		br.Msg = "计算失败,数据异常!"
+		br.ErrMsg = "计算失败,数据异常,Err:" + err.Error()
+		return
+	}
+
+	baseCalculate := models.BaseCalculate{
+		DataList:      dataList,
+		Frequency:     req.Frequency,
+		Formula:       req.Formula,
+		Calendar:      req.Calendar,
+		MoveType:      req.MoveType,
+		MoveFrequency: req.MoveFrequency,
+		FromFrequency: req.FromFrequency,
+		Source:        req.Source,
+	}
+
+	//1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值
+	switch baseCalculate.Source {
+	case 1:
+		dateDataMap, err, errMsg = baseCalculate.Ljzzy()
+	case 2:
+		dateDataMap, err, errMsg = baseCalculate.Ljzzj()
+	case 3:
+		dateDataMap, err, errMsg = baseCalculate.Tbz()
+	case 4:
+		dateDataMap, err, errMsg = baseCalculate.Tcz()
+	case 5:
+		dateDataMap, err, errMsg = baseCalculate.Nszydpjjs()
+	case 6:
+		dateDataMap, err, errMsg = baseCalculate.Hbz()
+	case 7:
+		dateDataMap, err, errMsg = baseCalculate.Hcz()
+	case 8:
+		dateDataMap, err, errMsg = baseCalculate.UpFrequency()
+	case 9:
+		dateDataMap, err, errMsg = baseCalculate.DownFrequency()
+	case 10:
+		dateDataMap, err, errMsg = baseCalculate.TimeShift()
+	case 11:
+		dateDataMap, err, errMsg = baseCalculate.Cjjx()
+	case 12:
+		dateDataMap, err, errMsg = baseCalculate.Annualized()
+	case 13:
+		dateDataMap, err, errMsg = baseCalculate.Ljz()
+	case 14:
+		dateDataMap, err, errMsg = baseCalculate.LjzNczj()
+	case 15:
+		dateDataMap, err, errMsg = baseCalculate.ExponentialSmoothing()
+	case 16:
+		dateDataMap, err, errMsg = baseCalculate.Rjz()
+	default:
+		errMsg = "错误的计算类型"
+		err = errors.New(errMsg + ":" + strconv.Itoa(baseCalculate.Source))
+	}
+
+	if err != nil {
+		br.Msg = "计算失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	dateStrDataMap, dateList := models.GetDateDataAndDateList(dateDataMap)
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "计算成功"
+	br.Data = models.BaseCalculateResp{
+		DataMap:  dateStrDataMap,
+		DateList: dateList,
+	}
+	br.IsAddLog = true
+}

+ 10 - 2
controllers/edb_info.go

@@ -105,8 +105,16 @@ func (this *EdbInfoController) Add() {
 			}
 		}
 	}
-	admnId, _ := strconv.Atoi(utils.InitAdminId)
-	edbInfo, err := models.EdbInfoAdd(&req, windUrl, admnId, utils.InitAdminName)
+
+	adminId, _ := strconv.Atoi(utils.InitAdminId)
+	if req.AdminId > 0 {
+		adminId = req.AdminId
+	}
+	adminName := utils.InitAdminName
+	if req.AdminName != "" {
+		adminName = strings.TrimSpace(req.AdminName)
+	}
+	edbInfo, err := models.EdbInfoAdd(&req, windUrl, adminId, adminName)
 	if err != nil {
 		br.Msg = "新增指标失败!"
 		br.ErrMsg = "新增指标失败,Err:" + err.Error()

+ 0 - 3
go.mod

@@ -13,10 +13,8 @@ require (
 	github.com/olivere/elastic/v7 v7.0.32
 	github.com/rdlucklib/rdluck_tools v1.0.3
 	github.com/shopspring/decimal v1.3.1
-	github.com/sirupsen/logrus v1.6.0
 	github.com/yidane/formula v0.0.0-20210902154546-0782e1736717
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
-	gopkg.in/natefinch/lumberjack.v2 v2.2.1
 )
 
 require (
@@ -33,7 +31,6 @@ require (
 	github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9 // indirect
 	github.com/hashicorp/golang-lru v0.5.4 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
-	github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
 	github.com/mitchellh/mapstructure v1.4.1 // indirect

+ 0 - 4
go.sum

@@ -278,7 +278,6 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -436,7 +435,6 @@ github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKz
 github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
 github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
 github.com/smartwalle/pongo2render v1.0.1/go.mod h1:MGnTzND7nEMz7g194kjlnw8lx/V5JJlb1hr5kDXEO0I=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -733,8 +731,6 @@ gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkp
 gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
-gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
-gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=

+ 1811 - 0
models/base_calculate.go

@@ -0,0 +1,1811 @@
+package models
+
+import (
+	"errors"
+	"eta/eta_index_lib/utils"
+	"fmt"
+	"github.com/shopspring/decimal"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// EdbInfoData
+// @Description: 指标数据
+type EdbInfoData struct {
+	EdbDataId int       `description:"数据ID"`
+	DataTime  time.Time `description:"数据日期"`
+	Value     float64   `description:"数据"`
+}
+
+// BaseCalculateBySearchData
+// @Description: 基础的计算公式
+type BaseCalculateBySearchData struct {
+	DataList      []*EdbInfoSearchData
+	Frequency     string `description:"需要转换的频度"`
+	Formula       interface{}
+	Calendar      string `description:"公历/农历"`
+	MoveType      int    `description:"移动方式:1:领先(默认),2:滞后"`
+	MoveFrequency string `description:"移动频度"`
+	FromFrequency string `description:"来源的频度"`
+	Source        int    `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
+}
+
+// BaseCalculate
+// @Description: 基础的计算公式
+type BaseCalculate struct {
+	DataList      []*EdbInfoData
+	Frequency     string `description:"需要转换的频度"`
+	Formula       interface{}
+	Calendar      string `description:"公历/农历"`
+	MoveType      int    `description:"移动方式:1:领先(默认),2:滞后"`
+	MoveFrequency string `description:"移动频度"`
+	FromFrequency string `description:"来源的频度"`
+	Source        int    `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
+}
+
+type BaseCalculateResp struct {
+	DataMap  map[string]float64
+	DateList []string
+}
+
+// Ljzzy
+// @Description: 累计值转月
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:05:19
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) Ljzzy() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+
+	dataList := obj.DataList // 升序
+	// 数据处理
+	yearMap := make(map[int]map[int]*EdbInfoData)
+	dataLen := len(dataList)
+	for i := 0; i < dataLen; i++ {
+		item := dataList[i]
+		//日其中获取年
+		itemDate := item.DataTime
+		year := itemDate.Year()
+		month := int(itemDate.Month())
+		if monthMap, yok := yearMap[year]; yok {
+			monthMap[month] = item
+			yearMap[year] = monthMap
+		} else {
+			monthMap = make(map[int]*EdbInfoData)
+			monthMap[month] = item
+			yearMap[year] = monthMap
+		}
+	}
+
+	// 开始计算
+	for yk, yv := range yearMap {
+		_, oneMonthOk := yv[1]
+		_, twoMonthOk := yv[2]
+		if !oneMonthOk && !twoMonthOk {
+			continue
+		}
+		for i := 1; i <= 12; i++ {
+			//fmt.Println(yk, i, yv[i])
+			dataCurrentItem := yv[i]
+			if dataCurrentItem == nil {
+				continue
+			}
+			var date time.Time
+			var val float64
+
+			// 一二月单独处理
+			if i == 1 || i == 2 {
+				if _, mok := yv[1]; mok { //1月有值
+					if i == 1 {
+						date = dataCurrentItem.DataTime
+						val, _ = decimal.NewFromFloat(dataCurrentItem.Value).Float64() //a.Div(b).Float64()
+					}
+					if i == 2 {
+						dataOneItem := yv[1]
+						date = dataCurrentItem.DataTime
+						twoMonth := decimal.NewFromFloat(dataCurrentItem.Value)
+						oneMonth := decimal.NewFromFloat(dataOneItem.Value)
+						val, _ = twoMonth.Sub(oneMonth).Float64()
+					}
+				} else { //1月无值
+					dataTwoItem := yv[2]
+					if i == 1 {
+						dateStr := strconv.Itoa(yk) + "-01-31"
+						a := decimal.NewFromFloat(dataTwoItem.Value)
+						b := decimal.NewFromFloat(2.0)
+						val, _ = a.Div(b).Float64()
+
+						date, err = time.ParseInLocation(utils.FormatDate, dateStr, time.Local)
+						if err != nil {
+							return
+						}
+
+					}
+					if i == 2 {
+						//1月无值:1月=2月/2 (不管怎样,都要给1月赋值)
+						{
+							dateStr := strconv.Itoa(yk) + "-01-31"
+							a := decimal.NewFromFloat(dataTwoItem.Value)
+							b := decimal.NewFromFloat(2.0)
+							val, _ = a.Div(b).Float64()
+							date, err = time.ParseInLocation(utils.FormatDate, dateStr, time.Local)
+							if err != nil {
+								return
+							}
+							dateDataMap[date] = val
+						}
+						//end 1月无值
+
+						// 这是正常二月份的值
+						date = dataCurrentItem.DataTime
+						a := decimal.NewFromFloat(dataTwoItem.Value)
+						b := decimal.NewFromFloat(2.0)
+						val, _ = a.Div(b).Float64()
+					}
+				}
+			} else {
+				dataPreItem := yv[i-1]
+				if dataCurrentItem != nil && dataPreItem != nil {
+					date = dataCurrentItem.DataTime
+					//val =  dataCurrentItem.Value - dataPreItem.Value
+					a := decimal.NewFromFloat(dataCurrentItem.Value)
+					b := decimal.NewFromFloat(dataPreItem.Value)
+					val, _ = a.Sub(b).Float64()
+				}
+			}
+
+			// 如果没有日期,那么就退出当前循环,进入下一个循环
+			if date.IsZero() {
+				continue
+			}
+
+			dateDataMap[date] = val
+		}
+	}
+
+	return
+}
+
+// Ljzzj
+// @Description: 累计值转季度
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:05:05
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) Ljzzj() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	dataList := obj.DataList // 升序
+	// 数据处理
+	yearMap := make(map[int]map[int]*EdbInfoData)
+	dataLen := len(dataList)
+	for i := 0; i < dataLen; i++ {
+		item := dataList[i]
+		//日其中获取年
+		itemDate := item.DataTime
+		year := itemDate.Year()
+		quarter := utils.MonthQuarterMap[int(itemDate.Month())]
+		if quarterMap, yok := yearMap[year]; yok {
+			quarterMap[quarter] = item
+			yearMap[year] = quarterMap
+		} else {
+			quarterMap = make(map[int]*EdbInfoData)
+			quarterMap[quarter] = item
+			yearMap[year] = quarterMap
+		}
+	}
+
+	// 开始计算
+	for yk, yv := range yearMap {
+		_, oneQuarterOk := yv[1]
+		_, twoQuarterOk := yv[2]
+		if !oneQuarterOk && !twoQuarterOk {
+			continue
+		}
+		for i := 1; i <= 4; i++ {
+			//fmt.Println(yk, i, yv[i])
+			dataCurrentItem := yv[i]
+			if dataCurrentItem == nil {
+				continue
+			}
+			var date time.Time
+			var val float64
+
+			// 一二季度单独处理
+			if i == 1 || i == 2 {
+				if _, mok := yv[1]; mok { //第1个季度有值
+					if i == 1 {
+						date = dataCurrentItem.DataTime
+						val, _ = decimal.NewFromFloat(dataCurrentItem.Value).Float64() //a.Div(b).Float64()
+					}
+					if i == 2 {
+						dataOneItem := yv[1]
+						date = dataCurrentItem.DataTime
+						twoQuarter := decimal.NewFromFloat(dataCurrentItem.Value)
+						oneQuarter := decimal.NewFromFloat(dataOneItem.Value)
+						val, _ = twoQuarter.Sub(oneQuarter).Float64()
+					}
+				} else { //第1个季度无值
+					dataTwoItem := yv[2]
+					if i == 1 {
+						dateStr := strconv.Itoa(yk) + "-03-31"
+						a := decimal.NewFromFloat(dataTwoItem.Value)
+						b := decimal.NewFromFloat(2.0)
+						val, _ = a.Div(b).Float64()
+						date, err = time.ParseInLocation(utils.FormatDate, dateStr, time.Local)
+						if err != nil {
+							return
+						}
+					}
+					if i == 2 {
+						//第1个季度无值:第1个季度=第2个季度/2 (不管怎样,都要给1季度赋值)
+						{
+							dateStr := strconv.Itoa(yk) + "-03-31"
+							a := decimal.NewFromFloat(dataTwoItem.Value)
+							b := decimal.NewFromFloat(2.0)
+							val, _ = a.Div(b).Float64()
+							date, err = time.ParseInLocation(utils.FormatDate, dateStr, time.Local)
+							if err != nil {
+								return
+							}
+
+							dateDataMap[date] = val
+						}
+						//end 第1个季度无值
+
+						date = dataCurrentItem.DataTime
+						a := decimal.NewFromFloat(dataTwoItem.Value)
+						b := decimal.NewFromFloat(2.0)
+						val, _ = a.Div(b).Float64()
+					}
+				}
+			} else {
+				dataPreItem := yv[i-1]
+				if dataCurrentItem != nil && dataPreItem != nil {
+					date = dataCurrentItem.DataTime
+					//val =  dataCurrentItem.Value - dataPreItem.Value
+					a := decimal.NewFromFloat(dataCurrentItem.Value)
+					b := decimal.NewFromFloat(dataPreItem.Value)
+					val, _ = a.Sub(b).Float64()
+				}
+			}
+
+			// 如果没有日期,那么就退出当前循环,进入下一个循环
+			if date.IsZero() {
+				continue
+			}
+
+			dateDataMap[date] = val
+		}
+	}
+
+	return
+}
+
+// Tbz
+// @Description: 同比值计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:04:59
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) Tbz() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	dataList := obj.DataList
+	frequency := obj.FromFrequency
+
+	//数据处理
+	// 数据降序
+	dataList = reverseSliceByDesc(dataList)
+
+	var dateArr []time.Time
+	dataMap := make(map[string]*EdbInfoData) // 避免因为时间戳导致的日期不对,还是用string来表示比较合适
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime.Format(utils.FormatDate)] = v
+	}
+
+	// 开始计算
+	for _, currentDate := range dateArr {
+		//当前日期
+		currentDateStr := currentDate.Format(utils.FormatDate)
+		currentItem, ok := dataMap[currentDateStr]
+		if !ok {
+			continue
+		}
+
+		// 找到的数据
+		var findItem *EdbInfoData
+
+		//上一年的日期
+		preDate := currentDate.AddDate(-1, 0, 0)
+		preDateStr := preDate.Format(utils.FormatDate)
+		if findItem, ok = dataMap[preDateStr]; !ok { //上一年同期没找到
+			if frequency == "月度" { //向上和向下,各找一个月
+				for i := 0; i <= 35; i++ {
+					nextDateDay := preDate.AddDate(0, 0, i)
+					nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+					if findItem, ok = dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+						break
+					} else {
+						preDateDay := preDate.AddDate(0, 0, -i)
+						preDateDayStr := preDateDay.Format(utils.FormatDate)
+						if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+							break
+						}
+					}
+				}
+			} else if frequency == "季度" || frequency == "年度" {
+				if findItem, ok = dataMap[preDateStr]; ok { //上一年同期->下一个月找到
+					break
+				}
+			} else {
+				nextDateDay := preDate.AddDate(0, 0, 1)
+				nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+
+				preDateDay := preDate.AddDate(0, 0, -1)
+				preDateDayStr := preDateDay.Format(utils.FormatDate)
+
+				for i := 0; i < 35; i++ {
+					if i >= 1 {
+						nextDateDay = nextDateDay.AddDate(0, 0, i)
+						nextDateDayStr = nextDateDay.Format(utils.FormatDate)
+					}
+					if findItem, ok = dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+						break
+					} else {
+						if i >= 1 {
+							preDateDay = preDateDay.AddDate(0, 0, -i)
+							preDateDayStr = preDateDay.Format(utils.FormatDate)
+						}
+						if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+							break
+						}
+					}
+				}
+			}
+
+		}
+
+		// 如果没找到数据
+		if findItem == nil {
+			continue
+		}
+
+		dateDataMap[currentDate] = tbzDiv(currentItem.Value, findItem.Value)
+	}
+
+	return
+}
+
+// tbzDiv
+// @Description: 同比值计算
+// @author: Roc
+// @datetime2023-11-02 16:29:14
+// @param a float64
+// @param b float64
+// @return float64
+func tbzDiv(a, b float64) float64 {
+	var val float64
+	if b != 0 {
+		af := decimal.NewFromFloat(a)
+		bf := decimal.NewFromFloat(b)
+		val, _ = af.Div(bf).Sub(decimal.NewFromFloat(1)).RoundCeil(4).Float64()
+	}
+	return val
+}
+
+// Tcz
+// @Description: 计算同差值
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:04:51
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) Tcz() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	dataList := obj.DataList // 降序
+	frequency := obj.FromFrequency
+
+	// 数据处理
+	// 数据降序
+	dataList = reverseSliceByDesc(dataList)
+	var dateArr []time.Time
+	dataMap := make(map[string]*EdbInfoData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime.Format(utils.FormatDate)] = v
+	}
+
+	// 开始计算
+	for _, currentDate := range dateArr {
+		//当前日期
+		currentItem, ok := dataMap[currentDate.Format(utils.FormatDate)]
+		if !ok {
+			continue
+		}
+
+		// 找到的数据
+		var findItem *EdbInfoData
+
+		//上一年的日期
+		preDate := currentDate.AddDate(-1, 0, 0)
+		preDateStr := preDate.Format(utils.FormatDate)
+		if findItem, ok = dataMap[preDateStr]; !ok {
+			//上一年同期没找到
+			if frequency == "月度" { //向上和向下,各找一个月
+				for i := 0; i <= 35; i++ {
+					nextDateDay := preDate.AddDate(0, 0, i)
+					nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+					if findItem, ok = dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+						break
+					} else {
+						preDateDay := preDate.AddDate(0, 0, -i)
+						preDateDayStr := preDateDay.Format(utils.FormatDate)
+						if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+							break
+						}
+					}
+				}
+			} else if frequency == "季度" || frequency == "年度" {
+				if findItem, ok = dataMap[preDateStr]; ok { //上一年同期->下一个月找到
+					break
+				}
+			} else {
+				for i := 0; i < 35; i++ {
+					nextDateDay := preDate.AddDate(0, 0, i)
+					nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+					if findItem, ok = dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+						break
+					} else {
+						preDateDay := preDate.AddDate(0, 0, -i)
+						preDateDayStr := preDateDay.Format(utils.FormatDate)
+						if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+							break
+						}
+					}
+				}
+			}
+		}
+
+		// 如果没找到数据
+		if findItem == nil {
+			continue
+		}
+
+		dateDataMap[currentDate] = tczSub(currentItem.Value, findItem.Value)
+	}
+
+	return
+}
+
+// tczSub
+// @Description: 计算同差值
+// @author: Roc
+// @datetime2023-11-02 18:01:46
+// @param a float64
+// @param b float64
+// @return float64
+func tczSub(a, b float64) float64 {
+	af := decimal.NewFromFloat(a)
+	bf := decimal.NewFromFloat(b)
+	val, _ := af.Sub(bf).RoundCeil(4).Float64()
+	return val
+}
+
+// Nszydpjjs
+// @Description: N数值移动平均数计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:17:38
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) Nszydpjjs() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	fromDataList := obj.DataList
+	nVal := fmt.Sprint(obj.Formula)
+	formulaInt, err := strconv.Atoi(nVal)
+	if err != nil {
+		return
+	}
+
+	// 数据处理
+
+	// 数据降序
+	fromDataList = reverseSliceByDesc(fromDataList)
+
+	var fromDateArr []time.Time
+	fromDataMap := make(map[time.Time]*EdbInfoData)
+	for _, v := range fromDataList {
+		fromDateArr = append(fromDateArr, v.DataTime)
+		fromDataMap[v.DataTime] = v
+	}
+
+	arrLen := len(fromDateArr)
+	for ak, currentDate := range fromDateArr {
+		//处理第一个值
+		var valArr []float64
+		if findItem, ok := fromDataMap[currentDate]; ok {
+			valArr = append(valArr, findItem.Value)
+		} else {
+			continue
+		}
+		if ak+1 != arrLen {
+			//处理除第一个值之外的N-1个值
+			for i := 1; i < formulaInt; i++ {
+				arrIndex := ak + i
+				if arrIndex >= arrLen {
+					break
+				}
+				arrVal := fromDateArr[arrIndex]
+				if findItem, ok := fromDataMap[arrVal]; ok {
+					valArr = append(valArr, findItem.Value)
+				} else {
+					continue
+				}
+			}
+		}
+		valArrLen := len(valArr)
+		//var totalVal float64
+		totalVal := decimal.NewFromFloat(0.00)
+		for _, v := range valArr {
+			newDecimal := decimal.NewFromFloat(v)
+			totalVal = totalVal.Add(newDecimal)
+		}
+		af := totalVal //decimal.NewFromFloat(totalVal)
+		bf := decimal.NewFromFloat(float64(valArrLen))
+		val, _ := af.Div(bf).RoundCeil(4).Float64()
+
+		dateDataMap[currentDate] = val
+	}
+
+	return
+}
+
+// Hbz
+// @Description: 环比值计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:28:24
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) Hbz() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	dataList := obj.DataList
+	nVal := fmt.Sprint(obj.Formula)
+	formulaInt, err := strconv.Atoi(nVal)
+	if err != nil {
+		return
+	}
+
+	// 数据处理
+	// 数据降序
+	dataList = reverseSliceByDesc(dataList)
+
+	var dateArr []time.Time
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+	}
+
+	// 数据计算
+	dataLen := len(dataList)
+	//fmt.Println("dataLen:", dataLen)
+	for i := 0; i < dataLen; i++ {
+		j := i + formulaInt
+		if j < dataLen {
+			//当期
+			currentItem := dataList[i]
+			preItem := dataList[j]
+
+			// 当期和上期没有数据
+			if currentItem == nil || preItem == nil {
+				continue
+			}
+
+			// 开始计算
+			val, ok := hbzDiv(currentItem.Value, preItem.Value)
+			// 计算失败
+			if !ok {
+				continue
+			}
+
+			dateDataMap[currentItem.DataTime] = val
+		}
+	}
+
+	return
+}
+
+// hbzDiv
+// @Description: 环比值计算,current:当期,pre:上期 公式: (当期-上期)/上期
+// @author: Roc
+// @datetime2023-11-02 18:20:11
+// @param current float64
+// @param pre float64
+// @return val float64
+// @return ok bool
+func hbzDiv(current, pre float64) (val float64, ok bool) {
+	if pre == 0 {
+		return
+	}
+	currentVal := decimal.NewFromFloat(current)
+	preVal := decimal.NewFromFloat(pre)
+	val, _ = currentVal.Sub(preVal).Div(preVal).RoundCeil(4).Float64()
+	//valStr := decimal.NewFromFloat(val).RoundCeil(4).String() //utils.SubFloatToString(val, 4)
+	ok = true
+
+	return
+}
+
+// Hcz
+// @Description: 计算环差值数据
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:33:20
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) Hcz() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	dataList := obj.DataList
+	nVal := fmt.Sprint(obj.Formula)
+	formulaInt, err := strconv.Atoi(nVal)
+	if err != nil {
+		return
+	}
+
+	// 数据处理
+	// 数据降序
+	dataList = reverseSliceByDesc(dataList)
+
+	var dateArr []time.Time
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+	}
+
+	dataLen := len(dataList)
+	fmt.Println("dataLen:", dataLen)
+	for i := 0; i < dataLen; i++ {
+		j := i + formulaInt
+		if j < dataLen {
+			//当期
+			currentItem := dataList[i]
+			preItem := dataList[j]
+
+			// 当期和上期没有数据
+			if currentItem == nil || preItem == nil {
+				continue
+			}
+
+			// 开始计算
+			val := hczDiv(currentItem.Value, preItem.Value)
+
+			dateDataMap[currentItem.DataTime] = val
+		}
+	}
+
+	return
+}
+
+// hczDiv
+// @Description: 环差值计算,current:当期,pre:上期 公式:当期-上期
+// @author: Roc
+// @datetime2023-11-02 18:33:07
+// @param current float64
+// @param pre float64
+// @return float64
+func hczDiv(current, pre float64) float64 {
+	currentVal := decimal.NewFromFloat(current)
+	preVal := decimal.NewFromFloat(pre)
+	val, _ := currentVal.Sub(preVal).RoundCeil(4).Float64()
+	//valStr := decimal.NewFromFloat(val).RoundCeil(4).String() //utils.SubFloatToString(val, 4)
+
+	return val
+}
+
+// UpFrequency
+// @Description: 升频计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:43:03
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) UpFrequency() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	dataList := obj.DataList
+
+	// 数据处理
+	var dateArr []time.Time
+	dataMap := make(map[time.Time]*EdbInfoData)
+	fromDataMap := make(map[time.Time]float64)
+	//来源指指标数据
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+		fromDataMap[v.DataTime] = v.Value
+	}
+
+	if obj.FromFrequency == `日度` {
+		errMsg = `不能选择日度指标`
+		err = errors.New(errMsg)
+		return
+	}
+
+	// 数据计算
+	dataLen := len(dataList)
+	for i := 0; i < dataLen; i++ {
+		//当期
+		currentItem := dataList[i]
+		currentDate := currentItem.DataTime
+		var day int
+		var preItem *EdbInfoData
+		var preDate time.Time
+		if i == 0 {
+			day = int(time.Now().Sub(currentDate).Hours() / float64(24))
+			preDate = time.Now()
+		} else {
+			j := i - 1
+			if j < dataLen {
+				preItem = dataList[j]
+				day = int(preItem.DataTime.Sub(currentDate).Hours() / float64(24))
+				utils.FileLog.Info("preItem.DataTime:" + preItem.DataTime.Format(utils.FormatDate) + ";currentItem.DataTime" + currentItem.DataTime.Format(utils.FormatDate))
+			}
+		}
+		for k := 0; k <= day; k++ {
+			needDay := preDate.AddDate(0, 0, -k)
+			dateDataMap[needDay] = currentItem.Value
+		}
+		dateDataMap[currentItem.DataTime] = currentItem.Value
+	}
+
+	return
+}
+
+// DownFrequency
+// @Description: 降频计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:51:26
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) DownFrequency() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	dataList := obj.DataList
+	edbFrequency := obj.Frequency
+	formula := obj.Formula.(string)
+
+	if !CheckFrequency(obj.FromFrequency, obj.Frequency) {
+		errMsg = "频度异常,不允许低频降频到高频"
+		err = errors.New(errMsg)
+		return
+	}
+
+	// 数据处理
+	var dateArr []time.Time
+	dataMap := make(map[time.Time]*EdbInfoData)
+	fromDataMap := make(map[time.Time]float64)
+	//来源指指标数据
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+		fromDataMap[v.DataTime] = v.Value
+	}
+
+	// 数据计算
+	dataLen := len(dataList)
+	if dataLen <= 0 {
+		return
+	}
+	startDataTime := dataList[0].DataTime
+	endDataTime := dataList[dataLen-1].DataTime
+
+	var lastValue float64     // 最近的值
+	var nextEndDate time.Time // 下一个节点的日期
+	weekDayDataList := make([]float64, 0)
+	for tmpStartDataTime := startDataTime; !tmpStartDataTime.After(endDataTime); tmpStartDataTime = tmpStartDataTime.AddDate(0, 0, 1) {
+		// 将当前数据加入到 weekDayDataList
+		if tmpData, ok := dataMap[tmpStartDataTime]; ok {
+			tmpValue := decimal.NewFromFloat(tmpData.Value)
+			tmpValueFloat, _ := tmpValue.Round(4).Float64()
+			weekDayDataList = append(weekDayDataList, tmpValueFloat)
+		}
+		// 如果下个节点的日期不存在,那么就先给赋值(兼容时间区间内只有一组数据的情况)
+		if nextEndDate.IsZero() {
+			nextEndDate = utils.GetFrequencyEndDay(tmpStartDataTime, edbFrequency)
+		}
+
+		// 日期处理过滤
+		switch edbFrequency {
+		case "周度":
+			if tmpStartDataTime.Weekday() != 0 {
+				//不是周日,代表需要进入下一个循环获取数据并计算
+				continue
+			} else {
+				//记录下一个结束节点的日期
+				nextEndDate = tmpStartDataTime.AddDate(0, 0, 7)
+			}
+		case "旬度":
+			nextDay := tmpStartDataTime.AddDate(0, 0, 1)
+			if nextDay.Day() != 1 && nextDay.Day() != 11 && nextDay.Day() != 21 {
+				//不是每月10、20、最后一天,代表需要进入下一个循环获取数据并计算
+				continue
+			} else {
+				//记录下一个结束节点的日期
+				if nextDay.Day() == 1 || nextDay.Day() == 11 {
+					//月初或者月末的时候,加10天就好了
+					nextEndDate = nextDay.AddDate(0, 0, 9)
+				} else {
+					tmpNextMonth := nextDay.AddDate(0, 1, 0)
+					nextEndDate = time.Date(tmpNextMonth.Year(), tmpNextMonth.Month(), 1, 0, 0, 0, 0, time.Local).AddDate(0, 0, -1)
+				}
+			}
+		case "月度":
+			nextDay := tmpStartDataTime.AddDate(0, 0, 1)
+			if nextDay.Day() != 1 {
+				//不是每月最后一天,代表需要进入下一个循环获取数据并计算
+				continue
+			} else {
+				//记录下一个结束节点的日期
+				nextEndDate = nextDay.AddDate(0, 1, -1)
+			}
+		case "季度":
+			nextDay := tmpStartDataTime.AddDate(0, 0, 1)
+			if (nextDay.Month() == 1 || nextDay.Month() == 4 || nextDay.Month() == 7 || nextDay.Month() == 10) && nextDay.Day() == 1 {
+				//记录下一个结束节点的日期
+				nextEndDate = nextDay.AddDate(0, 3, -1)
+			} else {
+				//不是3,6,9,12 月份的最后一天,代表需要进入下一个循环获取数据并计算
+				continue
+			}
+		case "年度":
+			if tmpStartDataTime.Month() == 12 && tmpStartDataTime.Day() == 31 {
+				//记录下一个结束节点的日期
+				nextEndDate = tmpStartDataTime.AddDate(1, 0, 0)
+			} else {
+				//不是每年的12-31日,代表需要进入下一个循环获取数据并计算
+				continue
+			}
+		default:
+			err = errors.New("错误的频度:" + edbFrequency)
+			return
+		}
+
+		// 当前时间段内的数据计算,得出实际值
+		var currVal float64
+		lenWeekDayDataList := len(weekDayDataList)
+		// 如果这个时间区间内没有数据,那么就采用上一个时间区间的值
+		if len(weekDayDataList) <= 0 {
+			currVal = lastValue
+		} else {
+			if formula == "期末值" {
+				currVal = weekDayDataList[lenWeekDayDataList-1]
+			} else {
+				// 平均值
+				sumValDeci := decimal.NewFromFloat(0)
+				for _, v := range weekDayDataList {
+					tmpValDeci := decimal.NewFromFloat(v)
+					sumValDeci = sumValDeci.Add(tmpValDeci)
+				}
+				lenDeci := decimal.NewFromInt(int64(lenWeekDayDataList))
+				currVal, _ = sumValDeci.Div(lenDeci).Round(4).Float64()
+			}
+		}
+
+		// 赋值
+		dateDataMap[tmpStartDataTime] = currVal
+
+		// 一轮结束后,数据清空
+		weekDayDataList = make([]float64, 0)
+	}
+
+	// 最后已有的日期处理完成后,需要对剩余不在时间段内的数据做处理
+	if len(weekDayDataList) > 0 {
+		// 当前时间段内的数据计算,得出实际值
+		var currVal float64
+		lenWeekDayDataList := len(weekDayDataList)
+		// 如果这个时间区间内没有数据,那么就采用上一个时间区间的值
+		if len(weekDayDataList) < 0 {
+			currVal = lastValue
+		} else {
+			if formula == "期末值" {
+				currVal = weekDayDataList[lenWeekDayDataList-1]
+			} else {
+				// 平均值
+				sumValDeci := decimal.NewFromFloat(0)
+				for _, v := range weekDayDataList {
+					tmpValDeci := decimal.NewFromFloat(v)
+					sumValDeci = sumValDeci.Add(tmpValDeci)
+				}
+				lenDeci := decimal.NewFromInt(int64(lenWeekDayDataList))
+				currVal, _ = sumValDeci.Div(lenDeci).Round(4).Float64()
+			}
+		}
+
+		// 赋值
+		dateDataMap[nextEndDate] = currVal
+	}
+
+	return
+}
+
+// TimeShift
+// @Description: 时间移位计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 13:19:07
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) TimeShift() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	dataList := obj.DataList
+
+	nVal := fmt.Sprint(obj.Formula)
+	formulaInt, err := strconv.Atoi(nVal)
+	if err != nil {
+		return
+	}
+
+	moveType := obj.MoveType
+	moveFrequency := obj.MoveFrequency
+
+	// 数据处理
+	var dateArr []time.Time
+	dataMap := make(map[time.Time]*EdbInfoData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+
+	var shiftDay int
+	switch moveFrequency {
+	case "天":
+		shiftDay = formulaInt
+	case "周":
+		shiftDay = formulaInt * 7
+	case "月":
+		shiftDay = formulaInt * 30
+	case "季":
+		shiftDay = formulaInt * 90
+	case "年":
+		shiftDay = formulaInt * 365
+	default:
+		shiftDay = formulaInt
+	}
+
+	if moveType == 2 {
+		shiftDay = -shiftDay
+	}
+
+	dataLen := len(dataList)
+	for i := 0; i < dataLen; i++ {
+		//当期
+		currentItem := dataList[i]
+		currentDate := currentItem.DataTime
+
+		newDate := currentDate.AddDate(0, 0, shiftDay)
+
+		val, _ := decimal.NewFromFloat(currentItem.Value).RoundCeil(4).Float64()
+
+		dateDataMap[newDate] = val
+	}
+
+	return
+}
+
+// Cjjx
+// @Description: 超季节性计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 13:28:23
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) Cjjx() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	dataList := obj.DataList
+
+	nVal := fmt.Sprint(obj.Formula)
+	formulaInt, err := strconv.Atoi(nVal)
+	if err != nil {
+		return
+	}
+
+	calendar := obj.Calendar
+
+	// 数据处理
+	var dateArr []time.Time
+	dataMap := make(map[time.Time]*EdbInfoData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+
+	// 通过插值法补全所有数据(包含周末)
+	handleDataMap := make(map[time.Time]float64)
+	_, err = HandleDataByLinearRegressionByTime(dataList, handleDataMap)
+	if err != nil {
+		return
+	}
+
+	// 每个年份的日期数据需要平移的天数
+	moveDayMap := make(map[int]int, 0) // 每个年份的春节公历
+	var lastDataDay time.Time
+	if len(dataList) > 0 {
+		lastDataDay = dataList[0].DataTime
+	}
+
+	// 数据计算
+	for _, currentDate := range dateArr {
+		// 如果遇到闰二月,如2.29,去掉该天数据
+		if strings.Contains(currentDate.Format(utils.FormatDate), "02-29") {
+			continue
+		}
+
+		//农历的超季节性运算,只计算11月--次年5月,分段计算,与数据区间和N数值有关
+		if calendar == "农历" && currentDate.Month() > 5 && currentDate.Month() < 11 {
+			continue
+		}
+
+		currentItem, ok := dataMap[currentDate]
+		// 找不到数据就退出当前循环,进入下一循环
+		if !ok {
+			continue
+		}
+
+		pastValueList := make([]float64, 0)                      // 过去几期的数据
+		pastValueList = append(pastValueList, currentItem.Value) //当前日期
+
+		for i := 1; i < formulaInt; i++ {
+			//前几年当天公历的日期
+			historyPreDate := currentDate.AddDate(-i, 0, 0)
+			moveDay := 0
+			if calendar == "农历" {
+				if tmpMoveDay, ok := moveDayMap[historyPreDate.Year()]; !ok {
+					moveDay, err = getMoveDay(lastDataDay, historyPreDate)
+					if err != nil {
+						return
+					}
+				} else {
+					moveDay = tmpMoveDay
+				}
+
+				// 移动天数到对应农历 的 公历 日期
+				historyPreDate = historyPreDate.AddDate(0, 0, moveDay)
+			}
+
+			if tmpValue, ok := handleDataMap[historyPreDate]; ok { //上一年同期找到
+				pastValueList = append(pastValueList, tmpValue)
+			}
+		}
+
+		if len(pastValueList) == formulaInt {
+			val, ok := cjjxSub(currentItem.Value, pastValueList)
+			if !ok {
+				continue
+			}
+			dateDataMap[currentDate] = val
+		}
+	}
+
+	return
+}
+
+// cjjxSub
+// @Description: 超季节性计算
+// @author: Roc
+// @datetime2023-11-03 13:25:49
+// @param currValue float64
+// @param pastValue []float64
+// @return value float64
+// @return ok bool
+func cjjxSub(currValue float64, pastValue []float64) (value float64, ok bool) {
+	num := len(pastValue)
+	if num == 0 {
+		return
+	}
+	numDecimal := decimal.NewFromInt(int64(num))
+
+	af := decimal.NewFromFloat(currValue)
+	bf := decimal.NewFromFloat(pastValue[0])
+
+	for k := 1; k < num; k++ {
+		tmpVal := decimal.NewFromFloat(pastValue[k])
+		bf = bf.Add(tmpVal)
+	}
+	value, _ = af.Sub(bf.Div(numDecimal)).RoundCeil(4).Float64()
+	ok = true
+
+	return
+}
+
+// Annualized
+// @Description: 年化计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 13:34:32
+// @param to orm.TxOrmer
+// @param edbInfoId int
+// @param source int
+// @param fromEdbInfo *EdbInfo
+// @param edbCode string
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) Annualized() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	fromDataList := obj.DataList
+	lenFromDataList := len(fromDataList)
+	// 如果来源指标没有数据,那么就直接返回得了
+	if lenFromDataList <= 0 {
+		return
+	}
+
+	// 数据处理
+	// 插值法数据处理
+	handleDataMap := make(map[time.Time]float64)
+	_, err = HandleDataByLinearRegressionByTime(fromDataList, handleDataMap)
+	if err != nil {
+		return
+	}
+
+	// 每年的最后一天的数据值
+	yearLastValMap := make(map[int]float64)
+	startDataTime := fromDataList[0].DataTime
+	endDataTime := fromDataList[lenFromDataList-1].DataTime
+	for i := startDataTime.Year(); i <= endDataTime.Year(); i++ {
+		tmpDate := time.Date(i, 12, 31, startDataTime.Hour(), startDataTime.Minute(), startDataTime.Second(), startDataTime.Nanosecond(), time.Local)
+		if tmpVal, ok := handleDataMap[tmpDate]; ok {
+			yearLastValMap[i] = tmpVal
+		}
+	}
+
+	// 数据计算
+	// 遍历来源指标数据
+	for _, v := range fromDataList {
+		currDate := v.DataTime
+
+		perValMap := make(map[time.Time]float64)
+		//前3年当日的数据
+		for i := 1; i <= 3; i++ {
+			tmpDateTime := currDate.AddDate(-i, 0, 0)
+			if tmpVal, ok := handleDataMap[tmpDateTime]; ok {
+				perValMap[tmpDateTime] = tmpVal
+			}
+		}
+		lenPerValMap := len(perValMap)
+		// 如果数据少于2年,那么就不参与计算,结束当前循环,进入下一个循环
+		if lenPerValMap < 2 {
+			continue
+		}
+
+		// N年 当前值占全年比重 的值列表
+		divValList := make([]decimal.Decimal, 0)
+		for tmpDateTime, tmpVal := range perValMap {
+			yearLastVal, ok2 := yearLastValMap[tmpDateTime.Year()]
+			// 如果当年最后一天没有数据
+			if !ok2 {
+				continue
+			}
+
+			// 当前值占全年比重
+			tmpYearLastVal := decimal.NewFromFloat(yearLastVal)
+			if tmpYearLastVal.IsZero() { //如果是0,那么就退出当前循环,进入下一个循环
+				continue
+			}
+			divVal := decimal.NewFromFloat(tmpVal).Div(tmpYearLastVal)
+			divValList = append(divValList, divVal)
+		}
+
+		lenDivValList := len(divValList)
+		// 如果 N年 当前值占全年比重 的值 小于 2个,那么就不参与计算,结束当前循环,进入下一个循环
+		if lenDivValList < 2 {
+			continue
+		}
+
+		divValSum := decimal.NewFromFloat(0)
+		for _, divVal := range divValList {
+			divValSum = divValSum.Add(divVal)
+		}
+
+		// 当前计算出来的结果
+		tmpDivVal := divValSum.Div(decimal.NewFromInt(int64(lenDivValList)))
+		if tmpDivVal.IsZero() { //如果是0,那么就退出当前循环,进入下一个循环
+			continue
+		}
+		currVal, _ := decimal.NewFromFloat(v.Value).Div(tmpDivVal).Round(4).Float64()
+
+		dateDataMap[currDate] = currVal
+	}
+
+	return
+}
+
+// Ljz
+// @Description: 累计值
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 13:49:17
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) Ljz() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	dataList := obj.DataList
+	frequency := obj.Frequency         //需要变更的频度
+	fromFrequency := obj.FromFrequency //来源的频度
+	// 数据处理
+	var isWeekData bool // 是否周度数据,如果是周度数据的话,是需要变频的,最后结果还需要除以7
+	// 周度数据需要先变成日度的
+	if fromFrequency == `周度` {
+		isWeekData = true
+	}
+
+	fromEdbDataMap := make(map[time.Time]float64)
+	if isWeekData {
+		dataList, err = HandleDataByLinearRegressionByTime(dataList, fromEdbDataMap)
+		if err != nil {
+			return
+		}
+	}
+
+	//日度转周度:日期选周五,计算上周六到本周五的日度值的加总,最新日期为最新值对应的周五。
+	//日度转月度:日期选每个月最后一天,计算当月所有日度值的加总,最新日期为最新值对应当月最后一天。
+	//日度转季度、年度:方法类似转月度。
+	//周度转月度/季度/年度:将周度值转成日度,空值用插值法插值,计算当月/当季/当年所有值的加总,然后除以7。
+	//月度转季度/年度: 当季/当年月度值相加。
+
+	dateList := make([]time.Time, 0)
+	valueMap := make(map[time.Time]float64)
+	switch frequency {
+	case "年度":
+		yearMap := make(map[int]float64)
+		yearList := make([]int, 0)
+		for _, item := range dataList {
+			year := item.DataTime.Year()
+			yearVal, ok := yearMap[year]
+			if ok {
+				yearMap[year] = item.Value + yearVal
+			} else {
+				yearList = append(yearList, year)
+				yearMap[year] = item.Value
+			}
+		}
+		for _, v := range yearList {
+			currTime := time.Date(v, 12, 31, 0, 0, 0, 0, time.Local)
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = yearMap[v]
+		}
+	case "半年度":
+		yearMonthMap := make(map[string]float64)
+		yearMonthList := make([]string, 0)
+		for _, item := range dataList {
+			itemDate := item.DataTime
+			year := itemDate.Year()
+			var tmpK string
+			if itemDate.Month() <= 6 {
+				tmpK = fmt.Sprint(year, "06")
+			} else {
+				tmpK = fmt.Sprint(year, "12")
+			}
+
+			yearVal, ok := yearMonthMap[tmpK]
+			if ok {
+				yearMonthMap[tmpK] = item.Value + yearVal
+			} else {
+				yearMonthList = append(yearMonthList, tmpK)
+				yearMonthMap[tmpK] = item.Value
+			}
+		}
+		for _, v := range yearMonthList {
+			currTime, tmpErr := time.ParseInLocation(utils.FormatYearMonthUnSpace, v, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			currTime = currTime.AddDate(0, 1, -1)
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = yearMonthMap[v]
+		}
+	case "季度":
+		yearMonthMap := make(map[string]float64)
+		yearMonthList := make([]string, 0)
+		for _, item := range dataList {
+			itemDate := item.DataTime
+			year := itemDate.Year()
+			var tmpK string
+			if itemDate.Month() <= 3 {
+				tmpK = fmt.Sprint(year, "03")
+			} else if itemDate.Month() <= 6 {
+				tmpK = fmt.Sprint(year, "06")
+			} else if itemDate.Month() <= 9 {
+				tmpK = fmt.Sprint(year, "09")
+			} else {
+				tmpK = fmt.Sprint(year, "12")
+			}
+
+			yearVal, ok := yearMonthMap[tmpK]
+			if ok {
+				yearMonthMap[tmpK] = item.Value + yearVal
+			} else {
+				yearMonthList = append(yearMonthList, tmpK)
+				yearMonthMap[tmpK] = item.Value
+			}
+		}
+		for _, v := range yearMonthList {
+			currTime, tmpErr := time.ParseInLocation(utils.FormatYearMonthUnSpace, v, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			currTime = currTime.AddDate(0, 1, -1)
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = yearMonthMap[v]
+		}
+	case "月度":
+		yearMonthMap := make(map[string]float64)
+		yearMonthList := make([]string, 0)
+		for _, item := range dataList {
+			itemDate := item.DataTime
+			year := itemDate.Year()
+			var tmpK string
+			tmpK = fmt.Sprint(year*100 + int(itemDate.Month()))
+
+			yearVal, ok := yearMonthMap[tmpK]
+			if ok {
+				yearMonthMap[tmpK] = item.Value + yearVal
+			} else {
+				yearMonthList = append(yearMonthList, tmpK)
+				yearMonthMap[tmpK] = item.Value
+			}
+		}
+		for _, v := range yearMonthList {
+			currTime, tmpErr := time.ParseInLocation(utils.FormatYearMonthUnSpace, v, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			currTime = currTime.AddDate(0, 1, -1)
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = yearMonthMap[v]
+		}
+	case "旬度":
+		tmpDateDataMap := make(map[time.Time]float64)
+		tmpDateList := make([]time.Time, 0)
+		for _, item := range dataList {
+			itemDate := item.DataTime
+			dayInt := itemDate.Year()*100 + int(itemDate.Month())
+			var currTime time.Time
+			if itemDate.Month() <= 10 {
+				tmpK := fmt.Sprint(dayInt*100, "10")
+				currTime, err = time.ParseInLocation(utils.FormatDateUnSpace, tmpK, time.Local)
+				if err != nil {
+					return
+				}
+
+			} else if itemDate.Month() <= 20 {
+				tmpK := fmt.Sprint(dayInt*100, "20")
+				currTime, err = time.ParseInLocation(utils.FormatDateUnSpace, tmpK, time.Local)
+				if err != nil {
+					return
+				}
+			} else {
+				currTime, err = time.ParseInLocation(utils.FormatYearMonthUnSpace, fmt.Sprint(dayInt), time.Local)
+				if err != nil {
+					return
+				}
+				currTime = currTime.AddDate(0, 1, -1)
+			}
+
+			yearVal, ok := tmpDateDataMap[currTime]
+			if ok {
+				tmpDateDataMap[currTime] = item.Value + yearVal
+			} else {
+				tmpDateList = append(tmpDateList, currTime)
+				tmpDateDataMap[currTime] = item.Value
+			}
+		}
+		for _, currTime := range tmpDateList {
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = tmpDateDataMap[currTime]
+		}
+	case "周度":
+		tmpDateDataMap := make(map[time.Time]float64)
+		tmpDateList := make([]time.Time, 0)
+		for _, item := range dataList {
+			itemDate := item.DataTime
+			var currTime time.Time
+			// 周六周日,这是下一个周五的数据
+			if itemDate.Weekday() == 0 {
+				currTime = itemDate.AddDate(0, 0, 5)
+			} else if itemDate.Weekday() == 6 {
+				currTime = itemDate.AddDate(0, 0, 6)
+			} else {
+				currTime = itemDate.AddDate(0, 0, 5-int(itemDate.Weekday()))
+			}
+
+			yearVal, ok := tmpDateDataMap[currTime]
+			if ok {
+				tmpDateDataMap[currTime] = item.Value + yearVal
+			} else {
+				tmpDateList = append(tmpDateList, currTime)
+				tmpDateDataMap[currTime] = item.Value
+			}
+		}
+		for _, currTime := range tmpDateList {
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = tmpDateDataMap[currTime]
+		}
+	default:
+		err = errors.New("错误的频度")
+		return
+
+	}
+
+	// 数据计算
+	for _, currTime := range dateList {
+		tmpVal, ok2 := valueMap[currTime]
+		if !ok2 {
+			err = errors.New("数据异常,date:" + currTime.Format(utils.FormatDate))
+			return
+		}
+		var saveValue float64
+		if isWeekData { //周度指标转的话,最后结果要除以7
+			saveValue, _ = decimal.NewFromFloat(tmpVal).Div(decimal.NewFromInt(7)).Round(4).Float64()
+		} else {
+			saveValue, _ = decimal.NewFromFloat(tmpVal).Round(4).Float64()
+		}
+
+		dateDataMap[currTime] = saveValue
+	}
+
+	return
+}
+
+// LjzNczj
+// @Description:年初至今累计值计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 13:55:44
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) LjzNczj() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	dataList := obj.DataList
+	frequency := obj.Frequency         //需要变更的频度
+	fromFrequency := obj.FromFrequency //来源的频度
+
+	// 数据处理
+	var isWeekData bool // 是否周度数据,如果是周度数据的话,是需要变频的,最后结果还需要除以7
+	// 周度数据需要先变成日度的
+	if fromFrequency == `周度` {
+		isWeekData = true
+	}
+
+	fromEdbDataMap := make(map[time.Time]float64)
+	if isWeekData {
+		dataList, err = HandleDataByLinearRegressionByTime(dataList, fromEdbDataMap)
+		if err != nil {
+			return
+		}
+	}
+
+	//日度数据年初至今:日期同原日度数据。将每年1月1日(含)到日度数据所在日期含间的日度值,进行加总。
+	//周度数据年初至今:日期同原周度数据。将周度值转成日度频率,空值用插值法插值,然后算法同日度年度至今,再除以7
+	//月度/季度数据年初至今:日期同原月度/季度数据,将每年1月1日(含)到月度数据所在日期(含)之间的月度/季度值,进行加总
+	//以此类推
+
+	dateList := make([]time.Time, 0)
+	valueMap := make(map[time.Time]float64)
+	yearMap := make(map[int]float64)
+	switch frequency {
+	case "周度":
+		tmpDateDataMap := make(map[time.Time]float64)
+		tmpDateList := make([]time.Time, 0)
+		for _, item := range dataList {
+			itemDate := item.DataTime
+			var currTime time.Time
+			// 周六周日,这是下一个周五的数据
+			if itemDate.Weekday() == 0 {
+				currTime = itemDate.AddDate(0, 0, 5)
+			} else if itemDate.Weekday() == 6 {
+				currTime = itemDate.AddDate(0, 0, 6)
+			} else {
+				currTime = itemDate.AddDate(0, 0, 5-int(itemDate.Weekday()))
+			}
+
+			year := itemDate.Year()
+			yearVal, ok := yearMap[year]
+			if ok {
+				yearMap[year] = item.Value + yearVal
+			} else {
+				yearMap[year] = item.Value
+			}
+
+			if itemDate.Equal(currTime) {
+				tmpDateDataMap[itemDate] = yearMap[year]
+				tmpDateList = append(tmpDateList, itemDate)
+			}
+		}
+		for _, currTime := range tmpDateList {
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = tmpDateDataMap[currTime]
+		}
+	default:
+		for _, item := range dataList {
+			itemDate := item.DataTime
+			year := itemDate.Year()
+			yearVal, ok := yearMap[year]
+			if ok {
+				yearMap[year] = item.Value + yearVal
+			} else {
+				yearMap[year] = item.Value
+			}
+			valueMap[itemDate] = yearMap[year]
+			dateList = append(dateList, itemDate)
+		}
+
+	}
+
+	// 数据计算
+	for _, currTime := range dateList {
+		tmpVal, ok2 := valueMap[currTime]
+		if !ok2 {
+			err = errors.New("数据异常,date:" + currTime.Format(utils.FormatDate))
+			return
+		}
+		var saveValue float64
+		if isWeekData { //周度指标转的话,最后结果要除以7
+			saveValue, _ = decimal.NewFromFloat(tmpVal).Div(decimal.NewFromInt(7)).Round(4).Float64()
+		} else {
+			saveValue, _ = decimal.NewFromFloat(tmpVal).Round(4).Float64()
+		}
+
+		dateDataMap[currTime] = saveValue
+	}
+
+	return
+}
+
+// ExponentialSmoothing
+// @Description: 指数修匀计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 14:07:47
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) ExponentialSmoothing() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	dataList := obj.DataList
+	formula := obj.Formula.(string) // alpha值
+
+	alpha, _ := strconv.ParseFloat(formula, 64)
+	if alpha <= 0 || alpha >= 1 {
+		err = fmt.Errorf("alpha值有误: %v", alpha)
+		return
+	}
+
+	// 获取标准差图表的指标数据
+	fromDataList, err := calculateExponentialSmoothingData(dataList, alpha)
+	if err != nil {
+		return
+	}
+
+	// 数据计算
+	for _, tmpData := range fromDataList {
+		if tmpData.DataTime.IsZero() {
+			continue
+		}
+		// 当前的实际值
+		saveValue, _ := decimal.NewFromFloat(tmpData.Value).Round(4).Float64()
+
+		dateDataMap[tmpData.DataTime] = saveValue
+	}
+
+	return
+}
+
+// calculateExponentialSmoothingData
+// @Description: 计算指数修匀
+// @author: Roc
+// @datetime2023-11-03 14:05:41
+// @param dataList []*EdbInfoData 时间基准指标在时间区间内的值
+// @param strAlpha float64
+// @return newDataList []EdbInfoData
+// @return err error
+func calculateExponentialSmoothingData(dataList []*EdbInfoData, alpha float64) (newDataList []EdbInfoData, err error) {
+	if alpha <= 0 || alpha >= 1 {
+		err = fmt.Errorf("alpha值有误: %v", alpha)
+		return
+	}
+
+	var preVal float64
+	alphaDecimal := decimal.NewFromFloat(alpha)
+	subAlpha := decimal.NewFromFloat(1).Sub(alphaDecimal)
+	for k, d := range dataList {
+		// 首期的值以原始值作为指数修匀的计算值
+		if k == 0 {
+			newDataList = append(newDataList, EdbInfoData{
+				EdbDataId: k,
+				DataTime:  dataList[k].DataTime,
+				Value:     d.Value,
+			})
+			preVal = d.Value
+			continue
+		}
+
+		// 上一期的值参与计算
+		preDecimal := decimal.NewFromFloat(preVal)
+		valDecimal := decimal.NewFromFloat(d.Value)
+
+		partA := alphaDecimal.Mul(valDecimal)
+		partB := subAlpha.Mul(preDecimal)
+		res, _ := (partA.Add(partB)).Float64()
+		preVal = res
+		newDataList = append(newDataList, EdbInfoData{
+			EdbDataId: k,
+			DataTime:  dataList[k].DataTime,
+			Value:     res,
+		})
+	}
+	return
+}
+
+// Rjz
+// @Description: 日均值计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 14:47:47
+// @return dateDataMap map[time.Time]float64
+// @return err error
+func (obj BaseCalculate) Rjz() (dateDataMap map[time.Time]float64, err error, errMsg string) {
+	dateDataMap = make(map[time.Time]float64)
+	dataList := obj.DataList
+
+	fromFrequency := obj.FromFrequency
+	if fromFrequency == `` {
+		errMsg = "原指标的频度不能为空"
+		err = errors.New(errMsg)
+		return
+	}
+
+	if obj.FromFrequency == "日度" {
+		errMsg = "日度指标无需进行日均值计算"
+		err = errors.New(errMsg)
+		return
+	}
+
+	// 数据处理
+
+	// 数据降序
+	dataList = reverseSliceByDesc(dataList)
+
+	var dateArr []time.Time
+	dataMap := make(map[time.Time]*EdbInfoData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+
+	// 数据计算
+	for _, currentDate := range dateArr {
+		//当前日期
+		currentItem, ok := dataMap[currentDate]
+		if !ok {
+			continue
+		}
+
+		//根据频度计算需要均分的天数
+		days := GetRjzFrequencyDays(currentDate, fromFrequency)
+		val, ok := rjzDivV2(currentItem.Value, days)
+		if !ok {
+			continue
+		}
+
+		dateDataMap[currentDate] = val
+	}
+
+	return
+}
+
+// rjzDivV2
+// @Description: 日均值计算
+// @author: Roc
+// @datetime2023-11-03 14:47:36
+// @param a float64
+// @param b int
+// @return val float64
+// @return ok bool
+func rjzDivV2(a float64, b int) (val float64, ok bool) {
+	if b == 0 {
+		return
+	}
+
+	af := decimal.NewFromFloat(a)
+	bf := decimal.NewFromFloat(float64(b))
+	val, _ = af.Div(bf).Round(4).Float64()
+	ok = true
+
+	return
+}
+
+// reverseSliceByDesc
+// @Description: 倒转切片
+// @author: Roc
+// @datetime2023-11-06 14:08:25
+// @param slice []*EdbInfoData
+// @return []*EdbInfoData
+func reverseSliceByDesc(slice []*EdbInfoData) (newSlice []*EdbInfoData) {
+	// 只有一个数据的话,那么就直接返回
+	if len(slice) <= 1 {
+		newSlice = slice
+		return
+	}
+
+	if !slice[1].DataTime.After(slice[0].DataTime) {
+		newSlice = slice
+		return
+	}
+
+	newSlice = make([]*EdbInfoData, len(slice))
+	for i, j := 0, len(slice)-1; i < len(slice); i, j = i+1, j-1 {
+		newSlice[i] = slice[j]
+	}
+
+	return
+}
+
+// EdbInfoSearchDataToData
+// @Description: 将EdbInfoSearchData转成EdbInfoData
+// @author: Roc
+// @datetime2023-11-09 11:11:31
+// @param dataList []*EdbInfoSearchData
+// @return newDateDataList []*EdbInfoData
+// @return err error
+func EdbInfoSearchDataToData(dataList []*EdbInfoSearchData) (newDateDataList []*EdbInfoData, err error) {
+	newDateDataList = make([]*EdbInfoData, 0)
+
+	for _, data := range dataList {
+		dateTime, tmpErr := time.ParseInLocation(utils.FormatDate, data.DataTime, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+
+		newDateDataList = append(newDateDataList, &EdbInfoData{
+			EdbDataId: data.EdbDataId,
+			DataTime:  dateTime,
+			Value:     data.Value,
+		})
+	}
+
+	return
+}
+
+// GetDateDataAndDateList
+// @Description: 通过时间数据map 获取 时间字符串数据map和日期字符串切片
+// @author: Roc
+// @datetime2023-11-09 13:10:38
+// @param dateDataMap map[time.Time]float64
+// @return dateStrDataMap map[string]float64
+// @return dateStrList []string
+func GetDateDataAndDateList(dateDataMap map[time.Time]float64) (dateStrDataMap map[string]float64, dateStrList []string) {
+	dateStrDataMap = make(map[string]float64)
+	dateStrList = make([]string, 0)
+	dateList := make([]time.Time, 0)
+	for date, val := range dateDataMap {
+		dateStr := date.Format(utils.FormatDate)
+		dateStrDataMap[dateStr] = val
+		dateList = append(dateList, date)
+	}
+
+	// 使用 sort.Slice 对日期切片进行排序
+	sort.Slice(dateList, func(i, j int) bool {
+		return dateList[i].Before(dateList[j])
+	})
+
+	// 将日期排序后返回日期字符串切片
+	for _, v := range dateList {
+		dateStrList = append(dateStrList, v.Format(utils.FormatDate))
+	}
+
+	return
+}

+ 1 - 1
models/base_from_smm.go

@@ -79,7 +79,7 @@ func AddEdbDataFromSmm(edbCode string) (err error) {
 	return
 }
 
-// 刷新有色指标数据
+// RefreshEdbDataFromSmm 刷新有色指标数据
 func RefreshEdbDataFromSmm(edbInfoId int, edbCode, startDate string) (err error) {
 	source := utils.DATA_SOURCE_YS
 	o := orm.NewOrm()

+ 10 - 4
models/base_from_wind.go

@@ -22,10 +22,14 @@ func AddEdbDataFromWind(edbCode string, item *EdbDataFromWind) (err error) {
 	var isAdd bool
 	addSql := ` INSERT INTO edb_data_wind(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
 	for k, v := range item.Dt {
-		timeStr := fmt.Sprintf("%d", v)
-		v = v / 1000
+		//timeStr := fmt.Sprintf("%d", v)
+		//v = v / 1000
 		t := time.Unix(v, 0)
 		dateTime := t.Format(utils.FormatDate)
+		t, _ = time.ParseInLocation(utils.FormatDate, dateTime, time.Local) // 这里的目的是为了处理成北京时间,所以多转一遍
+		timestamp := t.UnixNano() / 1e6
+		timeStr := fmt.Sprintf("%d", timestamp)
+
 		val := item.Close[k]
 		saveVal := utils.SubFloatToString(val, 20)
 		addSql += GetAddSql("0", edbCode, dateTime, timeStr, saveVal)
@@ -85,11 +89,13 @@ func RefreshEdbDataFromWind(edbInfoId int, edbCode, startDate string, item *EdbD
 	addMap := make(map[string]string)
 	edbInfoIdStr := strconv.Itoa(edbInfoId)
 	for k, v := range item.Dt {
-		timeStr := fmt.Sprintf("%d", v)
-		v = v / 1000
+		//timeStr := fmt.Sprintf("%d", v)
+		//v = v / 1000
 		t := time.Unix(v, 0)
 		dateTime := t.Format(utils.FormatDate)
 		t, _ = time.ParseInLocation(utils.FormatDate, dateTime, time.Local) // 这里的目的是为了处理成北京时间,所以多转一遍
+		timestamp := t.UnixNano() / 1e6
+		timeStr := fmt.Sprintf("%d", timestamp)
 
 		val := item.Close[k]
 		saveVal := utils.SubFloatToString(val, 30)

+ 0 - 3
models/edb_data_calculate_hcz.go

@@ -330,9 +330,6 @@ func refreshAllCalculateHcz(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo *
 
 // HczDiv 环差值计算,current:当期,pre:上期 公式:当期-上期
 func HczDiv(current, pre float64) string {
-	if pre == 0 {
-		return ""
-	}
 	currentVal := decimal.NewFromFloat(current)
 	preVal := decimal.NewFromFloat(pre)
 	val, _ := currentVal.Sub(preVal).Float64()

+ 2 - 2
models/edb_data_calculate_rjz.go

@@ -256,7 +256,7 @@ func refreshAllCalculateRjz(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo *
 				return err
 			}
 			//根据频度计算需要均分的天数
-			days, err := GetRjzFrequencyDays(currentDate, fromEdbInfo.Frequency)
+			days := GetRjzFrequencyDays(currentDate, fromEdbInfo.Frequency)
 			val := rjzDiv(currentItem.Value, days)
 
 			timestamp := currentDate.UnixNano() / 1e6
@@ -290,7 +290,7 @@ func refreshAllCalculateRjz(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo *
 	}
 	return
 }
-func GetRjzFrequencyDays(currDate time.Time, frequency string) (days int, err error) {
+func GetRjzFrequencyDays(currDate time.Time, frequency string) (days int) {
 	switch frequency {
 	case "周度", "周":
 		days = 7

+ 2 - 0
models/edb_info.go

@@ -1061,6 +1061,8 @@ type AddEdbInfoParams struct {
 	Unit         string `description:"单位"`
 	ClassifyId   int    `description:"分类id"`
 	TerminalCode string `description:"终端编码"`
+	AdminId      int    `description:"创建人ID"`
+	AdminName    string `description:"创建人姓名"`
 }
 
 // EdbInfoAdd 添加指标到指标库

+ 90 - 0
models/handle_data.go

@@ -139,3 +139,93 @@ func HandleDataByPreviousData(edbInfoDataList []*EdbInfoSearchData, handleDataMa
 
 	return
 }
+
+// HandleDataByLinearRegressionByTime 插值法补充数据(线性方程式) 时间为日期格式,而不是字符串
+func HandleDataByLinearRegressionByTime(edbInfoDataList []*EdbInfoData, handleDataMap map[time.Time]float64) (newList []*EdbInfoData, err error) {
+	if len(edbInfoDataList) < 2 {
+		return
+	}
+
+	var startEdbInfoData *EdbInfoData
+	for _, v := range edbInfoDataList {
+		handleDataMap[v.DataTime] = v.Value
+
+		// 第一个数据就给过滤了,给后面的试用
+		if startEdbInfoData == nil {
+			startEdbInfoData = v
+			newList = append(newList, &EdbInfoData{
+				EdbDataId: v.EdbDataId,
+				DataTime:  v.DataTime,
+				Value:     v.Value,
+			})
+			continue
+		}
+
+		// 获取两条数据之间相差的天数
+		startDataTime := startEdbInfoData.DataTime
+		currDataTime := v.DataTime
+		betweenHour := int(currDataTime.Sub(startDataTime).Hours())
+		betweenDay := betweenHour / 24
+
+		// 如果相差一天,那么过滤
+		if betweenDay <= 1 {
+			startEdbInfoData = v
+			newList = append(newList, &EdbInfoData{
+				EdbDataId: v.EdbDataId,
+				DataTime:  v.DataTime,
+				Value:     v.Value,
+			})
+			continue
+		}
+
+		// 生成线性方程式
+		var a, b float64
+		{
+			coordinateData := make([]utils.Coordinate, 0)
+			tmpCoordinate1 := utils.Coordinate{
+				X: 1,
+				Y: startEdbInfoData.Value,
+			}
+			coordinateData = append(coordinateData, tmpCoordinate1)
+			tmpCoordinate2 := utils.Coordinate{
+				X: float64(betweenDay) + 1,
+				Y: v.Value,
+			}
+			coordinateData = append(coordinateData, tmpCoordinate2)
+
+			a, b = utils.GetLinearResult(coordinateData)
+			if math.IsNaN(a) || math.IsNaN(b) {
+				err = errors.New("线性方程公式生成失败")
+				return
+			}
+		}
+
+		// 生成对应的值
+		{
+			for i := 1; i < betweenDay; i++ {
+				tmpDataTime := startDataTime.AddDate(0, 0, i)
+				aDecimal := decimal.NewFromFloat(a)
+				xDecimal := decimal.NewFromInt(int64(i) + 1)
+				bDecimal := decimal.NewFromFloat(b)
+
+				val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
+				handleDataMap[tmpDataTime] = val
+				newList = append(newList, &EdbInfoData{
+					DataTime: tmpDataTime,
+					Value:    val,
+				})
+			}
+		}
+
+		// 最后将自己赋值
+		newList = append(newList, &EdbInfoData{
+			EdbDataId: v.EdbDataId,
+			DataTime:  v.DataTime,
+			Value:     v.Value,
+		})
+
+		startEdbInfoData = v
+	}
+
+	return
+}

+ 9 - 0
routers/commentsRouter.go

@@ -97,6 +97,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_index_lib/controllers:CalculateController"] = append(beego.GlobalControllerRouter["eta/eta_index_lib/controllers:CalculateController"],
+        beego.ControllerComments{
+            Method: "Calculate",
+            Router: `/base`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_index_lib/controllers:CalculateController"] = append(beego.GlobalControllerRouter["eta/eta_index_lib/controllers:CalculateController"],
         beego.ControllerComments{
             Method: "BatchEdit",

+ 17 - 9
services/base_from_jiayue.go

@@ -303,7 +303,8 @@ func SyncJiaYueNewIndex(item models.BridgeJiaYueIndexAndData, menus []models.Bri
 	addParams.Unit = item.Unit
 	addParams.ClassifyId = classify.ClassifyId
 	addParams.Source = sourceId
-	edbInfo, e := models.EdbInfoAdd(addParams, "", 0, "")
+	adminId, _ := strconv.Atoi(utils.InitAdminId)
+	edbInfo, e := models.EdbInfoAdd(addParams, "", adminId, utils.InitAdminName)
 	if e != nil {
 		err = fmt.Errorf("EdbInfoAdd err: %s", e.Error())
 		return
@@ -332,14 +333,21 @@ func SyncJiaYueNewIndex(item models.BridgeJiaYueIndexAndData, menus []models.Bri
 // TransJiaYueFrequency 频度转换
 func TransJiaYueFrequency(origin string) string {
 	mapping := map[string]string{
-		"日":  "日度",
-		"周":  "周度",
-		"旬":  "旬度",
-		"半月": "旬度",
-		"月":  "月度",
-		"季":  "季度",
-		"半年": "半年度",
-		"年":  "年度",
+		"日":   "日度",
+		"周":   "周度",
+		"旬":   "旬度",
+		"半月":  "旬度",
+		"月":   "月度",
+		"季":   "季度",
+		"半年":  "半年度",
+		"年":   "年度",
+		"日度":  "日度",
+		"周度":  "周度",
+		"旬度":  "旬度",
+		"月度":  "月度",
+		"季度":  "季度",
+		"半年度": "半年度",
+		"年度":  "年度",
 	}
 	return mapping[origin]
 }

+ 7 - 0
services/base_from_smm.go

@@ -98,6 +98,13 @@ func SmmIndexHandle(baseFilePath, renameFilePath, indexName, indexCode, unit, fr
 		updateParams["interface"] = source
 		updateParams["modify_time"] = time.Now()
 
+		if baseFilePath != `` && item.BaseFileName != baseFilePath {
+			updateParams["base_file_name"] = baseFilePath
+		}
+		if renameFilePath != `` && item.RenameFileName != renameFilePath {
+			updateParams["rename_file_name"] = renameFilePath
+		}
+
 		whereParam := make(map[string]interface{})
 		whereParam["index_code"] = indexCode
 

+ 18 - 47
utils/logs.go

@@ -3,8 +3,6 @@ package utils
 import (
 	"encoding/json"
 	"github.com/beego/beego/v2/core/logs"
-	"github.com/sirupsen/logrus"
-	"gopkg.in/natefinch/lumberjack.v2"
 	"os"
 	"path"
 )
@@ -15,8 +13,8 @@ const (
 	DefaultApiLogPath = "./etalogs/apilog"
 )
 
-var FileLog = logrus.New()
-var ApiLog = logrus.New()
+var FileLog *logs.BeeLogger
+var ApiLog *logs.BeeLogger
 var Binlog *logs.BeeLogger
 
 func init() {
@@ -35,21 +33,14 @@ func init() {
 
 	// 打开文件
 	logFileName := path.Join(logPath, logFile)
-	logConf := getDefaultLogrusConfig(logFileName)
-	// 使用滚动压缩方式记录日志
-	rolling(FileLog, logConf)
-	//rolling(bLogFileName)
-	// 设置日志输出JSON格式
-	jsonFormat := new(logrus.JSONFormatter)
-	jsonFormat.DisableHTMLEscape = true
-	jsonFormat.TimestampFormat = HlbFormatDateTime
-	FileLog.SetFormatter(jsonFormat)
-	FileLog.SetReportCaller(true)
-	//LogInstance.SetFormatter(&logrus.TextFormatter{})
-	// 设置日志记录级别
-	//FileLog.SetLevel(logrus.DebugLevel)
+	FileLog = logs.NewLogger(1000000)
+	logConf := getDefaultLogConfig()
+
+	logConf.FileName = logFileName
+	b, _ := json.Marshal(logConf)
+	FileLog.SetLogger(logs.AdapterFile, string(b))
+	FileLog.EnableFuncCallDepth(true)
 
-	//FileLog.Info("abc")
 	initBinlog()
 	initApiLog()
 }
@@ -83,8 +74,8 @@ func initBinlog() {
 	logConf := getDefaultLogConfig()
 
 	logConf.FileName = logFileName
-	logConf.MaxLines = 10000000
-	logConf.Rotate = true
+	//logConf.MaxLines = 10000000
+	//logConf.Rotate = true
 	b, _ := json.Marshal(logConf)
 	Binlog.SetLogger(logs.AdapterFile, string(b))
 	Binlog.EnableFuncCallDepth(true)
@@ -103,39 +94,19 @@ func initApiLog() {
 
 	// 打开文件
 	logFileName := path.Join(logPath, logFile)
-	logConf := getDefaultLogrusConfig(logFileName)
-	// 使用滚动压缩方式记录日志
-	rolling(ApiLog, logConf)
-	//rolling(bLogFileName)
-	// 设置日志输出JSON格式
-	jsonFormat := new(logrus.JSONFormatter)
-	jsonFormat.DisableHTMLEscape = true
-	jsonFormat.TimestampFormat = HlbFormatDateTime
-	ApiLog.SetFormatter(jsonFormat)
-}
-
-// 日志滚动设置
-func rolling(fLog *logrus.Logger, config *lumberjack.Logger) {
-	// 设置输出
-	fLog.SetOutput(config)
-}
+	ApiLog = logs.NewLogger(1000000)
+	logConf := getDefaultLogConfig()
 
-func getDefaultLogrusConfig(logFile string) (config *lumberjack.Logger) {
-	config = &lumberjack.Logger{
-		Filename:   logFile,    //日志文件位置
-		MaxSize:    256,        // 单文件最大容量,单位是MB
-		MaxBackups: 0,          // 最大保留过期文件个数
-		MaxAge:     LogMaxDays, // 保留过期文件的最大时间间隔,单位是天
-		Compress:   true,       // 是否需要压缩滚动日志, 使用的 gzip 压缩
-		LocalTime:  true,
-	}
-	return
+	logConf.FileName = logFileName
+	b, _ := json.Marshal(logConf)
+	ApiLog.SetLogger(logs.AdapterFile, string(b))
+	ApiLog.EnableFuncCallDepth(true)
 }
 
 func getDefaultLogConfig() logConfig {
 	return logConfig{
 		FileName: "",
-		MaxLines: 0,
+		MaxLines: 10000000,
 		MaxSize:  1 << 28,
 		Daily:    true,
 		MaxDays:  LogMaxDays, //我就是喜欢31天,咋滴,不喜欢你就自己改-_-!