Explorar el Código

Merge branch 'yb/11.8_position_analysis'

ziwen hace 2 años
padre
commit
6038402e15

+ 46 - 0
controller/trade_analysis/trade_analysis.go

@@ -0,0 +1,46 @@
+package trade_analysis
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/response"
+	model "hongze/hongze_yb/models/tables/trade_analysis"
+	"hongze/hongze_yb/services/trade_analysis"
+)
+
+// GetClassifyName 获取交易所合约列表
+func GetClassifyName(c *gin.Context) {
+	//userinfo := userService.GetInfoByClaims(c)
+	list, err, errMsg := trade_analysis.GetClassifyName()
+	if err !=nil {
+		response.FailMsg(errMsg, err.Error(), c)
+		return
+	}
+
+	response.OkData("获取成功", list, c)
+}
+
+// GetPositionTop 获取合约榜单详情
+func GetPositionTop(c *gin.Context) {
+	var req model.GetPositionTopReq
+	if err := c.Bind(&req); err != nil {
+		response.Fail("参数有误", c)
+		return
+	}
+	if req.ClassifyName == "" {
+		response.Fail("请输入分类名称", c)
+		return
+	}
+	if req.ClassifyType == "" {
+		response.Fail("请输入合约名称", c)
+		return
+	}
+
+	//userinfo := userService.GetInfoByClaims(c)
+	list, err, errMsg := trade_analysis.GetPositionTopDetail(req)
+	if err !=nil {
+		response.FailMsg(errMsg, err.Error(), c)
+		return
+	}
+
+	response.OkData("获取成功", list, c)
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 526 - 0
go.sum


+ 2 - 0
init_serve/router.go

@@ -79,5 +79,7 @@ func InitRouter() (r *gin.Engine) {
 	routers.InitBulletChat(r)
 	// 我的图表
 	routers.InitMyChart(r)
+	// 持仓分析
+	routers.InitTradeAnalysis(r)
 	return
 }

+ 177 - 0
models/tables/trade_analysis/trade_analysis.go

@@ -0,0 +1,177 @@
+package trade_analysis
+
+import (
+	"hongze/hongze_yb/global"
+	"time"
+)
+
+// 上期能源持仓榜单表
+type TradePositionTop struct {
+	Id            uint64    `gorm:"primaryKey;column:id" json:"id"`
+	ClassifyName  string    `gorm:"column:classify_name" json:"classify_name"`     //分类名称
+	ClassifyType  string    `gorm:"column:classify_type" json:"classify_type"`     //分类名称下的类型
+	DealShortName string    `gorm:"column:deal_short_name" json:"deal_short_name"` //成交量公司简称
+	DealValue     int       `gorm:"column:deal_value" json:"deal_value"`           //成交量
+	DealChange    int       `gorm:"column:deal_change" json:"deal_change"`         //成交变化量
+	DataTime      time.Time `gorm:"column:data_time" json:"data_time"`             //数据日期
+	CreateTime    time.Time `gorm:"column:create_time" json:"create_time"`         //插入时间
+	ModifyTime    time.Time `gorm:"column:modify_time" json:"modify_time"`         //修改时间
+	DealType      int       `gorm:"column:deal_type" json:"deal_type"`             //交易类型:1多单,2空单,3净多单,4净空单
+	SourceType    int       `gorm:"column:source_type" json:"source_type"`         //数据来源,0是原始数据的值,1是由T+1日推算出的值,2是由T日的榜单数据推算出的值
+	Rank          int       `gorm:"column:rank" json:"rank"`                       //排名
+}
+
+type TradeClassifyNameList struct {
+	Exchange string                      `description:"交易所" json:"exchange"`
+	Sort     int                         `description:"排序字段" json:"sort"`
+	Num      int                         `description:"品种数量" json:"num"`
+	DataTime string                      `description:"最新更新时间" json:"data_time"`
+	Items    []TradeClassifyNameListItem `description:"子类" json:"items"`
+}
+type TradeClassifyNameListSort []TradeClassifyNameList
+func (v TradeClassifyNameListSort) Len() int {
+	return len(v)
+}
+
+func (v TradeClassifyNameListSort) Swap(i, j int) {
+	v[i], v[j] = v[j], v[i]
+}
+
+func (v TradeClassifyNameListSort) Less(i, j int) bool {
+	return v[i].Sort < v[j].Sort
+}
+
+type TradeClassifyNameListItemSort []TradeClassifyNameListItem
+func (v TradeClassifyNameListItemSort) Len() int {
+	return len(v)
+}
+
+func (v TradeClassifyNameListItemSort) Swap(i, j int) {
+	v[i], v[j] = v[j], v[i]
+}
+
+func (v TradeClassifyNameListItemSort) Less(i, j int) bool {
+	return v[i].ClassifyName < v[j].ClassifyName
+}
+
+type TradeClassifyNameListItem struct {
+	ClassifyName string                          `description:"交易分类" json:"classify_name"`
+	Items        []TradeClassifyNameListItemItem `description:"合约代码" json:"items"`
+}
+
+type TradeClassifyNameListItemItemSort []TradeClassifyNameListItemItem
+func (v TradeClassifyNameListItemItemSort) Len() int {
+	return len(v)
+}
+
+func (v TradeClassifyNameListItemItemSort) Swap(i, j int) {
+	v[i], v[j] = v[j], v[i]
+}
+
+func (v TradeClassifyNameListItemItemSort) Less(i, j int) bool {
+	return v[i].ClassifyType < v[j].ClassifyType
+}
+
+type TradeClassifyNameListItemItem struct {
+	ClassifyType string `json:"classify_type"` //分类名称下的类型
+}
+
+type TradeClassifyName struct {
+	ClassifyName  string    //分类名称
+	ClassifyType  string    //分类名称下的类型
+}
+
+func GetExchangeClassify(exchange string) (list []TradeClassifyName, err error) {
+	tableName := "base_from_trade_" + exchange + "_index"
+	orderStr := "classify_name DESC, classify_type asc"
+	if exchange == "zhengzhou"{
+		orderStr = "classify_name asc"
+	}
+	err = global.MYSQL["data"].
+		Table(tableName).
+		Select("classify_name, classify_type").
+		Group("classify_name, classify_type").
+		Where("rank <=20 and rank > 0 ").
+		Order(orderStr).Scan(&list).Error
+	return
+}
+
+type LastTimeItem struct {
+	CreateTime time.Time
+}
+func GetExchangeLastTime(exchange string) (item LastTimeItem, err error) {
+	tableName := "base_from_trade_" + exchange + "_index"
+	err = global.MYSQL["data"].
+		Table(tableName).
+		Select("create_time").
+		Order("create_time desc").First(&item).Error
+	return
+}
+
+type GetPositionTopReq struct {
+	Exchange     string `json:"exchange" form:"exchange"`      //交易所
+	ClassifyName string `json:"classify_name" form:"classify_name"` //分类名称
+	ClassifyType string `json:"classify_type" form:"classify_type"`  //具体合约名称
+	DataTime     string `json:"data_time" form:"data_time"`     //请求日期,如果为空,则返回最新的榜单日期
+}
+
+type GetPositionTopResp struct {
+	BuyList       GetPositionTopList `json:"buy_list"`        //多单列表
+	SoldList      GetPositionTopList `json:"sold_list"`       //空单列表
+	CleanBuyList  GetPositionTopList `json:"clean_buy_list"`  //净多单列表
+	CleanSoldList GetPositionTopList `json:"clean_sold_list"` //净空单列表
+	DataTime      string             `json:"data_time"`       //最新日期或者请求日期
+}
+
+type GetPositionTopList struct {
+	TotalDealValue  int                      `json:"total_deal_value"` //总计成交量
+	TotalDealChange int                      `json:"total_deal_change"` //校昨日变化
+	List            []GetPositionTopListItem `json:"list"`  //榜单详情列表
+}
+
+type GetPositionTopListItem struct {
+	DealShortName   string `json:"deal_short_name"`   //成交量公司简称
+	DealValue       int    `json:"deal_value"`        //成交量
+	DealChange      int    `json:"deal_change"`       //成交变化量
+	Rank            int    `json:"rank"`              //当前名次
+	Rate            string `json:"rate"`              //当前占比
+	BeforeAllRate   string `json:"before_all_rate"`   //排在前面的成交量总计占比(包含)
+	BeforeAllValue  int    `json:"before_all_value"`  //排在前面的成交量总计
+	BeforeAllChange int    `json:"before_all_change"` //排在前面的成交量增减总计
+}
+
+func GetTradePositionTop(exchange string, classifyName, classifyType, dataTime string)(list []TradePositionTop, err error) {
+	tableName := "trade_position_" + exchange + "_top"
+	err = global.MYSQL["data"].
+		Table(tableName).
+		Where("classify_name=? and classify_type=? and data_time=? and rank <=20 and rank > 0", classifyName, classifyType, dataTime).
+		Order("deal_value desc").Scan(&list).Error
+	return
+}
+
+func GetTradeTopLastDataTime(exchange string, classifyName, classifyType string)(item *TradePositionTop, err error) {
+	tableName := "trade_position_" + exchange + "_top"
+	if exchange == "zhengzhou" {
+		err = global.MYSQL["data"].
+			Table(tableName).
+			Where("classify_name=? ", classifyType).
+			Order("data_time desc").First(&item).Error
+	}else {
+		err = global.MYSQL["data"].
+			Table(tableName).
+			Where("classify_name=? and classify_type=?", classifyName, classifyType).
+			Order("data_time desc").First(&item).Error
+	}
+
+	return
+}
+
+
+func GetZhengzhouClassifyTypeByClassifyName(classifyName string) (item *TradeClassifyName, err error) {
+	tableName := "base_from_trade_zhengzhou_index"
+	err = global.MYSQL["data"].
+		Table(tableName).
+		Select("classify_name, classify_type").
+		Where("classify_name=?", classifyName).Limit(1).Find(&item).Error
+	return
+}

+ 15 - 0
routers/trade_analysis.go

@@ -0,0 +1,15 @@
+package routers
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/trade_analysis"
+	"hongze/hongze_yb/middleware"
+)
+
+func InitTradeAnalysis(r *gin.Engine) {
+	rGroup := r.Group("api/trade/analysis").Use(middleware.Token())
+	{
+		rGroup.GET("/classify", trade_analysis.GetClassifyName)
+		rGroup.GET("/top", trade_analysis.GetPositionTop)
+	}
+}

+ 363 - 0
services/trade_analysis/trade_analysis.go

@@ -0,0 +1,363 @@
+package trade_analysis
+
+import (
+	"fmt"
+	"hongze/hongze_yb/models/tables/trade_analysis"
+	"hongze/hongze_yb/utils"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+)
+
+func GetClassifyName() (list trade_analysis.TradeClassifyNameListSort, err error, errMsg string) {
+	//定义交易所
+	exchanges := map[string]string{
+		"zhengzhou": "郑商所",
+		"dalian":    "大商所",
+		"shanghai":  "上期所",
+		"cffex":     "中金所",
+		"ine":       "上期能源",
+	}
+	exchangesSortMap := map[string]int{
+		"zhengzhou": 1,
+		"dalian":    2,
+		"shanghai":  3,
+		"cffex":     4,
+		"ine":       5,
+	}
+	//查询每个交易所的最新更新时间
+	//查询每个交易所下的classifyNameList
+	classifyExchangeMap := make(map[string][]trade_analysis.TradeClassifyName)
+	timeMap := make(map[string]string)
+	i := 0
+	var wg sync.WaitGroup
+	for k, _ := range exchanges {
+		wg.Add(1)
+		go func(k string,classifyExchangeMap map[string][]trade_analysis.TradeClassifyName) {
+			defer wg.Done()
+			nameList, tmpErr := trade_analysis.GetExchangeClassify(k)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			for _, n := range nameList {
+				classifyExchangeMap[k] = append(classifyExchangeMap[k], n)
+			}
+
+			dataTimeItem, tmpErr := trade_analysis.GetExchangeLastTime(k)
+			if tmpErr != nil {
+				err = tmpErr
+				errMsg = "查询交易所最新更新时间失败"
+				return
+			}
+			timeMap[k] = dataTimeItem.CreateTime.Format(utils.FormatDateTime)
+
+		}(k, classifyExchangeMap)
+	}
+	wg.Wait()
+	for k, v := range exchanges {
+		tmp := trade_analysis.TradeClassifyNameList{
+			Exchange: v,
+			Items:    nil,
+			Sort: exchangesSortMap[k],
+		}
+		nameList, ok := classifyExchangeMap[k]
+		if !ok {
+			err = fmt.Errorf( "查询交易所分类信息失败")
+			errMsg = "查询交易所分类信息失败"
+			return
+		}
+		tmp.DataTime, ok = timeMap[k]
+		if !ok {
+			err = fmt.Errorf( "查询交易所最新更新时间失败")
+			errMsg = "查询交易所最新更新时间失败"
+			return
+		}
+		classifyMap := make(map[string][]trade_analysis.TradeClassifyNameListItemItem)
+		if len(nameList) > 0 {
+			if k == "zhengzhou" {
+				for _, item := range nameList {
+					classifyName := getZhengzhouClassifyName(item.ClassifyName)
+					tmpItemItem := trade_analysis.TradeClassifyNameListItemItem{
+						ClassifyType: item.ClassifyName,
+					}
+					classifyMap[classifyName] = append(classifyMap[classifyName], tmpItemItem)
+				}
+			}else{
+				for _, item := range nameList {
+					tmpItemItem := trade_analysis.TradeClassifyNameListItemItem{
+						ClassifyType: item.ClassifyType,
+					}
+					classifyMap[item.ClassifyName] = append(classifyMap[item.ClassifyName], tmpItemItem)
+				}
+			}
+			for n, l := range classifyMap {
+				sort.Sort(trade_analysis.TradeClassifyNameListItemItemSort(l))
+				tmpItems := trade_analysis.TradeClassifyNameListItem{
+					ClassifyName: n,
+					Items:        l,
+				}
+				tmp.Items = append(tmp.Items, tmpItems)
+				tmp.Num ++
+			}
+		}
+		sort.Sort(trade_analysis.TradeClassifyNameListItemSort(tmp.Items))
+		list = append(list, tmp)
+		i ++
+	}
+	if len(list) > 0 {
+		sort.Sort(list)
+	}
+	return
+}
+
+func getZhengzhouClassifyName(code string) (name string) {
+	if strings.HasPrefix(code,"PTA") {
+		name = "PTA"
+		return
+	}
+	if strings.HasPrefix(code,"TA") {
+		name = "PTA"
+		return
+	}
+	if strings.HasPrefix(code,"ZC") {
+		name="动力煤"
+		return
+	}
+	if strings.HasPrefix(code,"WH") {
+		name="强麦"
+		return
+	}
+	if strings.HasPrefix(code,"UR") {
+		name="尿素"
+		return
+	}
+	if strings.HasPrefix(code,"SR") {
+		name="白糖"
+		return
+	}
+	if strings.HasPrefix(code,"SM") {
+		name="锰硅"
+		return
+	}
+	if strings.HasPrefix(code,"SF") {
+		name="硅铁"
+		return
+	}
+	if strings.HasPrefix(code,"SA") {
+		name="纯碱"
+		return
+	}
+	if strings.HasPrefix(code,"RS") {
+		name="油菜籽"
+		return
+	}
+	if strings.HasPrefix(code,"RM") {
+		name="菜籽粕"
+		return
+	}
+	if strings.HasPrefix(code,"RI") {
+		name="早籼稻"
+		return
+	}
+	if strings.HasPrefix(code,"PM") {
+		name="普麦"
+		return
+	}
+	if strings.HasPrefix(code,"PK") {
+		name="花生"
+		return
+	}
+	if strings.HasPrefix(code,"PF") {
+		name="涤纶短纤"
+		return
+	}
+	if strings.HasPrefix(code,"OI") {
+		name="菜油"
+		return
+	}
+	if strings.HasPrefix(code,"MA") {
+		name="甲醇"
+		return
+	}
+	if strings.HasPrefix(code,"LR") {
+		name="晚籼稻"
+		return
+	}
+	if strings.HasPrefix(code,"JR") {
+		name="粳稻"
+		return
+	}
+	if strings.HasPrefix(code,"FG") {
+		name="玻璃"
+		return
+	}
+	if strings.HasPrefix(code,"CY") {
+		name="棉纱"
+		return
+	}
+	if strings.HasPrefix(code,"CJ") {
+		name="红枣"
+		return
+	}
+	if strings.HasPrefix(code,"CF") {
+		name="棉花"
+		return
+	}
+	if strings.HasPrefix(code,"AP") {
+		name="苹果"
+		return
+	}
+	return
+}
+
+func GetPositionTopDetail(req trade_analysis.GetPositionTopReq) (ret trade_analysis.GetPositionTopResp, err error, errMsg string) {
+	//定义交易所
+	exchanges := map[string]string{
+		"郑商所":"zhengzhou",
+		"大商所":"dalian",
+		"上期所":"shanghai",
+		"中金所":"cffex",
+		"上期能源":"ine",
+	}
+	exchange, ok := exchanges[req.Exchange]
+	if !ok {
+		errMsg = "请输入正确的交易所名称"
+		err = fmt.Errorf(errMsg)
+		return
+	}
+	dataTimeStr := req.DataTime
+	var dataTime time.Time
+	//查询最新的时间
+	if dataTimeStr == "" {
+		lastItem , tmpErr := trade_analysis.GetTradeTopLastDataTime(exchange, req.ClassifyName, req.ClassifyType)
+		if tmpErr != nil {
+			errMsg = "查询最新的榜单信息失败"
+			err = tmpErr
+			return
+		}
+		dataTime = lastItem.DataTime
+	}else{
+		dataTime, err = time.ParseInLocation(utils.FormatDate, dataTimeStr, time.Local)
+		if err != nil {
+			errMsg = "请输入正确的时间格式"
+			return
+		}
+	}
+
+	//遇到周末则跳过当天
+	weekStr := dataTime.Weekday().String()
+	if weekStr == "Sunday" || weekStr == "Saturday" {
+		/*errMsg = "日期不正确"
+		err = fmt.Errorf(errMsg)*/
+		return
+	}
+	dataTimeStr = dataTime.Format(utils.FormatDate)
+	classifyName := req.ClassifyName
+	classifyType := req.ClassifyType
+	if exchange == "zhengzhou" {
+		classifyName = classifyType
+		var typeItem *trade_analysis.TradeClassifyName
+		typeItem, err = trade_analysis.GetZhengzhouClassifyTypeByClassifyName(classifyName)
+		if err != nil {
+			if err == utils.ErrNoRow {
+				errMsg = "该合约不存在"
+				return
+			}
+			errMsg = "查询类型信息出错"
+			return
+		}
+		classifyType = typeItem.ClassifyType
+
+	}
+	//查询当日榜单列表
+	dataList, tmpErr := trade_analysis.GetTradePositionTop(exchange, classifyName, classifyType, dataTimeStr)
+	if tmpErr != nil {
+		errMsg = "查询榜单列表失败"
+		err = tmpErr
+		return
+	}
+	if len(dataList) <= 0 {
+		return
+	}
+	totalMap := make(map[int]int)
+	totalChangeMap := make(map[int]int)
+	totalTmpMap := make(map[int]int)
+	totalChangeTmpMap := make(map[int]int)
+
+	detailList := make(map[int][]trade_analysis.GetPositionTopListItem)
+	//统计汇总数据
+	for _, v := range dataList {
+		if t, ok1 := totalMap[v.DealType]; ok1 {
+			totalMap[v.DealType] = t+v.DealValue
+		}else{
+			totalMap[v.DealType] = v.DealValue
+		}
+		if t, ok1 := totalChangeMap[v.DealType]; ok1 {
+			totalChangeMap[v.DealType] = t+v.DealChange
+		}else{
+			totalChangeMap[v.DealType] = v.DealChange
+		}
+	}
+	_, okTmp1 := totalMap[1]
+	_, okTmp2 := totalMap[2]
+	_, okTmp3 := totalMap[3]
+	_, okTmp4 := totalMap[4]
+
+	if !okTmp1 || !okTmp2 || (!okTmp3 && !okTmp4) {
+		errMsg = "榜单数据缺失"
+		err = fmt.Errorf(errMsg)
+		return
+	}
+
+	for k, v := range dataList {
+		k++
+		if t, ok1 := totalTmpMap[v.DealType]; ok1 {
+			totalTmpMap[v.DealType] = t+v.DealValue
+		}else{
+			totalTmpMap[v.DealType] = v.DealValue
+		}
+		if t, ok1 := totalChangeTmpMap[v.DealType]; ok1 {
+			totalChangeTmpMap[v.DealType] = t+v.DealChange
+		}else{
+			totalChangeTmpMap[v.DealType] = v.DealChange
+		}
+
+		tmp := trade_analysis.GetPositionTopListItem{
+			DealShortName:   v.DealShortName,
+			DealValue:       v.DealValue,
+			DealChange:      v.DealChange,
+			Rank:            v.Rank,
+			BeforeAllValue:  totalTmpMap[v.DealType],
+			BeforeAllChange: totalChangeTmpMap[v.DealType],
+		}
+		//统计占比
+		rate := fmt.Sprintf("%.2f", float64(tmp.DealValue)/float64(totalMap[v.DealType])) // 保留2位小数
+		beforeAllRate := fmt.Sprintf("%.2f", float64(tmp.BeforeAllValue)/float64(totalMap[v.DealType])) // 保留2位小数
+		tmp.Rate = rate
+		tmp.BeforeAllRate = beforeAllRate
+		if tmp.DealShortName == "-"{
+			continue
+		}
+		detailList[v.DealType] = append(detailList[v.DealType], tmp)
+	}
+	ret.BuyList.TotalDealValue = totalMap[1]
+	ret.BuyList.TotalDealChange = totalChangeMap[1]
+	ret.BuyList.List = detailList[1]
+
+	ret.SoldList.TotalDealValue = totalMap[2]
+	ret.SoldList.TotalDealChange = totalChangeMap[2]
+	ret.SoldList.List = detailList[2]
+
+	ret.CleanBuyList.TotalDealValue = totalMap[3]
+	ret.CleanBuyList.TotalDealChange = totalChangeMap[3]
+	ret.CleanBuyList.List = detailList[3]
+
+	ret.CleanSoldList.TotalDealValue = totalMap[4]
+	ret.CleanSoldList.TotalDealChange = totalChangeMap[4]
+	ret.CleanSoldList.List = detailList[4]
+
+	ret.DataTime = dataTimeStr
+	return
+}

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio