package trade_analysis import ( tradeAnalysisModel "eta/eta_api/models/data_manage/trade_analysis" "eta/eta_api/utils" "fmt" "math" "time" ) // CheckAnalysisTableExtraConfig 校验表格配置 func CheckAnalysisTableExtraConfig(extraConfig tradeAnalysisModel.TableExtraConfig) (pass bool, tips string) { if extraConfig.CompanyName == "" { tips = "请选择期货公司" return } if len(extraConfig.ClassifyList) == 0 { tips = "请选择品种" return } var classifyTotal int for _, v := range extraConfig.ClassifyList { if v.Exchange == "" { tips = "请选择交易所" return } if len(v.ClassifyNames) == 0 { tips = "请选择品种" return } classifyTotal += len(v.ClassifyNames) } // TODO:品种选择上限 if classifyTotal > 5 { tips = "选择品种不超过5个" return } typeArr := []int{tradeAnalysisModel.ContractQueryTypeTop, tradeAnalysisModel.ContractQueryTypeTop2, tradeAnalysisModel.ContractQueryTypeTop3, tradeAnalysisModel.ContractQueryTypeAll, tradeAnalysisModel.ContractQueryTypeTotal} if !utils.InArrayByInt(typeArr, extraConfig.ContractType) { tips = "请选择正确的合约" return } if extraConfig.DateType == 1 && extraConfig.FixedDate == "" { tips = "请选择固定日期" return } if extraConfig.FixedDate != "" { _, e := time.Parse(utils.FormatDate, extraConfig.FixedDate) if e != nil { tips = "固定日期格式有误" return } } if extraConfig.PredictRatio < 0 || extraConfig.PredictRatio > 1 { tips = "请输入正确的估计参数" return } pass = true return } // GetAnalysisTableBaseDate 根据配置获取基准交易日期 func GetAnalysisTableBaseDate(dateType, intervalMove int, fixedDate string) (baseDate time.Time, err error) { if dateType == 1 { // 固定日期 t, _ := time.ParseInLocation(utils.FormatDate, fixedDate, time.Local) baseDate = t } else { // 最新交易日 st := time.Now().AddDate(0, 0, -7) // 默认前移7天, 在开始结束区间内取出指定交易日 if intervalMove > 0 { period := intervalMove * 7 st = st.AddDate(0, 0, -period) } tradeDates := utils.GetTradingDays(st, time.Now()) dateLen := len(tradeDates) if dateLen == 0 { err = fmt.Errorf("交易日序列异常") return } index := dateLen - 1 if intervalMove > 0 { index -= intervalMove } if index < 0 || index > dateLen { err = fmt.Errorf("交易日序列异常") return } baseDate = tradeDates[index] } return } // CalculateTableRowData 计算表格行数据 func CalculateTableRowData(exchange string, baseDate time.Time, topData []*tradeAnalysisModel.ContractTopRankData, contractsData []*tradeAnalysisModel.ContractCompanyTradeData) (rows []*tradeAnalysisModel.TableRowData, err error) { contractTopData := make(map[string]*tradeAnalysisModel.ContractTopRankData) for _, v := range topData { contractTopData[v.ClassifyType] = v } rows = make([]*tradeAnalysisModel.TableRowData, 0) for _, v := range contractsData { // 取出基准日期的数据 cd := new(tradeAnalysisModel.ContractCompanyTradeDataList) for _, d := range v.DataList { if d.Date.Equal(baseDate) { cd = d break } } // 合约基准日期无数据 if cd.Date.IsZero() { continue } td, ok := contractTopData[v.ClassifyType] if !ok { // 无前20数据 continue } row := new(tradeAnalysisModel.TableRowData) row.Exchange = exchange row.ClassifyName = td.ClassifyName row.ClassifyType = v.ClassifyType row.BuyValue = cd.BuyVal row.BuyChange = cd.BuyChange row.SoldValue = cd.SoldVal row.SoldChange = cd.SoldChange row.PureBuyVal = cd.PureBuyVal row.PureBuyChange = cd.PureBuyChange row.TopBuyValue = td.BuyValue row.TopSoldValue = td.SoldValue row.TopBuyChange = td.BuyChange row.TopSoldChange = td.SoldChange // 计算值 row.BuySoldRatio = math.Round(float64(cd.BuyVal)/float64(cd.BuyVal+cd.SoldVal)*100) / 100 row.BuyTopRatio = math.Round(float64(cd.BuyVal)/float64(td.BuyValue)*100) / 100 row.SoldTopRatio = math.Round(float64(cd.SoldVal)/float64(td.SoldValue)*100) / 100 row.TopPureBuy = td.BuyValue - td.SoldValue row.TopPureBuyChange = int(math.Abs(float64(td.BuyChange))) + int(math.Abs(float64(td.SoldChange))) // 净多变化=Abs(多单变化)+Abs(空单变化) row.TopBuySoldRatio = math.Round(float64(td.BuyValue)/float64(td.BuyValue+td.SoldValue)*100) / 100 rows = append(rows, row) } return } // GetTableRowsDataByConfig 根据配置获取表格行数据 func GetTableRowsDataByConfig(tableConfig tradeAnalysisModel.TableExtraConfig) (tableRows []*tradeAnalysisModel.TableRowData, err error) { // 基准日期 baseDate, e := GetAnalysisTableBaseDate(tableConfig.DateType, tableConfig.IntervalMove, tableConfig.FixedDate) if e != nil { err = fmt.Errorf("获取基准日期失败, %v", e) return } // 查询基准日期TOP20合约排名, 根据类型取出合约数 exchangeContracts := make(map[string][]*tradeAnalysisModel.ContractTopRankData) // 交易所最终取的合约 var contractMax int // 需要取出的品种对应的最大合约数 classifyMax := make(map[string]int) // 品种对应的合约数 switch tableConfig.ContractType { case tradeAnalysisModel.ContractQueryTypeTop: contractMax = 1 case tradeAnalysisModel.ContractQueryTypeTop2: contractMax = 2 case tradeAnalysisModel.ContractQueryTypeTop3: contractMax = 3 case tradeAnalysisModel.ContractQueryTypeAll, tradeAnalysisModel.ContractQueryTypeTotal: contractMax = 999 } // 遍历交易所, 查询各品种下的合约排名情况及TOP当日的多空单数据 var sortContract []string for _, v := range tableConfig.ClassifyList { contractRanks, e := GetTopContractRank(v.Exchange, v.ClassifyNames, baseDate) if e != nil { err = fmt.Errorf("获取基准日期合约排名失败, %v", e) return } if len(contractRanks) == 0 { continue } // ps.正常来讲这里查出来的合约是唯一的, 根据品种分组, 取出ContractType所需的合约数 for _, rd := range contractRanks { if classifyMax[rd.ClassifyName] >= contractMax { continue } classifyMax[rd.ClassifyName] += 1 if exchangeContracts[rd.Exchange] == nil { exchangeContracts[rd.Exchange] = make([]*tradeAnalysisModel.ContractTopRankData, 0) } exchangeContracts[rd.Exchange] = append(exchangeContracts[rd.Exchange], rd) sortContract = append(sortContract, rd.ClassifyType) } } // 查询对应品种与合约一周前后的多空单,填充预估值 mussyRows := make([]*tradeAnalysisModel.TableRowData, 0) for exchange, contracts := range exchangeContracts { var classifyNames, classifyTypes []string for _, v := range contracts { if !utils.InArrayByStr(classifyNames, v.ClassifyName) { classifyNames = append(classifyNames, v.ClassifyName) } if !utils.InArrayByStr(classifyTypes, v.ClassifyType) { classifyTypes = append(classifyTypes, v.ClassifyType) } } contractRowData, e := GetTableTradeData(exchange, classifyNames, classifyTypes, []string{tableConfig.CompanyName}, tableConfig.PredictRatio, baseDate.AddDate(0, 0, -5), baseDate.AddDate(0, 0, 5), tableConfig.ContractType) if e != nil { err = fmt.Errorf("获取公司合约多空单数据失败, %v", e) return } if len(contractRowData) == 0 { continue } // 计算行数据 rows, e := CalculateTableRowData(exchange, baseDate, contracts, contractRowData) if e != nil { err = fmt.Errorf("计算合约数据失败, %v", e) return } mussyRows = append(mussyRows, rows...) } // 排序 tableRows = make([]*tradeAnalysisModel.TableRowData, 0) contractRow := make(map[string]*tradeAnalysisModel.TableRowData) for _, v := range mussyRows { contractRow[v.ClassifyType] = v } for _, v := range sortContract { t := contractRow[v] if t != nil { tableRows = append(tableRows, t) } } return }