base_calculate.go 49 KB

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