base_calculate.go 45 KB

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