123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- 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
- }
|