profit_chart_info.go 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  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. hasChina := false // 是否包含国内的期货合约
  277. for _, v := range zlFutureGoodEdbInfoList {
  278. if v.RegionType == "国内" {
  279. hasChina = true
  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. // 需求池604,只要包含了国内合约,最大必须是12期
  336. if hasChina {
  337. maxN = 12
  338. }
  339. // 找出所有的N值,并进行正序排列
  340. dateListMap := make(map[string][]string, 0)
  341. for key, dateList := range nAllMap {
  342. sort.Slice(dateList, func(i, j int) bool {
  343. return dateList[i] < dateList[j]
  344. })
  345. dateListMap[key] = dateList
  346. }
  347. var reqEdbInfoIds []int
  348. for _, v := range edbInfoList {
  349. reqEdbInfoIds = append(reqEdbInfoIds, v.EdbInfoId)
  350. tmp := XData{
  351. Name: v.EdbName,
  352. NameEn: v.EdbNameEn,
  353. }
  354. xDataList = append(xDataList, tmp)
  355. }
  356. var edbIdList []int
  357. futureGoodNameMap := make(map[int]map[int]string)
  358. edbIdList, yDataList, futureGoodNameMap, err = ProfitChartChartData(baseEdbInfo, baseDataListMap, futureGoodEdbInfoDateAllMap, futureGoodDataListMap, chartInfoDateList, baseEdbInfo.EndDate, specialFutureGoodEdbInfoMap, formulaStr, tagEdbIdMap, dateListMap, maxN, reqEdbInfoIds)
  359. // todo 最后处理数据
  360. tmpXDataList, newYDataList, err := handleProfitResultData(xDataList, futureGoodNameMap, yDataList, earliestDateTime, edbIdList)
  361. if err != nil {
  362. return
  363. }
  364. if len(reqXDataList) == 0 {
  365. xDataList = tmpXDataList
  366. } else {
  367. xDataList = reqXDataList
  368. }
  369. yDataList = newYDataList
  370. return
  371. }
  372. // ProfitChartChartData 获取数据
  373. 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) {
  374. // 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
  375. //earliestDateTime time.Time
  376. // ETA指标数据
  377. allBaseEdbDateDataMap := make(map[int]map[string]float64)
  378. for edbInfoId, baseDataList := range baseDataListMap {
  379. baseEdbDateData := make(map[string]float64)
  380. for _, edbData := range baseDataList {
  381. baseEdbDateData[edbData.DataTime] = edbData.Value
  382. }
  383. allBaseEdbDateDataMap[edbInfoId] = baseEdbDateData
  384. }
  385. // 商品指标数据
  386. edbDataMap := make(map[int]map[string]float64)
  387. for edbInfoId, edbDataList := range futureGoodEdbDataListMap {
  388. edbDateData := make(map[string]float64)
  389. for _, edbData := range edbDataList {
  390. edbDateData[edbData.DataTime] = edbData.Value
  391. }
  392. edbDataMap[edbInfoId] = edbDateData
  393. }
  394. latestDateTime, _ := time.ParseInLocation(utils.FormatDate, latestDate, time.Local)
  395. yDataList = make([]YData, 0) //y轴的数据列表
  396. // 将计算公式中的字母转大写
  397. formulaStr = strings.ToUpper(formulaStr)
  398. futureGoodNameMap = make(map[int]map[int]string)
  399. for tmpk, barChartInfoDate := range chartInfoDateList {
  400. yDataMap := make(map[int]float64)
  401. var maxDate time.Time
  402. var findDateTime time.Time
  403. switch barChartInfoDate.Type {
  404. case 1: //最新值
  405. findDateTime = latestDateTime
  406. case 2: //近期几天
  407. findDateTime = latestDateTime.AddDate(0, 0, -barChartInfoDate.Value)
  408. case 3: // 固定日期
  409. //寻找固定日期的数据
  410. tmpFindDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
  411. if tmpErr != nil {
  412. err = tmpErr
  413. return
  414. }
  415. findDateTime = tmpFindDateTime
  416. default:
  417. err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
  418. return
  419. }
  420. if findDateTime.IsZero() {
  421. err = errors.New("错误的日期")
  422. return
  423. }
  424. findDataList := make([]float64, 0) // 当前日期的数据值
  425. noDataIdList := make([]int, 0) // 没有数据的指标id
  426. noDataIdMap := make(map[int]int, 0) // 没有数据的指标map
  427. xEdbInfoIdList := make([]int, 0) // 当前数据的指标id列表
  428. // 现货指标
  429. index := 0
  430. var realDateTime time.Time
  431. // 现货指标
  432. baseEdbDateData, ok := allBaseEdbDateDataMap[baseEdbInfo.EdbInfoId]
  433. if !ok {
  434. err = fmt.Errorf("指标id: %d 没有数据", baseEdbInfo.EdbInfoId)
  435. return
  436. }
  437. realDateTime, findDataValue, isFind, tmpErr := GetNeedDateData(findDateTime, baseDataListMap[baseEdbInfo.EdbInfoId], baseEdbDateData, edbDataMap)
  438. if tmpErr != nil {
  439. err = tmpErr
  440. return
  441. }
  442. if isFind {
  443. maxDate = realDateTime
  444. }
  445. fmt.Println("findDateTime", findDateTime, "realDateTime", realDateTime, "findDataValue", findDataValue, "isFind", isFind)
  446. edbIdList = make([]int, 0) //普通指标ID
  447. for _, edbInfoId := range reqEdbInfoIds {
  448. if edbInfoId == baseEdbInfo.EdbInfoId {
  449. findDataList = append(findDataList, findDataValue)
  450. yDataMap[index] = findDataValue
  451. xEdbInfoIdList = append(xEdbInfoIdList, edbInfoId)
  452. edbIdList = append(edbIdList, edbInfoId)
  453. index += 1
  454. continue
  455. }
  456. baseEdbDateDataTmp, ok := allBaseEdbDateDataMap[edbInfoId]
  457. if !ok {
  458. err = fmt.Errorf("指标id: %d 没有数据", edbInfoId)
  459. return
  460. }
  461. findDataValueTmp, isFindTmp := baseEdbDateDataTmp[realDateTime.Format(utils.FormatDate)]
  462. if !isFindTmp {
  463. noDataIdList = append(noDataIdList, edbInfoId)
  464. noDataIdMap[edbInfoId] = edbInfoId
  465. }
  466. findDataList = append(findDataList, findDataValueTmp)
  467. yDataMap[index] = findDataValueTmp
  468. xEdbInfoIdList = append(xEdbInfoIdList, edbInfoId)
  469. edbIdList = append(edbIdList, edbInfoId)
  470. index += 1
  471. }
  472. mList := make([]int, 0) // 间隔月份
  473. tmpNameMap := make(map[int]string)
  474. dateList := dateListMap[findDateTime.Format(utils.FormatDate)]
  475. // 最小开始的n值
  476. //minN := (findDateTime.Year()-earliestDateTime.Year())*12 + int(findDateTime.Month()-earliestDateTime.Month())
  477. for _, date := range dateList {
  478. currDate, _ := time.ParseInLocation(utils.FormatYearMonthDate, date, time.Local)
  479. // 如果当前的n值小于最小开始的n值,那么就不处理
  480. //if n < minN {
  481. // continue
  482. //}
  483. //findDateTime
  484. // 获取当前日期相对开始日期的期数
  485. tmpN := (currDate.Year()-realDateTime.Year())*12 + int(currDate.Month()-realDateTime.Month())
  486. if tmpN <= 0 {
  487. fmt.Println("realDateTime跳出循环",realDateTime,"tmpN", tmpN, "currDate", currDate, "realDateTime", realDateTime)
  488. continue
  489. }
  490. // 如果期数大于最大期数,那么就退出当前匹配
  491. if tmpN >= maxN {
  492. fmt.Println("realDateTime跳出循环",realDateTime,"tmpN >= maxN",tmpN, "maxN", maxN)
  493. break
  494. }
  495. zlAndChildEdbId := make(map[int]int)
  496. childFutureGoodEdbInfoIdList := make([]int, 0)
  497. for zlFutureGoodEdbInfoId, futureGoodEdbInfoListMap := range futureGoodEdbInfoAllMap {
  498. futureGoodEdbInfoList := futureGoodEdbInfoListMap[findDateTime.Format(utils.FormatDate)]
  499. // 判断是否特殊合约
  500. if childFutureGoodEdbInfoIdMap, ok := specialFutureGoodEdbInfoMap[zlFutureGoodEdbInfoId]; ok {
  501. if childFutureGoodEdbInfo, ok2 := childFutureGoodEdbInfoIdMap[tmpN]; ok2 {
  502. childFutureGoodEdbInfoIdList = append(childFutureGoodEdbInfoIdList, childFutureGoodEdbInfo.FutureGoodEdbInfoId)
  503. zlAndChildEdbId[zlFutureGoodEdbInfoId] = childFutureGoodEdbInfo.FutureGoodEdbInfoId
  504. }
  505. } else {
  506. if childFutureGoodEdbInfo, ok2 := futureGoodEdbInfoList[date]; ok2 {
  507. childFutureGoodEdbInfoIdList = append(childFutureGoodEdbInfoIdList, childFutureGoodEdbInfo.FutureGoodEdbInfoId)
  508. zlAndChildEdbId[zlFutureGoodEdbInfoId] = childFutureGoodEdbInfo.FutureGoodEdbInfoId
  509. }
  510. }
  511. }
  512. // 合约不全,不参与计算
  513. //if len(childFutureGoodEdbInfoIdList) != lenZlFutureGoodEdbInfo {
  514. // continue
  515. //}
  516. calculateMap := make(map[int]float64)
  517. for _, childFutureGoodEdbInfoId := range childFutureGoodEdbInfoIdList {
  518. fmt.Println("查找childFutureGoodEdbInfoId", childFutureGoodEdbInfoId,"日期为", realDateTime.Format(utils.FormatDate), "的值")
  519. tmpFindDataValue, tmpIsFind := edbDataMap[childFutureGoodEdbInfoId][realDateTime.Format(utils.FormatDate)]
  520. if tmpIsFind && tmpFindDataValue != 0 {
  521. calculateMap[childFutureGoodEdbInfoId] = tmpFindDataValue
  522. fmt.Println("已找到tmpFindDataValue", tmpFindDataValue, "tmpIsFind", tmpIsFind)
  523. } else {
  524. fmt.Println("未找到tmpFindDataValue", tmpFindDataValue, "tmpIsFind", tmpIsFind)
  525. }
  526. }
  527. // 合约的数据不全,不参与计算
  528. //if len(calculateMap) != lenZlFutureGoodEdbInfo {
  529. // continue
  530. //}
  531. newTagEdbIdMap := make(map[string]int)
  532. for tag, zlEdbId := range tagEdbIdMap {
  533. if tag == "A" {
  534. nameTmp := strings.Split(futureGoodEdbInfoAllMap[zlEdbId][findDateTime.Format(utils.FormatDate)][date].FutureGoodEdbName, "(")
  535. nameTmpEn := strings.Split(futureGoodEdbInfoAllMap[zlEdbId][findDateTime.Format(utils.FormatDate)][date].FutureGoodEdbNameEn, "(")
  536. if len(nameTmp) > 1 && len(nameTmpEn) > 1 {
  537. nameTmp[1] = strings.Trim(nameTmp[1], ")")
  538. nameTmpEn[1] = strings.Trim(nameTmpEn[1], ")")
  539. tmpNameMap[tmpN+1] = nameTmp[1] + "-" + nameTmpEn[1]
  540. }
  541. }
  542. newTagEdbIdMap[tag] = zlAndChildEdbId[zlEdbId]
  543. }
  544. //, formulaStr string, tagEdbIdMap map[string]int
  545. formulaFormStr := ReplaceFormula(newTagEdbIdMap, calculateMap, formulaStr)
  546. //计算公式异常,那么就移除该指标
  547. if formulaFormStr == `` {
  548. //removeDateList = append(removeDateList, sk)
  549. fmt.Println("异常了")
  550. continue
  551. }
  552. calVal, e := engine.ParseAndExec(formulaFormStr)
  553. //calVal, err := calResult.Float64()
  554. if e != nil {
  555. err = errors.New("计算失败:获取计算值失败 Err:" + e.Error() + ";formulaStr:" + formulaFormStr)
  556. utils.FileLog.Info("计算失败:获取计算值失败 Err:" + e.Error() + ";formulaStr:" + formulaFormStr)
  557. }
  558. //yDataMap[n] = calVal
  559. //xEdbInfoIdList = append(xEdbInfoIdList, n)
  560. calVal, _ = decimal.NewFromFloat(calVal).Round(utils.DataDigits).Float64()
  561. yDataMap[tmpN] = calVal
  562. xEdbInfoIdList = append(xEdbInfoIdList, tmpN)
  563. findDataList = append(findDataList, calVal)
  564. }
  565. yName := barChartInfoDate.Name
  566. yNameEn := barChartInfoDate.Name
  567. if yName == `` {
  568. if barChartInfoDate.Type == 2 {
  569. yName = strconv.Itoa(barChartInfoDate.Value) + "天前"
  570. if barChartInfoDate.Value == 1 {
  571. yNameEn = strconv.Itoa(barChartInfoDate.Value) + "day ago"
  572. } else {
  573. yNameEn = strconv.Itoa(barChartInfoDate.Value) + " days ago"
  574. }
  575. } else {
  576. yName = maxDate.Format(utils.FormatDate)
  577. yNameEn = maxDate.Format(utils.FormatDate)
  578. }
  579. }
  580. yDate := "0000-00-00"
  581. if !maxDate.IsZero() {
  582. yDate = maxDate.Format(utils.FormatDate)
  583. }
  584. {
  585. hasDataIndexList := make([]int, 0)
  586. for dataK, edbInfoId := range xEdbInfoIdList {
  587. if _, ok := noDataIdMap[edbInfoId]; !ok { // 如果是没有数据的指标id
  588. hasDataIndexList = append(hasDataIndexList, dataK)
  589. }
  590. }
  591. lenHasDataIndex := len(hasDataIndexList)
  592. if lenHasDataIndex > 0 {
  593. for lenHasDataI := 1; lenHasDataI < lenHasDataIndex; lenHasDataI++ {
  594. perK := hasDataIndexList[lenHasDataI-1] //上一个有数据的指标下标
  595. currK := hasDataIndexList[lenHasDataI] //当前有数据的指标下标
  596. preVal := findDataList[perK] //上一个有数据的坐标的值
  597. currVal := findDataList[currK] //当前有数据的指标的值
  598. // 环差值
  599. hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(currK - perK)))
  600. var tmpI int64
  601. // 将两个中间的数据做平均值补全
  602. for hcI := perK + 1; hcI < currK; hcI++ {
  603. tmpI++
  604. findDataList[hcI], _ = decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(tmpI))).RoundCeil(utils.DataDigits).Float64()
  605. }
  606. }
  607. }
  608. }
  609. futureGoodNameMap[tmpk] = tmpNameMap
  610. yDataList = append(yDataList, YData{
  611. Date: yDate,
  612. ConfigDate: realDateTime,
  613. Value: findDataList,
  614. NoDataEdbList: noDataIdList,
  615. XEdbInfoIdList: xEdbInfoIdList,
  616. Color: barChartInfoDate.Color,
  617. Name: yName,
  618. NameEn: yNameEn,
  619. EdbValMap: yDataMap,
  620. M: mList,
  621. })
  622. }
  623. return
  624. }
  625. // getFutureGoodEdbInfoList 获取适用的指标列表
  626. func getProfitFutureGoodEdbInfoList(earliestDateTime time.Time, zlFutureGoodEdbInfo *future_good.FutureGoodEdbInfo, tmpFutureGoodEdbInfoList []*future_good.FutureGoodEdbInfo, monthNum int) (futureGoodEdbInfoDateMap map[string]*future_good.FutureGoodEdbInfo, newMaxN int, err error) {
  627. maxN := 36 //最大36期合约
  628. futureGoodEdbInfoList := make([]*future_good.FutureGoodEdbInfo, 0)
  629. futureGoodEdbInfoDateMap = make(map[string]*future_good.FutureGoodEdbInfo)
  630. earliestDateTime = time.Date(earliestDateTime.Year(), earliestDateTime.Month(), 1, 0, 0, 0, 0, time.Local)
  631. if zlFutureGoodEdbInfo.RegionType == "国内" {
  632. startMonth := int(earliestDateTime.Month())
  633. if startMonth == 1 {
  634. futureGoodEdbInfoList = tmpFutureGoodEdbInfoList
  635. } else {
  636. // 因为是下标,所以对应想下标是需要-1的
  637. index := startMonth - 1
  638. futureGoodEdbInfoList = tmpFutureGoodEdbInfoList[index:]
  639. futureGoodEdbInfoList = append(futureGoodEdbInfoList, tmpFutureGoodEdbInfoList[:index]...)
  640. }
  641. lenFutureGoodEdbInfoList := len(futureGoodEdbInfoList)
  642. //futureGoodEdbInfoList
  643. //if isAllChina {
  644. //}
  645. // 如果全是国内指标,那么只需要拼上多出的几期合约即可
  646. maxN = lenFutureGoodEdbInfoList + monthNum
  647. for i := 1; i < maxN; i++ {
  648. k := i % lenFutureGoodEdbInfoList
  649. futureGoodEdbInfoDateMap[earliestDateTime.AddDate(0, i, 0).Format(utils.FormatYearMonthDate)] = futureGoodEdbInfoList[k]
  650. }
  651. //需求池604,只要是国内合约,最大必须是12期
  652. newMaxN = 12
  653. return
  654. }
  655. for _, v := range tmpFutureGoodEdbInfoList {
  656. //海外的连续日期,目前
  657. if v.FutureGoodEdbType == 2 {
  658. if v.Month <= maxN {
  659. futureGoodEdbInfoDateMap[earliestDateTime.AddDate(0, v.Month, 0).Format(utils.FormatYearMonthDate)] = v
  660. if v.Month > newMaxN {
  661. newMaxN = v.Month
  662. }
  663. }
  664. continue
  665. }
  666. if v.Year < earliestDateTime.Year() {
  667. continue
  668. }
  669. // 小于等于当前年,那么就肯定是ok的
  670. if v.Year == earliestDateTime.Year() && v.Month <= int(earliestDateTime.Month()) {
  671. continue
  672. }
  673. subYear := v.Year - earliestDateTime.Year()
  674. subMonth := v.Month - int(earliestDateTime.Month())
  675. // 如果(当前年-最新日期的年份) * 12个月 + (当前月-最新日期的月份) 小于总月份
  676. tmpN := subYear*12 + subMonth
  677. if tmpN < maxN {
  678. tmpDateTime := time.Date(v.Year, time.Month(v.Month), 0, 0, 0, 0, 0, time.Local)
  679. futureGoodEdbInfoDateMap[tmpDateTime.Format(utils.FormatYearMonthDate)] = v
  680. if tmpN > newMaxN {
  681. newMaxN = tmpN
  682. }
  683. continue
  684. }
  685. }
  686. return
  687. }
  688. 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) {
  689. futureGoodEdbInfoDateAllMap = make(map[string]map[string]*future_good.FutureGoodEdbInfo)
  690. for _, earliestDateTime := range earliestDateTimeList {
  691. futureGoodEdbInfoDateMap := make(map[string]*future_good.FutureGoodEdbInfo)
  692. var newMaxNTmp int
  693. futureGoodEdbInfoDateMap, newMaxNTmp, err = getProfitFutureGoodEdbInfoList(earliestDateTime, zlFutureGoodEdbInfo, tmpFutureGoodEdbInfoList, isAllChina, monthNumMap[earliestDateTime.Format(utils.FormatYearMonthDate)])
  694. if err != nil {
  695. return
  696. }
  697. if newMaxN < newMaxNTmp {
  698. newMaxN = newMaxNTmp
  699. }
  700. futureGoodEdbInfoDateAllMap[earliestDateTime.Format(utils.FormatDate)] = futureGoodEdbInfoDateMap
  701. }
  702. return
  703. }
  704. // handleProfitResultData 处理成最终的结果数据
  705. func handleProfitResultData(xDataListInit []XData, futureNameMap map[int]map[int]string, yDataList []YData, earliestDateTime time.Time, allEdbInfoIds []int) (xDataList []XData, newYDataList []YData, err error) {
  706. newYDataList = yDataList
  707. xDataList = xDataListInit
  708. nMap := make(map[int]int)
  709. nList := make([]int, 0)
  710. nListEdbMap := make(map[int]struct{})
  711. for _, v := range yDataList {
  712. for _, n := range v.XEdbInfoIdList {
  713. if utils.InArrayByInt(allEdbInfoIds, n) {
  714. if _, ok := nListEdbMap[n]; !ok {
  715. nList = append(nList, n)
  716. nListEdbMap[n] = struct{}{}
  717. }
  718. } else {
  719. nMap[n] = n
  720. }
  721. }
  722. }
  723. // 找出所有的N值,并进行正序排列
  724. nListTmp := make([]int, 0)
  725. for _, n := range nMap {
  726. nListTmp = append(nListTmp, n)
  727. }
  728. sort.Slice(nListTmp, func(i, j int) bool {
  729. return nListTmp[i] < nListTmp[j]
  730. })
  731. nList = append(nList, nListTmp...)
  732. for _, n := range nList {
  733. if utils.InArrayByInt(allEdbInfoIds, n) {
  734. continue
  735. }
  736. xDataList = append(xDataList, XData{
  737. Name: fmt.Sprint("M+", n),
  738. NameEn: fmt.Sprint("M+", n),
  739. })
  740. }
  741. for yIndex, yData := range yDataList {
  742. newYDataList[yIndex].XEdbInfoIdList = []int{}
  743. newYDataList[yIndex].Value = []float64{}
  744. tmpNList := nList
  745. xEdbInfoIdList := yData.XEdbInfoIdList
  746. valIndex := 0
  747. needNum := 0
  748. for _, n := range tmpNList {
  749. if len(xEdbInfoIdList) > 0 {
  750. currN := xEdbInfoIdList[0]
  751. // 当前距离最早的日期相差的N数
  752. if n == currN { // todo 改成所有的基础现货指标
  753. if needNum > 0 {
  754. currVal := yData.Value[valIndex]
  755. preVal := yData.Value[valIndex-1]
  756. hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(needNum + 1)))
  757. for tmpNum := 0; tmpNum < needNum; tmpNum++ {
  758. newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, 0)
  759. // 赋值平均值
  760. tmpVal, _ := decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(int64(tmpNum + 1)))).RoundCeil(utils.DataDigits).Float64()
  761. newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, tmpVal)
  762. }
  763. }
  764. if utils.InArrayByInt(allEdbInfoIds, currN) {
  765. newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, currN)
  766. } else {
  767. newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, currN+1)
  768. }
  769. newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[valIndex])
  770. valIndex++
  771. needNum = 0
  772. if len(xEdbInfoIdList) > 0 {
  773. xEdbInfoIdList = xEdbInfoIdList[1:]
  774. }
  775. } else {
  776. needNum++
  777. }
  778. }
  779. }
  780. }
  781. maxI := 0
  782. for _, yData := range newYDataList {
  783. lenEdb := len(yData.XEdbInfoIdList)
  784. for i := 0; i < lenEdb; i++ {
  785. if yData.XEdbInfoIdList[i] != 0 && !utils.InArrayByInt(yData.NoDataEdbList, yData.XEdbInfoIdList[i]) {
  786. if maxI < i {
  787. maxI = i
  788. }
  789. }
  790. }
  791. }
  792. earliestDateTime = time.Date(earliestDateTime.Year(), earliestDateTime.Month(), 1, 0, 0, 0, 0, time.Local)
  793. xDataList = xDataList[0 : maxI+1]
  794. for yIndex, yData := range newYDataList {
  795. if len(yData.XEdbInfoIdList) > maxI+1 {
  796. newYDataList[yIndex].XEdbInfoIdList = yData.XEdbInfoIdList[0 : maxI+1]
  797. }
  798. if len(yData.Value) > maxI+1 {
  799. newYDataList[yIndex].Value = yData.Value[0 : maxI+1]
  800. }
  801. nameList := make([]string, 0)
  802. enNameList := make([]string, 0)
  803. for k1, n := range newYDataList[yIndex].XEdbInfoIdList {
  804. if utils.InArrayByInt(allEdbInfoIds, n) { // 现货价不处理
  805. tmpItem := xDataListInit[k1]
  806. nameList = append(nameList, tmpItem.Name)
  807. enNameList = append(enNameList, tmpItem.NameEn)
  808. continue
  809. }
  810. if n <= 0 {
  811. nameList = append(nameList, `无合约`)
  812. enNameList = append(enNameList, `no contract`)
  813. } else {
  814. nameTmp := futureNameMap[yIndex][n]
  815. nameTmpSlice := strings.Split(nameTmp, "-")
  816. nameList = append(nameList, nameTmpSlice[0])
  817. enNameList = append(enNameList, nameTmpSlice[1])
  818. }
  819. }
  820. newYDataList[yIndex].NameList = nameList
  821. newYDataList[yIndex].EnNameList = enNameList
  822. }
  823. return
  824. }
  825. func CheckFormula(formula string) map[string]string {
  826. mathFormula := []string{"MAX", "MIN", "ABS", "ACOS", "ASIN", "CEIL", "MOD", "POW", "ROUND", "SIGN", "SIN", "TAN", "LOG10", "LOG2", "LOG", "LN"}
  827. str := strings.ToUpper(formula)
  828. for _, v := range mathFormula {
  829. str = strings.Replace(str, v, "", -1)
  830. }
  831. str = strings.Replace(str, "(", "", -1)
  832. str = strings.Replace(str, ")", "", -1)
  833. byteMap := make(map[string]string)
  834. for i := 0; i < len(str); i++ {
  835. byteInt := str[i]
  836. if byteInt >= 65 && byteInt <= 90 {
  837. byteStr := string(byteInt)
  838. if _, ok := byteMap[byteStr]; !ok {
  839. byteMap[byteStr] = byteStr
  840. }
  841. }
  842. }
  843. return byteMap
  844. }
  845. func ReplaceFormula(tagEdbIdMap map[string]int, valArr map[int]float64, formulaStr string) string {
  846. funMap := GetFormulaMap()
  847. for k, v := range funMap {
  848. formulaStr = strings.Replace(formulaStr, k, v, -1)
  849. }
  850. replaceCount := 0
  851. for tag, edbInfoId := range tagEdbIdMap {
  852. if val, valOk := valArr[edbInfoId]; valOk { //值存在
  853. dvStr := fmt.Sprintf("%v", val)
  854. formulaStr = strings.Replace(formulaStr, tag, dvStr, -1)
  855. replaceCount++
  856. }
  857. }
  858. for k, v := range funMap {
  859. formulaStr = strings.Replace(formulaStr, v, k, -1)
  860. }
  861. fmt.Println(formulaStr)
  862. if replaceCount == len(tagEdbIdMap) {
  863. return formulaStr
  864. } else {
  865. return ""
  866. }
  867. }
  868. func GetFormulaMap() map[string]string {
  869. funMap := make(map[string]string)
  870. funMap["MAX"] = "[@@]"
  871. funMap["MIN"] = "[@!]"
  872. funMap["ABS"] = "[@#]"
  873. funMap["CEIL"] = "[@$]"
  874. funMap["COS"] = "[@%]"
  875. funMap["FLOOR"] = "[@^]"
  876. funMap["MOD"] = "[@&]"
  877. funMap["POW"] = "[@*]"
  878. funMap["ROUND"] = "[@(]"
  879. return funMap
  880. }
  881. // GetNeedDateData 获取合约内需要的日期数据
  882. 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) {
  883. //dataList := edbDataListMap[edbInfoId] //指标的所有数据值
  884. if len(dataList) <= 0 {
  885. // 没有数据的指标id
  886. return
  887. }
  888. //最早的日期
  889. minDateTime, err := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  890. if err != nil {
  891. return
  892. }
  893. // 该日期存在数据的期货指标的最小数量,目前是现货和期货各1个,总共2个
  894. maxCount := 1
  895. for tmpDateTime := needDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
  896. tmpDate := tmpDateTime.Format(utils.FormatDate)
  897. tmpValue, ok := edbDataMap[tmpDate]
  898. if !ok {
  899. continue
  900. }
  901. // 该日期存在数据的指标数量
  902. count := 0
  903. for _, currEdbDataMap := range allEdbDataMap {
  904. _, tmpIsFind := currEdbDataMap[tmpDate]
  905. if tmpIsFind {
  906. count++
  907. if count >= maxCount {
  908. continue
  909. }
  910. }
  911. }
  912. // 该日期存在数据的期货指标数量小于2个,那么要继续往前找
  913. if count < maxCount {
  914. continue
  915. }
  916. //如果能找到数据,那么就返回
  917. // 数据为0,也直接返回,做无值处理
  918. if tmpValue == 0 {
  919. return
  920. }
  921. findDateTime, _ = time.ParseInLocation(utils.FormatDate, tmpDate, time.Local)
  922. findDataValue = tmpValue
  923. isFind = true
  924. return
  925. }
  926. return
  927. }