trade_analysis_interface.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. package trade_analysis
  2. import (
  3. tradeAnalysisModel "eta/eta_api/models/data_manage/trade_analysis"
  4. "eta/eta_api/utils"
  5. "fmt"
  6. "sort"
  7. "strings"
  8. "time"
  9. )
  10. // TradeAnalysisInterface 持仓分析查询接口
  11. type TradeAnalysisInterface interface {
  12. GetTradeDataByContracts(exchange string, classifyNames, contracts, queryCompanies []string, startDate, endDate time.Time) (items []*tradeAnalysisModel.OriginTradeData, topItems, lastItems []*tradeAnalysisModel.OriginTradeData, err error)
  13. GetContractTopRankData(exchange string, classifyNames []string, dataDate time.Time) (items []*tradeAnalysisModel.ContractTopRankData, err error)
  14. GetClassifyNewestDataTime(exchange string, classifyNames []string) (dataTime time.Time, err error)
  15. }
  16. // BaseTradeAnalysis 通用交易所
  17. type BaseTradeAnalysis struct{}
  18. // GetTradeDataByContracts 根据合约获取公司的持仓数据、TOP20数据以及每日的末位数据
  19. func (b *BaseTradeAnalysis) GetTradeDataByContracts(exchange string, classifyNames, contracts, queryCompanies []string, startDate, endDate time.Time) (items, topItems, lastItems []*tradeAnalysisModel.OriginTradeData, err error) {
  20. // 根据合约获取数据
  21. originData, e := tradeAnalysisModel.GetTradeDataByContracts(exchange, classifyNames, contracts, startDate, endDate)
  22. if e != nil {
  23. err = fmt.Errorf("根据合约获取持仓数据失败, %v", e)
  24. return
  25. }
  26. items, topItems, lastItems = formatOriginData2UseData(originData, queryCompanies)
  27. return
  28. }
  29. // formatOriginData2UseData 原始数据转换为持仓数据、TOP20以及末位数据
  30. func formatOriginData2UseData(originData []*tradeAnalysisModel.BaseFromTradeCommonIndex, queryCompanies []string) (items, topItems, lastItems []*tradeAnalysisModel.OriginTradeData) {
  31. items, topItems, lastItems = make([]*tradeAnalysisModel.OriginTradeData, 0), make([]*tradeAnalysisModel.OriginTradeData, 0), make([]*tradeAnalysisModel.OriginTradeData, 0)
  32. buyMaxRank, soldMaxRang := make(map[string]*tradeAnalysisModel.BaseFromTradeCommonIndex), make(map[string]*tradeAnalysisModel.BaseFromTradeCommonIndex)
  33. for _, v := range originData {
  34. // TOP20(大商所的Rank存在为0的)
  35. if v.Rank == 0 || v.Rank == 999 {
  36. topBuy := &tradeAnalysisModel.OriginTradeData{
  37. Rank: v.Rank,
  38. CompanyName: tradeAnalysisModel.TradeFuturesCompanyTop20,
  39. Val: v.BuyValue,
  40. ValChange: v.BuyChange,
  41. ValType: 1,
  42. DataTime: v.DataTime,
  43. ClassifyName: v.ClassifyName,
  44. ClassifyType: v.ClassifyType,
  45. }
  46. topSold := &tradeAnalysisModel.OriginTradeData{
  47. Rank: v.Rank,
  48. CompanyName: tradeAnalysisModel.TradeFuturesCompanyTop20,
  49. Val: v.SoldValue,
  50. ValChange: v.SoldChange,
  51. ValType: 2,
  52. DataTime: v.DataTime,
  53. ClassifyName: v.ClassifyName,
  54. ClassifyType: v.ClassifyType,
  55. }
  56. topItems = append(topItems, topBuy, topSold)
  57. continue
  58. }
  59. // 查询的公司-买单
  60. contractDateKey := fmt.Sprintf("%s_%s", v.DataTime.Format(utils.FormatDate), v.ClassifyType)
  61. if utils.InArrayByStr(queryCompanies, v.BuyShortName) {
  62. items = append(items, &tradeAnalysisModel.OriginTradeData{
  63. Rank: v.Rank,
  64. CompanyName: v.BuyShortName,
  65. Val: v.BuyValue,
  66. ValChange: v.BuyChange,
  67. ValType: 1,
  68. DataTime: v.DataTime,
  69. ClassifyName: v.ClassifyName,
  70. ClassifyType: v.ClassifyType,
  71. })
  72. // 比对[合约-数据日期]对应的rank,取出末位
  73. if buyMaxRank[contractDateKey] != nil && v.Rank > buyMaxRank[contractDateKey].Rank {
  74. buyMaxRank[contractDateKey] = v
  75. }
  76. if buyMaxRank[contractDateKey] == nil {
  77. buyMaxRank[contractDateKey] = v
  78. }
  79. }
  80. // 查询的公司-卖单
  81. if utils.InArrayByStr(queryCompanies, v.SoldShortName) {
  82. items = append(items, &tradeAnalysisModel.OriginTradeData{
  83. Rank: v.Rank,
  84. CompanyName: v.SoldShortName,
  85. Val: v.SoldValue,
  86. ValChange: v.SoldChange,
  87. ValType: 2,
  88. DataTime: v.DataTime,
  89. ClassifyName: v.ClassifyName,
  90. ClassifyType: v.ClassifyType,
  91. })
  92. // 比对数据日期对应的rank,取出末位
  93. if soldMaxRang[contractDateKey] != nil && v.Rank > soldMaxRang[contractDateKey].Rank {
  94. soldMaxRang[contractDateKey] = v
  95. }
  96. if soldMaxRang[contractDateKey] == nil {
  97. soldMaxRang[contractDateKey] = v
  98. }
  99. }
  100. }
  101. // 如果查询的公司中含TOP20,那么追加进items
  102. var hasTop bool
  103. if utils.InArrayByStr(queryCompanies, tradeAnalysisModel.TradeFuturesCompanyTop20) {
  104. hasTop = true
  105. }
  106. if hasTop {
  107. items = append(items, topItems...)
  108. }
  109. // 末位数据
  110. for _, v := range buyMaxRank {
  111. if v == nil {
  112. continue
  113. }
  114. lastItems = append(lastItems, &tradeAnalysisModel.OriginTradeData{
  115. Rank: v.Rank,
  116. CompanyName: v.BuyShortName,
  117. Val: v.BuyValue,
  118. ValChange: v.BuyChange,
  119. ValType: 1,
  120. DataTime: v.DataTime,
  121. ClassifyName: v.ClassifyName,
  122. ClassifyType: v.ClassifyType,
  123. })
  124. }
  125. for _, v := range buyMaxRank {
  126. if v == nil {
  127. continue
  128. }
  129. lastItems = append(lastItems, &tradeAnalysisModel.OriginTradeData{
  130. Rank: v.Rank,
  131. CompanyName: v.SoldShortName,
  132. Val: v.SoldValue,
  133. ValChange: v.SoldChange,
  134. ValType: 2,
  135. DataTime: v.DataTime,
  136. ClassifyName: v.ClassifyName,
  137. ClassifyType: v.ClassifyType,
  138. })
  139. }
  140. return
  141. }
  142. func (b *BaseTradeAnalysis) GetContractTopRankData(exchange string, classifyNames []string, dataDate time.Time) (items []*tradeAnalysisModel.ContractTopRankData, err error) {
  143. return tradeAnalysisModel.GetContractTopRankData(exchange, classifyNames, dataDate)
  144. }
  145. func (b *BaseTradeAnalysis) GetClassifyNewestDataTime(exchange string, classifyNames []string) (dataTime time.Time, err error) {
  146. return tradeAnalysisModel.GetClassifyNewestDataTime(exchange, classifyNames)
  147. }
  148. // ZhengzhouTradeAnalysis 郑商所
  149. type ZhengzhouTradeAnalysis struct{}
  150. func (z *ZhengzhouTradeAnalysis) GetTradeDataByContracts(exchange string, classifyNames, contracts, queryCompanies []string, startDate, endDate time.Time) (items, topItems, lastItems []*tradeAnalysisModel.OriginTradeData, err error) {
  151. // 根据品种获取合约
  152. //classifies, e := GetZhengzhouContractsByClassifyNames(classifyNames)
  153. //if e != nil {
  154. // err = fmt.Errorf("获取郑商所实际合约失败, %v", e)
  155. // return
  156. //}
  157. //contracts = classifies
  158. // 根据合约获取数据
  159. originData, e := tradeAnalysisModel.GetZhengzhouTradeDataByContracts(contracts, startDate, endDate)
  160. if e != nil {
  161. err = fmt.Errorf("根据合约获取持仓数据失败, %v", e)
  162. return
  163. }
  164. items, topItems, lastItems = formatOriginData2UseData(originData, queryCompanies)
  165. return
  166. }
  167. func (z *ZhengzhouTradeAnalysis) GetContractTopRankData(exchange string, classifyNames []string, dataDate time.Time) (items []*tradeAnalysisModel.ContractTopRankData, err error) {
  168. return tradeAnalysisModel.GetZhengzhouContractTopRankData(classifyNames, dataDate)
  169. }
  170. func (z *ZhengzhouTradeAnalysis) GetClassifyNewestDataTime(exchange string, classifyNames []string) (dataTime time.Time, err error) {
  171. return tradeAnalysisModel.GetClassifyNewestDataTime(exchange, classifyNames)
  172. }
  173. // GuangzhouTradeAnalysis 广期所
  174. type GuangzhouTradeAnalysis struct{}
  175. func (g *GuangzhouTradeAnalysis) GetTradeDataByContracts(exchange string, classifyNames, contracts, queryCompanies []string, startDate, endDate time.Time) (items, topItems, lastItems []*tradeAnalysisModel.OriginTradeData, err error) {
  176. items, topItems, lastItems = make([]*tradeAnalysisModel.OriginTradeData, 0), make([]*tradeAnalysisModel.OriginTradeData, 0), make([]*tradeAnalysisModel.OriginTradeData, 0)
  177. // 取品种ID
  178. classifyNameId := map[string]int{"si": 7, "lc": 8}
  179. classifyIdName := map[int]string{7: "si", 8: "lc"}
  180. var classifyIds []int
  181. for _, v := range classifyNames {
  182. if classifyNameId[v] > 0 {
  183. classifyIds = append(classifyIds, classifyNameId[v])
  184. }
  185. }
  186. // 查询指标
  187. indexes, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouIndex(classifyIds, contracts, "")
  188. if e != nil {
  189. err = fmt.Errorf("获取广期所指标失败, %v", e)
  190. return
  191. }
  192. var indexIds []int
  193. // 过滤掉成交量,只取买单卖单
  194. seatNameArr := []string{tradeAnalysisModel.GuangZhouSeatNameBuy, tradeAnalysisModel.GuangZhouSeatNameSold, tradeAnalysisModel.GuangZhouTopSeatNameBuy, tradeAnalysisModel.GuangZhouTopSeatNameSold}
  195. indexInfo := make(map[int]*tradeAnalysisModel.OriginTradeData)
  196. // 查询公司中是否含TOP20
  197. var hasTop bool
  198. if utils.InArrayByStr(queryCompanies, tradeAnalysisModel.TradeFuturesCompanyTop20) {
  199. hasTop = true
  200. }
  201. isTopIndex := make(map[int]bool)
  202. for _, v := range indexes {
  203. // eg.永安期货_si2401_持买单量
  204. nameArr := strings.Split(v.IndexName, "_")
  205. if len(nameArr) != 3 {
  206. continue
  207. }
  208. companyName := nameArr[0]
  209. var isTop bool
  210. if nameArr[0] == tradeAnalysisModel.GuangZhouTopCompanyAliasName {
  211. isTop = true
  212. isTopIndex[v.BaseFromTradeGuangzhouIndexId] = true
  213. companyName = tradeAnalysisModel.TradeFuturesCompanyTop20
  214. }
  215. if !utils.InArrayByStr(seatNameArr, nameArr[2]) {
  216. continue
  217. }
  218. // 过滤掉非TOP20以及非查询公司
  219. if !isTop && !utils.InArrayByStr(queryCompanies, companyName) {
  220. continue
  221. }
  222. indexIds = append(indexIds, v.BaseFromTradeGuangzhouIndexId)
  223. // 指标信息
  224. if indexInfo[v.BaseFromTradeGuangzhouIndexId] == nil {
  225. contractType := tradeAnalysisModel.GuangzhouSeatNameValType[nameArr[2]]
  226. if contractType == 0 {
  227. continue
  228. }
  229. indexInfo[v.BaseFromTradeGuangzhouIndexId] = new(tradeAnalysisModel.OriginTradeData)
  230. indexInfo[v.BaseFromTradeGuangzhouIndexId].CompanyName = companyName
  231. indexInfo[v.BaseFromTradeGuangzhouIndexId].ClassifyName = classifyIdName[v.BaseFromTradeGuangzhouClassifyId]
  232. indexInfo[v.BaseFromTradeGuangzhouIndexId].ClassifyType = nameArr[1]
  233. indexInfo[v.BaseFromTradeGuangzhouIndexId].ValType = contractType
  234. }
  235. }
  236. if len(indexIds) == 0 {
  237. return
  238. }
  239. // 查询指标数据
  240. indexesData, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouDataByIndexIds(indexIds, startDate, endDate)
  241. if e != nil {
  242. err = fmt.Errorf("获取广期所指标数据失败, %v", e)
  243. return
  244. }
  245. // 取出持仓数据、TOP20,比对末位数据
  246. contractMinData := make(map[string]*tradeAnalysisModel.OriginTradeData) // 合约末位
  247. for _, v := range indexesData {
  248. info, ok := indexInfo[v.BaseFromTradeGuangzhouIndexId]
  249. if !ok {
  250. continue
  251. }
  252. t := &tradeAnalysisModel.OriginTradeData{
  253. CompanyName: info.CompanyName,
  254. Val: int(v.Value),
  255. ValChange: int(v.QtySub),
  256. DataTime: v.DataTime,
  257. ClassifyName: info.ClassifyName,
  258. ClassifyType: info.ClassifyType,
  259. ValType: info.ValType,
  260. }
  261. // 如果是TOP20的指标,查询公司中含有TOP20那么追加进items,否则仅追加进topItems, 且TOP20不参与末位数据的比对
  262. if isTopIndex[v.BaseFromTradeGuangzhouIndexId] {
  263. if hasTop {
  264. items = append(items, t)
  265. }
  266. topItems = append(topItems, t)
  267. continue
  268. }
  269. items = append(items, t)
  270. // 比对末位数据
  271. k := fmt.Sprintf("%s-%d", info.ClassifyType, info.ValType)
  272. if contractMinData[k] == nil {
  273. contractMinData[k] = t
  274. continue
  275. }
  276. if t.Val < contractMinData[k].Val {
  277. contractMinData[k] = t
  278. }
  279. }
  280. // 末位数据
  281. for _, v := range contractMinData {
  282. lastItems = append(lastItems, v)
  283. }
  284. return
  285. }
  286. func (g *GuangzhouTradeAnalysis) GetContractTopRankData(exchange string, classifyNames []string, dataTime time.Time) (items []*tradeAnalysisModel.ContractTopRankData, err error) {
  287. items = make([]*tradeAnalysisModel.ContractTopRankData, 0)
  288. // 取品种ID
  289. classifyNameId := map[string]int{"si": 7, "lc": 8}
  290. classifyIdName := map[int]string{7: "si", 8: "lc"}
  291. var classifyIds []int
  292. for _, v := range classifyNames {
  293. if classifyNameId[v] > 0 {
  294. classifyIds = append(classifyIds, classifyNameId[v])
  295. }
  296. }
  297. // 查询TOP20指标
  298. indexKeyword := fmt.Sprint("%", tradeAnalysisModel.GuangZhouTopCompanyAliasName, "%")
  299. indexes, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouIndex(classifyIds, []string{}, indexKeyword)
  300. if e != nil {
  301. err = fmt.Errorf("获取广期所指标失败, %v", e)
  302. return
  303. }
  304. var indexIds []int
  305. indexIdContract := make(map[int]string) // [指标ID-合约_方向]
  306. contractRankData := make(map[string]*tradeAnalysisModel.ContractTopRankData) // [合约-合约TOP数据]
  307. for _, v := range indexes {
  308. // eg.永安期货_si2401_持买单量
  309. nameArr := strings.Split(v.IndexName, "_")
  310. if len(nameArr) != 3 {
  311. continue
  312. }
  313. contractCode := nameArr[1]
  314. indexIds = append(indexIds, v.BaseFromTradeGuangzhouIndexId)
  315. // 指标对应的[合约+方向]
  316. k := fmt.Sprintf("%s_%d", contractCode, tradeAnalysisModel.GuangzhouSeatNameValType[nameArr[2]])
  317. indexIdContract[v.BaseFromTradeGuangzhouIndexId] = k
  318. // 合约对应的数据
  319. if contractRankData[contractCode] == nil {
  320. contractRankData[contractCode] = new(tradeAnalysisModel.ContractTopRankData)
  321. contractRankData[contractCode].Exchange = exchange
  322. contractRankData[contractCode].ClassifyName = classifyIdName[v.BaseFromTradeGuangzhouClassifyId]
  323. contractRankData[contractCode].ClassifyType = contractCode
  324. contractRankData[contractCode].DataTime = dataTime
  325. }
  326. }
  327. if len(indexIds) == 0 {
  328. return
  329. }
  330. // 查询指标数据
  331. indexesData, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouDataByIndexIds(indexIds, dataTime, dataTime)
  332. if e != nil {
  333. err = fmt.Errorf("获取广期所指标数据失败, %v", e)
  334. return
  335. }
  336. for _, v := range indexesData {
  337. k := indexIdContract[v.BaseFromTradeGuangzhouIndexId]
  338. if k == "" {
  339. continue
  340. }
  341. nameArr := strings.Split(k, "_")
  342. if len(nameArr) != 2 {
  343. continue
  344. }
  345. contractCode := nameArr[0]
  346. if contractRankData[contractCode] == nil {
  347. continue
  348. }
  349. // 根据方向赋值:1-多单;2-空单;3-成交量
  350. switch nameArr[1] {
  351. case "1":
  352. contractRankData[contractCode].BuyValue = int(v.Value)
  353. case "2":
  354. contractRankData[contractCode].SoldValue = int(v.Value)
  355. case "3":
  356. contractRankData[contractCode].DealValue = int(v.Value)
  357. default:
  358. continue
  359. }
  360. }
  361. // 根据成交量排序并返回排名数据
  362. for _, v := range contractRankData {
  363. items = append(items, v)
  364. }
  365. sort.Slice(items, func(i, j int) bool {
  366. return items[i].DealValue > items[j].DealValue
  367. })
  368. return
  369. }
  370. func (g *GuangzhouTradeAnalysis) GetClassifyNewestDataTime(exchange string, classifyNames []string) (dataTime time.Time, err error) {
  371. // 取品种ID
  372. classifyNameId := map[string]int{"si": 7, "lc": 8}
  373. var classifyIds []int
  374. for _, v := range classifyNames {
  375. if classifyNameId[v] > 0 {
  376. classifyIds = append(classifyIds, classifyNameId[v])
  377. }
  378. }
  379. // 查询TOP20的最新日期
  380. indexKeyword := fmt.Sprint("%", tradeAnalysisModel.GuangZhouTopCompanyAliasName, "%")
  381. indexes, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouIndex(classifyIds, []string{}, indexKeyword)
  382. if e != nil {
  383. err = fmt.Errorf("获取广期所指标失败, %v", e)
  384. return
  385. }
  386. var indexIds []int
  387. for _, v := range indexes {
  388. // eg.永安期货_si2401_持买单量
  389. nameArr := strings.Split(v.IndexName, "_")
  390. if len(nameArr) != 3 {
  391. continue
  392. }
  393. indexIds = append(indexIds, v.BaseFromTradeGuangzhouIndexId)
  394. }
  395. if len(indexIds) == 0 {
  396. return
  397. }
  398. d, e := tradeAnalysisModel.GetGuangzhouClassifyNewestDataTime(indexIds)
  399. if e != nil {
  400. err = fmt.Errorf("获取广期品种最新数据失败, %v", e)
  401. return
  402. }
  403. dataTime = d
  404. return
  405. }