base_calculate.go 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726
  1. package models
  2. import (
  3. "errors"
  4. "eta/eta_index_lib/utils"
  5. "fmt"
  6. "github.com/shopspring/decimal"
  7. "strconv"
  8. "strings"
  9. "time"
  10. )
  11. // BaseCalculate
  12. // @Description: 基础的计算公式
  13. type BaseCalculate struct {
  14. DataList []*EdbInfoSearchData
  15. Frequency string `description:"需要转换的频度"`
  16. Formula interface{}
  17. Calendar string `description:"公历/农历"`
  18. MoveType int `description:"移动方式:1:领先(默认),2:滞后"`
  19. MoveFrequency string `description:"移动频度"`
  20. FromFrequency string `description:"来源的频度"`
  21. Source int `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
  22. }
  23. type BaseCalculateResp struct {
  24. DataMap map[string]float64
  25. DateList []string
  26. }
  27. // Ljzzy
  28. // @Description: 累计值转月
  29. // @author: Roc
  30. // @receiver obj
  31. // @datetime2023-11-02 18:05:19
  32. // @return dateDataMap map[string]float64
  33. // @return err error
  34. func (obj BaseCalculate) Ljzzy() (dateDataMap map[string]float64, err error, errMsg string) {
  35. dataList := obj.DataList // 升序
  36. // 数据处理
  37. yearMap := make(map[int]map[int]*EdbInfoSearchData)
  38. dataLen := len(dataList)
  39. for i := 0; i < dataLen; i++ {
  40. item := dataList[i]
  41. //日其中获取年
  42. itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
  43. if tmpErr != nil {
  44. err = tmpErr
  45. return
  46. }
  47. year := itemDate.Year()
  48. month := int(itemDate.Month())
  49. if monthMap, yok := yearMap[year]; yok {
  50. monthMap[month] = item
  51. yearMap[year] = monthMap
  52. } else {
  53. monthMap = make(map[int]*EdbInfoSearchData)
  54. monthMap[month] = item
  55. yearMap[year] = monthMap
  56. }
  57. }
  58. // 开始计算
  59. for yk, yv := range yearMap {
  60. _, oneMonthOk := yv[1]
  61. _, twoMonthOk := yv[2]
  62. if !oneMonthOk && !twoMonthOk {
  63. continue
  64. }
  65. for i := 1; i <= 12; i++ {
  66. //fmt.Println(yk, i, yv[i])
  67. dataCurrentItem := yv[i]
  68. if dataCurrentItem == nil {
  69. continue
  70. }
  71. var date string
  72. var val float64
  73. // 一二月单独处理
  74. if i == 1 || i == 2 {
  75. if _, mok := yv[1]; mok { //1月有值
  76. if i == 1 {
  77. date = dataCurrentItem.DataTime
  78. val, _ = decimal.NewFromFloat(dataCurrentItem.Value).Float64() //a.Div(b).Float64()
  79. }
  80. if i == 2 {
  81. dataOneItem := yv[1]
  82. date = dataCurrentItem.DataTime
  83. twoMonth := decimal.NewFromFloat(dataCurrentItem.Value)
  84. oneMonth := decimal.NewFromFloat(dataOneItem.Value)
  85. val, _ = twoMonth.Sub(oneMonth).Float64()
  86. }
  87. } else { //1月无值
  88. dataTwoItem := yv[2]
  89. if i == 1 {
  90. date = strconv.Itoa(yk) + "-01-31"
  91. a := decimal.NewFromFloat(dataTwoItem.Value)
  92. b := decimal.NewFromFloat(2.0)
  93. val, _ = a.Div(b).Float64()
  94. }
  95. if i == 2 {
  96. //1月无值:1月=2月/2 (不管怎样,都要给1月赋值)
  97. {
  98. date = strconv.Itoa(yk) + "-01-31"
  99. a := decimal.NewFromFloat(dataTwoItem.Value)
  100. b := decimal.NewFromFloat(2.0)
  101. val, _ = a.Div(b).Float64()
  102. dateDataMap[date] = val
  103. }
  104. //end 1月无值
  105. // 这是正常二月份的值
  106. date = dataCurrentItem.DataTime
  107. a := decimal.NewFromFloat(dataTwoItem.Value)
  108. b := decimal.NewFromFloat(2.0)
  109. val, _ = a.Div(b).Float64()
  110. }
  111. }
  112. } else {
  113. dataPreItem := yv[i-1]
  114. if dataCurrentItem != nil && dataPreItem != nil {
  115. date = dataCurrentItem.DataTime
  116. //val = dataCurrentItem.Value - dataPreItem.Value
  117. a := decimal.NewFromFloat(dataCurrentItem.Value)
  118. b := decimal.NewFromFloat(dataPreItem.Value)
  119. val, _ = a.Sub(b).Float64()
  120. }
  121. }
  122. // 如果没有日期,那么就退出当前循环,进入下一个循环
  123. if date == "" {
  124. continue
  125. }
  126. dateDataMap[date] = val
  127. }
  128. }
  129. return
  130. }
  131. // Ljzzj
  132. // @Description: 累计值转季度
  133. // @author: Roc
  134. // @receiver obj
  135. // @datetime2023-11-02 18:05:05
  136. // @return dateDataMap map[string]float64
  137. // @return err error
  138. func (obj BaseCalculate) Ljzzj() (dateDataMap map[string]float64, err error, errMsg string) {
  139. dataList := obj.DataList // 升序
  140. // 数据处理
  141. yearMap := make(map[int]map[int]*EdbInfoSearchData)
  142. dataLen := len(dataList)
  143. for i := 0; i < dataLen; i++ {
  144. item := dataList[i]
  145. //日其中获取年
  146. itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
  147. if tmpErr != nil {
  148. err = tmpErr
  149. return
  150. }
  151. year := itemDate.Year()
  152. quarter := utils.MonthQuarterMap[int(itemDate.Month())]
  153. if quarterMap, yok := yearMap[year]; yok {
  154. quarterMap[quarter] = item
  155. yearMap[year] = quarterMap
  156. } else {
  157. quarterMap = make(map[int]*EdbInfoSearchData)
  158. quarterMap[quarter] = item
  159. yearMap[year] = quarterMap
  160. }
  161. }
  162. // 开始计算
  163. for yk, yv := range yearMap {
  164. _, oneQuarterOk := yv[1]
  165. _, twoQuarterOk := yv[2]
  166. if !oneQuarterOk && !twoQuarterOk {
  167. continue
  168. }
  169. for i := 1; i <= 4; i++ {
  170. //fmt.Println(yk, i, yv[i])
  171. dataCurrentItem := yv[i]
  172. if dataCurrentItem == nil {
  173. continue
  174. }
  175. var date string
  176. var val float64
  177. // 一二季度单独处理
  178. if i == 1 || i == 2 {
  179. if _, mok := yv[1]; mok { //第1个季度有值
  180. if i == 1 {
  181. date = dataCurrentItem.DataTime
  182. val, _ = decimal.NewFromFloat(dataCurrentItem.Value).Float64() //a.Div(b).Float64()
  183. }
  184. if i == 2 {
  185. dataOneItem := yv[1]
  186. date = dataCurrentItem.DataTime
  187. twoQuarter := decimal.NewFromFloat(dataCurrentItem.Value)
  188. oneQuarter := decimal.NewFromFloat(dataOneItem.Value)
  189. val, _ = twoQuarter.Sub(oneQuarter).Float64()
  190. }
  191. } else { //第1个季度无值
  192. dataTwoItem := yv[2]
  193. if i == 1 {
  194. date = strconv.Itoa(yk) + "-03-31"
  195. a := decimal.NewFromFloat(dataTwoItem.Value)
  196. b := decimal.NewFromFloat(2.0)
  197. val, _ = a.Div(b).Float64()
  198. }
  199. if i == 2 {
  200. //第1个季度无值:第1个季度=第2个季度/2 (不管怎样,都要给1季度赋值)
  201. {
  202. date = strconv.Itoa(yk) + "-03-31"
  203. a := decimal.NewFromFloat(dataTwoItem.Value)
  204. b := decimal.NewFromFloat(2.0)
  205. val, _ = a.Div(b).Float64()
  206. dateDataMap[date] = val
  207. }
  208. //end 第1个季度无值
  209. date = dataCurrentItem.DataTime
  210. a := decimal.NewFromFloat(dataTwoItem.Value)
  211. b := decimal.NewFromFloat(2.0)
  212. val, _ = a.Div(b).Float64()
  213. }
  214. }
  215. } else {
  216. dataPreItem := yv[i-1]
  217. if dataCurrentItem != nil && dataPreItem != nil {
  218. date = dataCurrentItem.DataTime
  219. //val = dataCurrentItem.Value - dataPreItem.Value
  220. a := decimal.NewFromFloat(dataCurrentItem.Value)
  221. b := decimal.NewFromFloat(dataPreItem.Value)
  222. val, _ = a.Sub(b).Float64()
  223. }
  224. }
  225. // 如果没有日期,那么就退出当前循环,进入下一个循环
  226. if date == "" {
  227. continue
  228. }
  229. dateDataMap[date] = val
  230. }
  231. }
  232. return
  233. }
  234. // Tbz
  235. // @Description: 同比值计算
  236. // @author: Roc
  237. // @receiver obj
  238. // @datetime2023-11-02 18:04:59
  239. // @return dateDataMap map[string]float64
  240. // @return err error
  241. func (obj BaseCalculate) Tbz() (dateDataMap map[string]float64, err error, errMsg string) {
  242. dataList := obj.DataList // 降序
  243. //数据处理
  244. var dateArr []string
  245. dataMap := make(map[string]*EdbInfoSearchData)
  246. for _, v := range dataList {
  247. dateArr = append(dateArr, v.DataTime)
  248. dataMap[v.DataTime] = v
  249. }
  250. // 开始计算
  251. for _, av := range dateArr {
  252. currentItem, ok := dataMap[av]
  253. if !ok {
  254. continue
  255. }
  256. //当前日期
  257. currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, av, time.Local)
  258. if tmpErr != nil {
  259. err = tmpErr
  260. return
  261. }
  262. // 找到的数据
  263. var findItem *EdbInfoSearchData
  264. //上一年的日期
  265. preDate := currentDate.AddDate(-1, 0, 0)
  266. preDateStr := preDate.Format(utils.FormatDate)
  267. if findItem, ok = dataMap[preDateStr]; !ok { //上一年同期没找到
  268. if obj.Frequency == "月度" { //向上和向下,各找一个月
  269. for i := 0; i <= 35; i++ {
  270. nextDateDay := preDate.AddDate(0, 0, i)
  271. nextDateDayStr := nextDateDay.Format(utils.FormatDate)
  272. if findItem, ok = dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
  273. break
  274. } else {
  275. preDateDay := preDate.AddDate(0, 0, -i)
  276. preDateDayStr := preDateDay.Format(utils.FormatDate)
  277. if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
  278. break
  279. }
  280. }
  281. }
  282. } else if obj.Frequency == "季度" || obj.Frequency == "年度" {
  283. if findItem, ok = dataMap[preDateStr]; ok { //上一年同期->下一个月找到
  284. break
  285. }
  286. } else {
  287. nextDateDay := preDate.AddDate(0, 0, 1)
  288. nextDateDayStr := nextDateDay.Format(utils.FormatDate)
  289. preDateDay := preDate.AddDate(0, 0, -1)
  290. preDateDayStr := preDateDay.Format(utils.FormatDate)
  291. for i := 0; i < 35; i++ {
  292. if i >= 1 {
  293. nextDateDay = nextDateDay.AddDate(0, 0, i)
  294. nextDateDayStr = nextDateDay.Format(utils.FormatDate)
  295. }
  296. if findItem, ok = dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
  297. break
  298. } else {
  299. if i >= 1 {
  300. preDateDay = preDateDay.AddDate(0, 0, -i)
  301. preDateDayStr = preDateDay.Format(utils.FormatDate)
  302. }
  303. if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
  304. break
  305. }
  306. }
  307. }
  308. }
  309. }
  310. // 如果没找到数据
  311. if findItem == nil {
  312. continue
  313. }
  314. dateDataMap[av] = tbzDiv(currentItem.Value, findItem.Value)
  315. }
  316. return
  317. }
  318. // tbzDiv
  319. // @Description: 同比值计算
  320. // @author: Roc
  321. // @datetime2023-11-02 16:29:14
  322. // @param a float64
  323. // @param b float64
  324. // @return float64
  325. func tbzDiv(a, b float64) float64 {
  326. var val float64
  327. if b != 0 {
  328. af := decimal.NewFromFloat(a)
  329. bf := decimal.NewFromFloat(b)
  330. val, _ = af.Div(bf).Sub(decimal.NewFromFloat(1)).RoundCeil(4).Float64()
  331. }
  332. return val
  333. }
  334. // Tcz
  335. // @Description: 计算同差值
  336. // @author: Roc
  337. // @receiver obj
  338. // @datetime2023-11-02 18:04:51
  339. // @return dateDataMap map[string]float64
  340. // @return err error
  341. func (obj BaseCalculate) Tcz() (dateDataMap map[string]float64, err error, errMsg string) {
  342. dataList := obj.DataList // 降序
  343. // 数据处理
  344. var dateArr []string
  345. dataMap := make(map[string]*EdbInfoSearchData)
  346. for _, v := range dataList {
  347. dateArr = append(dateArr, v.DataTime)
  348. dataMap[v.DataTime] = v
  349. }
  350. // 开始计算
  351. for _, av := range dateArr {
  352. currentItem, ok := dataMap[av]
  353. if !ok {
  354. continue
  355. }
  356. //当前日期
  357. currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, av, time.Local)
  358. if tmpErr != nil {
  359. err = tmpErr
  360. return
  361. }
  362. // 找到的数据
  363. var findItem *EdbInfoSearchData
  364. //上一年的日期
  365. preDate := currentDate.AddDate(-1, 0, 0)
  366. preDateStr := preDate.Format(utils.FormatDate)
  367. if findItem, ok = dataMap[preDateStr]; !ok {
  368. //上一年同期没找到
  369. if obj.Frequency == "月度" { //向上和向下,各找一个月
  370. for i := 0; i <= 35; i++ {
  371. nextDateDay := preDate.AddDate(0, 0, i)
  372. nextDateDayStr := nextDateDay.Format(utils.FormatDate)
  373. if findItem, ok = dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
  374. break
  375. } else {
  376. preDateDay := preDate.AddDate(0, 0, -i)
  377. preDateDayStr := preDateDay.Format(utils.FormatDate)
  378. if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
  379. break
  380. }
  381. }
  382. }
  383. } else if obj.Frequency == "季度" || obj.Frequency == "年度" {
  384. if findItem, ok = dataMap[preDateStr]; ok { //上一年同期->下一个月找到
  385. break
  386. }
  387. } else {
  388. for i := 0; i < 35; i++ {
  389. nextDateDay := preDate.AddDate(0, 0, i)
  390. nextDateDayStr := nextDateDay.Format(utils.FormatDate)
  391. if findItem, ok = dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
  392. break
  393. } else {
  394. preDateDay := preDate.AddDate(0, 0, -i)
  395. preDateDayStr := preDateDay.Format(utils.FormatDate)
  396. if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
  397. break
  398. }
  399. }
  400. }
  401. }
  402. }
  403. // 如果没找到数据
  404. if findItem == nil {
  405. continue
  406. }
  407. dateDataMap[av] = tczSub(currentItem.Value, findItem.Value)
  408. }
  409. return
  410. }
  411. // tczSub
  412. // @Description: 计算同差值
  413. // @author: Roc
  414. // @datetime2023-11-02 18:01:46
  415. // @param a float64
  416. // @param b float64
  417. // @return float64
  418. func tczSub(a, b float64) float64 {
  419. af := decimal.NewFromFloat(a)
  420. bf := decimal.NewFromFloat(b)
  421. val, _ := af.Sub(bf).RoundCeil(4).Float64()
  422. return val
  423. }
  424. // Nszydpjjs
  425. // @Description: N数值移动平均数计算
  426. // @author: Roc
  427. // @receiver obj
  428. // @datetime2023-11-02 18:17:38
  429. // @return dateDataMap map[string]float64
  430. // @return err error
  431. func (obj BaseCalculate) Nszydpjjs() (dateDataMap map[string]float64, err error, errMsg string) {
  432. fromDataList := obj.DataList
  433. formulaInt := obj.Formula.(int)
  434. // 数据处理
  435. var fromDateArr []string
  436. fromDataMap := make(map[string]*EdbInfoSearchData)
  437. for _, v := range fromDataList {
  438. fromDateArr = append(fromDateArr, v.DataTime)
  439. fromDataMap[v.DataTime] = v
  440. }
  441. arrLen := len(fromDateArr)
  442. for ak, av := range fromDateArr {
  443. //处理第一个值
  444. var valArr []float64
  445. if findItem, ok := fromDataMap[av]; ok {
  446. valArr = append(valArr, findItem.Value)
  447. } else {
  448. continue
  449. }
  450. if ak+1 != arrLen {
  451. //处理除第一个值之外的N-1个值
  452. for i := 1; i < formulaInt; i++ {
  453. arrIndex := ak + i
  454. if arrIndex >= arrLen {
  455. break
  456. }
  457. arrVal := fromDateArr[arrIndex]
  458. if findItem, ok := fromDataMap[arrVal]; ok {
  459. valArr = append(valArr, findItem.Value)
  460. } else {
  461. continue
  462. }
  463. }
  464. }
  465. valArrLen := len(valArr)
  466. //var totalVal float64
  467. totalVal := decimal.NewFromFloat(0.00)
  468. for _, v := range valArr {
  469. newDecimal := decimal.NewFromFloat(v)
  470. totalVal = totalVal.Add(newDecimal)
  471. }
  472. af := totalVal //decimal.NewFromFloat(totalVal)
  473. bf := decimal.NewFromFloat(float64(valArrLen))
  474. val, _ := af.Div(bf).RoundCeil(4).Float64()
  475. dateDataMap[av] = val
  476. }
  477. return
  478. }
  479. // Hbz
  480. // @Description: 环比值计算
  481. // @author: Roc
  482. // @receiver obj
  483. // @datetime2023-11-02 18:28:24
  484. // @return dateDataMap map[string]float64
  485. // @return err error
  486. func (obj BaseCalculate) Hbz() (dateDataMap map[string]float64, err error, errMsg string) {
  487. dataList := obj.DataList
  488. formulaInt := obj.Formula.(int)
  489. // 数据处理
  490. var dateArr []string
  491. dataMap := make(map[string]*EdbInfoSearchData)
  492. for _, v := range dataList {
  493. dateArr = append(dateArr, v.DataTime)
  494. dataMap[v.DataTime] = v
  495. }
  496. // 数据计算
  497. dataLen := len(dataList)
  498. //fmt.Println("dataLen:", dataLen)
  499. for i := 0; i < dataLen; i++ {
  500. j := i + formulaInt
  501. if j < dataLen {
  502. //当期
  503. currentItem := dataList[i]
  504. preItem := dataList[j]
  505. // 当期和上期没有数据
  506. if currentItem == nil || preItem == nil {
  507. continue
  508. }
  509. // 开始计算
  510. val, ok := hbzDiv(currentItem.Value, preItem.Value)
  511. // 计算失败
  512. if !ok {
  513. continue
  514. }
  515. dateDataMap[currentItem.DataTime] = val
  516. }
  517. }
  518. return
  519. }
  520. // hbzDiv
  521. // @Description: 环比值计算,current:当期,pre:上期 公式: (当期-上期)/上期
  522. // @author: Roc
  523. // @datetime2023-11-02 18:20:11
  524. // @param current float64
  525. // @param pre float64
  526. // @return val float64
  527. // @return ok bool
  528. func hbzDiv(current, pre float64) (val float64, ok bool) {
  529. if pre == 0 {
  530. return
  531. }
  532. currentVal := decimal.NewFromFloat(current)
  533. preVal := decimal.NewFromFloat(pre)
  534. val, _ = currentVal.Sub(preVal).Div(preVal).RoundCeil(4).Float64()
  535. //valStr := decimal.NewFromFloat(val).RoundCeil(4).String() //utils.SubFloatToString(val, 4)
  536. ok = true
  537. return
  538. }
  539. // Hcz
  540. // @Description: 计算环差值数据
  541. // @author: Roc
  542. // @receiver obj
  543. // @datetime2023-11-02 18:33:20
  544. // @return dateDataMap map[string]float64
  545. // @return err error
  546. func (obj BaseCalculate) Hcz() (dateDataMap map[string]float64, err error, errMsg string) {
  547. dataList := obj.DataList
  548. formulaInt := obj.Formula.(int)
  549. // 数据处理
  550. var dateArr []string
  551. dataMap := make(map[string]*EdbInfoSearchData)
  552. for _, v := range dataList {
  553. dateArr = append(dateArr, v.DataTime)
  554. dataMap[v.DataTime] = v
  555. }
  556. dataLen := len(dataList)
  557. fmt.Println("dataLen:", dataLen)
  558. for i := 0; i < dataLen; i++ {
  559. j := i + formulaInt
  560. if j < dataLen {
  561. //当期
  562. currentItem := dataList[i]
  563. preItem := dataList[j]
  564. // 当期和上期没有数据
  565. if currentItem == nil || preItem == nil {
  566. continue
  567. }
  568. // 开始计算
  569. val := hczDiv(currentItem.Value, preItem.Value)
  570. dateDataMap[currentItem.DataTime] = val
  571. }
  572. }
  573. return
  574. }
  575. // hczDiv
  576. // @Description: 环差值计算,current:当期,pre:上期 公式:当期-上期
  577. // @author: Roc
  578. // @datetime2023-11-02 18:33:07
  579. // @param current float64
  580. // @param pre float64
  581. // @return float64
  582. func hczDiv(current, pre float64) float64 {
  583. currentVal := decimal.NewFromFloat(current)
  584. preVal := decimal.NewFromFloat(pre)
  585. val, _ := currentVal.Sub(preVal).RoundCeil(4).Float64()
  586. //valStr := decimal.NewFromFloat(val).RoundCeil(4).String() //utils.SubFloatToString(val, 4)
  587. return val
  588. }
  589. // UpFrequency
  590. // @Description: 升频计算
  591. // @author: Roc
  592. // @receiver obj
  593. // @datetime2023-11-02 18:43:03
  594. // @return dateDataMap map[string]float64
  595. // @return err error
  596. func (obj BaseCalculate) UpFrequency() (dateDataMap map[string]float64, err error, errMsg string) {
  597. dataList := obj.DataList
  598. // 数据处理
  599. var dateArr []string
  600. dataMap := make(map[string]*EdbInfoSearchData)
  601. fromDataMap := make(map[string]float64)
  602. //来源指指标数据
  603. for _, v := range dataList {
  604. dateArr = append(dateArr, v.DataTime)
  605. dataMap[v.DataTime] = v
  606. fromDataMap[v.DataTime] = v.Value
  607. }
  608. // 数据计算
  609. dataLen := len(dataList)
  610. for i := 0; i < dataLen; i++ {
  611. //当期
  612. currentItem := dataList[i]
  613. currentDate, _ := time.ParseInLocation(utils.FormatDate, currentItem.DataTime, time.Local)
  614. var day int
  615. var preItem *EdbInfoSearchData
  616. var preDate time.Time
  617. if i == 0 {
  618. day = int(time.Now().Sub(currentDate).Hours() / float64(24))
  619. preDate = time.Now()
  620. } else {
  621. j := i - 1
  622. if j < dataLen {
  623. preItem = dataList[j]
  624. preDate, _ = time.ParseInLocation(utils.FormatDate, preItem.DataTime, time.Local)
  625. day = int(preDate.Sub(currentDate).Hours() / float64(24))
  626. utils.FileLog.Info("preItem.DataTime:" + preItem.DataTime + ";currentItem.DataTime" + currentItem.DataTime)
  627. }
  628. }
  629. for k := 0; k <= day; k++ {
  630. needDay := preDate.AddDate(0, 0, -k)
  631. dateDataMap[needDay.Format(utils.FormatDate)] = currentItem.Value
  632. }
  633. dateDataMap[currentItem.DataTime] = currentItem.Value
  634. }
  635. return
  636. }
  637. // DownFrequency
  638. // @Description: 降频计算
  639. // @author: Roc
  640. // @receiver obj
  641. // @datetime2023-11-02 18:51:26
  642. // @return dateDataMap map[string]float64
  643. // @return err error
  644. func (obj BaseCalculate) DownFrequency() (dateDataMap map[string]float64, err error, errMsg string) {
  645. dataList := obj.DataList
  646. edbFrequency := obj.Frequency
  647. formula := obj.Formula.(string)
  648. // 数据处理
  649. var dateArr []string
  650. dataMap := make(map[string]*EdbInfoSearchData)
  651. fromDataMap := make(map[string]float64)
  652. //来源指指标数据
  653. for _, v := range dataList {
  654. dateArr = append(dateArr, v.DataTime)
  655. dataMap[v.DataTime] = v
  656. fromDataMap[v.DataTime] = v.Value
  657. }
  658. // 数据计算
  659. dataLen := len(dataList)
  660. if dataLen <= 0 {
  661. return
  662. }
  663. startDataTime, _ := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  664. endDataTime, _ := time.ParseInLocation(utils.FormatDate, dataList[dataLen-1].DataTime, time.Local)
  665. var lastValue float64 // 最近的值
  666. var nextEndDate time.Time // 下一个节点的日期
  667. weekDayDataList := make([]float64, 0)
  668. for tmpStartDataTime := startDataTime; !tmpStartDataTime.After(endDataTime); tmpStartDataTime = tmpStartDataTime.AddDate(0, 0, 1) {
  669. // 将当前数据加入到 weekDayDataList
  670. if tmpData, ok := dataMap[tmpStartDataTime.Format(utils.FormatDate)]; ok {
  671. tmpValue := decimal.NewFromFloat(tmpData.Value)
  672. tmpValueFloat, _ := tmpValue.Round(4).Float64()
  673. weekDayDataList = append(weekDayDataList, tmpValueFloat)
  674. }
  675. // 如果下个节点的日期不存在,那么就先给赋值(兼容时间区间内只有一组数据的情况)
  676. if nextEndDate.IsZero() {
  677. nextEndDate = utils.GetFrequencyEndDay(tmpStartDataTime, edbFrequency)
  678. }
  679. // 日期处理过滤
  680. switch edbFrequency {
  681. case "周度":
  682. if tmpStartDataTime.Weekday() != 0 {
  683. //不是周日,代表需要进入下一个循环获取数据并计算
  684. continue
  685. } else {
  686. //记录下一个结束节点的日期
  687. nextEndDate = tmpStartDataTime.AddDate(0, 0, 7)
  688. }
  689. case "旬度":
  690. nextDay := tmpStartDataTime.AddDate(0, 0, 1)
  691. if nextDay.Day() != 1 && nextDay.Day() != 11 && nextDay.Day() != 21 {
  692. //不是每月10、20、最后一天,代表需要进入下一个循环获取数据并计算
  693. continue
  694. } else {
  695. //记录下一个结束节点的日期
  696. if nextDay.Day() == 1 || nextDay.Day() == 11 {
  697. //月初或者月末的时候,加10天就好了
  698. nextEndDate = nextDay.AddDate(0, 0, 9)
  699. } else {
  700. tmpNextMonth := nextDay.AddDate(0, 1, 0)
  701. nextEndDate = time.Date(tmpNextMonth.Year(), tmpNextMonth.Month(), 1, 0, 0, 0, 0, time.Local).AddDate(0, 0, -1)
  702. }
  703. }
  704. case "月度":
  705. nextDay := tmpStartDataTime.AddDate(0, 0, 1)
  706. if nextDay.Day() != 1 {
  707. //不是每月最后一天,代表需要进入下一个循环获取数据并计算
  708. continue
  709. } else {
  710. //记录下一个结束节点的日期
  711. nextEndDate = nextDay.AddDate(0, 1, -1)
  712. }
  713. case "季度":
  714. nextDay := tmpStartDataTime.AddDate(0, 0, 1)
  715. if (nextDay.Month() == 1 || nextDay.Month() == 4 || nextDay.Month() == 7 || nextDay.Month() == 10) && nextDay.Day() == 1 {
  716. //记录下一个结束节点的日期
  717. nextEndDate = nextDay.AddDate(0, 3, -1)
  718. } else {
  719. //不是3,6,9,12 月份的最后一天,代表需要进入下一个循环获取数据并计算
  720. continue
  721. }
  722. case "年度":
  723. if tmpStartDataTime.Month() == 12 && tmpStartDataTime.Day() == 31 {
  724. //记录下一个结束节点的日期
  725. nextEndDate = tmpStartDataTime.AddDate(1, 0, 0)
  726. } else {
  727. //不是每年的12-31日,代表需要进入下一个循环获取数据并计算
  728. continue
  729. }
  730. default:
  731. err = errors.New("错误的频度:" + edbFrequency)
  732. return
  733. }
  734. // 当前时间段内的数据计算,得出实际值
  735. var currVal float64
  736. lenWeekDayDataList := len(weekDayDataList)
  737. // 如果这个时间区间内没有数据,那么就采用上一个时间区间的值
  738. if len(weekDayDataList) <= 0 {
  739. currVal = lastValue
  740. } else {
  741. if formula == "期末值" {
  742. currVal = weekDayDataList[lenWeekDayDataList-1]
  743. } else {
  744. // 平均值
  745. sumValDeci := decimal.NewFromFloat(0)
  746. for _, v := range weekDayDataList {
  747. tmpValDeci := decimal.NewFromFloat(v)
  748. sumValDeci = sumValDeci.Add(tmpValDeci)
  749. }
  750. lenDeci := decimal.NewFromInt(int64(lenWeekDayDataList))
  751. currVal, _ = sumValDeci.Div(lenDeci).Round(4).Float64()
  752. }
  753. }
  754. // 赋值
  755. dateDataMap[tmpStartDataTime.Format(utils.FormatDate)] = currVal
  756. // 一轮结束后,数据清空
  757. weekDayDataList = make([]float64, 0)
  758. }
  759. // 最后已有的日期处理完成后,需要对剩余不在时间段内的数据做处理
  760. if len(weekDayDataList) > 0 {
  761. // 当前时间段内的数据计算,得出实际值
  762. var currVal float64
  763. lenWeekDayDataList := len(weekDayDataList)
  764. // 如果这个时间区间内没有数据,那么就采用上一个时间区间的值
  765. if len(weekDayDataList) < 0 {
  766. currVal = lastValue
  767. } else {
  768. if formula == "期末值" {
  769. currVal = weekDayDataList[lenWeekDayDataList-1]
  770. } else {
  771. // 平均值
  772. sumValDeci := decimal.NewFromFloat(0)
  773. for _, v := range weekDayDataList {
  774. tmpValDeci := decimal.NewFromFloat(v)
  775. sumValDeci = sumValDeci.Add(tmpValDeci)
  776. }
  777. lenDeci := decimal.NewFromInt(int64(lenWeekDayDataList))
  778. currVal, _ = sumValDeci.Div(lenDeci).Round(4).Float64()
  779. }
  780. }
  781. // 赋值
  782. dateDataMap[nextEndDate.Format(utils.FormatDate)] = currVal
  783. }
  784. return
  785. }
  786. // TimeShift
  787. // @Description: 时间移位计算
  788. // @author: Roc
  789. // @receiver obj
  790. // @datetime2023-11-03 13:19:07
  791. // @return dateDataMap map[string]float64
  792. // @return err error
  793. func (obj BaseCalculate) TimeShift() (dateDataMap map[string]float64, err error, errMsg string) {
  794. dataList := obj.DataList
  795. formulaInt := obj.Formula.(int)
  796. moveType := obj.MoveType
  797. moveFrequency := obj.MoveFrequency
  798. // 数据处理
  799. var dateArr []string
  800. dataMap := make(map[string]*EdbInfoSearchData)
  801. for _, v := range dataList {
  802. dateArr = append(dateArr, v.DataTime)
  803. dataMap[v.DataTime] = v
  804. }
  805. var shiftDay int
  806. switch moveFrequency {
  807. case "天":
  808. shiftDay = formulaInt
  809. case "周":
  810. shiftDay = formulaInt * 7
  811. case "月":
  812. shiftDay = formulaInt * 30
  813. case "季":
  814. shiftDay = formulaInt * 90
  815. case "年":
  816. shiftDay = formulaInt * 365
  817. default:
  818. shiftDay = formulaInt
  819. }
  820. if moveType == 2 {
  821. shiftDay = -shiftDay
  822. }
  823. dataLen := len(dataList)
  824. for i := 0; i < dataLen; i++ {
  825. //当期
  826. currentItem := dataList[i]
  827. currentDate, _ := time.ParseInLocation(utils.FormatDate, currentItem.DataTime, time.Local)
  828. newDate := currentDate.AddDate(0, 0, shiftDay)
  829. val, _ := decimal.NewFromFloat(currentItem.Value).RoundCeil(4).Float64()
  830. dateDataMap[newDate.Format(utils.FormatDate)] = val
  831. }
  832. return
  833. }
  834. // Cjjx
  835. // @Description: 超季节性计算
  836. // @author: Roc
  837. // @receiver obj
  838. // @datetime2023-11-03 13:28:23
  839. // @return dateDataMap map[string]float64
  840. // @return err error
  841. func (obj BaseCalculate) Cjjx() (dateDataMap map[string]float64, err error, errMsg string) {
  842. dataList := obj.DataList
  843. formulaInt := obj.Formula.(int)
  844. calendar := obj.Calendar
  845. // 数据处理
  846. var dateArr []string
  847. dataMap := make(map[string]*EdbInfoSearchData)
  848. for _, v := range dataList {
  849. dateArr = append(dateArr, v.DataTime)
  850. dataMap[v.DataTime] = v
  851. }
  852. // 通过插值法补全所有数据(包含周末)
  853. handleDataMap := make(map[string]float64)
  854. _, err = HandleDataByLinearRegression(dataList, handleDataMap)
  855. if err != nil {
  856. return
  857. }
  858. // 每个年份的日期数据需要平移的天数
  859. moveDayMap := make(map[int]int, 0) // 每个年份的春节公历
  860. var lastDataDay time.Time
  861. if len(dataList) > 0 {
  862. lastDataDay, _ = time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
  863. }
  864. // 数据计算
  865. for _, av := range dateArr {
  866. // 如果遇到闰二月,如2.29,去掉该天数据
  867. if strings.Contains(av, "02-29") {
  868. continue
  869. }
  870. currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, av, time.Local)
  871. if tmpErr != nil {
  872. err = tmpErr
  873. return
  874. }
  875. //农历的超季节性运算,只计算11月--次年5月,分段计算,与数据区间和N数值有关
  876. if calendar == "农历" && currentDate.Month() > 5 && currentDate.Month() < 11 {
  877. continue
  878. }
  879. currentItem, ok := dataMap[av]
  880. // 找不到数据就退出当前循环,进入下一循环
  881. if !ok {
  882. continue
  883. }
  884. pastValueList := make([]float64, 0) // 过去几期的数据
  885. pastValueList = append(pastValueList, currentItem.Value) //当前日期
  886. for i := 1; i < formulaInt; i++ {
  887. //前几年当天公历的日期
  888. historyPreDate := currentDate.AddDate(-i, 0, 0)
  889. moveDay := 0
  890. if calendar == "农历" {
  891. if tmpMoveDay, ok := moveDayMap[historyPreDate.Year()]; !ok {
  892. moveDay, err = getMoveDay(lastDataDay, historyPreDate)
  893. if err != nil {
  894. return
  895. }
  896. } else {
  897. moveDay = tmpMoveDay
  898. }
  899. // 移动天数到对应农历 的 公历 日期
  900. historyPreDate = historyPreDate.AddDate(0, 0, moveDay)
  901. }
  902. historyPreDateStr := historyPreDate.Format(utils.FormatDate)
  903. if tmpValue, ok := handleDataMap[historyPreDateStr]; ok { //上一年同期找到
  904. pastValueList = append(pastValueList, tmpValue)
  905. }
  906. }
  907. if len(pastValueList) == formulaInt {
  908. val, ok := cjjxSub(currentItem.Value, pastValueList)
  909. if !ok {
  910. continue
  911. }
  912. dateDataMap[av] = val
  913. }
  914. }
  915. return
  916. }
  917. // cjjxSub
  918. // @Description: 超季节性计算
  919. // @author: Roc
  920. // @datetime2023-11-03 13:25:49
  921. // @param currValue float64
  922. // @param pastValue []float64
  923. // @return value float64
  924. // @return ok bool
  925. func cjjxSub(currValue float64, pastValue []float64) (value float64, ok bool) {
  926. num := len(pastValue)
  927. if num == 0 {
  928. return
  929. }
  930. numDecimal := decimal.NewFromInt(int64(num))
  931. af := decimal.NewFromFloat(currValue)
  932. bf := decimal.NewFromFloat(pastValue[0])
  933. for k := 1; k < num; k++ {
  934. tmpVal := decimal.NewFromFloat(pastValue[k])
  935. bf = bf.Add(tmpVal)
  936. }
  937. value, _ = af.Sub(bf.Div(numDecimal)).RoundCeil(4).Float64()
  938. ok = true
  939. return
  940. }
  941. // Annualized
  942. // @Description: 年化计算
  943. // @author: Roc
  944. // @receiver obj
  945. // @datetime2023-11-03 13:34:32
  946. // @param to orm.TxOrmer
  947. // @param edbInfoId int
  948. // @param source int
  949. // @param fromEdbInfo *EdbInfo
  950. // @param edbCode string
  951. // @return dateDataMap map[string]float64
  952. // @return err error
  953. func (obj BaseCalculate) Annualized() (dateDataMap map[string]float64, err error, errMsg string) {
  954. fromDataList := obj.DataList
  955. lenFromDataList := len(fromDataList)
  956. // 如果来源指标没有数据,那么就直接返回得了
  957. if lenFromDataList <= 0 {
  958. return
  959. }
  960. // 数据处理
  961. // 插值法数据处理
  962. handleDataMap := make(map[string]float64)
  963. _, err = HandleDataByLinearRegression(fromDataList, handleDataMap)
  964. if err != nil {
  965. return
  966. }
  967. // 每年的最后一天的数据值
  968. yearLastValMap := make(map[int]float64)
  969. startDataTime, _ := time.ParseInLocation(utils.FormatDate, fromDataList[0].DataTime, time.Local)
  970. endDataTime, _ := time.ParseInLocation(utils.FormatDate, fromDataList[lenFromDataList-1].DataTime, time.Local)
  971. for i := startDataTime.Year(); i <= endDataTime.Year(); i++ {
  972. tmpDateStr := fmt.Sprintf("%d-12-31", i)
  973. if tmpVal, ok := handleDataMap[tmpDateStr]; ok {
  974. yearLastValMap[i] = tmpVal
  975. }
  976. }
  977. // 数据计算
  978. // 遍历来源指标数据
  979. for _, v := range fromDataList {
  980. currDateStr := v.DataTime
  981. currDate, _ := time.ParseInLocation(utils.FormatDate, currDateStr, time.Local)
  982. perValMap := make(map[time.Time]float64)
  983. //前3年当日的数据
  984. for i := 1; i <= 3; i++ {
  985. tmpDateTime := currDate.AddDate(-i, 0, 0)
  986. if tmpVal, ok := handleDataMap[tmpDateTime.Format(utils.FormatDate)]; ok {
  987. perValMap[tmpDateTime] = tmpVal
  988. }
  989. }
  990. lenPerValMap := len(perValMap)
  991. // 如果数据少于2年,那么就不参与计算,结束当前循环,进入下一个循环
  992. if lenPerValMap < 2 {
  993. continue
  994. }
  995. // N年 当前值占全年比重 的值列表
  996. divValList := make([]decimal.Decimal, 0)
  997. for tmpDateTime, tmpVal := range perValMap {
  998. yearLastVal, ok2 := yearLastValMap[tmpDateTime.Year()]
  999. // 如果当年最后一天没有数据
  1000. if !ok2 {
  1001. continue
  1002. }
  1003. // 当前值占全年比重
  1004. tmpYearLastVal := decimal.NewFromFloat(yearLastVal)
  1005. if tmpYearLastVal.IsZero() { //如果是0,那么就退出当前循环,进入下一个循环
  1006. continue
  1007. }
  1008. divVal := decimal.NewFromFloat(tmpVal).Div(tmpYearLastVal)
  1009. divValList = append(divValList, divVal)
  1010. }
  1011. lenDivValList := len(divValList)
  1012. // 如果 N年 当前值占全年比重 的值 小于 2个,那么就不参与计算,结束当前循环,进入下一个循环
  1013. if lenDivValList < 2 {
  1014. continue
  1015. }
  1016. divValSum := decimal.NewFromFloat(0)
  1017. for _, divVal := range divValList {
  1018. divValSum = divValSum.Add(divVal)
  1019. }
  1020. // 当前计算出来的结果
  1021. tmpDivVal := divValSum.Div(decimal.NewFromInt(int64(lenDivValList)))
  1022. if tmpDivVal.IsZero() { //如果是0,那么就退出当前循环,进入下一个循环
  1023. continue
  1024. }
  1025. currVal, _ := decimal.NewFromFloat(v.Value).Div(tmpDivVal).Round(4).Float64()
  1026. dateDataMap[currDateStr] = currVal
  1027. }
  1028. return
  1029. }
  1030. // Ljz
  1031. // @Description: 累计值
  1032. // @author: Roc
  1033. // @receiver obj
  1034. // @datetime2023-11-03 13:49:17
  1035. // @return dateDataMap map[string]float64
  1036. // @return err error
  1037. func (obj BaseCalculate) Ljz() (dateDataMap map[string]float64, err error, errMsg string) {
  1038. dataList := obj.DataList
  1039. frequency := obj.Frequency //需要变更的频度
  1040. fromFrequency := obj.FromFrequency //来源的频度
  1041. // 数据处理
  1042. var isWeekData bool // 是否周度数据,如果是周度数据的话,是需要变频的,最后结果还需要除以7
  1043. // 周度数据需要先变成日度的
  1044. if fromFrequency == `周度` {
  1045. isWeekData = true
  1046. }
  1047. fromEdbDataMap := make(map[string]float64)
  1048. if isWeekData {
  1049. dataList, err = HandleDataByLinearRegression(dataList, fromEdbDataMap)
  1050. if err != nil {
  1051. return
  1052. }
  1053. }
  1054. //日度转周度:日期选周五,计算上周六到本周五的日度值的加总,最新日期为最新值对应的周五。
  1055. //日度转月度:日期选每个月最后一天,计算当月所有日度值的加总,最新日期为最新值对应当月最后一天。
  1056. //日度转季度、年度:方法类似转月度。
  1057. //周度转月度/季度/年度:将周度值转成日度,空值用插值法插值,计算当月/当季/当年所有值的加总,然后除以7。
  1058. //月度转季度/年度: 当季/当年月度值相加。
  1059. dateList := make([]time.Time, 0)
  1060. valueMap := make(map[time.Time]float64)
  1061. switch frequency {
  1062. case "年度":
  1063. yearMap := make(map[int]float64)
  1064. yearList := make([]int, 0)
  1065. for _, item := range dataList {
  1066. itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
  1067. if tmpErr != nil {
  1068. err = tmpErr
  1069. return
  1070. }
  1071. year := itemDate.Year()
  1072. yearVal, ok := yearMap[year]
  1073. if ok {
  1074. yearMap[year] = item.Value + yearVal
  1075. } else {
  1076. yearList = append(yearList, year)
  1077. yearMap[year] = item.Value
  1078. }
  1079. }
  1080. for _, v := range yearList {
  1081. currTime := time.Date(v, 12, 31, 0, 0, 0, 0, time.Local)
  1082. dateList = append(dateList, currTime)
  1083. valueMap[currTime] = yearMap[v]
  1084. }
  1085. case "半年度":
  1086. yearMonthMap := make(map[string]float64)
  1087. yearMonthList := make([]string, 0)
  1088. for _, item := range dataList {
  1089. itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
  1090. if tmpErr != nil {
  1091. err = tmpErr
  1092. return
  1093. }
  1094. year := itemDate.Year()
  1095. var tmpK string
  1096. if itemDate.Month() <= 6 {
  1097. tmpK = fmt.Sprint(year, "06")
  1098. } else {
  1099. tmpK = fmt.Sprint(year, "12")
  1100. }
  1101. yearVal, ok := yearMonthMap[tmpK]
  1102. if ok {
  1103. yearMonthMap[tmpK] = item.Value + yearVal
  1104. } else {
  1105. yearMonthList = append(yearMonthList, tmpK)
  1106. yearMonthMap[tmpK] = item.Value
  1107. }
  1108. }
  1109. for _, v := range yearMonthList {
  1110. currTime, tmpErr := time.ParseInLocation(utils.FormatYearMonthUnSpace, v, time.Local)
  1111. if tmpErr != nil {
  1112. err = tmpErr
  1113. return
  1114. }
  1115. currTime = currTime.AddDate(0, 1, -1)
  1116. dateList = append(dateList, currTime)
  1117. valueMap[currTime] = yearMonthMap[v]
  1118. }
  1119. case "季度":
  1120. yearMonthMap := make(map[string]float64)
  1121. yearMonthList := make([]string, 0)
  1122. for _, item := range dataList {
  1123. itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
  1124. if tmpErr != nil {
  1125. err = tmpErr
  1126. return
  1127. }
  1128. year := itemDate.Year()
  1129. var tmpK string
  1130. if itemDate.Month() <= 3 {
  1131. tmpK = fmt.Sprint(year, "03")
  1132. } else if itemDate.Month() <= 6 {
  1133. tmpK = fmt.Sprint(year, "06")
  1134. } else if itemDate.Month() <= 9 {
  1135. tmpK = fmt.Sprint(year, "09")
  1136. } else {
  1137. tmpK = fmt.Sprint(year, "12")
  1138. }
  1139. yearVal, ok := yearMonthMap[tmpK]
  1140. if ok {
  1141. yearMonthMap[tmpK] = item.Value + yearVal
  1142. } else {
  1143. yearMonthList = append(yearMonthList, tmpK)
  1144. yearMonthMap[tmpK] = item.Value
  1145. }
  1146. }
  1147. for _, v := range yearMonthList {
  1148. currTime, tmpErr := time.ParseInLocation(utils.FormatYearMonthUnSpace, v, time.Local)
  1149. if tmpErr != nil {
  1150. err = tmpErr
  1151. return
  1152. }
  1153. currTime = currTime.AddDate(0, 1, -1)
  1154. dateList = append(dateList, currTime)
  1155. valueMap[currTime] = yearMonthMap[v]
  1156. }
  1157. case "月度":
  1158. yearMonthMap := make(map[string]float64)
  1159. yearMonthList := make([]string, 0)
  1160. for _, item := range dataList {
  1161. itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
  1162. if tmpErr != nil {
  1163. err = tmpErr
  1164. return
  1165. }
  1166. year := itemDate.Year()
  1167. var tmpK string
  1168. tmpK = fmt.Sprint(year*100 + int(itemDate.Month()))
  1169. yearVal, ok := yearMonthMap[tmpK]
  1170. if ok {
  1171. yearMonthMap[tmpK] = item.Value + yearVal
  1172. } else {
  1173. yearMonthList = append(yearMonthList, tmpK)
  1174. yearMonthMap[tmpK] = item.Value
  1175. }
  1176. }
  1177. for _, v := range yearMonthList {
  1178. currTime, tmpErr := time.ParseInLocation(utils.FormatYearMonthUnSpace, v, time.Local)
  1179. if tmpErr != nil {
  1180. err = tmpErr
  1181. return
  1182. }
  1183. currTime = currTime.AddDate(0, 1, -1)
  1184. dateList = append(dateList, currTime)
  1185. valueMap[currTime] = yearMonthMap[v]
  1186. }
  1187. case "旬度":
  1188. tmpDateDataMap := make(map[time.Time]float64)
  1189. tmpDateList := make([]time.Time, 0)
  1190. for _, item := range dataList {
  1191. itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
  1192. if tmpErr != nil {
  1193. err = tmpErr
  1194. return
  1195. }
  1196. dayInt := itemDate.Year()*100 + int(itemDate.Month())
  1197. var currTime time.Time
  1198. if itemDate.Month() <= 10 {
  1199. tmpK := fmt.Sprint(dayInt*100, "10")
  1200. currTime, err = time.ParseInLocation(utils.FormatDateUnSpace, tmpK, time.Local)
  1201. if err != nil {
  1202. return
  1203. }
  1204. } else if itemDate.Month() <= 20 {
  1205. tmpK := fmt.Sprint(dayInt*100, "20")
  1206. currTime, err = time.ParseInLocation(utils.FormatDateUnSpace, tmpK, time.Local)
  1207. if err != nil {
  1208. return
  1209. }
  1210. } else {
  1211. currTime, err = time.ParseInLocation(utils.FormatYearMonthUnSpace, fmt.Sprint(dayInt), time.Local)
  1212. if err != nil {
  1213. return
  1214. }
  1215. currTime = currTime.AddDate(0, 1, -1)
  1216. }
  1217. yearVal, ok := tmpDateDataMap[currTime]
  1218. if ok {
  1219. tmpDateDataMap[currTime] = item.Value + yearVal
  1220. } else {
  1221. tmpDateList = append(tmpDateList, currTime)
  1222. tmpDateDataMap[currTime] = item.Value
  1223. }
  1224. }
  1225. for _, currTime := range tmpDateList {
  1226. dateList = append(dateList, currTime)
  1227. valueMap[currTime] = tmpDateDataMap[currTime]
  1228. }
  1229. case "周度":
  1230. tmpDateDataMap := make(map[time.Time]float64)
  1231. tmpDateList := make([]time.Time, 0)
  1232. for _, item := range dataList {
  1233. itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
  1234. if tmpErr != nil {
  1235. err = tmpErr
  1236. return
  1237. }
  1238. var currTime time.Time
  1239. // 周六周日,这是下一个周五的数据
  1240. if itemDate.Weekday() == 0 {
  1241. currTime = itemDate.AddDate(0, 0, 5)
  1242. } else if itemDate.Weekday() == 6 {
  1243. currTime = itemDate.AddDate(0, 0, 6)
  1244. } else {
  1245. currTime = itemDate.AddDate(0, 0, 5-int(itemDate.Weekday()))
  1246. }
  1247. yearVal, ok := tmpDateDataMap[currTime]
  1248. if ok {
  1249. tmpDateDataMap[currTime] = item.Value + yearVal
  1250. } else {
  1251. tmpDateList = append(tmpDateList, currTime)
  1252. tmpDateDataMap[currTime] = item.Value
  1253. }
  1254. }
  1255. for _, currTime := range tmpDateList {
  1256. dateList = append(dateList, currTime)
  1257. valueMap[currTime] = tmpDateDataMap[currTime]
  1258. }
  1259. default:
  1260. err = errors.New("错误的频度")
  1261. return
  1262. }
  1263. // 数据计算
  1264. for _, currTime := range dateList {
  1265. currDateStr := currTime.Format(utils.FormatDate)
  1266. tmpVal, ok2 := valueMap[currTime]
  1267. if !ok2 {
  1268. err = errors.New("数据异常,date:" + currDateStr)
  1269. return
  1270. }
  1271. var saveValue float64
  1272. if isWeekData { //周度指标转的话,最后结果要除以7
  1273. saveValue, _ = decimal.NewFromFloat(tmpVal).Div(decimal.NewFromInt(7)).Round(4).Float64()
  1274. } else {
  1275. saveValue, _ = decimal.NewFromFloat(tmpVal).Round(4).Float64()
  1276. }
  1277. dateDataMap[currDateStr] = saveValue
  1278. }
  1279. return
  1280. }
  1281. // LjzNczj
  1282. // @Description:年初至今累计值计算
  1283. // @author: Roc
  1284. // @receiver obj
  1285. // @datetime2023-11-03 13:55:44
  1286. // @return dateDataMap map[string]float64
  1287. // @return err error
  1288. func (obj BaseCalculate) LjzNczj() (dateDataMap map[string]float64, err error, errMsg string) {
  1289. dataList := obj.DataList
  1290. frequency := obj.Frequency //需要变更的频度
  1291. fromFrequency := obj.FromFrequency //来源的频度
  1292. // 数据处理
  1293. var isWeekData bool // 是否周度数据,如果是周度数据的话,是需要变频的,最后结果还需要除以7
  1294. // 周度数据需要先变成日度的
  1295. if fromFrequency == `周度` {
  1296. isWeekData = true
  1297. }
  1298. fromEdbDataMap := make(map[string]float64)
  1299. if isWeekData {
  1300. dataList, err = HandleDataByLinearRegression(dataList, fromEdbDataMap)
  1301. if err != nil {
  1302. return
  1303. }
  1304. }
  1305. //日度数据年初至今:日期同原日度数据。将每年1月1日(含)到日度数据所在日期含间的日度值,进行加总。
  1306. //周度数据年初至今:日期同原周度数据。将周度值转成日度频率,空值用插值法插值,然后算法同日度年度至今,再除以7
  1307. //月度/季度数据年初至今:日期同原月度/季度数据,将每年1月1日(含)到月度数据所在日期(含)之间的月度/季度值,进行加总
  1308. //以此类推
  1309. dateList := make([]time.Time, 0)
  1310. valueMap := make(map[time.Time]float64)
  1311. yearMap := make(map[int]float64)
  1312. switch frequency {
  1313. case "周度":
  1314. tmpDateDataMap := make(map[time.Time]float64)
  1315. tmpDateList := make([]time.Time, 0)
  1316. for _, item := range dataList {
  1317. itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
  1318. if tmpErr != nil {
  1319. err = tmpErr
  1320. return
  1321. }
  1322. var currTime time.Time
  1323. // 周六周日,这是下一个周五的数据
  1324. if itemDate.Weekday() == 0 {
  1325. currTime = itemDate.AddDate(0, 0, 5)
  1326. } else if itemDate.Weekday() == 6 {
  1327. currTime = itemDate.AddDate(0, 0, 6)
  1328. } else {
  1329. currTime = itemDate.AddDate(0, 0, 5-int(itemDate.Weekday()))
  1330. }
  1331. year := itemDate.Year()
  1332. yearVal, ok := yearMap[year]
  1333. if ok {
  1334. yearMap[year] = item.Value + yearVal
  1335. } else {
  1336. yearMap[year] = item.Value
  1337. }
  1338. if itemDate.Equal(currTime) {
  1339. tmpDateDataMap[itemDate] = yearMap[year]
  1340. tmpDateList = append(tmpDateList, itemDate)
  1341. }
  1342. }
  1343. for _, currTime := range tmpDateList {
  1344. dateList = append(dateList, currTime)
  1345. valueMap[currTime] = tmpDateDataMap[currTime]
  1346. }
  1347. default:
  1348. for _, item := range dataList {
  1349. itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
  1350. if tmpErr != nil {
  1351. err = tmpErr
  1352. return
  1353. }
  1354. year := itemDate.Year()
  1355. yearVal, ok := yearMap[year]
  1356. if ok {
  1357. yearMap[year] = item.Value + yearVal
  1358. } else {
  1359. yearMap[year] = item.Value
  1360. }
  1361. valueMap[itemDate] = yearMap[year]
  1362. dateList = append(dateList, itemDate)
  1363. }
  1364. }
  1365. // 数据计算
  1366. for _, currTime := range dateList {
  1367. currDateStr := currTime.Format(utils.FormatDate)
  1368. tmpVal, ok2 := valueMap[currTime]
  1369. if !ok2 {
  1370. err = errors.New("数据异常,date:" + currDateStr)
  1371. return
  1372. }
  1373. var saveValue float64
  1374. if isWeekData { //周度指标转的话,最后结果要除以7
  1375. saveValue, _ = decimal.NewFromFloat(tmpVal).Div(decimal.NewFromInt(7)).Round(4).Float64()
  1376. } else {
  1377. saveValue, _ = decimal.NewFromFloat(tmpVal).Round(4).Float64()
  1378. }
  1379. dateDataMap[currDateStr] = saveValue
  1380. }
  1381. return
  1382. }
  1383. // ExponentialSmoothing
  1384. // @Description: 指数修匀计算
  1385. // @author: Roc
  1386. // @receiver obj
  1387. // @datetime2023-11-03 14:07:47
  1388. // @return dateDataMap map[string]float64
  1389. // @return err error
  1390. func (obj BaseCalculate) ExponentialSmoothing() (dateDataMap map[string]float64, err error, errMsg string) {
  1391. dataList := obj.DataList
  1392. formula := obj.Formula.(string) // alpha值
  1393. alpha, _ := strconv.ParseFloat(formula, 64)
  1394. if alpha <= 0 || alpha >= 1 {
  1395. err = fmt.Errorf("alpha值有误: %v", alpha)
  1396. return
  1397. }
  1398. // 获取标准差图表的指标数据
  1399. fromDataList, err := calculateExponentialSmoothingData(dataList, alpha)
  1400. if err != nil {
  1401. return
  1402. }
  1403. // 数据计算
  1404. for _, tmpData := range fromDataList {
  1405. _, tmpErr := time.ParseInLocation(utils.FormatDate, tmpData.DataTime, time.Local)
  1406. if tmpErr != nil {
  1407. err = tmpErr
  1408. return
  1409. }
  1410. // 当前的实际值
  1411. saveValue, _ := decimal.NewFromFloat(tmpData.Value).Round(4).Float64()
  1412. dateDataMap[tmpData.DataTime] = saveValue
  1413. }
  1414. return
  1415. }
  1416. // calculateExponentialSmoothingData
  1417. // @Description: 计算指数修匀
  1418. // @author: Roc
  1419. // @datetime2023-11-03 14:05:41
  1420. // @param dataList []*EdbInfoSearchData 时间基准指标在时间区间内的值
  1421. // @param strAlpha float64
  1422. // @return newDataList []EdbInfoSearchData
  1423. // @return err error
  1424. func calculateExponentialSmoothingData(dataList []*EdbInfoSearchData, alpha float64) (newDataList []EdbInfoSearchData, err error) {
  1425. if alpha <= 0 || alpha >= 1 {
  1426. err = fmt.Errorf("alpha值有误: %v", alpha)
  1427. return
  1428. }
  1429. var preVal float64
  1430. alphaDecimal := decimal.NewFromFloat(alpha)
  1431. subAlpha := decimal.NewFromFloat(1).Sub(alphaDecimal)
  1432. for k, d := range dataList {
  1433. // 首期的值以原始值作为指数修匀的计算值
  1434. if k == 0 {
  1435. newDataList = append(newDataList, EdbInfoSearchData{
  1436. EdbDataId: k,
  1437. DataTime: dataList[k].DataTime,
  1438. Value: d.Value,
  1439. })
  1440. preVal = d.Value
  1441. continue
  1442. }
  1443. // 上一期的值参与计算
  1444. preDecimal := decimal.NewFromFloat(preVal)
  1445. valDecimal := decimal.NewFromFloat(d.Value)
  1446. partA := alphaDecimal.Mul(valDecimal)
  1447. partB := subAlpha.Mul(preDecimal)
  1448. res, _ := (partA.Add(partB)).Float64()
  1449. preVal = res
  1450. newDataList = append(newDataList, EdbInfoSearchData{
  1451. EdbDataId: k,
  1452. DataTime: dataList[k].DataTime,
  1453. Value: res,
  1454. })
  1455. }
  1456. return
  1457. }
  1458. // Rjz
  1459. // @Description: 日均值计算
  1460. // @author: Roc
  1461. // @receiver obj
  1462. // @datetime2023-11-03 14:47:47
  1463. // @return dateDataMap map[string]float64
  1464. // @return err error
  1465. func (obj BaseCalculate) Rjz() (dateDataMap map[string]float64, err error, errMsg string) {
  1466. dataList := obj.DataList
  1467. fromFrequency := obj.FromFrequency
  1468. if fromFrequency == `` {
  1469. err = errors.New("错误的频度:" + fromFrequency)
  1470. return
  1471. }
  1472. // 数据处理
  1473. var dateArr []string
  1474. dataMap := make(map[string]*EdbInfoSearchData)
  1475. for _, v := range dataList {
  1476. dateArr = append(dateArr, v.DataTime)
  1477. dataMap[v.DataTime] = v
  1478. }
  1479. // 数据计算
  1480. for _, av := range dateArr {
  1481. currentItem, ok := dataMap[av]
  1482. if !ok {
  1483. continue
  1484. }
  1485. //当前日期
  1486. currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, av, time.Local)
  1487. if tmpErr != nil {
  1488. err = tmpErr
  1489. return
  1490. }
  1491. //根据频度计算需要均分的天数
  1492. days := GetRjzFrequencyDays(currentDate, fromFrequency)
  1493. val, ok := rjzDivV2(currentItem.Value, days)
  1494. if !ok {
  1495. continue
  1496. }
  1497. dateDataMap[av] = val
  1498. }
  1499. return
  1500. }
  1501. // rjzDivV2
  1502. // @Description: 日均值计算
  1503. // @author: Roc
  1504. // @datetime2023-11-03 14:47:36
  1505. // @param a float64
  1506. // @param b int
  1507. // @return val float64
  1508. // @return ok bool
  1509. func rjzDivV2(a float64, b int) (val float64, ok bool) {
  1510. if b == 0 {
  1511. return
  1512. }
  1513. af := decimal.NewFromFloat(a)
  1514. bf := decimal.NewFromFloat(float64(b))
  1515. val, _ = af.Div(bf).Round(4).Float64()
  1516. return
  1517. }
  1518. // reverseSlice
  1519. // @Description: 倒装切片
  1520. // @author: Roc
  1521. // @datetime2023-11-06 14:08:25
  1522. // @param slice []*EdbInfoSearchData
  1523. // @return []*EdbInfoSearchData
  1524. func reverseSlice(slice []*EdbInfoSearchData) []*EdbInfoSearchData {
  1525. reversed := make([]*EdbInfoSearchData, len(slice))
  1526. for i, j := 0, len(slice)-1; i < len(slice); i, j = i+1, j-1 {
  1527. reversed[i] = slice[j]
  1528. }
  1529. return reversed
  1530. }
  1531. // reverseSlice
  1532. // @Description: 倒装切片
  1533. // @author: Roc
  1534. // @datetime2023-11-06 14:08:25
  1535. // @param slice []*EdbInfoSearchData
  1536. // @return []*EdbInfoSearchData
  1537. func reverseSliceByDesc(slice []*EdbInfoSearchData) (newSlice []*EdbInfoSearchData, err error) {
  1538. // 只有一个数据的话,那么就直接返回
  1539. if len(slice) <= 1 {
  1540. newSlice = slice
  1541. return
  1542. }
  1543. startDate, err := time.ParseInLocation(utils.FormatDate, slice[0].DataTime, time.Local)
  1544. if err != nil {
  1545. return
  1546. }
  1547. secondDate, err := time.ParseInLocation(utils.FormatDate, slice[1].DataTime, time.Local)
  1548. if err != nil {
  1549. return
  1550. }
  1551. if !secondDate.After(startDate) {
  1552. newSlice = slice
  1553. return
  1554. }
  1555. newSlice = make([]*EdbInfoSearchData, len(slice))
  1556. for i, j := 0, len(slice)-1; i < len(slice); i, j = i+1, j-1 {
  1557. newSlice[i] = slice[j]
  1558. }
  1559. return
  1560. }