trade_analysis_data.go 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. package trade_analysis
  2. import (
  3. "eta/eta_index_lib/models"
  4. tradeAnalysisModel "eta/eta_index_lib/models/trade_analysis"
  5. "eta/eta_index_lib/utils"
  6. "fmt"
  7. "sort"
  8. "strings"
  9. "time"
  10. )
  11. // FormatCompanyTradeData2EdbData [公司-合约加总]转为指标数据
  12. func FormatCompanyTradeData2EdbData(companyTradeData *tradeAnalysisModel.ContractCompanyTradeData, tradeType int) (edbData []*models.EdbDataList, err error) {
  13. if companyTradeData == nil {
  14. err = fmt.Errorf("持仓数据异常")
  15. return
  16. }
  17. edbData = make([]*models.EdbDataList, 0)
  18. var minData, maxData float64
  19. for dk, dv := range companyTradeData.DataList {
  20. // 交易方向
  21. var val float64
  22. if tradeType == tradeAnalysisModel.WarehouseBuyChartType {
  23. if dv.BuyValType == tradeAnalysisModel.TradeDataTypeNull {
  24. continue
  25. }
  26. val = float64(dv.BuyVal)
  27. }
  28. if tradeType == tradeAnalysisModel.WarehouseSoldChartType {
  29. if dv.SoldValType == tradeAnalysisModel.TradeDataTypeNull {
  30. continue
  31. }
  32. val = float64(dv.SoldVal)
  33. }
  34. if tradeType == tradeAnalysisModel.WarehousePureBuyChartType {
  35. if dv.PureBuyValType == tradeAnalysisModel.TradeDataTypeNull {
  36. continue
  37. }
  38. val = float64(dv.PureBuyVal)
  39. }
  40. if dk == 0 {
  41. minData = val
  42. maxData = val
  43. }
  44. if val < minData {
  45. minData = val
  46. }
  47. if val > maxData {
  48. maxData = val
  49. }
  50. edbData = append(edbData, &models.EdbDataList{
  51. DataTime: dv.Date.Format(utils.FormatDate),
  52. DataTimestamp: dv.Date.UnixNano() / 1e6,
  53. Value: val,
  54. })
  55. }
  56. return
  57. }
  58. func GetWarehouseTradeData(exchange, classifyName string, contracts, companies []string, predictRatio float64) (companyTradeData []*tradeAnalysisModel.ContractCompanyTradeData, err error) {
  59. // 获取合约持仓数据
  60. contractTradeData, lastBuyVal, lastSoldVal, e := GetContractCompanyTradeData(exchange, []string{classifyName}, contracts, companies, time.Time{}, time.Time{})
  61. if e != nil {
  62. err = fmt.Errorf("获取合约-持仓数据失败, %v", e)
  63. return
  64. }
  65. // 填充[合约-公司]预估数据, 并根据[公司-多合约]分组, [公司]算作一个指标, 指标值为[多个合约]的计算加总
  66. companyContracts := make(map[string][]*tradeAnalysisModel.ContractCompanyTradeData)
  67. for _, v := range contractTradeData {
  68. td, fd, ed, e := PredictingTradeData(v.DataList, lastBuyVal[v.ClassifyType], lastSoldVal[v.ClassifyType], predictRatio)
  69. if e != nil {
  70. err = fmt.Errorf("数据补全失败, %v", e)
  71. return
  72. }
  73. v.DataList = td
  74. v.StartDate = fd
  75. v.EndDate = ed
  76. if companyContracts[v.CompanyName] == nil {
  77. companyContracts[v.CompanyName] = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
  78. }
  79. companyContracts[v.CompanyName] = append(companyContracts[v.CompanyName], v)
  80. }
  81. // 以[公司]为组, 计算合约加总
  82. mussyTradeData := make(map[string]*tradeAnalysisModel.ContractCompanyTradeData)
  83. for k, v := range companyContracts {
  84. companyData := new(tradeAnalysisModel.ContractCompanyTradeData)
  85. companyData.CompanyName = k
  86. companyData.DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
  87. contractArr := make([]string, 0)
  88. // 合约加总
  89. sumDateData := make(map[time.Time]*tradeAnalysisModel.ContractCompanyTradeDataList)
  90. for _, vv := range v {
  91. contractArr = append(contractArr, vv.ClassifyType)
  92. for _, dv := range vv.DataList {
  93. if sumDateData[dv.Date] == nil {
  94. sumDateData[dv.Date] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
  95. sumDateData[dv.Date].Date = dv.Date
  96. }
  97. // 数据类型以第一个非零值为准, 只处理多空和净多, 变化就不管了
  98. if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
  99. sumDateData[dv.Date].BuyValType = dv.BuyValType
  100. }
  101. if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.BuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
  102. sumDateData[dv.Date].BuyValType = dv.BuyValType
  103. }
  104. if dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
  105. sumDateData[dv.Date].BuyVal += dv.BuyVal
  106. }
  107. // 空单
  108. if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeNull && dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
  109. sumDateData[dv.Date].SoldValType = dv.SoldValType
  110. }
  111. if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.SoldValType == tradeAnalysisModel.TradeDataTypeCalculate {
  112. sumDateData[dv.Date].SoldValType = dv.SoldValType
  113. }
  114. if dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
  115. sumDateData[dv.Date].SoldVal += dv.SoldVal
  116. }
  117. // 净多单
  118. if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
  119. sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
  120. }
  121. if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.PureBuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
  122. sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
  123. }
  124. if dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
  125. sumDateData[dv.Date].PureBuyVal += dv.PureBuyVal
  126. }
  127. }
  128. // 多个合约比对开始结束时间
  129. if companyData.StartDate.IsZero() {
  130. companyData.StartDate = vv.StartDate
  131. }
  132. if vv.StartDate.Before(companyData.StartDate) {
  133. companyData.StartDate = vv.StartDate
  134. }
  135. if companyData.EndDate.IsZero() {
  136. companyData.EndDate = vv.EndDate
  137. }
  138. if vv.EndDate.Before(companyData.EndDate) {
  139. companyData.EndDate = vv.EndDate
  140. }
  141. }
  142. for _, sv := range sumDateData {
  143. companyData.DataList = append(companyData.DataList, sv)
  144. }
  145. sort.Slice(companyData.DataList, func(i, j int) bool {
  146. return companyData.DataList[i].Date.Before(companyData.DataList[j].Date)
  147. })
  148. companyData.ClassifyType = strings.Join(contractArr, ",")
  149. mussyTradeData[k] = companyData
  150. }
  151. // 数据根据公司排序, 不然会随机乱
  152. companyTradeData = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
  153. for _, v := range companies {
  154. // 没数据也需要加进去, 不然edbList会少
  155. if mussyTradeData[v] == nil {
  156. companyData := new(tradeAnalysisModel.ContractCompanyTradeData)
  157. companyData.CompanyName = v
  158. companyData.DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
  159. companyTradeData = append(companyTradeData, companyData)
  160. continue
  161. }
  162. companyTradeData = append(companyTradeData, mussyTradeData[v])
  163. }
  164. return
  165. }
  166. // PredictingTradeData 根据数据库中的多空数据填充预估数据
  167. func PredictingTradeData(originData []*tradeAnalysisModel.ContractCompanyTradeDataList, lastBuyDateVal, lastSoldDateVal map[time.Time]int, predictRatio float64) (newData []*tradeAnalysisModel.ContractCompanyTradeDataList, firstDate, endDate time.Time, err error) {
  168. // 测试用的验证数据
  169. //lastBuyDateVal, lastSoldDateVal = make(map[time.Time]int), make(map[time.Time]int)
  170. //lastBuyDateVal[time.Date(2024, 7, 16, 0, 0, 0, 0, time.Local)] = 4602
  171. //lastBuyDateVal[time.Date(2024, 7, 17, 0, 0, 0, 0, time.Local)] = 5116
  172. //lastBuyDateVal[time.Date(2024, 7, 18, 0, 0, 0, 0, time.Local)] = 5130
  173. //lastBuyDateVal[time.Date(2024, 7, 19, 0, 0, 0, 0, time.Local)] = 5354
  174. //lastBuyDateVal[time.Date(2024, 7, 22, 0, 0, 0, 0, time.Local)] = 5916
  175. //lastBuyDateVal[time.Date(2024, 7, 23, 0, 0, 0, 0, time.Local)] = 6524
  176. //lastBuyDateVal[time.Date(2024, 7, 26, 0, 0, 0, 0, time.Local)] = 6575
  177. //lastBuyDateVal[time.Date(2024, 7, 29, 0, 0, 0, 0, time.Local)] = 7461
  178. //lastBuyDateVal[time.Date(2024, 7, 30, 0, 0, 0, 0, time.Local)] = 8488
  179. //
  180. //lastSoldDateVal[time.Date(2024, 7, 11, 0, 0, 0, 0, time.Local)] = 5467
  181. //lastSoldDateVal[time.Date(2024, 7, 12, 0, 0, 0, 0, time.Local)] = 5248
  182. //lastSoldDateVal[time.Date(2024, 7, 15, 0, 0, 0, 0, time.Local)] = 5102
  183. //lastSoldDateVal[time.Date(2024, 7, 16, 0, 0, 0, 0, time.Local)] = 4771
  184. //lastSoldDateVal[time.Date(2024, 7, 23, 0, 0, 0, 0, time.Local)] = 5989
  185. //lastSoldDateVal[time.Date(2024, 7, 26, 0, 0, 0, 0, time.Local)] = 6745
  186. //lastSoldDateVal[time.Date(2024, 7, 30, 0, 0, 0, 0, time.Local)] = 7272
  187. //
  188. //originData = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
  189. //originData = append(originData, &tradeAnalysisModel.ContractCompanyTradeDataList{
  190. // Date: time.Date(2024, 7, 10, 0, 0, 0, 0, time.Local),
  191. // BuyVal: 14324,
  192. // BuyValType: tradeAnalysisModel.TradeDataTypeOrigin,
  193. // BuyChange: -1107,
  194. // BuyChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  195. // SoldVal: 0,
  196. // SoldValType: tradeAnalysisModel.TradeDataTypeNull,
  197. // SoldChange: 0,
  198. // SoldChangeType: tradeAnalysisModel.TradeDataTypeNull,
  199. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  200. // Date: time.Date(2024, 7, 11, 0, 0, 0, 0, time.Local),
  201. // BuyVal: 14280,
  202. // BuyValType: tradeAnalysisModel.TradeDataTypeOrigin,
  203. // BuyChange: -44,
  204. // BuyChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  205. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  206. // Date: time.Date(2024, 7, 12, 0, 0, 0, 0, time.Local),
  207. // BuyVal: 14214,
  208. // BuyValType: tradeAnalysisModel.TradeDataTypeOrigin,
  209. // BuyChange: -66,
  210. // BuyChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  211. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  212. // Date: time.Date(2024, 7, 15, 0, 0, 0, 0, time.Local),
  213. // BuyVal: 14269,
  214. // BuyValType: tradeAnalysisModel.TradeDataTypeOrigin,
  215. // BuyChange: 55,
  216. // BuyChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  217. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  218. // Date: time.Date(2024, 7, 17, 0, 0, 0, 0, time.Local),
  219. // SoldVal: 5254,
  220. // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
  221. // SoldChange: 708,
  222. // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  223. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  224. // Date: time.Date(2024, 7, 18, 0, 0, 0, 0, time.Local),
  225. // SoldVal: 6595,
  226. // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
  227. // SoldChange: 1341,
  228. // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  229. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  230. // Date: time.Date(2024, 7, 19, 0, 0, 0, 0, time.Local),
  231. // SoldVal: 5938,
  232. // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
  233. // SoldChange: -657,
  234. // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  235. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  236. // Date: time.Date(2024, 7, 22, 0, 0, 0, 0, time.Local),
  237. // SoldVal: 6131,
  238. // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
  239. // SoldChange: 193,
  240. // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  241. //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
  242. // Date: time.Date(2024, 7, 29, 0, 0, 0, 0, time.Local),
  243. // SoldVal: 6679,
  244. // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
  245. // SoldChange: 312,
  246. // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
  247. //})
  248. if len(originData) == 0 {
  249. return
  250. }
  251. if predictRatio < 0 || predictRatio > 1 {
  252. err = fmt.Errorf("估计参数不在0-1之间")
  253. return
  254. }
  255. sort.Slice(originData, func(i, j int) bool {
  256. return originData[i].Date.Before(originData[j].Date)
  257. })
  258. dateVal := make(map[time.Time]*tradeAnalysisModel.ContractCompanyTradeDataList)
  259. for _, v := range originData {
  260. dateVal[v.Date] = v
  261. }
  262. // 生成开始日期-1d(可能会往前面推算一天)至结束日期间的交易日, 以交易日为时间序列遍历
  263. tradeDays := utils.GetTradingDays(originData[0].Date.AddDate(0, 0, -1), originData[len(originData)-1].Date)
  264. for k, v := range tradeDays {
  265. // T日多空均无的情况
  266. //bothLast := false
  267. if dateVal[v] == nil {
  268. // T-1和T+1[原始数据]均无值, 那么T日无数据
  269. hasPrev, hasNext := false, false
  270. if k-1 >= 0 {
  271. hasPrev = true
  272. }
  273. if k+1 <= len(tradeDays)-1 {
  274. hasNext = true
  275. }
  276. if !hasPrev && !hasNext {
  277. continue
  278. }
  279. // T+1有值, 优先从T+1推, 然后继续走下面计算净多单的逻辑
  280. if hasNext {
  281. nextDay := tradeDays[k+1]
  282. if dateVal[nextDay] != nil {
  283. // T+1有多/空及多空变化, 且是原始数据, 那么推出数据并在map中新加一日数据
  284. if dateVal[nextDay].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[nextDay].BuyChangeType == tradeAnalysisModel.TradeDataTypeOrigin {
  285. if _, ok := dateVal[v]; !ok {
  286. dateVal[v] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
  287. dateVal[v].Date = v
  288. }
  289. dateVal[v].BuyVal = dateVal[nextDay].BuyVal - dateVal[nextDay].BuyChange
  290. dateVal[v].BuyValType = tradeAnalysisModel.TradeDataTypeOrigin
  291. }
  292. if dateVal[nextDay].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[nextDay].SoldChangeType == tradeAnalysisModel.TradeDataTypeOrigin {
  293. if _, ok := dateVal[v]; !ok {
  294. dateVal[v] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
  295. dateVal[v].Date = v
  296. }
  297. dateVal[v].SoldVal = dateVal[nextDay].SoldVal - dateVal[nextDay].SoldChange
  298. dateVal[v].SoldValType = tradeAnalysisModel.TradeDataTypeOrigin
  299. }
  300. }
  301. }
  302. // T+1没推出来而T-1有值, 那么T多空均取末位, 计算净多单
  303. _, has := dateVal[v]
  304. if hasPrev && !has {
  305. sv, sok := lastSoldDateVal[v]
  306. bv, bok := lastBuyDateVal[v]
  307. if !sok && !bok {
  308. continue
  309. }
  310. dateVal[v] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
  311. dateVal[v].Date = v
  312. if sok {
  313. dateVal[v].SoldVal = int(predictRatio*float64(sv) + 0.5)
  314. dateVal[v].SoldValType = tradeAnalysisModel.TradeDataTypeCalculate
  315. }
  316. if bok {
  317. dateVal[v].BuyVal = int(predictRatio*float64(bv) + 0.5)
  318. dateVal[v].BuyValType = tradeAnalysisModel.TradeDataTypeCalculate
  319. }
  320. if dateVal[v].BuyValType > tradeAnalysisModel.TradeDataTypeNull && dateVal[v].SoldValType > tradeAnalysisModel.TradeDataTypeNull {
  321. dateVal[v].PureBuyVal = dateVal[v].BuyVal - dateVal[v].SoldVal
  322. dateVal[v].PureBuyValType = tradeAnalysisModel.TradeDataTypeCalculate
  323. }
  324. continue
  325. }
  326. }
  327. // 多空均有的情况下计算净多单
  328. if dateVal[v].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[v].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin {
  329. dateVal[v].PureBuyVal = dateVal[v].BuyVal - dateVal[v].SoldVal
  330. dateVal[v].PureBuyValType = tradeAnalysisModel.TradeDataTypeOrigin // 原始值算出来的也作原始值
  331. }
  332. // 仅有多单, 空单取末位, 计算净多单
  333. if dateVal[v].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[v].SoldValType == tradeAnalysisModel.TradeDataTypeNull {
  334. if sv, ok := lastSoldDateVal[v]; ok {
  335. dateVal[v].SoldVal = int(predictRatio*float64(sv) + 0.5) // 估计参数*末位值, 向上取整
  336. dateVal[v].SoldValType = tradeAnalysisModel.TradeDataTypeCalculate
  337. dateVal[v].PureBuyVal = dateVal[v].BuyVal - dateVal[v].SoldVal
  338. dateVal[v].PureBuyValType = tradeAnalysisModel.TradeDataTypeCalculate
  339. }
  340. }
  341. // 仅有空单, 多单取末位, 计算净多单
  342. if dateVal[v].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[v].BuyValType == tradeAnalysisModel.TradeDataTypeNull {
  343. if sv, ok := lastBuyDateVal[v]; ok {
  344. dateVal[v].BuyVal = int(predictRatio*float64(sv) + 0.5)
  345. dateVal[v].BuyValType = tradeAnalysisModel.TradeDataTypeCalculate
  346. dateVal[v].PureBuyVal = dateVal[v].BuyVal - dateVal[v].SoldVal
  347. dateVal[v].PureBuyValType = tradeAnalysisModel.TradeDataTypeCalculate
  348. }
  349. }
  350. }
  351. // 二次遍历, 计算与T-1的变化值
  352. for k, v := range tradeDays {
  353. // 无T/T-1数据, 忽略
  354. if dateVal[v] == nil {
  355. continue
  356. }
  357. if k-1 < 0 {
  358. continue
  359. }
  360. beforeDay := tradeDays[k-1]
  361. if dateVal[beforeDay] == nil {
  362. continue
  363. }
  364. // 多单变化
  365. if dateVal[v].BuyChangeType == tradeAnalysisModel.TradeDataTypeNull {
  366. if dateVal[v].BuyValType > tradeAnalysisModel.TradeDataTypeNull && dateVal[beforeDay].BuyValType > tradeAnalysisModel.TradeDataTypeNull {
  367. dateVal[v].BuyChange = dateVal[v].BuyVal - dateVal[beforeDay].BuyVal
  368. // 如果当日多单或者前日多单是估计值, 那么多单变化也为估计值
  369. if dateVal[v].BuyValType == tradeAnalysisModel.TradeDataTypeCalculate || dateVal[beforeDay].BuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
  370. dateVal[v].BuyChangeType = tradeAnalysisModel.TradeDataTypeCalculate
  371. }
  372. }
  373. }
  374. // 空单变化
  375. if dateVal[v].SoldChangeType == tradeAnalysisModel.TradeDataTypeNull {
  376. if dateVal[v].SoldValType > tradeAnalysisModel.TradeDataTypeNull && dateVal[beforeDay].SoldValType > tradeAnalysisModel.TradeDataTypeNull {
  377. dateVal[v].SoldChange = dateVal[v].SoldVal - dateVal[beforeDay].SoldVal
  378. // 如果当日空单或者前日空单是估计值, 那么空单变化也为估计值
  379. if dateVal[v].SoldValType == tradeAnalysisModel.TradeDataTypeCalculate || dateVal[beforeDay].SoldValType == tradeAnalysisModel.TradeDataTypeCalculate {
  380. dateVal[v].SoldChangeType = tradeAnalysisModel.TradeDataTypeCalculate
  381. }
  382. }
  383. }
  384. // 净多变化
  385. if dateVal[v].PureBuyChangeType == tradeAnalysisModel.TradeDataTypeNull {
  386. if dateVal[v].PureBuyValType > tradeAnalysisModel.TradeDataTypeNull && dateVal[beforeDay].PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
  387. dateVal[v].PureBuyChange = dateVal[v].PureBuyVal - dateVal[beforeDay].PureBuyVal
  388. dateVal[v].PureBuyChangeType = tradeAnalysisModel.TradeDataTypeOrigin
  389. // 如果当日净多单或者前日净多单是估计值, 那么净多单变化也为估计值
  390. if dateVal[v].PureBuyValType == tradeAnalysisModel.TradeDataTypeCalculate || dateVal[beforeDay].PureBuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
  391. dateVal[v].PureBuyChangeType = tradeAnalysisModel.TradeDataTypeCalculate
  392. }
  393. }
  394. }
  395. }
  396. // 重新遍历map, 生成数据序列并排序
  397. newData = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
  398. for _, v := range dateVal {
  399. if v.BuyValType == tradeAnalysisModel.TradeDataTypeNull && v.SoldValType == tradeAnalysisModel.TradeDataTypeNull {
  400. continue
  401. }
  402. newData = append(newData, v)
  403. }
  404. sort.Slice(newData, func(i, j int) bool {
  405. return newData[i].Date.Before(newData[j].Date)
  406. })
  407. if len(newData) > 0 {
  408. firstDate = newData[0].Date
  409. endDate = newData[len(newData)-1].Date
  410. }
  411. return
  412. }
  413. // GetTopContractRank 获取TOP20根据成交量的合约排名
  414. func GetTopContractRank(exchange string, classifyNames []string, dataDate time.Time) (items []*tradeAnalysisModel.ContractTopRankData, err error) {
  415. // 郑商所/广期所查询方式不一样
  416. var tradeAnalysis TradeAnalysisInterface
  417. switch exchange {
  418. case tradeAnalysisModel.TradeExchangeZhengzhou:
  419. tradeAnalysis = &ZhengzhouTradeAnalysis{}
  420. case tradeAnalysisModel.TradeExchangeGuangzhou:
  421. tradeAnalysis = &GuangzhouTradeAnalysis{}
  422. default:
  423. tradeAnalysis = &BaseTradeAnalysis{}
  424. }
  425. // 郑商所-需要把所选品种转为实际合约进行后续的查询
  426. if exchange == tradeAnalysisModel.TradeExchangeZhengzhou {
  427. classifies, e := GetZhengzhouContractsByClassifyNames(classifyNames)
  428. if e != nil {
  429. err = fmt.Errorf("获取郑商所实际合约失败, %v", e)
  430. return
  431. }
  432. classifyNames = classifies
  433. }
  434. // 获取多单/空单原始数据
  435. rankData, e := tradeAnalysis.GetContractTopRankData(exchange, classifyNames, dataDate)
  436. if e != nil {
  437. err = fmt.Errorf("获取多空单原始数据失败, %v", e)
  438. return
  439. }
  440. items = make([]*tradeAnalysisModel.ContractTopRankData, 0)
  441. for _, v := range rankData {
  442. v.Exchange = exchange
  443. // 郑商所-这里注意把查出来的品种和合约赋值,不然后续是乱的
  444. if v.Exchange == tradeAnalysisModel.TradeExchangeZhengzhou {
  445. v.ClassifyType = v.ClassifyName
  446. v.ClassifyName = GetZhengzhouClassifyName(v.ClassifyName)
  447. }
  448. items = append(items, v)
  449. }
  450. return
  451. }
  452. // GetTableTradeData 获取多空分析表格持仓数据
  453. func GetTableTradeData(exchange string, classifyName string, contracts []string, companyName string, predictRatio float64, startDate, endDate time.Time, contractType int) (companyTradeData []*tradeAnalysisModel.ContractCompanyTradeData, err error) {
  454. companyTradeData = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
  455. // 获取合约持仓数据
  456. contractTradeData, lastBuyVal, lastSoldVal, e := GetContractCompanyTradeData(exchange, []string{classifyName}, contracts, []string{companyName}, startDate, endDate)
  457. if e != nil {
  458. err = fmt.Errorf("获取合约-持仓数据失败, %v", e)
  459. return
  460. }
  461. // 填充[合约-公司]预估数据, 并根据[公司-多合约]分组, [公司]算作一个指标, 指标值为[多个合约]的计算加总
  462. companyContracts := make(map[string][]*tradeAnalysisModel.ContractCompanyTradeData)
  463. for _, v := range contractTradeData {
  464. td, fd, ed, e := PredictingTradeData(v.DataList, lastBuyVal[v.ClassifyType], lastSoldVal[v.ClassifyType], predictRatio)
  465. if e != nil {
  466. err = fmt.Errorf("数据补全失败, %v", e)
  467. return
  468. }
  469. v.DataList = td
  470. v.StartDate = fd
  471. v.EndDate = ed
  472. // 合约类型参数不为合约加总时, 每个合约算一行数据
  473. if contractType != tradeAnalysisModel.ContractQueryTypeTotal {
  474. companyTradeData = append(companyTradeData, v)
  475. continue
  476. }
  477. // 往下计算合约加总
  478. if companyContracts[v.CompanyName] == nil {
  479. companyContracts[v.CompanyName] = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
  480. }
  481. companyContracts[v.CompanyName] = append(companyContracts[v.CompanyName], v)
  482. }
  483. // 类型为合约加总才往下合并
  484. if contractType != tradeAnalysisModel.ContractQueryTypeTotal {
  485. return
  486. }
  487. // 以[公司]为组, 计算合约加总
  488. for k, v := range companyContracts {
  489. companyData := new(tradeAnalysisModel.ContractCompanyTradeData)
  490. companyData.CompanyName = k
  491. companyData.DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
  492. contractArr := make([]string, 0)
  493. // 合约加总
  494. sumDateData := make(map[time.Time]*tradeAnalysisModel.ContractCompanyTradeDataList)
  495. for _, vv := range v {
  496. contractArr = append(contractArr, vv.ClassifyType)
  497. for _, dv := range vv.DataList {
  498. if sumDateData[dv.Date] == nil {
  499. sumDateData[dv.Date] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
  500. sumDateData[dv.Date].Date = dv.Date
  501. }
  502. // 数据类型以第一个非零值为准, 只处理多空和净多, 变化就不管了
  503. if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
  504. sumDateData[dv.Date].BuyValType = dv.BuyValType
  505. }
  506. if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.BuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
  507. sumDateData[dv.Date].BuyValType = dv.BuyValType
  508. }
  509. if dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
  510. sumDateData[dv.Date].BuyVal += dv.BuyVal
  511. }
  512. // 空单
  513. if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeNull && dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
  514. sumDateData[dv.Date].SoldValType = dv.SoldValType
  515. }
  516. if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.SoldValType == tradeAnalysisModel.TradeDataTypeCalculate {
  517. sumDateData[dv.Date].SoldValType = dv.SoldValType
  518. }
  519. if dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
  520. sumDateData[dv.Date].SoldVal += dv.SoldVal
  521. }
  522. // 净多单
  523. if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
  524. sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
  525. }
  526. if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.PureBuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
  527. sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
  528. }
  529. if dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
  530. sumDateData[dv.Date].PureBuyVal += dv.PureBuyVal
  531. }
  532. }
  533. // 多个合约比对开始结束时间
  534. if companyData.StartDate.IsZero() {
  535. companyData.StartDate = vv.StartDate
  536. }
  537. if vv.StartDate.Before(companyData.StartDate) {
  538. companyData.StartDate = vv.StartDate
  539. }
  540. if companyData.EndDate.IsZero() {
  541. companyData.EndDate = vv.EndDate
  542. }
  543. if vv.EndDate.Before(companyData.EndDate) {
  544. companyData.EndDate = vv.EndDate
  545. }
  546. }
  547. for _, sv := range sumDateData {
  548. companyData.DataList = append(companyData.DataList, sv)
  549. }
  550. sort.Slice(companyData.DataList, func(i, j int) bool {
  551. return companyData.DataList[i].Date.Before(companyData.DataList[j].Date)
  552. })
  553. //companyData.ClassifyType = strings.Join(contractArr, ",")
  554. companyData.Exchange = exchange
  555. companyData.CompanyName = k
  556. companyData.ClassifyType = classifyName
  557. companyTradeData = append(companyTradeData, companyData)
  558. }
  559. return
  560. }
  561. // GetCorrelationTableTradeData 获取相关性表格持仓数据
  562. func GetCorrelationTableTradeData(exchange string, classifyName string, contracts, companies []string, predictRatio float64, contractType int) (companyTradeData []*tradeAnalysisModel.ContractCompanyTradeData, err error) {
  563. companyTradeData = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
  564. // 获取合约持仓数据
  565. contractTradeData, lastBuyVal, lastSoldVal, e := GetContractCompanyTradeData(exchange, []string{classifyName}, contracts, companies, time.Time{}, time.Time{})
  566. if e != nil {
  567. err = fmt.Errorf("获取合约-持仓数据失败, %v", e)
  568. return
  569. }
  570. // 填充[合约-公司]预估数据, 并根据[公司-多合约]分组, [公司]算作一个指标, 指标值为[多个合约]的计算加总
  571. companyContracts := make(map[string][]*tradeAnalysisModel.ContractCompanyTradeData)
  572. for _, v := range contractTradeData {
  573. td, fd, ed, e := PredictingTradeData(v.DataList, lastBuyVal[v.ClassifyType], lastSoldVal[v.ClassifyType], predictRatio)
  574. if e != nil {
  575. err = fmt.Errorf("数据补全失败, %v", e)
  576. return
  577. }
  578. v.DataList = td
  579. v.StartDate = fd
  580. v.EndDate = ed
  581. // 合约类型参数不为合约加总时, 每个合约算一行数据
  582. if contractType != tradeAnalysisModel.ContractQueryTypeTotal {
  583. companyTradeData = append(companyTradeData, v)
  584. continue
  585. }
  586. // 往下计算合约加总
  587. if companyContracts[v.CompanyName] == nil {
  588. companyContracts[v.CompanyName] = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
  589. }
  590. companyContracts[v.CompanyName] = append(companyContracts[v.CompanyName], v)
  591. }
  592. // 类型为合约加总才往下合并
  593. if contractType != tradeAnalysisModel.ContractQueryTypeTotal {
  594. return
  595. }
  596. // 以[公司]为组, 计算合约加总
  597. for k, v := range companyContracts {
  598. companyData := new(tradeAnalysisModel.ContractCompanyTradeData)
  599. companyData.CompanyName = k
  600. companyData.DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
  601. contractArr := make([]string, 0)
  602. // 合约加总
  603. sumDateData := make(map[time.Time]*tradeAnalysisModel.ContractCompanyTradeDataList)
  604. for _, vv := range v {
  605. contractArr = append(contractArr, vv.ClassifyType)
  606. for _, dv := range vv.DataList {
  607. if sumDateData[dv.Date] == nil {
  608. sumDateData[dv.Date] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
  609. sumDateData[dv.Date].Date = dv.Date
  610. }
  611. // 数据类型以第一个非零值为准, 只处理多空和净多, 变化就不管了
  612. if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
  613. sumDateData[dv.Date].BuyValType = dv.BuyValType
  614. }
  615. if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.BuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
  616. sumDateData[dv.Date].BuyValType = dv.BuyValType
  617. }
  618. if dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
  619. sumDateData[dv.Date].BuyVal += dv.BuyVal
  620. }
  621. // 空单
  622. if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeNull && dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
  623. sumDateData[dv.Date].SoldValType = dv.SoldValType
  624. }
  625. if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.SoldValType == tradeAnalysisModel.TradeDataTypeCalculate {
  626. sumDateData[dv.Date].SoldValType = dv.SoldValType
  627. }
  628. if dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
  629. sumDateData[dv.Date].SoldVal += dv.SoldVal
  630. }
  631. // 净多单
  632. if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
  633. sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
  634. }
  635. if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.PureBuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
  636. sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
  637. }
  638. if dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
  639. sumDateData[dv.Date].PureBuyVal += dv.PureBuyVal
  640. }
  641. }
  642. // 多个合约比对开始结束时间
  643. if companyData.StartDate.IsZero() {
  644. companyData.StartDate = vv.StartDate
  645. }
  646. if vv.StartDate.Before(companyData.StartDate) {
  647. companyData.StartDate = vv.StartDate
  648. }
  649. if companyData.EndDate.IsZero() {
  650. companyData.EndDate = vv.EndDate
  651. }
  652. if vv.EndDate.Before(companyData.EndDate) {
  653. companyData.EndDate = vv.EndDate
  654. }
  655. }
  656. for _, sv := range sumDateData {
  657. companyData.DataList = append(companyData.DataList, sv)
  658. }
  659. sort.Slice(companyData.DataList, func(i, j int) bool {
  660. return companyData.DataList[i].Date.Before(companyData.DataList[j].Date)
  661. })
  662. //companyData.ClassifyType = strings.Join(contractArr, ",")
  663. companyData.IsTotal = true
  664. companyData.Exchange = exchange
  665. companyData.CompanyName = k
  666. companyData.ClassifyName = classifyName
  667. companyData.ClassifyType = classifyName
  668. companyTradeData = append(companyTradeData, companyData)
  669. }
  670. return
  671. }
  672. // TransTradeData2EdbData 持仓数据转为指标数据
  673. func TransTradeData2EdbData(tradeData []*tradeAnalysisModel.ContractCompanyTradeData, contractPosition int) (edbData []*tradeAnalysisModel.ContractCompanyTradeEdb, edbDataMap []map[time.Time]int, err error) {
  674. if len(tradeData) == 0 {
  675. return
  676. }
  677. edbData = make([]*tradeAnalysisModel.ContractCompanyTradeEdb, 0)
  678. edbDataMap = make([]map[time.Time]int, 0)
  679. for _, v := range tradeData {
  680. newEdb := new(tradeAnalysisModel.ContractCompanyTradeEdb)
  681. newEdb.Exchange = v.Exchange
  682. newEdb.ClassifyName = v.ClassifyName
  683. newEdb.ClassifyType = v.ClassifyType
  684. newEdb.CompanyName = v.CompanyName
  685. newEdb.IsTotal = v.IsTotal
  686. newEdb.ContractPosition = contractPosition
  687. newEdb.StartDate = v.StartDate
  688. newEdb.EndDate = v.EndDate
  689. newEdb.DataList = make([]*tradeAnalysisModel.ContractCompanyTradeEdbData, 0)
  690. dataMap := make(map[time.Time]int)
  691. for _, d := range v.DataList {
  692. var vd int
  693. switch contractPosition {
  694. case tradeAnalysisModel.ContractPositionBuy:
  695. if d.BuyValType == tradeAnalysisModel.TradeDataTypeNull {
  696. continue
  697. }
  698. vd = d.BuyVal
  699. case tradeAnalysisModel.ContractPositionSold:
  700. if d.SoldValType == tradeAnalysisModel.TradeDataTypeNull {
  701. continue
  702. }
  703. vd = d.SoldVal
  704. case tradeAnalysisModel.ContractPositionPureBuy:
  705. if d.PureBuyValType == tradeAnalysisModel.TradeDataTypeNull {
  706. continue
  707. }
  708. vd = d.PureBuyVal
  709. default:
  710. continue
  711. }
  712. newEdb.DataList = append(newEdb.DataList, &tradeAnalysisModel.ContractCompanyTradeEdbData{
  713. DataTime: d.Date,
  714. Val: vd,
  715. })
  716. dataMap[d.Date] = vd
  717. }
  718. edbData = append(edbData, newEdb)
  719. edbDataMap = append(edbDataMap, dataMap)
  720. }
  721. return
  722. }
  723. // GetContractCompanyTradeData 获取合约持仓数据
  724. func GetContractCompanyTradeData(exchange string, classifyNames, contracts, companies []string, startDate, endDate time.Time) (contractTradeData map[string]*tradeAnalysisModel.ContractCompanyTradeData, lastBuyVal, lastSoldVal map[string]map[time.Time]int, err error) {
  725. // 各原始数据表期货公司名称不一致
  726. companyMap := make(map[string]string)
  727. {
  728. ob := new(tradeAnalysisModel.TradeFuturesCompany)
  729. list, e := ob.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
  730. if e != nil {
  731. err = fmt.Errorf("获取期货公司名称失败: %v", e)
  732. return
  733. }
  734. switch exchange {
  735. case "zhengzhou":
  736. for _, v := range list {
  737. companyMap[v.CompanyName] = v.ZhengzhouName
  738. }
  739. case "dalian":
  740. for _, v := range list {
  741. companyMap[v.CompanyName] = v.DalianName
  742. }
  743. case "shanghai":
  744. for _, v := range list {
  745. companyMap[v.CompanyName] = v.ShanghaiName
  746. }
  747. case "cffex":
  748. for _, v := range list {
  749. companyMap[v.CompanyName] = v.CffexName
  750. }
  751. case "ine":
  752. for _, v := range list {
  753. companyMap[v.CompanyName] = v.IneName
  754. }
  755. case "guangzhou":
  756. for _, v := range list {
  757. companyMap[v.CompanyName] = v.GuangzhouName
  758. }
  759. }
  760. }
  761. var queryCompanies []string
  762. for _, v := range companies {
  763. if v == tradeAnalysisModel.TradeFuturesCompanyTop20 {
  764. queryCompanies = append(queryCompanies, tradeAnalysisModel.TradeFuturesCompanyTop20)
  765. continue
  766. }
  767. companyName, ok := companyMap[v]
  768. if !ok {
  769. utils.FileLog.Info(fmt.Sprintf("交易所%s公司名称映射不存在: %s", exchange, v))
  770. continue
  771. }
  772. queryCompanies = append(queryCompanies, companyName)
  773. }
  774. // 郑商所/广期所查询方式不一样
  775. var tradeAnalysis TradeAnalysisInterface
  776. switch exchange {
  777. case tradeAnalysisModel.TradeExchangeZhengzhou:
  778. tradeAnalysis = &ZhengzhouTradeAnalysis{}
  779. case tradeAnalysisModel.TradeExchangeGuangzhou:
  780. tradeAnalysis = &GuangzhouTradeAnalysis{}
  781. default:
  782. tradeAnalysis = &BaseTradeAnalysis{}
  783. }
  784. // 获取多单/空单原始数据
  785. originList, _, lastOriginList, e := tradeAnalysis.GetTradeDataByContracts(exchange, classifyNames, contracts, queryCompanies, startDate, endDate)
  786. if e != nil {
  787. err = fmt.Errorf("获取多空单原始数据失败, %v", e)
  788. return
  789. }
  790. // [合约-期货公司]数据分组
  791. contractTradeData = make(map[string]*tradeAnalysisModel.ContractCompanyTradeData)
  792. {
  793. keyDateData := make(map[string]*tradeAnalysisModel.ContractCompanyTradeDataList)
  794. keyDateDataExist := make(map[string]bool)
  795. for _, v := range originList {
  796. companyName := v.CompanyName
  797. k := fmt.Sprintf("%s-%s", v.ClassifyType, companyName)
  798. if contractTradeData[k] == nil {
  799. contractTradeData[k] = new(tradeAnalysisModel.ContractCompanyTradeData)
  800. contractTradeData[k].Exchange = exchange
  801. contractTradeData[k].CompanyName = companyName
  802. contractTradeData[k].ClassifyName = v.ClassifyName
  803. contractTradeData[k].ClassifyType = v.ClassifyType
  804. contractTradeData[k].DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
  805. }
  806. kd := fmt.Sprintf("%s-%s", k, v.DataTime.Format(utils.FormatDate))
  807. if keyDateData[kd] == nil {
  808. keyDateData[kd] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
  809. keyDateData[kd].Date = v.DataTime
  810. }
  811. if v.ValType == 1 {
  812. keyDateData[kd].BuyVal = v.Val
  813. keyDateData[kd].BuyValType = tradeAnalysisModel.TradeDataTypeOrigin
  814. keyDateData[kd].BuyChange = v.ValChange
  815. keyDateData[kd].BuyChangeType = tradeAnalysisModel.TradeDataTypeOrigin
  816. }
  817. if v.ValType == 2 {
  818. keyDateData[kd].SoldVal = v.Val
  819. keyDateData[kd].SoldValType = tradeAnalysisModel.TradeDataTypeOrigin
  820. keyDateData[kd].SoldChange = v.ValChange
  821. keyDateData[kd].SoldChangeType = tradeAnalysisModel.TradeDataTypeOrigin
  822. }
  823. if !keyDateDataExist[kd] {
  824. contractTradeData[k].DataList = append(contractTradeData[k].DataList, keyDateData[kd])
  825. keyDateDataExist[kd] = true
  826. }
  827. }
  828. }
  829. // 合约的[日期-末位值]
  830. lastBuyVal = make(map[string]map[time.Time]int)
  831. lastSoldVal = make(map[string]map[time.Time]int)
  832. {
  833. for _, v := range lastOriginList {
  834. if v.ValType == 1 {
  835. if lastBuyVal[v.ClassifyType] == nil {
  836. lastBuyVal[v.ClassifyType] = make(map[time.Time]int)
  837. }
  838. lastBuyVal[v.ClassifyType][v.DataTime] = v.Val
  839. continue
  840. }
  841. if lastSoldVal[v.ClassifyType] == nil {
  842. lastSoldVal[v.ClassifyType] = make(map[time.Time]int)
  843. }
  844. lastSoldVal[v.ClassifyType][v.DataTime] = v.Val
  845. }
  846. }
  847. return
  848. }
  849. // GetTradeClassifyNewestDataTime 获取数据最新日期
  850. func GetTradeClassifyNewestDataTime(exchange string, classifyNames []string) (dataTime time.Time, err error) {
  851. var tradeAnalysis TradeAnalysisInterface
  852. switch exchange {
  853. case tradeAnalysisModel.TradeExchangeZhengzhou:
  854. tradeAnalysis = &ZhengzhouTradeAnalysis{}
  855. case tradeAnalysisModel.TradeExchangeGuangzhou:
  856. tradeAnalysis = &GuangzhouTradeAnalysis{}
  857. default:
  858. tradeAnalysis = &BaseTradeAnalysis{}
  859. }
  860. if exchange == tradeAnalysisModel.TradeExchangeZhengzhou {
  861. classifies, e := GetZhengzhouContractsByClassifyNames(classifyNames)
  862. if e != nil {
  863. err = fmt.Errorf("获取郑商所实际合约失败, %v", e)
  864. return
  865. }
  866. classifyNames = classifies
  867. }
  868. d, e := tradeAnalysis.GetClassifyNewestDataTime(exchange, classifyNames)
  869. if e != nil && e.Error() != utils.ErrNoRow() {
  870. err = fmt.Errorf("获取品种最新数据日期失败, %v", e)
  871. return
  872. }
  873. if !d.IsZero() {
  874. dataTime = d
  875. } else {
  876. dataTime = time.Now().Local()
  877. }
  878. return
  879. }