123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- package trade_analysis
- import (
- tradeAnalysisModel "eta/eta_index_lib/models/trade_analysis"
- "eta/eta_index_lib/utils"
- "fmt"
- "math"
- "strings"
- "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
- }
- // 根据类型取出合约数
- 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
- }
- var sortRules []string // 最终排序(合约加总以品种排序,其他以为合约排序)
- classifyContractsData := make(map[string][]*tradeAnalysisModel.ContractTopRankData) // 根据品种分组的合约数据
- classifyContracts := make(map[string][]string) // 品种合约
- for _, v := range tableConfig.ClassifyList {
- for _, classify := range v.ClassifyNames {
- // 获取合约排名及持仓数据
- contractRanks, e := GetTopContractRank(v.Exchange, []string{classify}, baseDate)
- if e != nil {
- err = fmt.Errorf("获取基准日期合约排名失败, %v", e)
- return
- }
- if len(contractRanks) == 0 {
- continue
- }
- flag := fmt.Sprintf("%s-%s", v.Exchange, classify)
- // 取出指定数量的合约
- var contractNum int
- for _, rd := range contractRanks {
- if contractNum >= contractMax {
- continue
- }
- contractNum += 1
- classifyContracts[classify] = append(classifyContracts[classify], rd.ClassifyType)
- if classifyContractsData[flag] == nil {
- classifyContractsData[flag] = make([]*tradeAnalysisModel.ContractTopRankData, 0)
- }
- classifyContractsData[flag] = append(classifyContractsData[flag], rd)
- // 以合约排序
- if tableConfig.ContractType != tradeAnalysisModel.ContractQueryTypeTotal {
- sortRules = append(sortRules, rd.ClassifyType)
- }
- }
- // 以品种排序
- if tableConfig.ContractType == tradeAnalysisModel.ContractQueryTypeTotal {
- sortRules = append(sortRules, classify)
- }
- }
- }
- mussyRows := make([]*tradeAnalysisModel.TableRowData, 0)
- for k, contracts := range classifyContractsData {
- var exchange, classifyName string
- keyArr := strings.Split(k, "-")
- if len(keyArr) != 2 {
- continue
- }
- exchange = keyArr[0]
- classifyName = keyArr[1]
- classifyTypes := classifyContracts[classifyName]
- if len(classifyTypes) == 0 {
- continue
- }
- // 合约加总时,contracts也需要加总,且ClassifyType为品种名
- if tableConfig.ContractType == tradeAnalysisModel.ContractQueryTypeTotal {
- contracts = MergeClassifyTypeTopRankData(contracts)
- }
- contractRowData, e := GetTableTradeData(exchange, classifyName, classifyTypes, 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 sortRules {
- t := contractRow[v]
- if t != nil {
- tableRows = append(tableRows, t)
- }
- }
- return
- }
- // MergeClassifyTypeTopRankData 类型为合约加总时-合并当日的TOP数据
- func MergeClassifyTypeTopRankData(classifyTypesData []*tradeAnalysisModel.ContractTopRankData) (mergedData []*tradeAnalysisModel.ContractTopRankData) {
- mergedData = make([]*tradeAnalysisModel.ContractTopRankData, 0)
- mergeData := new(tradeAnalysisModel.ContractTopRankData)
- for _, v := range classifyTypesData {
- mergeData.Exchange = v.Exchange
- mergeData.DealValue += v.DealValue
- mergeData.BuyValue += v.BuyValue
- mergeData.BuyChange += v.BuyChange
- mergeData.SoldValue += v.SoldValue
- mergeData.SoldChange += v.SoldChange
- mergeData.PureBuyValue += v.PureBuyValue
- mergeData.PureBuyChange += v.PureBuyChange
- mergeData.ClassifyName = v.ClassifyName
- mergeData.ClassifyType = v.ClassifyName // 合约合并后为品种名
- mergeData.DataTime = v.DataTime
- }
- mergedData = append(mergedData, mergeData)
- return
- }
|