Ver Fonte

feat:新增滚动相关性图表

Roc há 2 anos atrás
pai
commit
bd7f1961c6

+ 66 - 22
controllers/chart_common.go

@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"hongze/hongze_chart_lib/models"
 	"hongze/hongze_chart_lib/models/data_manage"
+	"hongze/hongze_chart_lib/services/data"
 	correlationServ "hongze/hongze_chart_lib/services/data/correlation"
 	future_goodServ "hongze/hongze_chart_lib/services/data/future_good"
 	"hongze/hongze_chart_lib/utils"
@@ -309,18 +310,6 @@ func GetCorrelationChartInfoDetailFromUniqueCode(chartInfo *models.ChartInfo, ke
 		return
 	}
 	//chartInfo.CorrelationLeadUnit = correlationChart.LeadUnit
-	xData := make([]int, 0)
-	yData := make([]float64, 0)
-	if e := json.Unmarshal([]byte(correlationChart.PeriodData), &xData); e != nil {
-		msg = "获取失败"
-		errMsg = "相关性图表X轴数据有误, Err:" + e.Error()
-		return
-	}
-	if e := json.Unmarshal([]byte(correlationChart.CorrelationData), &yData); e != nil {
-		msg = "获取失败"
-		errMsg = "相关性图表X轴数据有误, Err:" + e.Error()
-		return
-	}
 
 	// 获取指标信息
 	edbInfoMappingA, e := models.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdFirst)
@@ -336,13 +325,60 @@ func GetCorrelationChartInfoDetailFromUniqueCode(chartInfo *models.ChartInfo, ke
 		return
 	}
 
-	xEdbIdValue := xData
-	yDataList := make([]models.YData, 0)
-	yDate := "0000-00-00"
-	yDataList = append(yDataList, models.YData{
-		Date:  yDate,
-		Value: yData,
-	})
+	var dataResp interface{} // 绘图数据返回(目前是滚动相关性的图)
+	var xEdbIdValue []int
+	var xDateTimeValue []string
+	var yDataList []models.YData
+	switch chartInfo.Source {
+	case utils.CHART_SOURCE_CORRELATION: // 相关性图
+		moveUnitDays, ok := utils.FrequencyDaysMap[correlationChart.CalculateUnit]
+		if !ok {
+			msg = "错误的分析周期"
+			errMsg = "相关性图表数据有误"
+			return
+		}
+		startDate := time.Now().AddDate(0, 0, -correlationChart.CalculateValue*moveUnitDays).Format(utils.FormatDate)
+		endDate := time.Now().Format(utils.FormatDate)
+
+		xEdbIdValue, yDataList, e = correlationServ.GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, startDate, endDate)
+		if e != nil {
+			msg = "获取失败"
+			errMsg = "获取相关性图表, 图表计算值失败, Err:" + e.Error()
+			return
+		}
+	case utils.CHART_SOURCE_ROLLING_CORRELATION: // 滚动相关性图
+		multipleGraphConfigChartMapping, e := data_manage.GetMultipleGraphConfigChartMappingByChartId(chartInfo.ChartInfoId)
+		if e != nil {
+			msg = "获取失败"
+			errMsg = "获取滚动相关性图表的配置信息失败, Err:" + e.Error()
+			return
+		}
+		baseChartMultipleGraphConfigChartMapping, e := data_manage.GetMultipleGraphConfigChartMappingByIdAndSource(multipleGraphConfigChartMapping.MultipleGraphConfigId, 2)
+		if e != nil {
+			msg = "获取失败"
+			errMsg = "获取相关性图表的配置信息失败, Err:" + e.Error()
+			return
+		}
+		baseChartCorrelationChart := new(data_manage.ChartInfoCorrelation)
+		if e := baseChartCorrelationChart.GetItemById(baseChartMultipleGraphConfigChartMapping.ChartInfoId); e != nil {
+			msg = "获取失败"
+			errMsg = "获取基础相关性图表信息失败, Err:" + e.Error()
+			return
+		}
+		moveUnitDays, ok := utils.FrequencyDaysMap[baseChartCorrelationChart.CalculateUnit]
+		if !ok {
+			msg = "错误的分析周期"
+			errMsg = "错误的分析周期"
+			return
+		}
+		startDate := time.Now().AddDate(0, 0, -baseChartCorrelationChart.CalculateValue*moveUnitDays).Format(utils.FormatDate)
+		endDate := time.Now().Format(utils.FormatDate)
+		xDateTimeValue, yDataList, e = correlationServ.GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, correlationChart.CalculateValue, correlationChart.CalculateUnit, startDate, endDate)
+		dataResp = models.RollingCorrelationChartDataResp{
+			XDateTimeValue: xDateTimeValue,
+			YDataList:      yDataList,
+		}
+	}
 
 	// 完善指标信息
 	edbList, e := correlationServ.GetChartEdbInfoFormat(chartInfo.ChartInfoId, edbInfoMappingA, edbInfoMappingB)
@@ -365,6 +401,7 @@ func GetCorrelationChartInfoDetailFromUniqueCode(chartInfo *models.ChartInfo, ke
 	resp.XEdbIdValue = xEdbIdValue
 	resp.YDataList = yDataList
 	resp.CorrelationChartInfo = correlationInfo
+	resp.DataResp = dataResp
 
 	// 将数据加入缓存
 	if utils.Re == nil {
@@ -417,13 +454,20 @@ func (this *ChartController) CorrelationChartInfoRefresh() {
 	}
 	chartId = chartInfo.ChartInfoId
 
-	// 刷新相关性图表
-	if e := correlationServ.ChartInfoRefresh(chartInfo.ChartInfoId); e != nil {
+	err = data.ChartInfoRefreshV2(chartInfo.ChartInfoId)
+	if err != nil {
 		br.Msg = "刷新失败"
-		br.ErrMsg = "刷新相关性图表失败, Err:" + e.Error()
+		br.ErrMsg = "刷新图表关联指标信息失败,Err:" + err.Error()
 		return
 	}
 
+	//// 刷新相关性图表
+	//if e := correlationServ.ChartInfoRefresh(chartInfo.ChartInfoId); e != nil {
+	//	br.Msg = "刷新失败"
+	//	br.ErrMsg = "刷新相关性图表失败, Err:" + e.Error()
+	//	return
+	//}
+
 	//清除数据缓存
 	key := utils.HZ_CHART_LIB_DETAIL + uniqueCode
 	if utils.Re == nil {

+ 6 - 0
models/chart.go

@@ -182,6 +182,12 @@ type YData struct {
 	XEdbInfoIdList []int     `description:"对应X轴的指标id列表"`
 }
 
+// RollingCorrelationChartDataResp 滚动相关性图
+type RollingCorrelationChartDataResp struct {
+	XDateTimeValue []string `description:"滚动相关性图的x轴数据,日期数据"`
+	YDataList      []YData  `description:"滚动相关性图的y轴数据"`
+}
+
 // 指标季度数据计算(公历转农历)
 func AddCalculateQuarterV5(dataList []*EdbDataList) (result *EdbDataResult, err error) {
 	var errMsg string

+ 2 - 0
models/data_manage/chart_info_correlation.go

@@ -12,6 +12,8 @@ type ChartInfoCorrelation struct {
 	CorrelationChartInfoId int       `orm:"column(correlation_chart_info_id);pk" description:"相关性图表ID(chart_info表source=3的)"`
 	LeadValue              int       `description:"领先值"`
 	LeadUnit               string    `description:"领先单位"`
+	CalculateValue         int       `description:"计算窗口"`
+	CalculateUnit          string    `description:"计算频度"`
 	StartDate              time.Time `description:"开始日期"`
 	EndDate                time.Time `description:"结束日期"`
 	EdbInfoIdFirst         int       `description:"A指标ID"`

+ 79 - 0
models/data_manage/multiple_graph_config.go

@@ -0,0 +1,79 @@
+package data_manage
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// MultipleGraphConfig 多图配置表
+type MultipleGraphConfig struct {
+	MultipleGraphConfigId int       `orm:"column(multiple_graph_config_id);pk"`
+	EdbInfoIdA            int       `description:"指标A"`
+	EdbInfoIdB            int       `description:"指标B"`
+	Curve                 string    `description:"曲线图配置"`
+	Correlation           string    `description:"相关性配置"`
+	RollingCorrelation    string    `description:"滚动相关性配置"`
+	SysUserId             int       `description:"操作人id"`
+	SysUserRealName       string    `description:"操作人真实姓名"`
+	ModifyTime            time.Time `description:"最近一次修改时间"`
+	CreateTime            time.Time `description:"添加时间"`
+}
+
+// AddMultipleGraphConfig 新增多图配置
+func AddMultipleGraphConfig(item *MultipleGraphConfig) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	// 表格信息入库
+	lastId, err := o.Insert(item)
+	if err != nil {
+		return
+	}
+	item.MultipleGraphConfigId = int(lastId)
+	return
+}
+
+// Update 更新 基础信息
+func (item *MultipleGraphConfig) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(item, cols...)
+	return
+}
+
+// GetMultipleGraphConfigById 根据配置id获取配置
+func GetMultipleGraphConfigById(id int) (item *MultipleGraphConfig, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM multiple_graph_config WHERE multiple_graph_config_id = ? `
+	// 表格信息入库
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+// CurveConfig 曲线图配置
+type CurveConfig struct {
+	DateType    int     `description:"日期类型:1:00年至今,2:10年至今,3:15年至今,4:年初至今,5:自定义时间"`
+	StartDate   string  `description:"自定义开始日期"`
+	EndDate     string  `description:"自定义结束日期"`
+	LeftMin     float64 `description:"图表左侧最小值"`
+	LeftMax     float64 `description:"图表左侧最大值"`
+	RightMin    float64 `description:"图表右侧最小值"`
+	RightMax    float64 `description:"图表右侧最大值"`
+	IsOrder     bool    `description:"true:正序,false:逆序"`
+	EdbInfoType bool    `description:"true:标准指标,false:领先指标"`
+	LeadValue   int     `description:"领先值"`
+	LeadUnit    string  `description:"领先单位"`
+}
+
+// CorrelationConfig 相关性配置
+type CorrelationConfig struct {
+	LeadValue      int    `description:"领先期数"`
+	LeadUnit       string `description:"频度"`
+	CalculateValue int    `description:"计算窗口"`
+	CalculateUnit  string `description:"计算频度"`
+}
+
+// RollingCorrelationConfig 滚动相关性配置
+type RollingCorrelationConfig struct {
+	LeadValue      int    `description:"领先期数"`
+	LeadUnit       string `description:"频度"`
+	CalculateValue int    `description:"计算窗口"`
+	CalculateUnit  string `description:"计算频度"`
+}

+ 62 - 0
models/data_manage/multiple_graph_config_chart_mapping.go

@@ -0,0 +1,62 @@
+package data_manage
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// MultipleGraphConfigChartMapping 图表与多图配置的关系表
+type MultipleGraphConfigChartMapping struct {
+	Id                    int       `orm:"column(id);pk"`
+	MultipleGraphConfigId int       `description:"多图配置id"`
+	ChartInfoId           int       `description:"图表id"`
+	Source                int       `description:"来源,1:曲线图,2:相关性图;3:滚动相关性图1;4:滚动相关性图2;"`
+	ModifyTime            time.Time `description:"最近一次修改时间"`
+	CreateTime            time.Time `description:"添加时间"`
+}
+
+// AddMultipleGraphConfigChartMapping 新增多图配置
+func AddMultipleGraphConfigChartMapping(item *MultipleGraphConfigChartMapping) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	// 表格信息入库
+	lastId, err := o.Insert(item)
+	if err != nil {
+		return
+	}
+	item.Id = int(lastId)
+	return
+}
+
+// Update 更新 基础信息
+func (item *MultipleGraphConfigChartMapping) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(item, cols...)
+	return
+}
+
+// GetMultipleGraphConfigChartMappingByIdAndSource 根据配置id和来源获取关联关系
+func GetMultipleGraphConfigChartMappingByIdAndSource(configId, source int) (item *MultipleGraphConfigChartMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM multiple_graph_config_chart_mapping WHERE multiple_graph_config_id = ? AND source = ? `
+	err = o.Raw(sql, configId, source).QueryRow(&item)
+
+	return
+}
+
+// GetMultipleGraphConfigChartMappingByChartId 根据图表id和来源获取关联关系
+func GetMultipleGraphConfigChartMappingByChartId(chartId int) (item *MultipleGraphConfigChartMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM multiple_graph_config_chart_mapping WHERE chart_info_id = ?  `
+	err = o.Raw(sql, chartId).QueryRow(&item)
+
+	return
+}
+
+// GetMultipleGraphConfigChartMappingListById 根据配置id获取所有关联关系
+func GetMultipleGraphConfigChartMappingListById(configId int) (items []*MultipleGraphConfigChartMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM multiple_graph_config_chart_mapping WHERE multiple_graph_config_id = ? `
+	_, err = o.Raw(sql, configId).QueryRows(&items)
+
+	return
+}

+ 53 - 0
models/data_manage/multiple_graph_config_edb_mapping.go

@@ -0,0 +1,53 @@
+package data_manage
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// MultipleGraphConfigEdbMapping 指标与多图配置的关系表
+type MultipleGraphConfigEdbMapping struct {
+	Id                    int       `orm:"column(id);pk"`
+	MultipleGraphConfigId int       `description:"多图配置id"`
+	EdbInfoId             int       `description:"指标id"`
+	Source                int       `description:"来源,1:曲线图,2:相关性图;3:滚动相关性图1;4:滚动相关性图2;"`
+	ModifyTime            time.Time `description:"最近一次修改时间"`
+	CreateTime            time.Time `description:"添加时间"`
+}
+
+// AddMultipleGraphConfigEdbMapping 新增多图配置
+func AddMultipleGraphConfigEdbMapping(item *MultipleGraphConfigEdbMapping) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	// 表格信息入库
+	lastId, err := o.Insert(item)
+	if err != nil {
+		return
+	}
+	item.Id = int(lastId)
+	return
+}
+
+// Update 更新 基础信息
+func (item *MultipleGraphConfigEdbMapping) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(item, cols...)
+	return
+}
+
+// GetMultipleGraphConfigEdbMappingByIdAndSource 根据配置id和来源获取关联关系
+func GetMultipleGraphConfigEdbMappingByIdAndSource(configId, source int) (item *MultipleGraphConfigEdbMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM multiple_graph_config_edb_mapping WHERE multiple_graph_config_id = ? AND source = ? `
+	// 表格信息入库
+	err = o.Raw(sql, configId, source).QueryRow(&item)
+	return
+}
+
+// GetMultipleGraphConfigEdbMappingListById 根据配置id获取所有关联关系
+func GetMultipleGraphConfigEdbMappingListById(configId int) (items []*MultipleGraphConfigEdbMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM multiple_graph_config_edb_mapping WHERE multiple_graph_config_id = ? `
+	_, err = o.Raw(sql, configId).QueryRows(&items)
+
+	return
+}

+ 151 - 67
services/data/correlation/chart_info.go

@@ -1,13 +1,10 @@
 package correlation
 
 import (
-	"encoding/json"
 	"errors"
 	"fmt"
 	"github.com/shopspring/decimal"
 	"hongze/hongze_chart_lib/models"
-	"hongze/hongze_chart_lib/models/data_manage"
-	"hongze/hongze_chart_lib/services/alarm_msg"
 	"hongze/hongze_chart_lib/services/data"
 	"hongze/hongze_chart_lib/utils"
 	"math"
@@ -205,38 +202,85 @@ func GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *models.ChartEdbInfo
 		}
 	}
 
-	// 2023-03-02 时间序列始终以指标B为基准, 始终是A进行平移
-	baseEdbInfo := edbInfoMappingB
-	changeEdbInfo := edbInfoMappingA
+	//// 2023-03-02 时间序列始终以指标B为基准, 始终是A进行平移
+	//baseEdbInfo := edbInfoMappingB
+	//changeEdbInfo := edbInfoMappingA
+	// 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
+	baseEdbInfo := edbInfoMappingA
+	changeEdbInfo := edbInfoMappingB
 
 	// 获取时间基准指标在时间区间内的值
-	baseDataList := make([]*models.EdbDataList, 0)
+	aDataList := make([]*models.EdbDataList, 0)
 	switch baseEdbInfo.EdbInfoCategoryType {
 	case 0:
-		baseDataList, err = models.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.EdbInfoId, startDate, endDate)
+		aDataList, err = models.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.EdbInfoId, startDate, endDate)
 	case 1:
-		_, baseDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
+		_, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
 	default:
 		err = errors.New("指标base类型异常")
 		return
 	}
 
 	// 获取变频指标所有日期的值, 插值法完善数据
-	changeDataList := make([]*models.EdbDataList, 0)
+	bDataList := make([]*models.EdbDataList, 0)
 	switch changeEdbInfo.EdbInfoCategoryType {
 	case 0:
-		changeDataList, err = models.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.EdbInfoId, "", "")
+		bDataList, err = models.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.EdbInfoId, "", "")
 	case 1:
-		_, changeDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
+		_, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
 	default:
 		err = errors.New("指标change类型异常")
 		return
 	}
+	//changeDataMap := make(map[string]float64)
+	//newChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
+	//if e != nil {
+	//	err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+	//	return
+	//}
+
+	// 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
+	baseDataList := make([]*models.EdbDataList, 0)
+	changeDataList := make([]*models.EdbDataList, 0)
 	changeDataMap := make(map[string]float64)
-	newChangeDataList, e := HandleDataByLinearRegression(changeDataList, changeDataMap)
-	if e != nil {
-		err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
-		return
+
+	// 先把低频指标升频为高频
+	{
+		frequencyIntMap := map[string]int{
+			"日度": 1,
+			"周度": 2,
+			"旬度": 3,
+			"月度": 4,
+			"季度": 5,
+			"年度": 6,
+		}
+
+		// 如果A指标是高频,那么就需要对B指标进行升频
+		if frequencyIntMap[edbInfoMappingA.Frequency] < frequencyIntMap[edbInfoMappingB.Frequency] {
+			aDataMap := make(map[string]float64)
+			tmpNewChangeDataList, e := HandleDataByLinearRegression(aDataList, aDataMap)
+			if e != nil {
+				err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+				return
+			}
+			baseDataList = tmpNewChangeDataList
+		} else {
+			baseDataList = aDataList
+		}
+		// 如果B指标是高频,那么就需要对A指标进行升频
+		if frequencyIntMap[edbInfoMappingA.Frequency] > frequencyIntMap[edbInfoMappingB.Frequency] {
+			tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
+			if e != nil {
+				err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+				return
+			}
+			changeDataList = tmpNewChangeDataList
+		} else {
+			changeDataList = bDataList
+			for _, v := range baseDataList {
+				changeDataMap[v.DataTime] = v.Value
+			}
+		}
 	}
 
 	// 计算不领先也不滞后时的相关系数
@@ -262,10 +306,7 @@ func GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *models.ChartEdbInfo
 	// 计算领先/滞后N期
 	if leadValue > 0 {
 		// 平移变频指标领先/滞后的日期(单位天)
-		frequencyDaysMap := map[string]float64{
-			"天": 1, "周": 7, "月": 30, "季": 90, "年": 365,
-		}
-		moveUnitDays := frequencyDaysMap[leadUnit]
+		moveUnitDays := utils.FrequencyDaysMap[leadUnit]
 
 		for i := range xData {
 			if xData[i] == 0 {
@@ -274,9 +315,9 @@ func GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *models.ChartEdbInfo
 			}
 			yCalculateData := make([]float64, 0)
 
-			// 判断是向前平移还是向后平移
+			// 平移指定天数
 			mDays := int(moveUnitDays) * xData[i]
-			_, dMap := MoveDataDaysToNewDataList(newChangeDataList, mDays)
+			_, dMap := MoveDataDaysToNewDataList(changeDataList, mDays)
 
 			// 取出对应的基准日期的值
 			for i2 := range baseDataTimeArr {
@@ -303,59 +344,102 @@ func GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *models.ChartEdbInfo
 	return
 }
 
-// ChartInfoRefresh 图表刷新
-func ChartInfoRefresh(chartInfoId int) (err error) {
-	var errMsg string
-	defer func() {
-		if err != nil {
-			go alarm_msg.SendAlarmMsg("CorrelationChartInfoRefresh: "+errMsg, 3)
-		}
-	}()
-	correlationChart := new(data_manage.ChartInfoCorrelation)
-	if err = correlationChart.GetItemById(chartInfoId); err != nil {
-		errMsg = "获取相关性图表失败, Err: " + err.Error()
-		return
-	}
+// GetRollingCorrelationChartDataByEdbInfo 滚动相关性计算
+func GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *models.ChartEdbInfoMapping, leadValue int, leadUnit string, calculateValue int, calculateUnit string, startDate, endDate string) (xDateTimeValue []string, yDataList []models.YData, err error) {
+	xDateTimeValue = make([]string, 0)
+	yData := make([]float64, 0)
 
-	// 批量刷新ETA指标
-	err, errMsg = data.EdbInfoRefreshAllFromBase([]int{correlationChart.EdbInfoIdFirst, correlationChart.EdbInfoIdSecond}, false)
-	if err != nil {
-		return
-	}
+	baseEdbInfo := edbInfoMappingA
+	changeEdbInfo := edbInfoMappingB
 
-	// 重新生成数据并更新
-	edbInfoMappingA, err := models.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdFirst)
-	if err != nil {
-		errMsg = "获取相关性图表, A指标mapping信息失败, Err:" + err.Error()
-		return
-	}
-	edbInfoMappingB, err := models.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdSecond)
-	if err != nil {
-		errMsg = "获取相关性图表, B指标mapping信息失败, Err:" + err.Error()
+	// 获取时间基准指标在时间区间内的值
+	aDataList := make([]*models.EdbDataList, 0)
+	switch baseEdbInfo.EdbInfoCategoryType {
+	case 0:
+		aDataList, err = models.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.EdbInfoId, startDate, endDate)
+	case 1:
+		_, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
+	default:
+		err = errors.New("指标base类型异常")
 		return
 	}
-	periodData, correlationData, err := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, correlationChart.StartDate.Format(utils.FormatDate), correlationChart.EndDate.Format(utils.FormatDate))
-	if err != nil {
-		errMsg = "获取相关性图表, 图表计算值失败, Err:" + err.Error()
+
+	// 获取变频指标所有日期的值, 插值法完善数据
+	bDataList := make([]*models.EdbDataList, 0)
+	switch changeEdbInfo.EdbInfoCategoryType {
+	case 0:
+		bDataList, err = models.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.EdbInfoId, "", "")
+	case 1:
+		_, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
+	default:
+		err = errors.New("指标change类型异常")
 		return
 	}
-	periodDataByte, err := json.Marshal(periodData)
-	if err != nil {
-		errMsg = "相关性图表, X轴信息有误, Err:" + err.Error()
-		return
+
+	// 数据平移变频指标领先/滞后的日期(单位天)
+	// 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
+	//baseDataList := make([]*models.EdbDataList, 0)
+	baseDataMap := make(map[string]float64)
+	changeDataList := make([]*models.EdbDataList, 0)
+	changeDataMap := make(map[string]float64)
+
+	// A指标不管三七二十一,先变个频再说
+	{
+		_, e := HandleDataByLinearRegression(aDataList, baseDataMap)
+		if e != nil {
+			err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+			return
+		}
+		//baseDataList = tmpNewChangeDataList
 	}
-	correlationDataByte, err := json.Marshal(correlationData[0].Value)
-	if err != nil {
-		errMsg = "相关性图表, Y轴信息有误, Err:" + err.Error()
-		return
+	// A指标不管三七二十一,先变个频再说
+	{
+		tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
+		if e != nil {
+			err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+			return
+		}
+		changeDataList = tmpNewChangeDataList
+
+		// 平移下日期
+		moveUnitDays := utils.FrequencyDaysMap[leadUnit]
+		_, changeDataMap = MoveDataDaysToNewDataList(changeDataList, leadValue*moveUnitDays)
 	}
-	correlationChart.PeriodData = string(periodDataByte)
-	correlationChart.CorrelationData = string(correlationDataByte)
-	correlationChart.ModifyTime = time.Now().Local()
-	correlationUpdateCols := []string{"PeriodData", "CorrelationData", "ModifyTime"}
-	if err = correlationChart.Update(correlationUpdateCols); err != nil {
-		errMsg = "更新相关性图表失败, Err:" + err.Error()
-		return
+
+	// 计算计算时,需要多少个日期内数据
+	calculateDay := utils.FrequencyDaysMap[calculateUnit] * calculateValue
+
+	// 计算 每个日期的相关性值
+	{
+		startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+		endDateTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
+
+		for currDay := startDateTime; !currDay.After(endDateTime); currDay = currDay.AddDate(0, 0, 1) {
+			yCalculateData := make([]float64, 0)
+			baseCalculateData := make([]float64, 0)
+
+			// 取出对应的基准日期的值
+			for i := 0; i < calculateDay; i++ {
+				iDay := currDay.AddDate(0, 0, i).Format(utils.FormatDate)
+				baseCalculateData = append(baseCalculateData, baseDataMap[iDay])
+				yCalculateData = append(yCalculateData, changeDataMap[iDay])
+			}
+
+			// 公式计算出领先/滞后频度对应点的相关性系数
+			var ratio float64
+			if len(baseCalculateData) > 0 {
+				ratio = utils.CalculateCorrelationByIntArr(baseCalculateData, yCalculateData)
+			}
+			yData = append(yData, ratio)
+			xDateTimeValue = append(xDateTimeValue, currDay.AddDate(0, 0, calculateDay).Format(utils.FormatDate))
+		}
 	}
+
+	yDataList = make([]models.YData, 0)
+	yDate := "0000-00-00"
+	yDataList = append(yDataList, models.YData{
+		Date:  yDate,
+		Value: yData,
+	})
 	return
 }

+ 16 - 3
utils/constants.go

@@ -132,7 +132,20 @@ var (
 
 // 图表类型
 const (
-	CHART_SOURCE_DEFAULT     = 1
-	CHART_SOURCE_FUTURE_GOOD = 2
-	CHART_SOURCE_CORRELATION = 3 // 相关性图表
+	CHART_SOURCE_DEFAULT             = 1
+	CHART_SOURCE_FUTURE_GOOD         = 2
+	CHART_SOURCE_CORRELATION         = 3 // 相关性图表
+	CHART_SOURCE_ROLLING_CORRELATION = 4 // 滚动相关性图表
 )
+
+// 图表样式类型
+const (
+	CHART_TYPE_CURVE           = 1  //曲线图
+	CHART_TYPE_BAR             = 7  //柱形图
+	CHART_TYPE_SECTION_SCATTER = 10 //截面散点图样式
+)
+
+// FrequencyDaysMap 频度日期的map关系
+var FrequencyDaysMap = map[string]int{
+	"天": 1, "周": 7, "月": 30, "季": 90, "年": 365,
+}