|
@@ -0,0 +1,748 @@
|
|
|
+package data_manage
|
|
|
+
|
|
|
+import (
|
|
|
+ "encoding/json"
|
|
|
+ "eta/eta_api/controllers"
|
|
|
+ "eta/eta_api/models"
|
|
|
+ "eta/eta_api/models/data_manage"
|
|
|
+ "eta/eta_api/models/data_manage/request"
|
|
|
+ "eta/eta_api/services/data"
|
|
|
+ correlationServ "eta/eta_api/services/data/correlation"
|
|
|
+ "eta/eta_api/utils"
|
|
|
+ "fmt"
|
|
|
+ "sort"
|
|
|
+ "strings"
|
|
|
+ "sync"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+// FactorEdbSeriesController 因子指标系列
|
|
|
+type FactorEdbSeriesController struct {
|
|
|
+ controllers.BaseAuthController
|
|
|
+}
|
|
|
+
|
|
|
+// CalculateFuncList
|
|
|
+// @Title 计算方式列表
|
|
|
+// @Description 计算方式列表
|
|
|
+// @Param EdbInfoType query int false "指标计算类型: 0-普通指标; 1-预测指标"
|
|
|
+// @Success Ret=200 操作成功
|
|
|
+// @router /factor_edb_series/calculate_func/list [get]
|
|
|
+func (this *FactorEdbSeriesController) CalculateFuncList() {
|
|
|
+ br := new(models.BaseResponse).Init()
|
|
|
+ defer func() {
|
|
|
+ if br.ErrMsg == "" {
|
|
|
+ br.IsSendEmail = false
|
|
|
+ }
|
|
|
+ this.Data["json"] = br
|
|
|
+ this.ServeJSON()
|
|
|
+ }()
|
|
|
+ sysUser := this.SysUser
|
|
|
+ if sysUser == nil {
|
|
|
+ br.Msg = "请登录"
|
|
|
+ br.ErrMsg = "请登录,SysUser Is Empty"
|
|
|
+ br.Ret = 408
|
|
|
+ return
|
|
|
+ }
|
|
|
+ edbInfoType, _ := this.GetInt("EdbInfoType", 0)
|
|
|
+
|
|
|
+ funcOb := new(data_manage.FactorEdbSeriesCalculateFunc)
|
|
|
+ cond := fmt.Sprintf(` AND %s = ?`, funcOb.Cols().EdbInfoType)
|
|
|
+ pars := make([]interface{}, 0)
|
|
|
+ pars = append(pars, edbInfoType)
|
|
|
+ list, e := funcOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", funcOb.Cols().PrimaryId))
|
|
|
+ if e != nil {
|
|
|
+ br.Msg = "获取失败"
|
|
|
+ br.ErrMsg = fmt.Sprintf("获取计算方式列表失败, Err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ resp := make([]*data_manage.FactorEdbSeriesCalculateFuncItem, 0)
|
|
|
+ for _, v := range list {
|
|
|
+ resp = append(resp, v.Format2Item())
|
|
|
+ }
|
|
|
+
|
|
|
+ br.Data = resp
|
|
|
+ br.Ret = 200
|
|
|
+ br.Success = true
|
|
|
+ br.Msg = "获取成功"
|
|
|
+}
|
|
|
+
|
|
|
+// Add
|
|
|
+// @Title 新增
|
|
|
+// @Description 新增
|
|
|
+// @Param request body request.AddFactorEdbSeriesReq true "type json string"
|
|
|
+// @Success Ret=200 操作成功
|
|
|
+// @router /factor_edb_series/add [post]
|
|
|
+func (this *FactorEdbSeriesController) Add() {
|
|
|
+ br := new(models.BaseResponse).Init()
|
|
|
+ defer func() {
|
|
|
+ if br.ErrMsg == "" {
|
|
|
+ br.IsSendEmail = false
|
|
|
+ }
|
|
|
+ this.Data["json"] = br
|
|
|
+ this.ServeJSON()
|
|
|
+ }()
|
|
|
+ sysUser := this.SysUser
|
|
|
+ if sysUser == nil {
|
|
|
+ br.Msg = "请登录"
|
|
|
+ br.ErrMsg = "请登录,SysUser Is Empty"
|
|
|
+ br.Ret = 408
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var req request.AddFactorEdbSeriesReq
|
|
|
+ if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
|
|
|
+ br.Msg = "参数解析异常"
|
|
|
+ br.ErrMsg = fmt.Sprintf("参数解析异常, Err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ req.SeriesName = strings.TrimSpace(req.SeriesName)
|
|
|
+ if req.SeriesName == "" {
|
|
|
+ br.Msg = "请输入指标系列名称"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if len(req.EdbInfoIds) <= 0 {
|
|
|
+ br.Msg = "请选择因子指标系列"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if len(req.EdbInfoIds) > 100 {
|
|
|
+ br.Msg = "添加指标总数量不得超过100"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ calculateLen := len(req.Calculates)
|
|
|
+ if calculateLen > 5 {
|
|
|
+ br.Msg = "计算公式不可超过5个"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var calculatesJson string
|
|
|
+ if calculateLen > 0 {
|
|
|
+ b, e := json.Marshal(req.Calculates)
|
|
|
+ if e != nil {
|
|
|
+ br.Msg = "计算方式格式有误"
|
|
|
+ br.ErrMsg = "解析计算方式参数失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ calculatesJson = string(b)
|
|
|
+ for _, v := range req.Calculates {
|
|
|
+ switch v.Source {
|
|
|
+ case utils.EdbBaseCalculateNszydpjjs, utils.EdbBaseCalculateHbz, utils.EdbBaseCalculateHcz, utils.EdbBaseCalculateCjjx:
|
|
|
+ if v.Formula == nil {
|
|
|
+ br.Msg = "请输入N值"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ formulaInt, ok := v.Formula.(int)
|
|
|
+ if !ok {
|
|
|
+ br.Msg = "N值格式有误"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if formulaInt <= 0 {
|
|
|
+ br.Msg = "N值不可小于0, 重新输入"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ case utils.EdbBaseCalculateExponentialSmoothing:
|
|
|
+ if v.Formula == nil {
|
|
|
+ br.Msg = "请填写alpha值"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ alpha, ok := v.Formula.(float64)
|
|
|
+ if ok {
|
|
|
+ br.Msg = "alpha值格式有误"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if alpha <= 0 || alpha >= 1 {
|
|
|
+ br.Msg = "alpha值应在0-1之间, 请重新输入"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ edbArr, e := data_manage.GetEdbInfoByIdList(req.EdbInfoIds)
|
|
|
+ if e != nil {
|
|
|
+ br.Msg = "操作失败"
|
|
|
+ br.ErrMsg = "获取指标列表失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if len(edbArr) == 0 {
|
|
|
+ br.Msg = "因子指标系列有误"
|
|
|
+ br.ErrMsg = "因子指标系列长度为0"
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 新增指标系列
|
|
|
+ seriesItem := new(data_manage.FactorEdbSeries)
|
|
|
+ seriesItem.SeriesName = req.SeriesName
|
|
|
+ seriesItem.EdbInfoType = req.EdbInfoType
|
|
|
+ seriesItem.CreateTime = time.Now().Local()
|
|
|
+ seriesItem.ModifyTime = time.Now().Local()
|
|
|
+ if calculateLen > 0 {
|
|
|
+ seriesItem.CalculateState = data_manage.FactorEdbSeriesCalculating
|
|
|
+ seriesItem.CalculateStep = calculatesJson
|
|
|
+ }
|
|
|
+ mappings := make([]*data_manage.FactorEdbSeriesMapping, 0)
|
|
|
+ for _, v := range edbArr {
|
|
|
+ mappings = append(mappings, &data_manage.FactorEdbSeriesMapping{
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
+ EdbCode: v.EdbCode,
|
|
|
+ CreateTime: time.Now().Local(),
|
|
|
+ ModifyTime: time.Now().Local(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ seriesId, e := seriesItem.CreateSeriesAndMapping(seriesItem, mappings)
|
|
|
+ if e != nil {
|
|
|
+ br.Msg = "操作失败"
|
|
|
+ br.ErrMsg = "新增因子指标系列失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算指标数据
|
|
|
+ var calculateResp data_manage.FactorEdbSeriesStepCalculateResp
|
|
|
+ if calculateLen > 0 {
|
|
|
+ calculateResp, e = data.FactorEdbStepCalculate(seriesId, edbArr, req.Calculates, this.Lang, false)
|
|
|
+ if e != nil {
|
|
|
+ br.Msg = "操作失败"
|
|
|
+ br.ErrMsg = "计算因子指标失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新系列计算状态
|
|
|
+ cols := []string{seriesItem.Cols().CalculateState, seriesItem.Cols().ModifyTime}
|
|
|
+ seriesItem.CalculateState = data_manage.FactorEdbSeriesCalculated
|
|
|
+ seriesItem.ModifyTime = time.Now().Local()
|
|
|
+ if e = seriesItem.Update(cols); e != nil {
|
|
|
+ br.Msg = "操作失败"
|
|
|
+ br.ErrMsg = "更新因子指标系列计算状态失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ for _, v := range edbArr {
|
|
|
+ calculateResp.Success = append(calculateResp.Success, data_manage.FactorEdbSeriesStepCalculateResult{
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
+ EdbCode: v.EdbCode,
|
|
|
+ Msg: "保存成功",
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ calculateResp.SeriesId = seriesId
|
|
|
+
|
|
|
+ br.Data = calculateResp
|
|
|
+ br.Ret = 200
|
|
|
+ br.Success = true
|
|
|
+ br.Msg = "操作成功"
|
|
|
+ br.IsAddLog = true
|
|
|
+}
|
|
|
+
|
|
|
+// Edit
|
|
|
+// @Title 编辑
|
|
|
+// @Description 编辑
|
|
|
+// @Param request body request.EditFactorEdbSeriesReq true "type json string"
|
|
|
+// @Success Ret=200 操作成功
|
|
|
+// @router /factor_edb_series/edit [post]
|
|
|
+func (this *FactorEdbSeriesController) Edit() {
|
|
|
+ br := new(models.BaseResponse).Init()
|
|
|
+ defer func() {
|
|
|
+ if br.ErrMsg == "" {
|
|
|
+ br.IsSendEmail = false
|
|
|
+ }
|
|
|
+ this.Data["json"] = br
|
|
|
+ this.ServeJSON()
|
|
|
+ }()
|
|
|
+ sysUser := this.SysUser
|
|
|
+ if sysUser == nil {
|
|
|
+ br.Msg = "请登录"
|
|
|
+ br.ErrMsg = "请登录,SysUser Is Empty"
|
|
|
+ br.Ret = 408
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var req request.EditFactorEdbSeriesReq
|
|
|
+ if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
|
|
|
+ br.Msg = "参数解析异常"
|
|
|
+ br.ErrMsg = fmt.Sprintf("参数解析异常, Err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if req.SeriesId <= 0 {
|
|
|
+ br.Msg = "参数有误"
|
|
|
+ br.ErrMsg = fmt.Sprintf("参数有误, SeriesId: %d", req.SeriesId)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ req.SeriesName = strings.TrimSpace(req.SeriesName)
|
|
|
+ if req.SeriesName == "" {
|
|
|
+ br.Msg = "请输入指标系列名称"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if len(req.EdbInfoIds) <= 0 {
|
|
|
+ br.Msg = "请选择因子指标系列"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if len(req.EdbInfoIds) > 100 {
|
|
|
+ br.Msg = "添加指标总数量不得超过100"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ calculateLen := len(req.Calculates)
|
|
|
+ if calculateLen > 5 {
|
|
|
+ br.Msg = "计算公式不可超过5个"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var calculatesJson string
|
|
|
+ if calculateLen > 0 {
|
|
|
+ b, e := json.Marshal(req.Calculates)
|
|
|
+ if e != nil {
|
|
|
+ br.Msg = "计算方式格式有误"
|
|
|
+ br.ErrMsg = "解析计算方式参数失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ calculatesJson = string(b)
|
|
|
+ for _, v := range req.Calculates {
|
|
|
+ switch v.Source {
|
|
|
+ case utils.EdbBaseCalculateNszydpjjs, utils.EdbBaseCalculateHbz, utils.EdbBaseCalculateHcz, utils.EdbBaseCalculateCjjx:
|
|
|
+ if v.Formula == nil {
|
|
|
+ br.Msg = "请输入N值"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ formulaInt, ok := v.Formula.(int)
|
|
|
+ if !ok {
|
|
|
+ br.Msg = "N值格式有误"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if formulaInt <= 0 {
|
|
|
+ br.Msg = "N值不可小于0, 重新输入"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ case utils.EdbBaseCalculateExponentialSmoothing:
|
|
|
+ if v.Formula == nil {
|
|
|
+ br.Msg = "请填写alpha值"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ alpha, ok := v.Formula.(float64)
|
|
|
+ if ok {
|
|
|
+ br.Msg = "alpha值格式有误"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if alpha <= 0 || alpha >= 1 {
|
|
|
+ br.Msg = "alpha值应在0-1之间, 请重新输入"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ seriesOb := new(data_manage.FactorEdbSeries)
|
|
|
+ seriesItem, e := seriesOb.GetItemById(req.SeriesId)
|
|
|
+ if e != nil {
|
|
|
+ if e.Error() == utils.ErrNoRow() {
|
|
|
+ br.Msg = "该因子指标系列不存在"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ br.Msg = "获取失败"
|
|
|
+ br.ErrMsg = "获取因子指标系列失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ edbArr, e := data_manage.GetEdbInfoByIdList(req.EdbInfoIds)
|
|
|
+ if e != nil {
|
|
|
+ br.Msg = "操作失败"
|
|
|
+ br.ErrMsg = "获取指标列表失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if len(edbArr) == 0 {
|
|
|
+ br.Msg = "因子指标系列有误"
|
|
|
+ br.ErrMsg = "因子指标系列长度为0"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var calculateResp data_manage.FactorEdbSeriesStepCalculateResp
|
|
|
+ calculateResp.SeriesId = seriesItem.FactorEdbSeriesId
|
|
|
+
|
|
|
+ // 如果不需要进行重新计算(比如只改了系列名称)那么只更新指标系列
|
|
|
+ seriesItem.SeriesName = req.SeriesName
|
|
|
+ seriesItem.EdbInfoType = req.EdbInfoType
|
|
|
+ seriesItem.ModifyTime = time.Now().Local()
|
|
|
+ updateCols := []string{seriesOb.Cols().SeriesName, seriesOb.Cols().EdbInfoType, seriesOb.Cols().ModifyTime}
|
|
|
+ if !req.Recalculate {
|
|
|
+ if e = seriesItem.Update(updateCols); e != nil {
|
|
|
+ br.Msg = "操作成功"
|
|
|
+ br.ErrMsg = "更新因子指标系列信息失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for _, v := range edbArr {
|
|
|
+ calculateResp.Success = append(calculateResp.Success, data_manage.FactorEdbSeriesStepCalculateResult{
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
+ EdbCode: v.EdbCode,
|
|
|
+ Msg: "保存成功",
|
|
|
+ })
|
|
|
+ }
|
|
|
+ br.Data = calculateResp
|
|
|
+ br.Ret = 200
|
|
|
+ br.Success = true
|
|
|
+ br.Msg = "操作成功"
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新系列信息和指标关联
|
|
|
+ if calculateLen > 0 {
|
|
|
+ seriesItem.CalculateState = data_manage.FactorEdbSeriesCalculating
|
|
|
+ seriesItem.CalculateStep = calculatesJson
|
|
|
+ updateCols = append(updateCols, seriesOb.Cols().CalculateState, seriesOb.Cols().CalculateStep)
|
|
|
+ }
|
|
|
+ mappings := make([]*data_manage.FactorEdbSeriesMapping, 0)
|
|
|
+ for _, v := range edbArr {
|
|
|
+ mappings = append(mappings, &data_manage.FactorEdbSeriesMapping{
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
+ EdbCode: v.EdbCode,
|
|
|
+ CreateTime: time.Now().Local(),
|
|
|
+ ModifyTime: time.Now().Local(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if e = seriesItem.EditSeriesAndMapping(seriesItem, mappings, updateCols); e != nil {
|
|
|
+ br.Msg = "操作失败"
|
|
|
+ br.ErrMsg = "编辑因子指标系列失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重新计算
|
|
|
+ calculateResp, e = data.FactorEdbStepCalculate(seriesItem.FactorEdbSeriesId, edbArr, req.Calculates, this.Lang, req.Recalculate)
|
|
|
+ if e != nil {
|
|
|
+ br.Msg = "操作失败"
|
|
|
+ br.ErrMsg = "计算因子指标失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新系列计算状态
|
|
|
+ cols := []string{seriesItem.Cols().CalculateState, seriesItem.Cols().ModifyTime}
|
|
|
+ seriesItem.CalculateState = data_manage.FactorEdbSeriesCalculated
|
|
|
+ seriesItem.ModifyTime = time.Now().Local()
|
|
|
+ if e = seriesItem.Update(cols); e != nil {
|
|
|
+ br.Msg = "操作失败"
|
|
|
+ br.ErrMsg = "更新因子指标系列计算状态失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ br.Data = calculateResp
|
|
|
+ br.Ret = 200
|
|
|
+ br.Success = true
|
|
|
+ br.Msg = "操作成功"
|
|
|
+ br.IsAddLog = true
|
|
|
+}
|
|
|
+
|
|
|
+// Detail
|
|
|
+// @Title 详情
|
|
|
+// @Description 详情
|
|
|
+// @Param SeriesId query int false "多因子指标系列ID"
|
|
|
+// @Success 200 {object} data_manage.FactorEdbSeriesDetail
|
|
|
+// @router /factor_edb_series/detail [get]
|
|
|
+func (this *FactorEdbSeriesController) Detail() {
|
|
|
+ br := new(models.BaseResponse).Init()
|
|
|
+ defer func() {
|
|
|
+ if br.ErrMsg == "" {
|
|
|
+ br.IsSendEmail = false
|
|
|
+ }
|
|
|
+ this.Data["json"] = br
|
|
|
+ this.ServeJSON()
|
|
|
+ }()
|
|
|
+ sysUser := this.SysUser
|
|
|
+ if sysUser == nil {
|
|
|
+ br.Msg = "请登录"
|
|
|
+ br.ErrMsg = "请登录,SysUser Is Empty"
|
|
|
+ br.Ret = 408
|
|
|
+ return
|
|
|
+ }
|
|
|
+ seriesId, _ := this.GetInt("SeriesId", 0)
|
|
|
+ if seriesId <= 0 {
|
|
|
+ br.Msg = "参数有误"
|
|
|
+ br.ErrMsg = fmt.Sprintf("参数有误, SeriesId: %d", seriesId)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ seriesOb := new(data_manage.FactorEdbSeries)
|
|
|
+ series, e := seriesOb.GetItemById(seriesId)
|
|
|
+ if e != nil {
|
|
|
+ if e.Error() == utils.ErrNoRow() {
|
|
|
+ br.Msg = "该因子指标系列不存在"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ br.Msg = "获取失败"
|
|
|
+ br.ErrMsg = "获取因子指标系列失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ mappingOb := new(data_manage.FactorEdbSeriesMapping)
|
|
|
+ cond := fmt.Sprintf(" AND %s = ?", mappingOb.Cols().FactorEdbSeriesId)
|
|
|
+ pars := make([]interface{}, 0)
|
|
|
+ pars = append(pars, seriesId)
|
|
|
+ mappings, e := mappingOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", mappingOb.Cols().CreateTime))
|
|
|
+ if e != nil {
|
|
|
+ br.Msg = "获取失败"
|
|
|
+ br.ErrMsg = "获取因子指标系列关联失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ resp := new(data_manage.FactorEdbSeriesDetail)
|
|
|
+ resp.FactorEdbSeriesItem = series.Format2Item()
|
|
|
+ for _, m := range mappings {
|
|
|
+ resp.EdbMappings = append(resp.EdbMappings, m.Format2Item())
|
|
|
+ }
|
|
|
+
|
|
|
+ br.Data = resp
|
|
|
+ br.Ret = 200
|
|
|
+ br.Success = true
|
|
|
+ br.Msg = "获取成功"
|
|
|
+}
|
|
|
+
|
|
|
+// CorrelationMatrix
|
|
|
+// @Title 因子指标系列-相关性矩阵
|
|
|
+// @Description 因子指标系列-相关性矩阵
|
|
|
+// @Param request body request.FactorEdbSeriesCorrelationMatrixReq true "type json string"
|
|
|
+// @Success 200 {object} data_manage.FactorEdbSeriesCorrelationMatrixItem
|
|
|
+// @router /factor_edb_series/correlation/matrix [post]
|
|
|
+func (this *FactorEdbSeriesController) CorrelationMatrix() {
|
|
|
+ br := new(models.BaseResponse).Init()
|
|
|
+ defer func() {
|
|
|
+ if br.ErrMsg == "" {
|
|
|
+ br.IsSendEmail = false
|
|
|
+ }
|
|
|
+ this.Data["json"] = br
|
|
|
+ this.ServeJSON()
|
|
|
+ }()
|
|
|
+ sysUser := this.SysUser
|
|
|
+ if sysUser == nil {
|
|
|
+ br.Msg = "请登录"
|
|
|
+ br.ErrMsg = "请登录,SysUser Is Empty"
|
|
|
+ br.Ret = 408
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var req request.FactorEdbSeriesCorrelationMatrixReq
|
|
|
+ if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
|
|
|
+ br.Msg = "参数解析异常"
|
|
|
+ br.ErrMsg = fmt.Sprintf("参数解析异常, Err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if req.BaseEdbInfoId <= 0 {
|
|
|
+ br.Msg = "请选择标的指标"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if len(req.SeriesIds) == 0 {
|
|
|
+ br.Msg = "请选择因子指标系列"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if req.Correlation.LeadValue <= 0 {
|
|
|
+ br.Msg = "分析周期不允许设置为负数或0"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if req.Correlation.LeadUnit == "" {
|
|
|
+ br.Msg = "请选择分析周期频度"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ leadUnitDays, ok := utils.FrequencyDaysMap[req.Correlation.LeadUnit]
|
|
|
+ if !ok {
|
|
|
+ br.Msg = "错误的分析周期频度"
|
|
|
+ br.ErrMsg = fmt.Sprintf("分析周期频度有误: %s", req.Correlation.LeadUnit)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if req.Correlation.CalculateUnit == "" {
|
|
|
+ br.Msg = "请选择计算窗口频度"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ calculateUnitDays, ok := utils.FrequencyDaysMap[req.Correlation.CalculateUnit]
|
|
|
+ if !ok {
|
|
|
+ br.Msg = "错误的计算窗口频度"
|
|
|
+ br.ErrMsg = fmt.Sprintf("计算窗口频度有误: %s", req.Correlation.CalculateUnit)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ leadDays := 2 * req.Correlation.LeadValue * leadUnitDays
|
|
|
+ calculateDays := req.Correlation.CalculateValue * calculateUnitDays
|
|
|
+ if calculateDays < leadDays {
|
|
|
+ br.Msg = "计算窗口必须≥2*分析周期"
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取标的指标信息及数据
|
|
|
+ baseEdb, e := data_manage.GetEdbInfoById(req.BaseEdbInfoId)
|
|
|
+ if e != nil {
|
|
|
+ if e.Error() == utils.ErrNoRow() {
|
|
|
+ br.Msg = "标的指标不存在"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ br.Msg = "获取失败"
|
|
|
+ br.ErrMsg = "获取标的指标信息失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ dataListA := make([]*data_manage.EdbDataList, 0)
|
|
|
+ {
|
|
|
+ // 标的指标数据日期区间
|
|
|
+ startDate := time.Now().AddDate(0, 0, -calculateDays).Format(utils.FormatDate)
|
|
|
+ endDate := time.Now().Format(utils.FormatDate)
|
|
|
+ startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
|
|
|
+ startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate) // 不包含第一天
|
|
|
+ switch baseEdb.EdbInfoType {
|
|
|
+ case 0:
|
|
|
+ dataListA, e = data_manage.GetEdbDataList(baseEdb.Source, baseEdb.SubSource, baseEdb.EdbInfoId, startDate, endDate)
|
|
|
+ case 1:
|
|
|
+ _, dataListA, _, _, e, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdb.EdbInfoId, startDate, endDate, false)
|
|
|
+ default:
|
|
|
+ br.Msg = "获取失败"
|
|
|
+ br.ErrMsg = fmt.Sprintf("标的指标类型异常: %d", baseEdb.EdbInfoType)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if e != nil {
|
|
|
+ br.Msg = "获取失败"
|
|
|
+ br.ErrMsg = "获取标的指标数据失败, Err:" + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取因子系列
|
|
|
+ seriesIdItem := make(map[int]*data_manage.FactorEdbSeries)
|
|
|
+ {
|
|
|
+ ob := new(data_manage.FactorEdbSeries)
|
|
|
+ cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().PrimaryId, utils.GetOrmInReplace(len(req.SeriesIds)))
|
|
|
+ pars := make([]interface{}, 0)
|
|
|
+ pars = append(pars, req.SeriesIds)
|
|
|
+ items, e := ob.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", ob.Cols().PrimaryId))
|
|
|
+ if e != nil {
|
|
|
+ br.Msg = "获取失败"
|
|
|
+ br.ErrMsg = "获取因子指标系列失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if len(items) != len(req.SeriesIds) {
|
|
|
+ br.Msg = "获取失败"
|
|
|
+ br.ErrMsg = "因子指标系列数量有误"
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for _, v := range items {
|
|
|
+ seriesIdItem[v.FactorEdbSeriesId] = v
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取因子指标
|
|
|
+ edbMappings := make([]*data_manage.FactorEdbSeriesMapping, 0)
|
|
|
+ edbInfoIds := make([]int, 0)
|
|
|
+ {
|
|
|
+ ob := new(data_manage.FactorEdbSeriesMapping)
|
|
|
+ cond := fmt.Sprintf(" AND %s IN (%s)", ob.Cols().FactorEdbSeriesId, utils.GetOrmInReplace(len(req.SeriesIds)))
|
|
|
+ pars := make([]interface{}, 0)
|
|
|
+ pars = append(pars, req.SeriesIds)
|
|
|
+ order := fmt.Sprintf("%s ASC, %s ASC", ob.Cols().FactorEdbSeriesId, ob.Cols().EdbInfoId)
|
|
|
+ items, e := ob.GetItemsByCondition(cond, pars, []string{}, order)
|
|
|
+ if e != nil {
|
|
|
+ br.Msg = "获取失败"
|
|
|
+ br.ErrMsg = "获取因子指标关联失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for _, v := range items {
|
|
|
+ edbInfoIds = append(edbInfoIds, v.EdbInfoId)
|
|
|
+ }
|
|
|
+ edbMappings = items
|
|
|
+ }
|
|
|
+ edbIdItem := make(map[int]*data_manage.EdbInfo)
|
|
|
+ edbItems, e := data_manage.GetEdbInfoByIdList(edbInfoIds)
|
|
|
+ if e != nil {
|
|
|
+ br.Msg = "获取失败"
|
|
|
+ br.ErrMsg = "获取因子指标失败, Err: " + e.Error()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for _, v := range edbItems {
|
|
|
+ edbIdItem[v.EdbInfoId] = v
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取因子指标数据, 计算相关性
|
|
|
+ resp := new(data_manage.FactorEdbSeriesCorrelationMatrixResp)
|
|
|
+ calculateDataOb := new(data_manage.FactorEdbSeriesCalculateData)
|
|
|
+
|
|
|
+ calculateWorkers := make(chan struct{}, 10)
|
|
|
+ wg := sync.WaitGroup{}
|
|
|
+ edbExists := make(map[string]bool)
|
|
|
+ for _, v := range edbMappings {
|
|
|
+ existsKey := fmt.Sprintf("%d-%d", v.FactorEdbSeriesId, v.EdbInfoId)
|
|
|
+ if edbExists[existsKey] {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ edbExists[existsKey] = true
|
|
|
+
|
|
|
+ edbItem := edbIdItem[v.EdbInfoId]
|
|
|
+ if edbItem == nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ seriesItem := seriesIdItem[v.FactorEdbSeriesId]
|
|
|
+ if seriesItem == nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ wg.Add(1)
|
|
|
+ go func(mapping *data_manage.FactorEdbSeriesMapping, edb *data_manage.EdbInfo, series *data_manage.FactorEdbSeries) {
|
|
|
+ defer func() {
|
|
|
+ wg.Done()
|
|
|
+ <-calculateWorkers
|
|
|
+ }()
|
|
|
+ calculateWorkers <- struct{}{}
|
|
|
+
|
|
|
+ var item data_manage.FactorEdbSeriesCorrelationMatrixItem
|
|
|
+ item.SeriesId = series.FactorEdbSeriesId
|
|
|
+ item.EdbInfoId = edb.EdbInfoId
|
|
|
+ item.EdbCode = edb.EdbCode
|
|
|
+ item.EdbName = edb.EdbName
|
|
|
+
|
|
|
+ // 获取指标数据
|
|
|
+ dataListB := make([]*data_manage.EdbDataList, 0)
|
|
|
+ if series.CalculateState == data_manage.FactorEdbSeriesCalculated {
|
|
|
+ cond := fmt.Sprintf(" AND %s = ? AND %s = ?", calculateDataOb.Cols().FactorEdbSeriesId, calculateDataOb.Cols().EdbInfoId)
|
|
|
+ pars := make([]interface{}, 0)
|
|
|
+ pars = append(pars, mapping.FactorEdbSeriesId, mapping.EdbInfoId)
|
|
|
+ dataItems, e := calculateDataOb.GetItemsByCondition(cond, pars, []string{calculateDataOb.Cols().DataTime, calculateDataOb.Cols().Value}, fmt.Sprintf("%s ASC", calculateDataOb.Cols().DataTime))
|
|
|
+ if e != nil {
|
|
|
+ item.Msg = fmt.Sprintf("计算失败")
|
|
|
+ item.ErrMsg = fmt.Sprintf("获取计算数据失败, err: %v", e)
|
|
|
+ resp.Fail = append(resp.Fail, item)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ dataListB = data_manage.TransEdbSeriesCalculateData2EdbDataList(dataItems)
|
|
|
+ } else {
|
|
|
+ switch edb.EdbInfoType {
|
|
|
+ case 0:
|
|
|
+ dataListB, e = data_manage.GetEdbDataList(edb.Source, edb.SubSource, edb.EdbInfoId, "", "")
|
|
|
+ case 1:
|
|
|
+ _, dataListB, _, _, e, _ = data.GetPredictDataListByPredictEdbInfoId(edb.EdbInfoId, "", "", false)
|
|
|
+ default:
|
|
|
+ item.Msg = fmt.Sprintf("计算失败")
|
|
|
+ item.ErrMsg = fmt.Sprintf("指标类型异常, edbType: %d", edb.EdbInfoType)
|
|
|
+ resp.Fail = append(resp.Fail, item)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算相关性
|
|
|
+ xEdbIdValue, yDataList, e := correlationServ.CalculateCorrelation(req.Correlation.LeadValue, req.Correlation.LeadUnit, baseEdb.Frequency, edb.Frequency, dataListA, dataListB)
|
|
|
+ if e != nil {
|
|
|
+ item.Msg = fmt.Sprintf("计算失败")
|
|
|
+ item.ErrMsg = fmt.Sprintf("相关性计算失败, err: %v", e)
|
|
|
+ resp.Fail = append(resp.Fail, item)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按照固定规则排期数[0 1 2 3 -1 -2 -3]
|
|
|
+ yData := yDataList[0].Value
|
|
|
+ yLen := len(yData)
|
|
|
+ values := make([]data_manage.FactorEdbSeriesCorrelationMatrixValues, len(xEdbIdValue))
|
|
|
+ for k, x := range xEdbIdValue {
|
|
|
+ // y值常常会出现无数据的情况
|
|
|
+ var y float64
|
|
|
+ if k >= 0 && k < yLen {
|
|
|
+ y = yData[k]
|
|
|
+ }
|
|
|
+ y = utils.SubFloatToFloat(y, 2)
|
|
|
+ values[k] = data_manage.FactorEdbSeriesCorrelationMatrixValues{
|
|
|
+ XData: x, YData: y,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sort.Sort(data_manage.FactorEdbSeriesCorrelationMatrixOrder(values))
|
|
|
+
|
|
|
+ item.Msg = "计算成功"
|
|
|
+ item.Values = values
|
|
|
+ resp.Success = append(resp.Success, item)
|
|
|
+
|
|
|
+ // TODO:存储计算结果
|
|
|
+
|
|
|
+ }(v, edbItem, seriesItem)
|
|
|
+ }
|
|
|
+ wg.Wait()
|
|
|
+
|
|
|
+ br.Data = resp
|
|
|
+ br.Ret = 200
|
|
|
+ br.Success = true
|
|
|
+ br.Msg = "获取成功"
|
|
|
+}
|