Эх сурвалжийг харах

Merge branch 'eta_2.6.1_forecast_year_on_year_diff' into debug

kobe6258 1 өдөр өмнө
parent
commit
cf3805d1dc

+ 1 - 1
models/data_manage/request/predict_edb_info.go

@@ -41,7 +41,7 @@ type AddPredictEdbInfoReq struct {
 
 // RuleConfig 预测规则配置
 type RuleConfig struct {
-	RuleType     int                          `description:"预测规则,1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值,9:动态环差"`
+	RuleType     int                          `description:"预测规则,1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值,9:动态环差,17:动态同比,18:动态同差"`
 	Value        string                       `description:"值"`
 	EmptyType    int                          `description:"空值处理类型(0查找前后35天,1不计算,2前值填充,3后值填充,4等于0)"`
 	MaxEmptyType int                          `description:"MAX、MIN公式空值处理类型(1、等于0;2、跳过空值)"`

+ 7 - 2
services/data/predict_edb_info.go

@@ -612,7 +612,7 @@ func GetChartPredictEdbInfoDataListByConfList(predictEdbConfList []data_manage.P
 
 	predictEdbInfoData = make([]*data_manage.EdbDataList, 0)
 	//dataValue := lastDataValue
-	//预测规则,1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值
+	//预测规则,1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值,17:动态同比,18:动态同差
 
 	for _, predictEdbConf := range predictEdbConfList {
 		dataEndTime := endDate
@@ -814,8 +814,13 @@ func GetChartPredictEdbInfoDataListByConfList(predictEdbConfList []data_manage.P
 			if err != nil {
 				return
 			}
-		}
 
+		case 17, 18:
+			predictEdbInfoData, tmpMinValue, tmpMaxValue, err = GetChartPredictEdbInfoDataListByRuleDynamicYOYComparisonOrDifference(predictEdbConf.RuleType, predictEdbConf.PredictEdbInfoId, predictEdbConf.Value, dayList, realPredictEdbInfoData, existMap)
+			if err != nil {
+				return
+			}
+		}
 		// 下一个规则的开始日期
 		{
 			lenPredictEdbInfoData := len(predictEdbInfoData)

+ 159 - 25
services/data/predict_edb_info_rule.go

@@ -9,10 +9,18 @@ import (
 	"github.com/nosixtools/solarlunar"
 	"github.com/shopspring/decimal"
 	"math"
+	"strconv"
 	"strings"
 	"time"
 )
 
+var (
+	yoyMap = map[int]string{
+		17: "同比",
+		18: "同差",
+	}
+)
+
 type RuleParams struct {
 	EdbInfoId              int
 	DayList                []time.Time
@@ -1536,6 +1544,157 @@ type AnnualValueInversionConf struct {
 	YearList []int   `description:"指定年份列表"`
 }
 
+func getReplaceValue(replaceValueMap map[string]float64, days, dayStep int, currentDate time.Time) (replaceValue decimal.Decimal, success bool) {
+	nextDateDay := currentDate
+	for i := 0; i <= days; i++ {
+		replaceDateDayStr := nextDateDay.Format(utils.FormatDate)
+		if preValue, ok := replaceValueMap[replaceDateDayStr]; ok { //上一年同期->下一个月找到
+			replaceValue = decimal.NewFromFloat(preValue)
+			success = true
+			return
+		}
+		nextDateDay = nextDateDay.AddDate(0, 0, dayStep)
+	}
+	return decimal.NewFromInt(0), false
+}
+
+// GetChartPredictEdbInfoDataListByRuleDynamicYOYComparisonOrDifference 动态同比
+// 2、指标选择范围为预测指标。
+// 3、动态同比计算方法:预测值=去年同期值*(1+同比指标预测值)
+// 4、上述“去年同期”如果没有严格对应的日期,则前后查找最近35天的值。
+// 5、选择的同比指标日期需要与预测指标未来日期对应上,对应不上的不生成预测值。
+func GetChartPredictEdbInfoDataListByRuleDynamicYOYComparisonOrDifference(ruleType, edbInfoId int, configValue string, dayList []time.Time, realPredictEdbInfoData []*data_manage.EdbDataList, existMap map[string]float64) (newPredictEdbInfoData []*data_manage.EdbDataList, minValue, maxValue float64, err error) {
+	var yoyType string
+	if _, ok := yoyMap[ruleType]; !ok {
+		err = errors.New("计算规则不存在")
+		return
+	} else {
+		yoyType = yoyMap[ruleType]
+	}
+	//预测指标的去年同期数据
+	baseDynamicDataList := make(map[string]decimal.Decimal, len(dayList))
+	DynamicCalculateDataList := make(map[string]decimal.Decimal, len(dayList))
+	index := len(realPredictEdbInfoData)
+	if index <= 0 {
+		return
+	}
+	dynamicYOYComparisonIndexId, err := strconv.Atoi(configValue)
+	if err != nil {
+		return
+	}
+	newPredictEdbInfoData = make([]*data_manage.EdbDataList, 0, len(dayList))
+	// 获取同比预测指标的预测数据
+	dynamicYOYComparisonIndex, err := data_manage.GetEdbInfoById(dynamicYOYComparisonIndexId)
+	if err != nil {
+		return
+	}
+	if dynamicYOYComparisonIndex.EdbInfoType != 1 {
+		err = errors.New("选择的指标不是预测指标")
+		return
+	}
+	startDate, endDate := dayList[0].Format(utils.FormatDate), dayList[len(dayList)-1].Format(utils.FormatDate)
+	//获取动态同比指标对应预测日期的预测数据
+	dynamicYOYComparisonIndexDataList, err := data_manage.GetEdbDataList(dynamicYOYComparisonIndex.Source, dynamicYOYComparisonIndex.SubSource, dynamicYOYComparisonIndex.EdbInfoId, startDate, endDate)
+	if err != nil {
+		return
+	}
+	if len(dynamicYOYComparisonIndexDataList) <= 0 {
+		err = errors.New(fmt.Sprintf("选择%s指标没有预测数据", yoyType))
+		return
+	} else {
+		for _, v := range dynamicYOYComparisonIndexDataList {
+			DynamicCalculateDataList[v.DataTime] = decimal.NewFromFloat(v.Value)
+		}
+	}
+	//检查是不存在同期数据
+	for _, date := range dayList {
+		dayStr := date.Format(utils.FormatDate)
+		if _, ok := DynamicCalculateDataList[dayStr]; !ok {
+			err = errors.New(fmt.Sprintf("选择%s指标没有同期预测数据,日期:[%s]", yoyType, dayStr))
+			return
+		}
+	}
+	//获取上一期的同期数据
+	for _, date := range dayList {
+		preDate := date.AddDate(-1, 0, 0)
+		preDateStr := preDate.Format(utils.FormatDate)
+		if preValue, ok := existMap[preDateStr]; ok { //上一年同期找到
+			baseDynamicDataList[preDateStr] = decimal.NewFromFloat(preValue)
+		} else {
+			if baseDynamicDataList[preDateStr], ok = getReplaceValue(existMap, 0, -1, preDate); !ok {
+				err = errors.New(fmt.Sprintf("指标没有历史同期数据,Date:[%s]", preDateStr))
+				return
+			}
+		}
+	}
+
+	//获取后面的预测数据
+
+	for k, currentDate := range dayList {
+		var calculateValue decimal.Decimal
+		var dateStr = currentDate.Format(utils.FormatDate)
+		switch ruleType {
+		case 17:
+			calculateValue = baseDynamicDataList[dateStr].Mul(DynamicCalculateDataList[dateStr].Add(decimal.NewFromInt(1)))
+		case 18:
+			calculateValue = baseDynamicDataList[dateStr].Add(DynamicCalculateDataList[dateStr])
+		default:
+			err = errors.New("计算规则不存在")
+			return
+		}
+
+		tmpData := &data_manage.EdbDataList{
+			EdbDataId:     edbInfoId + 100000 + index + k,
+			EdbInfoId:     edbInfoId,
+			DataTime:      currentDate.Format(utils.FormatDate),
+			DataTimestamp: currentDate.UnixNano() / 1e6,
+		}
+		//currentItem := existMap[av]
+		var val = calculateValue.InexactFloat64()
+		tmpData.Value = val
+		newPredictEdbInfoData = append(newPredictEdbInfoData, tmpData)
+		existMap[tmpData.DataTime] = val
+		if k == 0 {
+			minValue = val
+			maxValue = val
+		} else {
+			// 最大最小值
+			if val < minValue {
+				minValue = val
+			}
+			if val > maxValue {
+				maxValue = val
+			}
+		}
+	}
+	return
+}
+
+// getYearListBySeasonConf 根据配置获取年份列表
+func getYearListBySeasonConf(configValue string) (yearList []int, seasonConf SeasonConf, err error) {
+	tmpErr := json.Unmarshal([]byte(configValue), &seasonConf)
+	if tmpErr != nil {
+		err = errors.New("年份配置信息异常:" + tmpErr.Error())
+		return
+	}
+	//选择方式,1:连续N年;2:指定年份
+	if seasonConf.YearType == 1 {
+		if seasonConf.NValue < 1 {
+			err = errors.New("连续N年不允许小于1")
+			return
+		}
+
+		currYear := time.Now().Year()
+		for i := 0; i < seasonConf.NValue; i++ {
+			yearList = append(yearList, currYear-i-1)
+		}
+	} else {
+		yearList = seasonConf.YearList
+	}
+
+	return
+}
+
 // GetChartPredictEdbInfoDataListByRuleAnnualValueInversion 根据 年度值倒推 规则获取预测数据
 // 预测指标-年度值倒推
 // 1、年度值倒推,选择同比法,支持选择多个年份(当前只可选择一个年份)。选择多个年份时,计算多个年份的余额平均,和同期平均。
@@ -1896,28 +2055,3 @@ func GetChartPredictEdbInfoDataListByRuleAnnualValueInversion(edbInfoId int, con
 
 	return
 }
-
-// getYearListBySeasonConf 根据配置获取年份列表
-func getYearListBySeasonConf(configValue string) (yearList []int, seasonConf SeasonConf, err error) {
-	tmpErr := json.Unmarshal([]byte(configValue), &seasonConf)
-	if tmpErr != nil {
-		err = errors.New("年份配置信息异常:" + tmpErr.Error())
-		return
-	}
-	//选择方式,1:连续N年;2:指定年份
-	if seasonConf.YearType == 1 {
-		if seasonConf.NValue < 1 {
-			err = errors.New("连续N年不允许小于1")
-			return
-		}
-
-		currYear := time.Now().Year()
-		for i := 0; i < seasonConf.NValue; i++ {
-			yearList = append(yearList, currYear-i-1)
-		}
-	} else {
-		yearList = seasonConf.YearList
-	}
-
-	return
-}