Prechádzať zdrojové kódy

增加“获取企业风管期货持仓头寸信息”接口

zhou.xiaoning 4 rokov pred
rodič
commit
ab8b6468db

+ 2 - 2
config/cfg.j2

@@ -8,9 +8,9 @@
         "openApiUrl":"{{openonline_url}}",
         "mobileOpenUrl": "{{mobileopen_url}}",
         "mobileAuthUrl": "{{mobileauth_url}}",
-        "quoteHost": "{{quote_agent_listen_addr}}",
+        "quoteHost": "{{quote_agent_internet_addr}}",
         "quotePort": "{{quote_agent_listen_port}}",
-        "tradeHost": "{{access_listen_addr}}",
+        "tradeHost": "{{access_internet_addr}}",
         "tradePort": "{{access_listen_port}}",
         "newsUrl": "{{news_url}}"
         }

+ 6 - 6
config/config.xml

@@ -13,11 +13,11 @@
     <DbAddress value="192.168.31.117"/>
     <DbName value="orcl"/>
     <DbPort value="1521"/>
-    <DbUser value="mtp2_test125"/>
+    <DbUser value="mtp2_test114"/>
     <DbPwd value="muchinfo"/>
   </DbSetting>
   <RedisSetting>
-    <Address value="192.168.30.125"/>
+    <Address value="192.168.31.114"/>
     <Port value="5007"/>
     <Timeout value="3"/>
     <ConnNum value="1"/>
@@ -25,11 +25,11 @@
     <Pwd value=""/>
   </RedisSetting>
   <MqSetting>
-    <Url value="amqp://guest:guest@192.168.30.125:5020/test"/>
+    <Url value="amqp://guest:guest@192.168.31.114:5020/test"/>
     <Exchange value="entry"/>
   </MqSetting>
   <MongoDBSetting>
-    <HostName value="192.168.30.125"/>
+    <HostName value="192.168.31.114"/>
     <Port value="5025"/>
     <DBName value="HistoryQuote"/>
     <Username value="quote_test01"/>
@@ -38,8 +38,8 @@
   <MySQLSetting>
     <Host value="192.168.30.140"/>
     <Port value="3306"/>
-    <DBName value="historyquote_test125"/>
-    <Username value="quote_test125"/>
+    <DBName value="historyquote_test114"/>
+    <Username value="quote_test114"/>
     <Password value="123456"/>
   </MySQLSetting>
 </Configuration>

+ 363 - 2
controllers/ermcp/qryOrder.go

@@ -1,15 +1,376 @@
 package ermcp
 
-import "github.com/gin-gonic/gin"
+import (
+	"mtp2_if/global/app"
+	"mtp2_if/global/e"
+	"mtp2_if/logger"
+	"mtp2_if/models"
+	"mtp2_if/utils"
+	"net/http"
 
+	"github.com/gin-gonic/gin"
+)
+
+// QueryErmcpTradePositionReq 获取企业风管期货持仓头寸信息请求参数
 type QueryErmcpTradePositionReq struct {
 	AccountID int `form:"accountID" binding:"required"`
+	MarketID  int `form:"marketID"`
 }
 
+// QueryErmcpTradePositionRsp 获取企业风管期货持仓头寸信息返回模型
 type QueryErmcpTradePositionRsp struct {
-	Goodsname string `json:"goodsname"` // 商品名称
+	Goodsname            string  `json:"goodsname"`            // 商品名称
+	BuyOrSell            int64   `json:"buyorsell"`            // 方向 - 0:买 1:卖
+	EnableQTY            int64   `json:"enableqty"`            // 可用量(总仓可用)
+	CurPositionQTY       int64   `json:"curpositionqty"`       // 当前持仓总数量(总仓数量)
+	Last                 float64 `json:"last"`                 // 现价
+	CurHolderAmount      float64 `json:"curholderamount" `     // 当前持仓总金额[商品币种](成本???)
+	PositionPL           float64 `json:"positionpl"`           // 持仓盈亏
+	PositionPLRate       float64 `json:"positionplrate"`       // 持仓盈亏率
+	CurTDPosition        int64   `json:"curtdposition"`        // 期末今日头寸(今仓数量)
+	CurTDPositionEnabled int64   `json:"curtdpositionenabled"` // 今仓可用
+	AveragePrice         float64 `json:"averageprice"`         // 持仓均价
+	UsedMargin           float64 `json:"usedmargin"`           // 占用保证金[商品币种]
+	ExExehangeName       string  `json:"exexchangename"`       // 外部交易所名称(简称)
+
+	Goodsid      int64   `json:"goodsid"`      // 商品ID(自增ID SEQ_GOODS)
+	Goodscode    string  `json:"goodscode"`    // 商品代码(内部)
+	Outgoodscode string  `json:"outgoodscode"` // 商品代码(外部)
+	Agreeunit    float64 `json:"agreeunit"`    // 合约单位
+	Decimalplace int64   `json:"decimalplace"` // 报价小数位
 }
 
+// QueryErmcpTradePosition 获取企业风管期货持仓头寸信息
+// @Summary 获取企业风管期货持仓头寸信息
+// @Produce json
+// @Security ApiKeyAuth
+// @Param accountID query int true "资金账户ID"
+// @Param marketID query int false "所属市场ID"
+// @Success 200 {object} QueryErmcpTradePositionRsp
+// @Failure 500 {object} app.Response
+// @Router /Ermcp/QueryErmcpTradePosition [get]
+// @Tags 企业风险管理(app)
 func QueryErmcpTradePosition(c *gin.Context) {
+	appG := app.Gin{C: c}
+
+	// 获取请求参数
+	var req QueryErmcpTradePositionReq
+	if err := appG.C.ShouldBindQuery(&req); err != nil {
+		logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
+		return
+	}
+
+	rsp := make([]QueryErmcpTradePositionRsp, 0)
+
+	// 获取资金账户信息
+	taAccount, err := models.GetTaAccountByID(req.AccountID)
+	if err != nil {
+		logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
+		return
+	}
+	if taAccount == nil {
+		logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
+		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
+		return
+	}
+
+	// 母账户要从HEDGE_OUTTRADEPOSITION表查询持仓头寸(未生成内部头寸);子账户从TRADEPOSITION表获持仓头寸
+	if taAccount.Ismain == 1 {
+		// 母账户
+		hedgeOutTradePositions, err := models.GetHedgeOutTradePositions(req.AccountID, req.MarketID)
+		if err != nil {
+			// 查询失败
+			logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
+			return
+		}
+		// 分解买卖方向的头寸
+		for _, v := range hedgeOutTradePositions {
+			// 分解买卖方向的头寸
+			if v.Curbuyposition > 0 {
+				// 买方向
+				item := QueryErmcpTradePositionRsp{
+					BuyOrSell:            0,
+					EnableQTY:            v.Curbuyposition - v.Fretdbuyposition - v.Freydbuyposition, // 买可用 = 期末买头寸 - 冻结今日买头寸 - 冻结上日买头寸
+					CurPositionQTY:       v.Curbuyposition,
+					CurHolderAmount:      0, // FIXME: - 缺少数据?
+					CurTDPosition:        v.Curtdbuyposition,
+					CurTDPositionEnabled: v.Curtdbuyposition - v.Fretdbuyposition, // 今仓买可用 = 期末今日买头寸 - 冻结今日买头寸
+					UsedMargin:           0,                                       // FIXME: - 缺少数据?
+
+					Goodsid: v.Hedgegoodsid,
+				}
+				// 获取对应商品信息
+				goods, err := models.GetGoods(int(v.Hedgegoodsid))
+				if err != nil {
+					// 查询失败
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
+					return
+				}
+				if goods == nil {
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
+					return
+				}
+				item.Goodscode = goods.Goodscode
+				item.Outgoodscode = goods.Outgoodscode
+				item.Goodsname = goods.Goodsname
+				item.Agreeunit = goods.Agreeunit
+				// 获取对应外部交易所名称
+				exchange, err := models.GetExternalexchangeByGoodsGroupID(int(goods.Goodsgroupid))
+				if err != nil {
+					// 查询失败
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil)
+					return
+				}
+				if exchange == nil {
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil)
+					return
+				}
+				item.ExExehangeName = exchange.Exchangefullname
+				// 获取对应商品盘面信息
+				quoteDays, err := models.GetQuoteDays("'" + goods.Outgoodscode + "'")
+				if err != nil {
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
+					return
+				}
+				if len(quoteDays) > 0 {
+					if quoteDays[0].Last != 0 {
+						item.Last = utils.IntToFloat64(int(quoteDays[0].Last), int(goods.Decimalplace))
+					}
+					// 没有现价则尝试用昨结
+					if item.Last == 0 && quoteDays[0].Presettle != 0 {
+						item.Last = utils.IntToFloat64(int(quoteDays[0].Presettle), int(goods.Decimalplace))
+					}
+				}
+				// FIXME: - 目前外部持仓头寸表里没有相关金额的字段,等相关服务处理
+
+				rsp = append(rsp, item)
+			}
+			if v.Cursellposition > 0 {
+				// 卖方向
+				item := QueryErmcpTradePositionRsp{
+					BuyOrSell:            1,
+					EnableQTY:            v.Cursellposition - v.Fretdsellposition - v.Freydsellposition,
+					CurPositionQTY:       v.Cursellposition,
+					CurHolderAmount:      0, // FIXME: - 缺少数据?
+					CurTDPosition:        v.Curtdsellposition,
+					CurTDPositionEnabled: v.Curtdsellposition - v.Fretdsellposition,
+					UsedMargin:           0, // FIXME: - 缺少数据?
+
+					Goodsid: v.Hedgegoodsid,
+				}
+				// 获取对应商品信息
+				goods, err := models.GetGoods(int(v.Hedgegoodsid))
+				if err != nil {
+					// 查询失败
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
+					return
+				}
+				if goods == nil {
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
+					return
+				}
+				item.Goodscode = goods.Goodscode
+				item.Outgoodscode = goods.Outgoodscode
+				item.Goodsname = goods.Goodsname
+				item.Agreeunit = goods.Agreeunit
+				// 获取对应外部交易所名称
+				exchange, err := models.GetExternalexchangeByGoodsGroupID(int(goods.Goodsgroupid))
+				if err != nil {
+					// 查询失败
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil)
+					return
+				}
+				if exchange == nil {
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil)
+					return
+				}
+				item.ExExehangeName = exchange.Exchangefullname
+				// 获取对应商品盘面信息
+				quoteDays, err := models.GetQuoteDays("'" + goods.Outgoodscode + "'")
+				if err != nil {
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
+					return
+				}
+				if len(quoteDays) > 0 {
+					if quoteDays[0].Last != 0 {
+						item.Last = utils.IntToFloat64(int(quoteDays[0].Last), int(goods.Decimalplace))
+					}
+					// 没有现价则尝试用昨结
+					if item.Last == 0 && quoteDays[0].Presettle != 0 {
+						item.Last = utils.IntToFloat64(int(quoteDays[0].Presettle), int(goods.Decimalplace))
+					}
+				}
+				// FIXME: - 目前外部持仓头寸表里没有相关金额的字段,等相关服务处理
+
+				rsp = append(rsp, item)
+			}
+		}
+	} else {
+		// 子账户
+		tradePositions, err := models.GetTradePositions(req.AccountID, req.MarketID)
+		if err != nil {
+			// 查询失败
+			logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+			appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
+			return
+		}
+		// 分解买卖方向的头寸
+		for _, v := range tradePositions {
+			if v.Buycurpositionqty > 0 {
+				// 买方向
+				item := QueryErmcpTradePositionRsp{
+					BuyOrSell:            0,
+					EnableQTY:            v.Buycurpositionqty - v.Buyfrozenqty, // 买可用 = 买当前持仓总数量 - 买持仓冻结数量
+					CurPositionQTY:       v.Buycurpositionqty,
+					CurHolderAmount:      v.Buycurholderamount,
+					CurTDPosition:        v.Buycurtdposition,
+					CurTDPositionEnabled: v.Buycurtdposition - v.Buyfretdposition, // 今仓买可用 = 买期末今日头寸 - 买冻结今日头寸
+					UsedMargin:           v.Usedmargin,
+
+					Goodsid: int64(v.Goodsid),
+				}
+				// 获取对应商品信息
+				goods, err := models.GetGoods(int(v.Goodsid))
+				if err != nil {
+					// 查询失败
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
+					return
+				}
+				if goods == nil {
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
+					return
+				}
+				item.Goodscode = goods.Goodscode
+				item.Outgoodscode = goods.Outgoodscode
+				item.Goodsname = goods.Goodsname
+				item.Agreeunit = goods.Agreeunit
+				// 获取对应外部交易所名称
+				exchange, err := models.GetExternalexchangeByGoodsGroupID(int(goods.Goodsgroupid))
+				if err != nil {
+					// 查询失败
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil)
+					return
+				}
+				if exchange == nil {
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil)
+					return
+				}
+				item.ExExehangeName = exchange.Exchangefullname
+				// 获取对应商品盘面信息
+				quoteDays, err := models.GetQuoteDays("'" + goods.Outgoodscode + "'")
+				if err != nil {
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
+					return
+				}
+				if len(quoteDays) > 0 {
+					if quoteDays[0].Last != 0 {
+						item.Last = utils.IntToFloat64(int(quoteDays[0].Last), int(goods.Decimalplace))
+					}
+					// 没有现价则尝试用昨结
+					if item.Last == 0 && quoteDays[0].Presettle != 0 {
+						item.Last = utils.IntToFloat64(int(quoteDays[0].Presettle), int(goods.Decimalplace))
+					}
+				}
+				// 计算持仓均价 = 买当前持仓总金额 / 买当前持仓总数量 / 合约单位
+				item.AveragePrice = v.Buycurholderamount / float64(v.Buycurpositionqty) / goods.Agreeunit
+				// 计算持仓盈亏:买方向持仓盈亏 = (最新价 - 持仓价) * 数量 * 合约单位
+				// 知识点:交易服务在结算后,会按结算价更新持仓单金额,所以持仓均价就是持仓价(结算价)
+				// 知识点:持仓盈亏是今日浮动盈亏,针对结算价进行计算;平仓盈亏是针对建仓价进行计算
+				// if item.Last == 0 {
+				// 	item.PositionPL = 0
+				// } else {
+				// 	item.PositionPL = (item.Last - item.AveragePrice) * float64(v.Buycurpositionqty) * goods.Agreeunit
+				// }
+				// FIXME: - 与老邓及王旭讨论过后,确认后期头寸相关价格会由交易服务落地,目前暂不进行计算
+			}
+			if v.Sellcurpositionqty > 0 {
+				// 卖方向
+				item := QueryErmcpTradePositionRsp{
+					BuyOrSell:            0,
+					EnableQTY:            v.Sellcurpositionqty - v.Sellfrozenqty,
+					CurPositionQTY:       v.Sellcurpositionqty,
+					CurHolderAmount:      v.Sellcurholderamount,
+					CurTDPosition:        v.Sellcurtdposition,
+					CurTDPositionEnabled: v.Sellcurtdposition - v.Sellfretdposition,
+					UsedMargin:           v.Usedmargin,
+
+					Goodsid: int64(v.Goodsid),
+				}
+				// 获取对应商品信息
+				goods, err := models.GetGoods(int(v.Goodsid))
+				if err != nil {
+					// 查询失败
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
+					return
+				}
+				if goods == nil {
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
+					return
+				}
+				item.Goodscode = goods.Goodscode
+				item.Outgoodscode = goods.Outgoodscode
+				item.Goodsname = goods.Goodsname
+				item.Agreeunit = goods.Agreeunit
+				// 获取对应外部交易所名称
+				exchange, err := models.GetExternalexchangeByGoodsGroupID(int(goods.Goodsgroupid))
+				if err != nil {
+					// 查询失败
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil)
+					return
+				}
+				if exchange == nil {
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed")
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil)
+					return
+				}
+				item.ExExehangeName = exchange.Exchangefullname
+				// 获取对应商品盘面信息
+				quoteDays, err := models.GetQuoteDays("'" + goods.Outgoodscode + "'")
+				if err != nil {
+					logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error())
+					appG.Response(http.StatusBadRequest, e.ERROR_GET_GOODS_FAILED, nil)
+					return
+				}
+				if len(quoteDays) > 0 {
+					if quoteDays[0].Last != 0 {
+						item.Last = utils.IntToFloat64(int(quoteDays[0].Last), int(goods.Decimalplace))
+					}
+					// 没有现价则尝试用昨结
+					if item.Last == 0 && quoteDays[0].Presettle != 0 {
+						item.Last = utils.IntToFloat64(int(quoteDays[0].Presettle), int(goods.Decimalplace))
+					}
+				}
+				// 计算持仓均价 = 买当前持仓总金额 / 买当前持仓总数量 / 合约单位
+				item.AveragePrice = v.Buycurholderamount / float64(v.Buycurpositionqty) / goods.Agreeunit
+				// 计算持仓盈亏:卖方向持仓盈亏 = (持仓价 - 最新价) * 数量 * 合约单位
+				// 知识点:交易服务在结算后,会按结算价更新持仓单金额,所以持仓均价就是持仓价(结算价)
+				// 知识点:持仓盈亏是今日浮动盈亏,针对结算价进行计算;平仓盈亏是针对建仓价进行计算
+			}
+		}
+	}
 
+	// 查询成功返回
+	logger.GetLogger().Debugln("QueryErmcpTradePosition successed: %v", rsp)
+	appG.Response(http.StatusOK, e.SUCCESS, rsp)
 }

+ 122 - 0
docs/docs.go

@@ -1657,6 +1657,51 @@ var doc = `{
                 }
             }
         },
+        "/Ermcp/QueryErmcpTradePosition": {
+            "get": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "企业风险管理(app)"
+                ],
+                "summary": "获取企业风管期货持仓头寸信息",
+                "parameters": [
+                    {
+                        "type": "integer",
+                        "description": "资金账户ID",
+                        "name": "accountID",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "所属市场ID",
+                        "name": "marketID",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/ermcp.QueryErmcpTradePositionRsp"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
         "/Ermcp/QueryExposureDetail": {
             "get": {
                 "security": [
@@ -9287,6 +9332,83 @@ var doc = `{
                 }
             }
         },
+        "ermcp.QueryErmcpTradePositionRsp": {
+            "type": "object",
+            "properties": {
+                "agreeunit": {
+                    "description": "合约单位",
+                    "type": "number"
+                },
+                "averageprice": {
+                    "description": "持仓均价",
+                    "type": "number"
+                },
+                "buyorsell": {
+                    "description": "方向 - 0:买 1:卖",
+                    "type": "integer"
+                },
+                "curholderamount": {
+                    "description": "当前持仓总金额[商品币种](成本???)",
+                    "type": "number"
+                },
+                "curpositionqty": {
+                    "description": "当前持仓总数量(总仓数量)",
+                    "type": "integer"
+                },
+                "curtdposition": {
+                    "description": "期末今日头寸(今仓数量)",
+                    "type": "integer"
+                },
+                "curtdpositionenabled": {
+                    "description": "今仓可用",
+                    "type": "integer"
+                },
+                "decimalplace": {
+                    "description": "报价小数位",
+                    "type": "integer"
+                },
+                "enableqty": {
+                    "description": "可用量(总仓可用)",
+                    "type": "integer"
+                },
+                "exexchangename": {
+                    "description": "外部交易所名称(简称)",
+                    "type": "string"
+                },
+                "goodscode": {
+                    "description": "商品代码(内部)",
+                    "type": "string"
+                },
+                "goodsid": {
+                    "description": "商品ID(自增ID SEQ_GOODS)",
+                    "type": "integer"
+                },
+                "goodsname": {
+                    "description": "商品名称",
+                    "type": "string"
+                },
+                "last": {
+                    "description": "现价",
+                    "type": "number"
+                },
+                "outgoodscode": {
+                    "description": "商品代码(外部)",
+                    "type": "string"
+                },
+                "positionpl": {
+                    "description": "持仓盈亏",
+                    "type": "number"
+                },
+                "positionplrate": {
+                    "description": "持仓盈亏率",
+                    "type": "number"
+                },
+                "usedmargin": {
+                    "description": "占用保证金[商品币种]",
+                    "type": "number"
+                }
+            }
+        },
         "ermcp.RealtimeExposurePositionRsp": {
             "type": "object",
             "properties": {

+ 122 - 0
docs/swagger.json

@@ -1641,6 +1641,51 @@
                 }
             }
         },
+        "/Ermcp/QueryErmcpTradePosition": {
+            "get": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "企业风险管理(app)"
+                ],
+                "summary": "获取企业风管期货持仓头寸信息",
+                "parameters": [
+                    {
+                        "type": "integer",
+                        "description": "资金账户ID",
+                        "name": "accountID",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "所属市场ID",
+                        "name": "marketID",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/ermcp.QueryErmcpTradePositionRsp"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/app.Response"
+                        }
+                    }
+                }
+            }
+        },
         "/Ermcp/QueryExposureDetail": {
             "get": {
                 "security": [
@@ -9271,6 +9316,83 @@
                 }
             }
         },
+        "ermcp.QueryErmcpTradePositionRsp": {
+            "type": "object",
+            "properties": {
+                "agreeunit": {
+                    "description": "合约单位",
+                    "type": "number"
+                },
+                "averageprice": {
+                    "description": "持仓均价",
+                    "type": "number"
+                },
+                "buyorsell": {
+                    "description": "方向 - 0:买 1:卖",
+                    "type": "integer"
+                },
+                "curholderamount": {
+                    "description": "当前持仓总金额[商品币种](成本???)",
+                    "type": "number"
+                },
+                "curpositionqty": {
+                    "description": "当前持仓总数量(总仓数量)",
+                    "type": "integer"
+                },
+                "curtdposition": {
+                    "description": "期末今日头寸(今仓数量)",
+                    "type": "integer"
+                },
+                "curtdpositionenabled": {
+                    "description": "今仓可用",
+                    "type": "integer"
+                },
+                "decimalplace": {
+                    "description": "报价小数位",
+                    "type": "integer"
+                },
+                "enableqty": {
+                    "description": "可用量(总仓可用)",
+                    "type": "integer"
+                },
+                "exexchangename": {
+                    "description": "外部交易所名称(简称)",
+                    "type": "string"
+                },
+                "goodscode": {
+                    "description": "商品代码(内部)",
+                    "type": "string"
+                },
+                "goodsid": {
+                    "description": "商品ID(自增ID SEQ_GOODS)",
+                    "type": "integer"
+                },
+                "goodsname": {
+                    "description": "商品名称",
+                    "type": "string"
+                },
+                "last": {
+                    "description": "现价",
+                    "type": "number"
+                },
+                "outgoodscode": {
+                    "description": "商品代码(外部)",
+                    "type": "string"
+                },
+                "positionpl": {
+                    "description": "持仓盈亏",
+                    "type": "number"
+                },
+                "positionplrate": {
+                    "description": "持仓盈亏率",
+                    "type": "number"
+                },
+                "usedmargin": {
+                    "description": "占用保证金[商品币种]",
+                    "type": "number"
+                }
+            }
+        },
         "ermcp.RealtimeExposurePositionRsp": {
             "type": "object",
             "properties": {

+ 85 - 0
docs/swagger.yaml

@@ -2472,6 +2472,63 @@ definitions:
         description: 现货商品名称
         type: string
     type: object
+  ermcp.QueryErmcpTradePositionRsp:
+    properties:
+      agreeunit:
+        description: 合约单位
+        type: number
+      averageprice:
+        description: 持仓均价
+        type: number
+      buyorsell:
+        description: 方向 - 0:买 1:卖
+        type: integer
+      curholderamount:
+        description: 当前持仓总金额[商品币种](成本???)
+        type: number
+      curpositionqty:
+        description: 当前持仓总数量(总仓数量)
+        type: integer
+      curtdposition:
+        description: 期末今日头寸(今仓数量)
+        type: integer
+      curtdpositionenabled:
+        description: 今仓可用
+        type: integer
+      decimalplace:
+        description: 报价小数位
+        type: integer
+      enableqty:
+        description: 可用量(总仓可用)
+        type: integer
+      exexchangename:
+        description: 外部交易所名称(简称)
+        type: string
+      goodscode:
+        description: 商品代码(内部)
+        type: string
+      goodsid:
+        description: 商品ID(自增ID SEQ_GOODS)
+        type: integer
+      goodsname:
+        description: 商品名称
+        type: string
+      last:
+        description: 现价
+        type: number
+      outgoodscode:
+        description: 商品代码(外部)
+        type: string
+      positionpl:
+        description: 持仓盈亏
+        type: number
+      positionplrate:
+        description: 持仓盈亏率
+        type: number
+      usedmargin:
+        description: 占用保证金[商品币种]
+        type: number
+    type: object
   ermcp.RealtimeExposurePositionRsp:
     properties:
       agreeunit:
@@ -9292,6 +9349,34 @@ paths:
       summary: 查询合同(采购和销售)
       tags:
       - 企业风险管理(app)
+  /Ermcp/QueryErmcpTradePosition:
+    get:
+      parameters:
+      - description: 资金账户ID
+        in: query
+        name: accountID
+        required: true
+        type: integer
+      - description: 所属市场ID
+        in: query
+        name: marketID
+        type: integer
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/ermcp.QueryErmcpTradePositionRsp'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/app.Response'
+      security:
+      - ApiKeyAuth: []
+      summary: 获取企业风管期货持仓头寸信息
+      tags:
+      - 企业风险管理(app)
   /Ermcp/QueryExposureDetail:
     get:
       parameters:

+ 16 - 0
models/account.go

@@ -732,6 +732,22 @@ func GetTaAccountsByLoginID(loginID, taAccountType int) ([]Taaccount, error) {
 	return taAccounts, nil
 }
 
+// GetTaAccountByID 通过AccountID获取资金账户信息
+func GetTaAccountByID(accountID int) (*Taaccount, error) {
+	engine := db.GetEngine()
+
+	var taaccount Taaccount
+	has, err := engine.Where("ACCOUNTID = ?", accountID).Get(&taaccount)
+	if err != nil {
+		return nil, err
+	}
+	if !has {
+		return nil, nil
+	}
+
+	return &taaccount, nil
+}
+
 // InsertWSKHUserInfo 新增网上开户账户信息(客户资料申请)
 func InsertWSKHUserInfo(userinfo Wskhuserinfo) error {
 	engine := db.GetEngine()

+ 20 - 1
models/ermcpOrder.go

@@ -1,6 +1,9 @@
 package models
 
-import "time"
+import (
+	"mtp2_if/db"
+	"time"
+)
 
 // 企业风管期货单据相关
 
@@ -145,3 +148,19 @@ type Hedgeinnertradedetail struct {
 func (Hedgeinnertradedetail) TableName() string {
 	return "HEDGE_INNERTRADEDETAIL"
 }
+
+// GetHedgeOutTradePositions 获取外部持仓头寸信息
+func GetHedgeOutTradePositions(accountID int, marketID int) ([]Hedgeouttradeposition, error) {
+	engine := db.GetEngine()
+
+	hedgeOutTradePositions := make([]Hedgeouttradeposition, 0)
+	session := engine.Where("ACCOUNTID = ?", accountID)
+	if marketID != 0 {
+		session = session.And("MARKETID = ?", marketID)
+	}
+	if err := session.Find(&hedgeOutTradePositions); err != nil {
+		return nil, err
+	}
+
+	return hedgeOutTradePositions, nil
+}

+ 16 - 0
models/market.go

@@ -386,3 +386,19 @@ func GetMarketsByLoginID(loginID int) ([]Market, error) {
 
 	return markets, nil
 }
+
+// GetExternalexchangeByGoodsGroupID 通过商品组ID获取对应交易所信息
+func GetExternalexchangeByGoodsGroupID(goodsGroupID int) (*Externalexchange, error) {
+	rst := make([]Externalexchange, 0)
+	if err := db.GetEngine().Table("EXTERNALEXCHANGE EX").
+		Join("INNER", "GOODSGROUP GG", "GG.EXEXCHANGEID = EX.AUTOID").
+		Where("GG.GOODSGROUPID = ?", goodsGroupID).
+		Find(&rst); err != nil {
+		return nil, err
+	}
+	if len(rst) == 0 {
+		return nil, nil
+	}
+
+	return &rst[0], nil
+}

+ 18 - 1
models/order.go

@@ -1,6 +1,9 @@
 package models
 
-import "time"
+import (
+	"mtp2_if/db"
+	"time"
+)
 
 // Tradeposition 持仓头寸表 - 导历史
 type Tradeposition struct {
@@ -357,3 +360,17 @@ type Tradegoodspickup struct {
 func (Tradegoodspickup) TableName() string {
 	return "TRADE_GOODSPICKUP"
 }
+
+// GetTradePositions 获取指定资金账户的持仓信息
+func GetTradePositions(accountID int, marketID int) ([]Tradeposition, error) {
+	tradePositions := make([]Tradeposition, 0)
+	session := db.GetEngine().Table("TRADEPOSITION T").Where("T.ACCOUNTID = ?", accountID)
+	if marketID != 0 {
+		session = session.And("T.GOODSID in (SELECT G.GOODSID FROM GOODS G WHERE G.MARKETID = ?)", marketID)
+	}
+	if err := session.Find(&tradePositions); err != nil {
+		return nil, err
+	}
+
+	return tradePositions, nil
+}

+ 2 - 0
routers/router.go

@@ -358,6 +358,8 @@ func InitRouter() *gin.Engine {
 		// 期货相关
 		// 查询企业风管期货商品信息
 		ermcpR.GET("/GetErmcpGoods", ermcp.GetErmcpGoods)
+		// 获取企业风管期货持仓头寸信息
+		ermcpR.GET("/QueryErmcpTradePosition", ermcp.QueryErmcpTradePosition)
 	}
 
 	return r