package ermcp import ( "mtp2_if/global/app" "mtp2_if/global/e" "mtp2_if/logger" "mtp2_if/models" "mtp2_if/utils" "net/http" "strconv" "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"` // 商品名称 BuyOrSell int64 `json:"buyorsell"` // 方向 - 0:买 1:卖 EnableQTY int64 `json:"enableqty"` // 可用(总仓可用) CurPositionQTY int64 `json:"curpositionqty"` // 持仓(总仓数量, 期末头寸) Last float64 `json:"last"` // 现价 CurTDPosition int64 `json:"curtdposition"` // 今仓数量(期末今日头寸) CurTDPositionEnabled int64 `json:"curtdpositionenabled"` // 今仓可用 PositionAveragePrice float64 `json:"positionaverageprice"` // 持仓均价【头寸变化更新】= 持仓成本 / 期末头寸 / 合约单位 OpenAveragePrice float64 `json:"openaverageprice" ` // 开仓均价【头寸变化更新】 = 开仓成本 / 期末头寸 / 合约单位 PositionPL float64 `json:"positionpl"` // 盯市浮盈【实时行情更新】(MTP:浮动盈亏、持仓盈亏) 买方向 = (最新价 - 持仓均价) * 买期末头寸 * 合约单位;卖方向 = (持仓均价 - 最新价) * 卖期末头寸 * 合约单位 OpenPL float64 `json:"openpl"` // 逐笔浮盈【实时行情更新】(MTP:开仓盈亏、平仓盈亏) 买方向 = (最新价 - 开仓均价) * 买期末头寸 * 合约单位;卖方向 = (开仓均价 - 最新价) * 卖期末头寸 * 合约单位 PositionPLRate float64 `json:"positionplrate"` // 持仓盈亏比例【实时行情更新】 = 持仓盈亏 / 开仓成本 UsedMargin float64 `json:"usedmargin"` // 占用保证金 ExExehangeName string `json:"exexchangename"` // 外部交易所名称 OpenCost float64 `json:"opencost"` // 开仓成本 PositionCost float64 `json:"positioncost"` // 持仓成本 Goodsid int64 `json:"goodsid"` // 商品ID(自增ID SEQ_GOODS) Goodscode string `json:"goodscode"` // 商品代码(内部) Outgoodscode string `json:"outgoodscode"` // 商品代码(外部) Agreeunit float64 `json:"agreeunit"` // 合约单位 Decimalplace int64 `json:"decimalplace"` // 报价小数位 Marketid int64 `json:"marketid"` // 所属市场ID } // QueryErmcpTradePosition 获取企业风管期货持仓头寸信息 // @Summary 获取企业风管期货持仓头寸信息 // @Description 本接口只使用于通道交易相关头寸查询;子账户持仓头寸占用保证金为0; // @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 } if taAccount.Ismain == 1 { // 母账户,从HEDGE_OUTTRADEPOSITION表查询持仓头寸(未生成内部头寸) 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, CurTDPosition: v.Curtdbuyposition, CurTDPositionEnabled: v.Curtdbuyposition - v.Fretdbuyposition, // 今仓买可用 = 期末今日买头寸 - 冻结今日买头寸 UsedMargin: v.Buyusemargin, OpenCost: v.Buyopencost, PositionCost: v.Buypositioncost, Goodsid: v.Hedgegoodsid, Marketid: int64(v.Marketid), } // 获取对应商品信息 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 item.Decimalplace = goods.Decimalplace // 获取对应外部交易所名称 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_EXEXCHANGE_FAILED, nil) return } if exchange == nil { logger.GetLogger().Errorf("QueryErmcpTradePosition failed") appG.Response(http.StatusBadRequest, e.ERROR_GET_EXEXCHANGE_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_QUOTE_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.OpenAveragePrice = v.Buyopencost / float64(v.Curbuyposition) / goods.Agreeunit item.OpenAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenAveragePrice, int(goods.Decimalplace)), 64) // 持仓均价 = 持仓成本 / 期末头寸 / 合约单位 item.PositionAveragePrice = v.Buypositioncost / float64(v.Curbuyposition) / goods.Agreeunit item.PositionAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionAveragePrice, int(goods.Decimalplace)), 64) // 盯市浮盈【实时行情更新】(MTP:浮动盈亏、持仓盈亏) 买方向 = (最新价 - 持仓均价) * 买期末头寸 * 合约单位;卖方向 = (持仓均价 - 最新价) * 卖期末头寸 * 合约单位 if item.Last != 0 { item.PositionPL = (item.Last - item.PositionAveragePrice) * float64(v.Curbuyposition) * goods.Agreeunit item.PositionPL, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPL, 2), 64) } // 逐笔浮盈【实时行情更新】(MTP:开仓盈亏、平仓盈亏) 买方向 = (最新价 - 开仓均价) * 买期末头寸 * 合约单位;卖方向 = (开仓均价 - 最新价) * 卖期末头寸 * 合约单位 if item.Last != 0 { item.OpenPL = (item.Last - item.OpenAveragePrice) * float64(v.Curbuyposition) * goods.Agreeunit item.OpenPL, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenPL, 2), 64) } // 持仓盈亏比例 = 持仓盈亏 / 开仓成本 if item.PositionPL != 0 && v.Buyopencost != 0 { item.PositionPLRate = item.PositionPL / v.Buyopencost item.PositionPLRate, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPLRate, 4), 64) } rsp = append(rsp, item) } if v.Cursellposition > 0 { // 卖方向 item := QueryErmcpTradePositionRsp{ BuyOrSell: 1, EnableQTY: v.Cursellposition - v.Fretdsellposition - v.Freydsellposition, CurPositionQTY: v.Cursellposition, CurTDPosition: v.Curtdsellposition, CurTDPositionEnabled: v.Curtdsellposition - v.Fretdsellposition, UsedMargin: v.Sellusemargin, OpenCost: v.Sellopencost, PositionCost: v.Sellpositioncost, Goodsid: v.Hedgegoodsid, Marketid: int64(v.Marketid), } // 获取对应商品信息 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 item.Decimalplace = goods.Decimalplace // 获取对应外部交易所名称 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_EXEXCHANGE_FAILED, nil) return } if exchange == nil { logger.GetLogger().Errorf("QueryErmcpTradePosition failed") appG.Response(http.StatusBadRequest, e.ERROR_GET_EXEXCHANGE_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_QUOTE_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.OpenAveragePrice = v.Sellopencost / float64(v.Cursellposition) / goods.Agreeunit item.OpenAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenAveragePrice, int(goods.Decimalplace)), 64) // 持仓均价 = 持仓成本 / 期末头寸 / 合约单位 item.PositionAveragePrice = v.Sellpositioncost / float64(v.Cursellposition) / goods.Agreeunit item.PositionAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionAveragePrice, int(goods.Decimalplace)), 64) // 盯市浮盈【实时行情更新】(MTP:浮动盈亏、持仓盈亏) 买方向 = (最新价 - 持仓均价) * 买期末头寸 * 合约单位;卖方向 = (持仓均价 - 最新价) * 卖期末头寸 * 合约单位 if item.Last != 0 { item.PositionPL = (item.PositionAveragePrice - item.Last) * float64(v.Cursellposition) * goods.Agreeunit item.PositionPL, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPL, 2), 64) } // 逐笔浮盈【实时行情更新】(MTP:开仓盈亏、平仓盈亏) 买方向 = (最新价 - 开仓均价) * 买期末头寸 * 合约单位;卖方向 = (开仓均价 - 最新价) * 卖期末头寸 * 合约单位 if item.Last != 0 { item.OpenPL = (item.OpenAveragePrice - item.Last) * float64(v.Cursellposition) * goods.Agreeunit item.OpenPL, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenPL, 2), 64) } // 持仓盈亏比例 = 持仓盈亏 / 开仓成本 if item.PositionPL != 0 && v.Sellopencost != 0 { item.PositionPLRate = item.PositionPL / v.Sellopencost item.PositionPLRate, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPLRate, 4), 64) } 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, CurTDPosition: v.Buycurtdposition, CurTDPositionEnabled: v.Buycurtdposition - v.Buyfretdposition, // 今仓买可用 = 期末今日买头寸 - 冻结今日买头寸 Goodsid: int64(v.Goodsid), } // 获取对应市场信息 market, err := models.GetMarketByGoodsID(int(v.Goodsid)) if err != nil { // 查询失败 logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil) return } if market == nil { logger.GetLogger().Errorf("QueryErmcpTradePosition failed") appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil) return } item.Marketid = int64(market.Marketid) // 获取对应商品信息 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 item.Decimalplace = goods.Decimalplace // 获取对应外部交易所名称 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_EXEXCHANGE_FAILED, nil) return } if exchange == nil { logger.GetLogger().Errorf("QueryErmcpTradePosition failed") appG.Response(http.StatusBadRequest, e.ERROR_GET_EXEXCHANGE_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_QUOTE_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)) } } // 子账户需要从内部持仓明细(通道)表汇总计划开仓成本和开仓均价 hedgeInnerHolderDetails, _ := models.GetHedgeInnerHolderDetails(req.AccountID, int(item.Goodsid), 0) for _, detail := range hedgeInnerHolderDetails { // 开仓成本 = 建仓价 * 持仓数量 * 合约单位 item.OpenCost += detail.Openprice * float64(detail.Holderqty) * goods.Agreeunit } // 开仓均价 = 开仓成本 / 期末头寸 / 合约单位 item.OpenAveragePrice = item.OpenCost / float64(item.CurPositionQTY) / goods.Agreeunit item.OpenAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenAveragePrice, int(goods.Decimalplace)), 64) // 持仓成本 item.PositionCost = v.Buycurholderamount // 持仓均价 = 持仓成本 / 期末头寸 / 合约单位 item.PositionAveragePrice = v.Buycurholderamount / float64(v.Buycurpositionqty) / goods.Agreeunit item.PositionAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionAveragePrice, int(goods.Decimalplace)), 64) // 盯市浮盈【实时行情更新】(MTP:浮动盈亏、持仓盈亏) 买方向 = (最新价 - 持仓均价) * 买期末头寸 * 合约单位;卖方向 = (持仓均价 - 最新价) * 卖期末头寸 * 合约单位 if item.Last != 0 { item.PositionPL = (item.Last - item.PositionAveragePrice) * float64(v.Buycurpositionqty) * goods.Agreeunit item.PositionPL, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPL, 2), 64) } // 逐笔浮盈【实时行情更新】(MTP:开仓盈亏、平仓盈亏) 买方向 = (最新价 - 开仓均价) * 买期末头寸 * 合约单位;卖方向 = (开仓均价 - 最新价) * 卖期末头寸 * 合约单位 if item.Last != 0 { item.OpenPL = (item.Last - item.OpenAveragePrice) * float64(v.Buycurpositionqty) * goods.Agreeunit item.OpenPL, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenPL, 2), 64) } // 持仓盈亏比例 = 持仓盈亏 / 开仓成本 if item.PositionPL != 0 && item.OpenCost != 0 { item.PositionPLRate = item.PositionPL / item.OpenCost item.PositionPLRate, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPLRate, 4), 64) } rsp = append(rsp, item) } if v.Sellcurpositionqty > 0 { // 卖方向 item := QueryErmcpTradePositionRsp{ BuyOrSell: 1, EnableQTY: v.Sellcurpositionqty - v.Sellfrozenqty, // 买可用 = 买当前持仓总数量 - 买持仓冻结数量 CurPositionQTY: v.Sellcurpositionqty, CurTDPosition: v.Sellcurtdposition, CurTDPositionEnabled: v.Sellcurtdposition - v.Sellfretdposition, // 今仓买可用 = 期末今日买头寸 - 冻结今日买头寸 Goodsid: int64(v.Goodsid), } // 获取对应市场信息 market, err := models.GetMarketByGoodsID(int(v.Goodsid)) if err != nil { // 查询失败 logger.GetLogger().Errorf("QueryErmcpTradePosition failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil) return } if market == nil { logger.GetLogger().Errorf("QueryErmcpTradePosition failed") appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil) return } item.Marketid = int64(market.Marketid) // 获取对应商品信息 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 item.Decimalplace = goods.Decimalplace // 获取对应外部交易所名称 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_EXEXCHANGE_FAILED, nil) return } if exchange == nil { logger.GetLogger().Errorf("QueryErmcpTradePosition failed") appG.Response(http.StatusBadRequest, e.ERROR_GET_EXEXCHANGE_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_QUOTE_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)) } } // 子账户需要从内部持仓明细(通道)表汇总计划开仓成本和开仓均价 hedgeInnerHolderDetails, _ := models.GetHedgeInnerHolderDetails(req.AccountID, int(item.Goodsid), 1) for _, detail := range hedgeInnerHolderDetails { // 开仓成本 = 建仓价 * 持仓数量 * 合约单位 item.OpenCost += detail.Openprice * float64(detail.Holderqty) * goods.Agreeunit } // 开仓均价 = 开仓成本 / 期末头寸 / 合约单位 item.OpenAveragePrice = item.OpenCost / float64(item.CurPositionQTY) / goods.Agreeunit item.OpenAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenAveragePrice, int(goods.Decimalplace)), 64) // 持仓成本 item.PositionCost = v.Sellcurholderamount // 持仓均价 = 持仓成本 / 期末头寸 / 合约单位 item.PositionAveragePrice = v.Sellcurholderamount / float64(v.Sellcurpositionqty) / goods.Agreeunit item.PositionAveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionAveragePrice, int(goods.Decimalplace)), 64) // 盯市浮盈【实时行情更新】(MTP:浮动盈亏、持仓盈亏) 买方向 = (最新价 - 持仓均价) * 买期末头寸 * 合约单位;卖方向 = (持仓均价 - 最新价) * 卖期末头寸 * 合约单位 if item.Last != 0 { item.PositionPL = (item.PositionAveragePrice - item.Last) * float64(v.Sellcurpositionqty) * goods.Agreeunit item.PositionPL, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPL, 2), 64) } // 逐笔浮盈【实时行情更新】(MTP:开仓盈亏、平仓盈亏) 买方向 = (最新价 - 开仓均价) * 买期末头寸 * 合约单位;卖方向 = (开仓均价 - 最新价) * 卖期末头寸 * 合约单位 if item.Last != 0 { item.OpenPL = (item.OpenAveragePrice - item.Last) * float64(v.Sellcurpositionqty) * goods.Agreeunit item.OpenPL, _ = strconv.ParseFloat(utils.FormatFloat(item.OpenPL, 2), 64) } // 持仓盈亏比例 = 持仓盈亏 / 开仓成本 if item.PositionPL != 0 && item.OpenCost != 0 { item.PositionPLRate = item.PositionPL / item.OpenCost item.PositionPLRate, _ = strconv.ParseFloat(utils.FormatFloat(item.PositionPLRate, 4), 64) } rsp = append(rsp, item) } } } // 查询成功返回 logger.GetLogger().Debugln("QueryErmcpTradePosition successed: %v", rsp) appG.Response(http.StatusOK, e.SUCCESS, rsp) } // QueryErmcpInnerHolderDetailsReq 获取企业风管期货内部持仓单信息请求参数 type QueryErmcpInnerHolderDetailsReq struct { AccountID int `form:"accountID" binding:"required"` GoodsID int `form:"goodsID"` BuyOrSell int `form:"buyOrSell"` } // QueryErmcpInnerHolderDetails 获取企业风管期货内部持仓单信息 // @Summary 获取企业风管期货内部持仓单信息 // @Produce json // @Security ApiKeyAuth // @Param accountID query int true "资金账户ID" // @Param goodsID query int false "商品ID" // @Param buyOrSell query int false "买卖方向,0:买 1:卖" // @Success 200 {object} models.Hedgeinnerholderdetail // @Failure 500 {object} app.Response // @Router /Ermcp/QueryErmcpInnerHolderDetails [get] // @Tags 企业风险管理(app) func QueryErmcpInnerHolderDetails(c *gin.Context) { appG := app.Gin{C: c} // 获取请求参数 var req QueryErmcpInnerHolderDetailsReq if err := appG.C.ShouldBindQuery(&req); err != nil { logger.GetLogger().Errorf("QueryErmcpInnerHolderDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil) return } var r models.Hedgeinnerholderdetail rst, err := r.GetList(req.AccountID, req.GoodsID, req.BuyOrSell) if err != nil { logger.GetLogger().Errorf("QueryErmcpInnerHolderDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } // 查询成功返回 logger.GetLogger().Debugln("QueryErmcpInnerHolderDetails successed: %v", rst) appG.Response(http.StatusOK, e.SUCCESS, rst) } // QueryErmcpOrderDetailsReq 获取企业风管期货委托单信息请求参数 type QueryErmcpOrderDetailsReq struct { AccountID int `form:"accountID" binding:"required"` } // QueryErmcpOrderDetails 获取企业风管期货委托单信息 // @Summary 获取企业风管期货委托单信息 // @Produce json // @Security ApiKeyAuth // @Param accountID query int true "资金账户ID" // @Success 200 {object} models.QueryHedgeOrderDetailRsp // @Failure 500 {object} app.Response // @Router /Ermcp/QueryErmcpOrderDetails [get] // @Tags 企业风险管理(app) func QueryErmcpOrderDetails(c *gin.Context) { appG := app.Gin{C: c} // 获取请求参数 var req QueryErmcpOrderDetailsReq if err := appG.C.ShouldBindQuery(&req); err != nil { logger.GetLogger().Errorf("QueryErmcpOrderDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil) return } // 获取资金账户信息 taAccount, err := models.GetTaAccountByID(req.AccountID) if err != nil { logger.GetLogger().Errorf("QueryErmcpOrderDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } if taAccount == nil { logger.GetLogger().Errorf("QueryErmcpOrderDetails failed") appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } rst := make([]models.QueryHedgeOrderDetailRsp, 0) if taAccount.Ismain == 1 { // 母账户 -> 外部委托单 rst, err = models.GetHedgeOutOrderDetails(req.AccountID) if err != nil { // 查询失败 logger.GetLogger().Errorf("QueryErmcpOrderDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } } else { // 子账户 -> 内部委托单 rst, err = models.GetHedgeInnerOrderDetails(req.AccountID) if err != nil { // 查询失败 logger.GetLogger().Errorf("QueryErmcpOrderDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } } // 查询成功返回 logger.GetLogger().Debugln("QueryErmcpOrderDetails successed: %v", rst) appG.Response(http.StatusOK, e.SUCCESS, rst) } // QueryErmcpHisOrderDetailsReq 获取企业风管期货历史委托单信息请求参数 type QueryErmcpHisOrderDetailsReq struct { AccountID int `form:"accountID" binding:"required"` StartDate string `form:"startDate"` // 开始时间 EndDate string `form:"endDate"` // 结束时间 } // QueryErmcpHisOrderDetails 获取企业风管期货历史委托单信息 // @Summary 获取企业风管期货历史委托单信息 // @Produce json // @Security ApiKeyAuth // @Param accountID query int true "资金账户ID" // @Param startDate query string false "开始时间 - 闭区间,格式:yyyy-MM-dd" // @Param endDate query string false "结束时间 - 闭区间,格式:yyyy-MM-dd" // @Success 200 {object} models.QueryHedgeOrderDetailRsp // @Failure 500 {object} app.Response // @Router /Ermcp/QueryErmcpHisOrderDetails [get] // @Tags 企业风险管理(app) func QueryErmcpHisOrderDetails(c *gin.Context) { appG := app.Gin{C: c} // 获取请求参数 var req QueryErmcpHisOrderDetailsReq if err := appG.C.ShouldBindQuery(&req); err != nil { logger.GetLogger().Errorf("QueryErmcpHisOrderDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil) return } // 获取资金账户信息 taAccount, err := models.GetTaAccountByID(req.AccountID) if err != nil { logger.GetLogger().Errorf("QueryErmcpHisOrderDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } if taAccount == nil { logger.GetLogger().Errorf("QueryErmcpHisOrderDetails failed") appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } rst := make([]models.QueryHedgeOrderDetailRsp, 0) if taAccount.Ismain == 1 { // 母账户 -> 外部历史委托单 rst, err = models.GetHisHedgeOutOrderDetails(req.AccountID, req.StartDate, req.EndDate) if err != nil { // 查询失败 logger.GetLogger().Errorf("QueryErmcpHisOrderDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } } else { // 子账户 -> 内部历史委托单 rst, err = models.GetHisHedgeInnerOrderDetails(req.AccountID, req.StartDate, req.EndDate) if err != nil { // 查询失败 logger.GetLogger().Errorf("QueryErmcpHisOrderDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } } // 查询成功返回 logger.GetLogger().Debugln("QueryErmcpHisOrderDetails successed: %v", rst) appG.Response(http.StatusOK, e.SUCCESS, rst) } // QueryHedgeTradeDetailReq 获取企业风管期货成交单信息请求参数 type QueryHedgeTradeDetailReq struct { AccountID int `form:"accountID" binding:"required"` GoodsID int `form:"goodsID"` BuyOrSell int `form:"buyOrSell"` OrderID int `form:"orderID"` } // QueryErmcpTradeDetails 获取企业风管期货成交单信息 // @Summary 获取企业风管期货成交单信息 // @Produce json // @Security ApiKeyAuth // @Param accountID query int true "资金账户ID" // @Param goodsID query int false "商品ID" // @Param buyOrSell query int false "买卖方向,0:买 1:卖" // @Param orderID query int false "关联委托单号" // @Success 200 {object} models.QueryHedgeTradeDetailRsp // @Failure 500 {object} app.Response // @Router /Ermcp/QueryErmcpTradeDetails [get] // @Tags 企业风险管理(app) func QueryErmcpTradeDetails(c *gin.Context) { appG := app.Gin{C: c} // 获取请求参数 var req QueryHedgeTradeDetailReq if err := appG.C.ShouldBindQuery(&req); err != nil { logger.GetLogger().Errorf("QueryErmcpTradeDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil) return } // 获取资金账户信息 taAccount, err := models.GetTaAccountByID(req.AccountID) if err != nil { logger.GetLogger().Errorf("QueryErmcpTradeDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } if taAccount == nil { logger.GetLogger().Errorf("QueryErmcpTradeDetails failed") appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } rst := make([]models.QueryHedgeTradeDetailRsp, 0) if taAccount.Ismain == 1 { // 母账户 -> 外部成交单 rst, err = models.GetHedgeOutTradeDetails(req.AccountID, req.GoodsID, req.BuyOrSell, req.OrderID) if err != nil { // 查询失败 logger.GetLogger().Errorf("QueryErmcpTradeDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } } else { // 子账户 -> 内部成交单 rst, err = models.GetHedgeInnerTradeDetails(req.AccountID, req.GoodsID, req.BuyOrSell, req.OrderID) if err != nil { // 查询失败 logger.GetLogger().Errorf("QueryErmcpTradeDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } } // 查询成功返回 logger.GetLogger().Debugln("QueryErmcpTradeDetails successed: %v", rst) appG.Response(http.StatusOK, e.SUCCESS, rst) } // QueryHedgeHisTradeDetaislReq 获取企业风管期货历史成交单信息请求参数 type QueryHedgeHisTradeDetaislReq struct { AccountID int `form:"accountID" binding:"required"` GoodsID int `form:"goodsID"` BuyOrSell int `form:"buyOrSell"` OrderID int `form:"orderID"` StartDate string `form:"startDate"` // 开始时间 EndDate string `form:"endDate"` // 结束时间 } // QueryErmcpHisTradeDetails 获取企业风管期货历史成交单信息 // @Summary 获取企业风管期货历史成交单信息 // @Produce json // @Security ApiKeyAuth // @Param accountID query int true "资金账户ID" // @Param goodsID query int false "商品ID" // @Param buyOrSell query int false "买卖方向,0:买 1:卖" // @Param orderID query int false "关联委托单号" // @Param startDate query string false "开始时间 - 闭区间,格式:yyyy-MM-dd" // @Param endDate query string false "结束时间 - 闭区间,格式:yyyy-MM-dd" // @Success 200 {object} models.QueryHedgeTradeDetailRsp // @Failure 500 {object} app.Response // @Router /Ermcp/QueryErmcpHisTradeDetails [get] // @Tags 企业风险管理(app) func QueryErmcpHisTradeDetails(c *gin.Context) { appG := app.Gin{C: c} // 获取请求参数 var req QueryHedgeHisTradeDetaislReq if err := appG.C.ShouldBindQuery(&req); err != nil { logger.GetLogger().Errorf("QueryErmcpHisTradeDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil) return } // 获取资金账户信息 taAccount, err := models.GetTaAccountByID(req.AccountID) if err != nil { logger.GetLogger().Errorf("QueryErmcpHisTradeDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } if taAccount == nil { logger.GetLogger().Errorf("QueryErmcpHisTradeDetails failed") appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } rst := make([]models.QueryHedgeTradeDetailRsp, 0) if taAccount.Ismain == 1 { // 母账户 -> 外部历史成交单 rst, err = models.GetHisHedgeOutTradeDetails(req.AccountID, req.GoodsID, req.BuyOrSell, req.OrderID, req.StartDate, req.EndDate) if err != nil { // 查询失败 logger.GetLogger().Errorf("QueryErmcpHisTradeDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } } else { // 子账户 -> 内部历史成交单 rst, err = models.GetHisHedgeInnerTradeDetails(req.AccountID, req.GoodsID, req.BuyOrSell, req.OrderID, req.StartDate, req.EndDate) if err != nil { // 查询失败 logger.GetLogger().Errorf("QueryErmcpHisTradeDetails failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } } // 查询成功返回 logger.GetLogger().Debugln("QueryErmcpHisTradeDetails successed: %v", rst) appG.Response(http.StatusOK, e.SUCCESS, rst) }