ai_predict_model_index.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. package services
  2. import (
  3. "encoding/json"
  4. aiPredictModel "eta/eta_api/models/ai_predict_model"
  5. "eta/eta_api/models/data_manage"
  6. "eta/eta_api/services/data"
  7. "eta/eta_api/utils"
  8. "fmt"
  9. "sort"
  10. "time"
  11. )
  12. func ImportAiPredictModelIndexAndData(imports []*aiPredictModel.AiPredictModelImportData) (err error) {
  13. if len(imports) == 0 {
  14. return
  15. }
  16. // 查询已存在的标的
  17. indexOb := new(aiPredictModel.AiPredictModelIndex)
  18. indexNameItem := make(map[string]*aiPredictModel.AiPredictModelIndex)
  19. {
  20. list, e := indexOb.GetItemsByCondition("", make([]interface{}, 0), []string{}, "")
  21. if e != nil {
  22. err = fmt.Errorf("获取标的失败, %v", e)
  23. return
  24. }
  25. for _, v := range list {
  26. indexNameItem[v.IndexName] = v
  27. }
  28. }
  29. 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}
  30. updateIndexes := make([]*aiPredictModel.AiPredictModelImportData, 0)
  31. createIndexes := make([]*aiPredictModel.AiPredictModelImportData, 0)
  32. for _, v := range imports {
  33. exist := indexNameItem[v.Index.IndexName]
  34. // 编辑
  35. if exist != nil {
  36. // 图例信息
  37. if exist.ExtraConfig != "" && v.Index.ExtraConfig != "" {
  38. var oldConfig, newConfig aiPredictModel.AiPredictModelIndexExtraConfig
  39. if e := json.Unmarshal([]byte(exist.ExtraConfig), &oldConfig); e != nil {
  40. err = fmt.Errorf("标的原配置解析失败, Config: %s, Err: %v", exist.ExtraConfig, e)
  41. return
  42. }
  43. if e := json.Unmarshal([]byte(v.Index.ExtraConfig), &newConfig); e != nil {
  44. err = fmt.Errorf("标的新配置解析失败, Config: %s, Err: %v", v.Index.ExtraConfig, e)
  45. return
  46. }
  47. oldConfig.DailyChart.PredictLegendName = newConfig.DailyChart.PredictLegendName
  48. b, _ := json.Marshal(oldConfig)
  49. v.Index.ExtraConfig = string(b)
  50. }
  51. v.Index.AiPredictModelIndexId = exist.AiPredictModelIndexId
  52. v.Index.IndexCode = exist.IndexCode
  53. updateIndexes = append(updateIndexes, v)
  54. continue
  55. }
  56. // 新增
  57. indexCode, e := utils.GenerateEdbCode(1, "IPM")
  58. if e != nil {
  59. err = fmt.Errorf("生成标的编码失败, %v", e)
  60. return
  61. }
  62. v.Index.IndexCode = indexCode
  63. createIndexes = append(createIndexes, v)
  64. }
  65. // 新增/更新指标
  66. if e := indexOb.ImportIndexAndData(createIndexes, updateIndexes, updateCols); e != nil {
  67. err = fmt.Errorf("导入指标失败, %v", e)
  68. return
  69. }
  70. return
  71. }
  72. func GetAiPredictChartDetailByData(indexItem *aiPredictModel.AiPredictModelIndex, indexData []*aiPredictModel.AiPredictModelData, source int) (resp *data_manage.ChartInfoDetailResp, err error) {
  73. resp = new(data_manage.ChartInfoDetailResp)
  74. // 标的配置
  75. var extraConfig aiPredictModel.AiPredictModelIndexExtraConfig
  76. if indexItem.ExtraConfig != "" {
  77. if e := json.Unmarshal([]byte(indexItem.ExtraConfig), &extraConfig); e != nil {
  78. err = fmt.Errorf("标的额外配置解析失败, Config: %s, Err: %v", indexItem.ExtraConfig, e)
  79. return
  80. }
  81. }
  82. // 图表信息
  83. var predictLegendName, confLeftMin, confLeftMax, unit string
  84. if source == aiPredictModel.ModelDataSourceDaily {
  85. predictLegendName = extraConfig.DailyChart.PredictLegendName
  86. if predictLegendName == "" {
  87. predictLegendName = "Predicted"
  88. }
  89. unit = extraConfig.DailyChart.Unit
  90. confLeftMin = extraConfig.DailyChart.LeftMin
  91. confLeftMax = extraConfig.DailyChart.LeftMax
  92. }
  93. if source == aiPredictModel.ModelDataSourceMonthly {
  94. predictLegendName = "预测值"
  95. unit = extraConfig.MonthlyChart.Unit
  96. confLeftMin = extraConfig.MonthlyChart.LeftMin
  97. confLeftMax = extraConfig.MonthlyChart.LeftMax
  98. }
  99. // 这里简单兼容下吧,暂时就不修数据了
  100. if confLeftMin == "" {
  101. confLeftMin = indexItem.LeftMin
  102. }
  103. if confLeftMax == "" {
  104. confLeftMax = indexItem.LeftMax
  105. }
  106. // 获取曲线图主题样式
  107. chartView := new(data_manage.ChartInfoView)
  108. chartView.ChartType = utils.CHART_SOURCE_DEFAULT
  109. chartTheme, e := data.GetChartThemeConfig(0, chartView.ChartType, utils.CHART_TYPE_CURVE)
  110. if e != nil {
  111. err = fmt.Errorf("获取图表主题样式失败, %v", e)
  112. return
  113. }
  114. chartView.ChartThemeStyle = chartTheme.Config
  115. chartView.ChartThemeId = chartTheme.ChartThemeId
  116. chartView.ChartName = indexItem.IndexName
  117. chartView.ChartNameEn = indexItem.IndexName
  118. chartView.DateType = 3
  119. chartView.Calendar = "公历"
  120. chartView.ChartSource = "AI预测模型"
  121. chartView.ChartSourceEn = "AI预测模型"
  122. chartView.Unit = unit
  123. chartView.UnitEn = unit
  124. // EdbList-固定一条为标的实际值、一条为预测值
  125. edbList := make([]*data_manage.ChartEdbInfoMapping, 0)
  126. edbActual, edbPredict := new(data_manage.ChartEdbInfoMapping), new(data_manage.ChartEdbInfoMapping)
  127. edbActual.EdbName = indexItem.IndexName
  128. edbActual.EdbNameEn = indexItem.IndexName
  129. edbActual.IsAxis = 1
  130. edbActual.Unit = unit
  131. edbActual.UnitEn = unit
  132. edbPredict.EdbName = predictLegendName
  133. edbPredict.EdbNameEn = predictLegendName
  134. edbPredict.IsAxis = 1
  135. edbPredict.Unit = unit
  136. edbPredict.UnitEn = unit
  137. actualData, predictData := make([]*data_manage.EdbDataList, 0), make([]*data_manage.EdbDataList, 0)
  138. var startDate, endDate time.Time
  139. var actualValues, predictValues []float64
  140. var actualNewest, predictNewest bool
  141. var actualLatestTimestamp int64 // 实际值最后一天的时间戳,作为日度图表的分割线
  142. for k, v := range indexData {
  143. // 如果实际值和预测值都是null那么该日期无效直接忽略
  144. if !v.Value.Valid && !v.PredictValue.Valid {
  145. continue
  146. }
  147. // 将有效值加入[]float64,最后取极值
  148. if v.Value.Valid {
  149. actualValues = append(actualValues, v.Value.Float64)
  150. }
  151. if v.PredictValue.Valid {
  152. predictValues = append(predictValues, v.PredictValue.Float64)
  153. }
  154. // 开始结束时间
  155. if k == 0 {
  156. startDate = v.DataTime
  157. endDate = v.CreateTime
  158. }
  159. if v.DataTime.Before(startDate) {
  160. startDate = v.DataTime
  161. }
  162. if v.DataTime.After(endDate) {
  163. endDate = v.DataTime
  164. }
  165. // 指标数据
  166. if v.Value.Valid {
  167. if !actualNewest {
  168. edbActual.LatestDate = v.DataTime.Format(utils.FormatDate)
  169. edbActual.LatestValue = v.Value.Float64
  170. actualLatestTimestamp = v.DataTime.UnixNano() / 1e6
  171. actualNewest = true
  172. }
  173. actualData = append(actualData, &data_manage.EdbDataList{
  174. DataTime: v.DataTime.Format(utils.FormatDate),
  175. Value: v.Value.Float64,
  176. DataTimestamp: v.DataTimestamp,
  177. })
  178. }
  179. if v.PredictValue.Valid {
  180. if !predictNewest {
  181. edbPredict.LatestDate = v.DataTime.Format(utils.FormatDate)
  182. edbPredict.LatestValue = v.Value.Float64
  183. predictNewest = true
  184. }
  185. predictData = append(predictData, &data_manage.EdbDataList{
  186. DataTime: v.DataTime.Format(utils.FormatDate),
  187. Value: v.PredictValue.Float64,
  188. DataTimestamp: v.DataTimestamp,
  189. })
  190. }
  191. }
  192. // 图表数据这里均做一个升序排序
  193. sort.Slice(actualData, func(i, j int) bool {
  194. return actualData[i].DataTimestamp < actualData[j].DataTimestamp
  195. })
  196. sort.Slice(predictData, func(i, j int) bool {
  197. return predictData[i].DataTimestamp < predictData[j].DataTimestamp
  198. })
  199. // 极值
  200. actualMin, actualMax := utils.FindMinMax(actualValues)
  201. predictMin, predictMax := utils.FindMinMax(predictValues)
  202. edbActual.MinData = actualMin
  203. edbActual.MaxData = actualMax
  204. edbPredict.MinData = predictMin
  205. edbPredict.MaxData = predictMax
  206. edbActual.DataList = actualData
  207. edbPredict.DataList = predictData
  208. edbList = append(edbList, edbActual, edbPredict)
  209. // 上下限
  210. if confLeftMin != "" {
  211. chartView.LeftMin = confLeftMin
  212. } else {
  213. leftMin := actualMin
  214. if leftMin > predictMin {
  215. leftMin = predictMin
  216. }
  217. chartView.LeftMin = fmt.Sprint(leftMin)
  218. }
  219. if confLeftMax != "" {
  220. chartView.LeftMax = confLeftMax
  221. } else {
  222. leftMax := actualMax
  223. if leftMax < predictMax {
  224. leftMax = predictMax
  225. }
  226. chartView.LeftMax = fmt.Sprint(leftMax)
  227. }
  228. chartView.StartDate = startDate.Format(utils.FormatDate)
  229. chartView.EndDate = endDate.Format(utils.FormatDate)
  230. // 日度图表的分割线日期
  231. if source == aiPredictModel.ModelDataSourceDaily {
  232. var dataResp struct {
  233. ActualLatestTimestamp int64
  234. }
  235. dataResp.ActualLatestTimestamp = actualLatestTimestamp
  236. resp.DataResp = dataResp
  237. }
  238. resp.ChartInfo = chartView
  239. resp.EdbInfoList = edbList
  240. return
  241. }