predict_edb_data_calculate_nhcc.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. package models
  2. import (
  3. "errors"
  4. "eta/eta_index_lib/utils"
  5. "fmt"
  6. "github.com/beego/beego/v2/client/orm"
  7. "github.com/shopspring/decimal"
  8. "math"
  9. "strings"
  10. "time"
  11. )
  12. // EdbDataPredictCalculateNhcc 拟合残差数据结构体
  13. type EdbDataPredictCalculateNhcc struct {
  14. EdbDataId int `orm:"column(edb_data_id);pk"`
  15. EdbInfoId int
  16. EdbCode string
  17. DataTime string
  18. Value float64
  19. Status int
  20. CreateTime time.Time
  21. ModifyTime time.Time
  22. DataTimestamp int64
  23. }
  24. // SavePredictCalculateNhcc 新增拟合残差数据
  25. func SavePredictCalculateNhcc(req *EdbInfoCalculateBatchSaveReq, firstEdbInfo, secondEdbInfo *EdbInfo, edbCode, uniqueCode string, nhccDate NhccDate, sysUserId int, sysUserRealName, lang string) (edbInfo *EdbInfo, latestDateStr string, latestValue float64, err error) {
  26. o := orm.NewOrm()
  27. to, err := o.Begin()
  28. if err != nil {
  29. return
  30. }
  31. defer func() {
  32. if err != nil {
  33. fmt.Println("SavePredictCalculateNhcc,Err:" + err.Error())
  34. _ = to.Rollback()
  35. } else {
  36. _ = to.Commit()
  37. }
  38. }()
  39. var existItemA, existItemB *EdbInfoCalculateMapping
  40. if req.EdbInfoId <= 0 {
  41. edbInfo = &EdbInfo{
  42. EdbInfoType: 1,
  43. SourceName: "预测拟合残差",
  44. Source: utils.DATA_SOURCE_PREDICT_CALCULATE_NHCC,
  45. EdbCode: edbCode,
  46. EdbName: req.EdbName,
  47. EdbNameSource: req.EdbName,
  48. Frequency: req.Frequency,
  49. Unit: req.Unit,
  50. StartDate: firstEdbInfo.StartDate,
  51. EndDate: firstEdbInfo.EndDate,
  52. ClassifyId: req.ClassifyId,
  53. SysUserId: sysUserId,
  54. SysUserRealName: sysUserRealName,
  55. UniqueCode: uniqueCode,
  56. CreateTime: time.Now(),
  57. ModifyTime: time.Now(),
  58. CalculateFormula: req.Formula,
  59. EdbNameEn: req.EdbName,
  60. UnitEn: req.Unit,
  61. EdbType: 2,
  62. }
  63. newEdbInfoId, tmpErr := to.Insert(edbInfo)
  64. if tmpErr != nil {
  65. err = tmpErr
  66. return
  67. }
  68. edbInfo.EdbInfoId = int(newEdbInfoId)
  69. //第一个指标
  70. {
  71. existItemA = &EdbInfoCalculateMapping{
  72. EdbInfoCalculateMappingId: 0,
  73. EdbInfoId: edbInfo.EdbInfoId,
  74. Source: edbInfo.Source,
  75. SourceName: edbInfo.SourceName,
  76. EdbCode: edbInfo.EdbCode,
  77. FromEdbInfoId: firstEdbInfo.EdbInfoId,
  78. FromEdbCode: firstEdbInfo.EdbCode,
  79. FromEdbName: firstEdbInfo.EdbName,
  80. FromSource: firstEdbInfo.Source,
  81. FromSourceName: firstEdbInfo.SourceName,
  82. FromTag: "A",
  83. MoveValue: req.EdbInfoIdArr[0].MoveValue,
  84. Sort: 1,
  85. CreateTime: time.Now(),
  86. ModifyTime: time.Now(),
  87. }
  88. insertId, tmpErr := to.Insert(existItemA)
  89. if tmpErr != nil {
  90. err = tmpErr
  91. return
  92. }
  93. existItemA.EdbInfoCalculateMappingId = int(insertId)
  94. }
  95. //第二个指标
  96. {
  97. existItemB = &EdbInfoCalculateMapping{
  98. EdbInfoCalculateMappingId: 0,
  99. EdbInfoId: edbInfo.EdbInfoId,
  100. Source: edbInfo.Source,
  101. SourceName: edbInfo.SourceName,
  102. EdbCode: edbInfo.EdbCode,
  103. FromEdbInfoId: secondEdbInfo.EdbInfoId,
  104. FromEdbCode: secondEdbInfo.EdbCode,
  105. FromEdbName: secondEdbInfo.EdbName,
  106. FromSource: secondEdbInfo.Source,
  107. FromSourceName: secondEdbInfo.SourceName,
  108. FromTag: "B",
  109. MoveValue: req.EdbInfoIdArr[1].MoveValue,
  110. Sort: 1,
  111. CreateTime: time.Now(),
  112. ModifyTime: time.Now(),
  113. }
  114. insertId, tmpErr := to.Insert(existItemB)
  115. if tmpErr != nil {
  116. err = tmpErr
  117. return
  118. }
  119. existItemB.EdbInfoCalculateMappingId = int(insertId)
  120. }
  121. } else {
  122. edbInfo, err = GetEdbInfoById(req.EdbInfoId)
  123. if err != nil {
  124. return
  125. }
  126. latestDateStr = edbInfo.LatestDate
  127. latestValue = edbInfo.LatestValue
  128. nowEdbInfo := *edbInfo // 现在的指标信息
  129. //修改指标信息
  130. switch lang {
  131. case utils.EnLangVersion:
  132. edbInfo.EdbNameEn = req.EdbName
  133. edbInfo.UnitEn = req.Unit
  134. default:
  135. edbInfo.EdbName = req.EdbName
  136. edbInfo.Unit = req.Unit
  137. edbInfo.EdbNameSource = req.EdbName
  138. }
  139. edbInfo.Frequency = req.Frequency
  140. edbInfo.ClassifyId = req.ClassifyId
  141. edbInfo.CalculateFormula = req.Formula
  142. edbInfo.ModifyTime = time.Now()
  143. _, err = to.Update(edbInfo, "EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId", "CalculateFormula", "ModifyTime", "EdbNameEn", "UnitEn")
  144. if err != nil {
  145. return
  146. }
  147. var existCondition string
  148. var existPars []interface{}
  149. existCondition += " AND edb_info_id=? "
  150. existPars = append(existPars, edbInfo.EdbInfoId)
  151. //查询出所有的关联指标
  152. var existList []*EdbInfoCalculateMapping
  153. existList, err = GetEdbInfoCalculateListByCondition(existCondition, existPars)
  154. if err != nil {
  155. err = fmt.Errorf("判断指标是否改变失败,Err:" + err.Error())
  156. return
  157. }
  158. for _, existItem := range existList {
  159. if existItem.FromTag == "A" {
  160. existItemA = existItem
  161. } else if existItem.FromTag == "B" {
  162. existItemB = existItem
  163. }
  164. }
  165. if existItemA == nil {
  166. err = errors.New("原自变量指标不存在")
  167. return
  168. }
  169. if existItemB == nil {
  170. err = errors.New("原因变量指标不存在")
  171. return
  172. }
  173. // 是否需要删除数据重新计算
  174. isNeedCalculateData := false
  175. // 如果截止日期变更,那么需要重新计算
  176. if req.Formula != nowEdbInfo.CalculateFormula {
  177. isNeedCalculateData = true
  178. }
  179. var isDeleteA, isDeleteB bool
  180. // 如果指标变了,那么需要删除关系
  181. {
  182. if existItemA.FromEdbInfoId != firstEdbInfo.EdbInfoId {
  183. //删除之前的A指标关联关系
  184. sql := ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? and from_edb_info_id = ?`
  185. _, err = to.Raw(sql, edbInfo.EdbInfoId, existItemA.FromEdbInfoId).Exec()
  186. if err != nil {
  187. err = fmt.Errorf("删除指标A关联关系失败,Err:" + err.Error())
  188. return
  189. }
  190. isDeleteA = true
  191. }
  192. //并重新计算
  193. if existItemB.FromEdbInfoId != secondEdbInfo.EdbInfoId {
  194. //删除之前的B指标关联关系
  195. sql := ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? and from_edb_info_id = ?`
  196. _, err = to.Raw(sql, edbInfo.EdbInfoId, existItemB.FromEdbInfoId).Exec()
  197. if err != nil {
  198. err = fmt.Errorf("删除指标B关联关系失败,Err:" + err.Error())
  199. return
  200. }
  201. isDeleteB = true
  202. }
  203. }
  204. //第一个指标数据
  205. {
  206. // 如果指标变了,那么需要删除关系,并重新计算
  207. if isDeleteA {
  208. //添加新的指标关系
  209. {
  210. existItemA = &EdbInfoCalculateMapping{
  211. EdbInfoCalculateMappingId: 0,
  212. EdbInfoId: edbInfo.EdbInfoId,
  213. Source: edbInfo.Source,
  214. SourceName: edbInfo.SourceName,
  215. EdbCode: edbInfo.EdbCode,
  216. FromEdbInfoId: firstEdbInfo.EdbInfoId,
  217. FromEdbCode: firstEdbInfo.EdbCode,
  218. FromEdbName: firstEdbInfo.EdbName,
  219. FromSource: firstEdbInfo.Source,
  220. FromSourceName: firstEdbInfo.SourceName,
  221. FromTag: "A",
  222. MoveValue: req.EdbInfoIdArr[0].MoveValue,
  223. Sort: 1,
  224. CreateTime: time.Now(),
  225. ModifyTime: time.Now(),
  226. }
  227. insertId, tmpErr := to.Insert(existItemA)
  228. if tmpErr != nil {
  229. err = tmpErr
  230. return
  231. }
  232. existItemA.EdbInfoCalculateMappingId = int(insertId)
  233. isNeedCalculateData = true
  234. }
  235. } else if existItemA.MoveValue != req.EdbInfoIdArr[0].MoveValue {
  236. // 如果平移天数不一致的话,
  237. existItemA.ModifyTime = time.Now()
  238. existItemA.MoveValue = req.EdbInfoIdArr[0].MoveValue
  239. _, err = to.Update(existItemA, "ModifyTime", "MoveValue")
  240. if err != nil {
  241. return
  242. }
  243. isNeedCalculateData = true
  244. }
  245. }
  246. //第二个指标数据
  247. {
  248. // 如果指标变了,那么需要删除关系,并重新计算
  249. if isDeleteB {
  250. // 添加新的指标关联关系
  251. existItemB = &EdbInfoCalculateMapping{
  252. EdbInfoCalculateMappingId: 0,
  253. EdbInfoId: edbInfo.EdbInfoId,
  254. Source: edbInfo.Source,
  255. SourceName: edbInfo.SourceName,
  256. EdbCode: edbInfo.EdbCode,
  257. FromEdbInfoId: secondEdbInfo.EdbInfoId,
  258. FromEdbCode: secondEdbInfo.EdbCode,
  259. FromEdbName: secondEdbInfo.EdbName,
  260. FromSource: secondEdbInfo.Source,
  261. FromSourceName: secondEdbInfo.SourceName,
  262. FromTag: "B",
  263. MoveValue: req.EdbInfoIdArr[1].MoveValue,
  264. Sort: 2,
  265. CreateTime: time.Now(),
  266. ModifyTime: time.Now(),
  267. }
  268. insertId, tmpErr := to.Insert(existItemB)
  269. if tmpErr != nil {
  270. err = tmpErr
  271. return
  272. }
  273. existItemB.EdbInfoCalculateMappingId = int(insertId)
  274. isNeedCalculateData = true
  275. } else if existItemB.MoveValue != req.EdbInfoIdArr[1].MoveValue {
  276. // 如果平移天数不一致的话,
  277. existItemB.ModifyTime = time.Now()
  278. existItemB.MoveValue = req.EdbInfoIdArr[1].MoveValue
  279. _, err = to.Update(existItemB, "ModifyTime", "MoveValue")
  280. if err != nil {
  281. return
  282. }
  283. isNeedCalculateData = true
  284. }
  285. }
  286. // 如果需要重新计算,那么先删除所有的指标数据,然后再重新计算
  287. if isNeedCalculateData {
  288. // 删除之前所有的指标数据
  289. tableName := GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
  290. sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? `, tableName)
  291. _, err = to.Raw(sql, edbInfo.EdbInfoId).Exec()
  292. if err != nil {
  293. err = fmt.Errorf("删除历史数据失败,Err:" + err.Error())
  294. return
  295. }
  296. } else {
  297. return
  298. }
  299. }
  300. //拼接数据
  301. latestDateStr, latestValue, err = refreshAllPredictCalculateNhcc(to, edbInfo, firstEdbInfo, secondEdbInfo, existItemA, existItemB, nhccDate)
  302. return
  303. }
  304. // RefreshAllPredictCalculateNhcc 刷新所有 拟合残差 数据
  305. func RefreshAllPredictCalculateNhcc(edbInfo *EdbInfo) (latestDateStr string, latestValue float64, err error) {
  306. o := orm.NewOrm()
  307. to, err := o.Begin()
  308. defer func() {
  309. if err != nil {
  310. fmt.Println("RefreshAllPredictCalculateNhcc,Err:" + err.Error())
  311. _ = to.Rollback()
  312. } else {
  313. _ = to.Commit()
  314. }
  315. }()
  316. //查询关联指标信息
  317. var existCondition string
  318. var existPars []interface{}
  319. existCondition += " AND edb_info_id=? "
  320. existPars = append(existPars, edbInfo.EdbInfoId)
  321. existList, err := GetEdbInfoCalculateListByCondition(existCondition, existPars)
  322. if err != nil {
  323. err = fmt.Errorf("判断指标是否改变失败,Err:" + err.Error())
  324. return
  325. }
  326. var existItemA, existItemB *EdbInfoCalculateMapping
  327. for _, existItem := range existList {
  328. if existItem.FromTag == "A" {
  329. existItemA = existItem
  330. } else if existItem.FromTag == "B" {
  331. existItemB = existItem
  332. }
  333. }
  334. if existItemA == nil {
  335. err = errors.New("原自变量指标不存在")
  336. return
  337. }
  338. if existItemB == nil {
  339. err = errors.New("原因变量指标不存在")
  340. return
  341. }
  342. fromEdbInfo, err := GetEdbInfoById(existItemA.FromEdbInfoId)
  343. if err != nil {
  344. err = fmt.Errorf("GetEdbInfoById Err:" + err.Error())
  345. return
  346. }
  347. secondEdbInfo, err := GetEdbInfoById(existItemB.FromEdbInfoId)
  348. if err != nil {
  349. err = fmt.Errorf("GetEdbInfoById Err:" + err.Error())
  350. return
  351. }
  352. timeList := strings.Split(edbInfo.CalculateFormula, ",")
  353. startDate, err := time.ParseInLocation(utils.FormatDate, timeList[0], time.Local)
  354. if err != nil {
  355. return
  356. }
  357. endDate, err := time.ParseInLocation(utils.FormatDate, timeList[1], time.Local)
  358. if err != nil {
  359. return
  360. }
  361. if endDate.Sub(startDate).Hours() < 48 {
  362. return
  363. }
  364. nhccDate := NhccDate{
  365. StartDate: startDate,
  366. EndDate: endDate,
  367. }
  368. // 刷新数据
  369. latestDateStr, latestValue, err = refreshAllPredictCalculateNhcc(to, edbInfo, fromEdbInfo, secondEdbInfo, existItemA, existItemB, nhccDate)
  370. return
  371. }
  372. // refreshAllPredictCalculateNhcc 刷新所有 拟合残差 数据
  373. func refreshAllPredictCalculateNhcc(to orm.TxOrmer, edbInfo, firstEdbInfo, secondEdbInfo *EdbInfo, existItemA, existItemB *EdbInfoCalculateMapping, nhccDate NhccDate) (latestDateStr string, latestValue float64, err error) {
  374. var dataList []*EdbDataPredictCalculateNhcc
  375. sql := ` SELECT * FROM edb_data_predict_calculate_nhcc WHERE edb_info_id=? ORDER BY data_time DESC `
  376. _, err = to.Raw(sql, edbInfo.EdbInfoId).QueryRows(&dataList)
  377. if err != nil {
  378. return
  379. }
  380. // 计算最新的实际值的日期
  381. latestDateA, _ := time.ParseInLocation(utils.FormatDate, firstEdbInfo.LatestDate, time.Local)
  382. if existItemA.MoveValue != 0 {
  383. latestDateA = latestDateA.AddDate(0, 0, existItemA.MoveValue)
  384. }
  385. latestDateB, _ := time.ParseInLocation(utils.FormatDate, secondEdbInfo.LatestDate, time.Local)
  386. if existItemB.MoveValue != 0 {
  387. latestDateB = latestDateA.AddDate(0, 0, existItemB.MoveValue)
  388. }
  389. if latestDateA.Before(latestDateB) {
  390. latestDateStr = latestDateA.Format(utils.FormatDate)
  391. } else {
  392. latestDateStr = latestDateB.Format(utils.FormatDate)
  393. }
  394. var dateArr []string
  395. dataMap := make(map[string]*EdbDataPredictCalculateNhcc)
  396. removeDataTimeMap := make(map[string]int) //需要移除的日期数据
  397. for _, v := range dataList {
  398. dateArr = append(dateArr, v.DataTime)
  399. dataMap[v.DataTime] = v
  400. removeDataTimeMap[v.DataTime] = 1
  401. }
  402. addDataList := make([]*EdbDataPredictCalculateNhcc, 0)
  403. aDataList, secondDataList, aDataMap, bDataMap, err := getPredictNhccData(firstEdbInfo, secondEdbInfo, existItemA, existItemB, nhccDate)
  404. // 计算线性方程公式
  405. var a, b float64
  406. {
  407. coordinateData := make([]utils.Coordinate, 0)
  408. for i := nhccDate.StartDate; i.Before(nhccDate.EndDate) || i.Equal(nhccDate.EndDate); i = i.AddDate(0, 0, 1) {
  409. dateStr := i.Format(utils.FormatDate)
  410. xValue, ok := aDataMap[dateStr]
  411. if !ok {
  412. err = errors.New("指标A日期:" + dateStr + "数据异常,导致计算线性方程公式失败")
  413. return
  414. }
  415. yValue, ok := bDataMap[dateStr]
  416. if !ok {
  417. err = errors.New("指标B日期:" + dateStr + "数据异常,导致计算线性方程公式失败")
  418. return
  419. }
  420. tmpCoordinate := utils.Coordinate{
  421. X: xValue,
  422. Y: yValue,
  423. }
  424. coordinateData = append(coordinateData, tmpCoordinate)
  425. }
  426. a, b = utils.GetLinearResult(coordinateData)
  427. }
  428. if math.IsNaN(a) || math.IsNaN(b) {
  429. err = errors.New("线性方程公式生成失败")
  430. return
  431. }
  432. //fmt.Println("a:", a, ";======b:", b)
  433. //计算B’
  434. newBDataMap := make(map[string]float64)
  435. {
  436. //B’=aA+b
  437. aDecimal := decimal.NewFromFloat(a)
  438. bDecimal := decimal.NewFromFloat(b)
  439. for _, aData := range aDataList {
  440. xDecimal := decimal.NewFromFloat(aData.Value)
  441. val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).RoundCeil(4).Float64()
  442. newBDataMap[aData.DataTime] = val
  443. }
  444. }
  445. // Delta=B-B‘
  446. for _, bData := range secondDataList {
  447. currDate := bData.DataTime
  448. //校验待删除日期数据里面是否存在该元素,如果存在的话,那么移除该元素
  449. if _, ok := removeDataTimeMap[currDate]; ok {
  450. delete(removeDataTimeMap, currDate)
  451. }
  452. b2Val, ok := newBDataMap[currDate]
  453. if !ok {
  454. // 如果B`不存在数据,那么就退出当前循环
  455. continue
  456. }
  457. bDecimal := decimal.NewFromFloat(bData.Value)
  458. b2Decimal := decimal.NewFromFloat(b2Val)
  459. val, _ := bDecimal.Sub(b2Decimal).RoundCeil(4).Float64()
  460. // 判断之前有没有该数据
  461. existData, ok := dataMap[currDate]
  462. if !ok { //不存在那么就添加吧
  463. currentDate, _ := time.ParseInLocation(utils.FormatDate, currDate, time.Local)
  464. timestamp := currentDate.UnixNano() / 1e6
  465. edbDataNhcc := &EdbDataPredictCalculateNhcc{
  466. EdbInfoId: edbInfo.EdbInfoId,
  467. EdbCode: edbInfo.EdbCode,
  468. DataTime: currDate,
  469. Value: val,
  470. Status: 1,
  471. CreateTime: time.Now(),
  472. ModifyTime: time.Now(),
  473. DataTimestamp: timestamp,
  474. }
  475. addDataList = append(addDataList, edbDataNhcc)
  476. } else {
  477. // 如果有的话,还需要判断值是否一致,一致则不处理,不一致则修改
  478. if existData.Value != val {
  479. existData.Value = val
  480. _, err = to.Update(existData, "Value")
  481. if err != nil {
  482. return
  483. }
  484. }
  485. }
  486. }
  487. //删除已经不存在的拟合残差指标数据(由于该指标当日的数据删除了)
  488. {
  489. removeDateList := make([]string, 0)
  490. for dateTime := range removeDataTimeMap {
  491. removeDateList = append(removeDateList, dateTime)
  492. }
  493. removeNum := len(removeDateList)
  494. if removeNum > 0 {
  495. //如果拼接指标变更了,那么需要删除所有的指标数据
  496. tableName := GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
  497. sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? and data_time in (`+utils.GetOrmInReplace(removeNum)+`) `, tableName)
  498. _, err = to.Raw(sql, edbInfo.EdbInfoId, removeDateList).Exec()
  499. if err != nil {
  500. err = fmt.Errorf("删除不存在的拟合残差指标数据失败,Err:" + err.Error())
  501. return
  502. }
  503. }
  504. }
  505. //数据入库
  506. if len(addDataList) > 0 {
  507. tmpAddDataList := make([]*EdbDataPredictCalculateNhcc, 0)
  508. i := 0
  509. for _, v := range addDataList {
  510. tmpAddDataList = append(tmpAddDataList, v)
  511. i++
  512. if i >= 500 {
  513. _, err = to.InsertMulti(len(tmpAddDataList), tmpAddDataList)
  514. if err != nil {
  515. return
  516. }
  517. i = 0
  518. tmpAddDataList = make([]*EdbDataPredictCalculateNhcc, 0)
  519. }
  520. }
  521. if len(tmpAddDataList) > 0 {
  522. _, err = to.InsertMulti(len(tmpAddDataList), tmpAddDataList)
  523. if err != nil {
  524. return
  525. }
  526. }
  527. }
  528. //确定最终值
  529. var finalLast EdbInfoSearchData
  530. sql = ` SELECT data_time , value FROM edb_data_predict_calculate_nhcc WHERE edb_info_id=? and data_time<=? ORDER BY data_time DESC `
  531. tmpErr := to.Raw(sql, edbInfo.EdbInfoId, latestDateStr).QueryRow(&finalLast)
  532. if tmpErr != nil {
  533. if tmpErr.Error() != utils.ErrNoRow() {
  534. err = tmpErr
  535. }
  536. return
  537. } else {
  538. latestDateStr = finalLast.DataTime
  539. latestValue = finalLast.Value
  540. }
  541. return
  542. }
  543. // CalculatePredictComputeCorrelation 计算相关性结果
  544. func CalculatePredictComputeCorrelation(req *EdbInfoCalculateBatchSaveReq, firstEdbInfo, secondEdbInfo *EdbInfo, nhccDate NhccDate) (r float64, err error) {
  545. var existItemA, existItemB *EdbInfoCalculateMapping
  546. //第一个指标
  547. {
  548. existItemA = &EdbInfoCalculateMapping{
  549. EdbInfoCalculateMappingId: 0,
  550. FromEdbInfoId: firstEdbInfo.EdbInfoId,
  551. FromEdbCode: firstEdbInfo.EdbCode,
  552. FromEdbName: firstEdbInfo.EdbName,
  553. FromSource: firstEdbInfo.Source,
  554. FromSourceName: firstEdbInfo.SourceName,
  555. FromTag: "A",
  556. MoveValue: req.EdbInfoIdArr[0].MoveValue,
  557. Sort: 1,
  558. CreateTime: time.Now(),
  559. ModifyTime: time.Now(),
  560. }
  561. }
  562. //第二个指标
  563. {
  564. existItemB = &EdbInfoCalculateMapping{
  565. EdbInfoCalculateMappingId: 0,
  566. FromEdbInfoId: secondEdbInfo.EdbInfoId,
  567. FromEdbCode: secondEdbInfo.EdbCode,
  568. FromEdbName: secondEdbInfo.EdbName,
  569. FromSource: secondEdbInfo.Source,
  570. FromSourceName: secondEdbInfo.SourceName,
  571. FromTag: "B",
  572. MoveValue: req.EdbInfoIdArr[1].MoveValue,
  573. Sort: 1,
  574. CreateTime: time.Now(),
  575. ModifyTime: time.Now(),
  576. }
  577. }
  578. o := orm.NewOrm()
  579. to, err := o.Begin()
  580. defer func() {
  581. if err != nil {
  582. fmt.Println("RefreshAllCalculateNhcc,Err:" + err.Error())
  583. _ = to.Rollback()
  584. } else {
  585. _ = to.Commit()
  586. }
  587. }()
  588. // 获取相关数据
  589. _, _, aDataMap, bDataMap, err := getPredictNhccData(firstEdbInfo, secondEdbInfo, existItemA, existItemB, nhccDate)
  590. // 计算相关性
  591. coordinateData := make([]utils.Coordinate, 0)
  592. for i := nhccDate.StartDate; i.Before(nhccDate.EndDate) || i.Equal(nhccDate.EndDate); i = i.AddDate(0, 0, 1) {
  593. dateStr := i.Format(utils.FormatDate)
  594. xValue, ok := aDataMap[dateStr]
  595. if !ok {
  596. err = errors.New("指标A日期:" + dateStr + "数据异常,导致计算线性方程公式失败")
  597. return
  598. }
  599. yValue, ok := bDataMap[dateStr]
  600. if !ok {
  601. err = errors.New("指标B日期:" + dateStr + "数据异常,导致计算线性方程公式失败")
  602. return
  603. }
  604. tmpCoordinate := utils.Coordinate{
  605. X: xValue,
  606. Y: yValue,
  607. }
  608. coordinateData = append(coordinateData, tmpCoordinate)
  609. }
  610. r = utils.ComputeCorrelation(coordinateData)
  611. return
  612. }
  613. // getNhccData 获取拟合残差需要的数据
  614. func getPredictNhccData(firstEdbInfo, secondEdbInfo *EdbInfo, existItemA, existItemB *EdbInfoCalculateMapping, nhccDate NhccDate) (aDataList []EdbInfoSearchData, secondDataList []*EdbInfoSearchData, aDataMap, bDataMap map[string]float64, err error) {
  615. //第一个指标
  616. aDataList = make([]EdbInfoSearchData, 0)
  617. aDataMap = make(map[string]float64)
  618. {
  619. /*var condition string
  620. var pars []interface{}
  621. condition += " AND edb_info_id=? "
  622. pars = append(pars, existItemA.FromEdbInfoId)
  623. //第一个指标的数据列表
  624. firstDataList, tmpErr := GetEdbDataListAllByTo(to, condition, pars, existItemA.FromSource, 0)
  625. if tmpErr != nil {
  626. return tmpErr
  627. }*/
  628. var firstDataList []*EdbInfoSearchData
  629. firstDataList, err = GetPredictEdbDataListAllByStartDate(firstEdbInfo, 0, "")
  630. if err != nil {
  631. return
  632. }
  633. aDataList, aDataMap = handleNhccData(firstDataList, existItemA.MoveValue)
  634. }
  635. //第二个指标
  636. bDataList := make([]EdbInfoSearchData, 0)
  637. secondDataList = make([]*EdbInfoSearchData, 0)
  638. bDataMap = make(map[string]float64)
  639. {
  640. /*condition = ``
  641. pars = make([]interface{}, 0)
  642. condition += " AND edb_info_id = ? "
  643. pars = append(pars, existItemB.FromEdbInfoId)
  644. //第二个指标的数据列表
  645. secondDataList, err = GetEdbDataListAllByTo(to, condition, pars, existItemB.FromSource, 0)
  646. if err != nil {
  647. return
  648. }*/
  649. secondDataList, err = GetPredictEdbDataListAllByStartDate(secondEdbInfo, 0, "")
  650. if err != nil {
  651. return
  652. }
  653. bDataList, bDataMap = handleNhccData(secondDataList, existItemB.MoveValue)
  654. }
  655. if len(aDataList) <= 0 {
  656. err = errors.New("指标A没有数据")
  657. return
  658. }
  659. if len(bDataList) <= 0 {
  660. err = errors.New("指标B没有数据")
  661. return
  662. }
  663. // 拟合残差计算的结束日期判断
  664. {
  665. endAData := aDataList[len(aDataList)-1]
  666. tmpEndDate, tmpErr := time.ParseInLocation(utils.FormatDate, endAData.DataTime, time.Local)
  667. if tmpErr != nil {
  668. err = tmpErr
  669. return
  670. }
  671. // 如果A指标的最新数据日期早于拟合残差的结束日期,那么就用A指标的最新数据日期
  672. if tmpEndDate.Before(nhccDate.EndDate) {
  673. nhccDate.EndDate = tmpEndDate
  674. }
  675. endBData := bDataList[len(bDataList)-1]
  676. tmpEndDate, tmpErr = time.ParseInLocation(utils.FormatDate, endBData.DataTime, time.Local)
  677. if tmpErr != nil {
  678. err = tmpErr
  679. return
  680. }
  681. // 如果B指标的最新数据日期早于拟合残差的结束日期,那么就用B指标的最新数据日期
  682. if tmpEndDate.Before(nhccDate.EndDate) {
  683. nhccDate.EndDate = tmpEndDate
  684. }
  685. }
  686. return
  687. }