chart_info.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. package future_good
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/shopspring/decimal"
  6. "hongze/hongze_ETA_mobile_api/models/data_manage"
  7. future_good2 "hongze/hongze_ETA_mobile_api/models/data_manage/future_good"
  8. "hongze/hongze_ETA_mobile_api/services/data"
  9. "hongze/hongze_ETA_mobile_api/utils"
  10. "strconv"
  11. "time"
  12. )
  13. // GetChartEdbData 获取图表的指标数据
  14. func GetChartEdbData(chartInfoId int, startDate, endDate string, edbInfoMapping, futureGoodEdbInfoMapping *data_manage.ChartEdbInfoMapping, barChartInfoDateList []data_manage.BarChartInfoDateReq, barChartInfoSort data_manage.BarChartInfoSortReq) (barConfigEdbInfoIdList []data_manage.BarChartInfoEdbItemReq, edbList []*data_manage.ChartEdbInfoMapping, xEdbIdValue []int, xDataList []data_manage.XData, yDataList []data_manage.YData, err error) {
  15. edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
  16. if futureGoodEdbInfoMapping == nil {
  17. err = errors.New("商品指标未选取")
  18. return
  19. }
  20. if edbInfoMapping == nil {
  21. err = errors.New("ETA指标未选取")
  22. return
  23. }
  24. // 指标对应的所有数据
  25. edbDataListMap := make(map[int][]*data_manage.EdbDataList)
  26. item := new(data_manage.ChartEdbInfoMapping)
  27. edbInfoMapping.FrequencyEn = data.GetFrequencyEn(edbInfoMapping.Frequency)
  28. if edbInfoMapping.Unit == `无` {
  29. edbInfoMapping.Unit = ``
  30. }
  31. if futureGoodEdbInfoMapping.Unit == `无` {
  32. futureGoodEdbInfoMapping.Unit = ``
  33. }
  34. if chartInfoId <= 0 {
  35. edbInfoMapping.IsAxis = 1
  36. edbInfoMapping.LeadValue = 0
  37. edbInfoMapping.LeadUnit = ""
  38. edbInfoMapping.ChartEdbMappingId = 0
  39. edbInfoMapping.ChartInfoId = 0
  40. edbInfoMapping.IsOrder = false
  41. edbInfoMapping.EdbInfoType = 1
  42. edbInfoMapping.ChartStyle = ""
  43. edbInfoMapping.ChartColor = ""
  44. edbInfoMapping.ChartWidth = 0
  45. futureGoodEdbInfoMapping.IsAxis = 1
  46. futureGoodEdbInfoMapping.LeadValue = 0
  47. futureGoodEdbInfoMapping.LeadUnit = ""
  48. futureGoodEdbInfoMapping.ChartEdbMappingId = 0
  49. futureGoodEdbInfoMapping.ChartInfoId = 0
  50. futureGoodEdbInfoMapping.IsOrder = false
  51. futureGoodEdbInfoMapping.EdbInfoType = 1
  52. futureGoodEdbInfoMapping.ChartStyle = ""
  53. futureGoodEdbInfoMapping.ChartColor = ""
  54. futureGoodEdbInfoMapping.ChartWidth = 0
  55. } else {
  56. edbInfoMapping.LeadUnitEn = data.GetLeadUnitEn(edbInfoMapping.LeadUnit)
  57. futureGoodEdbInfoMapping.LeadUnitEn = data.GetLeadUnitEn(futureGoodEdbInfoMapping.LeadUnit)
  58. }
  59. // 普通的指标数据
  60. {
  61. dataList := make([]*data_manage.EdbDataList, 0)
  62. dataList, err = data_manage.GetEdbDataList(edbInfoMapping.Source, edbInfoMapping.EdbInfoId, startDate, endDate)
  63. edbDataListMap[edbInfoMapping.EdbInfoId] = dataList
  64. item.DataList = dataList
  65. edbList = append(edbList, edbInfoMapping)
  66. barConfigEdbInfoIdList = append(barConfigEdbInfoIdList, data_manage.BarChartInfoEdbItemReq{
  67. EdbInfoId: edbInfoMapping.EdbInfoId,
  68. //Name: edbInfoMapping.EdbName,
  69. Name: "现货价",
  70. NameEn: "Spot Price",
  71. Source: edbInfoMapping.Source,
  72. })
  73. }
  74. // 获取期货指标以及期货数据
  75. futureGoodEdbInfoList, err := future_good2.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfoMapping.EdbInfoId)
  76. if err != nil {
  77. return
  78. }
  79. futureGoodMappingList := make([]*data_manage.ChartEdbInfoMapping, 0)
  80. for k, v := range futureGoodEdbInfoList {
  81. newMappingInfo := &data_manage.ChartEdbInfoMapping{
  82. EdbInfoId: v.FutureGoodEdbInfoId,
  83. SourceName: v.Exchange,
  84. Source: 0,
  85. EdbCode: v.FutureGoodEdbCode,
  86. EdbName: v.FutureGoodEdbName,
  87. EdbAliasName: v.FutureGoodEdbName,
  88. EdbNameEn: v.FutureGoodEdbNameEn,
  89. EdbType: edbInfoMapping.EdbType,
  90. Frequency: edbInfoMapping.Frequency,
  91. FrequencyEn: edbInfoMapping.FrequencyEn,
  92. Unit: edbInfoMapping.Unit,
  93. UnitEn: edbInfoMapping.UnitEn,
  94. StartDate: v.StartDate,
  95. EndDate: v.EndDate,
  96. ModifyTime: v.ModifyTime.Format(utils.FormatDateTime),
  97. ChartEdbMappingId: v.FutureGoodEdbInfoId,
  98. ChartInfoId: edbInfoMapping.ChartInfoId,
  99. MaxData: v.MaxValue,
  100. MinData: v.MinValue,
  101. IsOrder: edbInfoMapping.IsOrder,
  102. IsAxis: edbInfoMapping.IsAxis,
  103. EdbInfoType: edbInfoMapping.EdbInfoType,
  104. EdbInfoCategoryType: edbInfoMapping.EdbInfoCategoryType,
  105. LeadValue: edbInfoMapping.LeadValue,
  106. LeadUnit: edbInfoMapping.LeadUnit,
  107. LeadUnitEn: edbInfoMapping.LeadUnitEn,
  108. ChartStyle: edbInfoMapping.ChartStyle,
  109. ChartColor: edbInfoMapping.ChartColor,
  110. PredictChartColor: edbInfoMapping.PredictChartColor,
  111. ChartWidth: edbInfoMapping.ChartWidth,
  112. ChartType: edbInfoMapping.ChartType,
  113. LatestDate: v.LatestDate.Format(utils.FormatDateTime),
  114. LatestValue: v.LatestValue,
  115. UniqueCode: futureGoodEdbInfoMapping.UniqueCode + strconv.Itoa(k),
  116. MinValue: v.MinValue,
  117. MaxValue: v.MaxValue,
  118. DataList: nil,
  119. IsNullData: false,
  120. }
  121. futureGoodMappingList = append(futureGoodMappingList, newMappingInfo)
  122. barConfigEdbInfoIdList = append(barConfigEdbInfoIdList, data_manage.BarChartInfoEdbItemReq{
  123. EdbInfoId: newMappingInfo.EdbInfoId,
  124. Name: fmt.Sprint("M+", v.Month),
  125. NameEn: fmt.Sprint("M+", v.Month),
  126. Source: newMappingInfo.Source,
  127. })
  128. }
  129. // 获取数据
  130. for _, v := range futureGoodMappingList {
  131. dataList := make([]*data_manage.EdbDataList, 0)
  132. tmpDataList, tmpErr := future_good2.GetFutureGoodEdbDataListByDate(v.EdbInfoId, startDate, endDate)
  133. if tmpErr != nil {
  134. return
  135. }
  136. for _, tmpData := range tmpDataList {
  137. dataList = append(dataList, &data_manage.EdbDataList{
  138. EdbDataId: tmpData.FutureGoodEdbDataId,
  139. EdbInfoId: tmpData.FutureGoodEdbInfoId,
  140. DataTime: tmpData.DataTime.Format(utils.FormatDate),
  141. DataTimestamp: tmpData.DataTimestamp,
  142. Value: tmpData.Close,
  143. })
  144. }
  145. edbDataListMap[v.EdbInfoId] = dataList
  146. v.DataList = dataList
  147. }
  148. edbList = append(edbList, futureGoodMappingList...)
  149. xEdbIdValue, yDataList, err = BarChartData(edbList[0], futureGoodMappingList, edbDataListMap, barChartInfoDateList, barChartInfoSort)
  150. xDataList = []data_manage.XData{
  151. {
  152. Name: "现货价",
  153. NameEn: "Spot Price",
  154. },
  155. }
  156. for i := 1; i <= 11; i++ {
  157. xDataList = append(xDataList, data_manage.XData{
  158. Name: fmt.Sprint("M+", i),
  159. NameEn: fmt.Sprint("M+", i),
  160. })
  161. }
  162. return
  163. }
  164. // BarChartData 柱方图的数据处理
  165. func BarChartData(edbInfoMapping *data_manage.ChartEdbInfoMapping, futureGoodMappingList []*data_manage.ChartEdbInfoMapping, edbDataListMap map[int][]*data_manage.EdbDataList, barChartInfoDateList []data_manage.BarChartInfoDateReq, barChartInfoSort data_manage.BarChartInfoSortReq) (edbIdList []int, yDataList []data_manage.YData, err error) {
  166. // 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
  167. edbDataMap := make(map[int]map[string]float64)
  168. for edbInfoId, edbDataList := range edbDataListMap {
  169. edbDateData := make(map[string]float64)
  170. for _, edbData := range edbDataList {
  171. edbDateData[edbData.DataTime] = edbData.Value
  172. }
  173. edbDataMap[edbInfoId] = edbDateData
  174. }
  175. // edbIdList 指标展示顺序;x轴的指标顺序
  176. edbIdList = make([]int, 0)
  177. edbIdList = append(edbIdList, edbInfoMapping.EdbInfoId)
  178. if barChartInfoSort.Sort == 0 {
  179. for _, v := range futureGoodMappingList {
  180. edbIdList = append(edbIdList, v.EdbInfoId)
  181. }
  182. }
  183. //固定取螺纹期货主力合约的时间序列,最新值为该合约最新日期、N天前为该合约最新日期N天前
  184. rbzlInfo, err := future_good2.GetFutureGoodEdbInfoByCode("RBZL.SHF")
  185. if err != nil {
  186. return
  187. }
  188. latestDate := rbzlInfo.EndDate // 最新日期是这个
  189. if rbzlInfo.EndDate == `0000-00-00` {
  190. err = errors.New("日期异常")
  191. return
  192. }
  193. latestDateTime, _ := time.ParseInLocation(utils.FormatDate, latestDate, time.Local)
  194. yDataList = make([]data_manage.YData, 0) //y轴的数据列表
  195. for _, barChartInfoDate := range barChartInfoDateList {
  196. var maxDate time.Time
  197. var findDateTime time.Time
  198. switch barChartInfoDate.Type {
  199. case 1: //最新值
  200. findDateTime = latestDateTime
  201. case 2: //近期几天
  202. findDateTime = latestDateTime.AddDate(0, 0, -barChartInfoDate.Value)
  203. case 3: // 固定日期
  204. //寻找固定日期的数据
  205. tmpFindDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
  206. if tmpErr != nil {
  207. err = tmpErr
  208. return
  209. }
  210. findDateTime = tmpFindDateTime
  211. default:
  212. err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
  213. return
  214. }
  215. if findDateTime.IsZero() {
  216. err = errors.New("错误的日期")
  217. return
  218. }
  219. findDataList := make([]float64, 0) // 当前日期的数据值
  220. noDataIdList := make([]int, 0) // 没有数据的指标id
  221. noDataIdMap := make(map[int]int, 0) // 没有数据的指标map
  222. xEdbInfoIdList := make([]int, 0) // 当前数据的指标id列表
  223. // 现货指标
  224. realDateTime, findDataValue, isFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[edbInfoMapping.EdbInfoId], edbDataMap[edbInfoMapping.EdbInfoId])
  225. if tmpErr != nil {
  226. err = tmpErr
  227. return
  228. }
  229. findDataList = append(findDataList, findDataValue)
  230. if isFind {
  231. maxDate = realDateTime
  232. } else {
  233. noDataIdList = append(noDataIdList, edbInfoMapping.EdbInfoId)
  234. noDataIdMap[edbInfoMapping.EdbInfoId] = edbInfoMapping.EdbInfoId
  235. }
  236. currMonth := findDateTime.Month() // 当前月份
  237. xEdbInfoIdList = append(xEdbInfoIdList, edbInfoMapping.EdbInfoId)
  238. // 当前月的后面月份合约的数据
  239. for i := currMonth; i < 12; i++ {
  240. futureGoodMapping := futureGoodMappingList[i] // 当前的期货指标
  241. tmpRealDateTime, tmpFindDataValue, tmpIsFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[futureGoodMapping.EdbInfoId], edbDataMap[futureGoodMapping.EdbInfoId])
  242. if tmpErr != nil {
  243. err = tmpErr
  244. return
  245. }
  246. findDataList = append(findDataList, tmpFindDataValue)
  247. if tmpIsFind {
  248. if maxDate.IsZero() || maxDate.Before(tmpRealDateTime) {
  249. maxDate = tmpRealDateTime
  250. }
  251. } else {
  252. noDataIdList = append(noDataIdList, futureGoodMapping.EdbInfoId)
  253. noDataIdMap[futureGoodMapping.EdbInfoId] = futureGoodMapping.EdbInfoId
  254. }
  255. // 当前期货合约的指标
  256. xEdbInfoIdList = append(xEdbInfoIdList, futureGoodMapping.EdbInfoId)
  257. }
  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 = tmpRealDateTime
  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 xEdbInfoIdList {
  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, data_manage.YData{
  324. Date: yDate,
  325. Value: findDataList,
  326. NoDataEdbList: noDataIdList,
  327. XEdbInfoIdList: xEdbInfoIdList,
  328. Color: barChartInfoDate.Color,
  329. Name: yName,
  330. NameEn: yNameEn,
  331. })
  332. }
  333. return
  334. }
  335. // GetNeedDateData 获取合约内需要的日期数据
  336. func GetNeedDateData(needDateTime time.Time, dataList []*data_manage.EdbDataList, edbDataMap map[string]float64) (findDateTime time.Time, findDataValue float64, isFind bool, err error) {
  337. //dataList := edbDataListMap[edbInfoId] //指标的所有数据值
  338. if len(dataList) <= 0 {
  339. // 没有数据的指标id
  340. return
  341. }
  342. //最早的日期
  343. minDateTime, err := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  344. if err != nil {
  345. return
  346. }
  347. for tmpDateTime := needDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  348. tmpDate := tmpDateTime.Format(utils.FormatDate)
  349. if tmpValue, ok := edbDataMap[tmpDate]; ok { //如果能找到数据,那么就返回
  350. // 数据为0,也直接返回,做无值处理
  351. if tmpValue == 0 {
  352. return
  353. }
  354. findDateTime, _ = time.ParseInLocation(utils.FormatDate, tmpDate, time.Local)
  355. findDataValue = tmpValue
  356. isFind = true
  357. return
  358. }
  359. }
  360. return
  361. }