Browse Source

预测区间计算

xyxie 7 months ago
parent
commit
4f29328461
2 changed files with 351 additions and 14 deletions
  1. 335 0
      models/predict_edb_data_calculate_qjjs.go
  2. 16 14
      utils/constants.go

+ 335 - 0
models/predict_edb_data_calculate_qjjs.go

@@ -0,0 +1,335 @@
+package models
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_index_lib/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/shopspring/decimal"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type PredictCalculateRangeAnalysis struct {
+}
+
+func (obj PredictCalculateRangeAnalysis) Add(params AddCalculateBatchParams) (edbInfo *EdbInfo, latestDateStr string, latestValue float64, err error, errMsg string) {
+	req := params.Req
+	edbCode := params.EdbCode
+	uniqueCode := params.UniqueCode
+	sysUserId := params.SysUserId
+	sysUserRealName := params.SysUserRealName
+	//req *EdbInfoCalculateBatchSaveReq, edbCode, uniqueCode string, sysUserId int, sysUserRealName string
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("AddCalculateRangeAnalysis,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	if req.EdbInfoId > 0 {
+		err = errors.New("无法新增")
+		return
+	}
+
+	edbInfo = new(EdbInfo)
+	edbInfo.Source = obj.GetSource()
+	edbInfo.SourceName = obj.GetSourceName()
+	edbInfo.EdbCode = edbCode
+	edbInfo.EdbName = req.EdbName
+	edbInfo.EdbNameSource = req.EdbName
+	edbInfo.Frequency = req.Frequency
+	edbInfo.Unit = req.Unit
+	edbInfo.ClassifyId = req.ClassifyId
+	edbInfo.SysUserId = sysUserId
+	edbInfo.SysUserRealName = sysUserRealName
+	edbInfo.CreateTime = time.Now()
+	edbInfo.ModifyTime = time.Now()
+	edbInfo.UniqueCode = uniqueCode
+	edbInfo.CalculateFormula = req.CalculateFormula
+	edbInfo.EdbNameEn = req.EdbName
+	edbInfo.UnitEn = req.Unit
+	edbInfo.EdbType = obj.GetEdbType()
+	newEdbInfoId, tmpErr := to.Insert(edbInfo)
+	if tmpErr != nil {
+		err = tmpErr
+		return
+	}
+	edbInfo.EdbInfoId = int(newEdbInfoId)
+
+	//关联关系
+	fromEdbInfo, e := GetEdbInfoById(req.FromEdbInfoId)
+	if e != nil {
+		err = fmt.Errorf("获取来源指标失败,Err:%s", e.Error())
+		return
+	}
+
+	calculateMappingItem := new(EdbInfoCalculateMapping)
+	calculateMappingItem.CreateTime = time.Now()
+	calculateMappingItem.ModifyTime = time.Now()
+	calculateMappingItem.Sort = 1
+	calculateMappingItem.EdbCode = edbCode
+	calculateMappingItem.EdbInfoId = edbInfo.EdbInfoId
+	calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
+	calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
+	calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
+	calculateMappingItem.FromSource = fromEdbInfo.Source
+	calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
+	calculateMappingItem.FromTag = ""
+	calculateMappingItem.Source = edbInfo.Source
+	calculateMappingItem.SourceName = edbInfo.SourceName
+	calculateMappingItem.FromSubSource = edbInfo.SubSource
+
+	_, err = to.Insert(calculateMappingItem)
+	if err != nil {
+		return
+	}
+
+	//计算数据
+	latestDateStr, latestValue, err, errMsg = obj.refresh(to, edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, fromEdbInfo, edbInfo.EdbCode, edbInfo.CalculateFormula)
+
+	return
+}
+
+func (obj PredictCalculateRangeAnalysis) Edit(params EditCalculateBatchParams) (latestDateStr string, latestValue float64, err error, errMsg string) {
+	edbInfo := params.EdbInfo
+	req := params.Req
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("EditCalculateRangeAnalysis,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	//修改指标信息
+	edbInfo.EdbName = req.EdbName
+	edbInfo.EdbNameSource = req.EdbName
+	edbInfo.Frequency = req.Frequency
+	edbInfo.Unit = req.Unit
+	edbInfo.ClassifyId = req.ClassifyId
+	edbInfo.CalculateFormula = req.CalculateFormula
+	edbInfo.EdbNameEn = req.EdbNameEn
+	edbInfo.UnitEn = req.UnitEn
+	edbInfo.ModifyTime = time.Now()
+	_, err = to.Update(edbInfo, "EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId", "CalculateFormula", "ModifyTime", "EdbNameEn", "UnitEn")
+	if err != nil {
+		return
+	}
+
+	//删除,计算指标关联的,基础指标的关联关系
+	sql := ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? `
+	_, err = to.Raw(sql, edbInfo.EdbInfoId).Exec()
+	if err != nil {
+		err = errors.New("删除计算指标关联关系失败,Err:" + err.Error())
+		return
+	}
+	//清空原有数据
+	tableName := GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
+	sql = ` DELETE FROM ` + tableName + ` WHERE edb_info_id = ? `
+	_, err = to.Raw(sql, edbInfo.EdbInfoId).Exec()
+	if err != nil {
+		return
+	}
+
+	fromEdbInfo, e := GetEdbInfoById(req.FromEdbInfoId)
+	if e != nil {
+		err = fmt.Errorf("获取来源指标失败,Err:%s", e.Error())
+		return
+	}
+
+	calculateMappingItem := new(EdbInfoCalculateMapping)
+	calculateMappingItem.CreateTime = time.Now()
+	calculateMappingItem.ModifyTime = time.Now()
+	calculateMappingItem.Sort = 1
+	calculateMappingItem.EdbCode = edbInfo.EdbCode
+	calculateMappingItem.EdbInfoId = edbInfo.EdbInfoId
+	calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
+	calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
+	calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
+	calculateMappingItem.FromSource = fromEdbInfo.Source
+	calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
+	calculateMappingItem.FromTag = ""
+	calculateMappingItem.Source = edbInfo.Source
+	calculateMappingItem.SourceName = edbInfo.SourceName
+	calculateMappingItem.FromSubSource = edbInfo.SubSource
+
+	_, err = to.Insert(calculateMappingItem)
+	if err != nil {
+		return
+	}
+
+	//计算数据
+	latestDateStr, latestValue, err, errMsg = obj.refresh(to, edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, fromEdbInfo, edbInfo.EdbCode, edbInfo.CalculateFormula)
+
+	return
+}
+
+func (obj PredictCalculateRangeAnalysis) Refresh(params RefreshParams) (latestDateStr string, latestValue float64, err error, errMsg string) {
+	edbInfo := params.EdbInfo
+	edbInfoCalculateDetailList, err := GetEdbInfoCalculateDetailList(edbInfo.EdbInfoId)
+	if err != nil {
+		return
+	}
+	var fromEdbInfo *EdbInfo
+	for _, v := range edbInfoCalculateDetailList {
+		fromEdbInfo, _ = GetEdbInfoById(v.FromEdbInfoId)
+		break
+	}
+
+	if fromEdbInfo == nil {
+		errMsg = "指标异常"
+		err = errors.New(errMsg)
+		return
+	}
+
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("RefreshAllCalculateRangeAnalysis,Err:" + err.Error())
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	// 计算数据
+	latestDateStr, latestValue, err, errMsg = obj.refresh(to, edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, fromEdbInfo, edbInfo.EdbCode, edbInfo.CalculateFormula)
+
+	return
+}
+
+func (obj PredictCalculateRangeAnalysis) refresh(to orm.TxOrmer, edbInfoId, source, subSource int, fromEdbInfo *EdbInfo, edbCode, calculateFormula string) (latestDateStr string, latestValue float64, err error, errMsg string) {
+	edbInfoIdStr := strconv.Itoa(edbInfoId)
+	tableName := GetEdbDataTableName(obj.GetSource(), utils.DATA_SUB_SOURCE_EDB)
+
+	//获取扩散指数指标所有数据
+	existDataList, err := GetAllEdbDataListByTo(to, edbInfoId, source, subSource)
+	if err != nil {
+		return
+	}
+	latestDateStr = fromEdbInfo.LatestDate
+	//计算指标的map
+	existDataMap := make(map[string]*EdbData, 0)
+	removeDateMap := make(map[string]string)
+	for _, v := range existDataList {
+		existDataMap[v.DataTime] = v
+		removeDateMap[v.DataTime] = ``
+	}
+	var rangeAnalysisConf RangeAnalysisCalculateFormula
+	//fmt.Println("calculateFormula:", calculateFormula)
+	err = json.Unmarshal([]byte(calculateFormula), &rangeAnalysisConf)
+	if err != nil {
+		err = fmt.Errorf("解析区间计算公式失败 %s", err.Error())
+		return
+	}
+
+	rangeAnalysisChartData, err := GetRangeAnalysisChartDataByEdbInfo(to, fromEdbInfo, rangeAnalysisConf)
+	if err != nil {
+		err = fmt.Errorf("获取区间计算数据失败 %s", err.Error())
+		return
+	}
+	addSql := ` INSERT INTO ` + tableName + ` (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	var isAdd bool
+
+	for _, item := range rangeAnalysisChartData {
+		currDateStr := item.DataTime
+		currVal := item.Value
+		// 判断扩散指数指标是否存在数据
+		if existData, ok := existDataMap[currDateStr]; ok {
+			// 处理扩散指数数据的值
+			existValStr := existData.Value
+			existValDeci, tmpErr := decimal.NewFromString(existValStr)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			existVal, _ := existValDeci.Round(4).Float64()
+			// 判断扩散指数数据的值 与 当前计算出来的结果, 如果两个数据结果不相等的话,那么就修改咯
+			if existVal != currVal {
+				err = ModifyEdbDataById(source, subSource, existData.EdbDataId, fmt.Sprint(currVal))
+				if err != nil {
+					return
+				}
+			}
+		} else {
+			// 直接入库
+			timestamp := item.DataTimestamp
+			timestampStr := fmt.Sprintf("%d", timestamp)
+			addSql += GetAddSql(edbInfoIdStr, edbCode, currDateStr, timestampStr, fmt.Sprint(currVal))
+			isAdd = true
+		}
+
+		delete(removeDateMap, currDateStr)
+	}
+
+	// 数据入库
+	{
+
+		if isAdd {
+			addSql = strings.TrimRight(addSql, ",")
+			_, err = to.Raw(addSql).Exec()
+		}
+
+		// 移除不存在的日期数据
+		if len(removeDateMap) > 0 {
+			removeDateList := make([]string, 0) //需要移除的日期
+			for k := range removeDateMap {
+				removeDateList = append(removeDateList, k)
+			}
+			removeDateStr := strings.Join(removeDateList, `","`)
+			removeDateStr = `"` + removeDateStr + `"`
+			sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? and data_time in (%s) `, tableName, removeDateStr)
+			_, err = to.Raw(sql, edbInfoId).Exec()
+			if err != nil {
+				err = fmt.Errorf("删除扩散指数指标数据失败,Err:" + err.Error())
+				return
+			}
+		}
+	}
+	//确定实际数据的最终值
+	{
+		finalLast, tmpErr := GetFinalLastByTo(to, edbInfoId, obj.GetSource(), utils.DATA_SUB_SOURCE_EDB, fromEdbInfo.LatestDate)
+		if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+			return
+		}
+		if tmpErr == nil {
+			latestDateStr = finalLast.DataTime
+			latestValue = finalLast.Value
+		}
+	}
+	return
+}
+
+// GetSource 获取来源编码id
+func (obj PredictCalculateRangeAnalysis) GetSource() int {
+	return utils.DATA_SOURCE_PREDICT_CALCULATE_RANGEANLYSIS
+}
+
+// GetSourceName 获取来源名称
+func (obj PredictCalculateRangeAnalysis) GetSourceName() string {
+	return utils.DATA_SOURCE_NAME_PREDICT_CALCULATE_RANGEANLYSIS
+}
+
+// GetEdbType 获取指标类型
+func (obj PredictCalculateRangeAnalysis) GetEdbType() int {
+	return utils.CALCULATE_EDB_TYPE
+}

+ 16 - 14
utils/constants.go

@@ -99,18 +99,19 @@ const (
 	DATA_SOURCE_CALCULATE_ZDYFX                                 // 自定义分析->74
 	DATA_SOURCE_CALCULATE_RJZ                                   // 日均值计算->75
 
-	DATA_SOURCE_YONYI                  = 76 //涌益咨询
-	DATA_SOURCE_FENWEI                 = 77 //汾渭煤炭
-	DATA_SOURCE_GFEX                   = 78 // 广州期货交易所->78
-	DATA_SOURCE_ICPI                   = 79 // ICPI消费价格指数->79
-	DATA_SOURCE_MTJH                   = 80 // 煤炭江湖->80
-	DATA_SOURCE_CALCULATE_SUM          = 81
-	DATA_SOURCE_CALCULATE_AVG          = 82
-	DATA_SOURCE_BLOOMBERG              = 83 // bloomberg彭博数据
-	DATA_SOURCE_BUSINESS               = 84 // 来源于自有数据
-	DATA_SOURCE_SCI99                  = 85 // 卓创资讯
-	DATA_SOURCE_CCF                    = 86 // CCF化纤信息
-	DATA_SOURCE_CALCULATE_RANGEANLYSIS = 87 //区间计算->87
+	DATA_SOURCE_YONYI                          = 76 //涌益咨询
+	DATA_SOURCE_FENWEI                         = 77 //汾渭煤炭
+	DATA_SOURCE_GFEX                           = 78 // 广州期货交易所->78
+	DATA_SOURCE_ICPI                           = 79 // ICPI消费价格指数->79
+	DATA_SOURCE_MTJH                           = 80 // 煤炭江湖->80
+	DATA_SOURCE_CALCULATE_SUM                  = 81
+	DATA_SOURCE_CALCULATE_AVG                  = 82
+	DATA_SOURCE_BLOOMBERG                      = 83 // bloomberg彭博数据
+	DATA_SOURCE_BUSINESS                       = 84 // 来源于自有数据
+	DATA_SOURCE_SCI99                          = 85 // 卓创资讯
+	DATA_SOURCE_CCF                            = 86 // CCF化纤信息
+	DATA_SOURCE_CALCULATE_RANGEANLYSIS         = 87 //区间计算->87
+	DATA_SOURCE_PREDICT_CALCULATE_RANGEANLYSIS = 90 // 预测指标区间计算->90
 )
 
 // 指标来源的中文展示
@@ -196,8 +197,9 @@ const (
 	DATA_SOURCE_NAME_CALCULATE_SUM                        = `多指标求和`
 	DATA_SOURCE_NAME_CALCULATE_AVG                        = `多指标求平均`
 	DATA_SOURCE_NAME_BUSINESS                             = `自有数据`
-	DATA_SOURCE_NAME_CCF                                  = `CCF`  // CCF化纤信息
-	DATA_SOURCE_NAME_CALCULATE_RANGEANLYSIS               = `区间计算` //区间计算->87
+	DATA_SOURCE_NAME_CCF                                  = `CCF`    // CCF化纤信息
+	DATA_SOURCE_NAME_CALCULATE_RANGEANLYSIS               = `区间计算`   //区间计算->87
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_RANGEANLYSIS       = `预测区间计算` //区间计算->90
 )
 
 // 基础数据初始化日期