chart_info.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. package future_good
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/shopspring/decimal"
  6. "hongze/hongze_chart_lib/models"
  7. "hongze/hongze_chart_lib/models/data_manage"
  8. efuture_good "hongze/hongze_chart_lib/models/data_manage/future_good"
  9. "hongze/hongze_chart_lib/services/alarm_msg"
  10. "hongze/hongze_chart_lib/services/data"
  11. "hongze/hongze_chart_lib/utils"
  12. "strconv"
  13. "time"
  14. )
  15. // GetChartEdbData 获取图表的指标数据
  16. func GetChartEdbData(chartInfoId int, startDate, endDate string, edbInfoMapping, futureGoodEdbInfoMapping *models.ChartEdbInfoMapping, barChartInfoDateList []data_manage.BarChartInfoDateReq, barChartInfoSort data_manage.BarChartInfoSortReq) (barConfigEdbInfoIdList []data_manage.BarChartInfoEdbItemReq, edbList []*models.ChartEdbInfoMapping, xEdbIdValue []int, xDataList []models.XData, yDataList []models.YData, err error) {
  17. edbList = make([]*models.ChartEdbInfoMapping, 0)
  18. if futureGoodEdbInfoMapping == nil {
  19. err = errors.New("商品指标未选取")
  20. return
  21. }
  22. if edbInfoMapping == nil {
  23. err = errors.New("ETA指标未选取")
  24. return
  25. }
  26. // 指标对应的所有数据
  27. edbDataListMap := make(map[int][]*models.EdbDataList)
  28. item := new(data_manage.ChartEdbInfoMapping)
  29. edbInfoMapping.FrequencyEn = data.GetFrequencyEn(edbInfoMapping.Frequency)
  30. if edbInfoMapping.Unit == `无` {
  31. edbInfoMapping.Unit = ``
  32. }
  33. if futureGoodEdbInfoMapping.Unit == `无` {
  34. futureGoodEdbInfoMapping.Unit = ``
  35. }
  36. if chartInfoId <= 0 {
  37. edbInfoMapping.IsAxis = 1
  38. edbInfoMapping.LeadValue = 0
  39. edbInfoMapping.LeadUnit = ""
  40. edbInfoMapping.ChartEdbMappingId = 0
  41. edbInfoMapping.ChartInfoId = 0
  42. edbInfoMapping.IsOrder = false
  43. edbInfoMapping.EdbInfoType = 1
  44. edbInfoMapping.ChartStyle = ""
  45. edbInfoMapping.ChartColor = ""
  46. edbInfoMapping.ChartWidth = 0
  47. futureGoodEdbInfoMapping.IsAxis = 1
  48. futureGoodEdbInfoMapping.LeadValue = 0
  49. futureGoodEdbInfoMapping.LeadUnit = ""
  50. futureGoodEdbInfoMapping.ChartEdbMappingId = 0
  51. futureGoodEdbInfoMapping.ChartInfoId = 0
  52. futureGoodEdbInfoMapping.IsOrder = false
  53. futureGoodEdbInfoMapping.EdbInfoType = 1
  54. futureGoodEdbInfoMapping.ChartStyle = ""
  55. futureGoodEdbInfoMapping.ChartColor = ""
  56. futureGoodEdbInfoMapping.ChartWidth = 0
  57. } else {
  58. edbInfoMapping.LeadUnitEn = data.GetLeadUnitEn(edbInfoMapping.LeadUnit)
  59. futureGoodEdbInfoMapping.LeadUnitEn = data.GetLeadUnitEn(futureGoodEdbInfoMapping.LeadUnit)
  60. }
  61. // 普通的指标数据
  62. {
  63. dataList := make([]*models.EdbDataList, 0)
  64. dataList, err = models.GetEdbDataList(edbInfoMapping.Source, edbInfoMapping.EdbInfoId, startDate, endDate)
  65. edbDataListMap[edbInfoMapping.EdbInfoId] = dataList
  66. item.DataList = dataList
  67. edbList = append(edbList, edbInfoMapping)
  68. barConfigEdbInfoIdList = append(barConfigEdbInfoIdList, data_manage.BarChartInfoEdbItemReq{
  69. EdbInfoId: edbInfoMapping.EdbInfoId,
  70. //Name: edbInfoMapping.EdbName,
  71. Name: "现货价",
  72. NameEn: "Spot Price",
  73. Source: edbInfoMapping.Source,
  74. })
  75. }
  76. // 获取期货指标以及期货数据
  77. futureGoodEdbInfoList, err := efuture_good.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfoMapping.EdbInfoId)
  78. if err != nil {
  79. return
  80. }
  81. futureGoodMappingList := make([]*models.ChartEdbInfoMapping, 0)
  82. for k, v := range futureGoodEdbInfoList {
  83. newMappingInfo := &models.ChartEdbInfoMapping{
  84. EdbInfoId: v.FutureGoodEdbInfoId,
  85. SourceName: v.Exchange,
  86. Source: utils.CHART_SOURCE_FUTURE_GOOD,
  87. EdbCode: v.FutureGoodEdbCode,
  88. EdbName: v.FutureGoodEdbName,
  89. EdbAliasName: v.FutureGoodEdbName,
  90. EdbNameEn: v.FutureGoodEdbNameEn,
  91. EdbType: edbInfoMapping.EdbType,
  92. Frequency: edbInfoMapping.Frequency,
  93. FrequencyEn: edbInfoMapping.FrequencyEn,
  94. Unit: edbInfoMapping.Unit,
  95. UnitEn: edbInfoMapping.UnitEn,
  96. StartDate: v.StartDate,
  97. EndDate: v.EndDate,
  98. ModifyTime: v.ModifyTime.Format(utils.FormatDateTime),
  99. ChartEdbMappingId: v.FutureGoodEdbInfoId,
  100. ChartInfoId: edbInfoMapping.ChartInfoId,
  101. MaxData: v.MaxValue,
  102. MinData: v.MinValue,
  103. IsOrder: edbInfoMapping.IsOrder,
  104. IsAxis: edbInfoMapping.IsAxis,
  105. EdbInfoType: edbInfoMapping.EdbInfoType,
  106. EdbInfoCategoryType: edbInfoMapping.EdbInfoCategoryType,
  107. LeadValue: edbInfoMapping.LeadValue,
  108. LeadUnit: edbInfoMapping.LeadUnit,
  109. LeadUnitEn: edbInfoMapping.LeadUnitEn,
  110. ChartStyle: edbInfoMapping.ChartStyle,
  111. ChartColor: edbInfoMapping.ChartColor,
  112. PredictChartColor: edbInfoMapping.PredictChartColor,
  113. ChartWidth: edbInfoMapping.ChartWidth,
  114. ChartType: edbInfoMapping.ChartType,
  115. LatestDate: v.LatestDate.Format(utils.FormatDateTime),
  116. LatestValue: v.LatestValue,
  117. UniqueCode: futureGoodEdbInfoMapping.UniqueCode + strconv.Itoa(k),
  118. MinValue: v.MinValue,
  119. MaxValue: v.MaxValue,
  120. DataList: nil,
  121. IsNullData: false,
  122. }
  123. futureGoodMappingList = append(futureGoodMappingList, newMappingInfo)
  124. barConfigEdbInfoIdList = append(barConfigEdbInfoIdList, data_manage.BarChartInfoEdbItemReq{
  125. EdbInfoId: newMappingInfo.EdbInfoId,
  126. Name: fmt.Sprint("M+", v.Month),
  127. NameEn: fmt.Sprint("M+", v.Month),
  128. Source: newMappingInfo.Source,
  129. })
  130. }
  131. // 获取数据
  132. for _, v := range futureGoodMappingList {
  133. dataList := make([]*models.EdbDataList, 0)
  134. tmpDataList, tmpErr := efuture_good.GetFutureGoodEdbDataListByDate(v.EdbInfoId, startDate, endDate)
  135. if tmpErr != nil {
  136. return
  137. }
  138. for _, tmpData := range tmpDataList {
  139. dataList = append(dataList, &models.EdbDataList{
  140. EdbDataId: tmpData.FutureGoodEdbDataId,
  141. EdbInfoId: tmpData.FutureGoodEdbInfoId,
  142. DataTime: tmpData.DataTime.Format(utils.FormatDate),
  143. DataTimestamp: tmpData.DataTimestamp,
  144. Value: tmpData.Close,
  145. })
  146. }
  147. edbDataListMap[v.EdbInfoId] = dataList
  148. v.DataList = dataList
  149. }
  150. edbList = append(edbList, futureGoodMappingList...)
  151. xEdbIdValue, yDataList, err = BarChartData(edbList[0], futureGoodMappingList, edbDataListMap, barChartInfoDateList, barChartInfoSort)
  152. xDataList = []models.XData{
  153. {
  154. Name: "现货价",
  155. NameEn: "Spot Price",
  156. },
  157. }
  158. for i := 1; i <= 11; i++ {
  159. xDataList = append(xDataList, models.XData{
  160. Name: fmt.Sprint("M+", i),
  161. NameEn: fmt.Sprint("M+", i),
  162. })
  163. }
  164. return
  165. }
  166. // BarChartData 柱方图的数据处理
  167. func BarChartData(edbInfoMapping *models.ChartEdbInfoMapping, futureGoodMappingList []*models.ChartEdbInfoMapping, edbDataListMap map[int][]*models.EdbDataList, barChartInfoDateList []data_manage.BarChartInfoDateReq, barChartInfoSort data_manage.BarChartInfoSortReq) (edbIdList []int, yDataList []models.YData, err error) {
  168. // 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
  169. edbDataMap := make(map[int]map[string]float64)
  170. for edbInfoId, edbDataList := range edbDataListMap {
  171. edbDateData := make(map[string]float64)
  172. for _, edbData := range edbDataList {
  173. edbDateData[edbData.DataTime] = edbData.Value
  174. }
  175. edbDataMap[edbInfoId] = edbDateData
  176. }
  177. // edbIdList 指标展示顺序;x轴的指标顺序
  178. edbIdList = make([]int, 0)
  179. edbIdList = append(edbIdList, edbInfoMapping.EdbInfoId)
  180. if barChartInfoSort.Sort == 0 {
  181. for _, v := range futureGoodMappingList {
  182. edbIdList = append(edbIdList, v.EdbInfoId)
  183. }
  184. }
  185. //固定取螺纹期货主力合约的时间序列,最新值为该合约最新日期、N天前为该合约最新日期N天前
  186. rbzlInfo, err := efuture_good.GetFutureGoodEdbInfoByCode("RBZL.SHF")
  187. if err != nil {
  188. return
  189. }
  190. latestDate := rbzlInfo.EndDate // 最新日期是这个
  191. if rbzlInfo.EndDate == `0000-00-00` {
  192. err = errors.New("日期异常")
  193. return
  194. }
  195. latestDateTime, _ := time.ParseInLocation(utils.FormatDate, latestDate, time.Local)
  196. yDataList = make([]models.YData, 0) //y轴的数据列表
  197. for _, barChartInfoDate := range barChartInfoDateList {
  198. var maxDate time.Time
  199. var findDateTime time.Time
  200. switch barChartInfoDate.Type {
  201. case 1: //最新值
  202. findDateTime = latestDateTime
  203. case 2: //近期几天
  204. findDateTime = latestDateTime.AddDate(0, 0, -barChartInfoDate.Value)
  205. case 3: // 固定日期
  206. //寻找固定日期的数据
  207. tmpFindDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
  208. if tmpErr != nil {
  209. err = tmpErr
  210. return
  211. }
  212. findDateTime = tmpFindDateTime
  213. default:
  214. err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
  215. return
  216. }
  217. if findDateTime.IsZero() {
  218. err = errors.New("错误的日期")
  219. return
  220. }
  221. findDataList := make([]float64, 0) // 当前日期的数据值
  222. noDataIdList := make([]int, 0) // 没有数据的指标id
  223. noDataIdMap := make(map[int]int, 0) // 没有数据的指标map
  224. xEdbInfoIdList := make([]int, 0) // 当前数据的指标id列表
  225. // 现货指标
  226. realDateTime, findDataValue, isFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[edbInfoMapping.EdbInfoId], edbDataMap[edbInfoMapping.EdbInfoId])
  227. if tmpErr != nil {
  228. err = tmpErr
  229. return
  230. }
  231. findDataList = append(findDataList, findDataValue)
  232. if isFind {
  233. maxDate = realDateTime
  234. } else {
  235. noDataIdList = append(noDataIdList, edbInfoMapping.EdbInfoId)
  236. noDataIdMap[edbInfoMapping.EdbInfoId] = edbInfoMapping.EdbInfoId
  237. }
  238. currMonth := findDateTime.Month() // 当前月份
  239. xEdbInfoIdList = append(xEdbInfoIdList, edbInfoMapping.EdbInfoId)
  240. // 当前月的后面月份合约的数据
  241. for i := currMonth; i < 12; i++ {
  242. futureGoodMapping := futureGoodMappingList[i] // 当前的期货指标
  243. tmpRealDateTime, tmpFindDataValue, tmpIsFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[futureGoodMapping.EdbInfoId], edbDataMap[futureGoodMapping.EdbInfoId])
  244. if tmpErr != nil {
  245. err = tmpErr
  246. return
  247. }
  248. findDataList = append(findDataList, tmpFindDataValue)
  249. if tmpIsFind {
  250. if maxDate.IsZero() || maxDate.Before(tmpRealDateTime) {
  251. maxDate = tmpRealDateTime
  252. }
  253. } else {
  254. noDataIdList = append(noDataIdList, futureGoodMapping.EdbInfoId)
  255. noDataIdMap[futureGoodMapping.EdbInfoId] = futureGoodMapping.EdbInfoId
  256. }
  257. // 当前期货合约的指标
  258. xEdbInfoIdList = append(xEdbInfoIdList, futureGoodMapping.EdbInfoId)
  259. }
  260. // 当前月的前面月份合约的数据
  261. for i := 1; i < int(currMonth); i++ {
  262. futureGoodMapping := futureGoodMappingList[i-1] // 当前的期货指标
  263. tmpRealDateTime, tmpFindDataValue, tmpIsFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[futureGoodMapping.EdbInfoId], edbDataMap[futureGoodMapping.EdbInfoId])
  264. if tmpErr != nil {
  265. err = tmpErr
  266. return
  267. }
  268. findDataList = append(findDataList, tmpFindDataValue)
  269. if tmpIsFind {
  270. if maxDate.IsZero() || maxDate.Before(tmpRealDateTime) {
  271. maxDate = tmpRealDateTime
  272. }
  273. } else {
  274. noDataIdList = append(noDataIdList, futureGoodMapping.EdbInfoId)
  275. noDataIdMap[futureGoodMapping.EdbInfoId] = futureGoodMapping.EdbInfoId
  276. }
  277. // 当前期货合约的指标
  278. xEdbInfoIdList = append(xEdbInfoIdList, futureGoodMapping.EdbInfoId)
  279. }
  280. yName := barChartInfoDate.Name
  281. yNameEn := barChartInfoDate.Name
  282. if yName == `` {
  283. if barChartInfoDate.Type == 2 {
  284. yName = strconv.Itoa(barChartInfoDate.Value) + "天前"
  285. if barChartInfoDate.Value == 1 {
  286. yNameEn = strconv.Itoa(barChartInfoDate.Value) + "day ago"
  287. } else {
  288. yNameEn = strconv.Itoa(barChartInfoDate.Value) + " days ago"
  289. }
  290. } else {
  291. yName = maxDate.Format(utils.FormatDate)
  292. yNameEn = maxDate.Format(utils.FormatDate)
  293. }
  294. }
  295. yDate := "0000-00-00"
  296. if !maxDate.IsZero() {
  297. yDate = maxDate.Format(utils.FormatDate)
  298. }
  299. // 数据处理,将没有数据的下标,赋值平均值
  300. {
  301. hasDataIndexList := make([]int, 0)
  302. for dataK, edbInfoId := range xEdbInfoIdList {
  303. if _, ok := noDataIdMap[edbInfoId]; !ok { // 如果是没有数据的指标id
  304. hasDataIndexList = append(hasDataIndexList, dataK)
  305. }
  306. }
  307. lenHasDataIndex := len(hasDataIndexList)
  308. if lenHasDataIndex > 0 {
  309. for lenHasDataI := 1; lenHasDataI < lenHasDataIndex; lenHasDataI++ {
  310. perK := hasDataIndexList[lenHasDataI-1] //上一个有数据的指标下标
  311. currK := hasDataIndexList[lenHasDataI] //当前有数据的指标下标
  312. preVal := findDataList[perK] //上一个有数据的坐标的值
  313. currVal := findDataList[currK] //当前有数据的指标的值
  314. // 环差值
  315. hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(currK - perK)))
  316. var tmpI int64
  317. // 将两个中间的数据做平均值补全
  318. for hcI := perK + 1; hcI < currK; hcI++ {
  319. tmpI++
  320. findDataList[hcI], _ = decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(tmpI))).RoundCeil(4).Float64()
  321. }
  322. }
  323. }
  324. }
  325. yDataList = append(yDataList, models.YData{
  326. Date: yDate,
  327. Value: findDataList,
  328. NoDataEdbList: noDataIdList,
  329. XEdbInfoIdList: xEdbInfoIdList,
  330. Color: barChartInfoDate.Color,
  331. Name: yName,
  332. NameEn: yNameEn,
  333. })
  334. }
  335. return
  336. }
  337. // GetNeedDateData 获取合约内需要的日期数据
  338. func GetNeedDateData(needDateTime time.Time, dataList []*models.EdbDataList, edbDataMap map[string]float64) (findDateTime time.Time, findDataValue float64, isFind bool, err error) {
  339. //dataList := edbDataListMap[edbInfoId] //指标的所有数据值
  340. if len(dataList) <= 0 {
  341. // 没有数据的指标id
  342. return
  343. }
  344. //最早的日期
  345. minDateTime, err := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  346. if err != nil {
  347. return
  348. }
  349. for tmpDateTime := needDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  350. tmpDate := tmpDateTime.Format(utils.FormatDate)
  351. if tmpValue, ok := edbDataMap[tmpDate]; ok { //如果能找到数据,那么就返回
  352. // 数据为0,也直接返回,做无值处理
  353. if tmpValue == 0 {
  354. return
  355. }
  356. findDateTime, _ = time.ParseInLocation(utils.FormatDate, tmpDate, time.Local)
  357. findDataValue = tmpValue
  358. isFind = true
  359. return
  360. }
  361. }
  362. return
  363. }
  364. // FutureGoodChartInfoRefresh
  365. // @author Roc
  366. // @datetime 2023-2-2 18:44:46
  367. // @description 商品价格曲线图表刷新
  368. func FutureGoodChartInfoRefresh(chartInfoId int) (err error) {
  369. var errMsg string
  370. defer func() {
  371. if err != nil {
  372. go alarm_msg.SendAlarmMsg("ChartInfoRefresh:"+errMsg, 3)
  373. fmt.Println("ChartInfoRefresh Err:" + errMsg)
  374. }
  375. }()
  376. edbInfoMapping, err := models.GetEtaEdbChartEdbMapping(chartInfoId)
  377. if err != nil {
  378. errMsg = "获取需要刷新的ETA指标失败:Err:" + err.Error()
  379. return
  380. }
  381. // 获取期货指标
  382. futureGoodEdbInfoMapping, err := models.GetFutureGoodEdbChartEdbMapping(chartInfoId)
  383. if err != nil {
  384. errMsg = "获取需要刷新的商品期货指标失败:Err:" + err.Error()
  385. return
  386. }
  387. // 获取期货指标以及期货数据
  388. futureGoodEdbInfoList, err := efuture_good.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfoMapping.EdbInfoId)
  389. if err != nil {
  390. return
  391. }
  392. // 批量刷新ETA指标
  393. err, _ = data.EdbInfoRefreshAllFromBase([]int{edbInfoMapping.EdbInfoId}, false)
  394. if err != nil {
  395. return
  396. }
  397. // 批量刷新期货指标
  398. err = FutureGoodEdbInfoRefreshAllFromBase(futureGoodEdbInfoList, false)
  399. if err != nil {
  400. return
  401. }
  402. return
  403. }