chart_info.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. package correlation
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "github.com/shopspring/decimal"
  7. "hongze/hongze_yb/models/response/chart_info"
  8. "hongze/hongze_yb/models/tables/chart_edb_mapping"
  9. "hongze/hongze_yb/models/tables/chart_info_correlation"
  10. "hongze/hongze_yb/models/tables/edb_data"
  11. edbDataModel "hongze/hongze_yb/models/tables/edb_data"
  12. "hongze/hongze_yb/models/tables/factor_edb_series"
  13. "hongze/hongze_yb/models/tables/factor_edb_series_chart_mapping"
  14. "hongze/hongze_yb/services/alarm_msg"
  15. "hongze/hongze_yb/services/chart"
  16. "hongze/hongze_yb/utils"
  17. "math"
  18. "strings"
  19. "time"
  20. )
  21. // HandleDataByLinearRegression 线性方程插值法补全数据
  22. func HandleDataByLinearRegression(originList []*edb_data.EdbDataList, handleDataMap map[string]float64) (newList []*edb_data.EdbDataList, err error) {
  23. if len(originList) < 2 {
  24. return
  25. }
  26. var startEdbInfoData *edb_data.EdbDataList
  27. for _, v := range originList {
  28. handleDataMap[v.DataTime] = v.Value
  29. // 第一个数据就给过滤了,给后面的试用
  30. if startEdbInfoData == nil {
  31. startEdbInfoData = v
  32. newList = append(newList, &edb_data.EdbDataList{
  33. DataTime: v.DataTime,
  34. Value: v.Value,
  35. })
  36. continue
  37. }
  38. // 获取两条数据之间相差的天数
  39. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
  40. currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  41. betweenHour := int(currDataTime.Sub(startDataTime).Hours())
  42. betweenDay := betweenHour / 24
  43. // 如果相差一天,那么过滤
  44. if betweenDay <= 1 {
  45. startEdbInfoData = v
  46. newList = append(newList, &edb_data.EdbDataList{
  47. DataTime: v.DataTime,
  48. Value: v.Value,
  49. })
  50. continue
  51. }
  52. // 生成线性方程式
  53. var a, b float64
  54. {
  55. coordinateData := make([]utils.Coordinate, 0)
  56. tmpCoordinate1 := utils.Coordinate{
  57. X: 1,
  58. Y: startEdbInfoData.Value,
  59. }
  60. coordinateData = append(coordinateData, tmpCoordinate1)
  61. tmpCoordinate2 := utils.Coordinate{
  62. X: float64(betweenDay) + 1,
  63. Y: v.Value,
  64. }
  65. coordinateData = append(coordinateData, tmpCoordinate2)
  66. a, b = utils.GetLinearResult(coordinateData)
  67. if math.IsNaN(a) || math.IsNaN(b) {
  68. err = fmt.Errorf("线性方程公式生成失败")
  69. return
  70. }
  71. }
  72. // 生成对应的值
  73. {
  74. for i := 1; i < betweenDay; i++ {
  75. tmpDataTime := startDataTime.AddDate(0, 0, i)
  76. aDecimal := decimal.NewFromFloat(a)
  77. xDecimal := decimal.NewFromInt(int64(i) + 1)
  78. bDecimal := decimal.NewFromFloat(b)
  79. val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
  80. handleDataMap[tmpDataTime.Format(utils.FormatDate)] = val
  81. newList = append(newList, &edb_data.EdbDataList{
  82. DataTime: tmpDataTime.Format(utils.FormatDate),
  83. Value: val,
  84. })
  85. }
  86. }
  87. // 最后将自己赋值
  88. newList = append(newList, &edb_data.EdbDataList{
  89. EdbDataId: v.EdbDataId,
  90. DataTime: v.DataTime,
  91. Value: v.Value,
  92. })
  93. startEdbInfoData = v
  94. }
  95. return
  96. }
  97. // MoveDataDaysToNewDataList 平移指标数据生成新的数据序列
  98. func MoveDataDaysToNewDataList(dataList []*edb_data.EdbDataList, moveDay int) (newDataList []edb_data.EdbDataList, dateDataMap map[string]float64) {
  99. dateMap := make(map[time.Time]float64)
  100. var minDate, maxDate time.Time
  101. dateDataMap = make(map[string]float64)
  102. for _, v := range dataList {
  103. currDate, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  104. if minDate.IsZero() || currDate.Before(minDate) {
  105. minDate = currDate
  106. }
  107. if maxDate.IsZero() || currDate.After(maxDate) {
  108. maxDate = currDate
  109. }
  110. dateMap[currDate] = v.Value
  111. }
  112. // 处理领先、滞后数据
  113. newDateMap := make(map[time.Time]float64)
  114. for currDate, value := range dateMap {
  115. newDate := currDate.AddDate(0, 0, moveDay)
  116. newDateMap[newDate] = value
  117. }
  118. minDate = minDate.AddDate(0, 0, moveDay)
  119. maxDate = maxDate.AddDate(0, 0, moveDay)
  120. // 获取日期相差日
  121. dayNum := utils.GetTimeSubDay(minDate, maxDate)
  122. for i := 0; i <= dayNum; i++ {
  123. currDate := minDate.AddDate(0, 0, i)
  124. tmpValue, ok := newDateMap[currDate]
  125. if !ok {
  126. //找不到数据,那么就用前面的数据吧
  127. if len(newDataList)-1 < 0 {
  128. tmpValue = 0
  129. } else {
  130. tmpValue = newDataList[len(newDataList)-1].Value
  131. }
  132. }
  133. tmpData := edb_data.EdbDataList{
  134. DataTime: currDate.Format(utils.FormatDate),
  135. Value: tmpValue,
  136. }
  137. dateDataMap[tmpData.DataTime] = tmpData.Value
  138. newDataList = append(newDataList, tmpData)
  139. }
  140. return
  141. }
  142. // GetChartEdbInfoFormat 相关性图表-获取指标信息
  143. func GetChartEdbInfoFormat(chartInfoId int, edbInfoMappingA, edbInfoMappingB *chart_edb_mapping.ChartEdbInfoMapping) (edbList []*chart_edb_mapping.ChartEdbInfoMappingList, err error) {
  144. edbList = make([]*chart_edb_mapping.ChartEdbInfoMappingList, 0)
  145. if edbInfoMappingA == nil || edbInfoMappingB == nil {
  146. err = fmt.Errorf("指标信息有误")
  147. return
  148. }
  149. edbInfoMappingA.FrequencyEn = chart.GetFrequencyEn(edbInfoMappingA.Frequency)
  150. if edbInfoMappingA.Unit == `无` {
  151. edbInfoMappingA.Unit = ``
  152. }
  153. if edbInfoMappingB.Unit == `无` {
  154. edbInfoMappingB.Unit = ``
  155. }
  156. if chartInfoId <= 0 {
  157. edbInfoMappingA.IsAxis = 1
  158. edbInfoMappingA.LeadValue = 0
  159. edbInfoMappingA.LeadUnit = ""
  160. edbInfoMappingA.ChartEdbMappingId = 0
  161. edbInfoMappingA.ChartInfoId = 0
  162. edbInfoMappingA.IsOrder = false
  163. edbInfoMappingA.EdbInfoType = 1
  164. edbInfoMappingA.ChartStyle = ""
  165. edbInfoMappingA.ChartColor = ""
  166. edbInfoMappingA.ChartWidth = 0
  167. edbInfoMappingB.IsAxis = 1
  168. edbInfoMappingB.LeadValue = 0
  169. edbInfoMappingB.LeadUnit = ""
  170. edbInfoMappingB.ChartEdbMappingId = 0
  171. edbInfoMappingB.ChartInfoId = 0
  172. edbInfoMappingB.IsOrder = false
  173. edbInfoMappingB.EdbInfoType = 1
  174. edbInfoMappingB.ChartStyle = ""
  175. edbInfoMappingB.ChartColor = ""
  176. edbInfoMappingB.ChartWidth = 0
  177. } else {
  178. edbInfoMappingA.LeadUnitEn = chart.GetLeadUnitEn(edbInfoMappingA.LeadUnit)
  179. edbInfoMappingB.LeadUnitEn = chart.GetLeadUnitEn(edbInfoMappingB.LeadUnit)
  180. }
  181. aList := new(chart_edb_mapping.ChartEdbInfoMappingList)
  182. aList.ChartEdbInfoMapping = *edbInfoMappingA
  183. bList := new(chart_edb_mapping.ChartEdbInfoMappingList)
  184. bList.ChartEdbInfoMapping = *edbInfoMappingB
  185. edbList = append(edbList, aList, bList)
  186. return
  187. }
  188. // GetChartDataByEdbInfo 相关性图表-根据指标信息获取x轴和y轴
  189. func GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *chart_edb_mapping.ChartEdbInfoMapping, leadValue int, leadUnit, startDate, endDate string) (xEdbIdValue []int, yDataList []chart_info.YData, err error) {
  190. xData := make([]int, 0)
  191. yData := make([]float64, 0)
  192. if leadValue == 0 {
  193. xData = append(xData, 0)
  194. }
  195. if leadValue > 0 {
  196. leadMin := 0 - leadValue
  197. xLen := 2*leadValue + 1
  198. for i := 0; i < xLen; i++ {
  199. n := leadMin + i
  200. xData = append(xData, n)
  201. }
  202. }
  203. // 计算窗口,不包含第一天
  204. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  205. startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
  206. //// 2023-03-02 时间序列始终以指标B为基准, 始终是A进行平移
  207. //baseEdbInfo := edbInfoMappingB
  208. //changeEdbInfo := edbInfoMappingA
  209. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  210. baseEdbInfo := edbInfoMappingA
  211. changeEdbInfo := edbInfoMappingB
  212. // 获取时间基准指标在时间区间内的值
  213. aDataList := make([]*edb_data.EdbDataList, 0)
  214. switch baseEdbInfo.EdbInfoCategoryType {
  215. case 0:
  216. aDataList, err = edb_data.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, startDate, endDate)
  217. case 1:
  218. _, aDataList, _, _, err, _ = chart.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
  219. default:
  220. err = errors.New("指标base类型异常")
  221. return
  222. }
  223. // 获取变频指标所有日期的值, 插值法完善数据
  224. bDataList := make([]*edb_data.EdbDataList, 0)
  225. switch changeEdbInfo.EdbInfoCategoryType {
  226. case 0:
  227. bDataList, err = edb_data.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.SubSource, changeEdbInfo.EdbInfoId, "", "")
  228. case 1:
  229. _, bDataList, _, _, err, _ = chart.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
  230. default:
  231. err = errors.New("指标change类型异常")
  232. return
  233. }
  234. //changeDataMap := make(map[string]float64)
  235. //newChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  236. //if e != nil {
  237. // err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  238. // return
  239. //}
  240. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  241. baseDataList := make([]*edb_data.EdbDataList, 0)
  242. baseDataMap := make(map[string]float64)
  243. changeDataList := make([]*edb_data.EdbDataList, 0)
  244. changeDataMap := make(map[string]float64)
  245. // 先把低频指标升频为高频
  246. {
  247. frequencyIntMap := map[string]int{
  248. "日度": 1,
  249. "周度": 2,
  250. "旬度": 3,
  251. "月度": 4,
  252. "季度": 5,
  253. "年度": 6,
  254. }
  255. // 如果A指标是高频,那么就需要对B指标进行升频
  256. if frequencyIntMap[edbInfoMappingA.Frequency] < frequencyIntMap[edbInfoMappingB.Frequency] {
  257. tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  258. if e != nil {
  259. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  260. return
  261. }
  262. changeDataList = tmpNewChangeDataList
  263. baseDataList = aDataList
  264. for _, v := range baseDataList {
  265. baseDataMap[v.DataTime] = v.Value
  266. }
  267. } else if frequencyIntMap[edbInfoMappingA.Frequency] > frequencyIntMap[edbInfoMappingB.Frequency] {
  268. // 如果B指标是高频,那么就需要对A指标进行升频
  269. tmpNewChangeDataList, e := HandleDataByLinearRegression(aDataList, baseDataMap)
  270. if e != nil {
  271. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  272. return
  273. }
  274. baseDataList = tmpNewChangeDataList
  275. changeDataList = bDataList
  276. for _, v := range changeDataList {
  277. changeDataMap[v.DataTime] = v.Value
  278. }
  279. } else {
  280. baseDataList = aDataList
  281. for _, v := range baseDataList {
  282. baseDataMap[v.DataTime] = v.Value
  283. }
  284. changeDataList = bDataList
  285. for _, v := range changeDataList {
  286. changeDataMap[v.DataTime] = v.Value
  287. }
  288. }
  289. }
  290. // 计算不领先也不滞后时的相关系数
  291. baseCalculateData := make([]float64, 0)
  292. baseDataTimeArr := make([]string, 0)
  293. for i := range baseDataList {
  294. baseDataTimeArr = append(baseDataTimeArr, baseDataList[i].DataTime)
  295. baseCalculateData = append(baseCalculateData, baseDataList[i].Value)
  296. }
  297. //zeroBaseData := make([]float64, 0)
  298. //zeroCalculateData := make([]float64, 0)
  299. //for i := range baseDataTimeArr {
  300. // tmpBaseVal, ok1 := baseDataMap[baseDataTimeArr[i]]
  301. // tmpCalculateVal, ok2 := changeDataMap[baseDataTimeArr[i]]
  302. // if ok1 && ok2 {
  303. // zeroBaseData = append(zeroBaseData, tmpBaseVal)
  304. // zeroCalculateData = append(zeroCalculateData, tmpCalculateVal)
  305. // }
  306. //}
  307. //if len(zeroBaseData) != len(zeroCalculateData) {
  308. // err = fmt.Errorf("相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(zeroCalculateData))
  309. // return
  310. //}
  311. //zeroRatio := utils.CalculateCorrelationByIntArr(zeroBaseData, zeroCalculateData)
  312. //if leadValue == 0 {
  313. // yData = append(yData, zeroRatio)
  314. //}
  315. // 计算领先/滞后N期
  316. if leadValue > 0 {
  317. // 平移变频指标领先/滞后的日期(单位天)
  318. moveUnitDays := utils.FrequencyDaysMap[leadUnit]
  319. for i := range xData {
  320. //if xData[i] == 0 {
  321. // yData = append(yData, zeroRatio)
  322. // continue
  323. //}
  324. xCalculateData := make([]float64, 0)
  325. yCalculateData := make([]float64, 0)
  326. // 平移指定天数
  327. mDays := int(moveUnitDays) * xData[i]
  328. _, dMap := MoveDataDaysToNewDataList(changeDataList, mDays)
  329. // 取出对应的基准日期的值
  330. for i2 := range baseDataTimeArr {
  331. if yVal, ok := dMap[baseDataTimeArr[i2]]; ok {
  332. xCalculateData = append(xCalculateData, baseCalculateData[i2])
  333. yCalculateData = append(yCalculateData, yVal)
  334. }
  335. }
  336. if len(yCalculateData) <= 0 {
  337. //err = fmt.Errorf("领先滞后相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(yCalculateData))
  338. //return
  339. // 领先滞后后,没有可以计算的数据了
  340. continue
  341. }
  342. // 公式计算出领先/滞后频度对应点的相关性系数
  343. ratio := utils.CalculateCorrelationByIntArr(xCalculateData, yCalculateData)
  344. yData = append(yData, ratio)
  345. }
  346. }
  347. xEdbIdValue = xData
  348. yDataList = make([]chart_info.YData, 0)
  349. yDate := "0000-00-00"
  350. yDataList = append(yDataList, chart_info.YData{
  351. Date: yDate,
  352. Value: yData,
  353. })
  354. return
  355. }
  356. // RollingCorrelationChartDataResp 滚动相关性图的数据
  357. type RollingCorrelationChartDataResp struct {
  358. MaxData float64
  359. MinData float64
  360. LatestDate string `description:"真实数据的最后日期"`
  361. EdbInfoCategoryType int
  362. ChartColor string
  363. ChartStyle string
  364. PredictChartColor string
  365. ChartType int
  366. ChartWidth int
  367. EdbName string
  368. EdbNameEn string
  369. Unit string
  370. UnitEn string
  371. IsAxis int
  372. DataList []edbDataModel.EdbDataList
  373. }
  374. // GetRollingCorrelationChartDataByEdbInfo 滚动相关性计算
  375. func GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *chart_edb_mapping.ChartEdbInfoMapping, leadValue int, leadUnit string, calculateValue int, calculateUnit string, startDate, endDate, chartName, chartNameEn string) (dataResp RollingCorrelationChartDataResp, err error) {
  376. dataResp = RollingCorrelationChartDataResp{
  377. DataList: make([]edbDataModel.EdbDataList, 0),
  378. MaxData: 0,
  379. MinData: 0,
  380. ChartColor: "#00f",
  381. ChartStyle: `spline`,
  382. PredictChartColor: `#00f`,
  383. ChartType: 0,
  384. ChartWidth: 3,
  385. EdbName: chartName,
  386. EdbNameEn: chartNameEn,
  387. IsAxis: 1,
  388. }
  389. dataList := make([]edbDataModel.EdbDataList, 0)
  390. // 计算窗口,不包含第一天
  391. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  392. startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
  393. baseEdbInfo := edbInfoMappingA
  394. changeEdbInfo := edbInfoMappingB
  395. // 获取时间基准指标在时间区间内的值
  396. aDataList := make([]*edb_data.EdbDataList, 0)
  397. switch baseEdbInfo.EdbInfoCategoryType {
  398. case 0:
  399. aDataList, err = edb_data.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, startDate, endDate)
  400. case 1:
  401. _, aDataList, _, _, err, _ = chart.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
  402. default:
  403. err = errors.New("指标base类型异常")
  404. return
  405. }
  406. // 获取变频指标所有日期的值, 插值法完善数据
  407. bDataList := make([]*edb_data.EdbDataList, 0)
  408. switch changeEdbInfo.EdbInfoCategoryType {
  409. case 0:
  410. bDataList, err = edb_data.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.SubSource, changeEdbInfo.EdbInfoId, "", "")
  411. case 1:
  412. _, bDataList, _, _, err, _ = chart.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
  413. default:
  414. err = errors.New("指标change类型异常")
  415. return
  416. }
  417. // 数据平移变频指标领先/滞后的日期(单位天)
  418. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  419. //baseDataList := make([]*edb_data.EdbDataList, 0)
  420. baseDataMap := make(map[string]float64)
  421. changeDataList := make([]*edb_data.EdbDataList, 0)
  422. changeDataMap := make(map[string]float64)
  423. // A指标不管三七二十一,先变个频再说
  424. {
  425. _, e := HandleDataByLinearRegression(aDataList, baseDataMap)
  426. if e != nil {
  427. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  428. return
  429. }
  430. //baseDataList = tmpNewChangeDataList
  431. }
  432. // B指标不管三七二十一,先变个频再说
  433. {
  434. tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  435. if e != nil {
  436. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  437. return
  438. }
  439. changeDataList = tmpNewChangeDataList
  440. // 平移下日期
  441. moveUnitDays := utils.FrequencyDaysMap[leadUnit]
  442. _, changeDataMap = MoveDataDaysToNewDataList(changeDataList, leadValue*moveUnitDays)
  443. }
  444. // 计算计算时,需要多少个日期内数据
  445. calculateDay := utils.FrequencyDaysMap[calculateUnit] * calculateValue
  446. // 计算 每个日期的相关性值
  447. {
  448. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  449. if endDate == `` {
  450. // 因为时间格式是:2023-07-19T00:00:00+08:00;所以需要分开
  451. endDateList := strings.Split(baseEdbInfo.EndDate, "T")
  452. endDate = endDateList[0]
  453. }
  454. endDateTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  455. endDateTime = endDateTime.AddDate(0, 0, -(calculateDay - 1))
  456. // 是否开始第一条数据
  457. var isStart, isNotFirst bool
  458. for currDay := startDateTime; !currDay.After(endDateTime); currDay = currDay.AddDate(0, 0, 1) {
  459. yCalculateData := make([]float64, 0)
  460. baseCalculateData := make([]float64, 0)
  461. // 取出对应的基准日期的值
  462. for i := 0; i < calculateDay; i++ {
  463. iDay := currDay.AddDate(0, 0, i).Format(utils.FormatDate)
  464. tmpBaseValue, ok1 := baseDataMap[iDay]
  465. tmpChangeValue, ok2 := changeDataMap[iDay]
  466. if ok1 && ok2 {
  467. baseCalculateData = append(baseCalculateData, tmpBaseValue)
  468. yCalculateData = append(yCalculateData, tmpChangeValue)
  469. } else {
  470. continue
  471. }
  472. }
  473. // 公式计算出领先/滞后频度对应点的相关性系数
  474. var ratio float64
  475. if len(baseCalculateData) > 0 {
  476. ratio = utils.CalculateCorrelationByIntArr(baseCalculateData, yCalculateData)
  477. } else {
  478. // 没有数据的话,那就不返回
  479. continue
  480. }
  481. // 过滤前面都是0的数据
  482. {
  483. if ratio != 0 {
  484. isStart = true
  485. }
  486. if !isStart {
  487. continue
  488. }
  489. }
  490. dataTime := currDay.AddDate(0, 0, calculateDay-1)
  491. dataList = append(dataList, edbDataModel.EdbDataList{
  492. //EdbDataId: 0,
  493. EdbInfoId: 0,
  494. DataTime: dataTime.Format(utils.FormatDate),
  495. DataTimestamp: dataTime.UnixNano() / 1e6,
  496. Value: ratio,
  497. })
  498. if !isNotFirst {
  499. dataResp.MinData = ratio
  500. dataResp.MaxData = ratio
  501. isNotFirst = true
  502. }
  503. if dataResp.MinData > ratio {
  504. dataResp.MinData = ratio
  505. }
  506. if dataResp.MaxData < ratio {
  507. dataResp.MaxData = ratio
  508. }
  509. }
  510. dataResp.DataList = dataList
  511. }
  512. return
  513. }
  514. // ChartInfoRefresh 图表刷新
  515. func ChartInfoRefresh(chartInfoId int) (err error) {
  516. var errMsg string
  517. defer func() {
  518. if err != nil {
  519. //fmt.Println(err.Error())
  520. go alarm_msg.SendAlarmMsg("CorrelationChartInfoRefresh: "+errMsg, 3)
  521. }
  522. }()
  523. correlationChart := new(chart_info_correlation.ChartInfoCorrelation)
  524. if err = correlationChart.GetItemById(chartInfoId); err != nil {
  525. errMsg = "获取相关性图表失败, Err: " + err.Error()
  526. return
  527. }
  528. // 批量刷新ETA指标
  529. err, errMsg = chart.EdbInfoRefreshAllFromBase([]int{correlationChart.EdbInfoIdFirst, correlationChart.EdbInfoIdSecond}, false)
  530. if err != nil {
  531. return
  532. }
  533. // 重新生成数据并更新
  534. edbInfoMappingA, err := chart_edb_mapping.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdFirst)
  535. if err != nil {
  536. errMsg = "获取相关性图表, A指标mapping信息失败, Err:" + err.Error()
  537. return
  538. }
  539. edbInfoMappingB, err := chart_edb_mapping.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdSecond)
  540. if err != nil {
  541. errMsg = "获取相关性图表, B指标mapping信息失败, Err:" + err.Error()
  542. return
  543. }
  544. periodData, correlationData, err := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, correlationChart.StartDate.Format(utils.FormatDate), correlationChart.EndDate.Format(utils.FormatDate))
  545. if err != nil {
  546. errMsg = "获取相关性图表, 图表计算值失败, Err:" + err.Error()
  547. return
  548. }
  549. periodDataByte, err := json.Marshal(periodData)
  550. if err != nil {
  551. errMsg = "相关性图表, X轴信息有误, Err:" + err.Error()
  552. return
  553. }
  554. correlationDataByte, err := json.Marshal(correlationData[0].Value)
  555. if err != nil {
  556. errMsg = "相关性图表, Y轴信息有误, Err:" + err.Error()
  557. return
  558. }
  559. correlationChart.PeriodData = string(periodDataByte)
  560. correlationChart.CorrelationData = string(correlationDataByte)
  561. correlationChart.ModifyTime = time.Now().Local()
  562. correlationUpdateCols := []string{"PeriodData", "CorrelationData", "ModifyTime"}
  563. if err = correlationChart.Update(correlationUpdateCols); err != nil {
  564. errMsg = "更新相关性图表失败, Err:" + err.Error()
  565. return
  566. }
  567. return
  568. }
  569. // GetFactorChartDataByChartId 获取多因子相关性图表数据
  570. func GetFactorChartDataByChartId(chartInfoId int, extraConfig string) (xEdbIdValue []int, yDataList []chart_info.YData, err error) {
  571. if chartInfoId <= 0 {
  572. return
  573. }
  574. // 指标对应的图例
  575. extra := new(chart_info_correlation.CorrelationChartInfoExtraConfig)
  576. if extraConfig != "" {
  577. if e := json.Unmarshal([]byte(extraConfig), extra); e != nil {
  578. err = fmt.Errorf("解析图表额外配置失败, err: %v", e)
  579. return
  580. }
  581. }
  582. legends := make(map[string]*chart_info_correlation.CorrelationChartLegend)
  583. if extra != nil {
  584. for _, v := range extra.LegendConfig {
  585. s := fmt.Sprintf("%d-%d", v.SeriesId, v.EdbInfoId)
  586. legends[s] = v
  587. }
  588. }
  589. // 获取图表引用到的系列指标
  590. chartMappings, e := factor_edb_series_chart_mapping.GetChartUsedFactorSeriesEdb(chartInfoId)
  591. if e != nil {
  592. err = fmt.Errorf("获取图表引用系列指标失败, err: %v", e)
  593. return
  594. }
  595. // 取出计算结果
  596. yDataList = make([]chart_info.YData, 0)
  597. yDate := "0000-00-00"
  598. for k, m := range chartMappings {
  599. var values []factor_edb_series.FactorEdbSeriesCorrelationMatrixValues
  600. if m.CalculateData != "" {
  601. e = json.Unmarshal([]byte(m.CalculateData), &values)
  602. if e != nil {
  603. err = fmt.Errorf("系列指标计算数据有误, err: %v", e)
  604. return
  605. }
  606. }
  607. var y []float64
  608. for _, v := range values {
  609. if k == 0 {
  610. xEdbIdValue = append(xEdbIdValue, v.XData)
  611. }
  612. y = append(y, v.YData)
  613. }
  614. var yData chart_info.YData
  615. yData.Date = yDate
  616. yData.Value = y
  617. yData.SeriesEdb.SeriesId = m.FactorEdbSeriesId
  618. yData.SeriesEdb.EdbInfoId = m.EdbInfoId
  619. // 图例
  620. s := fmt.Sprintf("%d-%d", m.FactorEdbSeriesId, m.EdbInfoId)
  621. legend := legends[s]
  622. if legend != nil {
  623. yData.Name = legend.LegendName
  624. yData.Color = legend.Color
  625. }
  626. yDataList = append(yDataList, yData)
  627. }
  628. return
  629. }