trade_analysis_data.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. package trade_analysis
  2. import (
  3. "eta/eta_api/models/data_manage"
  4. tradeAnalysisModel "eta/eta_api/models/data_manage/trade_analysis"
  5. "eta/eta_api/services/data"
  6. "eta/eta_api/utils"
  7. "fmt"
  8. "sort"
  9. "strings"
  10. "time"
  11. )
  12. // FormatCompanyTradeData2EdbMappings [公司-合约加总]转为指标数据
  13. func FormatCompanyTradeData2EdbMappings(companyTradeData []*tradeAnalysisModel.ContractCompanyTradeData, tradeType, dateType, dateTypeNum int, startDate, endDate string, chartEdbList []*data_manage.ChartSaveItem) (edbMappings []*data_manage.ChartEdbInfoMapping, chartName string, err error) {
  14. edbMappings = make([]*data_manage.ChartEdbInfoMapping, 0)
  15. if dateType <= 0 {
  16. dateType = utils.DateTypeOneMonth
  17. }
  18. // 期货公司名称作为标识进行匹配
  19. edbMap := make(map[string]*data_manage.ChartSaveItem)
  20. if len(chartEdbList) > 0 {
  21. for _, v := range chartEdbList {
  22. edbMap[v.UniqueFlag] = v
  23. }
  24. }
  25. for k, v := range companyTradeData {
  26. mapping := new(data_manage.ChartEdbInfoMapping)
  27. mapping.EdbName = v.CompanyName
  28. mapping.EdbNameEn = v.CompanyName
  29. mapping.EdbAliasName = v.CompanyName
  30. mapping.EdbAliasNameEn = v.CompanyName
  31. mapping.Frequency = "日度"
  32. mapping.FrequencyEn = data.GetFrequencyEn(mapping.Frequency)
  33. mapping.SourceName = utils.SourceNameTradeAnalysis
  34. mapping.Source = utils.CHART_SOURCE_TRADE_ANALYSIS_PROCESS
  35. mapping.IsAxis = 1
  36. mapping.EdbInfoType = 1
  37. mapping.StartDate = v.StartDate.Format(utils.FormatDate)
  38. mapping.EndDate = v.EndDate.Format(utils.FormatDate)
  39. mapping.ConvertUnit = tradeAnalysisModel.WarehouseDefaultUnit // 固定单位
  40. mapping.UniqueFlag = v.CompanyName // 期货公司名称作为每条曲线的唯一标识
  41. // 有配置那么取配置中的图例名称和左右轴
  42. edbConf := edbMap[mapping.UniqueFlag]
  43. if edbConf != nil {
  44. mapping.EdbName = edbConf.EdbAliasName
  45. mapping.EdbNameEn = edbConf.EdbAliasName
  46. mapping.EdbAliasName = edbConf.EdbAliasName
  47. mapping.EdbAliasNameEn = edbConf.EdbAliasName
  48. mapping.IsAxis = edbConf.IsAxis
  49. }
  50. // 根据参数取日期范围
  51. var startTime, endTime time.Time
  52. if dateType > 0 {
  53. st, ed := utils.GetDateByDateTypeV2(dateType, startDate, endDate, dateTypeNum, time.Time{})
  54. if st != "" {
  55. startTime, _ = time.ParseInLocation(utils.FormatDate, st, time.Local)
  56. }
  57. if startTime.IsZero() {
  58. startTime = v.StartDate
  59. }
  60. if ed != "" {
  61. endTime, _ = time.ParseInLocation(utils.FormatDate, ed, time.Local)
  62. }
  63. if endTime.IsZero() {
  64. endTime = v.EndDate
  65. }
  66. }
  67. // 指标数据和最值
  68. edbData := make([]*data_manage.EdbDataList, 0)
  69. var minData, maxData float64
  70. var setMinMax bool
  71. for _, dv := range v.DataList {
  72. if dv.Date.Before(startTime) || dv.Date.After(endTime) {
  73. continue
  74. }
  75. // 交易方向
  76. var (
  77. val float64
  78. hasVal bool
  79. )
  80. if tradeType == tradeAnalysisModel.WarehouseBuyChartType {
  81. if dv.BuyValType == tradeAnalysisModel.TradeDataTypeNull {
  82. continue
  83. }
  84. hasVal = true
  85. val = float64(dv.BuyVal)
  86. }
  87. if tradeType == tradeAnalysisModel.WarehouseSoldChartType {
  88. if dv.SoldValType == tradeAnalysisModel.TradeDataTypeNull {
  89. continue
  90. }
  91. hasVal = true
  92. val = float64(dv.SoldVal)
  93. }
  94. if tradeType == tradeAnalysisModel.WarehousePureBuyChartType {
  95. if dv.PureBuyValType == tradeAnalysisModel.TradeDataTypeNull {
  96. continue
  97. }
  98. hasVal = true
  99. val = float64(dv.PureBuyVal)
  100. }
  101. if !hasVal {
  102. continue
  103. }
  104. if !setMinMax {
  105. minData = val
  106. maxData = val
  107. setMinMax = true
  108. }
  109. if val < minData {
  110. minData = val
  111. }
  112. if val > maxData {
  113. maxData = val
  114. }
  115. edbData = append(edbData, &data_manage.EdbDataList{
  116. DataTime: dv.Date.Format(utils.FormatDate),
  117. DataTimestamp: dv.Date.UnixNano() / 1e6,
  118. Value: val,
  119. })
  120. }
  121. mapping.MinData = minData
  122. mapping.MaxData = maxData
  123. mapping.DataList = edbData
  124. edbMappings = append(edbMappings, mapping)
  125. // 图表默认名称
  126. if k == 0 {
  127. chartName += strings.ReplaceAll(v.ClassifyType, ",", "")
  128. }
  129. chartName += v.CompanyName
  130. }
  131. // 图表名称后缀
  132. chartName += tradeAnalysisModel.WarehouseTypeSuffixNames[tradeType]
  133. return
  134. }
  135. func GetOriginTradeData(exchange, classifyName string, contracts, companies []string, predictRatio float64) (companyTradeData []*tradeAnalysisModel.ContractCompanyTradeData, err error) {
  136. // 各原始数据表期货公司名称不一致
  137. companyMap := make(map[string]string)
  138. {
  139. ob := new(tradeAnalysisModel.TradeFuturesCompany)
  140. list, e := ob.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
  141. if e != nil {
  142. err = fmt.Errorf("获取期货公司名称失败: %v", e)
  143. return
  144. }
  145. switch exchange {
  146. case "zhengzhou":
  147. for _, v := range list {
  148. companyMap[v.CompanyName] = v.ZhengzhouName
  149. }
  150. case "dalian":
  151. for _, v := range list {
  152. companyMap[v.CompanyName] = v.DalianName
  153. }
  154. case "shanghai":
  155. for _, v := range list {
  156. companyMap[v.CompanyName] = v.ShanghaiName
  157. }
  158. case "cffex":
  159. for _, v := range list {
  160. companyMap[v.CompanyName] = v.CffexName
  161. }
  162. case "ine":
  163. for _, v := range list {
  164. companyMap[v.CompanyName] = v.IneName
  165. }
  166. case "guangzhou":
  167. for _, v := range list {
  168. companyMap[v.CompanyName] = v.GuangzhouName
  169. }
  170. }
  171. }
  172. var queryCompanies []string
  173. for _, v := range companies {
  174. if v == tradeAnalysisModel.TradeFuturesCompanyTop20 {
  175. queryCompanies = append(queryCompanies, tradeAnalysisModel.TradeFuturesCompanyTop20)
  176. continue
  177. }
  178. companyName, ok := companyMap[v]
  179. if !ok {
  180. utils.FileLog.Info(fmt.Sprintf("交易所%s公司名称映射不存在: %s", exchange, v))
  181. continue
  182. }
  183. queryCompanies = append(queryCompanies, companyName)
  184. }
  185. // 郑商所/广期所查询方式不一样
  186. var tradeAnalysis TradeAnalysisInterface
  187. switch exchange {
  188. case tradeAnalysisModel.TradeExchangeZhengzhou:
  189. tradeAnalysis = &ZhengzhouTradeAnalysis{}
  190. case tradeAnalysisModel.TradeExchangeGuangzhou:
  191. tradeAnalysis = &GuangzhouTradeAnalysis{}
  192. default:
  193. tradeAnalysis = &BaseTradeAnalysis{}
  194. }
  195. // 获取多单/空单原始数据
  196. originList, e := tradeAnalysis.GetTradeDataByClassifyAndCompany(exchange, classifyName, contracts, queryCompanies)
  197. if e != nil {
  198. err = fmt.Errorf("获取多空单原始数据失败, %v", e)
  199. return
  200. }
  201. keyItems := make(map[string]*tradeAnalysisModel.ContractCompanyTradeData)
  202. keyDateData := make(map[string]*tradeAnalysisModel.ContractCompanyTradeDataList)
  203. keyDateDataExist := make(map[string]bool)
  204. for _, v := range originList {
  205. // Rank999和0对应的是TOP20
  206. companyName := v.CompanyName
  207. if v.Rank == 999 || v.Rank == 0 {
  208. companyName = tradeAnalysisModel.TradeFuturesCompanyTop20
  209. }
  210. k := fmt.Sprintf("%s-%s", v.ClassifyType, companyName)
  211. if keyItems[k] == nil {
  212. keyItems[k] = new(tradeAnalysisModel.ContractCompanyTradeData)
  213. keyItems[k].CompanyName = companyName
  214. keyItems[k].ClassifyType = v.ClassifyType
  215. keyItems[k].DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
  216. }
  217. kd := fmt.Sprintf("%s-%s", k, v.DataTime.Format(utils.FormatDate))
  218. if keyDateData[kd] == nil {
  219. keyDateData[kd] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
  220. keyDateData[kd].Date = v.DataTime
  221. }
  222. if v.ValType == 1 {
  223. keyDateData[kd].BuyVal = v.Val
  224. keyDateData[kd].BuyValType = tradeAnalysisModel.TradeDataTypeOrigin
  225. keyDateData[kd].BuyChange = v.ValChange
  226. keyDateData[kd].BuyChangeType = tradeAnalysisModel.TradeDataTypeOrigin
  227. }
  228. if v.ValType == 2 {
  229. keyDateData[kd].SoldVal = v.Val
  230. keyDateData[kd].SoldValType = tradeAnalysisModel.TradeDataTypeOrigin
  231. keyDateData[kd].SoldChange = v.ValChange
  232. keyDateData[kd].SoldChangeType = tradeAnalysisModel.TradeDataTypeOrigin
  233. }
  234. if !keyDateDataExist[kd] {
  235. keyItems[k].DataList = append(keyItems[k].DataList, keyDateData[kd])
  236. keyDateDataExist[kd] = true
  237. }
  238. }
  239. // 获取[合约]每日的末位多空单
  240. contractLastBuyDateVal := make(map[string]map[time.Time]int)
  241. contractLastSoldDateVal := make(map[string]map[time.Time]int)
  242. {
  243. lastOriginList, e := tradeAnalysis.GetLastTradeDataByClassify(exchange, classifyName, contracts)
  244. if e != nil {
  245. err = fmt.Errorf("获取末位多空单原始数据失败, %v", e)
  246. return
  247. }
  248. for _, v := range lastOriginList {
  249. if v.ValType == 1 {
  250. if contractLastBuyDateVal[v.ClassifyType] == nil {
  251. contractLastBuyDateVal[v.ClassifyType] = make(map[time.Time]int)
  252. }
  253. contractLastBuyDateVal[v.ClassifyType][v.DataTime] = v.Val
  254. continue
  255. }
  256. if contractLastSoldDateVal[v.ClassifyType] == nil {
  257. contractLastSoldDateVal[v.ClassifyType] = make(map[time.Time]int)
  258. }
  259. contractLastSoldDateVal[v.ClassifyType][v.DataTime] = v.Val
  260. }
  261. }
  262. // 填充[合约-公司]预估数据, 并根据[公司-多合约]分组, [公司]算作一个指标, 指标值为[多个合约]的计算加总
  263. companyContracts := make(map[string][]*tradeAnalysisModel.ContractCompanyTradeData)
  264. for _, v := range keyItems {
  265. td, fd, ed, e := PredictingTradeData(v.DataList, contractLastBuyDateVal[v.ClassifyType], contractLastSoldDateVal[v.ClassifyType], predictRatio)
  266. if e != nil {
  267. err = fmt.Errorf("数据补全失败, %v", e)
  268. return
  269. }
  270. v.DataList = td
  271. v.StartDate = fd
  272. v.EndDate = ed
  273. if companyContracts[v.CompanyName] == nil {
  274. companyContracts[v.CompanyName] = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
  275. }
  276. companyContracts[v.CompanyName] = append(companyContracts[v.CompanyName], v)
  277. }
  278. // 以[公司]为组, 计算合约加总
  279. mussyTradeData := make(map[string]*tradeAnalysisModel.ContractCompanyTradeData)
  280. for k, v := range companyContracts {
  281. companyData := new(tradeAnalysisModel.ContractCompanyTradeData)
  282. companyData.CompanyName = k
  283. companyData.DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
  284. contractArr := make([]string, 0)
  285. // 合约加总
  286. sumDateData := make(map[time.Time]*tradeAnalysisModel.ContractCompanyTradeDataList)
  287. for _, vv := range v {
  288. contractArr = append(contractArr, vv.ClassifyType)
  289. for _, dv := range vv.DataList {
  290. if sumDateData[dv.Date] == nil {
  291. sumDateData[dv.Date] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
  292. sumDateData[dv.Date].Date = dv.Date
  293. }
  294. // 数据类型以第一个非零值为准, 只处理多空和净多, 变化就不管了
  295. if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
  296. sumDateData[dv.Date].BuyValType = dv.BuyValType
  297. }
  298. if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.BuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
  299. sumDateData[dv.Date].BuyValType = dv.BuyValType
  300. }
  301. if dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
  302. sumDateData[dv.Date].BuyVal += dv.BuyVal
  303. }
  304. // 空单
  305. if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeNull && dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
  306. sumDateData[dv.Date].SoldValType = dv.SoldValType
  307. }
  308. if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.SoldValType == tradeAnalysisModel.TradeDataTypeCalculate {
  309. sumDateData[dv.Date].SoldValType = dv.SoldValType
  310. }
  311. if dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
  312. sumDateData[dv.Date].SoldVal += dv.SoldVal
  313. }
  314. // 净多单
  315. if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
  316. sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
  317. }
  318. if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.PureBuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
  319. sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
  320. }
  321. if dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
  322. sumDateData[dv.Date].PureBuyVal += dv.PureBuyVal
  323. }
  324. }
  325. // 多个合约比对开始结束时间
  326. if companyData.StartDate.IsZero() {
  327. companyData.StartDate = vv.StartDate
  328. }
  329. if vv.StartDate.Before(companyData.StartDate) {
  330. companyData.StartDate = vv.StartDate
  331. }
  332. if companyData.EndDate.IsZero() {
  333. companyData.EndDate = vv.EndDate
  334. }
  335. if vv.EndDate.Before(companyData.EndDate) {
  336. companyData.EndDate = vv.EndDate
  337. }
  338. }
  339. for _, sv := range sumDateData {
  340. companyData.DataList = append(companyData.DataList, sv)
  341. }
  342. sort.Slice(companyData.DataList, func(i, j int) bool {
  343. return companyData.DataList[i].Date.Before(companyData.DataList[j].Date)
  344. })
  345. companyData.ClassifyType = strings.Join(contractArr, ",")
  346. mussyTradeData[k] = companyData
  347. }
  348. // 数据根据公司排序, 不然会随机乱
  349. companyTradeData = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
  350. for _, v := range companies {
  351. // 没数据也需要加进去, 不然edbList会少
  352. if mussyTradeData[v] == nil {
  353. companyData := new(tradeAnalysisModel.ContractCompanyTradeData)
  354. companyData.CompanyName = v
  355. companyData.DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
  356. companyTradeData = append(companyTradeData, companyData)
  357. continue
  358. }
  359. companyTradeData = append(companyTradeData, mussyTradeData[v])
  360. }
  361. return
  362. }
  363. // PredictingTradeData 根据数据库中的多空数据填充预估数据
  364. func PredictingTradeData(originData []*tradeAnalysisModel.ContractCompanyTradeDataList, lastBuyDateVal, lastSoldDateVal map[time.Time]int, predictRatio float64) (newData []*tradeAnalysisModel.ContractCompanyTradeDataList, firstDate, endDate time.Time, err error) {
  365. // 测试用的验证数据
  366. //lastBuyDateVal, lastSoldDateVal = make(map[time.Time]int), make(map[time.Time]int)
  367. //lastBuyDateVal[time.Date(2024, 7, 16, 0, 0, 0, 0, time.Local)] = 4602
  368. //lastBuyDateVal[time.Date(2024, 7, 17, 0, 0, 0, 0, time.Local)] = 5116
  369. //lastBuyDateVal[time.Date(2024, 7, 18, 0, 0, 0, 0, time.Local)] = 5130
  370. //lastBuyDateVal[time.Date(2024, 7, 19, 0, 0, 0, 0, time.Local)] = 5354
  371. //lastBuyDateVal[time.Date(2024, 7, 22, 0, 0, 0, 0, time.Local)] = 5916
  372. //lastBuyDateVal[time.Date(2024, 7, 23, 0, 0, 0, 0, time.Local)] = 6524
  373. //lastBuyDateVal[time.Date(2024, 7, 26, 0, 0, 0, 0, time.Local)] = 6575
  374. //lastBuyDateVal[time.Date(2024, 7, 29, 0, 0, 0, 0, time.Local)] = 7461
  375. //lastBuyDateVal[time.Date(2024, 7, 30, 0, 0, 0, 0, time.Local)] = 8488
  376. //
  377. //lastSoldDateVal[time.Date(2024, 7, 11, 0, 0, 0, 0, time.Local)] = 5467
  378. //lastSoldDateVal[time.Date(2024, 7, 12, 0, 0, 0, 0, time.Local)] = 5248
  379. //lastSoldDateVal[time.Date(2024, 7, 15, 0, 0, 0, 0, time.Local)] = 5102
  380. //lastSoldDateVal[time.Date(2024, 7, 16, 0, 0, 0, 0, time.Local)] = 4771
  381. //lastSoldDateVal[time.Date(2024, 7, 23, 0, 0, 0, 0, time.Local)] = 5989
  382. //lastSoldDateVal[time.Date(2024, 7, 26, 0, 0, 0, 0, time.Local)] = 6745
  383. //lastSoldDateVal[time.Date(2024, 7, 30, 0, 0, 0, 0, time.Local)] = 7272
  384. //
  385. //originData = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
  386. //originData = append(originData, &tradeAnalysisModel.ContractCompanyTradeDataList{
  387. // Date: time.Date(2024, 7, 10, 0, 0, 0, 0, time.Local),
  388. // BuyVal: 14324,
  389. // BuyValType: tradeAnalysisModel.TradeDataTypeOrigin,
  390. // BuyChange: -1107,
  391. // BuyChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  392. // SoldVal: 0,
  393. // SoldValType: tradeAnalysisModel.TradeDataTypeNull,
  394. // SoldChange: 0,
  395. // SoldChangeType: tradeAnalysisModel.TradeDataTypeNull,
  396. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  397. // Date: time.Date(2024, 7, 11, 0, 0, 0, 0, time.Local),
  398. // BuyVal: 14280,
  399. // BuyValType: tradeAnalysisModel.TradeDataTypeOrigin,
  400. // BuyChange: -44,
  401. // BuyChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  402. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  403. // Date: time.Date(2024, 7, 12, 0, 0, 0, 0, time.Local),
  404. // BuyVal: 14214,
  405. // BuyValType: tradeAnalysisModel.TradeDataTypeOrigin,
  406. // BuyChange: -66,
  407. // BuyChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  408. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  409. // Date: time.Date(2024, 7, 15, 0, 0, 0, 0, time.Local),
  410. // BuyVal: 14269,
  411. // BuyValType: tradeAnalysisModel.TradeDataTypeOrigin,
  412. // BuyChange: 55,
  413. // BuyChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  414. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  415. // Date: time.Date(2024, 7, 17, 0, 0, 0, 0, time.Local),
  416. // SoldVal: 5254,
  417. // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
  418. // SoldChange: 708,
  419. // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  420. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  421. // Date: time.Date(2024, 7, 18, 0, 0, 0, 0, time.Local),
  422. // SoldVal: 6595,
  423. // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
  424. // SoldChange: 1341,
  425. // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  426. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  427. // Date: time.Date(2024, 7, 19, 0, 0, 0, 0, time.Local),
  428. // SoldVal: 5938,
  429. // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
  430. // SoldChange: -657,
  431. // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  432. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  433. // Date: time.Date(2024, 7, 22, 0, 0, 0, 0, time.Local),
  434. // SoldVal: 6131,
  435. // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
  436. // SoldChange: 193,
  437. // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  438. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  439. // Date: time.Date(2024, 7, 29, 0, 0, 0, 0, time.Local),
  440. // SoldVal: 6679,
  441. // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
  442. // SoldChange: 312,
  443. // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  444. //})
  445. if len(originData) == 0 {
  446. return
  447. }
  448. if predictRatio < 0 || predictRatio > 1 {
  449. err = fmt.Errorf("估计参数不在0-1之间")
  450. return
  451. }
  452. sort.Slice(originData, func(i, j int) bool {
  453. return originData[i].Date.Before(originData[j].Date)
  454. })
  455. dateVal := make(map[time.Time]*tradeAnalysisModel.ContractCompanyTradeDataList)
  456. for _, v := range originData {
  457. dateVal[v.Date] = v
  458. }
  459. // 生成开始日期-1d(可能会往前面推算一天)至结束日期间的交易日, 以交易日为时间序列遍历
  460. tradeDays := utils.GetTradingDays(originData[0].Date.AddDate(0, 0, -1), originData[len(originData)-1].Date)
  461. for k, v := range tradeDays {
  462. // T日多空均无的情况
  463. //bothLast := false
  464. if dateVal[v] == nil {
  465. // T-1和T+1[原始数据]均无值, 那么T日无数据
  466. hasPrev, hasNext := false, false
  467. if k-1 >= 0 {
  468. hasPrev = true
  469. }
  470. if k+1 <= len(tradeDays)-1 {
  471. hasNext = true
  472. }
  473. if !hasPrev && !hasNext {
  474. continue
  475. }
  476. // T+1有值, 优先从T+1推, 然后继续走下面计算净多单的逻辑
  477. if hasNext {
  478. nextDay := tradeDays[k+1]
  479. if dateVal[nextDay] != nil {
  480. // T+1有多/空及多空变化, 且是原始数据, 那么推出数据并在map中新加一日数据
  481. if dateVal[nextDay].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[nextDay].BuyChangeType == tradeAnalysisModel.TradeDataTypeOrigin {
  482. if _, ok := dateVal[v]; !ok {
  483. dateVal[v] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
  484. dateVal[v].Date = v
  485. }
  486. dateVal[v].BuyVal = dateVal[nextDay].BuyVal - dateVal[nextDay].BuyChange
  487. dateVal[v].BuyValType = tradeAnalysisModel.TradeDataTypeOrigin
  488. }
  489. if dateVal[nextDay].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[nextDay].SoldChangeType == tradeAnalysisModel.TradeDataTypeOrigin {
  490. if _, ok := dateVal[v]; !ok {
  491. dateVal[v] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
  492. dateVal[v].Date = v
  493. }
  494. dateVal[v].SoldVal = dateVal[nextDay].SoldVal - dateVal[nextDay].SoldChange
  495. dateVal[v].SoldValType = tradeAnalysisModel.TradeDataTypeOrigin
  496. }
  497. }
  498. }
  499. // T+1没推出来而T-1有值, 那么T多空均取末位, 计算净多单
  500. _, has := dateVal[v]
  501. if hasPrev && !has {
  502. sv, sok := lastSoldDateVal[v]
  503. bv, bok := lastBuyDateVal[v]
  504. if !sok && !bok {
  505. continue
  506. }
  507. dateVal[v] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
  508. dateVal[v].Date = v
  509. if sok {
  510. dateVal[v].SoldVal = int(predictRatio*float64(sv) + 0.5)
  511. dateVal[v].SoldValType = tradeAnalysisModel.TradeDataTypeCalculate
  512. }
  513. if bok {
  514. dateVal[v].BuyVal = int(predictRatio*float64(bv) + 0.5)
  515. dateVal[v].BuyValType = tradeAnalysisModel.TradeDataTypeCalculate
  516. }
  517. if dateVal[v].BuyValType > tradeAnalysisModel.TradeDataTypeNull && dateVal[v].SoldValType > tradeAnalysisModel.TradeDataTypeNull {
  518. dateVal[v].PureBuyVal = dateVal[v].BuyVal - dateVal[v].SoldVal
  519. dateVal[v].PureBuyValType = tradeAnalysisModel.TradeDataTypeCalculate
  520. }
  521. continue
  522. }
  523. }
  524. // 多空均有的情况下计算净多单
  525. if dateVal[v].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[v].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin {
  526. dateVal[v].PureBuyVal = dateVal[v].BuyVal - dateVal[v].SoldVal
  527. dateVal[v].PureBuyValType = tradeAnalysisModel.TradeDataTypeOrigin // 原始值算出来的也作原始值
  528. }
  529. // 仅有多单, 空单取末位, 计算净多单
  530. if dateVal[v].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[v].SoldValType == tradeAnalysisModel.TradeDataTypeNull {
  531. if sv, ok := lastSoldDateVal[v]; ok {
  532. dateVal[v].SoldVal = int(predictRatio*float64(sv) + 0.5) // 估计参数*末位值, 向上取整
  533. dateVal[v].SoldValType = tradeAnalysisModel.TradeDataTypeCalculate
  534. dateVal[v].PureBuyVal = dateVal[v].BuyVal - dateVal[v].SoldVal
  535. dateVal[v].PureBuyValType = tradeAnalysisModel.TradeDataTypeCalculate
  536. }
  537. }
  538. // 仅有空单, 多单取末位, 计算净多单
  539. if dateVal[v].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[v].BuyValType == tradeAnalysisModel.TradeDataTypeNull {
  540. if sv, ok := lastBuyDateVal[v]; ok {
  541. dateVal[v].BuyVal = int(predictRatio*float64(sv) + 0.5)
  542. dateVal[v].BuyValType = tradeAnalysisModel.TradeDataTypeCalculate
  543. dateVal[v].PureBuyVal = dateVal[v].BuyVal - dateVal[v].SoldVal
  544. dateVal[v].PureBuyValType = tradeAnalysisModel.TradeDataTypeCalculate
  545. }
  546. }
  547. }
  548. // 二次遍历, 计算与T-1的变化值
  549. for k, v := range tradeDays {
  550. // 无T/T-1数据, 忽略
  551. if dateVal[v] == nil {
  552. continue
  553. }
  554. if k-1 < 0 {
  555. continue
  556. }
  557. beforeDay := tradeDays[k-1]
  558. if dateVal[beforeDay] == nil {
  559. continue
  560. }
  561. // 多单变化
  562. if dateVal[v].BuyChangeType == tradeAnalysisModel.TradeDataTypeNull {
  563. if dateVal[v].BuyValType > tradeAnalysisModel.TradeDataTypeNull && dateVal[beforeDay].BuyValType > tradeAnalysisModel.TradeDataTypeNull {
  564. dateVal[v].BuyChange = dateVal[v].BuyVal - dateVal[beforeDay].BuyVal
  565. // 如果当日多单或者前日多单是估计值, 那么多单变化也为估计值
  566. if dateVal[v].BuyValType == tradeAnalysisModel.TradeDataTypeCalculate || dateVal[beforeDay].BuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
  567. dateVal[v].BuyChangeType = tradeAnalysisModel.TradeDataTypeCalculate
  568. }
  569. }
  570. }
  571. // 空单变化
  572. if dateVal[v].SoldChangeType == tradeAnalysisModel.TradeDataTypeNull {
  573. if dateVal[v].SoldValType > tradeAnalysisModel.TradeDataTypeNull && dateVal[beforeDay].SoldValType > tradeAnalysisModel.TradeDataTypeNull {
  574. dateVal[v].SoldChange = dateVal[v].SoldVal - dateVal[beforeDay].SoldVal
  575. // 如果当日空单或者前日空单是估计值, 那么空单变化也为估计值
  576. if dateVal[v].SoldValType == tradeAnalysisModel.TradeDataTypeCalculate || dateVal[beforeDay].SoldValType == tradeAnalysisModel.TradeDataTypeCalculate {
  577. dateVal[v].SoldChangeType = tradeAnalysisModel.TradeDataTypeCalculate
  578. }
  579. }
  580. }
  581. // 净多变化
  582. if dateVal[v].PureBuyChangeType == tradeAnalysisModel.TradeDataTypeNull {
  583. if dateVal[v].PureBuyValType > tradeAnalysisModel.TradeDataTypeNull && dateVal[beforeDay].PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
  584. dateVal[v].PureBuyChange = dateVal[v].PureBuyVal - dateVal[beforeDay].PureBuyVal
  585. dateVal[v].PureBuyChangeType = tradeAnalysisModel.TradeDataTypeOrigin
  586. // 如果当日净多单或者前日净多单是估计值, 那么净多单变化也为估计值
  587. if dateVal[v].PureBuyValType == tradeAnalysisModel.TradeDataTypeCalculate || dateVal[beforeDay].PureBuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
  588. dateVal[v].PureBuyChangeType = tradeAnalysisModel.TradeDataTypeCalculate
  589. }
  590. }
  591. }
  592. }
  593. // 重新遍历map, 生成数据序列并排序
  594. newData = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
  595. for _, v := range dateVal {
  596. if v.BuyValType == tradeAnalysisModel.TradeDataTypeNull && v.SoldValType == tradeAnalysisModel.TradeDataTypeNull {
  597. continue
  598. }
  599. newData = append(newData, v)
  600. }
  601. sort.Slice(newData, func(i, j int) bool {
  602. return newData[i].Date.Before(newData[j].Date)
  603. })
  604. if len(newData) > 0 {
  605. firstDate = newData[0].Date
  606. endDate = newData[len(newData)-1].Date
  607. }
  608. return
  609. }