123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934 |
- package trade_analysis
- import (
- "eta/eta_index_lib/models"
- tradeAnalysisModel "eta/eta_index_lib/models/trade_analysis"
- "eta/eta_index_lib/utils"
- "fmt"
- "sort"
- "strings"
- "time"
- )
- // FormatCompanyTradeData2EdbData [公司-合约加总]转为指标数据
- func FormatCompanyTradeData2EdbData(companyTradeData *tradeAnalysisModel.ContractCompanyTradeData, tradeType int) (edbData []*models.EdbDataList, err error) {
- if companyTradeData == nil {
- err = fmt.Errorf("持仓数据异常")
- return
- }
- edbData = make([]*models.EdbDataList, 0)
- var minData, maxData float64
- for dk, dv := range companyTradeData.DataList {
- // 交易方向
- var val float64
- if tradeType == tradeAnalysisModel.WarehouseBuyChartType {
- if dv.BuyValType == tradeAnalysisModel.TradeDataTypeNull {
- continue
- }
- val = float64(dv.BuyVal)
- }
- if tradeType == tradeAnalysisModel.WarehouseSoldChartType {
- if dv.SoldValType == tradeAnalysisModel.TradeDataTypeNull {
- continue
- }
- val = float64(dv.SoldVal)
- }
- if tradeType == tradeAnalysisModel.WarehousePureBuyChartType {
- if dv.PureBuyValType == tradeAnalysisModel.TradeDataTypeNull {
- continue
- }
- val = float64(dv.PureBuyVal)
- }
- if dk == 0 {
- minData = val
- maxData = val
- }
- if val < minData {
- minData = val
- }
- if val > maxData {
- maxData = val
- }
- edbData = append(edbData, &models.EdbDataList{
- DataTime: dv.Date.Format(utils.FormatDate),
- DataTimestamp: dv.Date.UnixNano() / 1e6,
- Value: val,
- })
- }
- return
- }
- func GetWarehouseTradeData(exchange, classifyName string, contracts, companies []string, predictRatio float64) (companyTradeData []*tradeAnalysisModel.ContractCompanyTradeData, err error) {
- // 获取合约持仓数据
- contractTradeData, lastBuyVal, lastSoldVal, e := GetContractCompanyTradeData(exchange, []string{classifyName}, contracts, companies, time.Time{}, time.Time{})
- if e != nil {
- err = fmt.Errorf("获取合约-持仓数据失败, %v", e)
- return
- }
- // 填充[合约-公司]预估数据, 并根据[公司-多合约]分组, [公司]算作一个指标, 指标值为[多个合约]的计算加总
- companyContracts := make(map[string][]*tradeAnalysisModel.ContractCompanyTradeData)
- for _, v := range contractTradeData {
- td, fd, ed, e := PredictingTradeData(v.DataList, lastBuyVal[v.ClassifyType], lastSoldVal[v.ClassifyType], predictRatio)
- if e != nil {
- err = fmt.Errorf("数据补全失败, %v", e)
- return
- }
- v.DataList = td
- v.StartDate = fd
- v.EndDate = ed
- if companyContracts[v.CompanyName] == nil {
- companyContracts[v.CompanyName] = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
- }
- companyContracts[v.CompanyName] = append(companyContracts[v.CompanyName], v)
- }
- // 以[公司]为组, 计算合约加总
- mussyTradeData := make(map[string]*tradeAnalysisModel.ContractCompanyTradeData)
- for k, v := range companyContracts {
- companyData := new(tradeAnalysisModel.ContractCompanyTradeData)
- companyData.CompanyName = k
- companyData.DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
- contractArr := make([]string, 0)
- // 合约加总
- sumDateData := make(map[time.Time]*tradeAnalysisModel.ContractCompanyTradeDataList)
- for _, vv := range v {
- contractArr = append(contractArr, vv.ClassifyType)
- for _, dv := range vv.DataList {
- if sumDateData[dv.Date] == nil {
- sumDateData[dv.Date] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
- sumDateData[dv.Date].Date = dv.Date
- }
- // 数据类型以第一个非零值为准, 只处理多空和净多, 变化就不管了
- if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].BuyValType = dv.BuyValType
- }
- if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.BuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
- sumDateData[dv.Date].BuyValType = dv.BuyValType
- }
- if dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].BuyVal += dv.BuyVal
- }
- // 空单
- if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeNull && dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].SoldValType = dv.SoldValType
- }
- if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.SoldValType == tradeAnalysisModel.TradeDataTypeCalculate {
- sumDateData[dv.Date].SoldValType = dv.SoldValType
- }
- if dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].SoldVal += dv.SoldVal
- }
- // 净多单
- if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
- }
- if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.PureBuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
- sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
- }
- if dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].PureBuyVal += dv.PureBuyVal
- }
- }
- // 多个合约比对开始结束时间
- if companyData.StartDate.IsZero() {
- companyData.StartDate = vv.StartDate
- }
- if vv.StartDate.Before(companyData.StartDate) {
- companyData.StartDate = vv.StartDate
- }
- if companyData.EndDate.IsZero() {
- companyData.EndDate = vv.EndDate
- }
- if vv.EndDate.Before(companyData.EndDate) {
- companyData.EndDate = vv.EndDate
- }
- }
- for _, sv := range sumDateData {
- companyData.DataList = append(companyData.DataList, sv)
- }
- sort.Slice(companyData.DataList, func(i, j int) bool {
- return companyData.DataList[i].Date.Before(companyData.DataList[j].Date)
- })
- companyData.ClassifyType = strings.Join(contractArr, ",")
- mussyTradeData[k] = companyData
- }
- // 数据根据公司排序, 不然会随机乱
- companyTradeData = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
- for _, v := range companies {
- // 没数据也需要加进去, 不然edbList会少
- if mussyTradeData[v] == nil {
- companyData := new(tradeAnalysisModel.ContractCompanyTradeData)
- companyData.CompanyName = v
- companyData.DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
- companyTradeData = append(companyTradeData, companyData)
- continue
- }
- companyTradeData = append(companyTradeData, mussyTradeData[v])
- }
- return
- }
- // PredictingTradeData 根据数据库中的多空数据填充预估数据
- func PredictingTradeData(originData []*tradeAnalysisModel.ContractCompanyTradeDataList, lastBuyDateVal, lastSoldDateVal map[time.Time]int, predictRatio float64) (newData []*tradeAnalysisModel.ContractCompanyTradeDataList, firstDate, endDate time.Time, err error) {
- // 测试用的验证数据
- //lastBuyDateVal, lastSoldDateVal = make(map[time.Time]int), make(map[time.Time]int)
- //lastBuyDateVal[time.Date(2024, 7, 16, 0, 0, 0, 0, time.Local)] = 4602
- //lastBuyDateVal[time.Date(2024, 7, 17, 0, 0, 0, 0, time.Local)] = 5116
- //lastBuyDateVal[time.Date(2024, 7, 18, 0, 0, 0, 0, time.Local)] = 5130
- //lastBuyDateVal[time.Date(2024, 7, 19, 0, 0, 0, 0, time.Local)] = 5354
- //lastBuyDateVal[time.Date(2024, 7, 22, 0, 0, 0, 0, time.Local)] = 5916
- //lastBuyDateVal[time.Date(2024, 7, 23, 0, 0, 0, 0, time.Local)] = 6524
- //lastBuyDateVal[time.Date(2024, 7, 26, 0, 0, 0, 0, time.Local)] = 6575
- //lastBuyDateVal[time.Date(2024, 7, 29, 0, 0, 0, 0, time.Local)] = 7461
- //lastBuyDateVal[time.Date(2024, 7, 30, 0, 0, 0, 0, time.Local)] = 8488
- //
- //lastSoldDateVal[time.Date(2024, 7, 11, 0, 0, 0, 0, time.Local)] = 5467
- //lastSoldDateVal[time.Date(2024, 7, 12, 0, 0, 0, 0, time.Local)] = 5248
- //lastSoldDateVal[time.Date(2024, 7, 15, 0, 0, 0, 0, time.Local)] = 5102
- //lastSoldDateVal[time.Date(2024, 7, 16, 0, 0, 0, 0, time.Local)] = 4771
- //lastSoldDateVal[time.Date(2024, 7, 23, 0, 0, 0, 0, time.Local)] = 5989
- //lastSoldDateVal[time.Date(2024, 7, 26, 0, 0, 0, 0, time.Local)] = 6745
- //lastSoldDateVal[time.Date(2024, 7, 30, 0, 0, 0, 0, time.Local)] = 7272
- //
- //originData = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
- //originData = append(originData, &tradeAnalysisModel.ContractCompanyTradeDataList{
- // Date: time.Date(2024, 7, 10, 0, 0, 0, 0, time.Local),
- // BuyVal: 14324,
- // BuyValType: tradeAnalysisModel.TradeDataTypeOrigin,
- // BuyChange: -1107,
- // BuyChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
- // SoldVal: 0,
- // SoldValType: tradeAnalysisModel.TradeDataTypeNull,
- // SoldChange: 0,
- // SoldChangeType: tradeAnalysisModel.TradeDataTypeNull,
- //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
- // Date: time.Date(2024, 7, 11, 0, 0, 0, 0, time.Local),
- // BuyVal: 14280,
- // BuyValType: tradeAnalysisModel.TradeDataTypeOrigin,
- // BuyChange: -44,
- // BuyChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
- //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
- // Date: time.Date(2024, 7, 12, 0, 0, 0, 0, time.Local),
- // BuyVal: 14214,
- // BuyValType: tradeAnalysisModel.TradeDataTypeOrigin,
- // BuyChange: -66,
- // BuyChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
- //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
- // Date: time.Date(2024, 7, 15, 0, 0, 0, 0, time.Local),
- // BuyVal: 14269,
- // BuyValType: tradeAnalysisModel.TradeDataTypeOrigin,
- // BuyChange: 55,
- // BuyChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
- //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
- // Date: time.Date(2024, 7, 17, 0, 0, 0, 0, time.Local),
- // SoldVal: 5254,
- // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
- // SoldChange: 708,
- // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
- //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
- // Date: time.Date(2024, 7, 18, 0, 0, 0, 0, time.Local),
- // SoldVal: 6595,
- // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
- // SoldChange: 1341,
- // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
- //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
- // Date: time.Date(2024, 7, 19, 0, 0, 0, 0, time.Local),
- // SoldVal: 5938,
- // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
- // SoldChange: -657,
- // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
- //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
- // Date: time.Date(2024, 7, 22, 0, 0, 0, 0, time.Local),
- // SoldVal: 6131,
- // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
- // SoldChange: 193,
- // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
- //}, &tradeAnalysisModel.ContractCompanyTradeDataList{
- // Date: time.Date(2024, 7, 29, 0, 0, 0, 0, time.Local),
- // SoldVal: 6679,
- // SoldValType: tradeAnalysisModel.TradeDataTypeOrigin,
- // SoldChange: 312,
- // SoldChangeType: tradeAnalysisModel.TradeDataTypeOrigin,
- //})
- if len(originData) == 0 {
- return
- }
- if predictRatio < 0 || predictRatio > 1 {
- err = fmt.Errorf("估计参数不在0-1之间")
- return
- }
- sort.Slice(originData, func(i, j int) bool {
- return originData[i].Date.Before(originData[j].Date)
- })
- dateVal := make(map[time.Time]*tradeAnalysisModel.ContractCompanyTradeDataList)
- for _, v := range originData {
- dateVal[v.Date] = v
- }
- // 生成开始日期-1d(可能会往前面推算一天)至结束日期间的交易日, 以交易日为时间序列遍历
- tradeDays := utils.GetTradingDays(originData[0].Date.AddDate(0, 0, -1), originData[len(originData)-1].Date)
- for k, v := range tradeDays {
- // T日多空均无的情况
- //bothLast := false
- if dateVal[v] == nil {
- // T-1和T+1[原始数据]均无值, 那么T日无数据
- hasPrev, hasNext := false, false
- if k-1 >= 0 {
- hasPrev = true
- }
- if k+1 <= len(tradeDays)-1 {
- hasNext = true
- }
- if !hasPrev && !hasNext {
- continue
- }
- // T+1有值, 优先从T+1推, 然后继续走下面计算净多单的逻辑
- if hasNext {
- nextDay := tradeDays[k+1]
- if dateVal[nextDay] != nil {
- // T+1有多/空及多空变化, 且是原始数据, 那么推出数据并在map中新加一日数据
- if dateVal[nextDay].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[nextDay].BuyChangeType == tradeAnalysisModel.TradeDataTypeOrigin {
- if _, ok := dateVal[v]; !ok {
- dateVal[v] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
- dateVal[v].Date = v
- }
- dateVal[v].BuyVal = dateVal[nextDay].BuyVal - dateVal[nextDay].BuyChange
- dateVal[v].BuyValType = tradeAnalysisModel.TradeDataTypeOrigin
- }
- if dateVal[nextDay].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[nextDay].SoldChangeType == tradeAnalysisModel.TradeDataTypeOrigin {
- if _, ok := dateVal[v]; !ok {
- dateVal[v] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
- dateVal[v].Date = v
- }
- dateVal[v].SoldVal = dateVal[nextDay].SoldVal - dateVal[nextDay].SoldChange
- dateVal[v].SoldValType = tradeAnalysisModel.TradeDataTypeOrigin
- }
- }
- }
- // T+1没推出来而T-1有值, 那么T多空均取末位, 计算净多单
- _, has := dateVal[v]
- if hasPrev && !has {
- sv, sok := lastSoldDateVal[v]
- bv, bok := lastBuyDateVal[v]
- if !sok && !bok {
- continue
- }
- dateVal[v] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
- dateVal[v].Date = v
- if sok {
- dateVal[v].SoldVal = int(predictRatio*float64(sv) + 0.5)
- dateVal[v].SoldValType = tradeAnalysisModel.TradeDataTypeCalculate
- }
- if bok {
- dateVal[v].BuyVal = int(predictRatio*float64(bv) + 0.5)
- dateVal[v].BuyValType = tradeAnalysisModel.TradeDataTypeCalculate
- }
- if dateVal[v].BuyValType > tradeAnalysisModel.TradeDataTypeNull && dateVal[v].SoldValType > tradeAnalysisModel.TradeDataTypeNull {
- dateVal[v].PureBuyVal = dateVal[v].BuyVal - dateVal[v].SoldVal
- dateVal[v].PureBuyValType = tradeAnalysisModel.TradeDataTypeCalculate
- }
- continue
- }
- }
- // 多空均有的情况下计算净多单
- if dateVal[v].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[v].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin {
- dateVal[v].PureBuyVal = dateVal[v].BuyVal - dateVal[v].SoldVal
- dateVal[v].PureBuyValType = tradeAnalysisModel.TradeDataTypeOrigin // 原始值算出来的也作原始值
- }
- // 仅有多单, 空单取末位, 计算净多单
- if dateVal[v].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[v].SoldValType == tradeAnalysisModel.TradeDataTypeNull {
- if sv, ok := lastSoldDateVal[v]; ok {
- dateVal[v].SoldVal = int(predictRatio*float64(sv) + 0.5) // 估计参数*末位值, 向上取整
- dateVal[v].SoldValType = tradeAnalysisModel.TradeDataTypeCalculate
- dateVal[v].PureBuyVal = dateVal[v].BuyVal - dateVal[v].SoldVal
- dateVal[v].PureBuyValType = tradeAnalysisModel.TradeDataTypeCalculate
- }
- }
- // 仅有空单, 多单取末位, 计算净多单
- if dateVal[v].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin && dateVal[v].BuyValType == tradeAnalysisModel.TradeDataTypeNull {
- if sv, ok := lastBuyDateVal[v]; ok {
- dateVal[v].BuyVal = int(predictRatio*float64(sv) + 0.5)
- dateVal[v].BuyValType = tradeAnalysisModel.TradeDataTypeCalculate
- dateVal[v].PureBuyVal = dateVal[v].BuyVal - dateVal[v].SoldVal
- dateVal[v].PureBuyValType = tradeAnalysisModel.TradeDataTypeCalculate
- }
- }
- }
- // 二次遍历, 计算与T-1的变化值
- for k, v := range tradeDays {
- // 无T/T-1数据, 忽略
- if dateVal[v] == nil {
- continue
- }
- if k-1 < 0 {
- continue
- }
- beforeDay := tradeDays[k-1]
- if dateVal[beforeDay] == nil {
- continue
- }
- // 多单变化
- if dateVal[v].BuyChangeType == tradeAnalysisModel.TradeDataTypeNull {
- if dateVal[v].BuyValType > tradeAnalysisModel.TradeDataTypeNull && dateVal[beforeDay].BuyValType > tradeAnalysisModel.TradeDataTypeNull {
- dateVal[v].BuyChange = dateVal[v].BuyVal - dateVal[beforeDay].BuyVal
- // 如果当日多单或者前日多单是估计值, 那么多单变化也为估计值
- if dateVal[v].BuyValType == tradeAnalysisModel.TradeDataTypeCalculate || dateVal[beforeDay].BuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
- dateVal[v].BuyChangeType = tradeAnalysisModel.TradeDataTypeCalculate
- }
- }
- }
- // 空单变化
- if dateVal[v].SoldChangeType == tradeAnalysisModel.TradeDataTypeNull {
- if dateVal[v].SoldValType > tradeAnalysisModel.TradeDataTypeNull && dateVal[beforeDay].SoldValType > tradeAnalysisModel.TradeDataTypeNull {
- dateVal[v].SoldChange = dateVal[v].SoldVal - dateVal[beforeDay].SoldVal
- // 如果当日空单或者前日空单是估计值, 那么空单变化也为估计值
- if dateVal[v].SoldValType == tradeAnalysisModel.TradeDataTypeCalculate || dateVal[beforeDay].SoldValType == tradeAnalysisModel.TradeDataTypeCalculate {
- dateVal[v].SoldChangeType = tradeAnalysisModel.TradeDataTypeCalculate
- }
- }
- }
- // 净多变化
- if dateVal[v].PureBuyChangeType == tradeAnalysisModel.TradeDataTypeNull {
- if dateVal[v].PureBuyValType > tradeAnalysisModel.TradeDataTypeNull && dateVal[beforeDay].PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
- dateVal[v].PureBuyChange = dateVal[v].PureBuyVal - dateVal[beforeDay].PureBuyVal
- dateVal[v].PureBuyChangeType = tradeAnalysisModel.TradeDataTypeOrigin
- // 如果当日净多单或者前日净多单是估计值, 那么净多单变化也为估计值
- if dateVal[v].PureBuyValType == tradeAnalysisModel.TradeDataTypeCalculate || dateVal[beforeDay].PureBuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
- dateVal[v].PureBuyChangeType = tradeAnalysisModel.TradeDataTypeCalculate
- }
- }
- }
- }
- // 重新遍历map, 生成数据序列并排序
- newData = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
- for _, v := range dateVal {
- if v.BuyValType == tradeAnalysisModel.TradeDataTypeNull && v.SoldValType == tradeAnalysisModel.TradeDataTypeNull {
- continue
- }
- newData = append(newData, v)
- }
- sort.Slice(newData, func(i, j int) bool {
- return newData[i].Date.Before(newData[j].Date)
- })
- if len(newData) > 0 {
- firstDate = newData[0].Date
- endDate = newData[len(newData)-1].Date
- }
- return
- }
- // GetTopContractRank 获取TOP20根据成交量的合约排名
- func GetTopContractRank(exchange string, classifyNames []string, dataDate time.Time) (items []*tradeAnalysisModel.ContractTopRankData, err error) {
- // 郑商所/广期所查询方式不一样
- var tradeAnalysis TradeAnalysisInterface
- switch exchange {
- case tradeAnalysisModel.TradeExchangeZhengzhou:
- tradeAnalysis = &ZhengzhouTradeAnalysis{}
- case tradeAnalysisModel.TradeExchangeGuangzhou:
- tradeAnalysis = &GuangzhouTradeAnalysis{}
- default:
- tradeAnalysis = &BaseTradeAnalysis{}
- }
- // 郑商所-需要把所选品种转为实际合约进行后续的查询
- if exchange == tradeAnalysisModel.TradeExchangeZhengzhou {
- classifies, e := GetZhengzhouContractsByClassifyNames(classifyNames)
- if e != nil {
- err = fmt.Errorf("获取郑商所实际合约失败, %v", e)
- return
- }
- classifyNames = classifies
- }
- // 获取多单/空单原始数据
- rankData, e := tradeAnalysis.GetContractTopRankData(exchange, classifyNames, dataDate)
- if e != nil {
- err = fmt.Errorf("获取多空单原始数据失败, %v", e)
- return
- }
- items = make([]*tradeAnalysisModel.ContractTopRankData, 0)
- for _, v := range rankData {
- v.Exchange = exchange
- // 郑商所-这里注意把查出来的品种和合约赋值,不然后续是乱的
- if v.Exchange == tradeAnalysisModel.TradeExchangeZhengzhou {
- v.ClassifyType = v.ClassifyName
- v.ClassifyName = GetZhengzhouClassifyName(v.ClassifyName)
- }
- items = append(items, v)
- }
- return
- }
- // GetTableTradeData 获取多空分析表格持仓数据
- func GetTableTradeData(exchange string, classifyName string, contracts []string, companyName string, predictRatio float64, startDate, endDate time.Time, contractType int) (companyTradeData []*tradeAnalysisModel.ContractCompanyTradeData, err error) {
- companyTradeData = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
- // 获取合约持仓数据
- contractTradeData, lastBuyVal, lastSoldVal, e := GetContractCompanyTradeData(exchange, []string{classifyName}, contracts, []string{companyName}, startDate, endDate)
- if e != nil {
- err = fmt.Errorf("获取合约-持仓数据失败, %v", e)
- return
- }
- // 填充[合约-公司]预估数据, 并根据[公司-多合约]分组, [公司]算作一个指标, 指标值为[多个合约]的计算加总
- companyContracts := make(map[string][]*tradeAnalysisModel.ContractCompanyTradeData)
- for _, v := range contractTradeData {
- td, fd, ed, e := PredictingTradeData(v.DataList, lastBuyVal[v.ClassifyType], lastSoldVal[v.ClassifyType], predictRatio)
- if e != nil {
- err = fmt.Errorf("数据补全失败, %v", e)
- return
- }
- v.DataList = td
- v.StartDate = fd
- v.EndDate = ed
- // 合约类型参数不为合约加总时, 每个合约算一行数据
- if contractType != tradeAnalysisModel.ContractQueryTypeTotal {
- companyTradeData = append(companyTradeData, v)
- continue
- }
- // 往下计算合约加总
- if companyContracts[v.CompanyName] == nil {
- companyContracts[v.CompanyName] = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
- }
- companyContracts[v.CompanyName] = append(companyContracts[v.CompanyName], v)
- }
- // 类型为合约加总才往下合并
- if contractType != tradeAnalysisModel.ContractQueryTypeTotal {
- return
- }
- // 以[公司]为组, 计算合约加总
- for k, v := range companyContracts {
- companyData := new(tradeAnalysisModel.ContractCompanyTradeData)
- companyData.CompanyName = k
- companyData.DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
- contractArr := make([]string, 0)
- // 合约加总
- sumDateData := make(map[time.Time]*tradeAnalysisModel.ContractCompanyTradeDataList)
- for _, vv := range v {
- contractArr = append(contractArr, vv.ClassifyType)
- for _, dv := range vv.DataList {
- if sumDateData[dv.Date] == nil {
- sumDateData[dv.Date] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
- sumDateData[dv.Date].Date = dv.Date
- }
- // 数据类型以第一个非零值为准, 只处理多空和净多, 变化就不管了
- if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].BuyValType = dv.BuyValType
- }
- if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.BuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
- sumDateData[dv.Date].BuyValType = dv.BuyValType
- }
- if dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].BuyVal += dv.BuyVal
- }
- // 空单
- if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeNull && dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].SoldValType = dv.SoldValType
- }
- if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.SoldValType == tradeAnalysisModel.TradeDataTypeCalculate {
- sumDateData[dv.Date].SoldValType = dv.SoldValType
- }
- if dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].SoldVal += dv.SoldVal
- }
- // 净多单
- if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
- }
- if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.PureBuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
- sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
- }
- if dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].PureBuyVal += dv.PureBuyVal
- }
- }
- // 多个合约比对开始结束时间
- if companyData.StartDate.IsZero() {
- companyData.StartDate = vv.StartDate
- }
- if vv.StartDate.Before(companyData.StartDate) {
- companyData.StartDate = vv.StartDate
- }
- if companyData.EndDate.IsZero() {
- companyData.EndDate = vv.EndDate
- }
- if vv.EndDate.Before(companyData.EndDate) {
- companyData.EndDate = vv.EndDate
- }
- }
- for _, sv := range sumDateData {
- companyData.DataList = append(companyData.DataList, sv)
- }
- sort.Slice(companyData.DataList, func(i, j int) bool {
- return companyData.DataList[i].Date.Before(companyData.DataList[j].Date)
- })
- //companyData.ClassifyType = strings.Join(contractArr, ",")
- companyData.Exchange = exchange
- companyData.CompanyName = k
- companyData.ClassifyType = classifyName
- companyTradeData = append(companyTradeData, companyData)
- }
- return
- }
- // GetCorrelationTableTradeData 获取相关性表格持仓数据
- func GetCorrelationTableTradeData(exchange string, classifyName string, contracts, companies []string, predictRatio float64, contractType int) (companyTradeData []*tradeAnalysisModel.ContractCompanyTradeData, err error) {
- companyTradeData = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
- // 获取合约持仓数据
- contractTradeData, lastBuyVal, lastSoldVal, e := GetContractCompanyTradeData(exchange, []string{classifyName}, contracts, companies, time.Time{}, time.Time{})
- if e != nil {
- err = fmt.Errorf("获取合约-持仓数据失败, %v", e)
- return
- }
- // 填充[合约-公司]预估数据, 并根据[公司-多合约]分组, [公司]算作一个指标, 指标值为[多个合约]的计算加总
- companyContracts := make(map[string][]*tradeAnalysisModel.ContractCompanyTradeData)
- for _, v := range contractTradeData {
- td, fd, ed, e := PredictingTradeData(v.DataList, lastBuyVal[v.ClassifyType], lastSoldVal[v.ClassifyType], predictRatio)
- if e != nil {
- err = fmt.Errorf("数据补全失败, %v", e)
- return
- }
- v.DataList = td
- v.StartDate = fd
- v.EndDate = ed
- // 合约类型参数不为合约加总时, 每个合约算一行数据
- if contractType != tradeAnalysisModel.ContractQueryTypeTotal {
- companyTradeData = append(companyTradeData, v)
- continue
- }
- // 往下计算合约加总
- if companyContracts[v.CompanyName] == nil {
- companyContracts[v.CompanyName] = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
- }
- companyContracts[v.CompanyName] = append(companyContracts[v.CompanyName], v)
- }
- // 类型为合约加总才往下合并
- if contractType != tradeAnalysisModel.ContractQueryTypeTotal {
- return
- }
- // 以[公司]为组, 计算合约加总
- for k, v := range companyContracts {
- companyData := new(tradeAnalysisModel.ContractCompanyTradeData)
- companyData.CompanyName = k
- companyData.DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
- contractArr := make([]string, 0)
- // 合约加总
- sumDateData := make(map[time.Time]*tradeAnalysisModel.ContractCompanyTradeDataList)
- for _, vv := range v {
- contractArr = append(contractArr, vv.ClassifyType)
- for _, dv := range vv.DataList {
- if sumDateData[dv.Date] == nil {
- sumDateData[dv.Date] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
- sumDateData[dv.Date].Date = dv.Date
- }
- // 数据类型以第一个非零值为准, 只处理多空和净多, 变化就不管了
- if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].BuyValType = dv.BuyValType
- }
- if sumDateData[dv.Date].BuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.BuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
- sumDateData[dv.Date].BuyValType = dv.BuyValType
- }
- if dv.BuyValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].BuyVal += dv.BuyVal
- }
- // 空单
- if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeNull && dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].SoldValType = dv.SoldValType
- }
- if sumDateData[dv.Date].SoldValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.SoldValType == tradeAnalysisModel.TradeDataTypeCalculate {
- sumDateData[dv.Date].SoldValType = dv.SoldValType
- }
- if dv.SoldValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].SoldVal += dv.SoldVal
- }
- // 净多单
- if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeNull && dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
- }
- if sumDateData[dv.Date].PureBuyValType == tradeAnalysisModel.TradeDataTypeOrigin && dv.PureBuyValType == tradeAnalysisModel.TradeDataTypeCalculate {
- sumDateData[dv.Date].PureBuyValType = dv.PureBuyValType
- }
- if dv.PureBuyValType > tradeAnalysisModel.TradeDataTypeNull {
- sumDateData[dv.Date].PureBuyVal += dv.PureBuyVal
- }
- }
- // 多个合约比对开始结束时间
- if companyData.StartDate.IsZero() {
- companyData.StartDate = vv.StartDate
- }
- if vv.StartDate.Before(companyData.StartDate) {
- companyData.StartDate = vv.StartDate
- }
- if companyData.EndDate.IsZero() {
- companyData.EndDate = vv.EndDate
- }
- if vv.EndDate.Before(companyData.EndDate) {
- companyData.EndDate = vv.EndDate
- }
- }
- for _, sv := range sumDateData {
- companyData.DataList = append(companyData.DataList, sv)
- }
- sort.Slice(companyData.DataList, func(i, j int) bool {
- return companyData.DataList[i].Date.Before(companyData.DataList[j].Date)
- })
- //companyData.ClassifyType = strings.Join(contractArr, ",")
- companyData.IsTotal = true
- companyData.Exchange = exchange
- companyData.CompanyName = k
- companyData.ClassifyName = classifyName
- companyData.ClassifyType = classifyName
- companyTradeData = append(companyTradeData, companyData)
- }
- return
- }
- // TransTradeData2EdbData 持仓数据转为指标数据
- func TransTradeData2EdbData(tradeData []*tradeAnalysisModel.ContractCompanyTradeData, contractPosition int) (edbData []*tradeAnalysisModel.ContractCompanyTradeEdb, edbDataMap []map[time.Time]int, err error) {
- if len(tradeData) == 0 {
- return
- }
- edbData = make([]*tradeAnalysisModel.ContractCompanyTradeEdb, 0)
- edbDataMap = make([]map[time.Time]int, 0)
- for _, v := range tradeData {
- newEdb := new(tradeAnalysisModel.ContractCompanyTradeEdb)
- newEdb.Exchange = v.Exchange
- newEdb.ClassifyName = v.ClassifyName
- newEdb.ClassifyType = v.ClassifyType
- newEdb.CompanyName = v.CompanyName
- newEdb.IsTotal = v.IsTotal
- newEdb.ContractPosition = contractPosition
- newEdb.StartDate = v.StartDate
- newEdb.EndDate = v.EndDate
- newEdb.DataList = make([]*tradeAnalysisModel.ContractCompanyTradeEdbData, 0)
- dataMap := make(map[time.Time]int)
- for _, d := range v.DataList {
- var vd int
- switch contractPosition {
- case tradeAnalysisModel.ContractPositionBuy:
- if d.BuyValType == tradeAnalysisModel.TradeDataTypeNull {
- continue
- }
- vd = d.BuyVal
- case tradeAnalysisModel.ContractPositionSold:
- if d.SoldValType == tradeAnalysisModel.TradeDataTypeNull {
- continue
- }
- vd = d.SoldVal
- case tradeAnalysisModel.ContractPositionPureBuy:
- if d.PureBuyValType == tradeAnalysisModel.TradeDataTypeNull {
- continue
- }
- vd = d.PureBuyVal
- default:
- continue
- }
- newEdb.DataList = append(newEdb.DataList, &tradeAnalysisModel.ContractCompanyTradeEdbData{
- DataTime: d.Date,
- Val: vd,
- })
- dataMap[d.Date] = vd
- }
- edbData = append(edbData, newEdb)
- edbDataMap = append(edbDataMap, dataMap)
- }
- return
- }
- // GetContractCompanyTradeData 获取合约持仓数据
- func GetContractCompanyTradeData(exchange string, classifyNames, contracts, companies []string, startDate, endDate time.Time) (contractTradeData map[string]*tradeAnalysisModel.ContractCompanyTradeData, lastBuyVal, lastSoldVal map[string]map[time.Time]int, err error) {
- // 各原始数据表期货公司名称不一致
- companyMap := make(map[string]string)
- {
- ob := new(tradeAnalysisModel.TradeFuturesCompany)
- list, e := ob.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
- if e != nil {
- err = fmt.Errorf("获取期货公司名称失败: %v", e)
- return
- }
- switch exchange {
- case "zhengzhou":
- for _, v := range list {
- companyMap[v.CompanyName] = v.ZhengzhouName
- }
- case "dalian":
- for _, v := range list {
- companyMap[v.CompanyName] = v.DalianName
- }
- case "shanghai":
- for _, v := range list {
- companyMap[v.CompanyName] = v.ShanghaiName
- }
- case "cffex":
- for _, v := range list {
- companyMap[v.CompanyName] = v.CffexName
- }
- case "ine":
- for _, v := range list {
- companyMap[v.CompanyName] = v.IneName
- }
- case "guangzhou":
- for _, v := range list {
- companyMap[v.CompanyName] = v.GuangzhouName
- }
- }
- }
- var queryCompanies []string
- for _, v := range companies {
- if v == tradeAnalysisModel.TradeFuturesCompanyTop20 {
- queryCompanies = append(queryCompanies, tradeAnalysisModel.TradeFuturesCompanyTop20)
- continue
- }
- companyName, ok := companyMap[v]
- if !ok {
- utils.FileLog.Info(fmt.Sprintf("交易所%s公司名称映射不存在: %s", exchange, v))
- continue
- }
- queryCompanies = append(queryCompanies, companyName)
- }
- // 郑商所/广期所查询方式不一样
- var tradeAnalysis TradeAnalysisInterface
- switch exchange {
- case tradeAnalysisModel.TradeExchangeZhengzhou:
- tradeAnalysis = &ZhengzhouTradeAnalysis{}
- case tradeAnalysisModel.TradeExchangeGuangzhou:
- tradeAnalysis = &GuangzhouTradeAnalysis{}
- default:
- tradeAnalysis = &BaseTradeAnalysis{}
- }
- // 获取多单/空单原始数据
- originList, _, lastOriginList, e := tradeAnalysis.GetTradeDataByContracts(exchange, classifyNames, contracts, queryCompanies, startDate, endDate)
- if e != nil {
- err = fmt.Errorf("获取多空单原始数据失败, %v", e)
- return
- }
- // [合约-期货公司]数据分组
- contractTradeData = make(map[string]*tradeAnalysisModel.ContractCompanyTradeData)
- {
- keyDateData := make(map[string]*tradeAnalysisModel.ContractCompanyTradeDataList)
- keyDateDataExist := make(map[string]bool)
- for _, v := range originList {
- companyName := v.CompanyName
- k := fmt.Sprintf("%s-%s", v.ClassifyType, companyName)
- if contractTradeData[k] == nil {
- contractTradeData[k] = new(tradeAnalysisModel.ContractCompanyTradeData)
- contractTradeData[k].Exchange = exchange
- contractTradeData[k].CompanyName = companyName
- contractTradeData[k].ClassifyName = v.ClassifyName
- contractTradeData[k].ClassifyType = v.ClassifyType
- contractTradeData[k].DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
- }
- kd := fmt.Sprintf("%s-%s", k, v.DataTime.Format(utils.FormatDate))
- if keyDateData[kd] == nil {
- keyDateData[kd] = new(tradeAnalysisModel.ContractCompanyTradeDataList)
- keyDateData[kd].Date = v.DataTime
- }
- if v.ValType == 1 {
- keyDateData[kd].BuyVal = v.Val
- keyDateData[kd].BuyValType = tradeAnalysisModel.TradeDataTypeOrigin
- keyDateData[kd].BuyChange = v.ValChange
- keyDateData[kd].BuyChangeType = tradeAnalysisModel.TradeDataTypeOrigin
- }
- if v.ValType == 2 {
- keyDateData[kd].SoldVal = v.Val
- keyDateData[kd].SoldValType = tradeAnalysisModel.TradeDataTypeOrigin
- keyDateData[kd].SoldChange = v.ValChange
- keyDateData[kd].SoldChangeType = tradeAnalysisModel.TradeDataTypeOrigin
- }
- if !keyDateDataExist[kd] {
- contractTradeData[k].DataList = append(contractTradeData[k].DataList, keyDateData[kd])
- keyDateDataExist[kd] = true
- }
- }
- }
- // 合约的[日期-末位值]
- lastBuyVal = make(map[string]map[time.Time]int)
- lastSoldVal = make(map[string]map[time.Time]int)
- {
- for _, v := range lastOriginList {
- if v.ValType == 1 {
- if lastBuyVal[v.ClassifyType] == nil {
- lastBuyVal[v.ClassifyType] = make(map[time.Time]int)
- }
- lastBuyVal[v.ClassifyType][v.DataTime] = v.Val
- continue
- }
- if lastSoldVal[v.ClassifyType] == nil {
- lastSoldVal[v.ClassifyType] = make(map[time.Time]int)
- }
- lastSoldVal[v.ClassifyType][v.DataTime] = v.Val
- }
- }
- return
- }
- // GetTradeClassifyNewestDataTime 获取数据最新日期
- func GetTradeClassifyNewestDataTime(exchange string, classifyNames []string) (dataTime time.Time, err error) {
- var tradeAnalysis TradeAnalysisInterface
- switch exchange {
- case tradeAnalysisModel.TradeExchangeZhengzhou:
- tradeAnalysis = &ZhengzhouTradeAnalysis{}
- case tradeAnalysisModel.TradeExchangeGuangzhou:
- tradeAnalysis = &GuangzhouTradeAnalysis{}
- default:
- tradeAnalysis = &BaseTradeAnalysis{}
- }
- if exchange == tradeAnalysisModel.TradeExchangeZhengzhou {
- classifies, e := GetZhengzhouContractsByClassifyNames(classifyNames)
- if e != nil {
- err = fmt.Errorf("获取郑商所实际合约失败, %v", e)
- return
- }
- classifyNames = classifies
- }
- d, e := tradeAnalysis.GetClassifyNewestDataTime(exchange, classifyNames)
- if e != nil && e.Error() != utils.ErrNoRow() {
- err = fmt.Errorf("获取品种最新数据日期失败, %v", e)
- return
- }
- if !d.IsZero() {
- dataTime = d
- } else {
- dataTime = time.Now().Local()
- }
- return
- }
|