|
|
@@ -10,7 +10,9 @@ import (
|
|
|
"mtp2_if/logger"
|
|
|
"mtp2_if/models"
|
|
|
"mtp2_if/mtpcache"
|
|
|
+ "mtp2_if/utils"
|
|
|
"net/http"
|
|
|
+ "strconv"
|
|
|
"time"
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
@@ -73,6 +75,10 @@ type QueryTradePositionRsp struct {
|
|
|
AveragePrice float64 `json:"averageprice" xorm:"AVERAGEPRICE"` // 持仓均价
|
|
|
Usedmargin float64 `json:"usedmargin" xorm:"'USEDMARGIN'"` // 占用保证金[商品币种]
|
|
|
QTYDECIMALPLACE int32 `json:"qtydecimalplace"` // 成交量小数位
|
|
|
+ PositionPL float64 `json:"positionpl"` // 持仓盈亏 买方向 = (最新价 - 持仓均价) * 买期末头寸 * 合约单位;卖方向 = (持仓均价 - 最新价) * 卖期末头寸 * 合约单位
|
|
|
+ PositionPLRate float64 `json:"positionplrate"` // 持仓盈亏比例【实时行情更新】 = 持仓盈亏 / 开仓成本
|
|
|
+ MarketAmount float64 `json:"marketamount"` // 市值
|
|
|
+ LastPrice float64 `json:"lastprice"` // 最新价
|
|
|
}
|
|
|
|
|
|
// QueryTradePosition 持仓汇总查询(合约市场)
|
|
|
@@ -96,7 +102,17 @@ func QueryTradePosition(c *gin.Context) {
|
|
|
appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
|
|
|
return
|
|
|
}
|
|
|
+ rst, ret := GetTradePosition(req.AccountID, req.TradeMode)
|
|
|
+ if ret {
|
|
|
+ appG.Response(http.StatusOK, e.SUCCESS, rst)
|
|
|
+ } else {
|
|
|
+ appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
+// GetTradePosition 获取持仓汇总数据, 成功返回true, 失败返回false
|
|
|
+func GetTradePosition(accIds string, tradeModes string) (rst []QueryTradePositionRsp, ret bool) {
|
|
|
+ rst = make([]QueryTradePositionRsp, 0)
|
|
|
// 查询数据
|
|
|
type tradePosition struct {
|
|
|
models.Tradeposition `xorm:"extends"`
|
|
|
@@ -119,18 +135,52 @@ func QueryTradePosition(c *gin.Context) {
|
|
|
Join("LEFT", "MARKET", "GOODS.MARKETID = MARKET.MARKETID").
|
|
|
Join("LEFT", "ENUMDICITEM", "GOODS.GOODUNITID = ENUMDICITEM.ENUMITEMNAME and ENUMDICITEM.ENUMDICCODE = 'goodsunit'").
|
|
|
Select("TRADEPOSITION.*, GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.CURRENCYID, GOODS.GOODUNITID,GOODS.QTYDECIMALPLACE, ENUMDICITEM.ENUMDICNAME as GOODUNIT, GOODS.AGREEUNIT, GOODS.DECIMALPLACE, MARKET.MARKETID, MARKET.TRADEMODE").
|
|
|
- Where(fmt.Sprintf(`TRADEPOSITION.ACCOUNTID in (%s)`, req.AccountID))
|
|
|
- if len(req.TradeMode) > 0 {
|
|
|
- s = s.And(fmt.Sprintf(`MARKET.TRADEMODE in (%s)`, req.TradeMode))
|
|
|
+ Where(fmt.Sprintf(`TRADEPOSITION.ACCOUNTID in (%s)`, accIds))
|
|
|
+ if len(tradeModes) > 0 {
|
|
|
+ s = s.And(fmt.Sprintf(`MARKET.TRADEMODE in (%s)`, tradeModes))
|
|
|
}
|
|
|
if err := s.Find(&datas); err != nil {
|
|
|
// 查询失败
|
|
|
logger.GetLogger().Errorf("QueryTradePosition failed: %s", err.Error())
|
|
|
- appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
|
|
|
+ return rst, false
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取盘面
|
|
|
+ goodGuotes := make([]models.Quoteday, 0)
|
|
|
+ if len(datas) > 0 {
|
|
|
+ var a models.InStrBuilder
|
|
|
+ for i := range datas {
|
|
|
+ a.Add(datas[i].Goodscode)
|
|
|
+ }
|
|
|
+ goodGuotes, _ = models.GetQuoteDays(a.InStr())
|
|
|
+ }
|
|
|
+
|
|
|
+ fCalcPL := func(goodsCode string, buyOrSell int64, qty, holderPrice,
|
|
|
+ agreeUnit float64, decimalPlace int64) (positionPL float64, marketAmount float64, lastPrice float64) {
|
|
|
+ positionPL = 0
|
|
|
+ for _, q := range goodGuotes {
|
|
|
+ if goodsCode == q.Goodscode {
|
|
|
+ if q.Last != 0 {
|
|
|
+ lastPrice = utils.IntToFloat64(int(q.Last), int(decimalPlace))
|
|
|
+ } else if q.Presettle != 0 {
|
|
|
+ lastPrice = utils.IntToFloat64(int(q.Presettle), int(decimalPlace))
|
|
|
+ } else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ positionPL = (lastPrice - holderPrice) * qty * agreeUnit
|
|
|
+ positionPL, _ = strconv.ParseFloat(utils.FormatFloat(positionPL, 2), 64)
|
|
|
+ if buyOrSell == 1 {
|
|
|
+ // 卖方向 *-1
|
|
|
+ positionPL *= -1.0
|
|
|
+ }
|
|
|
+ marketAmount = lastPrice * qty * agreeUnit
|
|
|
+ marketAmount, _ = strconv.ParseFloat(utils.FormatFloat(marketAmount, 2), 64)
|
|
|
+ }
|
|
|
+ }
|
|
|
return
|
|
|
}
|
|
|
+
|
|
|
// 构建返回数据
|
|
|
- rst := make([]QueryTradePositionRsp, 0)
|
|
|
for _, v := range datas {
|
|
|
// 构建买方向持仓汇总
|
|
|
if v.Buycurpositionqty > 0 {
|
|
|
@@ -161,6 +211,12 @@ func QueryTradePosition(c *gin.Context) {
|
|
|
//tradePosition.AveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(averagePrice, int(v.Decimalplace)), 64)
|
|
|
// #96004 改为固定3位小数
|
|
|
tradePosition.AveragePrice, _ = decimal.NewFromFloat(averagePrice).Round(3).Float64()
|
|
|
+ tradePosition.PositionPL, tradePosition.MarketAmount, tradePosition.LastPrice = fCalcPL(tradePosition.GoodsCode, tradePosition.BuyOrSell, tradePosition.CurPositionQTY,
|
|
|
+ tradePosition.AveragePrice, tradePosition.AgreeUnit, tradePosition.DecimalPlace)
|
|
|
+ if tradePosition.CurHolderAmount > 1e-10 {
|
|
|
+ tradePosition.PositionPLRate = tradePosition.PositionPL / tradePosition.CurHolderAmount
|
|
|
+ tradePosition.PositionPLRate, _ = strconv.ParseFloat(utils.FormatFloat(tradePosition.PositionPLRate, 4), 64)
|
|
|
+ }
|
|
|
rst = append(rst, tradePosition)
|
|
|
}
|
|
|
}
|
|
|
@@ -194,7 +250,12 @@ func QueryTradePosition(c *gin.Context) {
|
|
|
//tradePosition.AveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(averagePrice, int(v.Decimalplace)), 64)
|
|
|
// #96004 改为固定3位小数
|
|
|
tradePosition.AveragePrice, _ = decimal.NewFromFloat(averagePrice).Round(3).Float64()
|
|
|
-
|
|
|
+ tradePosition.PositionPL, tradePosition.MarketAmount, tradePosition.LastPrice = fCalcPL(tradePosition.GoodsCode, tradePosition.BuyOrSell, tradePosition.CurPositionQTY,
|
|
|
+ tradePosition.AveragePrice, tradePosition.AgreeUnit, tradePosition.DecimalPlace)
|
|
|
+ if tradePosition.CurHolderAmount > 1e-10 {
|
|
|
+ tradePosition.PositionPLRate = tradePosition.PositionPL / tradePosition.CurHolderAmount
|
|
|
+ tradePosition.PositionPLRate, _ = strconv.ParseFloat(utils.FormatFloat(tradePosition.PositionPLRate, 4), 64)
|
|
|
+ }
|
|
|
rst = append(rst, tradePosition)
|
|
|
}
|
|
|
}
|
|
|
@@ -202,7 +263,7 @@ func QueryTradePosition(c *gin.Context) {
|
|
|
|
|
|
// 查询成功
|
|
|
logger.GetLogger().Debugln("QueryTradePosition successed: %v", rst)
|
|
|
- appG.Response(http.StatusOK, e.SUCCESS, rst)
|
|
|
+ return rst, true
|
|
|
}
|
|
|
|
|
|
// QueryTradeOrderDetailReq 委托单查询请求参数(合约市场)
|