trade_analysis_interface.go 13 KB

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