chart_info.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  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. for i := currMonth; i < 12; i++ {
  241. futureGoodMapping := futureGoodMappingList[i] // 当前的期货指标
  242. tmpRealDateTime, tmpFindDataValue, tmpIsFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[futureGoodMapping.EdbInfoId], edbDataMap[futureGoodMapping.EdbInfoId])
  243. if tmpErr != nil {
  244. err = tmpErr
  245. return
  246. }
  247. findDataList = append(findDataList, tmpFindDataValue)
  248. if tmpIsFind {
  249. if maxDate.IsZero() || maxDate.Before(tmpRealDateTime) {
  250. maxDate = realDateTime
  251. }
  252. } else {
  253. noDataIdList = append(noDataIdList, futureGoodMapping.EdbInfoId)
  254. noDataIdMap[futureGoodMapping.EdbInfoId] = futureGoodMapping.EdbInfoId
  255. }
  256. // 当前期货合约的指标
  257. xEdbInfoIdList = append(xEdbInfoIdList, futureGoodMapping.EdbInfoId)
  258. }
  259. for i := 1; i < int(currMonth); i++ {
  260. futureGoodMapping := futureGoodMappingList[i-1] // 当前的期货指标
  261. tmpRealDateTime, tmpFindDataValue, tmpIsFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[futureGoodMapping.EdbInfoId], edbDataMap[futureGoodMapping.EdbInfoId])
  262. if tmpErr != nil {
  263. err = tmpErr
  264. return
  265. }
  266. findDataList = append(findDataList, tmpFindDataValue)
  267. if tmpIsFind {
  268. if maxDate.IsZero() || maxDate.Before(tmpRealDateTime) {
  269. maxDate = realDateTime
  270. }
  271. } else {
  272. noDataIdList = append(noDataIdList, futureGoodMapping.EdbInfoId)
  273. noDataIdMap[futureGoodMapping.EdbInfoId] = futureGoodMapping.EdbInfoId
  274. }
  275. // 当前期货合约的指标
  276. xEdbInfoIdList = append(xEdbInfoIdList, futureGoodMapping.EdbInfoId)
  277. }
  278. yName := barChartInfoDate.Name
  279. yNameEn := barChartInfoDate.Name
  280. if yName == `` {
  281. if barChartInfoDate.Type == 2 {
  282. yName = strconv.Itoa(barChartInfoDate.Value) + "天前"
  283. if barChartInfoDate.Value == 1 {
  284. yNameEn = strconv.Itoa(barChartInfoDate.Value) + "day ago"
  285. } else {
  286. yNameEn = strconv.Itoa(barChartInfoDate.Value) + " days ago"
  287. }
  288. } else {
  289. yName = maxDate.Format(utils.FormatDate)
  290. yNameEn = maxDate.Format(utils.FormatDate)
  291. }
  292. }
  293. yDate := "0000-00-00"
  294. if !maxDate.IsZero() {
  295. yDate = maxDate.Format(utils.FormatDate)
  296. }
  297. // 数据处理,将没有数据的下标,赋值平均值
  298. {
  299. hasDataIndexList := make([]int, 0)
  300. for dataK, edbInfoId := range edbIdList {
  301. if _, ok := noDataIdMap[edbInfoId]; !ok { // 如果是没有数据的指标id
  302. hasDataIndexList = append(hasDataIndexList, dataK)
  303. }
  304. }
  305. lenHasDataIndex := len(hasDataIndexList)
  306. if lenHasDataIndex > 0 {
  307. for lenHasDataI := 1; lenHasDataI < lenHasDataIndex; lenHasDataI++ {
  308. perK := hasDataIndexList[lenHasDataI-1] //上一个有数据的指标下标
  309. currK := hasDataIndexList[lenHasDataI] //当前有数据的指标下标
  310. preVal := findDataList[perK] //上一个有数据的坐标的值
  311. currVal := findDataList[currK] //当前有数据的指标的值
  312. // 环差值
  313. hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(currK - perK)))
  314. var tmpI int64
  315. // 将两个中间的数据做平均值补全
  316. for hcI := perK + 1; hcI < currK; hcI++ {
  317. tmpI++
  318. findDataList[hcI], _ = decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(tmpI))).RoundCeil(4).Float64()
  319. }
  320. }
  321. }
  322. }
  323. yDataList = append(yDataList, models.YData{
  324. Date: yDate,
  325. Value: findDataList,
  326. NoDataEdbList: noDataIdList,
  327. Color: barChartInfoDate.Color,
  328. Name: yName,
  329. NameEn: yNameEn,
  330. })
  331. }
  332. return
  333. }
  334. // GetNeedDateData 获取合约内需要的日期数据
  335. func GetNeedDateData(needDateTime time.Time, dataList []*models.EdbDataList, edbDataMap map[string]float64) (findDateTime time.Time, findDataValue float64, isFind bool, err error) {
  336. //dataList := edbDataListMap[edbInfoId] //指标的所有数据值
  337. if len(dataList) <= 0 {
  338. // 没有数据的指标id
  339. return
  340. }
  341. //最早的日期
  342. minDateTime, err := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  343. if err != nil {
  344. return
  345. }
  346. for tmpDateTime := needDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  347. tmpDate := tmpDateTime.Format(utils.FormatDate)
  348. if tmpValue, ok := edbDataMap[tmpDate]; ok { //如果能找到数据,那么就返回
  349. findDateTime, _ = time.ParseInLocation(utils.FormatDate, tmpDate, time.Local)
  350. findDataValue = tmpValue
  351. isFind = true
  352. return
  353. }
  354. }
  355. return
  356. }
  357. // FutureGoodChartInfoRefresh
  358. // @author Roc
  359. // @datetime 2023-2-2 18:44:46
  360. // @description 商品价格曲线图表刷新
  361. func FutureGoodChartInfoRefresh(chartInfoId int) (err error) {
  362. var errMsg string
  363. defer func() {
  364. if err != nil {
  365. go alarm_msg.SendAlarmMsg("ChartInfoRefresh:"+errMsg, 3)
  366. fmt.Println("ChartInfoRefresh Err:" + errMsg)
  367. }
  368. }()
  369. edbInfoMapping, err := models.GetEtaEdbChartEdbMapping(chartInfoId)
  370. if err != nil {
  371. errMsg = "获取需要刷新的ETA指标失败:Err:" + err.Error()
  372. return
  373. }
  374. // 获取期货指标
  375. futureGoodEdbInfoMapping, err := models.GetFutureGoodEdbChartEdbMapping(chartInfoId)
  376. if err != nil {
  377. errMsg = "获取需要刷新的商品期货指标失败:Err:" + err.Error()
  378. return
  379. }
  380. // 获取期货指标以及期货数据
  381. futureGoodEdbInfoList, err := efuture_good.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfoMapping.EdbInfoId)
  382. if err != nil {
  383. return
  384. }
  385. // 批量刷新ETA指标
  386. err, _ = data.EdbInfoRefreshAllFromBase([]int{edbInfoMapping.EdbInfoId}, false)
  387. if err != nil {
  388. return
  389. }
  390. // 批量刷新期货指标
  391. err = FutureGoodEdbInfoRefreshAllFromBase(futureGoodEdbInfoList, false)
  392. if err != nil {
  393. return
  394. }
  395. return
  396. }