123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- package services
- import (
- "encoding/json"
- aiPredictModel "eta/eta_api/models/ai_predict_model"
- "eta/eta_api/models/data_manage"
- "eta/eta_api/services/data"
- "eta/eta_api/utils"
- "fmt"
- "sort"
- "strconv"
- "time"
- )
- func ImportAiPredictModelIndexAndData(imports []*aiPredictModel.AiPredictModelImportData, adminId int, adminRealName string) (err error) {
- if len(imports) == 0 {
- return
- }
- // 查询已存在的标的
- indexOb := new(aiPredictModel.AiPredictModelIndex)
- indexNameItem := make(map[string]*aiPredictModel.AiPredictModelIndex)
- {
- list, e := indexOb.GetItemsByCondition("", make([]interface{}, 0), []string{}, "")
- if e != nil {
- err = fmt.Errorf("获取标的失败, %v", e)
- return
- }
- for _, v := range list {
- indexNameItem[v.IndexName] = v
- }
- }
- updateCols := []string{indexOb.Cols().ClassifyId, indexOb.Cols().ModelFramework, indexOb.Cols().PredictDate, indexOb.Cols().PredictValue, indexOb.Cols().DirectionAccuracy, indexOb.Cols().AbsoluteDeviation, indexOb.Cols().ExtraConfig, indexOb.Cols().SysUserId, indexOb.Cols().SysUserRealName, indexOb.Cols().ModifyTime}
- updateIndexes := make([]*aiPredictModel.AiPredictModelImportData, 0)
- createIndexes := make([]*aiPredictModel.AiPredictModelImportData, 0)
- for _, v := range imports {
- exist := indexNameItem[v.Index.IndexName]
- // 编辑
- if exist != nil {
- // 图例信息
- if exist.ExtraConfig != "" && v.Index.ExtraConfig != "" {
- var oldConfig, newConfig aiPredictModel.AiPredictModelIndexExtraConfig
- if e := json.Unmarshal([]byte(exist.ExtraConfig), &oldConfig); e != nil {
- err = fmt.Errorf("标的原配置解析失败, Config: %s, Err: %v", exist.ExtraConfig, e)
- return
- }
- if e := json.Unmarshal([]byte(v.Index.ExtraConfig), &newConfig); e != nil {
- err = fmt.Errorf("标的新配置解析失败, Config: %s, Err: %v", v.Index.ExtraConfig, e)
- return
- }
- oldConfig.DailyChart.PredictLegendName = newConfig.DailyChart.PredictLegendName
- b, _ := json.Marshal(oldConfig)
- v.Index.ExtraConfig = string(b)
- }
- v.Index.AiPredictModelIndexId = exist.AiPredictModelIndexId
- v.Index.IndexCode = exist.IndexCode
- updateIndexes = append(updateIndexes, v)
- continue
- }
- // 新增标的/图表
- indexCode, e := utils.GenerateEdbCode(1, "IPM")
- if e != nil {
- err = fmt.Errorf("生成标的编码失败, %v", e)
- return
- }
- v.Index.IndexCode = indexCode
- v.Charts = GetAiPredictCharts(v.Index.IndexName, adminId, adminRealName)
- createIndexes = append(createIndexes, v)
- }
- // 新增/更新指标
- chartIds, e := indexOb.ImportIndexAndData(createIndexes, updateIndexes, updateCols)
- if e != nil {
- err = fmt.Errorf("导入指标失败, %v", e)
- return
- }
- // 更新图表ES
- if len(chartIds) == 0 {
- return
- }
- go func() {
- for _, v := range chartIds {
- data.EsAddOrEditChartInfo(v)
- }
- }()
- return
- }
- func GetAiPredictChartDetailByData(indexItem *aiPredictModel.AiPredictModelIndex, indexData []*aiPredictModel.AiPredictModelData, source int) (resp *data_manage.ChartInfoDetailResp, err error) {
- resp = new(data_manage.ChartInfoDetailResp)
- // 标的配置
- var extraConfig aiPredictModel.AiPredictModelIndexExtraConfig
- if indexItem.ExtraConfig != "" {
- if e := json.Unmarshal([]byte(indexItem.ExtraConfig), &extraConfig); e != nil {
- err = fmt.Errorf("标的额外配置解析失败, Config: %s, Err: %v", indexItem.ExtraConfig, e)
- return
- }
- }
- // 图表信息
- var predictLegendName, confLeftMin, confLeftMax, unit string
- if source == aiPredictModel.ModelDataSourceDaily {
- predictLegendName = extraConfig.DailyChart.PredictLegendName
- if predictLegendName == "" {
- predictLegendName = "Predicted"
- }
- unit = extraConfig.DailyChart.Unit
- confLeftMin = extraConfig.DailyChart.LeftMin
- confLeftMax = extraConfig.DailyChart.LeftMax
- }
- if source == aiPredictModel.ModelDataSourceMonthly {
- predictLegendName = "预测值"
- unit = extraConfig.MonthlyChart.Unit
- confLeftMin = extraConfig.MonthlyChart.LeftMin
- confLeftMax = extraConfig.MonthlyChart.LeftMax
- }
- // 这里简单兼容下吧,暂时就不修数据了
- if confLeftMin == "" {
- confLeftMin = indexItem.LeftMin
- }
- if confLeftMax == "" {
- confLeftMax = indexItem.LeftMax
- }
- // 获取指标对应的图表
- chartSourceMapping := map[int]int{
- aiPredictModel.ModelDataSourceMonthly: utils.CHART_SOURCE_AI_PREDICT_MODEL_MONTHLY,
- aiPredictModel.ModelDataSourceDaily: utils.CHART_SOURCE_AI_PREDICT_MODEL_DAILY,
- }
- chartInfo, e := data_manage.GetAiPredictChartInfoByIndexId(chartSourceMapping[source], indexItem.AiPredictModelIndexId)
- if e != nil && !utils.IsErrNoRow(e) {
- err = fmt.Errorf("获取标的图表失败, %v", e)
- return
- }
- // 获取曲线图主题样式
- chartView := new(data_manage.ChartInfoView)
- if chartInfo != nil && chartInfo.ChartInfoId > 0 {
- chartView.ChartInfoId = chartInfo.ChartInfoId
- chartView.ChartName = chartInfo.ChartName
- chartView.ChartNameEn = chartInfo.ChartNameEn
- chartView.Source = chartInfo.Source
- } else {
- chartView.ChartName = indexItem.IndexName
- chartView.ChartNameEn = indexItem.IndexName
- }
- chartView.ChartType = utils.CHART_SOURCE_DEFAULT
- chartTheme, e := data.GetChartThemeConfig(0, chartView.ChartType, utils.CHART_TYPE_CURVE)
- if e != nil {
- err = fmt.Errorf("获取图表主题样式失败, %v", e)
- return
- }
- chartView.ChartThemeStyle = chartTheme.Config
- chartView.ChartThemeId = chartTheme.ChartThemeId
- chartView.ChartName = indexItem.IndexName
- chartView.ChartNameEn = indexItem.IndexName
- chartView.DateType = 3
- chartView.Calendar = "公历"
- chartView.ChartSource = "AI预测模型"
- chartView.ChartSourceEn = "AI预测模型"
- chartView.Unit = unit
- chartView.UnitEn = unit
- // EdbList-固定一条为标的实际值、一条为预测值
- edbList := make([]*data_manage.ChartEdbInfoMapping, 0)
- edbActual, edbPredict := new(data_manage.ChartEdbInfoMapping), new(data_manage.ChartEdbInfoMapping)
- edbActual.EdbName = indexItem.IndexName
- edbActual.EdbNameEn = indexItem.IndexName
- edbActual.IsAxis = 1
- edbActual.Unit = unit
- edbActual.UnitEn = unit
- edbPredict.EdbName = predictLegendName
- edbPredict.EdbNameEn = predictLegendName
- edbPredict.IsAxis = 1
- edbPredict.Unit = unit
- edbPredict.UnitEn = unit
- actualData, predictData := make([]*data_manage.EdbDataList, 0), make([]*data_manage.EdbDataList, 0)
- var startDate, endDate time.Time
- var actualValues, predictValues []float64
- var actualNewest, predictNewest bool
- var actualLatestTimestamp int64 // 实际值最后一天的时间戳,作为日度图表的分割线
- for k, v := range indexData {
- // 如果实际值和预测值都是null那么该日期无效直接忽略
- if !v.Value.Valid && !v.PredictValue.Valid {
- continue
- }
- // 将有效值加入[]float64,最后取极值
- if v.Value.Valid {
- actualValues = append(actualValues, v.Value.Float64)
- }
- if v.PredictValue.Valid {
- predictValues = append(predictValues, v.PredictValue.Float64)
- }
- // 开始结束时间
- if k == 0 {
- startDate = v.DataTime
- endDate = v.CreateTime
- }
- if v.DataTime.Before(startDate) {
- startDate = v.DataTime
- }
- if v.DataTime.After(endDate) {
- endDate = v.DataTime
- }
- // 指标数据
- if v.Value.Valid {
- if !actualNewest {
- edbActual.LatestDate = v.DataTime.Format(utils.FormatDate)
- edbActual.LatestValue = v.Value.Float64
- actualLatestTimestamp = v.DataTime.UnixNano() / 1e6
- actualNewest = true
- }
- actualData = append(actualData, &data_manage.EdbDataList{
- DataTime: v.DataTime.Format(utils.FormatDate),
- Value: v.Value.Float64,
- DataTimestamp: v.DataTimestamp,
- })
- }
- if v.PredictValue.Valid {
- if !predictNewest {
- edbPredict.LatestDate = v.DataTime.Format(utils.FormatDate)
- edbPredict.LatestValue = v.Value.Float64
- predictNewest = true
- }
- predictData = append(predictData, &data_manage.EdbDataList{
- DataTime: v.DataTime.Format(utils.FormatDate),
- Value: v.PredictValue.Float64,
- DataTimestamp: v.DataTimestamp,
- })
- }
- }
- // 图表数据这里均做一个升序排序
- sort.Slice(actualData, func(i, j int) bool {
- return actualData[i].DataTimestamp < actualData[j].DataTimestamp
- })
- sort.Slice(predictData, func(i, j int) bool {
- return predictData[i].DataTimestamp < predictData[j].DataTimestamp
- })
- // 极值
- actualMin, actualMax := utils.FindMinMax(actualValues)
- predictMin, predictMax := utils.FindMinMax(predictValues)
- edbActual.MinData = actualMin
- edbActual.MaxData = actualMax
- edbPredict.MinData = predictMin
- edbPredict.MaxData = predictMax
- edbActual.DataList = actualData
- edbPredict.DataList = predictData
- edbList = append(edbList, edbActual, edbPredict)
- // 上下限
- if confLeftMin != "" {
- chartView.LeftMin = confLeftMin
- } else {
- leftMin := actualMin
- if leftMin > predictMin {
- leftMin = predictMin
- }
- chartView.LeftMin = fmt.Sprint(leftMin)
- }
- if confLeftMax != "" {
- chartView.LeftMax = confLeftMax
- } else {
- leftMax := actualMax
- if leftMax < predictMax {
- leftMax = predictMax
- }
- chartView.LeftMax = fmt.Sprint(leftMax)
- }
- chartView.StartDate = startDate.Format(utils.FormatDate)
- chartView.EndDate = endDate.Format(utils.FormatDate)
- // 日度图表的分割线日期
- if source == aiPredictModel.ModelDataSourceDaily {
- var dataResp struct {
- ActualLatestTimestamp int64
- }
- dataResp.ActualLatestTimestamp = actualLatestTimestamp
- resp.DataResp = dataResp
- }
- resp.ChartInfo = chartView
- resp.EdbInfoList = edbList
- return
- }
- // GetAiPredictCharts 获取AI预测模型图表
- func GetAiPredictCharts(indexName string, adminId int, adminRealName string) (charts []*aiPredictModel.AiPredictModelImportCharts) {
- charts = make([]*aiPredictModel.AiPredictModelImportCharts, 0)
- // 日度/月度图表
- frequencyArr := []int{aiPredictModel.ModelDataSourceMonthly, aiPredictModel.ModelDataSourceDaily}
- sourceMapping := map[int]int{
- aiPredictModel.ModelDataSourceMonthly: utils.CHART_SOURCE_AI_PREDICT_MODEL_MONTHLY,
- aiPredictModel.ModelDataSourceDaily: utils.CHART_SOURCE_AI_PREDICT_MODEL_DAILY,
- }
- suffixNameMapping := map[int]string{
- aiPredictModel.ModelDataSourceMonthly: "预测模型/回测",
- aiPredictModel.ModelDataSourceDaily: "预测模型",
- }
- for _, v := range frequencyArr {
- chartSource := sourceMapping[v]
- newChart := new(aiPredictModel.AiPredictModelImportCharts)
- // 新增图表
- chartName := fmt.Sprintf("%s%s", indexName, suffixNameMapping[v])
- chartInfo := new(data_manage.ChartInfo)
- chartInfo.ChartName = chartName
- chartInfo.ChartNameEn = chartName
- chartInfo.ChartType = utils.CHART_TYPE_CURVE
- chartInfo.Calendar = "公历"
- chartInfo.SysUserId = adminId
- chartInfo.SysUserRealName = adminRealName
- chartInfo.CreateTime = time.Now()
- chartInfo.ModifyTime = time.Now()
- chartInfo.Source = chartSource
- time.Sleep(time.Microsecond)
- chartInfo.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + strconv.FormatInt(time.Now().UnixNano(), 10))
- newChart.ChartInfo = chartInfo
- // chart_edb_mapping中edb_info_id为标的ID
- edbMapping := new(data_manage.ChartEdbMapping)
- //edbMapping.EdbInfoId = indexId
- //edbMapping.UniqueCode = utils.MD5(fmt.Sprint(utils.CHART_PREFIX, "_", indexId, "_", strconv.FormatInt(time.Now().UnixNano(), 10)))
- edbMapping.Source = chartSource
- edbMapping.CreateTime = time.Now().Local()
- edbMapping.ModifyTime = time.Now().Local()
- newChart.EdbMappings = append(newChart.EdbMappings, edbMapping)
- charts = append(charts, newChart)
- }
- return
- }
- // FixAiPredictCharts 修复AI预测模型图表
- func FixAiPredictCharts() {
- var err error
- defer func() {
- if err != nil {
- fmt.Println(err)
- }
- fmt.Println("修复完成")
- }()
- fmt.Println("开始修复")
- indexOb := new(aiPredictModel.AiPredictModelIndex)
- indexes, e := indexOb.GetItemsByCondition("", make([]interface{}, 0), []string{}, "")
- if e != nil {
- err = fmt.Errorf("获取所有标的失败, %v", e)
- return
- }
- // 日度/月度图表
- frequencyArr := []int{aiPredictModel.ModelDataSourceMonthly, aiPredictModel.ModelDataSourceDaily}
- sourceMapping := map[int]int{
- aiPredictModel.ModelDataSourceMonthly: utils.CHART_SOURCE_AI_PREDICT_MODEL_MONTHLY,
- aiPredictModel.ModelDataSourceDaily: utils.CHART_SOURCE_AI_PREDICT_MODEL_DAILY,
- }
- suffixNameMapping := map[int]string{
- aiPredictModel.ModelDataSourceMonthly: "预测模型/回测",
- aiPredictModel.ModelDataSourceDaily: "预测模型",
- }
- chartOb := new(data_manage.ChartInfo)
- for _, v := range indexes {
- for _, fre := range frequencyArr {
- chartSource := sourceMapping[fre]
- item, e := data_manage.GetAiPredictChartInfoByIndexId(chartSource, v.AiPredictModelIndexId)
- if e != nil && !utils.IsErrNoRow(e) {
- err = fmt.Errorf("获取AI预测模型图表失败, %v", e)
- return
- }
- // 由于标的名称是固定的所以chart_info没有什么可更新的, 已加入过就忽略
- if item != nil && item.ChartInfoId > 0 {
- fmt.Printf("标的%d-%d图表已存在, continue\n", v.AiPredictModelIndexId, chartSource)
- continue
- }
- // 新增图表
- chartName := fmt.Sprintf("%s%s", v.IndexName, suffixNameMapping[fre])
- chartInfo := new(data_manage.ChartInfo)
- chartInfo.ChartName = chartName
- chartInfo.ChartNameEn = chartName
- chartInfo.ChartType = utils.CHART_TYPE_CURVE
- chartInfo.Calendar = "公历"
- chartInfo.SysUserId = v.SysUserId
- chartInfo.SysUserRealName = v.SysUserRealName
- chartInfo.CreateTime = time.Now()
- chartInfo.ModifyTime = time.Now()
- chartInfo.Source = chartSource
- time.Sleep(time.Microsecond)
- chartInfo.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + strconv.FormatInt(time.Now().UnixNano(), 10))
- // chart_edb_mapping中edb_info_id为标的ID
- mappings := make([]*data_manage.ChartEdbMapping, 0)
- edbMapping := new(data_manage.ChartEdbMapping)
- edbMapping.EdbInfoId = v.AiPredictModelIndexId
- edbMapping.UniqueCode = utils.MD5(fmt.Sprint(utils.CHART_PREFIX, "_", v.AiPredictModelIndexId, "_", strconv.FormatInt(time.Now().UnixNano(), 10)))
- edbMapping.Source = chartSource
- edbMapping.CreateTime = time.Now().Local()
- edbMapping.ModifyTime = time.Now().Local()
- mappings = append(mappings, edbMapping)
- // 新增图表
- if e = chartOb.AddChartInfoAndEdbMappings(chartInfo, mappings); e != nil {
- err = fmt.Errorf("新增图表及mapping失败, %v", e)
- return
- }
- // 写入ES
- if chartInfo.ChartInfoId <= 0 {
- err = fmt.Errorf("图表ID有误")
- return
- }
- go data.EsAddOrEditChartInfo(chartInfo.ChartInfoId)
- }
- }
- return
- }
|