package order import ( "encoding/json" "fmt" "mtp2_if/db" "mtp2_if/global/app" "mtp2_if/global/e" "mtp2_if/logger" "mtp2_if/models" "net/http" "time" "github.com/gin-gonic/gin" ) // QueryTradePositionReq 持仓汇总查询请求参数(合约市场) type QueryTradePositionReq struct { AccountID string `form:"accountID" binding:"required"` TradeMode string `form:"tradeMode"` } // QueryTradePositionRsp 持仓汇总查询返回模型(合约市场) type QueryTradePositionRsp struct { AccountID uint64 `json:"accountid" xorm:"'ACCOUNTID'"` // 资金账户 BuyOrSell int64 `json:"buyorsell" xorm:"'BUYORSELL'" ` // 方向 - 0:买 1:卖 GoodsCode string `json:"goodscode" xorm:"GOODSCODE"` // 商品代码 GoodsName string `json:"goodsname" xorm:"GOODSNAME"` // 商品名称 AgreeUnit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位 CurrencyID int64 `json:"currencyid" xorm:"'CURRENCYID'"` // 报价货币ID GoodUnitID int64 `json:"goodunitid" xorm:"'GOODUNITID'"` // 报价单位ID Goodunit string `json:"goodunit" xorm:"'GOODUNIT'"` // 报价单位 DecimalPlace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位 MarketID int64 `json:"marketid" xorm:"'MARKETID'"` // 所属市场ID TradeMode uint32 `json:"trademode" xorm:"'TRADEMODE'"` // 交易模式 PositionQTY uint64 `json:"positionqty" xorm:"'POSITIONQTY'"` // 期初持仓数量 HolderAmount float64 `json:"holderamount" xorm:"'HOLDERAMOUNT'"` // 期初持仓总金额[商品币种] CurPositionQTY uint64 `json:"curpositionqty" xorm:"'CURPOSITIONQTY'"` // 当前持仓总数量 CurHolderAmount float64 `json:"curholderamount" xorm:"'CURHOLDERAMOUNT'"` // 当前持仓总金额[商品币种] FrozenQTY uint64 `json:"frozenqty" xorm:"'FROZENQTY'"` // 持仓冻结数量 OtherFrozenQTY uint64 `json:"otherfrozenqty" xorm:"'OTHERFROZENQTY'"` // 持仓其他冻结数量(交割冻结) OpenReqQTY uint64 `json:"openreqqty" xorm:"'OPENREQQTY'"` // 开仓申请数量(用于比较最大持仓数量) OpenTotalQTY uint64 `json:"opentotalqty" xorm:"'OPENTOTALQTY'"` // 开仓总数量 CloseTotalQTY uint64 `json:"closetotalqty" xorm:"'CLOSETOTALQTY'"` // 平仓总数量 TNQTY uint64 `json:"tnqty" xorm:"'TNQTY'"` // T+N冻结总量 TNUsedQTY uint64 `json:"tnusedqty" xorm:"'TNUSEDQTY'"` // T+N使用量(可以使用T+N的冻结数量) CurTDPosition uint64 `json:"curtdposition" xorm:"'CURTDPOSITION'"` // 期末今日头寸 FreTDPosition uint64 `json:"fretdposition" xorm:"'FRETDPOSITION'"` // 冻结今日头寸 EnableQTY uint64 `json:"enableqty" xorm:"'ENABLEQTY'"` // 可用量 } // QueryTradePosition 持仓汇总查询(合约市场) // @Summary 持仓汇总查询(合约市场) // @Produce json // @Security ApiKeyAuth // @Param accountID query string true "资金账户 - 格式:1,2,3" // @Param tradeMode query string false "交易模式 - 格式:1,2,3" // @Success 200 {object} QueryTradePositionRsp // @Failure 500 {object} app.Response // @Router /Order/QueryTradePosition [get] // @Tags 通用单据 // 参考通用查询:SearchTradePositionDetail func QueryTradePosition(c *gin.Context) { appG := app.Gin{C: c} // 获取请求参数 var req QueryTradePositionReq if err := appG.C.ShouldBindQuery(&req); err != nil { logger.GetLogger().Errorf("QueryTradePosition failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil) return } // 查询数据 type tradePosition struct { models.Tradeposition `xorm:"extends"` Goodscode string `json:"goodscode" xorm:"'GOODSCODE'"` // 商品代码(内部) Goodsname string `json:"goodsname" xorm:"'GOODSNAME'"` // 商品名称 Currencyid int64 `json:"currencyid" xorm:"'CURRENCYID'"` // 报价货币ID Goodunitid int64 `json:"goodunitid" xorm:"'GOODUNITID'"` // 报价单位ID Goodunit string `json:"goodunit" xorm:"'GOODUNIT'"` // 报价单位 Agreeunit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位 Decimalplace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位 Marketid uint32 `json:"marketid" xorm:"'MARKETID'"` // 市场ID Trademode uint32 `json:"trademode" xorm:"'TRADEMODE'"` // 交易模式 } datas := make([]tradePosition, 0) engine := db.GetEngine() // ORACLE好像在JOIN里不支持别名功能(在XORM中) s := engine.Table("TRADEPOSITION"). Join("LEFT", "GOODS", "TRADEPOSITION.GOODSID = GOODS.GOODSID"). 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, 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)) } 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 := make([]QueryTradePositionRsp, 0) for _, v := range datas { // 构建买方向持仓汇总 if v.Buycurpositionqty > 0 { var tradePosition QueryTradePositionRsp // 反射数据 // struct -> json if jsonBytes, err := json.Marshal(v); err == nil { // json -> struct json.Unmarshal(jsonBytes, &tradePosition) tradePosition.BuyOrSell = 0 tradePosition.PositionQTY = v.Buypositionqty tradePosition.HolderAmount = v.Buyholderamount tradePosition.CurPositionQTY = v.Buycurpositionqty tradePosition.CurHolderAmount = v.Buycurholderamount tradePosition.FrozenQTY = v.Buyfrozenqty tradePosition.OtherFrozenQTY = v.Buyotherfrozenqty tradePosition.OpenReqQTY = v.Buyopenreqqty tradePosition.OpenTotalQTY = v.Buyopentotalqty tradePosition.CloseTotalQTY = v.Buyclosetotalqty tradePosition.TNQTY = v.Buytnqty tradePosition.TNUsedQTY = v.Buytnusedqty tradePosition.CurTDPosition = v.Buycurtdposition tradePosition.FreTDPosition = v.Buyfretdposition tradePosition.EnableQTY = v.Buycurpositionqty - v.Buyfrozenqty - v.Buyotherfrozenqty rst = append(rst, tradePosition) } } // 构建卖方向持仓汇总 if v.Tradeproperty != 2 && v.Sellcurpositionqty > 0 { var tradePosition QueryTradePositionRsp // 反射数据 // struct -> json if jsonBytes, err := json.Marshal(v); err == nil { // json -> struct json.Unmarshal(jsonBytes, &tradePosition) tradePosition.BuyOrSell = 1 tradePosition.PositionQTY = v.Sellpositionqty tradePosition.HolderAmount = v.Sellholderamount tradePosition.CurPositionQTY = v.Sellcurpositionqty tradePosition.CurHolderAmount = v.Sellcurholderamount tradePosition.FrozenQTY = v.Sellfrozenqty tradePosition.OtherFrozenQTY = v.Sellotherfrozenqty tradePosition.OpenReqQTY = v.Sellopenreqqty tradePosition.OpenTotalQTY = v.Sellopentotalqty tradePosition.CloseTotalQTY = v.Sellclosetotalqty tradePosition.TNQTY = v.Selltnqty tradePosition.TNUsedQTY = v.Selltnusedqty tradePosition.CurTDPosition = v.Sellcurtdposition tradePosition.FreTDPosition = v.Sellfretdposition tradePosition.EnableQTY = v.Sellcurpositionqty - v.Sellfrozenqty - v.Sellotherfrozenqty rst = append(rst, tradePosition) } } } // 查询成功 logger.GetLogger().Infof("QueryTradePosition successed: %v", rst) appG.Response(http.StatusOK, e.SUCCESS, rst) } // QueryTradeOrderDetailReq 委托单查询请求参数(合约市场) type QueryTradeOrderDetailReq struct { AccountID string `form:"accountID" binding:"required"` OrderStatus string `form:"orderStatus"` TradeMode string `form:"tradeMode"` OrderID int `form:"orderID"` } // QueryTradeOrderDetailRsp 委托单查询返回模型(合约市场) type QueryTradeOrderDetailRsp struct { // 委托单字段 Orderid int64 `json:"orderid" xorm:"'ORDERID'" binding:"required"` // 委托单号(100+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx) Tradedate string `json:"tradedate" xorm:"'TRADEDATE'" binding:"required"` // 交易日(yyyyMMdd) Buildtype int64 `json:"buildtype" xorm:"'BUILDTYPE'" binding:"required"` // 委托单据类型 - 1:建仓 2:平仓 3:先平后建 Preorderid int64 `json:"preorderid" xorm:"'PREORDERID'"` // 关联预埋单号(止盈止损单时填写) Cancelorderid int64 `json:"cancelorderid" xorm:"'CANCELORDERID'"` // 撤单单号(撤单时填写) Relatedid int64 `json:"relatedid" xorm:"'RELATEDID'"` // 关联单号(交割单) Marketid int64 `json:"marketid" xorm:"'MARKETID'" binding:"required"` // 市场ID Goodsid int64 `json:"goodsid" xorm:"'GOODSID'" binding:"required"` // 商品ID Accountid int64 `json:"accountid" xorm:"'ACCOUNTID'" binding:"required"` // 账户ID[报价币种] Buyorsell int64 `json:"buyorsell" xorm:"'BUYORSELL'" binding:"required"` // 买卖 - 0:买 1:卖 Pricemode int64 `json:"pricemode" xorm:"'PRICEMODE'" binding:"required"` // 取价方式 - 1:市价 2: 限价 Orderprice float64 `json:"orderprice" xorm:"'ORDERPRICE'"` // 委托价格 Orderqty int64 `json:"orderqty" xorm:"'ORDERQTY'" binding:"required"` // 委托数量 Tradeqty int64 `json:"tradeqty" xorm:"'TRADEQTY'"` // 成交数量 Cancelqty int64 `json:"cancelqty" xorm:"'CANCELQTY'"` // 撤单数量 Openqty int64 `json:"openqty" xorm:"'OPENQTY'"` // 开仓数量(先建后平操作,需要记录) Closeqty int64 `json:"closeqty" xorm:"'CLOSEQTY'"` // 平仓数量(先建后平操作 需要记录) Opentradeqty int64 `json:"opentradeqty" xorm:"'OPENTRADEQTY'"` // 开仓成交数量(先建后平操作,需要记录) Closetradeqty int64 `json:"closetradeqty" xorm:"'CLOSETRADEQTY'"` // 平仓成交数量(先建后平操作,需要记录) Freezemargin float64 `json:"freezemargin" xorm:"'FREEZEMARGIN'"` // 冻结保证金(冻结交易金额) Unfreezemargin float64 `json:"unfreezemargin" xorm:"'UNFREEZEMARGIN'"` // 解冻保证金 Freezecharge float64 `json:"freezecharge" xorm:"'FREEZECHARGE'"` // 冻结手续费 Unfreezecharge float64 `json:"unfreezecharge" xorm:"'UNFREEZECHARGE'"` // 解冻手续费 Openfreezecharge float64 `json:"openfreezecharge" xorm:"'OPENFREEZECHARGE'"` // 开仓冻结手续费(先建后平操作,需要记录) Closefreezecharge float64 `json:"closefreezecharge" xorm:"'CLOSEFREEZECHARGE'"` // 平仓冻结手续费(先建后平操作,需要记录) Openunfreezecharge float64 `json:"openunfreezecharge" xorm:"'OPENUNFREEZECHARGE'"` // 开仓解冻手续费(先建后平操作,需要记录) Closeunfreezecharge float64 `json:"closeunfreezecharge" xorm:"'CLOSEUNFREEZECHARGE'"` // 平仓解冻手续费(先建后平操作,需要记录) Validtype int64 `json:"validtype" xorm:"'VALIDTYPE'" binding:"required"` // 有效类型 - 1当日有效 2本周有效 3指定日期有效 4一直有效 5指定时间有效 Validtime time.Time `json:"validtime" xorm:"'VALIDTIME'"` // 有效期限 Volumetype int64 `json:"volumetype" xorm:"'VOLUMETYPE'"` // 当时间有效类型为 “立即执行否则取消 IOC” 时,需要此项 - 0:任意量 1:最小量(暂时不支持) 2:全部量 Operatetype int64 `json:"operatetype" xorm:"'OPERATETYPE'" binding:"required"` // 操作类型 - 1:正常下单 2:斩仓 3:转单 4:结算撤单 5:系统卖出(适用于先平后建的卖出) 6:行情源报价 7:(结算)到期强平 8:(结算)协议转让 9:系统对冲单 10:(结算)到期无效 11:交割协议转让 12:交割协议平仓 13:交割成交(所有权) 14:管理端强行平仓 15:管理端协议转让 Ordertime time.Time `json:"ordertime" xorm:"'ORDERTIME'" binding:"required"` // 委托时间 Orderstatus int64 `json:"orderstatus" xorm:"'ORDERSTATUS'"` // 委托状态 - 1: 委托请求 2:待冻结 3:委托成功 4: 委托失败 5:配对成功 6: 已撤销 7:部分成交 8:已成交 9:部成部撤 10:成交失败 11:已拒绝 12:经过摘牌(先摘后挂专用-先摘后挂已摘过) 13:冻结成功(通道交易专用) 14:通道已撤 15:通道部成部撤 16:成交失败违约(荷兰式竞拍专用) Listingselecttype int64 `json:"listingselecttype" xorm:"'LISTINGSELECTTYPE'"` // 挂牌点选类型 - 1:挂牌 2:摘牌 3:先摘后挂 Delistingtype int64 `json:"delistingtype" xorm:"'DELISTINGTYPE'"` // 摘牌类型 - 1:价格最优 2:点选成交 // 关联字段 GoodsCode string `json:"goodscode" xorm:"GOODSCODE"` // 商品代码 GoodsName string `json:"goodsname" xorm:"GOODSNAME"` // 商品名称 Marketname string `json:"marketname" xorm:"'MARKETNAME'"` // 市场名称 TradeMode uint32 `json:"trademode" xorm:"'TRADEMODE'"` // 交易模式 // 计算字段 Enableqty int64 `json:"enableqty" xorm:"ENABLEQTY"` // 可用数量, 委托数量 - 成交数量 - 撤单数量 } // QueryTradeOrderDetail 委托单查询请求(合约市场) // @Summary 委托单查询请求(合约市场) // @Produce json // @Security ApiKeyAuth // @Param accountID query string true "资金账户 - 格式:1,2,3" // @Param tradeMode query string false "交易模式 - 格式:1,2,3" // @Param orderStatus query string false "委托状态 - 格式:1,2,3" // @Param orderID query int false "委托单号" // @Success 200 {object} QueryTradeOrderDetailRsp // @Failure 500 {object} app.Response // @Router /Order/QueryTradeOrderDetail [get] // @Tags 通用单据 // 参考通用查询:SearchTradeOrderDetail func QueryTradeOrderDetail(c *gin.Context) { appG := app.Gin{C: c} // 获取请求参数 var req QueryTradeOrderDetailReq if err := appG.C.ShouldBindQuery(&req); err != nil { logger.GetLogger().Errorf("QueryTradeOrderDetail failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil) return } datas := make([]QueryTradeOrderDetailRsp, 0) engine := db.GetEngine() s := engine.Table("TRADE_ORDERDETAIL"). Join("LEFT", "GOODS", "GOODS.GOODSID = TRADE_ORDERDETAIL.GOODSID"). Join("LEFT", "MARKET", "MARKET.MARKETID = TRADE_ORDERDETAIL.MARKETID"). Select(`TRADE_ORDERDETAIL.*, TRADE_ORDERDETAIL.ORDERPRICE - TRADE_ORDERDETAIL.TRADEQTY - TRADE_ORDERDETAIL.CANCELQTY as ENABLEQTY, GOODS.GOODSCODE, GOODS.GOODSNAME, MARKET.MARKETNAME, MARKET.TRADEMODE`). Where(fmt.Sprintf(`TRADE_ORDERDETAIL.ORDERSRC != 10 and TRADE_ORDERDETAIL.ACCOUNTID in (%s)`, req.AccountID)). Desc("TRADE_ORDERDETAIL.ORDERTIME") if len(req.OrderStatus) > 0 { s = s.And(fmt.Sprintf(`TRADE_ORDERDETAIL.ORDERSTATUS in (%s)`, req.OrderStatus)) } if len(req.TradeMode) > 0 { s = s.And(fmt.Sprintf(`TRADE_ORDERDETAIL.TRADEMODE in (%s)`, req.TradeMode)) } if req.OrderID > 0 { s = s.And("TRADE_ORDERDETAIL.ORDERID = ?", req.OrderID) } if err := s.Find(&datas); err != nil { // 查询失败 logger.GetLogger().Errorf("QueryTradeOrderDetail failed: %s", err.Error()) appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil) return } // 查询成功 logger.GetLogger().Infof("QueryTradeOrderDetail successed: %v", datas) appG.Response(http.StatusOK, e.SUCCESS, datas) }