Browse Source

fix: 相关性图表保存逻辑

hsun 8 months ago
parent
commit
4daf1fee49

+ 103 - 40
controllers/data_manage/correlation/correlation_chart_info.go

@@ -1390,8 +1390,23 @@ func (this *CorrelationChartInfoController) Copy() {
 			originEdbSeriesMapping = list
 		}
 
+		seriesData := make([]*data_manage.FactorEdbSeriesCalculateData, 0)
+		{
+			dataOb := new(data_manage.FactorEdbSeriesCalculateData)
+			cond := fmt.Sprintf(" AND %s IN (%s)", dataOb.Cols().FactorEdbSeriesId, utils.GetOrmInReplace(len(seriesIds)))
+			pars := make([]interface{}, 0)
+			pars = append(pars, seriesIds)
+			list, e := dataOb.GetItemsByCondition(cond, pars, []string{}, "")
+			if e != nil {
+				br.Msg = "保存失败"
+				br.ErrMsg = fmt.Sprintf("获取系列计算数据失败, %v", e)
+				return
+			}
+			seriesData = list
+		}
+
 		// 新增图表/相关性图表/图表指标关联/指标系列图表关联
-		chartInfoId, seriesIdMap, e := data_manage.CreateMultiFactorCorrelationChartAndEdb(chartInfo, edbMappings, chartCorrelate, originChartMappings, true, originSeries, originEdbSeriesMapping)
+		chartInfoId, seriesIdMap, e := data_manage.CreateMultiFactorCorrelationChartAndEdb(chartInfo, edbMappings, chartCorrelate, originChartMappings, true, originSeries, originEdbSeriesMapping, seriesData)
 		if e != nil {
 			br.Msg = "保存失败"
 			br.ErrMsg = fmt.Sprintf("新增多因子相关性图表失败, Err: %v", e)
@@ -2352,25 +2367,43 @@ func (this *CorrelationChartInfoController) MultiFactorAdd() {
 		edbUsed[k] = true
 	}
 
-	// 指标系列-图表关联
-	chartMappings := make([]*data_manage.FactorEdbSeriesChartMapping, 0)
-	{
-		ob := new(data_manage.FactorEdbSeriesChartMapping)
-		cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().FactorEdbSeriesId, utils.GetOrmInReplace(len(seriesIds)))
-		pars := make([]interface{}, 0)
-		pars = append(pars, seriesIds)
-		items, e := ob.GetItemsByCondition(cond, pars, []string{}, "")
-		if e != nil {
-			br.Msg = "保存失败"
-			br.ErrMsg = fmt.Sprintf("获取指标系列图表关联失败, Err: %v", e)
-			return
-		}
-		chartMappings = items
+	// TODO:图表关联-生成相关性矩阵
+	var calculatePars data_manage.CalculateCorrelationMatrixPars
+	calculatePars.BaseEdbInfoId = req.BaseEdbInfoId
+	calculatePars.SeriesIds = req.FactorCorrelation.SeriesIds
+	var correlationConf data_manage.CorrelationConfig
+	correlationConf.LeadUnit = req.FactorCorrelation.LeadUnit
+	correlationConf.LeadValue = req.FactorCorrelation.LeadValue
+	correlationConf.CalculateUnit = req.FactorCorrelation.CalculateUnit
+	correlationConf.CalculateValue = req.FactorCorrelation.CalculateValue
+	calculatePars.Correlation = correlationConf
+	_, chartMappings, e := correlationServ.CalculateCorrelationMatrix(calculatePars)
+	if e != nil {
+		br.Msg = "计算矩阵失败"
+		br.ErrMsg = fmt.Sprintf("计算相关性矩阵失败, %v", e)
+		return
 	}
+
+	// 指标系列-图表关联
+	//chartMappings := make([]*data_manage.FactorEdbSeriesChartMapping, 0)
+	//{
+	//	ob := new(data_manage.FactorEdbSeriesChartMapping)
+	//	cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().FactorEdbSeriesId, utils.GetOrmInReplace(len(seriesIds)))
+	//	pars := make([]interface{}, 0)
+	//	pars = append(pars, seriesIds)
+	//	items, e := ob.GetItemsByCondition(cond, pars, []string{}, "")
+	//	if e != nil {
+	//		br.Msg = "保存失败"
+	//		br.ErrMsg = fmt.Sprintf("获取指标系列图表关联失败, Err: %v", e)
+	//		return
+	//	}
+	//	chartMappings = items
+	//}
+
 	for _, v := range chartMappings {
 		v.Source = chartSource
 		k := fmt.Sprintf("%d-%d", v.FactorEdbSeriesId, v.EdbInfoId)
-		v.EdbUsed = 0 // 先重置一下
+		//v.EdbUsed = 0 // 先重置一下
 		if edbUsed[k] {
 			v.EdbUsed = 1
 		}
@@ -2380,6 +2413,7 @@ func (this *CorrelationChartInfoController) MultiFactorAdd() {
 	// 另存为
 	originSeries := make([]*data_manage.FactorEdbSeries, 0)
 	originEdbSeriesMapping := make([]*data_manage.FactorEdbSeriesMapping, 0)
+	seriesData := make([]*data_manage.FactorEdbSeriesCalculateData, 0)
 	if req.SaveAs {
 		// 注意此处要复制一份系列及系列关联指标, 不可共用被复制图表的系列
 		{
@@ -2408,10 +2442,23 @@ func (this *CorrelationChartInfoController) MultiFactorAdd() {
 			}
 			originEdbSeriesMapping = list
 		}
+		{
+			dataOb := new(data_manage.FactorEdbSeriesCalculateData)
+			cond := fmt.Sprintf(" AND %s IN (%s)", dataOb.Cols().FactorEdbSeriesId, utils.GetOrmInReplace(len(seriesIds)))
+			pars := make([]interface{}, 0)
+			pars = append(pars, seriesIds)
+			list, e := dataOb.GetItemsByCondition(cond, pars, []string{}, "")
+			if e != nil {
+				br.Msg = "保存失败"
+				br.ErrMsg = fmt.Sprintf("获取系列计算数据失败, %v", e)
+				return
+			}
+			seriesData = list
+		}
 	}
 
 	// 新增图表/相关性图表/图表指标关联/指标系列图表关联
-	chartInfoId, seriesIdMap, e := data_manage.CreateMultiFactorCorrelationChartAndEdb(chartInfo, edbMappings, chartCorrelate, chartMappings, req.SaveAs, originSeries, originEdbSeriesMapping)
+	chartInfoId, seriesIdMap, e := data_manage.CreateMultiFactorCorrelationChartAndEdb(chartInfo, edbMappings, chartCorrelate, chartMappings, req.SaveAs, originSeries, originEdbSeriesMapping, seriesData)
 	if e != nil {
 		br.Msg = "保存失败"
 		br.ErrMsg = fmt.Sprintf("新增多因子相关性图表失败, Err: %v", e)
@@ -2708,35 +2755,51 @@ func (this *CorrelationChartInfoController) MultiFactorEdit() {
 		edbMappings = append(edbMappings, m)
 	}
 
-	seriesIds := req.FactorCorrelation.SeriesIds
+	//seriesIds := req.FactorCorrelation.SeriesIds
 	edbUsed := make(map[string]bool)
 	for _, v := range req.FactorCorrelation.SeriesEdb {
 		k := fmt.Sprintf("%d-%d", v.SeriesId, v.EdbInfoId)
 		edbUsed[k] = true
 	}
 
-	// 指标系列-图表关联
-	chartMappings := make([]*data_manage.FactorEdbSeriesChartMapping, 0)
-	{
-		ob := new(data_manage.FactorEdbSeriesChartMapping)
-		cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().FactorEdbSeriesId, utils.GetOrmInReplace(len(seriesIds)))
-		pars := make([]interface{}, 0)
-		pars = append(pars, seriesIds)
-		items, e := ob.GetItemsByCondition(cond, pars, []string{}, "")
-		if e != nil {
-			br.Msg = "保存失败"
-			br.ErrMsg = fmt.Sprintf("获取指标系列图表关联失败, Err: %v", e)
-			return
-		}
-		chartMappings = items
+	var calculatePars data_manage.CalculateCorrelationMatrixPars
+	calculatePars.BaseEdbInfoId = req.BaseEdbInfoId
+	calculatePars.SeriesIds = req.FactorCorrelation.SeriesIds
+	var correlationConf data_manage.CorrelationConfig
+	correlationConf.LeadUnit = req.FactorCorrelation.LeadUnit
+	correlationConf.LeadValue = req.FactorCorrelation.LeadValue
+	correlationConf.CalculateUnit = req.FactorCorrelation.CalculateUnit
+	correlationConf.CalculateValue = req.FactorCorrelation.CalculateValue
+	calculatePars.Correlation = correlationConf
+	_, chartMappings, e := correlationServ.CalculateCorrelationMatrix(calculatePars)
+	if e != nil {
+		br.Msg = "计算矩阵失败"
+		br.ErrMsg = fmt.Sprintf("计算相关性矩阵失败, %v", e)
+		return
 	}
-	existChartMappingIds := make([]int, 0) // 之前加的需要删除掉
-	updateChartMappings := make([]*data_manage.FactorEdbSeriesChartMapping, 0)
+
+	// 指标系列-图表关联
+	//chartMappings := make([]*data_manage.FactorEdbSeriesChartMapping, 0)
+	//{
+	//	ob := new(data_manage.FactorEdbSeriesChartMapping)
+	//	cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().FactorEdbSeriesId, utils.GetOrmInReplace(len(seriesIds)))
+	//	pars := make([]interface{}, 0)
+	//	pars = append(pars, seriesIds)
+	//	items, e := ob.GetItemsByCondition(cond, pars, []string{}, "")
+	//	if e != nil {
+	//		br.Msg = "保存失败"
+	//		br.ErrMsg = fmt.Sprintf("获取指标系列图表关联失败, Err: %v", e)
+	//		return
+	//	}
+	//	chartMappings = items
+	//}
+	//existChartMappingIds := make([]int, 0) // 之前加的需要删除掉
+	//updateChartMappings := make([]*data_manage.FactorEdbSeriesChartMapping, 0)
 	for _, v := range chartMappings {
-		if v.ChartInfoId == req.ChartInfoId {
-			existChartMappingIds = append(existChartMappingIds, v.FactorEdbSeriesChartMappingId)
-			continue
-		}
+		//if v.ChartInfoId == req.ChartInfoId {
+		//	existChartMappingIds = append(existChartMappingIds, v.FactorEdbSeriesChartMappingId)
+		//	continue
+		//}
 
 		k := fmt.Sprintf("%d-%d", v.FactorEdbSeriesId, v.EdbInfoId)
 		v.EdbUsed = 0
@@ -2746,11 +2809,11 @@ func (this *CorrelationChartInfoController) MultiFactorEdit() {
 		v.ChartInfoId = chartInfo.ChartInfoId
 		v.Source = chartSource
 		v.ModifyTime = time.Now().Local()
-		updateChartMappings = append(updateChartMappings, v)
+		//updateChartMappings = append(updateChartMappings, v)
 	}
 
 	// 更新图表/相关性图表/图表指标关联/指标系列图表关联
-	e = data_manage.UpdateMultiFactorCorrelationChartAndEdb(chartInfo, edbMappings, chartCorrelate, updateChartMappings, existChartMappingIds, chartUpdateCols, correlateUpdateCols)
+	e = data_manage.UpdateMultiFactorCorrelationChartAndEdb(chartInfo, edbMappings, chartCorrelate, chartMappings, chartUpdateCols, correlateUpdateCols)
 	if e != nil {
 		br.Msg = "保存失败"
 		br.ErrMsg = fmt.Sprintf("新增多因子相关性图表失败, Err: %v", e)

+ 260 - 250
controllers/data_manage/factor_edb_series.go

@@ -10,10 +10,8 @@ import (
 	correlationServ "eta/eta_api/services/data/correlation"
 	"eta/eta_api/utils"
 	"fmt"
-	"sort"
 	"strconv"
 	"strings"
-	"sync"
 	"time"
 )
 
@@ -562,258 +560,270 @@ func (this *FactorEdbSeriesController) CorrelationMatrix() {
 		return
 	}
 
-	// 获取标的指标信息及数据
-	baseEdb, e := data_manage.GetEdbInfoById(req.BaseEdbInfoId)
+	// 矩阵计算
+	var calculatePars data_manage.CalculateCorrelationMatrixPars
+	calculatePars.BaseEdbInfoId = req.BaseEdbInfoId
+	calculatePars.SeriesIds = req.SeriesIds
+	calculatePars.Correlation = req.Correlation
+	resp, _, e := correlationServ.CalculateCorrelationMatrix(calculatePars)
 	if e != nil {
-		if e.Error() == utils.ErrNoRow() {
-			br.Msg = "标的指标不存在"
-			return
-		}
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取标的指标信息失败, Err: " + e.Error()
-		return
-	}
-	dataListA := make([]*data_manage.EdbDataList, 0)
-	{
-		// 标的指标数据日期区间
-		startDate := time.Now().AddDate(0, 0, -calculateDays).Format(utils.FormatDate)
-		endDate := time.Now().Format(utils.FormatDate)
-		startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
-		startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate) // 不包含第一天
-		switch baseEdb.EdbInfoType {
-		case 0:
-			dataListA, e = data_manage.GetEdbDataList(baseEdb.Source, baseEdb.SubSource, baseEdb.EdbInfoId, startDate, endDate)
-		case 1:
-			_, dataListA, _, _, e, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdb.EdbInfoId, startDate, endDate, false)
-		default:
-			br.Msg = "获取失败"
-			br.ErrMsg = fmt.Sprintf("标的指标类型异常: %d", baseEdb.EdbInfoType)
-			return
-		}
-		if e != nil {
-			br.Msg = "获取失败"
-			br.ErrMsg = "获取标的指标数据失败, Err:" + e.Error()
-			return
-		}
-	}
-
-	// 获取因子系列
-	seriesIdItem := make(map[int]*data_manage.FactorEdbSeries)
-	{
-		ob := new(data_manage.FactorEdbSeries)
-		cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().PrimaryId, utils.GetOrmInReplace(len(req.SeriesIds)))
-		pars := make([]interface{}, 0)
-		pars = append(pars, req.SeriesIds)
-		items, e := ob.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", ob.Cols().PrimaryId))
-		if e != nil {
-			br.Msg = "获取失败"
-			br.ErrMsg = "获取因子指标系列失败, Err: " + e.Error()
-			return
-		}
-		if len(items) != len(req.SeriesIds) {
-			br.Msg = "获取失败"
-			br.ErrMsg = "因子指标系列数量有误"
-			return
-		}
-		for _, v := range items {
-			seriesIdItem[v.FactorEdbSeriesId] = v
-		}
-	}
-
-	// 获取因子指标
-	edbMappings := make([]*data_manage.FactorEdbSeriesMapping, 0)
-	edbInfoIds := make([]int, 0)
-	{
-		ob := new(data_manage.FactorEdbSeriesMapping)
-		cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().FactorEdbSeriesId, utils.GetOrmInReplace(len(req.SeriesIds)))
-		pars := make([]interface{}, 0)
-		pars = append(pars, req.SeriesIds)
-		order := fmt.Sprintf("%s ASC, %s ASC", ob.Cols().FactorEdbSeriesId, ob.Cols().EdbInfoId)
-		items, e := ob.GetItemsByCondition(cond, pars, []string{}, order)
-		if e != nil {
-			br.Msg = "获取失败"
-			br.ErrMsg = "获取因子指标关联失败, Err: " + e.Error()
-			return
-		}
-		for _, v := range items {
-			edbInfoIds = append(edbInfoIds, v.EdbInfoId)
-		}
-		edbMappings = items
-	}
-	edbIdItem := make(map[int]*data_manage.EdbInfo)
-	edbItems, e := data_manage.GetEdbInfoByIdList(edbInfoIds)
-	if e != nil {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取因子指标失败, Err: " + e.Error()
+		br.Msg = "计算失败"
+		br.ErrMsg = fmt.Sprintf("计算相关性矩阵失败, %v", e)
 		return
 	}
-	for _, v := range edbItems {
-		edbIdItem[v.EdbInfoId] = v
-	}
-
-	// 获取因子指标数据, 计算相关性
-	resp := new(data_manage.FactorEdbSeriesCorrelationMatrixResp)
-	calculateDataOb := new(data_manage.FactorEdbSeriesCalculateData)
-
-	calculateWorkers := make(chan struct{}, 10)
-	wg := sync.WaitGroup{}
-	edbExists := make(map[string]bool)
-	chartKeyMap := make(map[string]*data_manage.FactorEdbSeriesChartMapping)
-	for _, v := range edbMappings {
-		existsKey := fmt.Sprintf("%d-%d", v.FactorEdbSeriesId, v.EdbInfoId)
-		if edbExists[existsKey] {
-			continue
-		}
-		edbExists[existsKey] = true
 
-		edbItem := edbIdItem[v.EdbInfoId]
-		if edbItem == nil {
-			continue
-		}
-		seriesItem := seriesIdItem[v.FactorEdbSeriesId]
-		if seriesItem == nil {
-			continue
-		}
-
-		wg.Add(1)
-		go func(mapping *data_manage.FactorEdbSeriesMapping, edb *data_manage.EdbInfo, series *data_manage.FactorEdbSeries) {
-			defer func() {
-				wg.Done()
-				<-calculateWorkers
-			}()
-			calculateWorkers <- struct{}{}
-
-			var item data_manage.FactorEdbSeriesCorrelationMatrixItem
-			item.SeriesId = series.FactorEdbSeriesId
-			item.EdbInfoId = edb.EdbInfoId
-			item.EdbCode = edb.EdbCode
-			item.EdbName = edb.EdbName
-
-			// 指标来源
-			edbList := make([]*data_manage.ChartEdbInfoMapping, 0)
-			edbList = append(edbList, &data_manage.ChartEdbInfoMapping{
-				EdbInfoId:           edb.EdbInfoId,
-				EdbInfoCategoryType: edb.EdbInfoType,
-				EdbType:             edb.EdbType,
-				Source:              edb.Source,
-				SourceName:          edb.SourceName,
-			})
-			sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
-			item.SourceName = strings.Join(sourceNameList, ",")
-			item.SourceNameEn = strings.Join(sourceNameEnList, ",")
-
-			// 获取指标数据
-			dataListB := make([]*data_manage.EdbDataList, 0)
-			if series.CalculateState == data_manage.FactorEdbSeriesCalculated {
-				cond := fmt.Sprintf(" AND %s = ? AND %s = ?", calculateDataOb.Cols().FactorEdbSeriesId, calculateDataOb.Cols().EdbInfoId)
-				pars := make([]interface{}, 0)
-				pars = append(pars, mapping.FactorEdbSeriesId, mapping.EdbInfoId)
-				dataItems, e := calculateDataOb.GetItemsByCondition(cond, pars, []string{calculateDataOb.Cols().DataTime, calculateDataOb.Cols().Value}, fmt.Sprintf("%s ASC", calculateDataOb.Cols().DataTime))
-				if e != nil {
-					item.Msg = fmt.Sprintf("计算失败")
-					item.ErrMsg = fmt.Sprintf("获取计算数据失败, err: %v", e)
-					resp.Fail = append(resp.Fail, item)
-					return
-				}
-				dataListB = data_manage.TransEdbSeriesCalculateData2EdbDataList(dataItems)
-			} else {
-				switch edb.EdbInfoType {
-				case 0:
-					dataListB, e = data_manage.GetEdbDataList(edb.Source, edb.SubSource, edb.EdbInfoId, "", "")
-				case 1:
-					_, dataListB, _, _, e, _ = data.GetPredictDataListByPredictEdbInfoId(edb.EdbInfoId, "", "", false)
-				default:
-					item.Msg = fmt.Sprintf("计算失败")
-					item.ErrMsg = fmt.Sprintf("指标类型异常, edbType: %d", edb.EdbInfoType)
-					resp.Fail = append(resp.Fail, item)
-					return
-				}
-			}
-
-			// 计算相关性
-			xEdbIdValue, yDataList, e := correlationServ.CalculateCorrelation(req.Correlation.LeadValue, req.Correlation.LeadUnit, baseEdb.Frequency, edb.Frequency, dataListA, dataListB)
-			if e != nil {
-				item.Msg = fmt.Sprintf("计算失败")
-				item.ErrMsg = fmt.Sprintf("相关性计算失败, err: %v", e)
-				resp.Fail = append(resp.Fail, item)
-				return
-			}
-
-			// X及Y轴数据
-			yData := yDataList[0].Value
-			yLen := len(yData)
-			values := make([]data_manage.FactorEdbSeriesCorrelationMatrixValues, len(xEdbIdValue))
-			for k, x := range xEdbIdValue {
-				var y float64
-				if k >= 0 && k < yLen {
-					y = yData[k]
-				}
-				y = utils.SubFloatToFloat(y, 2)
-				values[k] = data_manage.FactorEdbSeriesCorrelationMatrixValues{
-					XData: x, YData: y,
-				}
-			}
-
-			// 图表关联-此处添加的chart_info_id=0
-			newMapping := new(data_manage.FactorEdbSeriesChartMapping)
-			newMapping.CalculateType = data_manage.FactorEdbSeriesChartCalculateTypeCorrelation
-
-			// 计算参数
-			var calculatePars data_manage.FactorEdbSeriesChartCalculateCorrelationReq
-			calculatePars.BaseEdbInfoId = req.BaseEdbInfoId
-			calculatePars.LeadValue = req.Correlation.LeadValue
-			calculatePars.LeadUnit = req.Correlation.LeadUnit
-			calculatePars.CalculateValue = req.Correlation.CalculateValue
-			calculatePars.CalculateUnit = req.Correlation.CalculateUnit
-			bc, e := json.Marshal(calculatePars)
-			if e != nil {
-				item.Msg = fmt.Sprintf("计算失败")
-				item.ErrMsg = fmt.Sprintf("计算参数JSON格式化失败, err: %v", e)
-				resp.Fail = append(resp.Fail, item)
-				return
-			}
-			newMapping.CalculatePars = string(bc)
-
-			// 计算结果, 注此处保存的是排序前的顺序
-			bv, e := json.Marshal(values)
-			if e != nil {
-				item.Msg = fmt.Sprintf("计算失败")
-				item.ErrMsg = fmt.Sprintf("计算结果JSON格式化失败, err: %v", e)
-				resp.Fail = append(resp.Fail, item)
-				return
-			}
-			newMapping.CalculateData = string(bv)
-			newMapping.FactorEdbSeriesId = mapping.FactorEdbSeriesId
-			newMapping.EdbInfoId = mapping.EdbInfoId
-			newMapping.CreateTime = time.Now().Local()
-			newMapping.ModifyTime = time.Now().Local()
-			chartKeyMap[existsKey] = newMapping
-
-			// 按照固定规则排期数[0 1 2 3 -1 -2 -3], 仅矩阵展示为此顺序
-			sort.Sort(data_manage.FactorEdbSeriesCorrelationMatrixOrder(values))
-			item.Msg = "计算成功"
-			item.Values = values
-			resp.Success = append(resp.Success, item)
-		}(v, edbItem, seriesItem)
-	}
-	wg.Wait()
-
-	// 新增图表关联, 此处按照顺序添加
-	chartMappings := make([]*data_manage.FactorEdbSeriesChartMapping, 0)
-	for _, v := range edbMappings {
-		k := fmt.Sprintf("%d-%d", v.FactorEdbSeriesId, v.EdbInfoId)
-		item := chartKeyMap[k]
-		if item == nil {
-			continue
-		}
-		chartMappings = append(chartMappings, item)
-	}
-	chartMappingOb := new(data_manage.FactorEdbSeriesChartMapping)
-	if e = chartMappingOb.ClearAndCreateMapping(req.SeriesIds, chartMappings); e != nil {
-		br.Msg = "获取失败"
-		br.ErrMsg = fmt.Sprintf("新增图表关联失败, Err: %v", e)
-		return
-	}
+	// 获取标的指标信息及数据
+	//baseEdb, e := data_manage.GetEdbInfoById(req.BaseEdbInfoId)
+	//if e != nil {
+	//	if e.Error() == utils.ErrNoRow() {
+	//		br.Msg = "标的指标不存在"
+	//		return
+	//	}
+	//	br.Msg = "获取失败"
+	//	br.ErrMsg = "获取标的指标信息失败, Err: " + e.Error()
+	//	return
+	//}
+	//dataListA := make([]*data_manage.EdbDataList, 0)
+	//{
+	//	// 标的指标数据日期区间
+	//	startDate := time.Now().AddDate(0, 0, -calculateDays).Format(utils.FormatDate)
+	//	endDate := time.Now().Format(utils.FormatDate)
+	//	startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+	//	startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate) // 不包含第一天
+	//	switch baseEdb.EdbInfoType {
+	//	case 0:
+	//		dataListA, e = data_manage.GetEdbDataList(baseEdb.Source, baseEdb.SubSource, baseEdb.EdbInfoId, startDate, endDate)
+	//	case 1:
+	//		_, dataListA, _, _, e, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdb.EdbInfoId, startDate, endDate, false)
+	//	default:
+	//		br.Msg = "获取失败"
+	//		br.ErrMsg = fmt.Sprintf("标的指标类型异常: %d", baseEdb.EdbInfoType)
+	//		return
+	//	}
+	//	if e != nil {
+	//		br.Msg = "获取失败"
+	//		br.ErrMsg = "获取标的指标数据失败, Err:" + e.Error()
+	//		return
+	//	}
+	//}
+	//
+	//// 获取因子系列
+	//seriesIdItem := make(map[int]*data_manage.FactorEdbSeries)
+	//{
+	//	ob := new(data_manage.FactorEdbSeries)
+	//	cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().PrimaryId, utils.GetOrmInReplace(len(req.SeriesIds)))
+	//	pars := make([]interface{}, 0)
+	//	pars = append(pars, req.SeriesIds)
+	//	items, e := ob.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", ob.Cols().PrimaryId))
+	//	if e != nil {
+	//		br.Msg = "获取失败"
+	//		br.ErrMsg = "获取因子指标系列失败, Err: " + e.Error()
+	//		return
+	//	}
+	//	if len(items) != len(req.SeriesIds) {
+	//		br.Msg = "获取失败"
+	//		br.ErrMsg = "因子指标系列数量有误"
+	//		return
+	//	}
+	//	for _, v := range items {
+	//		seriesIdItem[v.FactorEdbSeriesId] = v
+	//	}
+	//}
+	//
+	//// 获取因子指标
+	//edbMappings := make([]*data_manage.FactorEdbSeriesMapping, 0)
+	//edbInfoIds := make([]int, 0)
+	//{
+	//	ob := new(data_manage.FactorEdbSeriesMapping)
+	//	cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().FactorEdbSeriesId, utils.GetOrmInReplace(len(req.SeriesIds)))
+	//	pars := make([]interface{}, 0)
+	//	pars = append(pars, req.SeriesIds)
+	//	order := fmt.Sprintf("%s ASC, %s ASC", ob.Cols().FactorEdbSeriesId, ob.Cols().EdbInfoId)
+	//	items, e := ob.GetItemsByCondition(cond, pars, []string{}, order)
+	//	if e != nil {
+	//		br.Msg = "获取失败"
+	//		br.ErrMsg = "获取因子指标关联失败, Err: " + e.Error()
+	//		return
+	//	}
+	//	for _, v := range items {
+	//		edbInfoIds = append(edbInfoIds, v.EdbInfoId)
+	//	}
+	//	edbMappings = items
+	//}
+	//edbIdItem := make(map[int]*data_manage.EdbInfo)
+	//edbItems, e := data_manage.GetEdbInfoByIdList(edbInfoIds)
+	//if e != nil {
+	//	br.Msg = "获取失败"
+	//	br.ErrMsg = "获取因子指标失败, Err: " + e.Error()
+	//	return
+	//}
+	//for _, v := range edbItems {
+	//	edbIdItem[v.EdbInfoId] = v
+	//}
+	//
+	//// 获取因子指标数据, 计算相关性
+	//resp := new(data_manage.FactorEdbSeriesCorrelationMatrixResp)
+	//calculateDataOb := new(data_manage.FactorEdbSeriesCalculateData)
+	//
+	//calculateWorkers := make(chan struct{}, 10)
+	//wg := sync.WaitGroup{}
+	//edbExists := make(map[string]bool)
+	//chartKeyMap := make(map[string]*data_manage.FactorEdbSeriesChartMapping)
+	//for _, v := range edbMappings {
+	//	existsKey := fmt.Sprintf("%d-%d", v.FactorEdbSeriesId, v.EdbInfoId)
+	//	if edbExists[existsKey] {
+	//		continue
+	//	}
+	//	edbExists[existsKey] = true
+	//
+	//	edbItem := edbIdItem[v.EdbInfoId]
+	//	if edbItem == nil {
+	//		continue
+	//	}
+	//	seriesItem := seriesIdItem[v.FactorEdbSeriesId]
+	//	if seriesItem == nil {
+	//		continue
+	//	}
+	//
+	//	wg.Add(1)
+	//	go func(mapping *data_manage.FactorEdbSeriesMapping, edb *data_manage.EdbInfo, series *data_manage.FactorEdbSeries) {
+	//		defer func() {
+	//			wg.Done()
+	//			<-calculateWorkers
+	//		}()
+	//		calculateWorkers <- struct{}{}
+	//
+	//		var item data_manage.FactorEdbSeriesCorrelationMatrixItem
+	//		item.SeriesId = series.FactorEdbSeriesId
+	//		item.EdbInfoId = edb.EdbInfoId
+	//		item.EdbCode = edb.EdbCode
+	//		item.EdbName = edb.EdbName
+	//
+	//		// 指标来源
+	//		edbList := make([]*data_manage.ChartEdbInfoMapping, 0)
+	//		edbList = append(edbList, &data_manage.ChartEdbInfoMapping{
+	//			EdbInfoId:           edb.EdbInfoId,
+	//			EdbInfoCategoryType: edb.EdbInfoType,
+	//			EdbType:             edb.EdbType,
+	//			Source:              edb.Source,
+	//			SourceName:          edb.SourceName,
+	//		})
+	//		sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
+	//		item.SourceName = strings.Join(sourceNameList, ",")
+	//		item.SourceNameEn = strings.Join(sourceNameEnList, ",")
+	//
+	//		// 获取指标数据
+	//		dataListB := make([]*data_manage.EdbDataList, 0)
+	//		if series.CalculateState == data_manage.FactorEdbSeriesCalculated {
+	//			cond := fmt.Sprintf(" AND %s = ? AND %s = ?", calculateDataOb.Cols().FactorEdbSeriesId, calculateDataOb.Cols().EdbInfoId)
+	//			pars := make([]interface{}, 0)
+	//			pars = append(pars, mapping.FactorEdbSeriesId, mapping.EdbInfoId)
+	//			dataItems, e := calculateDataOb.GetItemsByCondition(cond, pars, []string{calculateDataOb.Cols().DataTime, calculateDataOb.Cols().Value}, fmt.Sprintf("%s ASC", calculateDataOb.Cols().DataTime))
+	//			if e != nil {
+	//				item.Msg = fmt.Sprintf("计算失败")
+	//				item.ErrMsg = fmt.Sprintf("获取计算数据失败, err: %v", e)
+	//				resp.Fail = append(resp.Fail, item)
+	//				return
+	//			}
+	//			dataListB = data_manage.TransEdbSeriesCalculateData2EdbDataList(dataItems)
+	//		} else {
+	//			switch edb.EdbInfoType {
+	//			case 0:
+	//				dataListB, e = data_manage.GetEdbDataList(edb.Source, edb.SubSource, edb.EdbInfoId, "", "")
+	//			case 1:
+	//				_, dataListB, _, _, e, _ = data.GetPredictDataListByPredictEdbInfoId(edb.EdbInfoId, "", "", false)
+	//			default:
+	//				item.Msg = fmt.Sprintf("计算失败")
+	//				item.ErrMsg = fmt.Sprintf("指标类型异常, edbType: %d", edb.EdbInfoType)
+	//				resp.Fail = append(resp.Fail, item)
+	//				return
+	//			}
+	//		}
+	//
+	//		// 计算相关性
+	//		xEdbIdValue, yDataList, e := correlationServ.CalculateCorrelation(req.Correlation.LeadValue, req.Correlation.LeadUnit, baseEdb.Frequency, edb.Frequency, dataListA, dataListB)
+	//		if e != nil {
+	//			item.Msg = fmt.Sprintf("计算失败")
+	//			item.ErrMsg = fmt.Sprintf("相关性计算失败, err: %v", e)
+	//			resp.Fail = append(resp.Fail, item)
+	//			return
+	//		}
+	//
+	//		// X及Y轴数据
+	//		yData := yDataList[0].Value
+	//		yLen := len(yData)
+	//		values := make([]data_manage.FactorEdbSeriesCorrelationMatrixValues, len(xEdbIdValue))
+	//		for k, x := range xEdbIdValue {
+	//			var y float64
+	//			if k >= 0 && k < yLen {
+	//				y = yData[k]
+	//			}
+	//			y = utils.SubFloatToFloat(y, 2)
+	//			values[k] = data_manage.FactorEdbSeriesCorrelationMatrixValues{
+	//				XData: x, YData: y,
+	//			}
+	//		}
+	//
+	//		// 图表关联-此处添加的chart_info_id=0
+	//		newMapping := new(data_manage.FactorEdbSeriesChartMapping)
+	//		newMapping.CalculateType = data_manage.FactorEdbSeriesChartCalculateTypeCorrelation
+	//
+	//		// 计算参数
+	//		var calculatePars data_manage.FactorEdbSeriesChartCalculateCorrelationReq
+	//		calculatePars.BaseEdbInfoId = req.BaseEdbInfoId
+	//		calculatePars.LeadValue = req.Correlation.LeadValue
+	//		calculatePars.LeadUnit = req.Correlation.LeadUnit
+	//		calculatePars.CalculateValue = req.Correlation.CalculateValue
+	//		calculatePars.CalculateUnit = req.Correlation.CalculateUnit
+	//		bc, e := json.Marshal(calculatePars)
+	//		if e != nil {
+	//			item.Msg = fmt.Sprintf("计算失败")
+	//			item.ErrMsg = fmt.Sprintf("计算参数JSON格式化失败, err: %v", e)
+	//			resp.Fail = append(resp.Fail, item)
+	//			return
+	//		}
+	//		newMapping.CalculatePars = string(bc)
+	//
+	//		// 计算结果, 注此处保存的是排序前的顺序
+	//		bv, e := json.Marshal(values)
+	//		if e != nil {
+	//			item.Msg = fmt.Sprintf("计算失败")
+	//			item.ErrMsg = fmt.Sprintf("计算结果JSON格式化失败, err: %v", e)
+	//			resp.Fail = append(resp.Fail, item)
+	//			return
+	//		}
+	//		newMapping.CalculateData = string(bv)
+	//		newMapping.FactorEdbSeriesId = mapping.FactorEdbSeriesId
+	//		newMapping.EdbInfoId = mapping.EdbInfoId
+	//		newMapping.CreateTime = time.Now().Local()
+	//		newMapping.ModifyTime = time.Now().Local()
+	//		chartKeyMap[existsKey] = newMapping
+	//
+	//		// 按照固定规则排期数[0 1 2 3 -1 -2 -3], 仅矩阵展示为此顺序
+	//		sort.Sort(data_manage.FactorEdbSeriesCorrelationMatrixOrder(values))
+	//		item.Msg = "计算成功"
+	//		item.Values = values
+	//		resp.Success = append(resp.Success, item)
+	//	}(v, edbItem, seriesItem)
+	//}
+	//wg.Wait()
+	//
+	//// 新增图表关联, 此处按照顺序添加
+	//chartMappings := make([]*data_manage.FactorEdbSeriesChartMapping, 0)
+	//for _, v := range edbMappings {
+	//	k := fmt.Sprintf("%d-%d", v.FactorEdbSeriesId, v.EdbInfoId)
+	//	item := chartKeyMap[k]
+	//	if item == nil {
+	//		continue
+	//	}
+	//	chartMappings = append(chartMappings, item)
+	//}
+	//chartMappingOb := new(data_manage.FactorEdbSeriesChartMapping)
+	//if e = chartMappingOb.ClearAndCreateMapping(req.SeriesIds, chartMappings); e != nil {
+	//	br.Msg = "获取失败"
+	//	br.ErrMsg = fmt.Sprintf("新增图表关联失败, Err: %v", e)
+	//	return
+	//}
 
 	br.Data = resp
 	br.Ret = 200

+ 72 - 38
models/data_manage/chart_info_correlation.go

@@ -1,7 +1,6 @@
 package data_manage
 
 import (
-	"eta/eta_api/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"strings"
@@ -169,7 +168,7 @@ type CorrelationChartInfoExtraConfig struct {
 }
 
 // CreateMultiFactorCorrelationChartAndEdb 新增多因子相关性图表
-func CreateMultiFactorCorrelationChartAndEdb(chartInfo *ChartInfo, edbMappingList []*ChartEdbMapping, correlationInfo *ChartInfoCorrelation, chartMappings []*FactorEdbSeriesChartMapping, saveAs bool, copySeries []*FactorEdbSeries, copySeriesEdb []*FactorEdbSeriesMapping) (chartInfoId int, seriesIdMap map[int]int, err error) {
+func CreateMultiFactorCorrelationChartAndEdb(chartInfo *ChartInfo, edbMappingList []*ChartEdbMapping, correlationInfo *ChartInfoCorrelation, chartMappings []*FactorEdbSeriesChartMapping, saveAs bool, copySeries []*FactorEdbSeries, copySeriesEdb []*FactorEdbSeriesMapping, copySeriesData []*FactorEdbSeriesCalculateData) (chartInfoId int, seriesIdMap map[int]int, err error) {
 	seriesIdMap = make(map[int]int) // 此处做一个原ID与新ID的映射, 另存为才用的到
 	o := orm.NewOrmUsingDB("data")
 	tx, e := o.Begin()
@@ -217,31 +216,44 @@ func CreateMultiFactorCorrelationChartAndEdb(chartInfo *ChartInfo, edbMappingLis
 	if !saveAs {
 		// 指标系列-图表关联
 		if len(chartMappings) > 0 {
-			chartMappingOb := new(FactorEdbSeriesChartMapping)
-			sql := fmt.Sprintf(`UPDATE %s SET %s = ?, %s = ?, %s = ?, %s = ? WHERE %s = ?`, chartMappingOb.TableName(), chartMappingOb.Cols().ChartInfoId, chartMappingOb.Cols().Source, chartMappingOb.Cols().EdbUsed, chartMappingOb.Cols().ModifyTime, chartMappingOb.Cols().PrimaryId)
-			p, e := o.Raw(sql).Prepare()
-			if e != nil {
-				err = fmt.Errorf("sql prepare err: %v", e)
-				return
-			}
-			defer func() {
-				_ = p.Close()
-			}()
 			for _, v := range chartMappings {
+				//v.FactorEdbSeriesChartMappingId = 0
 				v.ChartInfoId = chartInfoId
-				_, e = p.Exec(v.ChartInfoId, v.Source, v.EdbUsed, v.ModifyTime, v.FactorEdbSeriesChartMappingId)
-				if e != nil {
-					err = fmt.Errorf("update exec err: %v", e)
-					return
-				}
+				//v.FactorEdbSeriesId = seriesIdMap[v.FactorEdbSeriesId]
 			}
+			_, e = tx.InsertMulti(200, chartMappings)
+			if e != nil {
+				err = fmt.Errorf("insert series chart mappings err: %v", e)
+				return
+			}
+
+			//chartMappingOb := new(FactorEdbSeriesChartMapping)
+			//sql := fmt.Sprintf(`UPDATE %s SET %s = ?, %s = ?, %s = ?, %s = ? WHERE %s = ?`, chartMappingOb.TableName(), chartMappingOb.Cols().ChartInfoId, chartMappingOb.Cols().Source, chartMappingOb.Cols().EdbUsed, chartMappingOb.Cols().ModifyTime, chartMappingOb.Cols().PrimaryId)
+			//p, e := o.Raw(sql).Prepare()
+			//if e != nil {
+			//	err = fmt.Errorf("sql prepare err: %v", e)
+			//	return
+			//}
+			//defer func() {
+			//	_ = p.Close()
+			//}()
+			//for _, v := range chartMappings {
+			//	v.ChartInfoId = chartInfoId
+			//	_, e = p.Exec(v.ChartInfoId, v.Source, v.EdbUsed, v.ModifyTime, v.FactorEdbSeriesChartMappingId)
+			//	if e != nil {
+			//		err = fmt.Errorf("update exec err: %v", e)
+			//		return
+			//	}
+			//}
 		}
 		return
 	}
 
 	// 另存为
+	originSeriesIds := make([]int, 0)
 	for _, v := range copySeries {
 		id := v.FactorEdbSeriesId
+		originSeriesIds = append(originSeriesIds, id)
 		v.FactorEdbSeriesId = 0
 		newId, e := tx.Insert(v)
 		if e != nil {
@@ -271,11 +283,27 @@ func CreateMultiFactorCorrelationChartAndEdb(chartInfo *ChartInfo, edbMappingLis
 			return
 		}
 	}
+
+	// 系列指标计算
+	if len(copySeriesData) > 0 {
+		newCalculateData := make([]*FactorEdbSeriesCalculateData, 0)
+		for _, v := range copySeriesData {
+			t := v
+			t.FactorEdbSeriesCalculateDataId = 0
+			t.FactorEdbSeriesId = seriesIdMap[t.FactorEdbSeriesId]
+			newCalculateData = append(newCalculateData, t)
+		}
+		_, e = tx.InsertMulti(200, newCalculateData)
+		if e != nil {
+			err = fmt.Errorf("copy series calculate data err: %v", e)
+			return
+		}
+	}
 	return
 }
 
 // UpdateMultiFactorCorrelationChartAndEdb 编辑多因子相关性图表
-func UpdateMultiFactorCorrelationChartAndEdb(chartInfo *ChartInfo, edbMappingList []*ChartEdbMapping, correlationInfo *ChartInfoCorrelation, chartMappings []*FactorEdbSeriesChartMapping, existsChartMappingIds []int, chartUpdateCols, correlateUpdateCols []string) (err error) {
+func UpdateMultiFactorCorrelationChartAndEdb(chartInfo *ChartInfo, edbMappingList []*ChartEdbMapping, correlationInfo *ChartInfoCorrelation, chartMappings []*FactorEdbSeriesChartMapping, chartUpdateCols, correlateUpdateCols []string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	tx, e := o.Begin()
 	if e != nil {
@@ -324,33 +352,39 @@ func UpdateMultiFactorCorrelationChartAndEdb(chartInfo *ChartInfo, edbMappingLis
 
 	// 删除原关联
 	chartMappingOb := new(FactorEdbSeriesChartMapping)
-	if len(existsChartMappingIds) > 0 {
-		sql = fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, chartMappingOb.TableName(), chartMappingOb.Cols().PrimaryId, utils.GetOrmInReplace(len(existsChartMappingIds)))
-		_, e = tx.Raw(sql, existsChartMappingIds).Exec()
-		if e != nil {
-			err = fmt.Errorf("clear chart mapping err: %v", e)
-			return
-		}
+	//if len(existsChartMappingIds) > 0 {
+	sql = fmt.Sprintf(`DELETE FROM %s WHERE %s = ?`, chartMappingOb.TableName(), chartMappingOb.Cols().ChartInfoId)
+	_, e = tx.Raw(sql, chartInfo.ChartInfoId).Exec()
+	if e != nil {
+		err = fmt.Errorf("clear chart mapping err: %v", e)
+		return
 	}
+	//}
 
 	// 指标系列-图表关联
 	if len(chartMappings) > 0 {
-		sql = fmt.Sprintf(`UPDATE %s SET %s = ?, %s = ?, %s = ?, %s = ? WHERE %s = ?`, chartMappingOb.TableName(), chartMappingOb.Cols().ChartInfoId, chartMappingOb.Cols().Source, chartMappingOb.Cols().EdbUsed, chartMappingOb.Cols().ModifyTime, chartMappingOb.Cols().PrimaryId)
-		p, e := o.Raw(sql).Prepare()
+		_, e = tx.InsertMulti(200, chartMappings)
 		if e != nil {
-			err = fmt.Errorf("sql prepare err: %v", e)
+			err = fmt.Errorf("insert series chart mappings err: %v", e)
 			return
 		}
-		defer func() {
-			_ = p.Close()
-		}()
-		for _, v := range chartMappings {
-			_, e = p.Exec(v.ChartInfoId, v.Source, v.EdbUsed, v.ModifyTime, v.FactorEdbSeriesChartMappingId)
-			if e != nil {
-				err = fmt.Errorf("update exec err: %v", e)
-				return
-			}
-		}
+
+		//sql = fmt.Sprintf(`UPDATE %s SET %s = ?, %s = ?, %s = ?, %s = ? WHERE %s = ?`, chartMappingOb.TableName(), chartMappingOb.Cols().ChartInfoId, chartMappingOb.Cols().Source, chartMappingOb.Cols().EdbUsed, chartMappingOb.Cols().ModifyTime, chartMappingOb.Cols().PrimaryId)
+		//p, e := o.Raw(sql).Prepare()
+		//if e != nil {
+		//	err = fmt.Errorf("sql prepare err: %v", e)
+		//	return
+		//}
+		//defer func() {
+		//	_ = p.Close()
+		//}()
+		//for _, v := range chartMappings {
+		//	_, e = p.Exec(v.ChartInfoId, v.Source, v.EdbUsed, v.ModifyTime, v.FactorEdbSeriesChartMappingId)
+		//	if e != nil {
+		//		err = fmt.Errorf("update exec err: %v", e)
+		//		return
+		//	}
+		//}
 	}
 	return
 }

+ 7 - 0
models/data_manage/factor_edb_series.go

@@ -359,3 +359,10 @@ func (a FactorEdbSeriesCorrelationMatrixOrder) Less(i, j int) bool {
 	// 负数按绝对值的降序排序(即数值的升序)
 	return a[i].XData > a[j].XData
 }
+
+// CalculateCorrelationMatrixPars 计算相关性矩阵参数
+type CalculateCorrelationMatrixPars struct {
+	BaseEdbInfoId int               `description:"标的指标ID"`
+	SeriesIds     []int             `description:"系列IDs"`
+	Correlation   CorrelationConfig `description:"相关性配置"`
+}

+ 273 - 0
services/data/correlation/chart_info.go

@@ -14,6 +14,7 @@ import (
 	"sort"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 )
 
@@ -1628,3 +1629,275 @@ func RemoveCorrelationRelate(chartInfoId int) (err error) {
 	}
 	return
 }
+
+// CalculateCorrelationMatrix 计算相关性矩阵
+func CalculateCorrelationMatrix(req data_manage.CalculateCorrelationMatrixPars) (resp data_manage.FactorEdbSeriesCorrelationMatrixResp, chartMappings []*data_manage.FactorEdbSeriesChartMapping, err error) {
+	if req.BaseEdbInfoId <= 0 {
+		err = fmt.Errorf("请选择标的指标")
+		return
+	}
+	if len(req.SeriesIds) == 0 {
+		err = fmt.Errorf("请选择因子指标系列")
+		return
+	}
+	if req.Correlation.LeadValue <= 0 {
+		err = fmt.Errorf("分析周期不允许设置为负数或0")
+		return
+	}
+	if req.Correlation.LeadUnit == "" {
+		err = fmt.Errorf("请选择分析周期频度")
+		return
+	}
+	leadUnitDays, ok := utils.FrequencyDaysMap[req.Correlation.LeadUnit]
+	if !ok {
+		err = fmt.Errorf("错误的分析周期频度: %s", req.Correlation.LeadUnit)
+		return
+	}
+
+	if req.Correlation.CalculateUnit == "" {
+		err = fmt.Errorf("请选择计算窗口频度")
+		return
+	}
+	calculateUnitDays, ok := utils.FrequencyDaysMap[req.Correlation.CalculateUnit]
+	if !ok {
+		err = fmt.Errorf("计算窗口频度有误: %s", req.Correlation.CalculateUnit)
+		return
+	}
+	leadDays := 2 * req.Correlation.LeadValue * leadUnitDays
+	calculateDays := req.Correlation.CalculateValue * calculateUnitDays
+	if calculateDays < leadDays {
+		err = fmt.Errorf("计算窗口必须≥2*分析周期")
+		return
+	}
+
+	// 获取标的指标信息及数据
+	baseEdb, e := data_manage.GetEdbInfoById(req.BaseEdbInfoId)
+	if e != nil {
+		err = fmt.Errorf("获取标的指标失败, %v", e)
+		return
+	}
+	dataListA := make([]*data_manage.EdbDataList, 0)
+	{
+		// 标的指标数据日期区间
+		startDate := time.Now().AddDate(0, 0, -calculateDays).Format(utils.FormatDate)
+		endDate := time.Now().Format(utils.FormatDate)
+		startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+		startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate) // 不包含第一天
+		switch baseEdb.EdbInfoType {
+		case 0:
+			dataListA, e = data_manage.GetEdbDataList(baseEdb.Source, baseEdb.SubSource, baseEdb.EdbInfoId, startDate, endDate)
+		case 1:
+			_, dataListA, _, _, e, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdb.EdbInfoId, startDate, endDate, false)
+		default:
+			err = fmt.Errorf("标的指标类型异常: %d", baseEdb.EdbInfoType)
+			return
+		}
+		if e != nil {
+			err = fmt.Errorf("获取标的指标数据失败, %v", e)
+			return
+		}
+	}
+
+	// 获取因子系列
+	seriesIdItem := make(map[int]*data_manage.FactorEdbSeries)
+	{
+		ob := new(data_manage.FactorEdbSeries)
+		cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().PrimaryId, utils.GetOrmInReplace(len(req.SeriesIds)))
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.SeriesIds)
+		items, e := ob.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", ob.Cols().PrimaryId))
+		if e != nil {
+			err = fmt.Errorf("获取因子指标系列失败, %v", e)
+			return
+		}
+		for _, v := range items {
+			seriesIdItem[v.FactorEdbSeriesId] = v
+		}
+	}
+
+	// 获取因子指标
+	edbMappings := make([]*data_manage.FactorEdbSeriesMapping, 0)
+	edbInfoIds := make([]int, 0)
+	{
+		ob := new(data_manage.FactorEdbSeriesMapping)
+		cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().FactorEdbSeriesId, utils.GetOrmInReplace(len(req.SeriesIds)))
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.SeriesIds)
+		order := fmt.Sprintf("%s ASC, %s ASC", ob.Cols().FactorEdbSeriesId, ob.Cols().EdbInfoId)
+		items, e := ob.GetItemsByCondition(cond, pars, []string{}, order)
+		if e != nil {
+			err = fmt.Errorf("获取系列指标失败, %v", e)
+			return
+		}
+		for _, v := range items {
+			edbInfoIds = append(edbInfoIds, v.EdbInfoId)
+		}
+		edbMappings = items
+	}
+	edbIdItem := make(map[int]*data_manage.EdbInfo)
+	edbItems, e := data_manage.GetEdbInfoByIdList(edbInfoIds)
+	if e != nil {
+		err = fmt.Errorf("获取因子指标信息失败, %v", e)
+		return
+	}
+	for _, v := range edbItems {
+		edbIdItem[v.EdbInfoId] = v
+	}
+
+	calculateDataOb := new(data_manage.FactorEdbSeriesCalculateData)
+
+	calculateWorkers := make(chan struct{}, 10)
+	wg := sync.WaitGroup{}
+	edbExists := make(map[string]bool)
+	chartKeyMap := make(map[string]*data_manage.FactorEdbSeriesChartMapping)
+	for _, v := range edbMappings {
+		existsKey := fmt.Sprintf("%d-%d", v.FactorEdbSeriesId, v.EdbInfoId)
+		if edbExists[existsKey] {
+			continue
+		}
+		edbExists[existsKey] = true
+
+		edbItem := edbIdItem[v.EdbInfoId]
+		if edbItem == nil {
+			continue
+		}
+		seriesItem := seriesIdItem[v.FactorEdbSeriesId]
+		if seriesItem == nil {
+			continue
+		}
+
+		wg.Add(1)
+		go func(mapping *data_manage.FactorEdbSeriesMapping, edb *data_manage.EdbInfo, series *data_manage.FactorEdbSeries) {
+			defer func() {
+				wg.Done()
+				<-calculateWorkers
+			}()
+			calculateWorkers <- struct{}{}
+
+			var item data_manage.FactorEdbSeriesCorrelationMatrixItem
+			item.SeriesId = series.FactorEdbSeriesId
+			item.EdbInfoId = edb.EdbInfoId
+			item.EdbCode = edb.EdbCode
+			item.EdbName = edb.EdbName
+
+			// 指标来源
+			edbList := make([]*data_manage.ChartEdbInfoMapping, 0)
+			edbList = append(edbList, &data_manage.ChartEdbInfoMapping{
+				EdbInfoId:           edb.EdbInfoId,
+				EdbInfoCategoryType: edb.EdbInfoType,
+				EdbType:             edb.EdbType,
+				Source:              edb.Source,
+				SourceName:          edb.SourceName,
+			})
+			sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
+			item.SourceName = strings.Join(sourceNameList, ",")
+			item.SourceNameEn = strings.Join(sourceNameEnList, ",")
+
+			// 获取指标数据
+			dataListB := make([]*data_manage.EdbDataList, 0)
+			if series.CalculateState == data_manage.FactorEdbSeriesCalculated {
+				cond := fmt.Sprintf(" AND %s = ? AND %s = ?", calculateDataOb.Cols().FactorEdbSeriesId, calculateDataOb.Cols().EdbInfoId)
+				pars := make([]interface{}, 0)
+				pars = append(pars, mapping.FactorEdbSeriesId, mapping.EdbInfoId)
+				dataItems, e := calculateDataOb.GetItemsByCondition(cond, pars, []string{calculateDataOb.Cols().DataTime, calculateDataOb.Cols().Value}, fmt.Sprintf("%s ASC", calculateDataOb.Cols().DataTime))
+				if e != nil {
+					item.Msg = fmt.Sprintf("计算失败")
+					item.ErrMsg = fmt.Sprintf("获取计算数据失败, err: %v", e)
+					resp.Fail = append(resp.Fail, item)
+					return
+				}
+				dataListB = data_manage.TransEdbSeriesCalculateData2EdbDataList(dataItems)
+			} else {
+				switch edb.EdbInfoType {
+				case 0:
+					dataListB, e = data_manage.GetEdbDataList(edb.Source, edb.SubSource, edb.EdbInfoId, "", "")
+				case 1:
+					_, dataListB, _, _, e, _ = data.GetPredictDataListByPredictEdbInfoId(edb.EdbInfoId, "", "", false)
+				default:
+					item.Msg = fmt.Sprintf("计算失败")
+					item.ErrMsg = fmt.Sprintf("指标类型异常, edbType: %d", edb.EdbInfoType)
+					resp.Fail = append(resp.Fail, item)
+					return
+				}
+			}
+
+			// 计算相关性
+			xEdbIdValue, yDataList, e := CalculateCorrelation(req.Correlation.LeadValue, req.Correlation.LeadUnit, baseEdb.Frequency, edb.Frequency, dataListA, dataListB)
+			if e != nil {
+				item.Msg = fmt.Sprintf("计算失败")
+				item.ErrMsg = fmt.Sprintf("相关性计算失败, err: %v", e)
+				resp.Fail = append(resp.Fail, item)
+				return
+			}
+
+			// X及Y轴数据
+			yData := yDataList[0].Value
+			yLen := len(yData)
+			values := make([]data_manage.FactorEdbSeriesCorrelationMatrixValues, len(xEdbIdValue))
+			for k, x := range xEdbIdValue {
+				var y float64
+				if k >= 0 && k < yLen {
+					y = yData[k]
+				}
+				y = utils.SubFloatToFloat(y, 2)
+				values[k] = data_manage.FactorEdbSeriesCorrelationMatrixValues{
+					XData: x, YData: y,
+				}
+			}
+
+			// 图表关联
+			newMapping := new(data_manage.FactorEdbSeriesChartMapping)
+			newMapping.CalculateType = data_manage.FactorEdbSeriesChartCalculateTypeCorrelation
+
+			// 计算参数
+			var calculatePars data_manage.FactorEdbSeriesChartCalculateCorrelationReq
+			calculatePars.BaseEdbInfoId = req.BaseEdbInfoId
+			calculatePars.LeadValue = req.Correlation.LeadValue
+			calculatePars.LeadUnit = req.Correlation.LeadUnit
+			calculatePars.CalculateValue = req.Correlation.CalculateValue
+			calculatePars.CalculateUnit = req.Correlation.CalculateUnit
+			bc, e := json.Marshal(calculatePars)
+			if e != nil {
+				item.Msg = fmt.Sprintf("计算失败")
+				item.ErrMsg = fmt.Sprintf("计算参数JSON格式化失败, err: %v", e)
+				resp.Fail = append(resp.Fail, item)
+				return
+			}
+			newMapping.CalculatePars = string(bc)
+
+			// 计算结果, 注此处保存的是排序前的顺序
+			bv, e := json.Marshal(values)
+			if e != nil {
+				item.Msg = fmt.Sprintf("计算失败")
+				item.ErrMsg = fmt.Sprintf("计算结果JSON格式化失败, err: %v", e)
+				resp.Fail = append(resp.Fail, item)
+				return
+			}
+			newMapping.CalculateData = string(bv)
+			newMapping.FactorEdbSeriesId = mapping.FactorEdbSeriesId
+			newMapping.EdbInfoId = mapping.EdbInfoId
+			newMapping.CreateTime = time.Now().Local()
+			newMapping.ModifyTime = time.Now().Local()
+			chartKeyMap[existsKey] = newMapping
+
+			// 按照固定规则排期数[0 1 2 3 -1 -2 -3], 仅矩阵展示为此顺序
+			sort.Sort(data_manage.FactorEdbSeriesCorrelationMatrixOrder(values))
+			item.Msg = "计算成功"
+			item.Values = values
+			resp.Success = append(resp.Success, item)
+		}(v, edbItem, seriesItem)
+	}
+	wg.Wait()
+
+	// 新增图表关联, 此处按照顺序添加
+	chartMappings = make([]*data_manage.FactorEdbSeriesChartMapping, 0)
+	for _, v := range edbMappings {
+		k := fmt.Sprintf("%d-%d", v.FactorEdbSeriesId, v.EdbInfoId)
+		item := chartKeyMap[k]
+		if item == nil {
+			continue
+		}
+		chartMappings = append(chartMappings, item)
+	}
+	return
+}