package trade_analysis import ( tradeAnalysisModel "eta/eta_index_lib/models/trade_analysis" "eta/eta_index_lib/utils" "fmt" "sort" "strings" "time" ) // TradeAnalysisInterface 持仓分析查询接口 type TradeAnalysisInterface interface { GetTradeDataByContracts(exchange string, classifyNames, contracts, queryCompanies []string, startDate, endDate time.Time) (items []*tradeAnalysisModel.OriginTradeData, topItems, lastItems []*tradeAnalysisModel.OriginTradeData, err error) GetContractTopRankData(exchange string, classifyNames []string, dataDate time.Time) (items []*tradeAnalysisModel.ContractTopRankData, err error) GetClassifyNewestDataTime(exchange string, classifyNames []string) (dataTime time.Time, err error) } // BaseTradeAnalysis 通用交易所 type BaseTradeAnalysis struct{} // GetTradeDataByContracts 根据合约获取公司的持仓数据、TOP20数据以及每日的末位数据 func (b *BaseTradeAnalysis) GetTradeDataByContracts(exchange string, classifyNames, contracts, queryCompanies []string, startDate, endDate time.Time) (items, topItems, lastItems []*tradeAnalysisModel.OriginTradeData, err error) { // 根据合约获取数据 originData, e := tradeAnalysisModel.GetTradeDataByContracts(exchange, classifyNames, contracts, startDate, endDate) if e != nil { err = fmt.Errorf("根据合约获取持仓数据失败, %v", e) return } items, topItems, lastItems = formatOriginData2UseData(originData, queryCompanies) return } // formatOriginData2UseData 原始数据转换为持仓数据、TOP20以及末位数据 func formatOriginData2UseData(originData []*tradeAnalysisModel.BaseFromTradeCommonIndex, queryCompanies []string) (items, topItems, lastItems []*tradeAnalysisModel.OriginTradeData) { items, topItems, lastItems = make([]*tradeAnalysisModel.OriginTradeData, 0), make([]*tradeAnalysisModel.OriginTradeData, 0), make([]*tradeAnalysisModel.OriginTradeData, 0) buyMaxRank, soldMaxRang := make(map[string]*tradeAnalysisModel.BaseFromTradeCommonIndex), make(map[string]*tradeAnalysisModel.BaseFromTradeCommonIndex) for _, v := range originData { // TOP20(大商所的Rank存在为0的) if v.Rank == 0 || v.Rank == 999 { topBuy := &tradeAnalysisModel.OriginTradeData{ Rank: v.Rank, CompanyName: tradeAnalysisModel.TradeFuturesCompanyTop20, Val: v.BuyValue, ValChange: v.BuyChange, ValType: 1, DataTime: v.DataTime, ClassifyName: v.ClassifyName, ClassifyType: v.ClassifyType, } topSold := &tradeAnalysisModel.OriginTradeData{ Rank: v.Rank, CompanyName: tradeAnalysisModel.TradeFuturesCompanyTop20, Val: v.SoldValue, ValChange: v.SoldChange, ValType: 2, DataTime: v.DataTime, ClassifyName: v.ClassifyName, ClassifyType: v.ClassifyType, } topItems = append(topItems, topBuy, topSold) continue } // 查询的公司-买单 contractDateKey := fmt.Sprintf("%s_%s", v.DataTime.Format(utils.FormatDate), v.ClassifyType) if utils.InArrayByStr(queryCompanies, v.BuyShortName) { items = append(items, &tradeAnalysisModel.OriginTradeData{ Rank: v.Rank, CompanyName: v.BuyShortName, Val: v.BuyValue, ValChange: v.BuyChange, ValType: 1, DataTime: v.DataTime, ClassifyName: v.ClassifyName, ClassifyType: v.ClassifyType, }) // 比对[合约-数据日期]对应的rank,取出末位 if buyMaxRank[contractDateKey] != nil && v.Rank > buyMaxRank[contractDateKey].Rank { buyMaxRank[contractDateKey] = v } if buyMaxRank[contractDateKey] == nil { buyMaxRank[contractDateKey] = v } } // 查询的公司-卖单 if utils.InArrayByStr(queryCompanies, v.SoldShortName) { items = append(items, &tradeAnalysisModel.OriginTradeData{ Rank: v.Rank, CompanyName: v.SoldShortName, Val: v.SoldValue, ValChange: v.SoldChange, ValType: 2, DataTime: v.DataTime, ClassifyName: v.ClassifyName, ClassifyType: v.ClassifyType, }) // 比对数据日期对应的rank,取出末位 if soldMaxRang[contractDateKey] != nil && v.Rank > soldMaxRang[contractDateKey].Rank { soldMaxRang[contractDateKey] = v } if soldMaxRang[contractDateKey] == nil { soldMaxRang[contractDateKey] = v } } } // 如果查询的公司中含TOP20,那么追加进items var hasTop bool if utils.InArrayByStr(queryCompanies, tradeAnalysisModel.TradeFuturesCompanyTop20) { hasTop = true } if hasTop { items = append(items, topItems...) } // 末位数据 for _, v := range buyMaxRank { if v == nil { continue } lastItems = append(lastItems, &tradeAnalysisModel.OriginTradeData{ Rank: v.Rank, CompanyName: v.BuyShortName, Val: v.BuyValue, ValChange: v.BuyChange, ValType: 1, DataTime: v.DataTime, ClassifyName: v.ClassifyName, ClassifyType: v.ClassifyType, }) } for _, v := range buyMaxRank { if v == nil { continue } lastItems = append(lastItems, &tradeAnalysisModel.OriginTradeData{ Rank: v.Rank, CompanyName: v.SoldShortName, Val: v.SoldValue, ValChange: v.SoldChange, ValType: 2, DataTime: v.DataTime, ClassifyName: v.ClassifyName, ClassifyType: v.ClassifyType, }) } return } func (b *BaseTradeAnalysis) GetContractTopRankData(exchange string, classifyNames []string, dataDate time.Time) (items []*tradeAnalysisModel.ContractTopRankData, err error) { return tradeAnalysisModel.GetContractTopRankData(exchange, classifyNames, dataDate) } func (b *BaseTradeAnalysis) GetClassifyNewestDataTime(exchange string, classifyNames []string) (dataTime time.Time, err error) { return tradeAnalysisModel.GetClassifyNewestDataTime(exchange, classifyNames) } // ZhengzhouTradeAnalysis 郑商所 type ZhengzhouTradeAnalysis struct{} func (z *ZhengzhouTradeAnalysis) GetTradeDataByContracts(exchange string, classifyNames, contracts, queryCompanies []string, startDate, endDate time.Time) (items, topItems, lastItems []*tradeAnalysisModel.OriginTradeData, err error) { // 根据品种获取合约 //classifies, e := GetZhengzhouContractsByClassifyNames(classifyNames) //if e != nil { // err = fmt.Errorf("获取郑商所实际合约失败, %v", e) // return //} //contracts = classifies // 根据合约获取数据 originData, e := tradeAnalysisModel.GetZhengzhouTradeDataByContracts(contracts, startDate, endDate) if e != nil { err = fmt.Errorf("根据合约获取持仓数据失败, %v", e) return } items, topItems, lastItems = formatOriginData2UseData(originData, queryCompanies) return } func (z *ZhengzhouTradeAnalysis) GetContractTopRankData(exchange string, classifyNames []string, dataDate time.Time) (items []*tradeAnalysisModel.ContractTopRankData, err error) { return tradeAnalysisModel.GetZhengzhouContractTopRankData(classifyNames, dataDate) } func (z *ZhengzhouTradeAnalysis) GetClassifyNewestDataTime(exchange string, classifyNames []string) (dataTime time.Time, err error) { return tradeAnalysisModel.GetClassifyNewestDataTime(exchange, classifyNames) } // GuangzhouTradeAnalysis 广期所 type GuangzhouTradeAnalysis struct{} func (g *GuangzhouTradeAnalysis) GetTradeDataByContracts(exchange string, classifyNames, contracts, queryCompanies []string, startDate, endDate time.Time) (items, topItems, lastItems []*tradeAnalysisModel.OriginTradeData, err error) { items, topItems, lastItems = make([]*tradeAnalysisModel.OriginTradeData, 0), make([]*tradeAnalysisModel.OriginTradeData, 0), make([]*tradeAnalysisModel.OriginTradeData, 0) // 取品种ID classifyNameId := map[string]int{"si": 7, "lc": 8} classifyIdName := map[int]string{7: "si", 8: "lc"} var classifyIds []int for _, v := range classifyNames { if classifyNameId[v] > 0 { classifyIds = append(classifyIds, classifyNameId[v]) } } // 查询指标 indexes, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouIndex(classifyIds, contracts, "") if e != nil { err = fmt.Errorf("获取广期所指标失败, %v", e) return } var indexIds []int // 过滤掉成交量,只取买单卖单 seatNameArr := []string{tradeAnalysisModel.GuangZhouSeatNameBuy, tradeAnalysisModel.GuangZhouSeatNameSold, tradeAnalysisModel.GuangZhouTopSeatNameBuy, tradeAnalysisModel.GuangZhouTopSeatNameSold} indexInfo := make(map[int]*tradeAnalysisModel.OriginTradeData) // 查询公司中是否含TOP20 var hasTop bool if utils.InArrayByStr(queryCompanies, tradeAnalysisModel.TradeFuturesCompanyTop20) { hasTop = true } isTopIndex := make(map[int]bool) for _, v := range indexes { // eg.永安期货_si2401_持买单量 nameArr := strings.Split(v.IndexName, "_") if len(nameArr) != 3 { continue } companyName := nameArr[0] var isTop bool if nameArr[0] == tradeAnalysisModel.GuangZhouTopCompanyAliasName { isTop = true isTopIndex[v.BaseFromTradeGuangzhouIndexId] = true companyName = tradeAnalysisModel.TradeFuturesCompanyTop20 } if !utils.InArrayByStr(seatNameArr, nameArr[2]) { continue } // 过滤掉非TOP20以及非查询公司 if !isTop && !utils.InArrayByStr(queryCompanies, companyName) { continue } indexIds = append(indexIds, v.BaseFromTradeGuangzhouIndexId) // 指标信息 if indexInfo[v.BaseFromTradeGuangzhouIndexId] == nil { contractType := tradeAnalysisModel.GuangzhouSeatNameValType[nameArr[2]] if contractType == 0 { continue } indexInfo[v.BaseFromTradeGuangzhouIndexId] = new(tradeAnalysisModel.OriginTradeData) indexInfo[v.BaseFromTradeGuangzhouIndexId].CompanyName = companyName indexInfo[v.BaseFromTradeGuangzhouIndexId].ClassifyName = classifyIdName[v.BaseFromTradeGuangzhouClassifyId] indexInfo[v.BaseFromTradeGuangzhouIndexId].ClassifyType = nameArr[1] indexInfo[v.BaseFromTradeGuangzhouIndexId].ValType = contractType } } if len(indexIds) == 0 { return } // 查询指标数据 indexesData, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouDataByIndexIds(indexIds, startDate, endDate) if e != nil { err = fmt.Errorf("获取广期所指标数据失败, %v", e) return } // 取出持仓数据、TOP20,比对末位数据 contractMinData := make(map[string]*tradeAnalysisModel.OriginTradeData) // 合约末位 for _, v := range indexesData { info, ok := indexInfo[v.BaseFromTradeGuangzhouIndexId] if !ok { continue } t := &tradeAnalysisModel.OriginTradeData{ CompanyName: info.CompanyName, Val: int(v.Value), ValChange: int(v.QtySub), DataTime: v.DataTime, ClassifyName: info.ClassifyName, ClassifyType: info.ClassifyType, ValType: info.ValType, } // 如果是TOP20的指标,查询公司中含有TOP20那么追加进items,否则仅追加进topItems, 且TOP20不参与末位数据的比对 if isTopIndex[v.BaseFromTradeGuangzhouIndexId] { if hasTop { items = append(items, t) } topItems = append(topItems, t) continue } items = append(items, t) // 比对末位数据 k := fmt.Sprintf("%s-%d", info.ClassifyType, info.ValType) if contractMinData[k] == nil { contractMinData[k] = t continue } if t.Val < contractMinData[k].Val { contractMinData[k] = t } } // 末位数据 for _, v := range contractMinData { lastItems = append(lastItems, v) } return } func (g *GuangzhouTradeAnalysis) GetContractTopRankData(exchange string, classifyNames []string, dataTime time.Time) (items []*tradeAnalysisModel.ContractTopRankData, err error) { items = make([]*tradeAnalysisModel.ContractTopRankData, 0) // 取品种ID classifyNameId := map[string]int{"si": 7, "lc": 8} classifyIdName := map[int]string{7: "si", 8: "lc"} var classifyIds []int for _, v := range classifyNames { if classifyNameId[v] > 0 { classifyIds = append(classifyIds, classifyNameId[v]) } } // 查询TOP20指标 indexKeyword := fmt.Sprint("%", tradeAnalysisModel.GuangZhouTopCompanyAliasName, "%") indexes, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouIndex(classifyIds, []string{}, indexKeyword) if e != nil { err = fmt.Errorf("获取广期所指标失败, %v", e) return } var indexIds []int indexIdContract := make(map[int]string) // [指标ID-合约_方向] contractRankData := make(map[string]*tradeAnalysisModel.ContractTopRankData) // [合约-合约TOP数据] for _, v := range indexes { // eg.永安期货_si2401_持买单量 nameArr := strings.Split(v.IndexName, "_") if len(nameArr) != 3 { continue } contractCode := nameArr[1] indexIds = append(indexIds, v.BaseFromTradeGuangzhouIndexId) // 指标对应的[合约+方向] k := fmt.Sprintf("%s_%d", contractCode, tradeAnalysisModel.GuangzhouSeatNameValType[nameArr[2]]) indexIdContract[v.BaseFromTradeGuangzhouIndexId] = k // 合约对应的数据 if contractRankData[contractCode] == nil { contractRankData[contractCode] = new(tradeAnalysisModel.ContractTopRankData) contractRankData[contractCode].Exchange = exchange contractRankData[contractCode].ClassifyName = classifyIdName[v.BaseFromTradeGuangzhouClassifyId] contractRankData[contractCode].ClassifyType = contractCode contractRankData[contractCode].DataTime = dataTime } } if len(indexIds) == 0 { return } // 查询指标数据 indexesData, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouDataByIndexIds(indexIds, dataTime, dataTime) if e != nil { err = fmt.Errorf("获取广期所指标数据失败, %v", e) return } for _, v := range indexesData { k := indexIdContract[v.BaseFromTradeGuangzhouIndexId] if k == "" { continue } nameArr := strings.Split(k, "_") if len(nameArr) != 2 { continue } contractCode := nameArr[0] if contractRankData[contractCode] == nil { continue } // 根据方向赋值:1-多单;2-空单;3-成交量 switch nameArr[1] { case "1": contractRankData[contractCode].BuyValue = int(v.Value) case "2": contractRankData[contractCode].SoldValue = int(v.Value) case "3": contractRankData[contractCode].DealValue = int(v.Value) default: continue } } // 根据成交量排序并返回排名数据 for _, v := range contractRankData { items = append(items, v) } sort.Slice(items, func(i, j int) bool { return items[i].DealValue > items[j].DealValue }) return } func (g *GuangzhouTradeAnalysis) GetClassifyNewestDataTime(exchange string, classifyNames []string) (dataTime time.Time, err error) { // 取品种ID classifyNameId := map[string]int{"si": 7, "lc": 8} var classifyIds []int for _, v := range classifyNames { if classifyNameId[v] > 0 { classifyIds = append(classifyIds, classifyNameId[v]) } } // 查询TOP20的最新日期 indexKeyword := fmt.Sprint("%", tradeAnalysisModel.GuangZhouTopCompanyAliasName, "%") indexes, e := tradeAnalysisModel.GetBaseFromTradeGuangzhouIndex(classifyIds, []string{}, indexKeyword) if e != nil { err = fmt.Errorf("获取广期所指标失败, %v", e) return } var indexIds []int for _, v := range indexes { // eg.永安期货_si2401_持买单量 nameArr := strings.Split(v.IndexName, "_") if len(nameArr) != 3 { continue } indexIds = append(indexIds, v.BaseFromTradeGuangzhouIndexId) } if len(indexIds) == 0 { return } d, e := tradeAnalysisModel.GetGuangzhouClassifyNewestDataTime(indexIds) if e != nil { err = fmt.Errorf("获取广期品种最新数据失败, %v", e) return } dataTime = d return }