|
@@ -0,0 +1,684 @@
|
|
|
+package ai_predict_model
|
|
|
+
|
|
|
+import (
|
|
|
+ "eta/eta_index_lib/global"
|
|
|
+ "eta/eta_index_lib/models"
|
|
|
+ "eta/eta_index_lib/utils"
|
|
|
+ "fmt"
|
|
|
+ "github.com/rdlucklib/rdluck_tools/paging"
|
|
|
+ "strconv"
|
|
|
+ "strings"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+// 训练状态
|
|
|
+const (
|
|
|
+ RunStatusWaiting = "待运行"
|
|
|
+ RunStatusRunning = "运行中"
|
|
|
+ RunStatusSuccess = "运行成功"
|
|
|
+ RunStatusFailed = "运行失败"
|
|
|
+)
|
|
|
+
|
|
|
+// AiPredictModelIndex AI预测模型标的
|
|
|
+type AiPredictModelIndex struct {
|
|
|
+ AiPredictModelIndexId int `orm:"column(ai_predict_model_index_id);pk" gorm:"primaryKey"`
|
|
|
+ IndexName string `description:"标的名称"`
|
|
|
+ IndexCode string `description:"自生成的指标编码"`
|
|
|
+ ClassifyId int `description:"分类ID"`
|
|
|
+ ModelFramework string `description:"模型框架"`
|
|
|
+ PredictDate time.Time `description:"预测日期"`
|
|
|
+ PredictValue float64 `description:"预测值"`
|
|
|
+ PredictFrequency string `description:"预测频度"`
|
|
|
+ DirectionAccuracy string `description:"方向准确度"`
|
|
|
+ AbsoluteDeviation string `description:"绝对偏差"`
|
|
|
+ ExtraConfig string `description:"模型参数"`
|
|
|
+ Sort int `description:"排序"`
|
|
|
+ SysUserId int `description:"创建人ID"`
|
|
|
+ SysUserRealName string `description:"创建人姓名"`
|
|
|
+ LeftMin string `description:"图表左侧最小值"`
|
|
|
+ LeftMax string `description:"图表左侧最大值"`
|
|
|
+ CreateTime time.Time `description:"创建时间"`
|
|
|
+ ModifyTime time.Time `description:"修改时间"`
|
|
|
+ AiPredictModelIndexConfigId int `gorm:"column:ai_predict_model_index_config_id" description:"标的当前的配置id"`
|
|
|
+ ScriptPath string `gorm:"column:script_path" description:"脚本的路径"`
|
|
|
+ TrainStatus string `gorm:"column:train_status" description:"训练状态,枚举值:待训练,训练中,训练成功,训练失败"`
|
|
|
+ RunStatus string `gorm:"column:run_status" description:"运行状态,枚举值:待运行,运行中,运行成功,运行失败"`
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) TableName() string {
|
|
|
+ return "ai_predict_model_index"
|
|
|
+}
|
|
|
+
|
|
|
+type AiPredictModelIndexCols struct {
|
|
|
+ PrimaryId string
|
|
|
+ IndexName string
|
|
|
+ IndexCode string
|
|
|
+ ClassifyId string
|
|
|
+ ModelFramework string
|
|
|
+ PredictDate string
|
|
|
+ PredictValue string
|
|
|
+ DirectionAccuracy string
|
|
|
+ AbsoluteDeviation string
|
|
|
+ ExtraConfig string
|
|
|
+ Sort string
|
|
|
+ SysUserId string
|
|
|
+ SysUserRealName string
|
|
|
+ LeftMin string
|
|
|
+ LeftMax string
|
|
|
+ CreateTime string
|
|
|
+ ModifyTime string
|
|
|
+ AiPredictModelIndexConfigId string
|
|
|
+ ScriptPath string
|
|
|
+ TrainStatus string
|
|
|
+ RunStatus string
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) Cols() AiPredictModelIndexCols {
|
|
|
+ return AiPredictModelIndexCols{
|
|
|
+ PrimaryId: "ai_predict_model_index_id",
|
|
|
+ IndexName: "index_name",
|
|
|
+ IndexCode: "index_code",
|
|
|
+ ClassifyId: "classify_id",
|
|
|
+ ModelFramework: "model_framework",
|
|
|
+ PredictDate: "predict_date",
|
|
|
+ PredictValue: "predict_value",
|
|
|
+ DirectionAccuracy: "direction_accuracy",
|
|
|
+ AbsoluteDeviation: "absolute_deviation",
|
|
|
+ ExtraConfig: "extra_config",
|
|
|
+ Sort: "sort",
|
|
|
+ SysUserId: "sys_user_id",
|
|
|
+ SysUserRealName: "sys_user_real_name",
|
|
|
+ LeftMin: "left_min",
|
|
|
+ LeftMax: "left_max",
|
|
|
+ CreateTime: "create_time",
|
|
|
+ ModifyTime: "modify_time",
|
|
|
+ AiPredictModelIndexConfigId: "ai_predict_model_index_config_id",
|
|
|
+ ScriptPath: "script_path",
|
|
|
+ TrainStatus: "train_status",
|
|
|
+ RunStatus: "run_status",
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) Create() (err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ err = o.Create(m).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) CreateMulti(items []*AiPredictModelIndex) (err error) {
|
|
|
+ if len(items) == 0 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ err = o.CreateInBatches(items, utils.MultiAddNum).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) Update(cols []string) (err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ err = o.Select(cols).Updates(m).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) Remove() (err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
|
|
|
+ err = o.Exec(sql, m.AiPredictModelIndexId).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) MultiRemove(ids []int) (err error) {
|
|
|
+ if len(ids) == 0 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
|
|
|
+ err = o.Exec(sql, ids).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) RemoveByCondition(condition string, pars []interface{}) (err error) {
|
|
|
+ if condition == "" {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ sql := fmt.Sprintf(`DELETE FROM %s WHERE %s`, m.TableName(), condition)
|
|
|
+ err = o.Exec(sql, pars...).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) GetItemById(id int) (item *AiPredictModelIndex, err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
|
|
|
+ err = o.Raw(sql, id).First(&item).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetItemByConfigId
|
|
|
+// @Description: 根据配置id获取标的信息
|
|
|
+// @author: Roc
|
|
|
+// @receiver m
|
|
|
+// @datetime 2025-05-06 13:31:24
|
|
|
+// @param configId int
|
|
|
+// @return item *AiPredictModelIndex
|
|
|
+// @return err error
|
|
|
+func (m *AiPredictModelIndex) GetItemByConfigId(configId int) (item *AiPredictModelIndex, err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().AiPredictModelIndexConfigId)
|
|
|
+ err = o.Raw(sql, configId).First(&item).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *AiPredictModelIndex, err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ order := ``
|
|
|
+ if orderRule != "" {
|
|
|
+ order = ` ORDER BY ` + orderRule
|
|
|
+ }
|
|
|
+ sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
|
|
|
+ err = o.Raw(sql, pars...).First(&item).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
|
|
|
+ err = o.Raw(sql, pars...).Scan(&count).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*AiPredictModelIndex, err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ fields := strings.Join(fieldArr, ",")
|
|
|
+ if len(fieldArr) == 0 {
|
|
|
+ fields = `*`
|
|
|
+ }
|
|
|
+ order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
|
|
|
+ if orderRule != "" {
|
|
|
+ order = ` ORDER BY ` + orderRule
|
|
|
+ }
|
|
|
+ sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
|
|
|
+ err = o.Raw(sql, pars...).Find(&items).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*AiPredictModelIndex, err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ fields := strings.Join(fieldArr, ",")
|
|
|
+ if len(fieldArr) == 0 {
|
|
|
+ fields = `*`
|
|
|
+ }
|
|
|
+ order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
|
|
|
+ if orderRule != "" {
|
|
|
+ order = ` ORDER BY ` + orderRule
|
|
|
+ }
|
|
|
+ sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
|
|
|
+ pars = append(pars, startSize, pageSize)
|
|
|
+ err = o.Raw(sql, pars...).Find(&items).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// AiPredictModelIndexItem AI预测模型标的信息
|
|
|
+type AiPredictModelIndexItem struct {
|
|
|
+ IndexId int `description:"标的ID"`
|
|
|
+ IndexName string `description:"标的名称"`
|
|
|
+ IndexCode string `description:"自生成的指标编码"`
|
|
|
+ ClassifyId int `description:"分类ID"`
|
|
|
+ ClassifyName string `description:"分类名称"`
|
|
|
+ ModelFramework string `description:"模型框架"`
|
|
|
+ PredictDate string `description:"预测日期"`
|
|
|
+ PredictValue float64 `description:"预测值"`
|
|
|
+ PredictFrequency string `description:"预测频度"`
|
|
|
+ DirectionAccuracy string `description:"方向准确度"`
|
|
|
+ AbsoluteDeviation string `description:"绝对偏差"`
|
|
|
+ ExtraConfig string `description:"模型参数"`
|
|
|
+ SysUserId int `description:"创建人ID"`
|
|
|
+ SysUserRealName string `description:"创建人姓名"`
|
|
|
+ CreateTime string `description:"创建时间"`
|
|
|
+ ModifyTime string `description:"修改时间"`
|
|
|
+ SearchText string `description:"搜索结果(含高亮)"`
|
|
|
+ AiPredictModelIndexConfigId int `gorm:"column:ai_predict_model_index_config_id" description:"标的当前的配置id"`
|
|
|
+ ScriptPath string `gorm:"column:script_path" description:"脚本的路径"`
|
|
|
+ TrainStatus string `gorm:"column:train_status" description:"训练状态,枚举值:待训练,训练中,训练成功,训练失败"`
|
|
|
+ RunStatus string `gorm:"column:run_status" description:"运行状态,枚举值:待运行,运行中,运行成功,运行失败"`
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) Format2Item() (item *AiPredictModelIndexItem) {
|
|
|
+ item = new(AiPredictModelIndexItem)
|
|
|
+ item.IndexId = m.AiPredictModelIndexId
|
|
|
+ item.IndexName = m.IndexName
|
|
|
+ item.IndexCode = m.IndexCode
|
|
|
+ item.ClassifyId = m.ClassifyId
|
|
|
+ item.ModelFramework = m.ModelFramework
|
|
|
+ item.PredictDate = utils.TimeTransferString(utils.FormatDate, m.PredictDate)
|
|
|
+ item.PredictValue = m.PredictValue
|
|
|
+ item.PredictFrequency = m.PredictFrequency
|
|
|
+ item.DirectionAccuracy = m.DirectionAccuracy
|
|
|
+ item.AbsoluteDeviation = m.AbsoluteDeviation
|
|
|
+ item.ExtraConfig = m.ExtraConfig
|
|
|
+ item.SysUserId = m.SysUserId
|
|
|
+ item.SysUserRealName = m.SysUserRealName
|
|
|
+ item.AiPredictModelIndexConfigId = m.AiPredictModelIndexConfigId
|
|
|
+ item.ScriptPath = m.ScriptPath
|
|
|
+ item.TrainStatus = m.TrainStatus
|
|
|
+ item.RunStatus = m.RunStatus
|
|
|
+ item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, m.CreateTime)
|
|
|
+ item.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, m.ModifyTime)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+type AiPredictModelIndexPageListResp struct {
|
|
|
+ Paging *paging.PagingItem
|
|
|
+ List []*AiPredictModelIndexItem `description:"列表"`
|
|
|
+}
|
|
|
+
|
|
|
+// RemoveIndexAndData 删除标的及数据
|
|
|
+func (m *AiPredictModelIndex) RemoveIndexAndData(indexId int, chartIds []int) (err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ tx := o.Begin()
|
|
|
+ defer func() {
|
|
|
+ if err != nil {
|
|
|
+ _ = tx.Rollback()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ _ = tx.Commit()
|
|
|
+ }()
|
|
|
+
|
|
|
+ sql := `DELETE FROM ai_predict_model_index WHERE ai_predict_model_index_id = ? LIMIT 1`
|
|
|
+ e := tx.Exec(sql, indexId).Error
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("remove index err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ sql = ` DELETE FROM ai_predict_model_data WHERE ai_predict_model_index_id = ?`
|
|
|
+ e = tx.Exec(sql, indexId).Error
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("remove index data err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 删除图表
|
|
|
+ if len(chartIds) == 0 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ sql = ` DELETE FROM chart_info WHERE chart_info_id IN ?`
|
|
|
+ if e = tx.Exec(sql, chartIds).Error; e != nil {
|
|
|
+ err = fmt.Errorf("remove charts err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ sql = ` DELETE FROM chart_edb_mapping WHERE chart_info_id IN ?`
|
|
|
+ if e = tx.Exec(sql, chartIds).Error; e != nil {
|
|
|
+ err = fmt.Errorf("remove chart mappings err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// UpdateAiPredictModelIndexSortByClassifyId 根据分类id更新排序
|
|
|
+func UpdateAiPredictModelIndexSortByClassifyId(classifyId, nowSort int, prevEdbInfoId int, updateSort string) (err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ sql := ` UPDATE ai_predict_model_index SET sort = ` + updateSort + ` WHERE classify_id = ?`
|
|
|
+ if prevEdbInfoId > 0 {
|
|
|
+ sql += ` AND ( sort > ? or ( ai_predict_model_index_id > ` + fmt.Sprint(prevEdbInfoId) + ` and sort=` + fmt.Sprint(nowSort) + ` )) `
|
|
|
+ } else {
|
|
|
+ sql += ` AND ( sort > ? )`
|
|
|
+ }
|
|
|
+ err = o.Exec(sql, classifyId, nowSort).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetFirstAiPredictModelIndexByClassifyId 获取当前分类下,且排序数相同 的排序第一条的数据
|
|
|
+func GetFirstAiPredictModelIndexByClassifyId(classifyId int) (item *AiPredictModelIndex, err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ sql := ` SELECT * FROM ai_predict_model_index WHERE classify_id = ? order by sort asc,ai_predict_model_index_id asc limit 1`
|
|
|
+ err = o.Raw(sql, classifyId).First(&item).Error
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+type AiPredictModelImportData struct {
|
|
|
+ Index *AiPredictModelIndex
|
|
|
+ Data []*AiPredictModelData
|
|
|
+ Charts []*AiPredictModelImportCharts
|
|
|
+}
|
|
|
+
|
|
|
+type AiPredictModelImportCharts struct {
|
|
|
+ ChartInfo *models.ChartInfo
|
|
|
+ EdbMappings []*models.ChartEdbMapping
|
|
|
+}
|
|
|
+
|
|
|
+// ImportIndexAndData 导入数据
|
|
|
+func (m *AiPredictModelIndex) ImportIndexAndData(createIndexes, updateIndexes []*AiPredictModelImportData, updateCols []string) (chartIds []int, err error) {
|
|
|
+ if len(createIndexes) == 0 && len(updateIndexes) == 0 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ tx := o.Begin()
|
|
|
+ defer func() {
|
|
|
+ if err != nil {
|
|
|
+ _ = tx.Rollback()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ _ = tx.Commit()
|
|
|
+ }()
|
|
|
+
|
|
|
+ if len(updateIndexes) > 0 {
|
|
|
+ for _, v := range updateIndexes {
|
|
|
+ // 更新指标
|
|
|
+ e := tx.Select(updateCols).Updates(v.Index).Error
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("update index err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var hasDaily, hasMonthly bool
|
|
|
+ for _, d := range v.Data {
|
|
|
+ d.AiPredictModelIndexId = v.Index.AiPredictModelIndexId
|
|
|
+ d.IndexCode = v.Index.IndexCode
|
|
|
+ d.DataTimestamp = d.DataTime.UnixNano() / 1e6
|
|
|
+ if d.Source == ModelDataSourceDaily {
|
|
|
+ hasDaily = true
|
|
|
+ }
|
|
|
+ if d.Source == ModelDataSourceMonthly {
|
|
|
+ hasMonthly = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 哪个有数据就先清空然后重新写入,没数据就保留旧数据, 都没就忽略
|
|
|
+ if !hasDaily && !hasMonthly {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ removeCond := ``
|
|
|
+ removePars := make([]interface{}, 0)
|
|
|
+ removePars = append(removePars, v.Index.AiPredictModelIndexId)
|
|
|
+ if hasDaily && !hasMonthly {
|
|
|
+ removeCond += ` AND source = ?`
|
|
|
+ removePars = append(removePars, ModelDataSourceDaily)
|
|
|
+ }
|
|
|
+ if !hasDaily && hasMonthly {
|
|
|
+ removeCond += ` AND source = ?`
|
|
|
+ removePars = append(removePars, ModelDataSourceMonthly)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清空指标并新增
|
|
|
+ sql := fmt.Sprintf(`DELETE FROM ai_predict_model_data WHERE ai_predict_model_index_id = ? %s`, removeCond)
|
|
|
+ e = tx.Exec(sql, removePars...).Error
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("clear index data err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ e = tx.CreateInBatches(v.Data, utils.MultiAddNum).Error
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("insert index data err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(createIndexes) > 0 {
|
|
|
+ for _, v := range createIndexes {
|
|
|
+ if e := tx.Create(v.Index).Error; e != nil {
|
|
|
+ err = fmt.Errorf("insert index err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ indexId := v.Index.AiPredictModelIndexId
|
|
|
+ for _, d := range v.Data {
|
|
|
+ d.AiPredictModelIndexId = indexId
|
|
|
+ d.IndexCode = v.Index.IndexCode
|
|
|
+ d.DataTimestamp = d.DataTime.UnixNano() / 1e6
|
|
|
+ }
|
|
|
+ if e := tx.CreateInBatches(v.Data, utils.MultiAddNum).Error; e != nil {
|
|
|
+ err = fmt.Errorf("insert index data err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 图表
|
|
|
+ if len(v.Charts) == 0 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ for _, ct := range v.Charts {
|
|
|
+ if e := tx.Create(ct.ChartInfo).Error; e != nil {
|
|
|
+ err = fmt.Errorf("insert chart err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for _, cm := range ct.EdbMappings {
|
|
|
+ cm.ChartInfoId = ct.ChartInfo.ChartInfoId
|
|
|
+ cm.EdbInfoId = indexId
|
|
|
+ time.Sleep(time.Microsecond)
|
|
|
+ cm.UniqueCode = utils.MD5(fmt.Sprint(utils.CHART_PREFIX, "_", indexId, "_", strconv.FormatInt(time.Now().UnixNano(), 10)))
|
|
|
+ }
|
|
|
+ if e := tx.CreateInBatches(ct.EdbMappings, utils.MultiAddNum).Error; e != nil {
|
|
|
+ err = fmt.Errorf("insert chart mapping err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ chartIds = append(chartIds, ct.ChartInfo.ChartInfoId)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+type AiPredictModelIndexSaveReq struct {
|
|
|
+ IndexId int `description:"指标ID"`
|
|
|
+ MonthlyChart *AiPredictModelIndexSaveChart `description:"月度图表信息"`
|
|
|
+ DailyChart *AiPredictModelIndexSaveChart `description:"日度图表信息"`
|
|
|
+}
|
|
|
+
|
|
|
+type AiPredictModelIndexSaveChart struct {
|
|
|
+ LeftMin string `description:"图表左侧最小值"`
|
|
|
+ LeftMax string `description:"图表左侧最大值"`
|
|
|
+ Unit string `description:"单位"`
|
|
|
+}
|
|
|
+
|
|
|
+type AiPredictModelIndexExtraConfig struct {
|
|
|
+ MonthlyChart MonthlyChartConfig
|
|
|
+ DailyChart DailyChartConfig
|
|
|
+}
|
|
|
+type MonthlyChartConfig struct {
|
|
|
+ LeftMin string `description:"图表左侧最小值"`
|
|
|
+ LeftMax string `description:"图表左侧最大值"`
|
|
|
+ Unit string `description:"单位"`
|
|
|
+}
|
|
|
+
|
|
|
+type DailyChartConfig struct {
|
|
|
+ LeftMin string `description:"图表左侧最小值"`
|
|
|
+ LeftMax string `description:"图表左侧最大值"`
|
|
|
+ Unit string `description:"单位"`
|
|
|
+ PredictLegendName string `description:"预测图例的名称(通常为Predicted)"`
|
|
|
+}
|
|
|
+
|
|
|
+func (m *AiPredictModelIndex) GetSortMax() (sort int, err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ sql := `SELECT COALESCE(MAX(sort), 0) AS sort FROM ai_predict_model_index`
|
|
|
+ err = o.Raw(sql).Scan(&sort).Error
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 查询分类的最大排序
|
|
|
+ sql = `SELECT COALESCE(MAX(sort), 0) AS sort FROM ai_predict_model_classify`
|
|
|
+ var classifySort int
|
|
|
+ err = o.Raw(sql).Scan(&classifySort).Error
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if classifySort > sort {
|
|
|
+ sort = classifySort
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// UpdateRunStatusByIdList
|
|
|
+// @Description: 通过标的ID列表更新运行状态
|
|
|
+// @author: Roc
|
|
|
+// @receiver m
|
|
|
+// @datetime 2025-05-08 14:44:15
|
|
|
+// @param indexIdList []int
|
|
|
+// @return err error
|
|
|
+func (m *AiPredictModelIndex) UpdateRunStatusByIdList(indexIdList []int) (err error) {
|
|
|
+ if len(indexIdList) <= 0 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ sql := ` UPDATE ai_predict_model_index SET run_status = ? WHERE ai_predict_model_index_id in (?)`
|
|
|
+ err = global.DbMap[utils.DbNameIndex].Exec(sql, RunStatusWaiting, indexIdList).Error
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// UpdateIndexAndData 导入数据
|
|
|
+func (m *AiPredictModelIndex) UpdateIndexAndData(modelIndexItem *AiPredictModelIndex, dataList []*AiPredictModelData, updateCols []string) (err error) {
|
|
|
+ o := global.DbMap[utils.DbNameIndex]
|
|
|
+ tx := o.Begin()
|
|
|
+ defer func() {
|
|
|
+ if err != nil {
|
|
|
+ _ = tx.Rollback()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ _ = tx.Commit()
|
|
|
+ }()
|
|
|
+
|
|
|
+ // 更新指标
|
|
|
+ e := tx.Select(updateCols).Updates(modelIndexItem).Error
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("update index err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ var existDataList []*AiPredictModelData
|
|
|
+ // 查询标的的所有数据
|
|
|
+ sqlRun := `SELECT * FROM ai_predict_model_data WHERE ai_predict_model_index_id = ? ORDER BY ai_predict_model_data_id DESC`
|
|
|
+ err = tx.Raw(sqlRun, modelIndexItem.AiPredictModelIndexId).Find(&existDataList).Error
|
|
|
+ if err != nil {
|
|
|
+ err = fmt.Errorf("find index data err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ existDailyMap := make(map[string]*AiPredictModelData)
|
|
|
+ existMonthlyMap := make(map[string]*AiPredictModelData)
|
|
|
+ removeDailyDateMap := make(map[string]bool)
|
|
|
+ removeMonthlyDateMap := make(map[string]bool)
|
|
|
+
|
|
|
+ for _, d := range existDataList {
|
|
|
+ tmpDate := d.DataTime.Format(utils.FormatDate)
|
|
|
+ if d.Source == ModelDataSourceDaily {
|
|
|
+ existDailyMap[tmpDate] = d
|
|
|
+ removeDailyDateMap[tmpDate] = true
|
|
|
+ }
|
|
|
+ if d.Source == ModelDataSourceMonthly {
|
|
|
+ existMonthlyMap[tmpDate] = d
|
|
|
+ removeMonthlyDateMap[tmpDate] = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ addDataList := make([]*AiPredictModelData, 0)
|
|
|
+ for _, tmpData := range dataList {
|
|
|
+ tmpData.AiPredictModelIndexId = modelIndexItem.AiPredictModelIndexId
|
|
|
+ tmpData.IndexCode = modelIndexItem.IndexCode
|
|
|
+ tmpData.DataTimestamp = tmpData.DataTime.UnixNano() / 1e6
|
|
|
+
|
|
|
+ // 档期日期
|
|
|
+ tmpDate := tmpData.DataTime.Format(utils.FormatDate)
|
|
|
+
|
|
|
+ if tmpData.Source == ModelDataSourceDaily {
|
|
|
+ delete(removeDailyDateMap, tmpDate)
|
|
|
+ if existData, ok := existDailyMap[tmpDate]; ok {
|
|
|
+ // 修改
|
|
|
+ dataUpdateCols := make([]string, 0)
|
|
|
+ if existData.Value != tmpData.Value {
|
|
|
+ existData.Value = tmpData.Value
|
|
|
+ dataUpdateCols = append(dataUpdateCols, "Value")
|
|
|
+ }
|
|
|
+ if existData.PredictValue != tmpData.PredictValue {
|
|
|
+ existData.PredictValue = tmpData.PredictValue
|
|
|
+ dataUpdateCols = append(dataUpdateCols, "PredictValue")
|
|
|
+ }
|
|
|
+ if existData.Direction != tmpData.Direction {
|
|
|
+ existData.Direction = tmpData.Direction
|
|
|
+ dataUpdateCols = append(dataUpdateCols, "Direction")
|
|
|
+ }
|
|
|
+ if existData.DeviationRate != tmpData.DeviationRate {
|
|
|
+ existData.DeviationRate = tmpData.DeviationRate
|
|
|
+ dataUpdateCols = append(dataUpdateCols, "DeviationRate")
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(dataUpdateCols) > 0 {
|
|
|
+ existData.ModifyTime = time.Now()
|
|
|
+ dataUpdateCols = append(dataUpdateCols, "ModifyTime")
|
|
|
+ tmpErr := tx.Select(dataUpdateCols).Updates(existData).Error
|
|
|
+ if tmpErr != nil {
|
|
|
+ utils.FileLog.Error("update index data err: %v", tmpErr)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ addDataList = append(addDataList, tmpData)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if tmpData.Source == ModelDataSourceMonthly {
|
|
|
+ delete(removeMonthlyDateMap, tmpDate)
|
|
|
+ if existData, ok := existMonthlyMap[tmpDate]; ok {
|
|
|
+ // 修改
|
|
|
+ dataUpdateCols := make([]string, 0)
|
|
|
+ if existData.Value != tmpData.Value {
|
|
|
+ existData.Value = tmpData.Value
|
|
|
+ dataUpdateCols = append(dataUpdateCols, "Value")
|
|
|
+ }
|
|
|
+ if existData.PredictValue.Float64 != tmpData.PredictValue.Float64 {
|
|
|
+ existData.PredictValue = tmpData.PredictValue
|
|
|
+ dataUpdateCols = append(dataUpdateCols, "PredictValue")
|
|
|
+ }
|
|
|
+ if existData.Direction != tmpData.Direction {
|
|
|
+ existData.Direction = tmpData.Direction
|
|
|
+ dataUpdateCols = append(dataUpdateCols, "Direction")
|
|
|
+ }
|
|
|
+ if existData.DeviationRate != tmpData.DeviationRate {
|
|
|
+ existData.DeviationRate = tmpData.DeviationRate
|
|
|
+ dataUpdateCols = append(dataUpdateCols, "DeviationRate")
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(dataUpdateCols) > 0 {
|
|
|
+ existData.ModifyTime = time.Now()
|
|
|
+ dataUpdateCols = append(dataUpdateCols, "ModifyTime")
|
|
|
+ tmpErr := tx.Select(dataUpdateCols).Updates(existData).Error
|
|
|
+ if tmpErr != nil {
|
|
|
+ utils.FileLog.Error("update index data err: %v", tmpErr)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ addDataList = append(addDataList, tmpData)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清除不要了的日度指标
|
|
|
+ if len(removeDailyDateMap) > 0 {
|
|
|
+ removeDateList := make([]string, 0)
|
|
|
+ for date := range removeDailyDateMap {
|
|
|
+ removeDateList = append(removeDateList, date)
|
|
|
+ }
|
|
|
+ sql := `DELETE FROM ai_predict_model_data WHERE ai_predict_model_index_id = ? AND source = ? AND data_time IN (?)`
|
|
|
+ e = tx.Exec(sql, modelIndexItem.AiPredictModelIndexId, ModelDataSourceDaily, removeDateList).Error
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("clear index daily data err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清除不要了的月度指标
|
|
|
+ if len(removeMonthlyDateMap) > 0 {
|
|
|
+ removeDateList := make([]string, 0)
|
|
|
+ for date := range removeMonthlyDateMap {
|
|
|
+ removeDateList = append(removeDateList, date)
|
|
|
+ }
|
|
|
+ sql := `DELETE FROM ai_predict_model_data WHERE ai_predict_model_index_id = ? AND source = ? AND data_time IN (?)`
|
|
|
+ e = tx.Exec(sql, modelIndexItem.AiPredictModelIndexId, ModelDataSourceMonthly, removeDateList).Error
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("clear index monthly data err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ e = tx.CreateInBatches(addDataList, utils.MultiAddNum).Error
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("insert index data err: %v", e)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+}
|