chart_info.go 16 KB

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