chart_info.go 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907
  1. package correlation
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "eta/eta_api/models/data_manage"
  6. "eta/eta_api/models/system"
  7. "eta/eta_api/services/alarm_msg"
  8. "eta/eta_api/services/data"
  9. "eta/eta_api/utils"
  10. "fmt"
  11. "github.com/shopspring/decimal"
  12. "math"
  13. "sort"
  14. "strconv"
  15. "strings"
  16. "sync"
  17. "time"
  18. )
  19. // HandleDataByLinearRegression 线性方程插值法补全数据
  20. func HandleDataByLinearRegression(originList []*data_manage.EdbDataList, handleDataMap map[string]float64) (newList []*data_manage.EdbDataList, err error) {
  21. if len(originList) < 2 {
  22. return
  23. }
  24. var startEdbInfoData *data_manage.EdbDataList
  25. for _, v := range originList {
  26. handleDataMap[v.DataTime] = v.Value
  27. // 第一个数据就给过滤了,给后面的试用
  28. if startEdbInfoData == nil {
  29. startEdbInfoData = v
  30. newList = append(newList, &data_manage.EdbDataList{
  31. DataTime: v.DataTime,
  32. Value: v.Value,
  33. })
  34. continue
  35. }
  36. // 获取两条数据之间相差的天数
  37. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
  38. currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  39. betweenHour := int(currDataTime.Sub(startDataTime).Hours())
  40. betweenDay := betweenHour / 24
  41. // 如果相差一天,那么过滤
  42. if betweenDay <= 1 {
  43. startEdbInfoData = v
  44. newList = append(newList, &data_manage.EdbDataList{
  45. DataTime: v.DataTime,
  46. Value: v.Value,
  47. })
  48. continue
  49. }
  50. // 生成线性方程式
  51. var a, b float64
  52. {
  53. coordinateData := make([]utils.Coordinate, 0)
  54. tmpCoordinate1 := utils.Coordinate{
  55. X: 1,
  56. Y: startEdbInfoData.Value,
  57. }
  58. coordinateData = append(coordinateData, tmpCoordinate1)
  59. tmpCoordinate2 := utils.Coordinate{
  60. X: float64(betweenDay) + 1,
  61. Y: v.Value,
  62. }
  63. coordinateData = append(coordinateData, tmpCoordinate2)
  64. a, b = utils.GetLinearResult(coordinateData)
  65. if math.IsNaN(a) || math.IsNaN(b) {
  66. err = fmt.Errorf("线性方程公式生成失败")
  67. return
  68. }
  69. }
  70. // 生成对应的值
  71. {
  72. for i := 1; i < betweenDay; i++ {
  73. tmpDataTime := startDataTime.AddDate(0, 0, i)
  74. aDecimal := decimal.NewFromFloat(a)
  75. xDecimal := decimal.NewFromInt(int64(i) + 1)
  76. bDecimal := decimal.NewFromFloat(b)
  77. val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
  78. handleDataMap[tmpDataTime.Format(utils.FormatDate)] = val
  79. newList = append(newList, &data_manage.EdbDataList{
  80. DataTime: tmpDataTime.Format(utils.FormatDate),
  81. Value: val,
  82. })
  83. }
  84. }
  85. // 最后将自己赋值
  86. newList = append(newList, &data_manage.EdbDataList{
  87. EdbDataId: v.EdbDataId,
  88. DataTime: v.DataTime,
  89. Value: v.Value,
  90. })
  91. startEdbInfoData = v
  92. }
  93. return
  94. }
  95. // MoveDataDaysToNewDataList 平移指标数据生成新的数据序列
  96. func MoveDataDaysToNewDataList(dataList []*data_manage.EdbDataList, moveDay int) (newDataList []data_manage.EdbDataList, dateDataMap map[string]float64) {
  97. dateMap := make(map[time.Time]float64)
  98. var minDate, maxDate time.Time
  99. dateDataMap = make(map[string]float64)
  100. for _, v := range dataList {
  101. currDate, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  102. if minDate.IsZero() || currDate.Before(minDate) {
  103. minDate = currDate
  104. }
  105. if maxDate.IsZero() || currDate.After(maxDate) {
  106. maxDate = currDate
  107. }
  108. dateMap[currDate] = v.Value
  109. }
  110. // 处理领先、滞后数据
  111. newDateMap := make(map[time.Time]float64)
  112. for currDate, value := range dateMap {
  113. newDate := currDate.AddDate(0, 0, moveDay)
  114. newDateMap[newDate] = value
  115. }
  116. minDate = minDate.AddDate(0, 0, moveDay)
  117. maxDate = maxDate.AddDate(0, 0, moveDay)
  118. // 获取日期相差日
  119. dayNum := utils.GetTimeSubDay(minDate, maxDate)
  120. for i := 0; i <= dayNum; i++ {
  121. currDate := minDate.AddDate(0, 0, i)
  122. tmpValue, ok := newDateMap[currDate]
  123. if !ok {
  124. //找不到数据,那么就用前面的数据吧
  125. if len(newDataList)-1 < 0 {
  126. tmpValue = 0
  127. } else {
  128. tmpValue = newDataList[len(newDataList)-1].Value
  129. }
  130. }
  131. tmpData := data_manage.EdbDataList{
  132. DataTime: currDate.Format(utils.FormatDate),
  133. Value: tmpValue,
  134. }
  135. dateDataMap[tmpData.DataTime] = tmpData.Value
  136. newDataList = append(newDataList, tmpData)
  137. }
  138. return
  139. }
  140. // GetChartEdbInfoFormat 相关性图表-获取指标信息
  141. func GetChartEdbInfoFormat(chartInfoId int, edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping) (edbList []*data_manage.ChartEdbInfoMapping, err error) {
  142. edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
  143. if edbInfoMappingA == nil || edbInfoMappingB == nil {
  144. err = fmt.Errorf("指标信息有误")
  145. return
  146. }
  147. edbInfoMappingA.FrequencyEn = data.GetFrequencyEn(edbInfoMappingA.Frequency)
  148. if edbInfoMappingA.Unit == `无` {
  149. edbInfoMappingA.Unit = ``
  150. }
  151. if edbInfoMappingB.Unit == `无` {
  152. edbInfoMappingB.Unit = ``
  153. }
  154. if chartInfoId <= 0 {
  155. edbInfoMappingA.IsAxis = 1
  156. edbInfoMappingA.LeadValue = 0
  157. edbInfoMappingA.LeadUnit = ""
  158. edbInfoMappingA.ChartEdbMappingId = 0
  159. edbInfoMappingA.ChartInfoId = 0
  160. edbInfoMappingA.IsOrder = false
  161. edbInfoMappingA.EdbInfoType = 1
  162. edbInfoMappingA.ChartStyle = ""
  163. edbInfoMappingA.ChartColor = ""
  164. edbInfoMappingA.ChartWidth = 0
  165. edbInfoMappingB.IsAxis = 1
  166. edbInfoMappingB.LeadValue = 0
  167. edbInfoMappingB.LeadUnit = ""
  168. edbInfoMappingB.ChartEdbMappingId = 0
  169. edbInfoMappingB.ChartInfoId = 0
  170. edbInfoMappingB.IsOrder = false
  171. edbInfoMappingB.EdbInfoType = 1
  172. edbInfoMappingB.ChartStyle = ""
  173. edbInfoMappingB.ChartColor = ""
  174. edbInfoMappingB.ChartWidth = 0
  175. } else {
  176. edbInfoMappingA.LeadUnitEn = data.GetLeadUnitEn(edbInfoMappingA.LeadUnit)
  177. edbInfoMappingB.LeadUnitEn = data.GetLeadUnitEn(edbInfoMappingB.LeadUnit)
  178. }
  179. edbList = append(edbList, edbInfoMappingA, edbInfoMappingB)
  180. return
  181. }
  182. // GetChartDataByEdbInfo 相关性图表-根据指标信息获取x轴和y轴
  183. func GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping, leadValue int, leadUnit, startDate, endDate, extraConfig string) (xEdbIdValue []int, yDataList []data_manage.YData, err error) {
  184. xData := make([]int, 0)
  185. yData := make([]float64, 0)
  186. if leadValue == 0 {
  187. xData = append(xData, 0)
  188. }
  189. if leadValue > 0 {
  190. leadMin := 0 - leadValue
  191. xLen := 2*leadValue + 1
  192. for i := 0; i < xLen; i++ {
  193. n := leadMin + i
  194. xData = append(xData, n)
  195. }
  196. }
  197. // 计算窗口,不包含第一天
  198. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  199. startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
  200. //// 2023-03-02 时间序列始终以指标B为基准, 始终是A进行平移
  201. //baseEdbInfo := edbInfoMappingB
  202. //changeEdbInfo := edbInfoMappingA
  203. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  204. baseEdbInfo := edbInfoMappingA
  205. changeEdbInfo := edbInfoMappingB
  206. // 获取时间基准指标在时间区间内的值
  207. aDataList := make([]*data_manage.EdbDataList, 0)
  208. switch baseEdbInfo.EdbInfoCategoryType {
  209. case 0:
  210. aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, startDate, endDate)
  211. case 1:
  212. _, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
  213. default:
  214. err = errors.New("指标base类型异常")
  215. return
  216. }
  217. // 获取变频指标所有日期的值, 插值法完善数据
  218. bDataList := make([]*data_manage.EdbDataList, 0)
  219. switch changeEdbInfo.EdbInfoCategoryType {
  220. case 0:
  221. bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.SubSource, changeEdbInfo.EdbInfoId, "", "")
  222. case 1:
  223. _, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
  224. default:
  225. err = errors.New("指标change类型异常")
  226. return
  227. }
  228. //changeDataMap := make(map[string]float64)
  229. //newChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  230. //if e != nil {
  231. // err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  232. // return
  233. //}
  234. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  235. baseDataList := make([]*data_manage.EdbDataList, 0)
  236. baseDataMap := make(map[string]float64)
  237. changeDataList := make([]*data_manage.EdbDataList, 0)
  238. changeDataMap := make(map[string]float64)
  239. // 先把低频指标升频为高频
  240. {
  241. frequencyIntMap := map[string]int{
  242. "日度": 1,
  243. "周度": 2,
  244. "旬度": 3,
  245. "月度": 4,
  246. "季度": 5,
  247. "年度": 6,
  248. }
  249. // 如果A指标是高频,那么就需要对B指标进行升频
  250. if frequencyIntMap[edbInfoMappingA.Frequency] < frequencyIntMap[edbInfoMappingB.Frequency] {
  251. tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  252. if e != nil {
  253. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  254. return
  255. }
  256. changeDataList = tmpNewChangeDataList
  257. baseDataList = aDataList
  258. for _, v := range baseDataList {
  259. baseDataMap[v.DataTime] = v.Value
  260. }
  261. } else if frequencyIntMap[edbInfoMappingA.Frequency] > frequencyIntMap[edbInfoMappingB.Frequency] {
  262. // 如果B指标是高频,那么就需要对A指标进行升频
  263. tmpNewChangeDataList, e := HandleDataByLinearRegression(aDataList, baseDataMap)
  264. if e != nil {
  265. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  266. return
  267. }
  268. baseDataList = tmpNewChangeDataList
  269. changeDataList = bDataList
  270. for _, v := range changeDataList {
  271. changeDataMap[v.DataTime] = v.Value
  272. }
  273. } else {
  274. baseDataList = aDataList
  275. for _, v := range baseDataList {
  276. baseDataMap[v.DataTime] = v.Value
  277. }
  278. changeDataList = bDataList
  279. for _, v := range changeDataList {
  280. changeDataMap[v.DataTime] = v.Value
  281. }
  282. }
  283. }
  284. // 计算不领先也不滞后时的相关系数
  285. baseCalculateData := make([]float64, 0)
  286. baseDataTimeArr := make([]string, 0)
  287. for i := range baseDataList {
  288. baseDataTimeArr = append(baseDataTimeArr, baseDataList[i].DataTime)
  289. baseCalculateData = append(baseCalculateData, baseDataList[i].Value)
  290. }
  291. //zeroBaseData := make([]float64, 0)
  292. //zeroCalculateData := make([]float64, 0)
  293. //for i := range baseDataTimeArr {
  294. // tmpBaseVal, ok1 := baseDataMap[baseDataTimeArr[i]]
  295. // tmpCalculateVal, ok2 := changeDataMap[baseDataTimeArr[i]]
  296. // if ok1 && ok2 {
  297. // zeroBaseData = append(zeroBaseData, tmpBaseVal)
  298. // zeroCalculateData = append(zeroCalculateData, tmpCalculateVal)
  299. // }
  300. //}
  301. //if len(zeroBaseData) != len(zeroCalculateData) {
  302. // err = fmt.Errorf("相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(zeroCalculateData))
  303. // return
  304. //}
  305. //zeroRatio := utils.CalculateCorrelationByIntArr(zeroBaseData, zeroCalculateData)
  306. //if leadValue == 0 {
  307. // yData = append(yData, zeroRatio)
  308. //}
  309. // 计算领先/滞后N期
  310. if leadValue > 0 {
  311. // 平移变频指标领先/滞后的日期(单位天)
  312. moveUnitDays := utils.FrequencyDaysMap[leadUnit]
  313. for i := range xData {
  314. //if xData[i] == 0 {
  315. // yData = append(yData, zeroRatio)
  316. // continue
  317. //}
  318. xCalculateData := make([]float64, 0)
  319. yCalculateData := make([]float64, 0)
  320. // 平移指定天数
  321. mDays := int(moveUnitDays) * xData[i]
  322. _, dMap := MoveDataDaysToNewDataList(changeDataList, mDays)
  323. // 取出对应的基准日期的值
  324. for i2 := range baseDataTimeArr {
  325. tmpDate := baseDataTimeArr[i2]
  326. if yVal, ok := dMap[tmpDate]; ok {
  327. xCalculateData = append(xCalculateData, baseCalculateData[i2])
  328. yCalculateData = append(yCalculateData, yVal)
  329. }
  330. }
  331. if len(yCalculateData) <= 0 {
  332. //err = fmt.Errorf("领先滞后相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(yCalculateData))
  333. //return
  334. // 领先滞后后,没有可以计算的数据了
  335. continue
  336. }
  337. // 公式计算出领先/滞后频度对应点的相关性系数
  338. ratio := utils.CalculateCorrelationByIntArr(xCalculateData, yCalculateData)
  339. yData = append(yData, ratio)
  340. }
  341. }
  342. // 图例
  343. var extra data_manage.CorrelationChartInfoExtraConfig
  344. legend := new(data_manage.CorrelationChartLegend)
  345. if extraConfig != "" {
  346. if e := json.Unmarshal([]byte(extraConfig), &extra); e != nil {
  347. err = fmt.Errorf("图例解析异常, err: %v", e)
  348. return
  349. }
  350. if len(extra.LegendConfig) > 0 {
  351. legend = extra.LegendConfig[0]
  352. }
  353. }
  354. xEdbIdValue = xData
  355. yDataList = make([]data_manage.YData, 0)
  356. yDate := "0000-00-00"
  357. var y data_manage.YData
  358. y.Date = yDate
  359. y.Value = yData
  360. if legend != nil {
  361. y.Name = legend.LegendName
  362. y.Color = legend.Color
  363. }
  364. yDataList = append(yDataList, y)
  365. return
  366. }
  367. // RollingCorrelationChartDataResp 滚动相关性图表数据
  368. type RollingCorrelationChartDataResp struct {
  369. MaxData float64
  370. MinData float64
  371. LatestDate string `description:"真实数据的最后日期"`
  372. EdbInfoCategoryType int
  373. ChartColor string
  374. ChartStyle string
  375. PredictChartColor string
  376. ChartType int
  377. ChartWidth int
  378. EdbName string
  379. EdbNameEn string
  380. Unit string
  381. UnitEn string
  382. IsAxis int
  383. DataList []data_manage.EdbDataList
  384. }
  385. // GetRollingCorrelationChartDataByEdbInfo 滚动相关性计算
  386. func GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping, leadValue int, leadUnit string, calculateValue int, calculateUnit string, startDate, endDate, chartName, chartNameEn string) (dataResp RollingCorrelationChartDataResp, err error) {
  387. dataResp = RollingCorrelationChartDataResp{
  388. DataList: make([]data_manage.EdbDataList, 0),
  389. MaxData: 0,
  390. MinData: 0,
  391. ChartColor: "#00f",
  392. ChartStyle: `spline`,
  393. PredictChartColor: `#00f`,
  394. ChartType: 0,
  395. ChartWidth: 3,
  396. EdbName: chartName,
  397. EdbNameEn: chartNameEn,
  398. IsAxis: 1,
  399. }
  400. dataList := make([]data_manage.EdbDataList, 0)
  401. // 计算窗口,不包含第一天
  402. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  403. startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
  404. baseEdbInfo := edbInfoMappingA
  405. changeEdbInfo := edbInfoMappingB
  406. // 获取时间基准指标在时间区间内的值
  407. aDataList := make([]*data_manage.EdbDataList, 0)
  408. switch baseEdbInfo.EdbInfoCategoryType {
  409. case 0:
  410. aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, startDate, endDate)
  411. case 1:
  412. _, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, true)
  413. default:
  414. err = errors.New("指标base类型异常")
  415. return
  416. }
  417. // 获取变频指标所有日期的值, 插值法完善数据
  418. bDataList := make([]*data_manage.EdbDataList, 0)
  419. switch changeEdbInfo.EdbInfoCategoryType {
  420. case 0:
  421. bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.SubSource, changeEdbInfo.EdbInfoId, "", "")
  422. case 1:
  423. _, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
  424. default:
  425. err = errors.New("指标change类型异常")
  426. return
  427. }
  428. // 数据平移变频指标领先/滞后的日期(单位天)
  429. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  430. //baseDataList := make([]*data_manage.EdbDataList, 0)
  431. baseDataMap := make(map[string]float64)
  432. changeDataList := make([]*data_manage.EdbDataList, 0)
  433. changeDataMap := make(map[string]float64)
  434. // A指标不管三七二十一,先变个频再说
  435. {
  436. _, e := HandleDataByLinearRegression(aDataList, baseDataMap)
  437. if e != nil {
  438. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  439. return
  440. }
  441. //baseDataList = tmpNewChangeDataList
  442. }
  443. // B指标不管三七二十一,先变个频再说
  444. {
  445. tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  446. if e != nil {
  447. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  448. return
  449. }
  450. changeDataList = tmpNewChangeDataList
  451. // 平移下日期
  452. moveUnitDays := utils.FrequencyDaysMap[leadUnit]
  453. _, changeDataMap = MoveDataDaysToNewDataList(changeDataList, leadValue*moveUnitDays)
  454. }
  455. // 计算计算时,需要多少个日期内数据
  456. calculateDay := utils.FrequencyDaysMap[calculateUnit] * calculateValue
  457. // 计算 每个日期的相关性值
  458. {
  459. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  460. if endDate == `` {
  461. endDate = baseEdbInfo.EndDate
  462. }
  463. endDateTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  464. endDateTime = endDateTime.AddDate(0, 0, -(calculateDay - 1))
  465. // 是否开始第一条数据
  466. var isStart, isNotFirst bool
  467. for currDay := startDateTime; !currDay.After(endDateTime); currDay = currDay.AddDate(0, 0, 1) {
  468. yCalculateData := make([]float64, 0)
  469. baseCalculateData := make([]float64, 0)
  470. // 取出对应的基准日期的值
  471. for i := 0; i < calculateDay; i++ {
  472. iDay := currDay.AddDate(0, 0, i).Format(utils.FormatDate)
  473. tmpBaseValue, ok1 := baseDataMap[iDay]
  474. tmpChangeValue, ok2 := changeDataMap[iDay]
  475. if ok1 && ok2 {
  476. baseCalculateData = append(baseCalculateData, tmpBaseValue)
  477. yCalculateData = append(yCalculateData, tmpChangeValue)
  478. } else {
  479. continue
  480. }
  481. }
  482. // 公式计算出领先/滞后频度对应点的相关性系数
  483. var ratio float64
  484. if len(baseCalculateData) > 0 {
  485. ratio = utils.CalculateCorrelationByIntArr(baseCalculateData, yCalculateData)
  486. } else {
  487. // 没有数据的话,那就不返回
  488. continue
  489. }
  490. // 过滤前面都是0的数据
  491. {
  492. if ratio != 0 {
  493. isStart = true
  494. }
  495. if !isStart {
  496. continue
  497. }
  498. }
  499. dataTime := currDay.AddDate(0, 0, calculateDay-1)
  500. dataList = append(dataList, data_manage.EdbDataList{
  501. //EdbDataId: 0,
  502. EdbInfoId: 0,
  503. DataTime: dataTime.Format(utils.FormatDate),
  504. DataTimestamp: dataTime.UnixNano() / 1e6,
  505. Value: ratio,
  506. })
  507. if !isNotFirst {
  508. dataResp.MinData = ratio
  509. dataResp.MaxData = ratio
  510. isNotFirst = true
  511. }
  512. if dataResp.MinData > ratio {
  513. dataResp.MinData = ratio
  514. }
  515. if dataResp.MaxData < ratio {
  516. dataResp.MaxData = ratio
  517. }
  518. }
  519. dataResp.DataList = dataList
  520. }
  521. return
  522. }
  523. // ChartInfoRefresh 图表刷新
  524. func ChartInfoRefresh(chartInfoId int, uniqueCode string) (isAsync bool, err error) {
  525. var errMsg string
  526. defer func() {
  527. if err != nil {
  528. tips := fmt.Sprintf("CorrelationChartInfoRefresh: %s", errMsg)
  529. utils.FileLog.Info(tips)
  530. go alarm_msg.SendAlarmMsg(tips, 3)
  531. }
  532. }()
  533. correlationChart := new(data_manage.ChartInfoCorrelation)
  534. if err = correlationChart.GetItemById(chartInfoId); err != nil {
  535. errMsg = "获取相关性图表失败, Err: " + err.Error()
  536. return
  537. }
  538. // 多因子刷新-异步
  539. if correlationChart.AnalysisMode == 1 {
  540. isAsync = true
  541. go func() {
  542. // 1.刷新图表关联的指标
  543. mappings, e := data_manage.GetChartEdbMappingList(chartInfoId)
  544. if e != nil {
  545. utils.FileLog.Info(fmt.Sprintf("获取图表关联指标失败, err: %v", e))
  546. return
  547. }
  548. if len(mappings) == 0 {
  549. utils.FileLog.Info("图表无关联指标")
  550. return
  551. }
  552. var edbIds []int
  553. for _, v := range mappings {
  554. edbIds = append(edbIds, v.EdbInfoId)
  555. }
  556. if e, _ = data.EdbInfoRefreshAllFromBaseV3(edbIds, false, true, false); e != nil {
  557. utils.FileLog.Info(fmt.Sprintf("批量刷新指标失败, err: %v", e))
  558. return
  559. }
  560. // 2.刷新指标系列计算数据
  561. for _, v := range mappings {
  562. _, e = data.PostRefreshFactorEdbRecalculate(v.EdbInfoId, v.EdbCode)
  563. if e != nil {
  564. utils.FileLog.Info(fmt.Sprintf("PostRefreshFactorEdbRecalculate err: %v", e))
  565. continue
  566. }
  567. }
  568. // 3.刷新图表矩阵
  569. _, e = data.PostRefreshFactorEdbChartRecalculate(chartInfoId)
  570. if e != nil {
  571. utils.FileLog.Info(fmt.Sprintf("PostRefreshFactorEdbRecalculate err: %v", e))
  572. return
  573. }
  574. // 4.清除图表缓存
  575. key := utils.HZ_CHART_LIB_DETAIL + uniqueCode
  576. _ = utils.Rc.Delete(key)
  577. }()
  578. return
  579. }
  580. // 批量刷新ETA指标
  581. err, _ = data.EdbInfoRefreshAllFromBaseV3([]int{correlationChart.EdbInfoIdFirst, correlationChart.EdbInfoIdSecond}, false, true, false)
  582. if err != nil {
  583. return
  584. }
  585. // 重新生成数据并更新
  586. edbInfoMappingA, err := data_manage.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdFirst)
  587. if err != nil {
  588. errMsg = "获取相关性图表, A指标mapping信息失败, Err:" + err.Error()
  589. return
  590. }
  591. edbInfoMappingB, err := data_manage.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdSecond)
  592. if err != nil {
  593. errMsg = "获取相关性图表, B指标mapping信息失败, Err:" + err.Error()
  594. return
  595. }
  596. periodData, correlationData, err := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, correlationChart.StartDate.Format(utils.FormatDate), correlationChart.EndDate.Format(utils.FormatDate), "")
  597. if err != nil {
  598. errMsg = "获取相关性图表, 图表计算值失败, Err:" + err.Error()
  599. return
  600. }
  601. periodDataByte, err := json.Marshal(periodData)
  602. if err != nil {
  603. errMsg = "相关性图表, X轴信息有误, Err:" + err.Error()
  604. return
  605. }
  606. correlationDataByte, err := json.Marshal(correlationData[0].Value)
  607. if err != nil {
  608. errMsg = "相关性图表, Y轴信息有误, Err:" + err.Error()
  609. return
  610. }
  611. correlationChart.PeriodData = string(periodDataByte)
  612. correlationChart.CorrelationData = string(correlationDataByte)
  613. correlationChart.ModifyTime = time.Now().Local()
  614. correlationUpdateCols := []string{"PeriodData", "CorrelationData", "ModifyTime"}
  615. if err = correlationChart.Update(correlationUpdateCols); err != nil {
  616. errMsg = "更新相关性图表失败, Err:" + err.Error()
  617. return
  618. }
  619. return
  620. }
  621. // GetChartAndCorrelationInfo 获取图表信息和相关信息信息
  622. func GetChartAndCorrelationInfo(chartInfoId int) (chartInfo *data_manage.ChartInfo, correlationInfo *data_manage.ChartInfoCorrelation, tips string, err error) {
  623. item, e := data_manage.GetChartInfoById(chartInfoId)
  624. if e != nil {
  625. if e.Error() == utils.ErrNoRow() {
  626. tips = "图表已被删除, 请刷新页面"
  627. err = fmt.Errorf("图表已被删除, 请刷新页面")
  628. return
  629. }
  630. err = fmt.Errorf("获取图表信息失败, Err: %s", e.Error())
  631. return
  632. }
  633. if item.Source != utils.CHART_SOURCE_CORRELATION {
  634. tips = "该图不是相关性图表"
  635. err = fmt.Errorf("该图不是相关性图表")
  636. return
  637. }
  638. chartInfo = item
  639. correlationInfo = new(data_manage.ChartInfoCorrelation)
  640. if e = correlationInfo.GetItemById(chartInfo.ChartInfoId); e != nil {
  641. err = fmt.Errorf("获取图表相关性信息失败, Err: %s", e.Error())
  642. return
  643. }
  644. return
  645. }
  646. // AddChartInfo 添加图表
  647. func AddChartInfo(req data_manage.AddChartInfoReq, source int, sysUser *system.Admin, lang string) (chartInfo *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
  648. isSendEmail = true
  649. req.ChartName = strings.Trim(req.ChartName, " ")
  650. if req.ChartName == "" {
  651. errMsg = "请填写图表名称!"
  652. err = errors.New(errMsg)
  653. isSendEmail = false
  654. return
  655. }
  656. if req.ChartClassifyId <= 0 {
  657. errMsg = "分类参数错误!"
  658. err = errors.New(errMsg)
  659. isSendEmail = false
  660. return
  661. }
  662. // 相关性图表配置
  663. if req.CorrelationChartInfo.LeadValue == 0 && source == utils.CHART_SOURCE_CORRELATION {
  664. errMsg = "请输入领先期数"
  665. err = errors.New(errMsg)
  666. isSendEmail = false
  667. return
  668. }
  669. if req.CorrelationChartInfo.LeadUnit == "" {
  670. errMsg = "请填写领先单位"
  671. err = errors.New(errMsg)
  672. isSendEmail = false
  673. return
  674. }
  675. //if req.CorrelationChartInfo.StartDate == "" || req.CorrelationChartInfo.EndDate == "" {
  676. // errMsg = "请填写开始结束日期"
  677. // err = errors.New(errMsg)
  678. // isSendEmail = false
  679. // return
  680. //}
  681. //startDate, e := time.Parse(utils.FormatDate, req.CorrelationChartInfo.StartDate)
  682. //if e != nil {
  683. // errMsg = "开始日期格式有误"
  684. // err = errors.New(errMsg)
  685. // isSendEmail = false
  686. // return
  687. //}
  688. //endDate, e := time.Parse(utils.FormatDate, req.CorrelationChartInfo.EndDate)
  689. //if e != nil {
  690. // errMsg = "结束日期格式有误"
  691. // err = errors.New(errMsg)
  692. // isSendEmail = false
  693. // return
  694. //}
  695. if len(req.CorrelationChartInfo.EdbInfoIdList) != 2 {
  696. errMsg = "请选择AB指标"
  697. err = errors.New(errMsg)
  698. isSendEmail = false
  699. return
  700. }
  701. chartClassify, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
  702. if err != nil {
  703. if err.Error() == utils.ErrNoRow() {
  704. errMsg = "分类不存在"
  705. err = errors.New(errMsg)
  706. isSendEmail = false
  707. return
  708. }
  709. errMsg = "获取分类信息失败"
  710. err = errors.New("获取分类信息失败,Err:" + err.Error())
  711. return
  712. }
  713. if chartClassify == nil {
  714. errMsg = "分类不存在"
  715. err = errors.New(errMsg)
  716. isSendEmail = false
  717. return
  718. }
  719. var edbInfoIdArr []int
  720. for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
  721. edbInfoId := v.EdbInfoId
  722. edbInfo, tmpErr := data_manage.GetEdbInfoById(edbInfoId)
  723. if tmpErr != nil {
  724. if tmpErr.Error() == utils.ErrNoRow() {
  725. errMsg = "指标不存在!"
  726. err = errors.New("指标不存在,edbInfoId:" + strconv.Itoa(edbInfoId))
  727. return
  728. } else {
  729. errMsg = "获取指标信息失败!"
  730. err = errors.New("获取图表的指标信息失败,Err:" + tmpErr.Error())
  731. return
  732. }
  733. }
  734. if edbInfo == nil {
  735. errMsg = "指标已被删除,请重新选择!"
  736. err = errors.New("指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
  737. return
  738. } else {
  739. if edbInfo.EdbInfoId <= 0 {
  740. errMsg = "指标已被删除,请重新选择!"
  741. err = errors.New("指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
  742. return
  743. }
  744. }
  745. edbInfoIdArr = append(edbInfoIdArr, edbInfoId)
  746. edbInfo.EdbNameSource = edbInfo.EdbName
  747. }
  748. sort.Ints(edbInfoIdArr)
  749. var edbInfoIdArrStr []string
  750. for _, v := range edbInfoIdArr {
  751. edbInfoIdArrStr = append(edbInfoIdArrStr, strconv.Itoa(v))
  752. }
  753. edbInfoIdStr := strings.Join(edbInfoIdArrStr, ",")
  754. var chartInfoId int
  755. // 判断图表是否存在
  756. {
  757. var condition string
  758. var pars []interface{}
  759. switch lang {
  760. case utils.EnLangVersion:
  761. condition += " AND chart_name_en = ? AND source = ? "
  762. default:
  763. condition += " AND chart_name=? AND source = ? "
  764. }
  765. pars = append(pars, req.ChartName, source)
  766. count, tmpErr := data_manage.GetChartInfoCountByCondition(condition, pars)
  767. if tmpErr != nil {
  768. errMsg = "判断图表名称是否存在失败"
  769. err = errors.New("判断图表名称是否存在失败,Err:" + tmpErr.Error())
  770. return
  771. }
  772. if count > 0 {
  773. errMsg = "图表已存在,请重新填写"
  774. err = errors.New(errMsg)
  775. isSendEmail = false
  776. return
  777. }
  778. }
  779. disableVal := data.CheckIsDisableChart(edbInfoIdArr)
  780. chartInfo = new(data_manage.ChartInfo)
  781. chartInfo.ChartName = req.ChartName
  782. chartInfo.ChartNameEn = req.ChartName
  783. chartInfo.EdbInfoIds = edbInfoIdStr
  784. chartInfo.ChartClassifyId = req.ChartClassifyId
  785. chartInfo.SysUserId = sysUser.AdminId
  786. chartInfo.SysUserRealName = sysUser.RealName
  787. chartInfo.CreateTime = time.Now()
  788. chartInfo.ModifyTime = time.Now()
  789. chartInfo.IsSetName = 0
  790. timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
  791. chartInfo.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp)
  792. chartInfo.ChartType = 9 // 相关性图
  793. chartInfo.Calendar = "公历"
  794. chartInfo.DateType = 6
  795. chartInfo.StartDate = req.StartDate
  796. chartInfo.EndDate = req.EndDate
  797. chartInfo.SeasonStartDate = req.StartDate
  798. chartInfo.SeasonEndDate = req.EndDate
  799. chartInfo.LeftMin = req.LeftMin
  800. chartInfo.LeftMax = req.LeftMax
  801. chartInfo.RightMin = req.RightMin
  802. chartInfo.RightMax = req.RightMax
  803. chartInfo.Disabled = disableVal
  804. chartInfo.Source = source
  805. chartInfo.ChartThemeId = req.ChartThemeId
  806. chartInfo.SourcesFrom = req.SourcesFrom
  807. chartInfo.Instructions = req.Instructions
  808. chartInfo.MarkersLines = req.MarkersLines
  809. chartInfo.MarkersAreas = req.MarkersAreas
  810. if req.ExtraConfig != "" {
  811. chartInfo.ExtraConfig = req.ExtraConfig
  812. }
  813. // 指标信息
  814. mapList := make([]*data_manage.ChartEdbMapping, 0)
  815. for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
  816. mapItem := new(data_manage.ChartEdbMapping)
  817. mapItem.EdbInfoId = v.EdbInfoId
  818. mapItem.CreateTime = time.Now()
  819. mapItem.ModifyTime = time.Now()
  820. edbTimestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
  821. mapItem.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + edbTimestamp + "_" + strconv.Itoa(v.EdbInfoId))
  822. mapItem.IsOrder = true
  823. mapItem.IsAxis = 1
  824. mapItem.EdbInfoType = 1
  825. mapItem.Source = utils.CHART_SOURCE_CORRELATION
  826. mapList = append(mapList, mapItem)
  827. }
  828. // 相关性图表扩展信息
  829. correlationChart := new(data_manage.ChartInfoCorrelation)
  830. correlationChart.LeadValue = req.CorrelationChartInfo.LeadValue
  831. correlationChart.LeadUnit = req.CorrelationChartInfo.LeadUnit
  832. correlationChart.CalculateValue = req.CorrelationChartInfo.CalculateValue
  833. correlationChart.CalculateUnit = req.CorrelationChartInfo.CalculateUnit
  834. correlationChart.BaseCalculateValue = req.CorrelationChartInfo.BaseCalculateValue
  835. correlationChart.BaseCalculateUnit = req.CorrelationChartInfo.BaseCalculateUnit
  836. // 滚动相关性会有日期等信息
  837. if source == utils.CHART_SOURCE_ROLLING_CORRELATION {
  838. correlationChart.DateType = req.CorrelationChartInfo.DateType
  839. if req.CorrelationChartInfo.StartDate != `` {
  840. startDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, req.CorrelationChartInfo.StartDate, time.Local)
  841. if tmpErr != nil {
  842. err = tmpErr
  843. return
  844. }
  845. correlationChart.StartDate = startDateTime
  846. }
  847. if req.CorrelationChartInfo.EndDate != `` {
  848. endDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, req.CorrelationChartInfo.EndDate, time.Local)
  849. if tmpErr != nil {
  850. err = tmpErr
  851. return
  852. }
  853. correlationChart.EndDate = endDateTime
  854. }
  855. }
  856. correlationChart.EdbInfoIdFirst = req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId
  857. correlationChart.EdbInfoIdSecond = req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId
  858. correlationChart.CreateTime = time.Now().Local()
  859. correlationChart.ModifyTime = time.Now().Local()
  860. //// 生成图表x轴y轴数据
  861. //edbInfoMappingA, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId)
  862. //if e != nil {
  863. // errMsg = "获取失败"
  864. // err = errors.New("获取相关性图表, A指标mapping信息失败, Err:" + e.Error())
  865. // return
  866. //}
  867. //edbInfoMappingB, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId)
  868. //if e != nil {
  869. // errMsg = "获取失败"
  870. // err = errors.New("获取相关性图表, B指标mapping信息失败, Err:" + e.Error())
  871. // return
  872. //}
  873. //periodData, correlationData, e := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, req.CorrelationChartInfo.LeadValue, req.CorrelationChartInfo.LeadUnit, req.CorrelationChartInfo.StartDate, req.CorrelationChartInfo.EndDate)
  874. //if e != nil {
  875. // errMsg = "获取失败"
  876. // err = errors.New("获取相关性图表, 图表计算值失败, Err:" + e.Error())
  877. // return
  878. //}
  879. //periodDataByte, e := json.Marshal(periodData)
  880. //if e != nil {
  881. // errMsg = "获取失败"
  882. // err = errors.New("相关性图表, X轴信息有误, Err:" + e.Error())
  883. // return
  884. //}
  885. //correlationDataByte, e := json.Marshal(correlationData[0].Value)
  886. //if e != nil {
  887. // errMsg = "获取失败"
  888. // err = errors.New("相关性图表, Y轴信息有误, Err:" + e.Error())
  889. // return
  890. //}
  891. //correlationChart.PeriodData = string(periodDataByte)
  892. //correlationChart.CorrelationData = string(correlationDataByte)
  893. // 新增图表和指标mapping
  894. chartInfoId, e := data_manage.CreateCorrelationChartAndEdb(chartInfo, mapList, correlationChart)
  895. if e != nil {
  896. errMsg = "操作失败"
  897. err = errors.New("新增相关性图表失败, Err: " + e.Error())
  898. return
  899. }
  900. // 添加指标引用记录
  901. _ = data.SaveChartEdbInfoRelation(edbInfoIdArr, chartInfo)
  902. //添加es数据
  903. go data.EsAddOrEditChartInfo(chartInfoId)
  904. return
  905. }
  906. // EditChartInfo 编辑图表
  907. func EditChartInfo(req data_manage.EditChartInfoReq, sysUser *system.Admin, lang string) (chartItem *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
  908. isSendEmail = true
  909. chartItem, err = data_manage.GetChartInfoById(req.ChartInfoId)
  910. if err != nil {
  911. if err.Error() == utils.ErrNoRow() {
  912. errMsg = "图表已被删除,请刷新页面"
  913. err = errors.New(errMsg)
  914. isSendEmail = false
  915. return
  916. }
  917. errMsg = "获取图表信息失败"
  918. err = errors.New("获取图表信息失败,Err:" + err.Error())
  919. return
  920. }
  921. if chartItem.Source != utils.CHART_SOURCE_CORRELATION && chartItem.Source != utils.CHART_SOURCE_ROLLING_CORRELATION {
  922. errMsg = "该图不是相关性图表!"
  923. err = errors.New(errMsg)
  924. isSendEmail = false
  925. return
  926. }
  927. req.ChartName = strings.Trim(req.ChartName, " ")
  928. if req.ChartClassifyId <= 0 {
  929. errMsg = "分类参数错误!"
  930. err = errors.New(errMsg)
  931. isSendEmail = false
  932. return
  933. }
  934. // 相关性图表配置
  935. if req.CorrelationChartInfo.LeadValue == 0 && chartItem.Source == utils.CHART_SOURCE_CORRELATION {
  936. errMsg = "请输入领先期数"
  937. err = errors.New(errMsg)
  938. isSendEmail = false
  939. return
  940. }
  941. if req.CorrelationChartInfo.LeadUnit == "" {
  942. errMsg = "请填写领先单位"
  943. err = errors.New(errMsg)
  944. isSendEmail = false
  945. return
  946. }
  947. //if req.CorrelationChartInfo.StartDate == "" || req.CorrelationChartInfo.EndDate == "" {
  948. // errMsg = "请填写开始结束日期"
  949. // err = errors.New(errMsg)
  950. // isSendEmail = false
  951. // return
  952. //}
  953. startDate, e := time.Parse(utils.FormatDate, req.CorrelationChartInfo.StartDate)
  954. if e != nil {
  955. errMsg = "开始日期格式有误"
  956. err = errors.New(errMsg)
  957. isSendEmail = false
  958. return
  959. }
  960. var endDate time.Time
  961. if req.CorrelationChartInfo.EndDate != `` {
  962. endDate, e = time.Parse(utils.FormatDate, req.CorrelationChartInfo.EndDate)
  963. if e != nil {
  964. errMsg = "结束日期格式有误"
  965. err = errors.New(errMsg)
  966. isSendEmail = false
  967. return
  968. }
  969. }
  970. if len(req.CorrelationChartInfo.EdbInfoIdList) != 2 {
  971. errMsg = "请选择AB指标"
  972. err = errors.New(errMsg)
  973. isSendEmail = false
  974. return
  975. }
  976. chartClassify, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
  977. if err != nil {
  978. if err.Error() == utils.ErrNoRow() {
  979. errMsg = "分类不存在"
  980. err = errors.New(errMsg)
  981. isSendEmail = false
  982. return
  983. }
  984. errMsg = "获取分类信息失败"
  985. err = errors.New("获取分类信息失败,Err:" + err.Error())
  986. return
  987. }
  988. if chartClassify == nil {
  989. errMsg = "分类不存在"
  990. err = errors.New(errMsg)
  991. isSendEmail = false
  992. return
  993. }
  994. // 图表操作权限
  995. ok := data.CheckOpChartPermission(sysUser, chartItem.SysUserId, true)
  996. if !ok {
  997. errMsg = "没有该图表的操作权限"
  998. err = errors.New(errMsg)
  999. isSendEmail = false
  1000. return
  1001. }
  1002. var edbInfoIdArr []int
  1003. for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
  1004. edbInfoId := v.EdbInfoId
  1005. edbInfo, tmpErr := data_manage.GetEdbInfoById(edbInfoId)
  1006. if tmpErr != nil {
  1007. if tmpErr.Error() == utils.ErrNoRow() {
  1008. errMsg = "图表不存在!"
  1009. err = errors.New("图表指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
  1010. return
  1011. } else {
  1012. errMsg = "获取图表信息失败!"
  1013. err = errors.New("获取图表的指标信息失败,Err:" + tmpErr.Error())
  1014. return
  1015. }
  1016. }
  1017. if edbInfo == nil {
  1018. errMsg = "指标不存在!"
  1019. err = errors.New("指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
  1020. return
  1021. }
  1022. edbInfoIdArr = append(edbInfoIdArr, edbInfoId)
  1023. }
  1024. sort.Ints(edbInfoIdArr)
  1025. var edbInfoIdArrStr []string
  1026. for _, v := range edbInfoIdArr {
  1027. edbInfoIdArrStr = append(edbInfoIdArrStr, strconv.Itoa(v))
  1028. }
  1029. edbInfoIdStr := strings.Join(edbInfoIdArrStr, ",")
  1030. //判断图表是否存在
  1031. {
  1032. var condition string
  1033. var pars []interface{}
  1034. condition += " AND chart_info_id <> ? "
  1035. pars = append(pars, req.ChartInfoId)
  1036. switch lang {
  1037. case utils.EnLangVersion:
  1038. condition += " AND chart_name_en = ? AND source = ? "
  1039. default:
  1040. condition += " AND chart_name=? AND source = ? "
  1041. }
  1042. pars = append(pars, req.ChartName, chartItem.Source)
  1043. count, tmpErr := data_manage.GetChartInfoCountByCondition(condition, pars)
  1044. if tmpErr != nil {
  1045. errMsg = "判断图表名称是否存在失败"
  1046. err = errors.New("判断图表名称是否存在失败,Err:" + tmpErr.Error())
  1047. return
  1048. }
  1049. if count > 0 {
  1050. errMsg = "图表已存在,请重新填写"
  1051. err = errors.New(errMsg)
  1052. isSendEmail = false
  1053. return
  1054. }
  1055. }
  1056. correlationChart := new(data_manage.ChartInfoCorrelation)
  1057. if e := correlationChart.GetItemById(chartItem.ChartInfoId); e != nil {
  1058. errMsg = "操作失败"
  1059. err = errors.New("图表相关性信息不存在, Err: " + e.Error())
  1060. return
  1061. }
  1062. // 图表启用与否
  1063. disableVal := data.CheckIsDisableChart(edbInfoIdArr)
  1064. // 重新生成图表值, 并修改相关性图表扩展信息
  1065. //edbInfoMappingA, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId)
  1066. //if e != nil {
  1067. // errMsg = "获取失败"
  1068. // err = errors.New("获取相关性图表, A指标mapping信息失败, Err:" + e.Error())
  1069. // return
  1070. //}
  1071. //edbInfoMappingB, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId)
  1072. //if e != nil {
  1073. // errMsg = "获取失败"
  1074. // err = errors.New("获取相关性图表, B指标mapping信息失败, Err:" + e.Error())
  1075. // return
  1076. //}
  1077. //periodData, correlationData, e := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, req.CorrelationChartInfo.LeadValue, req.CorrelationChartInfo.LeadUnit, req.CorrelationChartInfo.StartDate, req.CorrelationChartInfo.EndDate)
  1078. //if e != nil {
  1079. // errMsg = "获取失败"
  1080. // err = errors.New("获取相关性图表, 图表计算值失败, Err:" + e.Error())
  1081. // return
  1082. //}
  1083. //periodDataByte, e := json.Marshal(periodData)
  1084. //if e != nil {
  1085. // errMsg = "获取失败"
  1086. // err = errors.New("相关性图表, X轴信息有误, Err:" + e.Error())
  1087. // return
  1088. //}
  1089. //correlationDataByte, e := json.Marshal(correlationData[0].Value)
  1090. //if e != nil {
  1091. // errMsg = "获取失败"
  1092. // err = errors.New("相关性图表, Y轴信息有误, Err:" + e.Error())
  1093. // return
  1094. //}
  1095. correlationChart.LeadValue = req.CorrelationChartInfo.LeadValue
  1096. correlationChart.LeadUnit = req.CorrelationChartInfo.LeadUnit
  1097. correlationChart.CalculateValue = req.CorrelationChartInfo.CalculateValue
  1098. correlationChart.CalculateUnit = req.CorrelationChartInfo.CalculateUnit
  1099. correlationChart.StartDate = startDate
  1100. correlationChart.EndDate = endDate
  1101. correlationChart.EdbInfoIdFirst = req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId
  1102. correlationChart.EdbInfoIdSecond = req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId
  1103. // 滚动相关性会有日期等信息
  1104. if chartItem.Source == utils.CHART_SOURCE_ROLLING_CORRELATION {
  1105. correlationChart.DateType = req.CorrelationChartInfo.DateType
  1106. }
  1107. //correlationChart.PeriodData = string(periodDataByte)
  1108. //correlationChart.CorrelationData = string(correlationDataByte)
  1109. correlationChart.ModifyTime = time.Now().Local()
  1110. //correlationUpdateCols := []string{"LeadValue", "LeadUnit", "StartDate", "EndDate", "EdbInfoIdFirst", "EdbInfoIdSecond", "PeriodData","CorrelationData", "ModifyTime"}
  1111. correlationUpdateCols := []string{"LeadValue", "LeadUnit", "CalculateValue", "CalculateUnit", "DateType", "StartDate", "EndDate", "EdbInfoIdFirst", "EdbInfoIdSecond", "ModifyTime"}
  1112. // 修改图表与指标mapping
  1113. req.ChartType = 9
  1114. err = data_manage.EditCorrelationChartInfoAndMapping(&req, edbInfoIdStr, "公历", 6, disableVal, ``,
  1115. correlationChart, correlationUpdateCols)
  1116. if err != nil {
  1117. errMsg = "保存失败"
  1118. err = errors.New("保存失败,Err:" + err.Error())
  1119. return
  1120. }
  1121. resp := new(data_manage.AddChartInfoResp)
  1122. resp.ChartInfoId = chartItem.ChartInfoId
  1123. resp.UniqueCode = chartItem.UniqueCode
  1124. resp.ChartType = req.ChartType
  1125. // 添加指标引用记录
  1126. _ = data.SaveChartEdbInfoRelation(edbInfoIdArr, chartItem)
  1127. //添加es数据
  1128. go data.EsAddOrEditChartInfo(chartItem.ChartInfoId)
  1129. //修改my eta es数据
  1130. go data.EsAddOrEditMyChartInfoByChartInfoId(chartItem.ChartInfoId)
  1131. return
  1132. }
  1133. // CopyChartInfo 复制图表
  1134. func CopyChartInfo(configId, classifyId int, chartName string, correlationChartInfoReq data_manage.CorrelationChartInfoReq, oldChartInfo *data_manage.ChartInfo, sysUser *system.Admin, lang string) (chartInfo *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
  1135. configSource := 2
  1136. isSendEmail = true
  1137. // 获取相关性图的配置
  1138. multipleGraphConfigChartMapping, err := data_manage.GetMultipleGraphConfigChartMappingByIdAndSource(configId, configSource)
  1139. if err != nil {
  1140. return
  1141. }
  1142. multipleGraphConfig, err := data_manage.GetMultipleGraphConfigById(configId)
  1143. if err != nil {
  1144. return
  1145. }
  1146. multipleGraphConfig.MultipleGraphConfigId = 0
  1147. err = data_manage.AddMultipleGraphConfig(multipleGraphConfig)
  1148. if err != nil {
  1149. return
  1150. }
  1151. // 添加图
  1152. addChartReq := data_manage.AddChartInfoReq{
  1153. ChartClassifyId: classifyId,
  1154. ChartName: chartName,
  1155. ChartType: utils.CHART_TYPE_CURVE,
  1156. Calendar: "公历",
  1157. CorrelationChartInfo: correlationChartInfoReq,
  1158. ChartThemeId: oldChartInfo.ChartThemeId,
  1159. SourcesFrom: oldChartInfo.SourcesFrom,
  1160. Instructions: oldChartInfo.Instructions,
  1161. MarkersLines: oldChartInfo.MarkersLines,
  1162. MarkersAreas: oldChartInfo.MarkersAreas,
  1163. }
  1164. chartSource := utils.CHART_SOURCE_CORRELATION // 默认是相关性图
  1165. chartInfo, err, errMsg, isSendEmail = AddChartInfo(addChartReq, chartSource, sysUser, lang)
  1166. if err != nil {
  1167. return
  1168. }
  1169. // 添加关系
  1170. multipleGraphConfigChartMapping = &data_manage.MultipleGraphConfigChartMapping{
  1171. //Id: 0,
  1172. MultipleGraphConfigId: multipleGraphConfig.MultipleGraphConfigId,
  1173. ChartInfoId: chartInfo.ChartInfoId,
  1174. Source: configSource,
  1175. ModifyTime: time.Now(),
  1176. CreateTime: time.Now(),
  1177. }
  1178. err = data_manage.AddMultipleGraphConfigChartMapping(multipleGraphConfigChartMapping)
  1179. if err != nil {
  1180. return
  1181. }
  1182. //添加es数据
  1183. go data.EsAddOrEditChartInfo(chartInfo.ChartInfoId)
  1184. return
  1185. }
  1186. // CalculateCorrelation 计算相关性-获取x轴和y轴
  1187. func CalculateCorrelation(leadValue int, leadUnit, frequencyA, frequencyB string, dataListA, dataListB []*data_manage.EdbDataList) (xEdbIdValue []int, yDataList []data_manage.YData, err error) {
  1188. xData := make([]int, 0)
  1189. yData := make([]float64, 0)
  1190. if leadValue == 0 {
  1191. xData = append(xData, 0)
  1192. }
  1193. if leadValue > 0 {
  1194. leadMin := 0 - leadValue
  1195. xLen := 2*leadValue + 1
  1196. for i := 0; i < xLen; i++ {
  1197. n := leadMin + i
  1198. xData = append(xData, n)
  1199. }
  1200. }
  1201. // 计算窗口,不包含第一天
  1202. //startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  1203. //startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
  1204. //// 2023-03-02 时间序列始终以指标B为基准, 始终是A进行平移
  1205. //baseEdbInfo := edbInfoMappingB
  1206. //changeEdbInfo := edbInfoMappingA
  1207. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  1208. //baseEdbInfo := edbInfoMappingA
  1209. //changeEdbInfo := edbInfoMappingB
  1210. // 获取时间基准指标在时间区间内的值
  1211. //aDataList := make([]*data_manage.EdbDataList, 0)
  1212. //switch baseEdbInfo.EdbInfoCategoryType {
  1213. //case 0:
  1214. // aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, startDate, endDate)
  1215. //case 1:
  1216. // _, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
  1217. //default:
  1218. // err = errors.New("指标base类型异常")
  1219. // return
  1220. //}
  1221. //
  1222. //// 获取变频指标所有日期的值, 插值法完善数据
  1223. //bDataList := make([]*data_manage.EdbDataList, 0)
  1224. //switch changeEdbInfo.EdbInfoCategoryType {
  1225. //case 0:
  1226. // bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.SubSource, changeEdbInfo.EdbInfoId, "", "")
  1227. //case 1:
  1228. // _, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
  1229. //default:
  1230. // err = errors.New("指标change类型异常")
  1231. // return
  1232. //}
  1233. //changeDataMap := make(map[string]float64)
  1234. //newChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  1235. //if e != nil {
  1236. // err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  1237. // return
  1238. //}
  1239. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  1240. baseDataList := make([]*data_manage.EdbDataList, 0)
  1241. baseDataMap := make(map[string]float64)
  1242. changeDataList := make([]*data_manage.EdbDataList, 0)
  1243. changeDataMap := make(map[string]float64)
  1244. // 先把低频指标升频为高频
  1245. {
  1246. frequencyIntMap := map[string]int{
  1247. "日度": 1,
  1248. "周度": 2,
  1249. "旬度": 3,
  1250. "月度": 4,
  1251. "季度": 5,
  1252. "年度": 6,
  1253. }
  1254. // 如果A指标是高频,那么就需要对B指标进行升频
  1255. if frequencyIntMap[frequencyA] < frequencyIntMap[frequencyB] {
  1256. tmpNewChangeDataList, e := HandleDataByLinearRegression(dataListB, changeDataMap)
  1257. if e != nil {
  1258. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  1259. return
  1260. }
  1261. changeDataList = tmpNewChangeDataList
  1262. baseDataList = dataListA
  1263. for _, v := range baseDataList {
  1264. baseDataMap[v.DataTime] = v.Value
  1265. }
  1266. } else if frequencyIntMap[frequencyA] > frequencyIntMap[frequencyB] {
  1267. // 如果B指标是高频,那么就需要对A指标进行升频
  1268. tmpNewChangeDataList, e := HandleDataByLinearRegression(dataListA, baseDataMap)
  1269. if e != nil {
  1270. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  1271. return
  1272. }
  1273. baseDataList = tmpNewChangeDataList
  1274. changeDataList = dataListB
  1275. for _, v := range changeDataList {
  1276. changeDataMap[v.DataTime] = v.Value
  1277. }
  1278. } else {
  1279. baseDataList = dataListA
  1280. for _, v := range baseDataList {
  1281. baseDataMap[v.DataTime] = v.Value
  1282. }
  1283. changeDataList = dataListB
  1284. for _, v := range changeDataList {
  1285. changeDataMap[v.DataTime] = v.Value
  1286. }
  1287. }
  1288. }
  1289. // 计算不领先也不滞后时的相关系数
  1290. baseCalculateData := make([]float64, 0)
  1291. baseDataTimeArr := make([]string, 0)
  1292. for i := range baseDataList {
  1293. baseDataTimeArr = append(baseDataTimeArr, baseDataList[i].DataTime)
  1294. baseCalculateData = append(baseCalculateData, baseDataList[i].Value)
  1295. }
  1296. //zeroBaseData := make([]float64, 0)
  1297. //zeroCalculateData := make([]float64, 0)
  1298. //for i := range baseDataTimeArr {
  1299. // tmpBaseVal, ok1 := baseDataMap[baseDataTimeArr[i]]
  1300. // tmpCalculateVal, ok2 := changeDataMap[baseDataTimeArr[i]]
  1301. // if ok1 && ok2 {
  1302. // zeroBaseData = append(zeroBaseData, tmpBaseVal)
  1303. // zeroCalculateData = append(zeroCalculateData, tmpCalculateVal)
  1304. // }
  1305. //}
  1306. //if len(zeroBaseData) != len(zeroCalculateData) {
  1307. // err = fmt.Errorf("相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(zeroCalculateData))
  1308. // return
  1309. //}
  1310. //zeroRatio := utils.CalculateCorrelationByIntArr(zeroBaseData, zeroCalculateData)
  1311. //if leadValue == 0 {
  1312. // yData = append(yData, zeroRatio)
  1313. //}
  1314. // 计算领先/滞后N期
  1315. if leadValue > 0 {
  1316. // 平移变频指标领先/滞后的日期(单位天)
  1317. moveUnitDays := utils.FrequencyDaysMap[leadUnit]
  1318. for i := range xData {
  1319. //if xData[i] == 0 {
  1320. // yData = append(yData, zeroRatio)
  1321. // continue
  1322. //}
  1323. xCalculateData := make([]float64, 0)
  1324. yCalculateData := make([]float64, 0)
  1325. // 平移指定天数
  1326. mDays := int(moveUnitDays) * xData[i]
  1327. _, dMap := MoveDataDaysToNewDataList(changeDataList, mDays)
  1328. // 取出对应的基准日期的值
  1329. for i2 := range baseDataTimeArr {
  1330. tmpDate := baseDataTimeArr[i2]
  1331. if yVal, ok := dMap[tmpDate]; ok {
  1332. xCalculateData = append(xCalculateData, baseCalculateData[i2])
  1333. yCalculateData = append(yCalculateData, yVal)
  1334. }
  1335. }
  1336. if len(yCalculateData) <= 0 {
  1337. //err = fmt.Errorf("领先滞后相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(yCalculateData))
  1338. //return
  1339. // 领先滞后后,没有可以计算的数据了
  1340. continue
  1341. }
  1342. // 公式计算出领先/滞后频度对应点的相关性系数
  1343. ratio := utils.CalculateCorrelationByIntArr(xCalculateData, yCalculateData)
  1344. yData = append(yData, ratio)
  1345. }
  1346. }
  1347. xEdbIdValue = xData
  1348. yDataList = make([]data_manage.YData, 0)
  1349. yDate := "0000-00-00"
  1350. yDataList = append(yDataList, data_manage.YData{
  1351. Date: yDate,
  1352. Value: yData,
  1353. })
  1354. return
  1355. }
  1356. // GetFactorChartDataByChartId 获取多因子相关性图表数据
  1357. func GetFactorChartDataByChartId(chartInfoId int, extraConfig string) (xEdbIdValue []int, yDataList []data_manage.YData, err error) {
  1358. if chartInfoId <= 0 {
  1359. return
  1360. }
  1361. // 指标对应的图例
  1362. extra := new(data_manage.CorrelationChartInfoExtraConfig)
  1363. if extraConfig != "" {
  1364. if e := json.Unmarshal([]byte(extraConfig), extra); e != nil {
  1365. err = fmt.Errorf("解析图表额外配置失败, err: %v", e)
  1366. return
  1367. }
  1368. }
  1369. legends := make(map[string]*data_manage.CorrelationChartLegend)
  1370. if extra != nil {
  1371. for _, v := range extra.LegendConfig {
  1372. s := fmt.Sprintf("%d-%d", v.SeriesId, v.EdbInfoId)
  1373. legends[s] = v
  1374. }
  1375. }
  1376. // 获取图表引用到的系列指标
  1377. chartMappingOb := new(data_manage.FactorEdbSeriesChartMapping)
  1378. cond := fmt.Sprintf(" AND %s = ? AND %s = 1", chartMappingOb.Cols().ChartInfoId, chartMappingOb.Cols().EdbUsed)
  1379. pars := make([]interface{}, 0)
  1380. pars = append(pars, chartInfoId)
  1381. chartMappings, e := chartMappingOb.GetItemsByCondition(cond, pars, []string{}, "")
  1382. if e != nil {
  1383. err = fmt.Errorf("获取图表引用系列指标失败")
  1384. return
  1385. }
  1386. // 取出计算结果
  1387. yDataList = make([]data_manage.YData, 0)
  1388. yDate := "0000-00-00"
  1389. for k, m := range chartMappings {
  1390. var values []data_manage.FactorEdbSeriesCorrelationMatrixValues
  1391. if m.CalculateData != "" {
  1392. e = json.Unmarshal([]byte(m.CalculateData), &values)
  1393. if e != nil {
  1394. err = fmt.Errorf("系列指标计算数据有误, err: %v", e)
  1395. return
  1396. }
  1397. }
  1398. var y []float64
  1399. for _, v := range values {
  1400. if k == 0 {
  1401. xEdbIdValue = append(xEdbIdValue, v.XData)
  1402. }
  1403. y = append(y, v.YData)
  1404. }
  1405. var yData data_manage.YData
  1406. yData.Date = yDate
  1407. yData.Value = y
  1408. yData.SeriesEdb.SeriesId = m.FactorEdbSeriesId
  1409. yData.SeriesEdb.EdbInfoId = m.EdbInfoId
  1410. // 图例
  1411. s := fmt.Sprintf("%d-%d", m.FactorEdbSeriesId, m.EdbInfoId)
  1412. legend := legends[s]
  1413. if legend != nil {
  1414. yData.Name = legend.LegendName
  1415. yData.Color = legend.Color
  1416. }
  1417. yDataList = append(yDataList, yData)
  1418. }
  1419. return
  1420. }
  1421. // RemoveCorrelationRelate 删除相关性图表关联信息
  1422. func RemoveCorrelationRelate(chartInfoId int) (err error) {
  1423. if chartInfoId <= 0 {
  1424. return
  1425. }
  1426. // 相关性图表
  1427. chartCorrelate := new(data_manage.ChartInfoCorrelation)
  1428. if e := chartCorrelate.GetItemById(chartInfoId); e != nil && e.Error() != utils.ErrNoRow() {
  1429. err = fmt.Errorf("获取相关性图表信息失败, %v", e)
  1430. return
  1431. }
  1432. if chartCorrelate == nil {
  1433. return
  1434. }
  1435. // 删除相关性图
  1436. if e := chartCorrelate.Delete(); e != nil {
  1437. err = fmt.Errorf("删除相关性图表失败, %v", e)
  1438. return
  1439. }
  1440. // 多因子
  1441. if chartCorrelate.AnalysisMode != 1 {
  1442. return
  1443. }
  1444. seriesIds := make([]int, 0)
  1445. // 删除图表关联
  1446. chartMappingOb := new(data_manage.FactorEdbSeriesChartMapping)
  1447. {
  1448. cond := fmt.Sprintf(" AND %s = ?", chartMappingOb.Cols().ChartInfoId)
  1449. pars := make([]interface{}, 0)
  1450. pars = append(pars, chartCorrelate.CorrelationChartInfoId)
  1451. items, e := chartMappingOb.GetItemsByCondition(cond, pars, []string{}, "")
  1452. if e != nil {
  1453. err = fmt.Errorf("获取图表关联指标系列失败, %v", e)
  1454. return
  1455. }
  1456. for _, v := range items {
  1457. if !utils.InArrayByInt(seriesIds, v.FactorEdbSeriesId) {
  1458. seriesIds = append(seriesIds, v.FactorEdbSeriesId)
  1459. }
  1460. }
  1461. removeCond := fmt.Sprintf(" %s = ?", chartMappingOb.Cols().ChartInfoId)
  1462. if e = chartMappingOb.RemoveByCondition(removeCond, pars); e != nil {
  1463. err = fmt.Errorf("删除图表关联指标系列失败, %v", e)
  1464. return
  1465. }
  1466. }
  1467. // 删除系列
  1468. if len(seriesIds) == 0 {
  1469. return
  1470. }
  1471. seriesOb := new(data_manage.FactorEdbSeries)
  1472. if e := seriesOb.MultiRemove(seriesIds); e != nil {
  1473. err = fmt.Errorf("删除系列失败, %v", e)
  1474. return
  1475. }
  1476. edbMappingOb := new(data_manage.FactorEdbSeriesMapping)
  1477. {
  1478. cond := fmt.Sprintf(" %s IN (%s)", edbMappingOb.Cols().FactorEdbSeriesId, utils.GetOrmInReplace(len(seriesIds)))
  1479. pars := make([]interface{}, 0)
  1480. pars = append(pars, seriesIds)
  1481. if e := edbMappingOb.RemoveByCondition(cond, pars); e != nil {
  1482. err = fmt.Errorf("删除系列指标失败, %v", e)
  1483. return
  1484. }
  1485. }
  1486. calculateOb := new(data_manage.FactorEdbSeriesCalculateData)
  1487. {
  1488. cond := fmt.Sprintf(" %s IN (%s)", calculateOb.Cols().FactorEdbSeriesId, utils.GetOrmInReplace(len(seriesIds)))
  1489. pars := make([]interface{}, 0)
  1490. pars = append(pars, seriesIds)
  1491. if e := calculateOb.RemoveByCondition(cond, pars); e != nil {
  1492. err = fmt.Errorf("删除系列指标计算失败, %v", e)
  1493. return
  1494. }
  1495. }
  1496. return
  1497. }
  1498. // CalculateCorrelationMatrix 计算相关性矩阵
  1499. func CalculateCorrelationMatrix(req data_manage.CalculateCorrelationMatrixPars) (resp data_manage.FactorEdbSeriesCorrelationMatrixResp, chartMappings []*data_manage.FactorEdbSeriesChartMapping, err error) {
  1500. if req.BaseEdbInfoId <= 0 {
  1501. err = fmt.Errorf("请选择标的指标")
  1502. return
  1503. }
  1504. if len(req.SeriesIds) == 0 {
  1505. err = fmt.Errorf("请选择因子指标系列")
  1506. return
  1507. }
  1508. if req.Correlation.LeadValue <= 0 {
  1509. err = fmt.Errorf("分析周期不允许设置为负数或0")
  1510. return
  1511. }
  1512. if req.Correlation.LeadUnit == "" {
  1513. err = fmt.Errorf("请选择分析周期频度")
  1514. return
  1515. }
  1516. leadUnitDays, ok := utils.FrequencyDaysMap[req.Correlation.LeadUnit]
  1517. if !ok {
  1518. err = fmt.Errorf("错误的分析周期频度: %s", req.Correlation.LeadUnit)
  1519. return
  1520. }
  1521. if req.Correlation.CalculateUnit == "" {
  1522. err = fmt.Errorf("请选择计算窗口频度")
  1523. return
  1524. }
  1525. calculateUnitDays, ok := utils.FrequencyDaysMap[req.Correlation.CalculateUnit]
  1526. if !ok {
  1527. err = fmt.Errorf("计算窗口频度有误: %s", req.Correlation.CalculateUnit)
  1528. return
  1529. }
  1530. leadDays := 2 * req.Correlation.LeadValue * leadUnitDays
  1531. calculateDays := req.Correlation.CalculateValue * calculateUnitDays
  1532. if calculateDays < leadDays {
  1533. err = fmt.Errorf("计算窗口必须≥2*分析周期")
  1534. return
  1535. }
  1536. // 获取标的指标信息及数据
  1537. baseEdb, e := data_manage.GetEdbInfoById(req.BaseEdbInfoId)
  1538. if e != nil {
  1539. err = fmt.Errorf("获取标的指标失败, %v", e)
  1540. return
  1541. }
  1542. dataListA := make([]*data_manage.EdbDataList, 0)
  1543. {
  1544. // 标的指标数据日期区间
  1545. startDate := time.Now().AddDate(0, 0, -calculateDays).Format(utils.FormatDate)
  1546. endDate := time.Now().Format(utils.FormatDate)
  1547. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  1548. startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate) // 不包含第一天
  1549. switch baseEdb.EdbInfoType {
  1550. case 0:
  1551. dataListA, e = data_manage.GetEdbDataList(baseEdb.Source, baseEdb.SubSource, baseEdb.EdbInfoId, startDate, endDate)
  1552. case 1:
  1553. _, dataListA, _, _, e, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdb.EdbInfoId, startDate, endDate, false)
  1554. default:
  1555. err = fmt.Errorf("标的指标类型异常: %d", baseEdb.EdbInfoType)
  1556. return
  1557. }
  1558. if e != nil {
  1559. err = fmt.Errorf("获取标的指标数据失败, %v", e)
  1560. return
  1561. }
  1562. }
  1563. // 获取因子系列
  1564. seriesIdItem := make(map[int]*data_manage.FactorEdbSeries)
  1565. {
  1566. ob := new(data_manage.FactorEdbSeries)
  1567. cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().PrimaryId, utils.GetOrmInReplace(len(req.SeriesIds)))
  1568. pars := make([]interface{}, 0)
  1569. pars = append(pars, req.SeriesIds)
  1570. items, e := ob.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", ob.Cols().PrimaryId))
  1571. if e != nil {
  1572. err = fmt.Errorf("获取因子指标系列失败, %v", e)
  1573. return
  1574. }
  1575. for _, v := range items {
  1576. seriesIdItem[v.FactorEdbSeriesId] = v
  1577. }
  1578. }
  1579. // 获取因子指标
  1580. edbMappings := make([]*data_manage.FactorEdbSeriesMapping, 0)
  1581. edbInfoIds := make([]int, 0)
  1582. {
  1583. ob := new(data_manage.FactorEdbSeriesMapping)
  1584. cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().FactorEdbSeriesId, utils.GetOrmInReplace(len(req.SeriesIds)))
  1585. pars := make([]interface{}, 0)
  1586. pars = append(pars, req.SeriesIds)
  1587. order := fmt.Sprintf("%s ASC, %s ASC", ob.Cols().FactorEdbSeriesId, ob.Cols().EdbInfoId)
  1588. items, e := ob.GetItemsByCondition(cond, pars, []string{}, order)
  1589. if e != nil {
  1590. err = fmt.Errorf("获取系列指标失败, %v", e)
  1591. return
  1592. }
  1593. for _, v := range items {
  1594. edbInfoIds = append(edbInfoIds, v.EdbInfoId)
  1595. }
  1596. edbMappings = items
  1597. }
  1598. edbIdItem := make(map[int]*data_manage.EdbInfo)
  1599. edbItems, e := data_manage.GetEdbInfoByIdList(edbInfoIds)
  1600. if e != nil {
  1601. err = fmt.Errorf("获取因子指标信息失败, %v", e)
  1602. return
  1603. }
  1604. for _, v := range edbItems {
  1605. edbIdItem[v.EdbInfoId] = v
  1606. }
  1607. calculateDataOb := new(data_manage.FactorEdbSeriesCalculateData)
  1608. calculateWorkers := make(chan struct{}, 10)
  1609. wg := sync.WaitGroup{}
  1610. edbExists := make(map[string]bool)
  1611. chartKeyMap := make(map[string]*data_manage.FactorEdbSeriesChartMapping)
  1612. for _, v := range edbMappings {
  1613. existsKey := fmt.Sprintf("%d-%d", v.FactorEdbSeriesId, v.EdbInfoId)
  1614. if edbExists[existsKey] {
  1615. continue
  1616. }
  1617. edbExists[existsKey] = true
  1618. edbItem := edbIdItem[v.EdbInfoId]
  1619. if edbItem == nil {
  1620. continue
  1621. }
  1622. seriesItem := seriesIdItem[v.FactorEdbSeriesId]
  1623. if seriesItem == nil {
  1624. continue
  1625. }
  1626. wg.Add(1)
  1627. go func(mapping *data_manage.FactorEdbSeriesMapping, edb *data_manage.EdbInfo, series *data_manage.FactorEdbSeries) {
  1628. defer func() {
  1629. wg.Done()
  1630. <-calculateWorkers
  1631. }()
  1632. calculateWorkers <- struct{}{}
  1633. var item data_manage.FactorEdbSeriesCorrelationMatrixItem
  1634. item.SeriesId = series.FactorEdbSeriesId
  1635. item.EdbInfoId = edb.EdbInfoId
  1636. item.EdbCode = edb.EdbCode
  1637. item.EdbName = edb.EdbName
  1638. // 指标来源
  1639. edbList := make([]*data_manage.ChartEdbInfoMapping, 0)
  1640. edbList = append(edbList, &data_manage.ChartEdbInfoMapping{
  1641. EdbInfoId: edb.EdbInfoId,
  1642. EdbInfoCategoryType: edb.EdbInfoType,
  1643. EdbType: edb.EdbType,
  1644. Source: edb.Source,
  1645. SourceName: edb.SourceName,
  1646. })
  1647. sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
  1648. item.SourceName = strings.Join(sourceNameList, ",")
  1649. item.SourceNameEn = strings.Join(sourceNameEnList, ",")
  1650. // 获取指标数据
  1651. dataListB := make([]*data_manage.EdbDataList, 0)
  1652. if series.CalculateState == data_manage.FactorEdbSeriesCalculated {
  1653. cond := fmt.Sprintf(" AND %s = ? AND %s = ?", calculateDataOb.Cols().FactorEdbSeriesId, calculateDataOb.Cols().EdbInfoId)
  1654. pars := make([]interface{}, 0)
  1655. pars = append(pars, mapping.FactorEdbSeriesId, mapping.EdbInfoId)
  1656. dataItems, e := calculateDataOb.GetItemsByCondition(cond, pars, []string{calculateDataOb.Cols().DataTime, calculateDataOb.Cols().Value}, fmt.Sprintf("%s ASC", calculateDataOb.Cols().DataTime))
  1657. if e != nil {
  1658. item.Msg = fmt.Sprintf("计算失败")
  1659. item.ErrMsg = fmt.Sprintf("获取计算数据失败, err: %v", e)
  1660. resp.Fail = append(resp.Fail, item)
  1661. return
  1662. }
  1663. dataListB = data_manage.TransEdbSeriesCalculateData2EdbDataList(dataItems)
  1664. } else {
  1665. switch edb.EdbInfoType {
  1666. case 0:
  1667. dataListB, e = data_manage.GetEdbDataList(edb.Source, edb.SubSource, edb.EdbInfoId, "", "")
  1668. case 1:
  1669. _, dataListB, _, _, e, _ = data.GetPredictDataListByPredictEdbInfoId(edb.EdbInfoId, "", "", false)
  1670. default:
  1671. item.Msg = fmt.Sprintf("计算失败")
  1672. item.ErrMsg = fmt.Sprintf("指标类型异常, edbType: %d", edb.EdbInfoType)
  1673. resp.Fail = append(resp.Fail, item)
  1674. return
  1675. }
  1676. }
  1677. // 计算相关性
  1678. xEdbIdValue, yDataList, e := CalculateCorrelation(req.Correlation.LeadValue, req.Correlation.LeadUnit, baseEdb.Frequency, edb.Frequency, dataListA, dataListB)
  1679. if e != nil {
  1680. item.Msg = fmt.Sprintf("计算失败")
  1681. item.ErrMsg = fmt.Sprintf("相关性计算失败, err: %v", e)
  1682. resp.Fail = append(resp.Fail, item)
  1683. return
  1684. }
  1685. // X及Y轴数据
  1686. yData := yDataList[0].Value
  1687. yLen := len(yData)
  1688. values := make([]data_manage.FactorEdbSeriesCorrelationMatrixValues, len(xEdbIdValue))
  1689. for k, x := range xEdbIdValue {
  1690. var y float64
  1691. if k >= 0 && k < yLen {
  1692. y = yData[k]
  1693. }
  1694. y = utils.SubFloatToFloat(y, 2)
  1695. values[k] = data_manage.FactorEdbSeriesCorrelationMatrixValues{
  1696. XData: x, YData: y,
  1697. }
  1698. }
  1699. // 图表关联
  1700. newMapping := new(data_manage.FactorEdbSeriesChartMapping)
  1701. newMapping.CalculateType = data_manage.FactorEdbSeriesChartCalculateTypeCorrelation
  1702. // 计算参数
  1703. var calculatePars data_manage.FactorEdbSeriesChartCalculateCorrelationReq
  1704. calculatePars.BaseEdbInfoId = req.BaseEdbInfoId
  1705. calculatePars.LeadValue = req.Correlation.LeadValue
  1706. calculatePars.LeadUnit = req.Correlation.LeadUnit
  1707. calculatePars.CalculateValue = req.Correlation.CalculateValue
  1708. calculatePars.CalculateUnit = req.Correlation.CalculateUnit
  1709. bc, e := json.Marshal(calculatePars)
  1710. if e != nil {
  1711. item.Msg = fmt.Sprintf("计算失败")
  1712. item.ErrMsg = fmt.Sprintf("计算参数JSON格式化失败, err: %v", e)
  1713. resp.Fail = append(resp.Fail, item)
  1714. return
  1715. }
  1716. newMapping.CalculatePars = string(bc)
  1717. // 计算结果, 注此处保存的是排序前的顺序
  1718. bv, e := json.Marshal(values)
  1719. if e != nil {
  1720. item.Msg = fmt.Sprintf("计算失败")
  1721. item.ErrMsg = fmt.Sprintf("计算结果JSON格式化失败, err: %v", e)
  1722. resp.Fail = append(resp.Fail, item)
  1723. return
  1724. }
  1725. newMapping.CalculateData = string(bv)
  1726. newMapping.FactorEdbSeriesId = mapping.FactorEdbSeriesId
  1727. newMapping.EdbInfoId = mapping.EdbInfoId
  1728. newMapping.CreateTime = time.Now().Local()
  1729. newMapping.ModifyTime = time.Now().Local()
  1730. chartKeyMap[existsKey] = newMapping
  1731. // 按照固定规则排期数[0 1 2 3 -1 -2 -3], 仅矩阵展示为此顺序
  1732. sort.Sort(data_manage.FactorEdbSeriesCorrelationMatrixOrder(values))
  1733. item.Msg = "计算成功"
  1734. item.Values = values
  1735. resp.Success = append(resp.Success, item)
  1736. }(v, edbItem, seriesItem)
  1737. }
  1738. wg.Wait()
  1739. // 新增图表关联, 此处按照顺序添加
  1740. chartMappings = make([]*data_manage.FactorEdbSeriesChartMapping, 0)
  1741. for _, v := range edbMappings {
  1742. k := fmt.Sprintf("%d-%d", v.FactorEdbSeriesId, v.EdbInfoId)
  1743. item := chartKeyMap[k]
  1744. if item == nil {
  1745. continue
  1746. }
  1747. chartMappings = append(chartMappings, item)
  1748. }
  1749. return
  1750. }