order.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. package order
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "mtp2_if/db"
  6. "mtp2_if/global/app"
  7. "mtp2_if/global/e"
  8. "mtp2_if/logger"
  9. "mtp2_if/models"
  10. "net/http"
  11. "time"
  12. "github.com/gin-gonic/gin"
  13. )
  14. // QueryTradePositionReq 持仓汇总查询请求参数(合约市场)
  15. type QueryTradePositionReq struct {
  16. AccountID string `form:"accountID" binding:"required"`
  17. TradeMode string `form:"tradeMode"`
  18. }
  19. // QueryTradePositionRsp 持仓汇总查询返回模型(合约市场)
  20. type QueryTradePositionRsp struct {
  21. AccountID uint64 `json:"accountid" xorm:"'ACCOUNTID'"` // 资金账户
  22. BuyOrSell int64 `json:"buyorsell" xorm:"'BUYORSELL'" ` // 方向 - 0:买 1:卖
  23. GoodsCode string `json:"goodscode" xorm:"GOODSCODE"` // 商品代码
  24. GoodsName string `json:"goodsname" xorm:"GOODSNAME"` // 商品名称
  25. AgreeUnit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位
  26. CurrencyID int64 `json:"currencyid" xorm:"'CURRENCYID'"` // 报价货币ID
  27. GoodUnitID int64 `json:"goodunitid" xorm:"'GOODUNITID'"` // 报价单位ID
  28. Goodunit string `json:"goodunit" xorm:"'GOODUNIT'"` // 报价单位
  29. DecimalPlace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位
  30. MarketID int64 `json:"marketid" xorm:"'MARKETID'"` // 所属市场ID
  31. TradeMode uint32 `json:"trademode" xorm:"'TRADEMODE'"` // 交易模式
  32. PositionQTY uint64 `json:"positionqty" xorm:"'POSITIONQTY'"` // 期初持仓数量
  33. HolderAmount float64 `json:"holderamount" xorm:"'HOLDERAMOUNT'"` // 期初持仓总金额[商品币种]
  34. CurPositionQTY uint64 `json:"curpositionqty" xorm:"'CURPOSITIONQTY'"` // 当前持仓总数量
  35. CurHolderAmount float64 `json:"curholderamount" xorm:"'CURHOLDERAMOUNT'"` // 当前持仓总金额[商品币种]
  36. FrozenQTY uint64 `json:"frozenqty" xorm:"'FROZENQTY'"` // 持仓冻结数量
  37. OtherFrozenQTY uint64 `json:"otherfrozenqty" xorm:"'OTHERFROZENQTY'"` // 持仓其他冻结数量(交割冻结)
  38. OpenReqQTY uint64 `json:"openreqqty" xorm:"'OPENREQQTY'"` // 开仓申请数量(用于比较最大持仓数量)
  39. OpenTotalQTY uint64 `json:"opentotalqty" xorm:"'OPENTOTALQTY'"` // 开仓总数量
  40. CloseTotalQTY uint64 `json:"closetotalqty" xorm:"'CLOSETOTALQTY'"` // 平仓总数量
  41. TNQTY uint64 `json:"tnqty" xorm:"'TNQTY'"` // T+N冻结总量
  42. TNUsedQTY uint64 `json:"tnusedqty" xorm:"'TNUSEDQTY'"` // T+N使用量(可以使用T+N的冻结数量)
  43. CurTDPosition uint64 `json:"curtdposition" xorm:"'CURTDPOSITION'"` // 期末今日头寸
  44. FreTDPosition uint64 `json:"fretdposition" xorm:"'FRETDPOSITION'"` // 冻结今日头寸
  45. EnableQTY uint64 `json:"enableqty" xorm:"'ENABLEQTY'"` // 可用量
  46. }
  47. // QueryTradePosition 持仓汇总查询(合约市场)
  48. // @Summary 持仓汇总查询(合约市场)
  49. // @Produce json
  50. // @Security ApiKeyAuth
  51. // @Param accountID query string true "资金账户 - 格式:1,2,3"
  52. // @Param tradeMode query string false "交易模式 - 格式:1,2,3"
  53. // @Success 200 {object} QueryTradePositionRsp
  54. // @Failure 500 {object} app.Response
  55. // @Router /Order/QueryTradePosition [get]
  56. // @Tags 通用单据
  57. // 参考通用查询:SearchTradePositionDetail
  58. func QueryTradePosition(c *gin.Context) {
  59. appG := app.Gin{C: c}
  60. // 获取请求参数
  61. var req QueryTradePositionReq
  62. if err := appG.C.ShouldBindQuery(&req); err != nil {
  63. logger.GetLogger().Errorf("QueryTradePosition failed: %s", err.Error())
  64. appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
  65. return
  66. }
  67. // 查询数据
  68. type tradePosition struct {
  69. models.Tradeposition `xorm:"extends"`
  70. Goodscode string `json:"goodscode" xorm:"'GOODSCODE'"` // 商品代码(内部)
  71. Goodsname string `json:"goodsname" xorm:"'GOODSNAME'"` // 商品名称
  72. Currencyid int64 `json:"currencyid" xorm:"'CURRENCYID'"` // 报价货币ID
  73. Goodunitid int64 `json:"goodunitid" xorm:"'GOODUNITID'"` // 报价单位ID
  74. Goodunit string `json:"goodunit" xorm:"'GOODUNIT'"` // 报价单位
  75. Agreeunit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位
  76. Decimalplace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位
  77. Marketid uint32 `json:"marketid" xorm:"'MARKETID'"` // 市场ID
  78. Trademode uint32 `json:"trademode" xorm:"'TRADEMODE'"` // 交易模式
  79. }
  80. datas := make([]tradePosition, 0)
  81. engine := db.GetEngine()
  82. // ORACLE好像在JOIN里不支持别名功能(在XORM中)
  83. s := engine.Table("TRADEPOSITION").
  84. Join("LEFT", "GOODS", "TRADEPOSITION.GOODSID = GOODS.GOODSID").
  85. Join("LEFT", "MARKET", "GOODS.MARKETID = MARKET.MARKETID").
  86. Join("LEFT", "ENUMDICITEM", "GOODS.GOODUNITID = ENUMDICITEM.ENUMITEMNAME and ENUMDICITEM.ENUMDICCODE = 'goodsunit'").
  87. Select("TRADEPOSITION.*, GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.CURRENCYID, GOODS.GOODUNITID, ENUMDICITEM.ENUMDICNAME as GOODUNIT, GOODS.AGREEUNIT, GOODS.DECIMALPLACE, MARKET.MARKETID, MARKET.TRADEMODE").
  88. Where(fmt.Sprintf(`TRADEPOSITION.ACCOUNTID in (%s)`, req.AccountID))
  89. if len(req.TradeMode) > 0 {
  90. s = s.And(fmt.Sprintf(`MARKET.TRADEMODE in (%s)`, req.TradeMode))
  91. }
  92. if err := s.Find(&datas); err != nil {
  93. // 查询失败
  94. logger.GetLogger().Errorf("QueryTradePosition failed: %s", err.Error())
  95. appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
  96. return
  97. }
  98. // 构建返回数据
  99. rst := make([]QueryTradePositionRsp, 0)
  100. for _, v := range datas {
  101. // 构建买方向持仓汇总
  102. if v.Buycurpositionqty > 0 {
  103. var tradePosition QueryTradePositionRsp
  104. // 反射数据
  105. // struct -> json
  106. if jsonBytes, err := json.Marshal(v); err == nil {
  107. // json -> struct
  108. json.Unmarshal(jsonBytes, &tradePosition)
  109. tradePosition.BuyOrSell = 0
  110. tradePosition.PositionQTY = v.Buypositionqty
  111. tradePosition.HolderAmount = v.Buyholderamount
  112. tradePosition.CurPositionQTY = v.Buycurpositionqty
  113. tradePosition.CurHolderAmount = v.Buycurholderamount
  114. tradePosition.FrozenQTY = v.Buyfrozenqty
  115. tradePosition.OtherFrozenQTY = v.Buyotherfrozenqty
  116. tradePosition.OpenReqQTY = v.Buyopenreqqty
  117. tradePosition.OpenTotalQTY = v.Buyopentotalqty
  118. tradePosition.CloseTotalQTY = v.Buyclosetotalqty
  119. tradePosition.TNQTY = v.Buytnqty
  120. tradePosition.TNUsedQTY = v.Buytnusedqty
  121. tradePosition.CurTDPosition = v.Buycurtdposition
  122. tradePosition.FreTDPosition = v.Buyfretdposition
  123. tradePosition.EnableQTY = v.Buycurpositionqty - v.Buyfrozenqty - v.Buyotherfrozenqty
  124. rst = append(rst, tradePosition)
  125. }
  126. }
  127. // 构建卖方向持仓汇总
  128. if v.Tradeproperty != 2 && v.Sellcurpositionqty > 0 {
  129. var tradePosition QueryTradePositionRsp
  130. // 反射数据
  131. // struct -> json
  132. if jsonBytes, err := json.Marshal(v); err == nil {
  133. // json -> struct
  134. json.Unmarshal(jsonBytes, &tradePosition)
  135. tradePosition.BuyOrSell = 1
  136. tradePosition.PositionQTY = v.Sellpositionqty
  137. tradePosition.HolderAmount = v.Sellholderamount
  138. tradePosition.CurPositionQTY = v.Sellcurpositionqty
  139. tradePosition.CurHolderAmount = v.Sellcurholderamount
  140. tradePosition.FrozenQTY = v.Sellfrozenqty
  141. tradePosition.OtherFrozenQTY = v.Sellotherfrozenqty
  142. tradePosition.OpenReqQTY = v.Sellopenreqqty
  143. tradePosition.OpenTotalQTY = v.Sellopentotalqty
  144. tradePosition.CloseTotalQTY = v.Sellclosetotalqty
  145. tradePosition.TNQTY = v.Selltnqty
  146. tradePosition.TNUsedQTY = v.Selltnusedqty
  147. tradePosition.CurTDPosition = v.Sellcurtdposition
  148. tradePosition.FreTDPosition = v.Sellfretdposition
  149. tradePosition.EnableQTY = v.Sellcurpositionqty - v.Sellfrozenqty - v.Sellotherfrozenqty
  150. rst = append(rst, tradePosition)
  151. }
  152. }
  153. }
  154. // 查询成功
  155. logger.GetLogger().Infof("QueryTradePosition successed: %v", rst)
  156. appG.Response(http.StatusOK, e.SUCCESS, rst)
  157. }
  158. // QueryTradeOrderDetailReq 委托单查询请求参数(合约市场)
  159. type QueryTradeOrderDetailReq struct {
  160. AccountID string `form:"accountID" binding:"required"`
  161. OrderStatus string `form:"orderStatus"`
  162. TradeMode string `form:"tradeMode"`
  163. OrderID int `form:"orderID"`
  164. }
  165. // QueryTradeOrderDetailRsp 委托单查询返回模型(合约市场)
  166. type QueryTradeOrderDetailRsp struct {
  167. // 委托单字段
  168. Orderid int64 `json:"orderid" xorm:"'ORDERID'" binding:"required"` // 委托单号(100+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx)
  169. Tradedate string `json:"tradedate" xorm:"'TRADEDATE'" binding:"required"` // 交易日(yyyyMMdd)
  170. Buildtype int64 `json:"buildtype" xorm:"'BUILDTYPE'" binding:"required"` // 委托单据类型 - 1:建仓 2:平仓 3:先平后建
  171. Preorderid int64 `json:"preorderid" xorm:"'PREORDERID'"` // 关联预埋单号(止盈止损单时填写)
  172. Cancelorderid int64 `json:"cancelorderid" xorm:"'CANCELORDERID'"` // 撤单单号(撤单时填写)
  173. Relatedid int64 `json:"relatedid" xorm:"'RELATEDID'"` // 关联单号(交割单)
  174. Marketid int64 `json:"marketid" xorm:"'MARKETID'" binding:"required"` // 市场ID
  175. Goodsid int64 `json:"goodsid" xorm:"'GOODSID'" binding:"required"` // 商品ID
  176. Accountid int64 `json:"accountid" xorm:"'ACCOUNTID'" binding:"required"` // 账户ID[报价币种]
  177. Buyorsell int64 `json:"buyorsell" xorm:"'BUYORSELL'" binding:"required"` // 买卖 - 0:买 1:卖
  178. Pricemode int64 `json:"pricemode" xorm:"'PRICEMODE'" binding:"required"` // 取价方式 - 1:市价 2: 限价
  179. Orderprice float64 `json:"orderprice" xorm:"'ORDERPRICE'"` // 委托价格
  180. Orderqty int64 `json:"orderqty" xorm:"'ORDERQTY'" binding:"required"` // 委托数量
  181. Tradeqty int64 `json:"tradeqty" xorm:"'TRADEQTY'"` // 成交数量
  182. Cancelqty int64 `json:"cancelqty" xorm:"'CANCELQTY'"` // 撤单数量
  183. Openqty int64 `json:"openqty" xorm:"'OPENQTY'"` // 开仓数量(先建后平操作,需要记录)
  184. Closeqty int64 `json:"closeqty" xorm:"'CLOSEQTY'"` // 平仓数量(先建后平操作 需要记录)
  185. Opentradeqty int64 `json:"opentradeqty" xorm:"'OPENTRADEQTY'"` // 开仓成交数量(先建后平操作,需要记录)
  186. Closetradeqty int64 `json:"closetradeqty" xorm:"'CLOSETRADEQTY'"` // 平仓成交数量(先建后平操作,需要记录)
  187. Freezemargin float64 `json:"freezemargin" xorm:"'FREEZEMARGIN'"` // 冻结保证金(冻结交易金额)
  188. Unfreezemargin float64 `json:"unfreezemargin" xorm:"'UNFREEZEMARGIN'"` // 解冻保证金
  189. Freezecharge float64 `json:"freezecharge" xorm:"'FREEZECHARGE'"` // 冻结手续费
  190. Unfreezecharge float64 `json:"unfreezecharge" xorm:"'UNFREEZECHARGE'"` // 解冻手续费
  191. Openfreezecharge float64 `json:"openfreezecharge" xorm:"'OPENFREEZECHARGE'"` // 开仓冻结手续费(先建后平操作,需要记录)
  192. Closefreezecharge float64 `json:"closefreezecharge" xorm:"'CLOSEFREEZECHARGE'"` // 平仓冻结手续费(先建后平操作,需要记录)
  193. Openunfreezecharge float64 `json:"openunfreezecharge" xorm:"'OPENUNFREEZECHARGE'"` // 开仓解冻手续费(先建后平操作,需要记录)
  194. Closeunfreezecharge float64 `json:"closeunfreezecharge" xorm:"'CLOSEUNFREEZECHARGE'"` // 平仓解冻手续费(先建后平操作,需要记录)
  195. Validtype int64 `json:"validtype" xorm:"'VALIDTYPE'" binding:"required"` // 有效类型 - 1当日有效 2本周有效 3指定日期有效 4一直有效 5指定时间有效
  196. Validtime time.Time `json:"validtime" xorm:"'VALIDTIME'"` // 有效期限
  197. Volumetype int64 `json:"volumetype" xorm:"'VOLUMETYPE'"` // 当时间有效类型为 “立即执行否则取消 IOC” 时,需要此项 - 0:任意量 1:最小量(暂时不支持) 2:全部量
  198. Operatetype int64 `json:"operatetype" xorm:"'OPERATETYPE'" binding:"required"` // 操作类型 - 1:正常下单 2:斩仓 3:转单 4:结算撤单 5:系统卖出(适用于先平后建的卖出) 6:行情源报价 7:(结算)到期强平 8:(结算)协议转让 9:系统对冲单 10:(结算)到期无效 11:交割协议转让 12:交割协议平仓 13:交割成交(所有权) 14:管理端强行平仓 15:管理端协议转让
  199. Ordertime time.Time `json:"ordertime" xorm:"'ORDERTIME'" binding:"required"` // 委托时间
  200. Orderstatus int64 `json:"orderstatus" xorm:"'ORDERSTATUS'"` // 委托状态 - 1: 委托请求 2:待冻结 3:委托成功 4: 委托失败 5:配对成功 6: 已撤销 7:部分成交 8:已成交 9:部成部撤 10:成交失败 11:已拒绝 12:经过摘牌(先摘后挂专用-先摘后挂已摘过) 13:冻结成功(通道交易专用) 14:通道已撤 15:通道部成部撤 16:成交失败违约(荷兰式竞拍专用)
  201. Listingselecttype int64 `json:"listingselecttype" xorm:"'LISTINGSELECTTYPE'"` // 挂牌点选类型 - 1:挂牌 2:摘牌 3:先摘后挂
  202. Delistingtype int64 `json:"delistingtype" xorm:"'DELISTINGTYPE'"` // 摘牌类型 - 1:价格最优 2:点选成交
  203. // 关联字段
  204. GoodsCode string `json:"goodscode" xorm:"GOODSCODE"` // 商品代码
  205. GoodsName string `json:"goodsname" xorm:"GOODSNAME"` // 商品名称
  206. Marketname string `json:"marketname" xorm:"'MARKETNAME'"` // 市场名称
  207. TradeMode uint32 `json:"trademode" xorm:"'TRADEMODE'"` // 交易模式
  208. // 计算字段
  209. Enableqty int64 `json:"enableqty" xorm:"ENABLEQTY"` // 可用数量, 委托数量 - 成交数量 - 撤单数量
  210. }
  211. // QueryTradeOrderDetail 委托单查询请求(合约市场)
  212. // @Summary 委托单查询请求(合约市场)
  213. // @Produce json
  214. // @Security ApiKeyAuth
  215. // @Param accountID query string true "资金账户 - 格式:1,2,3"
  216. // @Param tradeMode query string false "交易模式 - 格式:1,2,3"
  217. // @Param orderStatus query string false "委托状态 - 格式:1,2,3"
  218. // @Param orderID query int false "委托单号"
  219. // @Success 200 {object} QueryTradeOrderDetailRsp
  220. // @Failure 500 {object} app.Response
  221. // @Router /Order/QueryTradeOrderDetail [get]
  222. // @Tags 通用单据
  223. // 参考通用查询:SearchTradeOrderDetail
  224. func QueryTradeOrderDetail(c *gin.Context) {
  225. appG := app.Gin{C: c}
  226. // 获取请求参数
  227. var req QueryTradeOrderDetailReq
  228. if err := appG.C.ShouldBindQuery(&req); err != nil {
  229. logger.GetLogger().Errorf("QueryTradeOrderDetail failed: %s", err.Error())
  230. appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
  231. return
  232. }
  233. datas := make([]QueryTradeOrderDetailRsp, 0)
  234. engine := db.GetEngine()
  235. s := engine.Table("TRADE_ORDERDETAIL").
  236. Join("LEFT", "GOODS", "GOODS.GOODSID = TRADE_ORDERDETAIL.GOODSID").
  237. Join("LEFT", "MARKET", "MARKET.MARKETID = TRADE_ORDERDETAIL.MARKETID").
  238. Select(`TRADE_ORDERDETAIL.*, TRADE_ORDERDETAIL.ORDERPRICE - TRADE_ORDERDETAIL.TRADEQTY - TRADE_ORDERDETAIL.CANCELQTY as ENABLEQTY,
  239. GOODS.GOODSCODE, GOODS.GOODSNAME, MARKET.MARKETNAME, MARKET.TRADEMODE`).
  240. Where(fmt.Sprintf(`TRADE_ORDERDETAIL.ORDERSRC != 10 and TRADE_ORDERDETAIL.ACCOUNTID in (%s)`, req.AccountID)).
  241. Desc("TRADE_ORDERDETAIL.ORDERTIME")
  242. if len(req.OrderStatus) > 0 {
  243. s = s.And(fmt.Sprintf(`TRADE_ORDERDETAIL.ORDERSTATUS in (%s)`, req.OrderStatus))
  244. }
  245. if len(req.TradeMode) > 0 {
  246. s = s.And(fmt.Sprintf(`TRADE_ORDERDETAIL.TRADEMODE in (%s)`, req.TradeMode))
  247. }
  248. if req.OrderID > 0 {
  249. s = s.And("TRADE_ORDERDETAIL.ORDERID = ?", req.OrderID)
  250. }
  251. if err := s.Find(&datas); err != nil {
  252. // 查询失败
  253. logger.GetLogger().Errorf("QueryTradeOrderDetail failed: %s", err.Error())
  254. appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
  255. return
  256. }
  257. // 查询成功
  258. logger.GetLogger().Infof("QueryTradeOrderDetail successed: %v", datas)
  259. appG.Response(http.StatusOK, e.SUCCESS, datas)
  260. }