chart_info.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  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. "sort"
  16. "strconv"
  17. "time"
  18. )
  19. // GetChartEdbData 获取图表的指标数据
  20. func GetChartEdbData(chartInfoId int, startDate, endDate string, edbInfoMapping, futureGoodEdbInfoMapping *chartEdbMappingModel.ChartEdbInfoMappingList, barChartInfoDateList []request.BarChartInfoDateReq) (barConfigEdbInfoIdList []request.BarChartInfoEdbItemReq, edbList []*chartEdbMappingModel.ChartEdbInfoMappingList, xEdbIdValue []int, xDataList []chart_info.XData, yDataList []chart_info.YData, sourceArr []string, err error) {
  21. edbList = make([]*chartEdbMappingModel.ChartEdbInfoMappingList, 0)
  22. sourceArr = make([]string, 0)
  23. if futureGoodEdbInfoMapping == nil {
  24. err = errors.New("商品指标未选取")
  25. return
  26. }
  27. if edbInfoMapping == nil {
  28. err = errors.New("ETA指标未选取")
  29. return
  30. }
  31. // 指标对应的所有数据
  32. edbDataListMap := make(map[int][]*edbDataModel.EdbDataList)
  33. item := new(chartEdbMappingModel.ChartEdbInfoMappingList)
  34. edbInfoMapping.FrequencyEn = chart.GetFrequencyEn(edbInfoMapping.Frequency)
  35. if edbInfoMapping.Unit == `无` {
  36. edbInfoMapping.Unit = ``
  37. }
  38. if futureGoodEdbInfoMapping.Unit == `无` {
  39. futureGoodEdbInfoMapping.Unit = ``
  40. }
  41. if chartInfoId <= 0 {
  42. edbInfoMapping.IsAxis = 1
  43. edbInfoMapping.LeadValue = 0
  44. edbInfoMapping.LeadUnit = ""
  45. edbInfoMapping.ChartEdbMappingId = 0
  46. edbInfoMapping.ChartInfoId = 0
  47. edbInfoMapping.IsOrder = false
  48. edbInfoMapping.EdbInfoType = 1
  49. edbInfoMapping.ChartStyle = ""
  50. edbInfoMapping.ChartColor = ""
  51. edbInfoMapping.ChartWidth = 0
  52. futureGoodEdbInfoMapping.IsAxis = 1
  53. futureGoodEdbInfoMapping.LeadValue = 0
  54. futureGoodEdbInfoMapping.LeadUnit = ""
  55. futureGoodEdbInfoMapping.ChartEdbMappingId = 0
  56. futureGoodEdbInfoMapping.ChartInfoId = 0
  57. futureGoodEdbInfoMapping.IsOrder = false
  58. futureGoodEdbInfoMapping.EdbInfoType = 1
  59. futureGoodEdbInfoMapping.ChartStyle = ""
  60. futureGoodEdbInfoMapping.ChartColor = ""
  61. futureGoodEdbInfoMapping.ChartWidth = 0
  62. } else {
  63. edbInfoMapping.LeadUnitEn = chart.GetLeadUnitEn(edbInfoMapping.LeadUnit)
  64. futureGoodEdbInfoMapping.LeadUnitEn = chart.GetLeadUnitEn(futureGoodEdbInfoMapping.LeadUnit)
  65. }
  66. // 普通的指标数据
  67. {
  68. dataList := make([]*edbDataModel.EdbDataList, 0)
  69. dataList, err = edbDataModel.GetEdbDataList(edbInfoMapping.Source, edbInfoMapping.SubSource, edbInfoMapping.EdbInfoId, startDate, endDate)
  70. edbDataListMap[edbInfoMapping.EdbInfoId] = dataList
  71. item.DataList = dataList
  72. edbList = append(edbList, edbInfoMapping)
  73. barConfigEdbInfoIdList = append(barConfigEdbInfoIdList, request.BarChartInfoEdbItemReq{
  74. EdbInfoId: edbInfoMapping.EdbInfoId,
  75. //Name: edbInfoMapping.EdbName,
  76. Name: "现货价",
  77. NameEn: "Spot Price",
  78. Source: edbInfoMapping.Source,
  79. })
  80. if !utils.InArray(edbInfoMapping.Source, utils.SystemSourceList) { //来源于系统的指标,都展示为弘则研究
  81. if !utils.InArray(edbInfoMapping.SourceName, sourceArr) {
  82. sourceArr = append(sourceArr, edbInfoMapping.SourceName)
  83. }
  84. }
  85. }
  86. // 获取主力合约和最新日期
  87. var zlFutureGoodEdbInfo *future_good_edb_info.FutureGoodEdbInfo
  88. var latestDate string // 最新日期是这个
  89. var regionType string // 交易所来源:“国内”,“海外”
  90. var futureGoodEdbType int
  91. {
  92. // 寻找主力合约
  93. zlFutureGoodEdbInfo, err = future_good_edb_info.GetFutureGoodEdbInfo(futureGoodEdbInfoMapping.EdbInfoId)
  94. if err != nil {
  95. return
  96. }
  97. regionType = zlFutureGoodEdbInfo.RegionType
  98. futureGoodEdbType = int(zlFutureGoodEdbInfo.FutureGoodEdbType)
  99. // 如果当前合约配置的 "画图时,日期来源的指标id" 并不是自己的话,那么就去查找对应配置的合约
  100. if uint64(zlFutureGoodEdbInfo.DateSourceID) != zlFutureGoodEdbInfo.FutureGoodEdbInfoID {
  101. sourceDateFutureGoodEdbInfo, tmpErr := future_good_edb_info.GetFutureGoodEdbInfo(int(zlFutureGoodEdbInfo.DateSourceID))
  102. if tmpErr != nil {
  103. err = tmpErr
  104. return
  105. }
  106. latestDate = sourceDateFutureGoodEdbInfo.EndDate.Format(utils.FormatDate) // 最新日期是这个
  107. } else {
  108. latestDate = zlFutureGoodEdbInfo.EndDate.Format(utils.FormatDate) // 最新日期是这个
  109. }
  110. if latestDate == `0000-00-00` {
  111. err = errors.New("日期异常")
  112. return
  113. }
  114. }
  115. // 获取期货指标以及期货数据
  116. tmpFutureGoodEdbInfoList, err := future_good_edb_info.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfoMapping.EdbInfoId)
  117. if err != nil {
  118. return
  119. }
  120. latestDateTime, _ := time.ParseInLocation(utils.FormatDate, latestDate, time.Local)
  121. _, futureGoodEdbInfoList, err := getFutureGoodEdbInfoList(latestDateTime, tmpFutureGoodEdbInfoList, barChartInfoDateList)
  122. if err != nil {
  123. return
  124. }
  125. futureGoodMappingList := make([]*chartEdbMappingModel.ChartEdbInfoMappingList, 0)
  126. for k, v := range futureGoodEdbInfoList {
  127. newMappingInfo := &chartEdbMappingModel.ChartEdbInfoMappingList{
  128. ChartEdbInfoMapping: chartEdbMappingModel.ChartEdbInfoMapping{
  129. EdbInfoId: int(v.FutureGoodEdbInfoID),
  130. SourceName: v.Exchange,
  131. Source: utils.CHART_SOURCE_FUTURE_GOOD,
  132. EdbCode: v.FutureGoodEdbCode,
  133. EdbName: v.FutureGoodEdbName,
  134. EdbAliasName: v.FutureGoodEdbName,
  135. EdbNameEn: v.FutureGoodEdbNameEn,
  136. EdbType: edbInfoMapping.EdbType,
  137. Frequency: edbInfoMapping.Frequency,
  138. FrequencyEn: edbInfoMapping.FrequencyEn,
  139. Unit: edbInfoMapping.Unit,
  140. UnitEn: edbInfoMapping.UnitEn,
  141. StartDate: v.StartDate.Format(utils.FormatDateTime),
  142. EndDate: v.EndDate.Format(utils.FormatDateTime),
  143. ModifyTime: v.ModifyTime.Format(utils.FormatDateTime),
  144. ChartEdbMappingId: int(v.FutureGoodEdbInfoID),
  145. ChartInfoId: edbInfoMapping.ChartInfoId,
  146. MaxData: v.MaxValue,
  147. MinData: v.MinValue,
  148. IsOrder: edbInfoMapping.IsOrder,
  149. IsAxis: edbInfoMapping.IsAxis,
  150. EdbInfoType: edbInfoMapping.EdbInfoType,
  151. EdbInfoCategoryType: edbInfoMapping.EdbInfoCategoryType,
  152. LeadValue: edbInfoMapping.LeadValue,
  153. LeadUnit: edbInfoMapping.LeadUnit,
  154. LeadUnitEn: edbInfoMapping.LeadUnitEn,
  155. ChartStyle: edbInfoMapping.ChartStyle,
  156. ChartColor: edbInfoMapping.ChartColor,
  157. PredictChartColor: edbInfoMapping.PredictChartColor,
  158. ChartWidth: edbInfoMapping.ChartWidth,
  159. ChartType: edbInfoMapping.ChartType,
  160. LatestDate: v.LatestDate,
  161. LatestValue: v.LatestValue,
  162. UniqueCode: futureGoodEdbInfoMapping.UniqueCode + "1" + strconv.Itoa(k),
  163. MinValue: v.MinValue,
  164. MaxValue: v.MaxValue,
  165. },
  166. DataList: nil,
  167. IsNullData: false,
  168. }
  169. futureGoodMappingList = append(futureGoodMappingList, newMappingInfo)
  170. barConfigEdbInfoIdList = append(barConfigEdbInfoIdList, request.BarChartInfoEdbItemReq{
  171. EdbInfoId: newMappingInfo.EdbInfoId,
  172. Name: fmt.Sprint("M+", v.Month),
  173. NameEn: fmt.Sprint("M+", v.Month),
  174. Source: newMappingInfo.Source,
  175. })
  176. }
  177. // 获取数据
  178. for _, v := range futureGoodMappingList {
  179. dataList := make([]*edbDataModel.EdbDataList, 0)
  180. tmpDataList, tmpErr := future_good_edb_data.GetFutureGoodEdbDataListByDate(v.EdbInfoId, startDate, endDate)
  181. if tmpErr != nil {
  182. return
  183. }
  184. for _, tmpData := range tmpDataList {
  185. dataList = append(dataList, &edbDataModel.EdbDataList{
  186. EdbDataId: int(tmpData.FutureGoodEdbDataID),
  187. EdbInfoId: int(tmpData.FutureGoodEdbInfoID),
  188. DataTime: tmpData.DataTime.Format(utils.FormatDate),
  189. DataTimestamp: tmpData.DataTimestamp,
  190. Value: tmpData.Close,
  191. })
  192. }
  193. edbDataListMap[v.EdbInfoId] = dataList
  194. v.DataList = dataList
  195. }
  196. edbList = append(edbList, futureGoodMappingList...)
  197. xEdbIdValue, yDataList, err = BarChartData(edbList[0], futureGoodEdbInfoList, edbDataListMap, barChartInfoDateList, regionType, edbInfoMapping.EndDate)
  198. xDataList = []chart_info.XData{
  199. {
  200. Name: "现货价",
  201. NameEn: "Spot Price",
  202. },
  203. }
  204. //yDataList =make([]chart_info.YData,0)
  205. //chart_info.YData{
  206. // Date: "",
  207. // Color: "",
  208. // Name: "",
  209. // NameEn: "",
  210. // Value: nil,
  211. // NoDataEdbList: nil,
  212. // XEdbInfoIdList: nil,
  213. //}
  214. futureGoodEdbInfoIndexMap := make(map[int]int)
  215. for index, v := range futureGoodEdbInfoList {
  216. futureGoodEdbInfoIndexMap[int(v.FutureGoodEdbInfoID)] = index
  217. }
  218. nMap := make(map[int]int)
  219. maxIndex := 0 // 最大x轴的下标
  220. for k, tmpYData := range yDataList {
  221. yDataMap := tmpYData.EdbValMap
  222. edbInfoIdList := make([]int, 0)
  223. noDataEdbInfoIdList := make([]int, 0)
  224. valueList := make([]float64, 0)
  225. noDataEdbIdMap := make(map[int]int)
  226. // 所有的N值
  227. for _, n := range tmpYData.M {
  228. nMap[n] = n
  229. }
  230. // 基础指标
  231. {
  232. baseEdbInfId := edbList[0].EdbInfoId
  233. edbInfoIdList = append(edbInfoIdList, baseEdbInfId)
  234. tmpVal, ok := yDataMap[baseEdbInfId]
  235. valueList = append(valueList, tmpVal)
  236. if !ok || tmpVal == 0 {
  237. noDataEdbInfoIdList = append(noDataEdbInfoIdList, baseEdbInfId)
  238. noDataEdbIdMap[baseEdbInfId] = baseEdbInfId
  239. }
  240. }
  241. for _, futureGoodEdbInfo := range futureGoodEdbInfoList {
  242. tmpEdbInfId := int(futureGoodEdbInfo.FutureGoodEdbInfoID)
  243. edbInfoIdList = append(edbInfoIdList, tmpEdbInfId)
  244. tmpVal, ok := yDataMap[tmpEdbInfId]
  245. valueList = append(valueList, tmpVal)
  246. if !ok || tmpVal == 0 {
  247. noDataEdbInfoIdList = append(noDataEdbInfoIdList, tmpEdbInfId)
  248. noDataEdbIdMap[tmpEdbInfId] = tmpEdbInfId
  249. }
  250. }
  251. //tmpYData.Value = valueList
  252. tmpYData.NoDataEdbList = noDataEdbInfoIdList
  253. yDataList[k] = tmpYData
  254. lenEdbId := len(edbInfoIdList)
  255. tmpMaxIndex := lenEdbId - 1 // 当前数据的最大x轴的下标
  256. for i := lenEdbId - 1; i >= 0; i-- {
  257. // 如果没有在无数据的指标列表中找到,那么就找到了最大x轴的下标
  258. if _, ok := noDataEdbIdMap[edbInfoIdList[i]]; !ok {
  259. // 如果最大x轴的下标 小于 当前下标,那么就重新赋值
  260. if maxIndex < i-1 {
  261. maxIndex = i - 1
  262. }
  263. break
  264. }
  265. tmpMaxIndex = i - 1
  266. }
  267. // 如果最大x轴的下标 小于 当前下标,那么就重新赋值
  268. if maxIndex < tmpMaxIndex {
  269. maxIndex = tmpMaxIndex
  270. }
  271. }
  272. //xEdbIdValue = xEdbIdValue[0:maxIndex]
  273. // 找出所有的N值,并进行正序排列
  274. nList := make([]int, 0)
  275. for _, n := range nMap {
  276. nList = append(nList, n)
  277. }
  278. sort.Slice(nList, func(i, j int) bool {
  279. return nList[i] < nList[j]
  280. })
  281. for k, v := range yDataList {
  282. if len(v.XEdbInfoIdList) >= maxIndex+1 {
  283. yDataList[k].XEdbInfoIdList = v.XEdbInfoIdList[0 : maxIndex+1]
  284. }
  285. if len(v.Value) >= maxIndex+1 {
  286. yDataList[k].Value = v.Value[0 : maxIndex+1]
  287. }
  288. }
  289. tmpXDataList, newYDataList, err := handleResultData(regionType, futureGoodEdbType, yDataList, futureGoodEdbInfoList, maxIndex)
  290. if err != nil {
  291. return
  292. }
  293. xDataList = append(xDataList, tmpXDataList...)
  294. yDataList = newYDataList
  295. return
  296. }
  297. // BarChartData 获取数据
  298. func BarChartData(edbInfoMapping *chartEdbMappingModel.ChartEdbInfoMappingList, futureGoodMappingList []*future_good_edb_info.FutureGoodEdbInfo, edbDataListMap map[int][]*edbDataModel.EdbDataList, barChartInfoDateList []request.BarChartInfoDateReq, regionType, latestDate string) (edbIdList []int, yDataList []chart_info.YData, err error) {
  299. // 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
  300. edbDataMap := make(map[int]map[string]float64)
  301. for edbInfoId, edbDataList := range edbDataListMap {
  302. edbDateData := make(map[string]float64)
  303. for _, edbData := range edbDataList {
  304. edbDateData[edbData.DataTime] = edbData.Value
  305. }
  306. edbDataMap[edbInfoId] = edbDateData
  307. }
  308. // edbIdList 指标展示顺序;x轴的指标顺序
  309. edbIdList = make([]int, 0)
  310. edbIdList = append(edbIdList, edbInfoMapping.EdbInfoId)
  311. for _, v := range futureGoodMappingList {
  312. edbIdList = append(edbIdList, int(v.FutureGoodEdbInfoID))
  313. }
  314. latestDateTime, _ := time.ParseInLocation(utils.FormatDate, latestDate, time.Local)
  315. yDataList = make([]chart_info.YData, 0) //y轴的数据列表
  316. for _, barChartInfoDate := range barChartInfoDateList {
  317. yDataMap := make(map[int]float64)
  318. var maxDate time.Time
  319. var findDateTime time.Time
  320. switch barChartInfoDate.Type {
  321. case 1: //最新值
  322. findDateTime = latestDateTime
  323. case 2: //近期几天
  324. findDateTime = latestDateTime.AddDate(0, 0, -barChartInfoDate.Value)
  325. case 3: // 固定日期
  326. //寻找固定日期的数据
  327. tmpFindDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
  328. if tmpErr != nil {
  329. err = tmpErr
  330. return
  331. }
  332. findDateTime = tmpFindDateTime
  333. default:
  334. err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
  335. return
  336. }
  337. if findDateTime.IsZero() {
  338. err = errors.New("错误的日期")
  339. return
  340. }
  341. findDataList := make([]float64, 0) // 当前日期的数据值
  342. noDataIdList := make([]int, 0) // 没有数据的指标id
  343. noDataIdMap := make(map[int]int, 0) // 没有数据的指标map
  344. xEdbInfoIdList := make([]int, 0) // 当前数据的指标id列表
  345. // 现货指标
  346. realDateTime, findDataValue, isFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[edbInfoMapping.EdbInfoId], edbDataMap[edbInfoMapping.EdbInfoId])
  347. if tmpErr != nil {
  348. err = tmpErr
  349. return
  350. }
  351. findDataList = append(findDataList, findDataValue)
  352. yDataMap[edbInfoMapping.EdbInfoId] = findDataValue
  353. if isFind {
  354. maxDate = realDateTime
  355. } else {
  356. noDataIdList = append(noDataIdList, edbInfoMapping.EdbInfoId)
  357. noDataIdMap[edbInfoMapping.EdbInfoId] = edbInfoMapping.EdbInfoId
  358. }
  359. currMonth := findDateTime.Month() // 当前月份
  360. currYear := findDateTime.Year() // 当前年份
  361. xEdbInfoIdList = append(xEdbInfoIdList, edbInfoMapping.EdbInfoId)
  362. mList := make([]int, 0) // 间隔月份
  363. indexList := make([]int, 0)
  364. if regionType == `国内` {
  365. for i := currMonth + 1; i <= 12; i++ {
  366. indexList = append(indexList, int(i))
  367. mList = append(mList, int(i-currMonth))
  368. }
  369. for i := 1; i < int(currMonth); i++ {
  370. indexList = append(indexList, i)
  371. mList = append(mList, 12+i-int(currMonth))
  372. }
  373. } else {
  374. for i, v := range futureGoodMappingList {
  375. if v.FutureGoodEdbType == 2 {
  376. if i == 0 {
  377. continue
  378. }
  379. indexList = append(indexList, i)
  380. mList = append(mList, int(v.Month))
  381. } else {
  382. if v.Year > currYear || (v.Year == currYear && int(v.Month) > int(currMonth)) {
  383. indexList = append(indexList, i)
  384. mList = append(mList, (v.Year-currYear)*12+int(v.Month)-int(currMonth))
  385. }
  386. }
  387. }
  388. }
  389. for _, i := range indexList {
  390. futureGoodMapping := futureGoodMappingList[i] // 当前的期货指标
  391. //tmpRealDateTime, tmpFindDataValue, tmpIsFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[futureGoodMapping.FutureGoodEdbInfoId], edbDataMap[futureGoodMapping.FutureGoodEdbInfoId])
  392. //if tmpErr != nil {
  393. // err = tmpErr
  394. // return
  395. //}
  396. //tmpRealDateTime := findDateTime // 按照配置找到的日期
  397. tmpRealDateTime := realDateTime // 实际现货的日期
  398. tmpFindDataValue, tmpIsFind := edbDataMap[int(futureGoodMapping.FutureGoodEdbInfoID)][tmpRealDateTime.Format(utils.FormatDate)]
  399. yDataMap[int(futureGoodMapping.FutureGoodEdbInfoID)] = tmpFindDataValue
  400. findDataList = append(findDataList, tmpFindDataValue)
  401. if tmpIsFind {
  402. if maxDate.IsZero() || maxDate.Before(tmpRealDateTime) {
  403. maxDate = tmpRealDateTime
  404. }
  405. } else {
  406. noDataIdList = append(noDataIdList, int(futureGoodMapping.FutureGoodEdbInfoID))
  407. noDataIdMap[int(futureGoodMapping.FutureGoodEdbInfoID)] = int(futureGoodMapping.FutureGoodEdbInfoID)
  408. }
  409. // 当前期货合约的指标
  410. xEdbInfoIdList = append(xEdbInfoIdList, int(futureGoodMapping.FutureGoodEdbInfoID))
  411. }
  412. yName := barChartInfoDate.Name
  413. yNameEn := barChartInfoDate.Name
  414. if yName == `` {
  415. if barChartInfoDate.Type == 2 {
  416. yName = strconv.Itoa(barChartInfoDate.Value) + "天前"
  417. if barChartInfoDate.Value == 1 {
  418. yNameEn = strconv.Itoa(barChartInfoDate.Value) + "day ago"
  419. } else {
  420. yNameEn = strconv.Itoa(barChartInfoDate.Value) + " days ago"
  421. }
  422. } else {
  423. yName = maxDate.Format(utils.FormatDate)
  424. yNameEn = maxDate.Format(utils.FormatDate)
  425. }
  426. }
  427. yDate := "0000-00-00"
  428. if !maxDate.IsZero() {
  429. yDate = maxDate.Format(utils.FormatDate)
  430. }
  431. // 数据处理,将没有数据的下标,赋值平均值
  432. {
  433. hasDataIndexList := make([]int, 0)
  434. for dataK, edbInfoId := range xEdbInfoIdList {
  435. if _, ok := noDataIdMap[edbInfoId]; !ok { // 如果是没有数据的指标id
  436. hasDataIndexList = append(hasDataIndexList, dataK)
  437. }
  438. }
  439. lenHasDataIndex := len(hasDataIndexList)
  440. if lenHasDataIndex > 0 {
  441. for lenHasDataI := 1; lenHasDataI < lenHasDataIndex; lenHasDataI++ {
  442. perK := hasDataIndexList[lenHasDataI-1] //上一个有数据的指标下标
  443. currK := hasDataIndexList[lenHasDataI] //当前有数据的指标下标
  444. preVal := findDataList[perK] //上一个有数据的坐标的值
  445. currVal := findDataList[currK] //当前有数据的指标的值
  446. // 环差值
  447. hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(currK - perK)))
  448. var tmpI int64
  449. // 将两个中间的数据做平均值补全
  450. for hcI := perK + 1; hcI < currK; hcI++ {
  451. tmpI++
  452. findDataList[hcI], _ = decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(tmpI))).RoundCeil(4).Float64()
  453. }
  454. }
  455. }
  456. }
  457. yDataList = append(yDataList, chart_info.YData{
  458. Date: yDate,
  459. ConfigDate: realDateTime,
  460. Value: findDataList,
  461. NoDataEdbList: noDataIdList,
  462. XEdbInfoIdList: xEdbInfoIdList,
  463. Color: barChartInfoDate.Color,
  464. Name: yName,
  465. NameEn: yNameEn,
  466. EdbValMap: yDataMap,
  467. M: mList,
  468. })
  469. }
  470. return
  471. }
  472. // GetNeedDateData 获取合约内需要的日期数据
  473. func GetNeedDateData(needDateTime time.Time, dataList []*edbDataModel.EdbDataList, edbDataMap map[string]float64) (findDateTime time.Time, findDataValue float64, isFind bool, err error) {
  474. //dataList := edbDataListMap[edbInfoId] //指标的所有数据值
  475. if len(dataList) <= 0 {
  476. // 没有数据的指标id
  477. return
  478. }
  479. //最早的日期
  480. minDateTime, err := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  481. if err != nil {
  482. return
  483. }
  484. for tmpDateTime := needDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  485. tmpDate := tmpDateTime.Format(utils.FormatDate)
  486. if tmpValue, ok := edbDataMap[tmpDate]; ok { //如果能找到数据,那么就返回
  487. // 数据为0,也直接返回,做无值处理
  488. if tmpValue == 0 {
  489. return
  490. }
  491. findDateTime, _ = time.ParseInLocation(utils.FormatDate, tmpDate, time.Local)
  492. findDataValue = tmpValue
  493. isFind = true
  494. return
  495. }
  496. }
  497. return
  498. }
  499. // FutureGoodChartInfoRefresh
  500. // @author Roc
  501. // @datetime 2023-2-2 18:44:46
  502. // @description 商品价格曲线图表刷新
  503. func FutureGoodChartInfoRefresh(chartInfoId int) (err error) {
  504. var errMsg string
  505. defer func() {
  506. if err != nil {
  507. go alarm_msg.SendAlarmMsg("ChartInfoRefresh:"+errMsg, 3)
  508. fmt.Println("ChartInfoRefresh Err:" + errMsg)
  509. }
  510. }()
  511. edbInfoMapping, err := chartEdbMappingModel.GetEtaEdbChartEdbMapping(chartInfoId)
  512. if err != nil {
  513. errMsg = "获取需要刷新的ETA指标失败:Err:" + err.Error()
  514. return
  515. }
  516. // 获取期货指标
  517. futureGoodEdbInfoMapping, err := chartEdbMappingModel.GetFutureGoodEdbChartEdbMapping(chartInfoId)
  518. if err != nil {
  519. errMsg = "获取需要刷新的商品期货指标失败:Err:" + err.Error()
  520. return
  521. }
  522. // 获取期货指标以及期货数据
  523. futureGoodEdbInfoList, err := future_good_edb_info.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfoMapping.EdbInfoId)
  524. if err != nil {
  525. return
  526. }
  527. // 批量刷新ETA指标
  528. err, _ = chart.EdbInfoRefreshAllFromBase([]int{edbInfoMapping.EdbInfoId}, false)
  529. if err != nil {
  530. return
  531. }
  532. // 批量刷新期货指标
  533. err = FutureGoodEdbInfoRefreshAllFromBase(futureGoodEdbInfoList, false)
  534. if err != nil {
  535. return
  536. }
  537. return
  538. }
  539. // handleResultData 处理成最终的结果数据
  540. func handleResultData(regionType string, futureGoodEdbType int, yDataList []chart_info.YData, futureGoodEdbInfoList []*future_good_edb_info.FutureGoodEdbInfo, maxIndex int) (xDataList []chart_info.XData, newYDataList []chart_info.YData, err error) {
  541. xDataList = make([]chart_info.XData, 0)
  542. newYDataList = yDataList
  543. if regionType == `国内` {
  544. for i := 1; i < 12; i++ {
  545. if i > maxIndex {
  546. break
  547. }
  548. xDataList = append(xDataList, chart_info.XData{
  549. Name: fmt.Sprint("M+", i),
  550. NameEn: fmt.Sprint("M+", i),
  551. })
  552. }
  553. return
  554. }
  555. futureGoodEdbInfoMap := make(map[int]*future_good_edb_info.FutureGoodEdbInfo)
  556. for _, v := range futureGoodEdbInfoList {
  557. futureGoodEdbInfoMap[int(v.FutureGoodEdbInfoID)] = v
  558. }
  559. if futureGoodEdbType == 2 { // FutureGoodEdbType int `description:"指标类型,1:年月是固定的合约;2:只有M+N期的合约,未固定年月"`
  560. nList := []int{3, 15, 27}
  561. for _, i := range nList {
  562. xDataList = append(xDataList, chart_info.XData{
  563. Name: fmt.Sprint("M+", i),
  564. NameEn: fmt.Sprint("M+", i),
  565. })
  566. }
  567. for yIndex, yData := range yDataList {
  568. newYDataList[yIndex].XEdbInfoIdList = []int{}
  569. newYDataList[yIndex].Value = []float64{}
  570. tmpNList := nList
  571. //当前的主力合约
  572. newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, yData.XEdbInfoIdList[0])
  573. newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[0])
  574. xEdbInfoIdList := yData.XEdbInfoIdList[1:]
  575. valIndex := 1
  576. needNum := 0
  577. for _, n := range tmpNList {
  578. if len(xEdbInfoIdList) > 0 {
  579. edbInfoId := xEdbInfoIdList[0]
  580. futureGoodEdbInfo, ok := futureGoodEdbInfoMap[edbInfoId]
  581. if !ok {
  582. err = errors.New("找不到指标")
  583. return
  584. }
  585. // 当前距离最早的日期相差的N数
  586. if int(futureGoodEdbInfo.Month) == n {
  587. if needNum > 0 {
  588. currVal := yData.Value[valIndex]
  589. preVal := yData.Value[valIndex-1]
  590. hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(needNum + 1)))
  591. for tmpNum := 0; tmpNum < needNum; tmpNum++ {
  592. newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, 0)
  593. // 赋值平均值
  594. tmpVal, _ := decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(int64(tmpNum + 1)))).RoundCeil(4).Float64()
  595. newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, tmpVal)
  596. }
  597. }
  598. newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, edbInfoId)
  599. newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[valIndex])
  600. valIndex++
  601. needNum = 0
  602. if len(xEdbInfoIdList) > 0 {
  603. xEdbInfoIdList = xEdbInfoIdList[1:]
  604. }
  605. } else {
  606. needNum++
  607. }
  608. }
  609. }
  610. }
  611. maxI := 0
  612. for _, yData := range newYDataList {
  613. lenEdb := len(yData.XEdbInfoIdList)
  614. for i := 0; i < lenEdb; i++ {
  615. if yData.XEdbInfoIdList[i] != 0 && !utils.InArrayByInt(yData.NoDataEdbList, yData.XEdbInfoIdList[i]) {
  616. if maxI < i {
  617. maxI = i
  618. }
  619. }
  620. }
  621. }
  622. xDataList = xDataList[0:maxI]
  623. for yIndex, yData := range newYDataList {
  624. if len(yData.XEdbInfoIdList) > maxI+1 {
  625. newYDataList[yIndex].XEdbInfoIdList = yData.XEdbInfoIdList[0 : maxI+1]
  626. }
  627. if len(yData.Value) > maxI+1 {
  628. newYDataList[yIndex].Value = yData.Value[0 : maxI+1]
  629. }
  630. }
  631. return
  632. }
  633. nMap := make(map[int]int)
  634. for _, v := range yDataList {
  635. findDateTime := v.ConfigDate
  636. currMonth := findDateTime.Month() // 当前月份
  637. currYear := findDateTime.Year() // 当前年份
  638. //v.XEdbInfoIdList
  639. for edbInfoIndex, edbInfoId := range v.XEdbInfoIdList {
  640. // 第一个不处理
  641. if edbInfoIndex == 0 {
  642. continue
  643. }
  644. futureGoodEdbInfo, ok := futureGoodEdbInfoMap[edbInfoId]
  645. if !ok {
  646. err = errors.New("找不到指标")
  647. return
  648. }
  649. n := (futureGoodEdbInfo.Year-currYear)*12 + int(futureGoodEdbInfo.Month) - int(currMonth)
  650. nMap[n] = n
  651. }
  652. }
  653. // 找出所有的N值,并进行正序排列
  654. nList := make([]int, 0)
  655. for _, n := range nMap {
  656. nList = append(nList, n)
  657. }
  658. sort.Slice(nList, func(i, j int) bool {
  659. return nList[i] < nList[j]
  660. })
  661. //prevMonth := 1
  662. for _, n := range nList {
  663. xDataList = append(xDataList, chart_info.XData{
  664. Name: fmt.Sprint("M+", n),
  665. NameEn: fmt.Sprint("M+", n),
  666. })
  667. }
  668. for yIndex, yData := range yDataList {
  669. newYDataList[yIndex].XEdbInfoIdList = []int{}
  670. newYDataList[yIndex].Value = []float64{}
  671. tmpNList := nList
  672. //当前的主力合约
  673. newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, yData.XEdbInfoIdList[0])
  674. newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[0])
  675. xEdbInfoIdList := yData.XEdbInfoIdList[1:]
  676. currDataTime := yData.ConfigDate
  677. valIndex := 1
  678. needNum := 0
  679. for _, n := range tmpNList {
  680. if len(xEdbInfoIdList) > 0 {
  681. edbInfoId := xEdbInfoIdList[0]
  682. futureGoodEdbInfo, ok := futureGoodEdbInfoMap[edbInfoId]
  683. if !ok {
  684. err = errors.New("找不到指标")
  685. return
  686. }
  687. // 当前距离最早的日期相差的N数
  688. divMonth := (futureGoodEdbInfo.Year-currDataTime.Year())*12 + (int(futureGoodEdbInfo.Month) - int(currDataTime.Month()))
  689. if divMonth == n {
  690. if needNum > 0 {
  691. currVal := yData.Value[valIndex]
  692. preVal := yData.Value[valIndex-1]
  693. hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(needNum + 1)))
  694. for tmpNum := 0; tmpNum < needNum; tmpNum++ {
  695. newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, 0)
  696. // 赋值平均值
  697. tmpVal, _ := decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(int64(tmpNum + 1)))).RoundCeil(4).Float64()
  698. newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, tmpVal)
  699. }
  700. }
  701. newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, edbInfoId)
  702. newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[valIndex])
  703. valIndex++
  704. needNum = 0
  705. if len(xEdbInfoIdList) > 0 {
  706. xEdbInfoIdList = xEdbInfoIdList[1:]
  707. }
  708. } else {
  709. needNum++
  710. }
  711. }
  712. }
  713. }
  714. maxI := 0
  715. for _, yData := range newYDataList {
  716. lenEdb := len(yData.XEdbInfoIdList)
  717. for i := 0; i < lenEdb; i++ {
  718. if yData.XEdbInfoIdList[i] != 0 && !utils.InArrayByInt(yData.NoDataEdbList, yData.XEdbInfoIdList[i]) {
  719. if maxI < i {
  720. maxI = i
  721. }
  722. }
  723. }
  724. }
  725. xDataList = xDataList[0:maxI]
  726. for yIndex, yData := range newYDataList {
  727. if len(yData.XEdbInfoIdList) > maxI+1 {
  728. newYDataList[yIndex].XEdbInfoIdList = yData.XEdbInfoIdList[0 : maxI+1]
  729. }
  730. if len(yData.Value) > maxI+1 {
  731. newYDataList[yIndex].Value = yData.Value[0 : maxI+1]
  732. }
  733. }
  734. return
  735. }
  736. // getFutureGoodEdbInfoList 获取适用的指标列表
  737. func getFutureGoodEdbInfoList(latestDateTime time.Time, tmpFutureGoodEdbInfoList []*future_good_edb_info.FutureGoodEdbInfo, barChartInfoDateList []request.BarChartInfoDateReq) (earliestDateTime time.Time, futureGoodEdbInfoList []*future_good_edb_info.FutureGoodEdbInfo, err error) {
  738. maxM := 36 //最大36期合约
  739. futureGoodEdbInfoList = make([]*future_good_edb_info.FutureGoodEdbInfo, 0)
  740. earliestDateTime = latestDateTime // 数据的最早日期,目的是为了找出最早的合约
  741. for _, barChartInfoDate := range barChartInfoDateList {
  742. var findDateTime time.Time
  743. switch barChartInfoDate.Type {
  744. case 1: //最新值
  745. findDateTime = latestDateTime
  746. case 2: //近期几天
  747. findDateTime = latestDateTime.AddDate(0, 0, -barChartInfoDate.Value)
  748. case 3: // 固定日期
  749. //寻找固定日期的数据
  750. tmpFindDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
  751. if tmpErr != nil {
  752. err = tmpErr
  753. return
  754. }
  755. findDateTime = tmpFindDateTime
  756. default:
  757. err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
  758. return
  759. }
  760. if findDateTime.IsZero() {
  761. err = errors.New("错误的日期")
  762. return
  763. }
  764. if findDateTime.Before(earliestDateTime) {
  765. earliestDateTime = findDateTime
  766. }
  767. }
  768. for _, v := range tmpFutureGoodEdbInfoList {
  769. if v.RegionType == `国内` {
  770. futureGoodEdbInfoList = append(futureGoodEdbInfoList, v)
  771. continue
  772. }
  773. //海外的连续日期,目前
  774. if v.FutureGoodEdbType == 2 {
  775. if int(v.Month) <= maxM {
  776. //addMonth := int(earliestDateTime.Month()) + int(v.Month)
  777. //v.Year = earliestDateTime.Year() + addMonth/12
  778. //realMonth := addMonth % 12
  779. //if realMonth == 0 {
  780. // realMonth = 12
  781. //}
  782. //v.Month = uint32(realMonth)
  783. futureGoodEdbInfoList = append(futureGoodEdbInfoList, v)
  784. }
  785. continue
  786. }
  787. if v.Year < earliestDateTime.Year() {
  788. continue
  789. }
  790. // 小于等于当前年,那么就肯定是ok的
  791. if v.Year <= earliestDateTime.Year() {
  792. futureGoodEdbInfoList = append(futureGoodEdbInfoList, v)
  793. continue
  794. }
  795. // 如果(当前年-最新日期的年份) * 12个月 + (当前月-最新日期的月份) 小于总月份
  796. if (v.Year-earliestDateTime.Year())*12+(int(v.Month)-int(earliestDateTime.Month())) <= maxM {
  797. futureGoodEdbInfoList = append(futureGoodEdbInfoList, v)
  798. continue
  799. }
  800. }
  801. return
  802. }