|
@@ -1,6 +1,7 @@
|
|
|
package logic
|
|
|
|
|
|
import (
|
|
|
+ "encoding/json"
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
"github.com/shopspring/decimal"
|
|
@@ -97,9 +98,97 @@ type BarChartInfoEdbItemReq struct {
|
|
|
Source int `description:"1:ETA图库;2:商品价格"`
|
|
|
}
|
|
|
|
|
|
-// GetProfitChartEdbData 获取利润图表的指标数据
|
|
|
-func GetProfitChartEdbData(baseEdbInfo *models.EdbInfo, zlFutureGoodEdbInfoList []*future_good.FutureGoodEdbInfo, chartInfoDateList []ChartInfoDateReq, formulaStr string, edbInfoFromTagList []models.EdbInfoFromTag) (barConfigEdbInfoIdList []BarChartInfoEdbItemReq, xEdbIdValue []int, xDataList []XData, yDataList []YData, err error) {
|
|
|
+// ChartInfoReq 图表预览请求数据
|
|
|
+type ChartInfoReq struct {
|
|
|
+ FutureGoodEdbInfoIdList []models.EdbInfoFromTag `description:"指标信息"`
|
|
|
+ CalculateFormula string `description:"计算公式"`
|
|
|
+ BaseEdbInfoId int `description:"基础的指标id"`
|
|
|
+ DateList []ChartInfoDateReq `description:"日期配置"`
|
|
|
+ ProfitNameEn string `description:"利润英文名称"`
|
|
|
+}
|
|
|
+
|
|
|
+// RefreshByChartId 根据图表id刷新图表
|
|
|
+func RefreshByChartId(chartInfoId int) (err error, errMsg string) {
|
|
|
+ // 查找图表
|
|
|
+ chartInfo, err := models.GetChartInfoById(chartInfoId)
|
|
|
+ if err != nil {
|
|
|
+ if err.Error() == utils.ErrNoRow() {
|
|
|
+ err = nil
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if chartInfo.Source != utils.CHART_SOURCE_FUTURE_GOOD_PROFIT {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var extraConf ChartInfoReq
|
|
|
+ err = json.Unmarshal([]byte(chartInfo.ExtraConfig), &extraConf)
|
|
|
+ if err != nil {
|
|
|
+ errMsg = "商品利润曲线图配置异常"
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查找商品利润图表的扩展信息
|
|
|
+ chartInfoFutureGoodProfit := new(future_good.ChartInfoFutureGoodProfit)
|
|
|
+ if err = chartInfoFutureGoodProfit.GetItemById(chartInfoId); err != nil {
|
|
|
+ errMsg = "获取失败"
|
|
|
+ if err.Error() == utils.ErrNoRow() {
|
|
|
+ err = nil
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ baseEdbInfo, err := models.GetEdbInfoById(extraConf.BaseEdbInfoId)
|
|
|
+ if err != nil {
|
|
|
+ errMsg = "获取失败"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 商品数据库指标
|
|
|
+ futureGoodEdbInfoMap := make(map[int]*future_good.FutureGoodEdbInfo)
|
|
|
+ zlFutureGoodEdbInfoList := make([]*future_good.FutureGoodEdbInfo, 0)
|
|
|
+ for _, v := range extraConf.FutureGoodEdbInfoIdList {
|
|
|
+ if _, ok := futureGoodEdbInfoMap[v.EdbInfoId]; ok {
|
|
|
+ continue
|
|
|
+ }
|
|
|
|
|
|
+ zlFutureGoodEdbInfo, tmpErr := future_good.GetFutureGoodEdbInfo(v.EdbInfoId)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ errMsg = "获取失败"
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ futureGoodEdbInfoMap[v.EdbInfoId] = zlFutureGoodEdbInfo
|
|
|
+ zlFutureGoodEdbInfoList = append(zlFutureGoodEdbInfoList, zlFutureGoodEdbInfo)
|
|
|
+ }
|
|
|
+
|
|
|
+ xDataList, yDataList, err := GetProfitChartEdbData(baseEdbInfo, zlFutureGoodEdbInfoList, extraConf.DateList, extraConf.CalculateFormula, extraConf.FutureGoodEdbInfoIdList)
|
|
|
+
|
|
|
+ xDataListByte, err := json.Marshal(xDataList)
|
|
|
+ if err != nil {
|
|
|
+ errMsg = "保存失败"
|
|
|
+ err = errors.New("X轴数据转换失败,ERR:" + err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ yDataListByte, err := json.Marshal(yDataList)
|
|
|
+ if err != nil {
|
|
|
+ errMsg = "保存失败"
|
|
|
+ err = errors.New("Y轴数据转换失败,ERR:" + err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ extraUpdateCol := make([]string, 0)
|
|
|
+ chartInfoFutureGoodProfit.XValue = string(xDataListByte)
|
|
|
+ chartInfoFutureGoodProfit.YValue = string(yDataListByte)
|
|
|
+ chartInfoFutureGoodProfit.ProfitName = zlFutureGoodEdbInfoList[0].FutureGoodEdbName + "盘面利润"
|
|
|
+ chartInfoFutureGoodProfit.ModifyTime = time.Now()
|
|
|
+ extraUpdateCol = []string{"XValue", "YValue", "ProfitName", "ModifyTime"}
|
|
|
+ err = chartInfoFutureGoodProfit.Update(extraUpdateCol)
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetProfitChartEdbData 获取利润图表的指标数据
|
|
|
+func GetProfitChartEdbData(baseEdbInfo *models.EdbInfo, zlFutureGoodEdbInfoList []*future_good.FutureGoodEdbInfo, chartInfoDateList []ChartInfoDateReq, formulaStr string, edbInfoFromTagList []models.EdbInfoFromTag) (xDataList []XData, yDataList []YData, err error) {
|
|
|
if baseEdbInfo == nil {
|
|
|
err = errors.New("ETA指标未选取")
|
|
|
return
|
|
@@ -167,8 +256,10 @@ func GetProfitChartEdbData(baseEdbInfo *models.EdbInfo, zlFutureGoodEdbInfoList
|
|
|
monthNum := (latestDateTime.Year()-earliestDateTime.Year())*12 + int(latestDateTime.Month()-earliestDateTime.Month())
|
|
|
|
|
|
// 存储主力合约下的所有月份合约
|
|
|
- futureGoodEdbInfoMap := make(map[int]map[int]*future_good.FutureGoodEdbInfo)
|
|
|
+ futureGoodEdbInfoDateMap := make(map[int]map[string]*future_good.FutureGoodEdbInfo)
|
|
|
futureGoodDataListMap := make(map[int][]*models.EdbDataList, 0)
|
|
|
+ // 特殊的商品期货合约(只有M+N的合约,没有固定日期的合约)
|
|
|
+ specialFutureGoodEdbInfoMap := make(map[int]map[int]*future_good.FutureGoodEdbInfo, 0)
|
|
|
|
|
|
isAllChina := true // 是否都是国内的期货合约
|
|
|
for _, v := range zlFutureGoodEdbInfoList {
|
|
@@ -178,7 +269,7 @@ func GetProfitChartEdbData(baseEdbInfo *models.EdbInfo, zlFutureGoodEdbInfoList
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- nMap := make(map[int]int)
|
|
|
+ nMap := make(map[string]string)
|
|
|
var maxN int // 最大N值
|
|
|
for _, v := range zlFutureGoodEdbInfoList {
|
|
|
// 如果不是有效的商品期货指标,那么就过滤掉,不做数据查询处理,避免没必要的请求
|
|
@@ -200,12 +291,14 @@ func GetProfitChartEdbData(baseEdbInfo *models.EdbInfo, zlFutureGoodEdbInfoList
|
|
|
if maxN < tmpMaxN {
|
|
|
maxN = tmpMaxN
|
|
|
}
|
|
|
- futureGoodEdbInfoMap[v.FutureGoodEdbInfoId] = childFutureGoodEdbInfoMap
|
|
|
+ futureGoodEdbInfoDateMap[v.FutureGoodEdbInfoId] = childFutureGoodEdbInfoMap
|
|
|
|
|
|
+ if v.FutureGoodEdbType == 2 {
|
|
|
+ specialFutureGoodEdbInfoMap[v.FutureGoodEdbInfoId] = make(map[int]*future_good.FutureGoodEdbInfo)
|
|
|
+ }
|
|
|
// 获取数据
|
|
|
- for n, childFutureGoodEdbInfo := range childFutureGoodEdbInfoMap {
|
|
|
- nMap[n] = n
|
|
|
-
|
|
|
+ for date, childFutureGoodEdbInfo := range childFutureGoodEdbInfoMap {
|
|
|
+ nMap[date] = date
|
|
|
dataList := make([]*models.EdbDataList, 0)
|
|
|
|
|
|
tmpDataList, tmpErr := future_good.GetFutureGoodEdbDataListByDate(childFutureGoodEdbInfo.FutureGoodEdbInfoId, "", "")
|
|
@@ -222,19 +315,26 @@ func GetProfitChartEdbData(baseEdbInfo *models.EdbInfo, zlFutureGoodEdbInfoList
|
|
|
})
|
|
|
}
|
|
|
futureGoodDataListMap[childFutureGoodEdbInfo.FutureGoodEdbInfoId] = dataList
|
|
|
+
|
|
|
+ if childFutureGoodEdbInfo.FutureGoodEdbType == 2 {
|
|
|
+ specialFutureGoodEdbInfoMap[v.FutureGoodEdbInfoId][childFutureGoodEdbInfo.Month] = childFutureGoodEdbInfo
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 找出所有的N值,并进行正序排列
|
|
|
- nList := make([]int, 0)
|
|
|
+ dateList := make([]string, 0)
|
|
|
for _, n := range nMap {
|
|
|
- nList = append(nList, n)
|
|
|
+ dateList = append(dateList, n)
|
|
|
}
|
|
|
- sort.Slice(nList, func(i, j int) bool {
|
|
|
- return nList[i] < nList[j]
|
|
|
+ sort.Slice(dateList, func(i, j int) bool {
|
|
|
+ return dateList[i] < dateList[j]
|
|
|
})
|
|
|
|
|
|
- _, yDataList, err = ProfitChartChartData(baseDataList, futureGoodEdbInfoMap, futureGoodDataListMap, chartInfoDateList, latestDate, formulaStr, tagEdbIdMap, earliestDateTime, nList)
|
|
|
+ _, yDataList, err = ProfitChartChartData(baseDataList, futureGoodEdbInfoDateMap, futureGoodDataListMap, chartInfoDateList, latestDate, specialFutureGoodEdbInfoMap, formulaStr, tagEdbIdMap, dateList)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
tmpXDataList, newYDataList, err := handleProfitResultData(baseEdbInfo, yDataList, earliestDateTime)
|
|
|
if err != nil {
|
|
@@ -253,7 +353,7 @@ func GetProfitChartEdbData(baseEdbInfo *models.EdbInfo, zlFutureGoodEdbInfoList
|
|
|
}
|
|
|
|
|
|
// ProfitChartChartData 获取数据
|
|
|
-func ProfitChartChartData(baseDataList []*models.EdbDataList, futureGoodEdbInfoMap map[int]map[int]*future_good.FutureGoodEdbInfo, futureGoodEdbDataListMap map[int][]*models.EdbDataList, chartInfoDateList []ChartInfoDateReq, latestDate string, formulaStr string, tagEdbIdMap map[string]int, earliestDateTime time.Time, nList []int) (edbIdList []int, yDataList []YData, err error) {
|
|
|
+func ProfitChartChartData(baseDataList []*models.EdbDataList, futureGoodEdbInfoMap map[int]map[string]*future_good.FutureGoodEdbInfo, futureGoodEdbDataListMap map[int][]*models.EdbDataList, chartInfoDateList []ChartInfoDateReq, latestDate string, specialFutureGoodEdbInfoMap map[int]map[int]*future_good.FutureGoodEdbInfo, formulaStr string, tagEdbIdMap map[string]int, dateList []string) (edbIdList []int, yDataList []YData, err error) {
|
|
|
// 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
|
|
|
//earliestDateTime time.Time
|
|
|
// ETA指标数据
|
|
@@ -327,18 +427,35 @@ func ProfitChartChartData(baseDataList []*models.EdbDataList, futureGoodEdbInfoM
|
|
|
mList := make([]int, 0) // 间隔月份
|
|
|
|
|
|
// 最小开始的n值
|
|
|
- minN := (findDateTime.Year()-earliestDateTime.Year())*12 + int(findDateTime.Month()-earliestDateTime.Month())
|
|
|
- for _, n := range nList {
|
|
|
+ //minN := (findDateTime.Year()-earliestDateTime.Year())*12 + int(findDateTime.Month()-earliestDateTime.Month())
|
|
|
+ for _, date := range dateList {
|
|
|
+ currDate, _ := time.ParseInLocation(utils.FormatYearMonthDate, date, time.Local)
|
|
|
// 如果当前的n值小于最小开始的n值,那么就不处理
|
|
|
- if n < minN {
|
|
|
+ //if n < minN {
|
|
|
+ // continue
|
|
|
+ //}
|
|
|
+ //findDateTime
|
|
|
+
|
|
|
+ tmpN := (currDate.Year()-findDateTime.Year())*12 + int(currDate.Month()-findDateTime.Month())
|
|
|
+ if tmpN <= 0 {
|
|
|
continue
|
|
|
}
|
|
|
+
|
|
|
zlAndChildEdbId := make(map[int]int)
|
|
|
childFutureGoodEdbInfoIdList := make([]int, 0)
|
|
|
- for futureGoodEdbInfoId, futureGoodEdbInfo := range futureGoodEdbInfoMap {
|
|
|
- if childFutureGoodEdbInfo, ok := futureGoodEdbInfo[n]; ok {
|
|
|
- childFutureGoodEdbInfoIdList = append(childFutureGoodEdbInfoIdList, childFutureGoodEdbInfo.FutureGoodEdbInfoId)
|
|
|
- zlAndChildEdbId[futureGoodEdbInfoId] = childFutureGoodEdbInfo.FutureGoodEdbInfoId
|
|
|
+ for zlFutureGoodEdbInfoId, futureGoodEdbInfoList := range futureGoodEdbInfoMap {
|
|
|
+ // 判断是否特殊合约
|
|
|
+ if childFutureGoodEdbInfoIdMap, ok := specialFutureGoodEdbInfoMap[zlFutureGoodEdbInfoId]; ok {
|
|
|
+ if childFutureGoodEdbInfo, ok2 := childFutureGoodEdbInfoIdMap[tmpN]; ok2 {
|
|
|
+ childFutureGoodEdbInfoIdList = append(childFutureGoodEdbInfoIdList, childFutureGoodEdbInfo.FutureGoodEdbInfoId)
|
|
|
+ zlAndChildEdbId[zlFutureGoodEdbInfoId] = childFutureGoodEdbInfo.FutureGoodEdbInfoId
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ if childFutureGoodEdbInfo, ok2 := futureGoodEdbInfoList[date]; ok2 {
|
|
|
+ childFutureGoodEdbInfoIdList = append(childFutureGoodEdbInfoIdList, childFutureGoodEdbInfo.FutureGoodEdbInfoId)
|
|
|
+ zlAndChildEdbId[zlFutureGoodEdbInfoId] = childFutureGoodEdbInfo.FutureGoodEdbInfoId
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -401,8 +518,8 @@ func ProfitChartChartData(baseDataList []*models.EdbDataList, futureGoodEdbInfoM
|
|
|
}
|
|
|
//yDataMap[n] = calVal
|
|
|
//xEdbInfoIdList = append(xEdbInfoIdList, n)
|
|
|
- yDataMap[n+minN] = calVal
|
|
|
- xEdbInfoIdList = append(xEdbInfoIdList, n+minN)
|
|
|
+ yDataMap[tmpN] = calVal
|
|
|
+ xEdbInfoIdList = append(xEdbInfoIdList, tmpN)
|
|
|
findDataList = append(findDataList, calVal)
|
|
|
}
|
|
|
yName := barChartInfoDate.Name
|
|
@@ -443,10 +560,12 @@ func ProfitChartChartData(baseDataList []*models.EdbDataList, futureGoodEdbInfoM
|
|
|
}
|
|
|
|
|
|
// getFutureGoodEdbInfoList 获取适用的指标列表
|
|
|
-func getProfitFutureGoodEdbInfoList(earliestDateTime time.Time, zlFutureGoodEdbInfo *future_good.FutureGoodEdbInfo, tmpFutureGoodEdbInfoList []*future_good.FutureGoodEdbInfo, isAllChina bool, monthNum int) (futureGoodEdbInfoMap map[int]*future_good.FutureGoodEdbInfo, newMaxN int, err error) {
|
|
|
+func getProfitFutureGoodEdbInfoList(earliestDateTime time.Time, zlFutureGoodEdbInfo *future_good.FutureGoodEdbInfo, tmpFutureGoodEdbInfoList []*future_good.FutureGoodEdbInfo, isAllChina bool, monthNum int) (futureGoodEdbInfoDateMap map[string]*future_good.FutureGoodEdbInfo, newMaxN int, err error) {
|
|
|
maxM := 32 //最大32期合约
|
|
|
futureGoodEdbInfoList := make([]*future_good.FutureGoodEdbInfo, 0)
|
|
|
- futureGoodEdbInfoMap = make(map[int]*future_good.FutureGoodEdbInfo)
|
|
|
+ futureGoodEdbInfoDateMap = make(map[string]*future_good.FutureGoodEdbInfo)
|
|
|
+
|
|
|
+ earliestDateTime = time.Date(earliestDateTime.Year(), earliestDateTime.Month(), 1, 0, 0, 0, 0, time.Local)
|
|
|
if zlFutureGoodEdbInfo.RegionType == "国内" {
|
|
|
startMonth := int(earliestDateTime.Month())
|
|
|
if startMonth == 1 {
|
|
@@ -467,7 +586,7 @@ func getProfitFutureGoodEdbInfoList(earliestDateTime time.Time, zlFutureGoodEdbI
|
|
|
|
|
|
for i := 1; i < maxM; i++ {
|
|
|
k := i % lenFutureGoodEdbInfoList
|
|
|
- futureGoodEdbInfoMap[i] = futureGoodEdbInfoList[k]
|
|
|
+ futureGoodEdbInfoDateMap[earliestDateTime.AddDate(0, i, 0).Format(utils.FormatYearMonthDate)] = futureGoodEdbInfoList[k]
|
|
|
if i > newMaxN {
|
|
|
newMaxN = i
|
|
|
}
|
|
@@ -480,7 +599,7 @@ func getProfitFutureGoodEdbInfoList(earliestDateTime time.Time, zlFutureGoodEdbI
|
|
|
//海外的连续日期,目前
|
|
|
if v.FutureGoodEdbType == 2 {
|
|
|
if v.Month <= maxM {
|
|
|
- futureGoodEdbInfoMap[v.Month] = v
|
|
|
+ futureGoodEdbInfoDateMap[earliestDateTime.AddDate(0, v.Month, 0).Format(utils.FormatYearMonthDate)] = v
|
|
|
if v.Month > newMaxN {
|
|
|
newMaxN = v.Month
|
|
|
}
|
|
@@ -501,7 +620,8 @@ func getProfitFutureGoodEdbInfoList(earliestDateTime time.Time, zlFutureGoodEdbI
|
|
|
// 如果(当前年-最新日期的年份) * 12个月 + (当前月-最新日期的月份) 小于总月份
|
|
|
tmpN := subYear*12 + subMonth
|
|
|
if tmpN < maxM {
|
|
|
- futureGoodEdbInfoMap[tmpN] = v
|
|
|
+ earliestDateTime = time.Date(v.Year, time.Month(v.Month), 0, 0, 0, 0, 0, time.Local)
|
|
|
+ futureGoodEdbInfoDateMap[earliestDateTime.Format(utils.FormatYearMonthDate)] = v
|
|
|
if tmpN > newMaxN {
|
|
|
newMaxN = tmpN
|
|
|
}
|
|
@@ -607,6 +727,8 @@ func handleProfitResultData(baseEdbInfo *models.EdbInfo, yDataList []YData, earl
|
|
|
newYDataList[yIndex].Value = yData.Value[0 : maxI+1]
|
|
|
}
|
|
|
|
|
|
+ currDate, _ := time.ParseInLocation(utils.FormatDate, yData.Date, time.Local)
|
|
|
+
|
|
|
nameList := make([]string, 0)
|
|
|
enNameList := make([]string, 0)
|
|
|
for _, n := range newYDataList[yIndex].XEdbInfoIdList {
|
|
@@ -621,9 +743,7 @@ func handleProfitResultData(baseEdbInfo *models.EdbInfo, yDataList []YData, earl
|
|
|
} else {
|
|
|
var date string
|
|
|
|
|
|
- currDate, _ := time.ParseInLocation(utils.FormatDate, yData.Date, time.Local)
|
|
|
- subN := (currDate.Year()-earliestDateTime.Year())*12 + int(currDate.Month()-earliestDateTime.Month())
|
|
|
- currDateTime := earliestDateTime.AddDate(0, n-subN-1, 0)
|
|
|
+ currDateTime := currDate.AddDate(0, n-1, 0)
|
|
|
month := int(currDateTime.Month())
|
|
|
date = fmt.Sprintf("%d%d", currDateTime.Year(), month)
|
|
|
if month < 10 {
|