profit_chart_info.go 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019
  1. package logic
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "eta/eta_index_lib/models"
  6. "eta/eta_index_lib/models/future_good"
  7. "eta/eta_index_lib/utils"
  8. "fmt"
  9. "github.com/dengsgo/math-engine/engine"
  10. "github.com/shopspring/decimal"
  11. "sort"
  12. "strconv"
  13. "strings"
  14. "time"
  15. )
  16. // ChartInfoDateReq 图表的日期数据(日期相关)
  17. type ChartInfoDateReq struct {
  18. Type int `description:"配置类型"`
  19. Date string `description:"固定日期"`
  20. Value int `description:"N天的值"`
  21. Color string `description:"颜色"`
  22. Name string `description:"别名"`
  23. }
  24. // SectionScatterReq 截面散点请求
  25. type SectionScatterReq struct {
  26. XName string `description:"x轴名称"`
  27. XNameEn string `description:"x轴名称(英文)"`
  28. XUnitName string `description:"x轴单位名称"`
  29. XUnitNameEn string `description:"x轴单位名称(英文)"`
  30. YName string `description:"y轴名称"`
  31. YNameEn string `description:"y轴名称(英文)"`
  32. YUnitName string `description:"y轴单位名称"`
  33. YUnitNameEn string `description:"y轴单位名称(英文)"`
  34. XMinValue string `description:"X轴的最小值"`
  35. XMaxValue string `description:"X轴的最大值"`
  36. YMinValue string `description:"Y轴的最小值"`
  37. YMaxValue string `description:"Y轴的最大值"`
  38. //EdbList []SectionScatterEdbItemReq `description:"指标数据"`
  39. SeriesList []SectionScatterSeriesItemReq `description:"系列数据"`
  40. }
  41. // SectionScatterSeriesItemReq 系列的请求
  42. type SectionScatterSeriesItemReq struct {
  43. Name string `description:"系列名"`
  44. NameEn string `description:"系列名(英文名)"`
  45. Color string `description:"颜色"`
  46. EdbInfoList []SectionScatterEdbItemReq
  47. ShowTrendLine bool `description:"是否展示趋势线"`
  48. ShowFitEquation bool `description:"是否展示方程式"`
  49. ShowRSquare bool `description:"是否展示R平方"`
  50. }
  51. // SectionScatterEdbItemReq 截面散点请求的指标
  52. type SectionScatterEdbItemReq struct {
  53. XEdbInfoId int `description:"X轴的指标ID"`
  54. YEdbInfoId int `description:"Y轴的指标ID"`
  55. Name string `description:"别名"`
  56. NameEn string `description:"英文别名"`
  57. XDateType int `description:"X轴的日期配置类型"`
  58. XDate string `description:"X轴的日期固定日期"`
  59. XDateValue int `description:"X轴的日期N天的值"`
  60. YDateType int `description:"Y轴的日期配置类型"`
  61. YDate string `description:"Y轴的日期固定日期"`
  62. YDateValue int `description:"Y轴的日期N天的值"`
  63. IsShow bool `description:"是否展示"`
  64. }
  65. // XData 商品价格曲线的的x轴数据
  66. type XData struct {
  67. Name string `description:"别名"`
  68. NameEn string `description:"英文别名"`
  69. }
  70. // YData 柱方图的y轴数据
  71. type YData struct {
  72. Date string `description:"数据日期"`
  73. ConfigDate time.Time `description:"配置的日期" json:"-"`
  74. Color string `description:"数据颜色"`
  75. Name string `description:"别名"`
  76. NameEn string `description:"英文别名"`
  77. Value []float64 `description:"每个指标的值"`
  78. NoDataEdbList []int `description:"没有数据的指标列表"`
  79. XEdbInfoIdList []int `description:"对应X轴的指标id列表"`
  80. NameList []string `description:"每个值对应的名称"`
  81. EnNameList []string `description:"每个值对应的英文名称"`
  82. EdbValMap map[int]float64 `description:"指标与值的对应" json:"-"`
  83. M []int `description:"对应开始日期的间隔值" json:"-"`
  84. }
  85. // BarChartInfoEdbItemReq 柱方图预览请求数据(指标相关)
  86. type BarChartInfoEdbItemReq struct {
  87. EdbInfoId int `description:"指标ID"`
  88. Name string `description:"别名"`
  89. NameEn string `description:"英文别名"`
  90. Source int `description:"1:ETA图库;2:商品价格"`
  91. }
  92. // ChartInfoReq 图表预览请求数据
  93. type ChartInfoReq struct {
  94. FutureGoodEdbInfoIdList []models.EdbInfoFromTag `description:"指标信息"`
  95. CalculateFormula string `description:"计算公式"`
  96. BaseEdbInfoId int `description:"基础的指标id"`
  97. DateList []ChartInfoDateReq `description:"日期配置"`
  98. ProfitNameEn string `description:"利润英文名称"`
  99. EdbInfoIdList []int `description:"现货指标ID列表"`
  100. XDataList []XData `description:"横轴配置"`
  101. }
  102. // RefreshByChartId 根据图表id刷新图表
  103. func RefreshByChartId(chartInfoId int) (err error, errMsg string) {
  104. // 查找图表
  105. chartInfo, err := models.GetChartInfoById(chartInfoId)
  106. if err != nil {
  107. if err.Error() == utils.ErrNoRow() {
  108. err = nil
  109. }
  110. return
  111. }
  112. if chartInfo.Source != utils.CHART_SOURCE_FUTURE_GOOD_PROFIT {
  113. return
  114. }
  115. var extraConf ChartInfoReq
  116. err = json.Unmarshal([]byte(chartInfo.ExtraConfig), &extraConf)
  117. if err != nil {
  118. errMsg = "商品利润曲线图配置异常"
  119. return
  120. }
  121. // 查找商品利润图表的扩展信息
  122. chartInfoFutureGoodProfit := new(future_good.ChartInfoFutureGoodProfit)
  123. if err = chartInfoFutureGoodProfit.GetItemById(chartInfoId); err != nil {
  124. errMsg = "获取失败"
  125. if err.Error() == utils.ErrNoRow() {
  126. err = nil
  127. }
  128. return
  129. }
  130. if len(extraConf.EdbInfoIdList) == 0 {
  131. extraConf.EdbInfoIdList = append(extraConf.EdbInfoIdList, extraConf.BaseEdbInfoId)
  132. }
  133. baseEdbInfo := new(models.EdbInfo)
  134. // ETA指标
  135. edbInfoListTmp, err := models.GetEdbInfoByIdList(extraConf.EdbInfoIdList)
  136. if err != nil {
  137. errMsg = "获取失败"
  138. return
  139. }
  140. //按照请求顺序排序
  141. edbInfoMap := make(map[int]*models.EdbInfo)
  142. for _, v := range edbInfoListTmp {
  143. edbInfoMap[v.EdbInfoId] = v
  144. }
  145. edbInfoList := make([]*models.EdbInfo, 0)
  146. for _, v := range extraConf.EdbInfoIdList {
  147. edbInfoList = append(edbInfoList, edbInfoMap[v])
  148. }
  149. edbInfoListMap := make(map[int]*models.EdbInfo)
  150. for k, v := range edbInfoList {
  151. edbInfoList[k].EdbNameSource = v.EdbName
  152. edbInfoListMap[v.EdbInfoId] = v
  153. if v.EdbInfoId == extraConf.BaseEdbInfoId {
  154. baseEdbInfo = v
  155. }
  156. }
  157. // 商品数据库指标
  158. futureGoodEdbInfoMap := make(map[int]*future_good.FutureGoodEdbInfo)
  159. zlFutureGoodEdbInfoList := make([]*future_good.FutureGoodEdbInfo, 0)
  160. for _, v := range extraConf.FutureGoodEdbInfoIdList {
  161. if _, ok := futureGoodEdbInfoMap[v.EdbInfoId]; ok {
  162. continue
  163. }
  164. zlFutureGoodEdbInfo, tmpErr := future_good.GetFutureGoodEdbInfo(v.EdbInfoId)
  165. if tmpErr != nil {
  166. err = tmpErr
  167. errMsg = "获取失败"
  168. return
  169. }
  170. futureGoodEdbInfoMap[v.EdbInfoId] = zlFutureGoodEdbInfo
  171. zlFutureGoodEdbInfoList = append(zlFutureGoodEdbInfoList, zlFutureGoodEdbInfo)
  172. }
  173. xDataList, yDataList, err := GetProfitChartEdbData(baseEdbInfo, edbInfoList, zlFutureGoodEdbInfoList, extraConf.DateList, extraConf.CalculateFormula, extraConf.FutureGoodEdbInfoIdList, extraConf.XDataList)
  174. xDataListByte, err := json.Marshal(xDataList)
  175. if err != nil {
  176. errMsg = "保存失败"
  177. err = errors.New("X轴数据转换失败,ERR:" + err.Error())
  178. return
  179. }
  180. yDataListByte, err := json.Marshal(yDataList)
  181. if err != nil {
  182. errMsg = "保存失败"
  183. err = errors.New("Y轴数据转换失败,ERR:" + err.Error())
  184. return
  185. }
  186. extraUpdateCol := make([]string, 0)
  187. chartInfoFutureGoodProfit.XValue = string(xDataListByte)
  188. chartInfoFutureGoodProfit.YValue = string(yDataListByte)
  189. //chartInfoFutureGoodProfit.ProfitName = zlFutureGoodEdbInfoList[0].FutureGoodEdbName + "盘面利润"
  190. chartInfoFutureGoodProfit.ModifyTime = time.Now()
  191. extraUpdateCol = []string{"XValue", "YValue", "ProfitName", "ModifyTime"}
  192. err = chartInfoFutureGoodProfit.Update(extraUpdateCol)
  193. return
  194. }
  195. // GetProfitChartEdbData 获取利润图表的指标数据
  196. func GetProfitChartEdbData(baseEdbInfo *models.EdbInfo, edbInfoList []*models.EdbInfo, zlFutureGoodEdbInfoList []*future_good.FutureGoodEdbInfo, chartInfoDateList []ChartInfoDateReq, formulaStr string, edbInfoFromTagList []models.EdbInfoFromTag, reqXDataList []XData) (xDataList []XData, yDataList []YData, err error) {
  197. if baseEdbInfo == nil {
  198. err = errors.New("ETA指标未选取")
  199. return
  200. }
  201. if len(edbInfoList) == 0 {
  202. edbInfoList = append(edbInfoList, baseEdbInfo)
  203. }
  204. if len(zlFutureGoodEdbInfoList) <= 0 {
  205. err = errors.New("商品指标未选取")
  206. return
  207. }
  208. // 标签与期货商品指标的关联关系
  209. tagEdbIdMap := make(map[string]int)
  210. // 有效的期货商品指标
  211. futureGoodEdbInfoIdMap := make(map[int]int)
  212. {
  213. tmpTagEdbIdMap := make(map[string]int)
  214. for _, v := range edbInfoFromTagList {
  215. tmpTagEdbIdMap[v.FromTag] = v.EdbInfoId
  216. }
  217. formulaMap := CheckFormula(formulaStr)
  218. for _, tag := range formulaMap {
  219. tagEdbIdMap[tag] = tmpTagEdbIdMap[tag]
  220. futureGoodEdbInfoIdMap[tmpTagEdbIdMap[tag]] = tmpTagEdbIdMap[tag]
  221. }
  222. }
  223. // 指标对应的所有数据
  224. //edbDataListMap := make(map[int][]*models.EdbDataList)
  225. // 普通的指标数据
  226. baseDataListMap := make(map[int][]*models.EdbDataList)
  227. for _, v := range edbInfoList {
  228. baseDataList := make([]*models.EdbDataList, 0)
  229. baseDataList, err = models.GetEdbDataList(v.Source, v.SubSource, v.EdbInfoId, "", "")
  230. if err != nil {
  231. return
  232. }
  233. baseDataListMap[v.EdbInfoId] = baseDataList
  234. }
  235. latestDate := zlFutureGoodEdbInfoList[0].EndDate
  236. latestDateTime, _ := time.ParseInLocation(utils.FormatDate, latestDate, time.Local)
  237. findDateTimeList := make([]time.Time, 0)
  238. earliestDateTime := latestDateTime // 数据的最早日期,目的是为了找出最早的合约
  239. for _, barChartInfoDate := range chartInfoDateList {
  240. var findDateTime time.Time
  241. switch barChartInfoDate.Type {
  242. case 1: //最新值
  243. findDateTime = latestDateTime
  244. case 2: //近期几天
  245. findDateTime = latestDateTime.AddDate(0, 0, -barChartInfoDate.Value)
  246. case 3: // 固定日期
  247. //寻找固定日期的数据
  248. tmpFindDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
  249. if tmpErr != nil {
  250. err = tmpErr
  251. return
  252. }
  253. findDateTime = tmpFindDateTime
  254. default:
  255. err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
  256. return
  257. }
  258. if findDateTime.IsZero() {
  259. err = errors.New("错误的日期")
  260. return
  261. }
  262. if findDateTime.Before(earliestDateTime) {
  263. earliestDateTime = findDateTime
  264. }
  265. findDateTimeList = append(findDateTimeList, findDateTime)
  266. }
  267. monthNumMap := make(map[string]int)
  268. for _, findDateTimeTmp := range findDateTimeList {
  269. monthNumMap[findDateTimeTmp.Format(utils.FormatDate)] = (latestDateTime.Year()-findDateTimeTmp.Year())*12 + int(latestDateTime.Month()-findDateTimeTmp.Month())
  270. }
  271. // 存储主力合约下的所有月份合约
  272. futureGoodEdbInfoDateAllMap := make(map[int]map[string]map[string]*future_good.FutureGoodEdbInfo)
  273. futureGoodDataListMap := make(map[int][]*models.EdbDataList, 0)
  274. // 特殊的商品期货合约(只有M+N的合约,没有固定日期的合约)
  275. specialFutureGoodEdbInfoMap := make(map[int]map[int]*future_good.FutureGoodEdbInfo, 0)
  276. isAllChina := true // 是否都是国内的期货合约
  277. for _, v := range zlFutureGoodEdbInfoList {
  278. if v.RegionType != "国内" {
  279. isAllChina = false
  280. break
  281. }
  282. }
  283. nAllMap := make(map[string][]string)
  284. var maxN int // 最大N值
  285. for _, v := range zlFutureGoodEdbInfoList {
  286. // 如果不是有效的商品期货指标,那么就过滤掉,不做数据查询处理,避免没必要的请求
  287. if _, ok := futureGoodEdbInfoIdMap[v.FutureGoodEdbInfoId]; !ok {
  288. continue
  289. }
  290. // 获取期货指标以及期货数据
  291. tmpFutureGoodEdbInfoList, tmpErr := future_good.GetChildFutureGoodEdbInfoListByParentId(v.FutureGoodEdbInfoId)
  292. if tmpErr != nil {
  293. err = tmpErr
  294. return
  295. }
  296. childFutureGoodEdbInfoAllMap, tmpMaxN, tmpErr := GetProfitFutureGoodEdbInfoList(findDateTimeList, v, tmpFutureGoodEdbInfoList, isAllChina, monthNumMap)
  297. if tmpErr != nil {
  298. err = tmpErr
  299. return
  300. }
  301. if maxN < tmpMaxN {
  302. maxN = tmpMaxN
  303. }
  304. futureGoodEdbInfoDateAllMap[v.FutureGoodEdbInfoId] = childFutureGoodEdbInfoAllMap
  305. if v.FutureGoodEdbType == 2 {
  306. specialFutureGoodEdbInfoMap[v.FutureGoodEdbInfoId] = make(map[int]*future_good.FutureGoodEdbInfo)
  307. }
  308. // 获取数据
  309. for findDateTime, childFutureGoodEdbInfoMap := range childFutureGoodEdbInfoAllMap {
  310. for date, childFutureGoodEdbInfo := range childFutureGoodEdbInfoMap {
  311. nAllMap[findDateTime] = append(nAllMap[findDateTime], date)
  312. dataList := make([]*models.EdbDataList, 0)
  313. if _, ok := futureGoodDataListMap[childFutureGoodEdbInfo.FutureGoodEdbInfoId]; !ok {
  314. tmpDataList, tmpErr := future_good.GetFutureGoodEdbDataListByDate(childFutureGoodEdbInfo.FutureGoodEdbInfoId, "", "")
  315. if tmpErr != nil {
  316. return
  317. }
  318. for _, tmpData := range tmpDataList {
  319. dataList = append(dataList, &models.EdbDataList{
  320. EdbDataId: tmpData.FutureGoodEdbDataId,
  321. EdbInfoId: tmpData.FutureGoodEdbInfoId,
  322. DataTime: tmpData.DataTime.Format(utils.FormatDate),
  323. DataTimestamp: tmpData.DataTimestamp,
  324. Value: tmpData.Close,
  325. })
  326. }
  327. futureGoodDataListMap[childFutureGoodEdbInfo.FutureGoodEdbInfoId] = dataList
  328. }
  329. if childFutureGoodEdbInfo.FutureGoodEdbType == 2 {
  330. specialFutureGoodEdbInfoMap[v.FutureGoodEdbInfoId][childFutureGoodEdbInfo.Month] = childFutureGoodEdbInfo
  331. }
  332. }
  333. }
  334. }
  335. // 找出所有的N值,并进行正序排列
  336. dateListMap := make(map[string][]string, 0)
  337. for key, dateList := range nAllMap {
  338. sort.Slice(dateList, func(i, j int) bool {
  339. return dateList[i] < dateList[j]
  340. })
  341. dateListMap[key] = dateList
  342. }
  343. var reqEdbInfoIds []int
  344. for _, v := range edbInfoList {
  345. reqEdbInfoIds = append(reqEdbInfoIds, v.EdbInfoId)
  346. tmp := XData{
  347. Name: v.EdbName,
  348. NameEn: v.EdbNameEn,
  349. }
  350. xDataList = append(xDataList, tmp)
  351. }
  352. var edbIdList []int
  353. futureGoodNameMap := make(map[int]map[int]string)
  354. edbIdList, yDataList, futureGoodNameMap, err = ProfitChartChartData(baseEdbInfo, baseDataListMap, futureGoodEdbInfoDateAllMap, futureGoodDataListMap, chartInfoDateList, baseEdbInfo.EndDate, specialFutureGoodEdbInfoMap, formulaStr, tagEdbIdMap, dateListMap, maxN, reqEdbInfoIds)
  355. // todo 最后处理数据
  356. tmpXDataList, newYDataList, err := handleProfitResultData(xDataList, futureGoodNameMap, yDataList, earliestDateTime, edbIdList)
  357. if err != nil {
  358. return
  359. }
  360. if len(reqXDataList) == 0 {
  361. xDataList = tmpXDataList
  362. } else {
  363. xDataList = reqXDataList
  364. }
  365. yDataList = newYDataList
  366. return
  367. }
  368. // ProfitChartChartData 获取数据
  369. func ProfitChartChartData(baseEdbInfo *models.EdbInfo, baseDataListMap map[int][]*models.EdbDataList, futureGoodEdbInfoAllMap map[int]map[string]map[string]*future_good.FutureGoodEdbInfo, futureGoodEdbDataListMap map[int][]*models.EdbDataList, chartInfoDateList []ChartInfoDateReq, latestDate string, specialFutureGoodEdbInfoMap map[int]map[int]*future_good.FutureGoodEdbInfo, formulaStr string, tagEdbIdMap map[string]int, dateListMap map[string][]string, maxN int, reqEdbInfoIds []int) (edbIdList []int, yDataList []YData, futureGoodNameMap map[int]map[int]string, err error) {
  370. // 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
  371. //earliestDateTime time.Time
  372. // ETA指标数据
  373. allBaseEdbDateDataMap := make(map[int]map[string]float64)
  374. for edbInfoId, baseDataList := range baseDataListMap {
  375. baseEdbDateData := make(map[string]float64)
  376. for _, edbData := range baseDataList {
  377. baseEdbDateData[edbData.DataTime] = edbData.Value
  378. }
  379. allBaseEdbDateDataMap[edbInfoId] = baseEdbDateData
  380. }
  381. // 商品指标数据
  382. edbDataMap := make(map[int]map[string]float64)
  383. for edbInfoId, edbDataList := range futureGoodEdbDataListMap {
  384. edbDateData := make(map[string]float64)
  385. for _, edbData := range edbDataList {
  386. edbDateData[edbData.DataTime] = edbData.Value
  387. }
  388. edbDataMap[edbInfoId] = edbDateData
  389. }
  390. latestDateTime, _ := time.ParseInLocation(utils.FormatDate, latestDate, time.Local)
  391. yDataList = make([]YData, 0) //y轴的数据列表
  392. // 将计算公式中的字母转大写
  393. formulaStr = strings.ToUpper(formulaStr)
  394. futureGoodNameMap = make(map[int]map[int]string)
  395. for tmpk, barChartInfoDate := range chartInfoDateList {
  396. yDataMap := make(map[int]float64)
  397. var maxDate time.Time
  398. var findDateTime time.Time
  399. switch barChartInfoDate.Type {
  400. case 1: //最新值
  401. findDateTime = latestDateTime
  402. case 2: //近期几天
  403. findDateTime = latestDateTime.AddDate(0, 0, -barChartInfoDate.Value)
  404. case 3: // 固定日期
  405. //寻找固定日期的数据
  406. tmpFindDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
  407. if tmpErr != nil {
  408. err = tmpErr
  409. return
  410. }
  411. findDateTime = tmpFindDateTime
  412. default:
  413. err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
  414. return
  415. }
  416. if findDateTime.IsZero() {
  417. err = errors.New("错误的日期")
  418. return
  419. }
  420. findDataList := make([]float64, 0) // 当前日期的数据值
  421. noDataIdList := make([]int, 0) // 没有数据的指标id
  422. noDataIdMap := make(map[int]int, 0) // 没有数据的指标map
  423. xEdbInfoIdList := make([]int, 0) // 当前数据的指标id列表
  424. // 现货指标
  425. index := 0
  426. var realDateTime time.Time
  427. // 现货指标
  428. baseEdbDateData, ok := allBaseEdbDateDataMap[baseEdbInfo.EdbInfoId]
  429. if !ok {
  430. err = fmt.Errorf("指标id: %d 没有数据", baseEdbInfo.EdbInfoId)
  431. return
  432. }
  433. realDateTime, findDataValue, isFind, tmpErr := GetNeedDateData(findDateTime, baseDataListMap[baseEdbInfo.EdbInfoId], baseEdbDateData, edbDataMap)
  434. if tmpErr != nil {
  435. err = tmpErr
  436. return
  437. }
  438. if isFind {
  439. maxDate = realDateTime
  440. }
  441. fmt.Println("findDateTime", findDateTime, "realDateTime", realDateTime, "findDataValue", findDataValue, "isFind", isFind)
  442. edbIdList = make([]int, 0) //普通指标ID
  443. for _, edbInfoId := range reqEdbInfoIds {
  444. if edbInfoId == baseEdbInfo.EdbInfoId {
  445. findDataList = append(findDataList, findDataValue)
  446. yDataMap[index] = findDataValue
  447. xEdbInfoIdList = append(xEdbInfoIdList, edbInfoId)
  448. edbIdList = append(edbIdList, edbInfoId)
  449. index += 1
  450. continue
  451. }
  452. baseEdbDateDataTmp, ok := allBaseEdbDateDataMap[edbInfoId]
  453. if !ok {
  454. err = fmt.Errorf("指标id: %d 没有数据", edbInfoId)
  455. return
  456. }
  457. findDataValueTmp, isFindTmp := baseEdbDateDataTmp[realDateTime.Format(utils.FormatDate)]
  458. if !isFindTmp {
  459. noDataIdList = append(noDataIdList, edbInfoId)
  460. noDataIdMap[edbInfoId] = edbInfoId
  461. }
  462. findDataList = append(findDataList, findDataValueTmp)
  463. yDataMap[index] = findDataValueTmp
  464. xEdbInfoIdList = append(xEdbInfoIdList, edbInfoId)
  465. edbIdList = append(edbIdList, edbInfoId)
  466. index += 1
  467. }
  468. mList := make([]int, 0) // 间隔月份
  469. tmpNameMap := make(map[int]string)
  470. dateList := dateListMap[findDateTime.Format(utils.FormatDate)]
  471. // 最小开始的n值
  472. //minN := (findDateTime.Year()-earliestDateTime.Year())*12 + int(findDateTime.Month()-earliestDateTime.Month())
  473. for _, date := range dateList {
  474. currDate, _ := time.ParseInLocation(utils.FormatYearMonthDate, date, time.Local)
  475. // 如果当前的n值小于最小开始的n值,那么就不处理
  476. //if n < minN {
  477. // continue
  478. //}
  479. //findDateTime
  480. // 获取当前日期相对开始日期的期数
  481. tmpN := (currDate.Year()-realDateTime.Year())*12 + int(currDate.Month()-realDateTime.Month())
  482. if tmpN <= 0 {
  483. fmt.Println("realDateTime跳出循环",realDateTime,"tmpN", tmpN, "currDate", currDate, "realDateTime", realDateTime)
  484. continue
  485. }
  486. // 如果期数大于最大期数,那么就退出当前匹配
  487. if tmpN >= maxN {
  488. fmt.Println("realDateTime跳出循环",realDateTime,"tmpN >= maxN",tmpN, "maxN", maxN)
  489. break
  490. }
  491. zlAndChildEdbId := make(map[int]int)
  492. childFutureGoodEdbInfoIdList := make([]int, 0)
  493. for zlFutureGoodEdbInfoId, futureGoodEdbInfoListMap := range futureGoodEdbInfoAllMap {
  494. futureGoodEdbInfoList := futureGoodEdbInfoListMap[findDateTime.Format(utils.FormatDate)]
  495. // 判断是否特殊合约
  496. if childFutureGoodEdbInfoIdMap, ok := specialFutureGoodEdbInfoMap[zlFutureGoodEdbInfoId]; ok {
  497. if childFutureGoodEdbInfo, ok2 := childFutureGoodEdbInfoIdMap[tmpN]; ok2 {
  498. childFutureGoodEdbInfoIdList = append(childFutureGoodEdbInfoIdList, childFutureGoodEdbInfo.FutureGoodEdbInfoId)
  499. zlAndChildEdbId[zlFutureGoodEdbInfoId] = childFutureGoodEdbInfo.FutureGoodEdbInfoId
  500. }
  501. } else {
  502. if childFutureGoodEdbInfo, ok2 := futureGoodEdbInfoList[date]; ok2 {
  503. childFutureGoodEdbInfoIdList = append(childFutureGoodEdbInfoIdList, childFutureGoodEdbInfo.FutureGoodEdbInfoId)
  504. zlAndChildEdbId[zlFutureGoodEdbInfoId] = childFutureGoodEdbInfo.FutureGoodEdbInfoId
  505. }
  506. }
  507. }
  508. // 合约不全,不参与计算
  509. //if len(childFutureGoodEdbInfoIdList) != lenZlFutureGoodEdbInfo {
  510. // continue
  511. //}
  512. calculateMap := make(map[int]float64)
  513. for _, childFutureGoodEdbInfoId := range childFutureGoodEdbInfoIdList {
  514. fmt.Println("查找childFutureGoodEdbInfoId", childFutureGoodEdbInfoId,"日期为", realDateTime.Format(utils.FormatDate), "的值")
  515. tmpFindDataValue, tmpIsFind := edbDataMap[childFutureGoodEdbInfoId][realDateTime.Format(utils.FormatDate)]
  516. if tmpIsFind && tmpFindDataValue != 0 {
  517. calculateMap[childFutureGoodEdbInfoId] = tmpFindDataValue
  518. fmt.Println("已找到tmpFindDataValue", tmpFindDataValue, "tmpIsFind", tmpIsFind)
  519. } else {
  520. fmt.Println("未找到tmpFindDataValue", tmpFindDataValue, "tmpIsFind", tmpIsFind)
  521. }
  522. }
  523. // 合约的数据不全,不参与计算
  524. //if len(calculateMap) != lenZlFutureGoodEdbInfo {
  525. // continue
  526. //}
  527. newTagEdbIdMap := make(map[string]int)
  528. for tag, zlEdbId := range tagEdbIdMap {
  529. if tag == "A" {
  530. nameTmp := strings.Split(futureGoodEdbInfoAllMap[zlEdbId][findDateTime.Format(utils.FormatDate)][date].FutureGoodEdbName, "(")
  531. nameTmpEn := strings.Split(futureGoodEdbInfoAllMap[zlEdbId][findDateTime.Format(utils.FormatDate)][date].FutureGoodEdbNameEn, "(")
  532. if len(nameTmp) > 1 && len(nameTmpEn) > 1 {
  533. nameTmp[1] = strings.Trim(nameTmp[1], ")")
  534. nameTmpEn[1] = strings.Trim(nameTmpEn[1], ")")
  535. tmpNameMap[tmpN+1] = nameTmp[1] + "-" + nameTmpEn[1]
  536. }
  537. }
  538. newTagEdbIdMap[tag] = zlAndChildEdbId[zlEdbId]
  539. }
  540. //, formulaStr string, tagEdbIdMap map[string]int
  541. formulaFormStr := ReplaceFormula(newTagEdbIdMap, calculateMap, formulaStr)
  542. //计算公式异常,那么就移除该指标
  543. if formulaFormStr == `` {
  544. //removeDateList = append(removeDateList, sk)
  545. fmt.Println("异常了")
  546. continue
  547. }
  548. calVal, e := engine.ParseAndExec(formulaFormStr)
  549. //calVal, err := calResult.Float64()
  550. if e != nil {
  551. err = errors.New("计算失败:获取计算值失败 Err:" + e.Error() + ";formulaStr:" + formulaFormStr)
  552. utils.FileLog.Info("计算失败:获取计算值失败 Err:" + e.Error() + ";formulaStr:" + formulaFormStr)
  553. }
  554. //yDataMap[n] = calVal
  555. //xEdbInfoIdList = append(xEdbInfoIdList, n)
  556. calVal, _ = decimal.NewFromFloat(calVal).Round(4).Float64()
  557. yDataMap[tmpN] = calVal
  558. xEdbInfoIdList = append(xEdbInfoIdList, tmpN)
  559. findDataList = append(findDataList, calVal)
  560. }
  561. yName := barChartInfoDate.Name
  562. yNameEn := barChartInfoDate.Name
  563. if yName == `` {
  564. if barChartInfoDate.Type == 2 {
  565. yName = strconv.Itoa(barChartInfoDate.Value) + "天前"
  566. if barChartInfoDate.Value == 1 {
  567. yNameEn = strconv.Itoa(barChartInfoDate.Value) + "day ago"
  568. } else {
  569. yNameEn = strconv.Itoa(barChartInfoDate.Value) + " days ago"
  570. }
  571. } else {
  572. yName = maxDate.Format(utils.FormatDate)
  573. yNameEn = maxDate.Format(utils.FormatDate)
  574. }
  575. }
  576. yDate := "0000-00-00"
  577. if !maxDate.IsZero() {
  578. yDate = maxDate.Format(utils.FormatDate)
  579. }
  580. {
  581. hasDataIndexList := make([]int, 0)
  582. for dataK, edbInfoId := range xEdbInfoIdList {
  583. if _, ok := noDataIdMap[edbInfoId]; !ok { // 如果是没有数据的指标id
  584. hasDataIndexList = append(hasDataIndexList, dataK)
  585. }
  586. }
  587. lenHasDataIndex := len(hasDataIndexList)
  588. if lenHasDataIndex > 0 {
  589. for lenHasDataI := 1; lenHasDataI < lenHasDataIndex; lenHasDataI++ {
  590. perK := hasDataIndexList[lenHasDataI-1] //上一个有数据的指标下标
  591. currK := hasDataIndexList[lenHasDataI] //当前有数据的指标下标
  592. preVal := findDataList[perK] //上一个有数据的坐标的值
  593. currVal := findDataList[currK] //当前有数据的指标的值
  594. // 环差值
  595. hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(currK - perK)))
  596. var tmpI int64
  597. // 将两个中间的数据做平均值补全
  598. for hcI := perK + 1; hcI < currK; hcI++ {
  599. tmpI++
  600. findDataList[hcI], _ = decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(tmpI))).RoundCeil(4).Float64()
  601. }
  602. }
  603. }
  604. }
  605. futureGoodNameMap[tmpk] = tmpNameMap
  606. yDataList = append(yDataList, YData{
  607. Date: yDate,
  608. ConfigDate: realDateTime,
  609. Value: findDataList,
  610. NoDataEdbList: noDataIdList,
  611. XEdbInfoIdList: xEdbInfoIdList,
  612. Color: barChartInfoDate.Color,
  613. Name: yName,
  614. NameEn: yNameEn,
  615. EdbValMap: yDataMap,
  616. M: mList,
  617. })
  618. }
  619. return
  620. }
  621. // getFutureGoodEdbInfoList 获取适用的指标列表
  622. func getProfitFutureGoodEdbInfoList(earliestDateTime time.Time, zlFutureGoodEdbInfo *future_good.FutureGoodEdbInfo, tmpFutureGoodEdbInfoList []*future_good.FutureGoodEdbInfo, isAllChina bool, monthNum int) (futureGoodEdbInfoDateMap map[string]*future_good.FutureGoodEdbInfo, newMaxN int, err error) {
  623. maxN := 36 //最大36期合约
  624. futureGoodEdbInfoList := make([]*future_good.FutureGoodEdbInfo, 0)
  625. futureGoodEdbInfoDateMap = make(map[string]*future_good.FutureGoodEdbInfo)
  626. earliestDateTime = time.Date(earliestDateTime.Year(), earliestDateTime.Month(), 1, 0, 0, 0, 0, time.Local)
  627. if zlFutureGoodEdbInfo.RegionType == "国内" {
  628. startMonth := int(earliestDateTime.Month())
  629. if startMonth == 1 {
  630. futureGoodEdbInfoList = tmpFutureGoodEdbInfoList
  631. } else {
  632. // 因为是下标,所以对应想下标是需要-1的
  633. index := startMonth - 1
  634. futureGoodEdbInfoList = tmpFutureGoodEdbInfoList[index:]
  635. futureGoodEdbInfoList = append(futureGoodEdbInfoList, tmpFutureGoodEdbInfoList[:index]...)
  636. }
  637. lenFutureGoodEdbInfoList := len(futureGoodEdbInfoList)
  638. //futureGoodEdbInfoList
  639. //if isAllChina {
  640. //}
  641. // 如果全是国内指标,那么只需要拼上多出的几期合约即可
  642. maxN = lenFutureGoodEdbInfoList + monthNum
  643. for i := 1; i < maxN; i++ {
  644. k := i % lenFutureGoodEdbInfoList
  645. futureGoodEdbInfoDateMap[earliestDateTime.AddDate(0, i, 0).Format(utils.FormatYearMonthDate)] = futureGoodEdbInfoList[k]
  646. }
  647. //需求池604,只要是国内合约,最大必须是12期
  648. newMaxN = 12
  649. return
  650. }
  651. for _, v := range tmpFutureGoodEdbInfoList {
  652. //海外的连续日期,目前
  653. if v.FutureGoodEdbType == 2 {
  654. if v.Month <= maxN {
  655. futureGoodEdbInfoDateMap[earliestDateTime.AddDate(0, v.Month, 0).Format(utils.FormatYearMonthDate)] = v
  656. if v.Month > newMaxN {
  657. newMaxN = v.Month
  658. }
  659. }
  660. continue
  661. }
  662. if v.Year < earliestDateTime.Year() {
  663. continue
  664. }
  665. // 小于等于当前年,那么就肯定是ok的
  666. if v.Year == earliestDateTime.Year() && v.Month <= int(earliestDateTime.Month()) {
  667. continue
  668. }
  669. subYear := v.Year - earliestDateTime.Year()
  670. subMonth := v.Month - int(earliestDateTime.Month())
  671. // 如果(当前年-最新日期的年份) * 12个月 + (当前月-最新日期的月份) 小于总月份
  672. tmpN := subYear*12 + subMonth
  673. if tmpN < maxN {
  674. tmpDateTime := time.Date(v.Year, time.Month(v.Month), 0, 0, 0, 0, 0, time.Local)
  675. futureGoodEdbInfoDateMap[tmpDateTime.Format(utils.FormatYearMonthDate)] = v
  676. if tmpN > newMaxN {
  677. newMaxN = tmpN
  678. }
  679. continue
  680. }
  681. }
  682. return
  683. }
  684. func GetProfitFutureGoodEdbInfoList(earliestDateTimeList []time.Time, zlFutureGoodEdbInfo *future_good.FutureGoodEdbInfo, tmpFutureGoodEdbInfoList []*future_good.FutureGoodEdbInfo, isAllChina bool, monthNumMap map[string]int) (futureGoodEdbInfoDateAllMap map[string]map[string]*future_good.FutureGoodEdbInfo, newMaxN int, err error) {
  685. futureGoodEdbInfoDateAllMap = make(map[string]map[string]*future_good.FutureGoodEdbInfo)
  686. for _, earliestDateTime := range earliestDateTimeList {
  687. futureGoodEdbInfoDateMap := make(map[string]*future_good.FutureGoodEdbInfo)
  688. var newMaxNTmp int
  689. futureGoodEdbInfoDateMap, newMaxNTmp, err = getProfitFutureGoodEdbInfoList(earliestDateTime, zlFutureGoodEdbInfo, tmpFutureGoodEdbInfoList, isAllChina, monthNumMap[earliestDateTime.Format(utils.FormatYearMonthDate)])
  690. if err != nil {
  691. return
  692. }
  693. if newMaxN < newMaxNTmp {
  694. newMaxN = newMaxNTmp
  695. }
  696. futureGoodEdbInfoDateAllMap[earliestDateTime.Format(utils.FormatDate)] = futureGoodEdbInfoDateMap
  697. }
  698. return
  699. }
  700. // handleProfitResultData 处理成最终的结果数据
  701. func handleProfitResultData(xDataListInit []XData, futureNameMap map[int]map[int]string, yDataList []YData, earliestDateTime time.Time, allEdbInfoIds []int) (xDataList []XData, newYDataList []YData, err error) {
  702. newYDataList = yDataList
  703. xDataList = xDataListInit
  704. nMap := make(map[int]int)
  705. nList := make([]int, 0)
  706. nListEdbMap := make(map[int]struct{})
  707. for _, v := range yDataList {
  708. for _, n := range v.XEdbInfoIdList {
  709. if utils.InArrayByInt(allEdbInfoIds, n) {
  710. if _, ok := nListEdbMap[n]; !ok {
  711. nList = append(nList, n)
  712. nListEdbMap[n] = struct{}{}
  713. }
  714. } else {
  715. nMap[n] = n
  716. }
  717. }
  718. }
  719. // 找出所有的N值,并进行正序排列
  720. nListTmp := make([]int, 0)
  721. for _, n := range nMap {
  722. nListTmp = append(nListTmp, n)
  723. }
  724. sort.Slice(nListTmp, func(i, j int) bool {
  725. return nListTmp[i] < nListTmp[j]
  726. })
  727. nList = append(nList, nListTmp...)
  728. for _, n := range nList {
  729. if utils.InArrayByInt(allEdbInfoIds, n) {
  730. continue
  731. }
  732. xDataList = append(xDataList, XData{
  733. Name: fmt.Sprint("M+", n),
  734. NameEn: fmt.Sprint("M+", n),
  735. })
  736. }
  737. for yIndex, yData := range yDataList {
  738. newYDataList[yIndex].XEdbInfoIdList = []int{}
  739. newYDataList[yIndex].Value = []float64{}
  740. tmpNList := nList
  741. xEdbInfoIdList := yData.XEdbInfoIdList
  742. valIndex := 0
  743. needNum := 0
  744. for _, n := range tmpNList {
  745. if len(xEdbInfoIdList) > 0 {
  746. currN := xEdbInfoIdList[0]
  747. // 当前距离最早的日期相差的N数
  748. if n == currN { // todo 改成所有的基础现货指标
  749. if needNum > 0 {
  750. currVal := yData.Value[valIndex]
  751. preVal := yData.Value[valIndex-1]
  752. hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(needNum + 1)))
  753. for tmpNum := 0; tmpNum < needNum; tmpNum++ {
  754. newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, 0)
  755. // 赋值平均值
  756. tmpVal, _ := decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(int64(tmpNum + 1)))).RoundCeil(4).Float64()
  757. newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, tmpVal)
  758. }
  759. }
  760. if utils.InArrayByInt(allEdbInfoIds, currN) {
  761. newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, currN)
  762. } else {
  763. newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, currN+1)
  764. }
  765. newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[valIndex])
  766. valIndex++
  767. needNum = 0
  768. if len(xEdbInfoIdList) > 0 {
  769. xEdbInfoIdList = xEdbInfoIdList[1:]
  770. }
  771. } else {
  772. needNum++
  773. }
  774. }
  775. }
  776. }
  777. maxI := 0
  778. for _, yData := range newYDataList {
  779. lenEdb := len(yData.XEdbInfoIdList)
  780. for i := 0; i < lenEdb; i++ {
  781. if yData.XEdbInfoIdList[i] != 0 && !utils.InArrayByInt(yData.NoDataEdbList, yData.XEdbInfoIdList[i]) {
  782. if maxI < i {
  783. maxI = i
  784. }
  785. }
  786. }
  787. }
  788. earliestDateTime = time.Date(earliestDateTime.Year(), earliestDateTime.Month(), 1, 0, 0, 0, 0, time.Local)
  789. xDataList = xDataList[0 : maxI+1]
  790. for yIndex, yData := range newYDataList {
  791. if len(yData.XEdbInfoIdList) > maxI+1 {
  792. newYDataList[yIndex].XEdbInfoIdList = yData.XEdbInfoIdList[0 : maxI+1]
  793. }
  794. if len(yData.Value) > maxI+1 {
  795. newYDataList[yIndex].Value = yData.Value[0 : maxI+1]
  796. }
  797. nameList := make([]string, 0)
  798. enNameList := make([]string, 0)
  799. for k1, n := range newYDataList[yIndex].XEdbInfoIdList {
  800. if utils.InArrayByInt(allEdbInfoIds, n) { // 现货价不处理
  801. tmpItem := xDataListInit[k1]
  802. nameList = append(nameList, tmpItem.Name)
  803. enNameList = append(enNameList, tmpItem.NameEn)
  804. continue
  805. }
  806. if n <= 0 {
  807. nameList = append(nameList, `无合约`)
  808. enNameList = append(enNameList, `no contract`)
  809. } else {
  810. nameTmp := futureNameMap[yIndex][n]
  811. nameTmpSlice := strings.Split(nameTmp, "-")
  812. nameList = append(nameList, nameTmpSlice[0])
  813. enNameList = append(enNameList, nameTmpSlice[1])
  814. }
  815. }
  816. newYDataList[yIndex].NameList = nameList
  817. newYDataList[yIndex].EnNameList = enNameList
  818. }
  819. return
  820. }
  821. func CheckFormula(formula string) map[string]string {
  822. mathFormula := []string{"MAX", "MIN", "ABS", "ACOS", "ASIN", "CEIL", "MOD", "POW", "ROUND", "SIGN", "SIN", "TAN", "LOG10", "LOG2", "LOG", "LN"}
  823. str := strings.ToUpper(formula)
  824. for _, v := range mathFormula {
  825. str = strings.Replace(str, v, "", -1)
  826. }
  827. str = strings.Replace(str, "(", "", -1)
  828. str = strings.Replace(str, ")", "", -1)
  829. byteMap := make(map[string]string)
  830. for i := 0; i < len(str); i++ {
  831. byteInt := str[i]
  832. if byteInt >= 65 && byteInt <= 90 {
  833. byteStr := string(byteInt)
  834. if _, ok := byteMap[byteStr]; !ok {
  835. byteMap[byteStr] = byteStr
  836. }
  837. }
  838. }
  839. return byteMap
  840. }
  841. func ReplaceFormula(tagEdbIdMap map[string]int, valArr map[int]float64, formulaStr string) string {
  842. funMap := GetFormulaMap()
  843. for k, v := range funMap {
  844. formulaStr = strings.Replace(formulaStr, k, v, -1)
  845. }
  846. replaceCount := 0
  847. for tag, edbInfoId := range tagEdbIdMap {
  848. if val, valOk := valArr[edbInfoId]; valOk { //值存在
  849. dvStr := fmt.Sprintf("%v", val)
  850. formulaStr = strings.Replace(formulaStr, tag, dvStr, -1)
  851. replaceCount++
  852. }
  853. }
  854. for k, v := range funMap {
  855. formulaStr = strings.Replace(formulaStr, v, k, -1)
  856. }
  857. fmt.Println(formulaStr)
  858. if replaceCount == len(tagEdbIdMap) {
  859. return formulaStr
  860. } else {
  861. return ""
  862. }
  863. }
  864. func GetFormulaMap() map[string]string {
  865. funMap := make(map[string]string)
  866. funMap["MAX"] = "[@@]"
  867. funMap["MIN"] = "[@!]"
  868. funMap["ABS"] = "[@#]"
  869. funMap["CEIL"] = "[@$]"
  870. funMap["COS"] = "[@%]"
  871. funMap["FLOOR"] = "[@^]"
  872. funMap["MOD"] = "[@&]"
  873. funMap["POW"] = "[@*]"
  874. funMap["ROUND"] = "[@(]"
  875. return funMap
  876. }
  877. // GetNeedDateData 获取合约内需要的日期数据
  878. func GetNeedDateData(needDateTime time.Time, dataList []*models.EdbDataList, edbDataMap map[string]float64, allEdbDataMap map[int]map[string]float64) (findDateTime time.Time, findDataValue float64, isFind bool, err error) {
  879. //dataList := edbDataListMap[edbInfoId] //指标的所有数据值
  880. if len(dataList) <= 0 {
  881. // 没有数据的指标id
  882. return
  883. }
  884. //最早的日期
  885. minDateTime, err := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  886. if err != nil {
  887. return
  888. }
  889. // 该日期存在数据的期货指标的最小数量,目前是现货和期货各1个,总共2个
  890. maxCount := 1
  891. for tmpDateTime := needDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  892. tmpDate := tmpDateTime.Format(utils.FormatDate)
  893. tmpValue, ok := edbDataMap[tmpDate]
  894. if !ok {
  895. continue
  896. }
  897. // 该日期存在数据的指标数量
  898. count := 0
  899. for _, currEdbDataMap := range allEdbDataMap {
  900. _, tmpIsFind := currEdbDataMap[tmpDate]
  901. if tmpIsFind {
  902. count++
  903. if count >= maxCount {
  904. continue
  905. }
  906. }
  907. }
  908. // 该日期存在数据的期货指标数量小于2个,那么要继续往前找
  909. if count < maxCount {
  910. continue
  911. }
  912. //如果能找到数据,那么就返回
  913. // 数据为0,也直接返回,做无值处理
  914. if tmpValue == 0 {
  915. return
  916. }
  917. findDateTime, _ = time.ParseInLocation(utils.FormatDate, tmpDate, time.Local)
  918. findDataValue = tmpValue
  919. isFind = true
  920. return
  921. }
  922. return
  923. }