|
@@ -14,6 +14,7 @@ import (
|
|
|
"sort"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
+ "sync"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
@@ -1632,3 +1633,275 @@ func RemoveCorrelationRelate(chartInfoId int) (err error) {
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+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
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ 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
|
|
|
+
|
|
|
+
|
|
|
+ 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
|
|
|
+}
|