order.go 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. package order
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "math"
  6. "mtp2_if/db"
  7. "mtp2_if/global/app"
  8. "mtp2_if/global/e"
  9. "mtp2_if/logger"
  10. "mtp2_if/models"
  11. "mtp2_if/mtpcache"
  12. "mtp2_if/utils"
  13. "net/http"
  14. "strconv"
  15. "time"
  16. "github.com/gin-gonic/gin"
  17. )
  18. type QtyCovert struct {
  19. QTYDECIMALPLACE int32
  20. }
  21. // CovertQty 根据数位 放大缩小
  22. func (r *QtyCovert) CovertQty(v int64) float64 {
  23. return float64(v) / math.Pow10(int(r.QTYDECIMALPLACE))
  24. }
  25. // QueryTradePositionReq 持仓汇总查询请求参数(合约市场)
  26. type QueryTradePositionReq struct {
  27. AccountID string `form:"accountID" binding:"required"`
  28. TradeMode string `form:"tradeMode"`
  29. }
  30. // QueryTradePositionRsp 持仓汇总查询返回模型(合约市场)
  31. type QueryTradePositionRsp struct {
  32. AccountID int64 `json:"accountid" xorm:"'ACCOUNTID'"` // 资金账户
  33. BuyOrSell int64 `json:"buyorsell" xorm:"'BUYORSELL'" ` // 方向 - 0:买 1:卖
  34. Goodsid int32 `json:"goodsid" xorm:"'GOODSID'" binding:"required"` // 商品Id
  35. GoodsCode string `json:"goodscode" xorm:"GOODSCODE"` // 商品代码
  36. GoodsName string `json:"goodsname" xorm:"GOODSNAME"` // 商品名称
  37. AgreeUnit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位
  38. CurrencyID int64 `json:"currencyid" xorm:"'CURRENCYID'"` // 报价货币ID
  39. GoodUnitID int64 `json:"goodunitid" xorm:"'GOODUNITID'"` // 报价单位ID
  40. Goodunit string `json:"goodunit" xorm:"'GOODUNIT'"` // 报价单位
  41. DecimalPlace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位
  42. MarketID int64 `json:"marketid" xorm:"'MARKETID'"` // 所属市场ID
  43. TradeMode int32 `json:"trademode" xorm:"'TRADEMODE'"` // 交易模式
  44. PositionQTY float64 `json:"positionqty" xorm:"'POSITIONQTY'"` // 期初持仓数量
  45. HolderAmount float64 `json:"holderamount" xorm:"'HOLDERAMOUNT'"` // 期初持仓总金额[商品币种]
  46. CurPositionQTY float64 `json:"curpositionqty" xorm:"'CURPOSITIONQTY'"` // 当前持仓总数量
  47. CurHolderAmount float64 `json:"curholderamount" xorm:"'CURHOLDERAMOUNT'"` // 当前持仓总金额[商品币种]
  48. FrozenQTY float64 `json:"frozenqty" xorm:"'FROZENQTY'"` // 持仓冻结数量
  49. OtherFrozenQTY float64 `json:"otherfrozenqty" xorm:"'OTHERFROZENQTY'"` // 持仓其他冻结数量(交割冻结)
  50. OpenReqQTY float64 `json:"openreqqty" xorm:"'OPENREQQTY'"` // 开仓申请数量(用于比较最大持仓数量)
  51. OpenTotalQTY float64 `json:"opentotalqty" xorm:"'OPENTOTALQTY'"` // 开仓总数量
  52. CloseTotalQTY float64 `json:"closetotalqty" xorm:"'CLOSETOTALQTY'"` // 平仓总数量
  53. TNQTY float64 `json:"tnqty" xorm:"'TNQTY'"` // T+N冻结总量
  54. TNUsedQTY float64 `json:"tnusedqty" xorm:"'TNUSEDQTY'"` // T+N使用量(可以使用T+N的冻结数量)
  55. CurTDPosition float64 `json:"curtdposition" xorm:"'CURTDPOSITION'"` // 期末今日头寸
  56. FreTDPosition float64 `json:"fretdposition" xorm:"'FRETDPOSITION'"` // 冻结今日头寸
  57. EnableQTY float64 `json:"enableqty" xorm:"'ENABLEQTY'"` // 可用量
  58. AveragePrice float64 `json:"averageprice" xorm:"AVERAGEPRICE"` // 持仓均价
  59. Usedmargin float64 `json:"usedmargin" xorm:"'USEDMARGIN'"` // 占用保证金[商品币种]
  60. QTYDECIMALPLACE int32 `json:"qtydecimalplace"` // 成交量小数位
  61. }
  62. // QueryTradePosition 持仓汇总查询(合约市场)
  63. // @Summary 持仓汇总查询(合约市场)
  64. // @Produce json
  65. // @Security ApiKeyAuth
  66. // @Param accountID query string true "资金账户 - 格式:1,2,3"
  67. // @Param tradeMode query string false "交易模式 - 格式:1,2,3"
  68. // @Success 200 {object} QueryTradePositionRsp
  69. // @Failure 500 {object} app.Response
  70. // @Router /Order/QueryTradePosition [get]
  71. // @Tags 通用单据
  72. // 参考通用查询:SearchTradePositionDetail
  73. func QueryTradePosition(c *gin.Context) {
  74. appG := app.Gin{C: c}
  75. // 获取请求参数
  76. var req QueryTradePositionReq
  77. if err := appG.C.ShouldBindQuery(&req); err != nil {
  78. logger.GetLogger().Errorf("QueryTradePosition failed: %s", err.Error())
  79. appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
  80. return
  81. }
  82. // 查询数据
  83. type tradePosition struct {
  84. models.Tradeposition `xorm:"extends"`
  85. Goodscode string `json:"goodscode" xorm:"'GOODSCODE'"` // 商品代码(内部)
  86. Goodsname string `json:"goodsname" xorm:"'GOODSNAME'"` // 商品名称
  87. Currencyid int64 `json:"currencyid" xorm:"'CURRENCYID'"` // 报价货币ID
  88. Goodunitid int64 `json:"goodunitid" xorm:"'GOODUNITID'"` // 报价单位ID
  89. Goodunit string `json:"goodunit" xorm:"'GOODUNIT'"` // 报价单位
  90. Agreeunit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位
  91. Decimalplace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位
  92. Marketid int32 `json:"marketid" xorm:"'MARKETID'"` // 市场ID
  93. Trademode int32 `json:"trademode" xorm:"'TRADEMODE'"` // 交易模式
  94. QTYDECIMALPLACE int32 `json:"qtydecimalplace" xorm:"'QTYDECIMALPLACE'"` // 成交量小数位
  95. }
  96. datas := make([]tradePosition, 0)
  97. engine := db.GetEngine()
  98. // ORACLE好像在JOIN里不支持别名功能(在XORM中)
  99. s := engine.Table("TRADEPOSITION").
  100. Join("LEFT", "GOODS", "TRADEPOSITION.GOODSID = GOODS.GOODSID").
  101. Join("LEFT", "MARKET", "GOODS.MARKETID = MARKET.MARKETID").
  102. Join("LEFT", "ENUMDICITEM", "GOODS.GOODUNITID = ENUMDICITEM.ENUMITEMNAME and ENUMDICITEM.ENUMDICCODE = 'goodsunit'").
  103. Select("TRADEPOSITION.*, GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.CURRENCYID, GOODS.GOODUNITID,GOODS.QTYDECIMALPLACE, ENUMDICITEM.ENUMDICNAME as GOODUNIT, GOODS.AGREEUNIT, GOODS.DECIMALPLACE, MARKET.MARKETID, MARKET.TRADEMODE").
  104. Where(fmt.Sprintf(`TRADEPOSITION.ACCOUNTID in (%s)`, req.AccountID))
  105. if len(req.TradeMode) > 0 {
  106. s = s.And(fmt.Sprintf(`MARKET.TRADEMODE in (%s)`, req.TradeMode))
  107. }
  108. if err := s.Find(&datas); err != nil {
  109. // 查询失败
  110. logger.GetLogger().Errorf("QueryTradePosition failed: %s", err.Error())
  111. appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
  112. return
  113. }
  114. // 构建返回数据
  115. rst := make([]QueryTradePositionRsp, 0)
  116. for _, v := range datas {
  117. // 构建买方向持仓汇总
  118. if v.Buycurpositionqty > 0 {
  119. var tradePosition QueryTradePositionRsp
  120. // 反射数据
  121. // struct -> json
  122. if jsonBytes, err := json.Marshal(v); err == nil {
  123. c := QtyCovert{QTYDECIMALPLACE: v.QTYDECIMALPLACE}
  124. // json -> struct
  125. json.Unmarshal(jsonBytes, &tradePosition)
  126. tradePosition.BuyOrSell = 0
  127. tradePosition.PositionQTY = c.CovertQty(v.Buypositionqty)
  128. tradePosition.HolderAmount = v.Buyholderamount
  129. tradePosition.CurPositionQTY = c.CovertQty(v.Buycurpositionqty)
  130. tradePosition.CurHolderAmount = v.Buycurholderamount
  131. tradePosition.FrozenQTY = c.CovertQty(v.Buyfrozenqty)
  132. tradePosition.OtherFrozenQTY = c.CovertQty(v.Buyotherfrozenqty)
  133. tradePosition.OpenReqQTY = c.CovertQty(v.Buyopenreqqty)
  134. tradePosition.OpenTotalQTY = c.CovertQty(v.Buyopentotalqty)
  135. tradePosition.CloseTotalQTY = c.CovertQty(v.Buyclosetotalqty)
  136. tradePosition.TNQTY = c.CovertQty(v.Buytnqty)
  137. tradePosition.TNUsedQTY = c.CovertQty(v.Buytnusedqty)
  138. tradePosition.CurTDPosition = c.CovertQty(v.Buycurtdposition)
  139. tradePosition.FreTDPosition = c.CovertQty(v.Buyfretdposition)
  140. tradePosition.EnableQTY = c.CovertQty(v.Buycurpositionqty - v.Buyfrozenqty - v.Buyotherfrozenqty)
  141. // 计算持仓均价
  142. averagePrice := tradePosition.CurHolderAmount / float64(tradePosition.CurPositionQTY) / tradePosition.AgreeUnit
  143. tradePosition.AveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(averagePrice, int(v.Decimalplace)), 64)
  144. rst = append(rst, tradePosition)
  145. }
  146. }
  147. // 构建卖方向持仓汇总
  148. if v.Tradeproperty != 2 && v.Sellcurpositionqty > 0 {
  149. var tradePosition QueryTradePositionRsp
  150. // 反射数据
  151. // struct -> json
  152. if jsonBytes, err := json.Marshal(v); err == nil {
  153. c := QtyCovert{QTYDECIMALPLACE: v.QTYDECIMALPLACE}
  154. // json -> struct
  155. json.Unmarshal(jsonBytes, &tradePosition)
  156. tradePosition.BuyOrSell = 1
  157. tradePosition.PositionQTY = c.CovertQty(v.Sellpositionqty)
  158. tradePosition.HolderAmount = v.Sellholderamount
  159. tradePosition.CurPositionQTY = c.CovertQty(v.Sellcurpositionqty)
  160. tradePosition.CurHolderAmount = v.Sellcurholderamount
  161. tradePosition.FrozenQTY = c.CovertQty(v.Sellfrozenqty)
  162. tradePosition.OtherFrozenQTY = c.CovertQty(v.Sellotherfrozenqty)
  163. tradePosition.OpenReqQTY = c.CovertQty(v.Sellopenreqqty)
  164. tradePosition.OpenTotalQTY = c.CovertQty(v.Sellopentotalqty)
  165. tradePosition.CloseTotalQTY = c.CovertQty(v.Sellclosetotalqty)
  166. tradePosition.TNQTY = c.CovertQty(v.Selltnqty)
  167. tradePosition.TNUsedQTY = c.CovertQty(v.Selltnusedqty)
  168. tradePosition.CurTDPosition = c.CovertQty(v.Sellcurtdposition)
  169. tradePosition.FreTDPosition = c.CovertQty(v.Sellfretdposition)
  170. tradePosition.EnableQTY = c.CovertQty(v.Sellcurpositionqty - v.Sellfrozenqty - v.Sellotherfrozenqty)
  171. // 计算持仓均价
  172. averagePrice := tradePosition.CurHolderAmount / float64(tradePosition.CurPositionQTY) / tradePosition.AgreeUnit
  173. tradePosition.AveragePrice, _ = strconv.ParseFloat(utils.FormatFloat(averagePrice, int(v.Decimalplace)), 64)
  174. rst = append(rst, tradePosition)
  175. }
  176. }
  177. }
  178. // 查询成功
  179. logger.GetLogger().Debugln("QueryTradePosition successed: %v", rst)
  180. appG.Response(http.StatusOK, e.SUCCESS, rst)
  181. }
  182. // QueryTradeOrderDetailReq 委托单查询请求参数(合约市场)
  183. type QueryTradeOrderDetailReq struct {
  184. AccountID string `form:"accountID" binding:"required"`
  185. OrderStatus string `form:"orderStatus"`
  186. TradeMode string `form:"tradeMode"`
  187. OrderID int `form:"orderID"`
  188. }
  189. // QueryTradeOrderDetailRsp 委托单查询返回模型(合约市场)
  190. type QueryTradeOrderDetailRsp struct {
  191. Orderid string `json:"orderid" xorm:"'ORDERID'"` // 委托单号(100+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx)
  192. Tradedate string `json:"tradedate" xorm:"'TRADEDATE'" binding:"required"` // 交易日(yyyyMMdd)
  193. Buildtype int64 `json:"buildtype" xorm:"'BUILDTYPE'" binding:"required"` // 委托单据类型 - 1:建仓 2:平仓 3:先平后建
  194. Preorderid string `json:"preorderid" xorm:"'PREORDERID'"` // 关联预埋单号(止盈止损单时填写)
  195. Cancelorderid string `json:"cancelorderid" xorm:"'CANCELORDERID'"` // 撤单单号(撤单时填写)
  196. Relatedid string `json:"relatedid" xorm:"'RELATEDID'"` // 关联单号(交割单)
  197. Marketid int64 `json:"marketid" xorm:"'MARKETID'" binding:"required"` // 市场ID
  198. Goodsid int64 `json:"goodsid" xorm:"'GOODSID'" binding:"required"` // 商品ID
  199. Accountid int64 `json:"accountid" xorm:"'ACCOUNTID'" binding:"required"` // 账户ID[报价币种]
  200. Buyorsell int64 `json:"buyorsell" xorm:"'BUYORSELL'" binding:"required"` // 买卖 - 0:买 1:卖
  201. Pricemode int64 `json:"pricemode" xorm:"'PRICEMODE'" binding:"required"` // 取价方式 - 1:市价 2: 限价
  202. Orderprice float64 `json:"orderprice" xorm:"'ORDERPRICE'"` // 委托价格
  203. Orderqty float64 `json:"orderqty" xorm:"'ORDERQTY'" binding:"required"` // 委托数量
  204. Tradeqty float64 `json:"tradeqty" xorm:"'TRADEQTY'"` // 成交数量
  205. Cancelqty float64 `json:"cancelqty" xorm:"'CANCELQTY'"` // 撤单数量
  206. Openqty float64 `json:"openqty" xorm:"'OPENQTY'"` // 开仓数量(先建后平操作,需要记录)
  207. Closeqty float64 `json:"closeqty" xorm:"'CLOSEQTY'"` // 平仓数量(先建后平操作 需要记录)
  208. Opentradeqty float64 `json:"opentradeqty" xorm:"'OPENTRADEQTY'"` // 开仓成交数量(先建后平操作,需要记录)
  209. Closetradeqty float64 `json:"closetradeqty" xorm:"'CLOSETRADEQTY'"` // 平仓成交数量(先建后平操作,需要记录)
  210. Freezemargin float64 `json:"freezemargin" xorm:"'FREEZEMARGIN'"` // 冻结保证金(冻结交易金额)
  211. Unfreezemargin float64 `json:"unfreezemargin" xorm:"'UNFREEZEMARGIN'"` // 解冻保证金
  212. Freezecharge float64 `json:"freezecharge" xorm:"'FREEZECHARGE'"` // 冻结手续费
  213. Unfreezecharge float64 `json:"unfreezecharge" xorm:"'UNFREEZECHARGE'"` // 解冻手续费
  214. Openfreezecharge float64 `json:"openfreezecharge" xorm:"'OPENFREEZECHARGE'"` // 开仓冻结手续费(先建后平操作,需要记录)
  215. Closefreezecharge float64 `json:"closefreezecharge" xorm:"'CLOSEFREEZECHARGE'"` // 平仓冻结手续费(先建后平操作,需要记录)
  216. Openunfreezecharge float64 `json:"openunfreezecharge" xorm:"'OPENUNFREEZECHARGE'"` // 开仓解冻手续费(先建后平操作,需要记录)
  217. Closeunfreezecharge float64 `json:"closeunfreezecharge" xorm:"'CLOSEUNFREEZECHARGE'"` // 平仓解冻手续费(先建后平操作,需要记录)
  218. Validtype int64 `json:"validtype" xorm:"'VALIDTYPE'" binding:"required"` // 有效类型 - 1当日有效 2本周有效 3指定日期有效 4一直有效 5指定时间有效
  219. Validtime time.Time `json:"validtime" xorm:"'VALIDTIME'"` // 有效期限
  220. Volumetype int64 `json:"volumetype" xorm:"'VOLUMETYPE'"` // 当时间有效类型为 “立即执行否则取消 IOC” 时,需要此项 - 0:任意量 1:最小量(暂时不支持) 2:全部量
  221. Operatetype int64 `json:"operatetype" xorm:"'OPERATETYPE'" binding:"required"` // 操作类型 - 1:正常下单 2:斩仓 3:转单 4:结算撤单 5:系统卖出(适用于先平后建的卖出) 6:行情源报价 7:(结算)到期强平 8:(结算)协议转让 9:系统对冲单 10:(结算)到期无效 11:交割协议转让 12:交割协议平仓 13:交割成交(所有权) 14:管理端强行平仓 15:管理端协议转让
  222. Ordertime time.Time `json:"ordertime" xorm:"'ORDERTIME'" binding:"required"` // 委托时间
  223. Orderstatus int64 `json:"orderstatus" xorm:"'ORDERSTATUS'"` // 委托状态 - 1: 委托请求 2:待冻结 3:委托成功 4: 委托失败 5:配对成功 6: 已撤销 7:部分成交 8:已成交 9:部成部撤 10:成交失败 11:已拒绝 12:经过摘牌(先摘后挂专用-先摘后挂已摘过) 13:冻结成功(通道交易专用) 14:通道已撤 15:通道部成部撤 16:成交失败违约(荷兰式竞拍专用)
  224. Listingselecttype int64 `json:"listingselecttype" xorm:"'LISTINGSELECTTYPE'"` // 挂牌点选类型 - 1:挂牌 2:摘牌 3:先摘后挂
  225. Delistingtype int64 `json:"delistingtype" xorm:"'DELISTINGTYPE'"` // 摘牌类型 - 1:价格最优 2:点选成交
  226. Ordersrc int64 `json:"ordersrc" xorm:"'ORDERSRC'"` // 委托来源 - 1:客户端 2:管理端 3:风控服务 4:交割服务 5:交易服务 6:交易日结 7:商品强平 8:管理端商品退市强平 9:交易接口 10:交割服务商被动(受托竞价) 11:预埋触发
  227. Clienttype int64 `json:"clienttype" xorm:"'CLIENTTYPE'"` // 客户端类型 - 0:保留为未填终端类型 1:PC管理端 2:PC交易端 3:手机客户端_安卓 4:网页客户端 5:微信客户端 6:手机客户端_苹果 7:网上开户客户端 8:无效终端编号 9:报价终端(中江)
  228. Operatorid int64 `json:"operatorid" xorm:"'OPERATORID'"` // 登录账号(LoginID)
  229. GOODUNITID int32 `json:"goodunitid" xorm:"'GOODUNITID'"` // 商品单位id
  230. GoodsCode string `json:"goodscode" xorm:"GOODSCODE"` // 商品代码
  231. GoodsName string `json:"goodsname" xorm:"GOODSNAME"` // 商品名称
  232. DECIMALPLACE int32 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 商品报价小数位
  233. QTYDECIMALPLACE int `json:"qtydecimalplace" xorm:"'QTYDECIMALPLACE'"` // 商品报价小数位
  234. Marketname string `json:"marketname" xorm:"'MARKETNAME'"` // 市场名称
  235. TradeMode int32 `json:"trademode" xorm:"'TRADEMODE'"` // 交易模式
  236. ENUMDICNAME string `json:"enumdicname"` // 单位名称
  237. Enableqty float64 `json:"enableqty" xorm:"ENABLEQTY"` // 可用数量 = 委托数量 - 成交数量 - 撤单数量
  238. }
  239. func (r *QueryTradeOrderDetailRsp) calc() {
  240. fCovert := func(v *float64) {
  241. *v = *v / math.Pow10(r.QTYDECIMALPLACE)
  242. }
  243. fCovert(&r.Orderqty)
  244. fCovert(&r.Tradeqty)
  245. fCovert(&r.Cancelqty)
  246. fCovert(&r.Openqty)
  247. fCovert(&r.Closeqty)
  248. fCovert(&r.Opentradeqty)
  249. fCovert(&r.Closetradeqty)
  250. fCovert(&r.Enableqty)
  251. r.ENUMDICNAME = mtpcache.GetEnumDicitemName(r.GOODUNITID)
  252. }
  253. // QueryTradeOrderDetail 委托单查询请求(合约市场)
  254. // @Summary 委托单查询请求(合约市场)
  255. // @Produce json
  256. // @Security ApiKeyAuth
  257. // @Param accountID query string true "资金账户 - 格式:1,2,3"
  258. // @Param tradeMode query string false "交易模式 - 格式:1,2,3"
  259. // @Param orderStatus query string false "委托状态 - 格式:1,2,3"
  260. // @Param orderID query int false "委托单号"
  261. // @Success 200 {object} QueryTradeOrderDetailRsp
  262. // @Failure 500 {object} app.Response
  263. // @Router /Order/QueryTradeOrderDetail [get]
  264. // @Tags 通用单据
  265. // 参考通用查询:SearchTradeOrderDetail
  266. func QueryTradeOrderDetail(c *gin.Context) {
  267. appG := app.Gin{C: c}
  268. // 获取请求参数
  269. var req QueryTradeOrderDetailReq
  270. if err := appG.C.ShouldBindQuery(&req); err != nil {
  271. logger.GetLogger().Errorf("QueryTradeOrderDetail failed: %s", err.Error())
  272. appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
  273. return
  274. }
  275. datas := make([]QueryTradeOrderDetailRsp, 0)
  276. engine := db.GetEngine()
  277. // 由于int64类型数据(单号)过长是获取会有问题(可能是oci8组件问题),所以这里将可能会出问题的单号都用to_char来输出
  278. s := engine.Table("TRADE_ORDERDETAIL").
  279. Join("LEFT", "GOODS", "GOODS.GOODSID = TRADE_ORDERDETAIL.GOODSID").
  280. Join("LEFT", "MARKET", "MARKET.MARKETID = TRADE_ORDERDETAIL.MARKETID").
  281. Select(`to_char(TRADE_ORDERDETAIL.ORDERID) as ORDERID, to_char(TRADE_ORDERDETAIL.PREORDERID) as PREORDERID, to_char(TRADE_ORDERDETAIL.CANCELORDERID) as CANCELORDERID, to_char(TRADE_ORDERDETAIL.RELATEDID) as RELATEDID,
  282. TRADE_ORDERDETAIL.*, TRADE_ORDERDETAIL.ORDERQTY - TRADE_ORDERDETAIL.TRADEQTY - TRADE_ORDERDETAIL.CANCELQTY as ENABLEQTY,
  283. GOODS.GOODSCODE, GOODS.GOODSNAME,GOODS.DECIMALPLACE, GOODS.QTYDECIMALPLACE,GOODS.GOODUNITID, MARKET.MARKETNAME, MARKET.TRADEMODE`).
  284. Where(fmt.Sprintf(`TRADE_ORDERDETAIL.ORDERSRC != 10 and TRADE_ORDERDETAIL.ACCOUNTID in (%s)`, req.AccountID)).
  285. Desc("TRADE_ORDERDETAIL.ORDERTIME")
  286. if len(req.OrderStatus) > 0 {
  287. s = s.And(fmt.Sprintf(`TRADE_ORDERDETAIL.ORDERSTATUS in (%s)`, req.OrderStatus))
  288. }
  289. if len(req.TradeMode) > 0 {
  290. s = s.And(fmt.Sprintf(`MARKET.TRADEMODE in (%s)`, req.TradeMode))
  291. }
  292. if req.OrderID > 0 {
  293. s = s.And("TRADE_ORDERDETAIL.ORDERID = ?", req.OrderID)
  294. }
  295. if err := s.Find(&datas); err != nil {
  296. // 查询失败
  297. logger.GetLogger().Errorf("QueryTradeOrderDetail failed: %s", err.Error())
  298. appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
  299. return
  300. }
  301. // 查询成功
  302. logger.GetLogger().Debugln("QueryTradeOrderDetail successed: %v", datas)
  303. for i := range datas {
  304. datas[i].calc()
  305. }
  306. appG.Response(http.StatusOK, e.SUCCESS, datas)
  307. }
  308. // QueryHisTradeOrderDetailReq 历史委托单查询请求参数(合约市场)
  309. type QueryHisTradeOrderDetailReq struct {
  310. AccountID string `form:"accountID" binding:"required"` // 资金账户 - 格式:1,2,3
  311. OrderStatus string `form:"orderStatus"` // 委托状态 - 格式:1,2,3
  312. TradeMode string `form:"tradeMode"` // 交易模式 - 格式:1,2,3
  313. OrderID int `form:"orderID"` // 委托单号
  314. StartDate string `form:"startDate"` // 开始时间
  315. EndDate string `form:"endDate"` // 结束时间
  316. }
  317. // QueryHisTradeOrderDetailRsp 历史委托单查询返回模型(合约市场)
  318. type QueryHisTradeOrderDetailRsp struct {
  319. models.Histradeorderdetail `xorm:"extends"`
  320. GoodsCode string `json:"goodscode" xorm:"GOODSCODE"` // 商品代码
  321. GoodsName string `json:"goodsname" xorm:"GOODSNAME"` // 商品名称
  322. DECIMALPLACE int32 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 商品报价小数位
  323. QTYDECIMALPLACE int `json:"qtydecimalplace" xorm:"'QTYDECIMALPLACE'"` // 成交量小数位
  324. GOODUNITID int32 `json:"goodunitid" xorm:"'GOODUNITID'"` // 商品单位id
  325. Marketname string `json:"marketname" xorm:"'MARKETNAME'"` // 市场名称
  326. TradeMode int32 `json:"trademode" xorm:"'TRADEMODE'"` // 交易模式
  327. ENUMDICNAME string `json:"enumdicname"` // 单位名称
  328. }
  329. func (r *QueryHisTradeOrderDetailRsp) calc() {
  330. fCovert := func(v *float64) {
  331. *v = *v / math.Pow10(r.QTYDECIMALPLACE)
  332. }
  333. fCovert(&r.Orderqty)
  334. fCovert(&r.Tradeqty)
  335. fCovert(&r.Cancelqty)
  336. fCovert(&r.Openqty)
  337. fCovert(&r.Closeqty)
  338. fCovert(&r.Opentradeqty)
  339. fCovert(&r.Closetradeqty)
  340. r.ENUMDICNAME = mtpcache.GetEnumDicitemName(r.GOODUNITID)
  341. }
  342. // QueryHisTradeOrderDetail 历史委托单查询请求(合约市场)
  343. // @Summary 历史委托单查询请求(合约市场)
  344. // @Produce json
  345. // @Security ApiKeyAuth
  346. // @Param accountID query string true "资金账户 - 格式:1,2,3"
  347. // @Param tradeMode query string false "交易模式 - 格式:1,2,3"
  348. // @Param orderStatus query string false "委托状态 - 格式:1,2,3"
  349. // @Param orderID query int false "委托单号"
  350. // @Param startDate query string false "开始时间 - 闭区间,格式:yyyy-MM-dd"
  351. // @Param endDate query string false "结束时间 - 闭区间,格式:yyyy-MM-dd"
  352. // @Success 200 {object} QueryHisTradeOrderDetailRsp
  353. // @Failure 500 {object} app.Response
  354. // @Router /Order/QueryHisTradeOrderDetail [get]
  355. // @Tags 通用单据
  356. // 参考通用查询:Client_QueryHis_trade_orderdetail
  357. func QueryHisTradeOrderDetail(c *gin.Context) {
  358. appG := app.Gin{C: c}
  359. // 获取请求参数
  360. var req QueryHisTradeOrderDetailReq
  361. if err := appG.C.ShouldBindQuery(&req); err != nil {
  362. logger.GetLogger().Errorf("QueryHisTradeOrderDetail failed: %s", err.Error())
  363. appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
  364. return
  365. }
  366. datas := make([]QueryHisTradeOrderDetailRsp, 0)
  367. engine := db.GetEngine()
  368. s := engine.Table("HIS_TRADE_ORDERDETAIL").
  369. Join("LEFT", "GOODS", "GOODS.GOODSID = HIS_TRADE_ORDERDETAIL.GOODSID").
  370. Join("LEFT", "MARKET", "MARKET.MARKETID = HIS_TRADE_ORDERDETAIL.MARKETID").
  371. Select(`to_char(HIS_TRADE_ORDERDETAIL.ORDERID) as ORDERID, to_char(HIS_TRADE_ORDERDETAIL.PREORDERID) as PREORDERID, to_char(HIS_TRADE_ORDERDETAIL.CANCELORDERID) as CANCELORDERID, to_char(HIS_TRADE_ORDERDETAIL.RELATEDID) as RELATEDID,
  372. HIS_TRADE_ORDERDETAIL.*,
  373. GOODS.GOODSCODE, GOODS.GOODSNAME,GOODS.DECIMALPLACE, GOODS.QTYDECIMALPLACE,GOODS.GOODUNITID, MARKET.MARKETNAME, MARKET.TRADEMODE`).
  374. Where(fmt.Sprintf(`HIS_TRADE_ORDERDETAIL.ORDERSRC != 10 and HIS_TRADE_ORDERDETAIL.ISVALIDDATA = 1 and HIS_TRADE_ORDERDETAIL.ACCOUNTID in (%s)`, req.AccountID)).
  375. Desc("HIS_TRADE_ORDERDETAIL.ORDERTIME")
  376. if len(req.OrderStatus) > 0 {
  377. s = s.And(fmt.Sprintf(`HIS_TRADE_ORDERDETAIL.ORDERSTATUS in (%s)`, req.OrderStatus))
  378. }
  379. if len(req.TradeMode) > 0 {
  380. s = s.And(fmt.Sprintf(`MARKET.TRADEMODE in (%s)`, req.TradeMode))
  381. }
  382. if req.OrderID > 0 {
  383. s = s.And("HIS_TRADE_ORDERDETAIL.ORDERID = ?", req.OrderID)
  384. }
  385. if len(req.StartDate) > 0 {
  386. s = s.And(fmt.Sprintf("to_date(HIS_TRADE_ORDERDETAIL.HISTRADEDATE,'yyyyMMdd') >= to_date('%s','yyyy-MM-dd')", req.StartDate))
  387. }
  388. if len(req.EndDate) > 0 {
  389. s = s.And(fmt.Sprintf("to_date(HIS_TRADE_ORDERDETAIL.HISTRADEDATE,'yyyyMMdd') <= to_date('%s','yyyy-MM-dd')", req.EndDate))
  390. }
  391. if err := s.Find(&datas); err != nil {
  392. // 查询失败
  393. logger.GetLogger().Errorf("QueryHisTradeOrderDetail failed: %s", err.Error())
  394. appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
  395. return
  396. }
  397. // 查询成功
  398. logger.GetLogger().Debugln("QueryHisTradeOrderDetail successed: %v", datas)
  399. for i := range datas {
  400. datas[i].calc()
  401. }
  402. appG.Response(http.StatusOK, e.SUCCESS, datas)
  403. }
  404. // QueryTradeDetailReq 成交单查询请求参数
  405. type QueryTradeDetailReq struct {
  406. AccountID string `form:"accountID" binding:"required"`
  407. TradeID int `form:"tradeID"`
  408. OrderID int `form:"orderID"`
  409. TradeMode string `form:"tradeMode"`
  410. BuildType int `form:"buildType"`
  411. TradeType string `form:"tradeType"`
  412. GoodsID int `form:"goodsID"`
  413. }
  414. // QueryTradeDetailRsp 成交单查询返回模型
  415. type QueryTradeDetailRsp struct {
  416. models.Tradetradedetail `xorm:"extends"`
  417. GoodsCode string `json:"goodscode" xorm:"GOODSCODE"` // 商品代码
  418. GoodsName string `json:"goodsname" xorm:"GOODSNAME"` // 商品名称
  419. DECIMALPLACE int32 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 商品报价小数位
  420. QTYDECIMALPLACE int `json:"qtydecimalplace" xorm:"'QTYDECIMALPLACE'"` // 商品报价小数位
  421. GOODUNITID int32 `json:"goodunitid" xorm:"'GOODUNITID'"` // 商品单位id
  422. Marketname string `json:"marketname" xorm:"'MARKETNAME'"` // 市场名称
  423. TradeMode int32 `json:"trademode" xorm:"'TRADEMODE'"` // 交易模式
  424. ListingSelectType int32 `json:"listingselecttype" xorm:"'LISTINGSELECTTYPE'"` // 关联委托单挂牌点选类型 - 1:挂牌 2:摘牌 3:先摘后挂
  425. Charge float64 `json:"charge" xorm:"CHARGE"` // 手续费
  426. ENUMDICNAME string `json:"enumdicname"` // 单位名称
  427. }
  428. func (r *QueryTradeDetailRsp) calc() {
  429. fCovert := func(v *float64) {
  430. *v = *v / math.Pow10(r.QTYDECIMALPLACE)
  431. }
  432. fCovert(&r.Tradeqty)
  433. fCovert(&r.Openqty)
  434. fCovert(&r.Closeqty)
  435. r.ENUMDICNAME = mtpcache.GetEnumDicitemName(r.GOODUNITID)
  436. }
  437. // QueryTradeDetail 成交单查询(合约市场)
  438. // @Summary 成交单查询(合约市场)
  439. // @Produce json
  440. // @Security ApiKeyAuth
  441. // @Param accountID query string true "资金账户 - 格式:1,2,3"
  442. // @Param tradeID query int false "成交单号"
  443. // @Param orderID query int false "委托单号"
  444. // @Param tradeMode query string false "交易模式 - 格式:1,2,3"
  445. // @Param buildType query int false "委托单据类型"
  446. // @Param tradeType query string false "成交类别 - 格式:1,2,3"
  447. // @Param goodsID query int false "商品ID"
  448. // @Success 200 {object} QueryTradeDetailRsp
  449. // @Failure 500 {object} app.Response
  450. // @Router /Order/QueryTradeDetail [get]
  451. // @Tags 通用单据
  452. // 参考通用查询:SearchAllTransactionDetailOrder
  453. func QueryTradeDetail(c *gin.Context) {
  454. appG := app.Gin{C: c}
  455. // 获取请求参数
  456. var req QueryTradeDetailReq
  457. if err := appG.C.ShouldBindQuery(&req); err != nil {
  458. logger.GetLogger().Errorf("QueryTradeDetail failed: %s", err.Error())
  459. appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
  460. return
  461. }
  462. datas := make([]QueryTradeDetailRsp, 0)
  463. engine := db.GetEngine()
  464. s := engine.Table("TRADE_TRADEDETAIL").
  465. Join("LEFT", "GOODS", "GOODS.GOODSID = TRADE_TRADEDETAIL.GOODSID").
  466. Join("LEFT", "MARKET", "MARKET.MARKETID = TRADE_TRADEDETAIL.MARKETID").
  467. Join("LEFT", "TRADE_ORDERDETAIL", "TRADE_ORDERDETAIL.ORDERID = TRADE_TRADEDETAIL.ORDERID").
  468. Select(`to_char(TRADE_TRADEDETAIL.TRADEID) as TRADEID, to_char(TRADE_TRADEDETAIL.ORDERID) as ORDERID,
  469. TRADE_TRADEDETAIL.*, CASE TRADE_TRADEDETAIL.BUILDTYPE WHEN 1 THEN TRADE_TRADEDETAIL.OPENCHARGE ELSE TRADE_TRADEDETAIL.CLOSECHARGE END as CHARGE,
  470. GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.DECIMALPLACE, GOODS.QTYDECIMALPLACE,GOODS.GOODUNITID, MARKET.MARKETNAME, MARKET.TRADEMODE,
  471. TRADE_ORDERDETAIL.LISTINGSELECTTYPE`).
  472. Where(fmt.Sprintf("TRADE_TRADEDETAIL.TRADETYPE <= 13 and TRADE_TRADEDETAIL.ACCOUNTID in (%s)", req.AccountID)).
  473. Desc("TRADE_TRADEDETAIL.TRADETIME")
  474. if req.TradeID > 0 {
  475. s = s.And("TRADE_TRADEDETAIL.TRADEID = ?", req.TradeID)
  476. }
  477. if req.OrderID > 0 {
  478. s = s.And("TRADE_TRADEDETAIL.ORDERID = ?", req.OrderID)
  479. }
  480. if req.GoodsID > 0 {
  481. s = s.And("TRADE_TRADEDETAIL.GOODSID = ?", req.GoodsID)
  482. }
  483. if len(req.TradeMode) > 0 {
  484. s = s.And(fmt.Sprintf("MARKET.TRADEMODE in (%s)", req.TradeMode))
  485. }
  486. if req.BuildType > 0 {
  487. s = s.And("TRADE_TRADEDETAIL.BUILDTYPE = ?", req.BuildType)
  488. }
  489. if len(req.TradeType) > 0 {
  490. s = s.And(fmt.Sprintf("TRADE_TRADEDETAIL.TRADETYPE in (%s)", req.TradeType))
  491. }
  492. if err := s.Find(&datas); err != nil {
  493. // 查询失败
  494. logger.GetLogger().Errorf("QueryTradeDetail failed: %s", err.Error())
  495. appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
  496. return
  497. }
  498. // 查询成功
  499. logger.GetLogger().Debugln("QueryTradeDetail successed: %v", datas)
  500. for i := range datas {
  501. datas[i].calc()
  502. }
  503. appG.Response(http.StatusOK, e.SUCCESS, datas)
  504. }
  505. // QueryHisTradeDetailReq 历史成交单查询请求参数
  506. type QueryHisTradeDetailReq struct {
  507. AccountID string `form:"accountID" binding:"required"`
  508. TradeID int `form:"tradeID"`
  509. OrderID int `form:"orderID"`
  510. GoodsID int `form:"goodsID"`
  511. TradeMode string `form:"tradeMode"`
  512. BuildType int `form:"buildType"`
  513. TradeType string `form:"tradeType"`
  514. StartDate string `form:"startDate"` // 开始时间
  515. EndDate string `form:"endDate"` // 结束时间
  516. }
  517. // QueryHisTradeDetailRsp 历史成交单查询返回模型
  518. type QueryHisTradeDetailRsp struct {
  519. models.Histradetradedetail `xorm:"extends"`
  520. GoodsCode string `json:"goodscode" xorm:"GOODSCODE"` // 商品代码
  521. GoodsName string `json:"goodsname" xorm:"GOODSNAME"` // 商品名称
  522. DECIMALPLACE int32 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 商品报价小数位
  523. QTYDECIMALPLACE int `json:"qtydecimalplace" xorm:"'QTYDECIMALPLACE'"` // 商品报价小数位
  524. GOODUNITID int32 `json:"goodunitid" xorm:"'GOODUNITID'"` // 商品单位id
  525. Marketname string `json:"marketname" xorm:"'MARKETNAME'"` // 市场名称
  526. TradeMode int32 `json:"trademode" xorm:"'TRADEMODE'"` // 交易模式
  527. ListingSelectType int32 `json:"listingselecttype" xorm:"'LISTINGSELECTTYPE'"` // 关联委托单挂牌点选类型 - 1:挂牌 2:摘牌 3:先摘后挂
  528. Charge float64 `json:"charge" xorm:"CHARGE"` // 手续费
  529. ENUMDICNAME string `json:"enumdicname"` // 单位名称
  530. }
  531. func (r *QueryHisTradeDetailRsp) calc() {
  532. fCovert := func(v *float64) {
  533. *v = *v / math.Pow10(r.QTYDECIMALPLACE)
  534. }
  535. fCovert(&r.Tradeqty)
  536. fCovert(&r.Openqty)
  537. fCovert(&r.Closeqty)
  538. r.ENUMDICNAME = mtpcache.GetEnumDicitemName(r.GOODUNITID)
  539. }
  540. // QueryHisTradeDetail 历史成交单查询(合约市场)
  541. // @Summary 历史成交单查询(合约市场)
  542. // @Produce json
  543. // @Security ApiKeyAuth
  544. // @Param accountID query string true "资金账户 - 格式:1,2,3"
  545. // @Param tradeID query int false "成交单号"
  546. // @Param orderID query int false "委托单号"
  547. // @Param goodsID query int false "商品ID"
  548. // @Param tradeMode query string false "交易模式 - 格式:1,2,3"
  549. // @Param buildType query int false "委托单据类型"
  550. // @Param tradeType query string false "成交类别 - 格式:1,2,3"
  551. // @Param startDate query string false "开始时间 - 闭区间,格式:yyyy-MM-dd"
  552. // @Param endDate query string false "结束时间 - 闭区间,格式:yyyy-MM-dd"
  553. // @Success 200 {object} QueryHisTradeDetailRsp
  554. // @Failure 500 {object} app.Response
  555. // @Router /Order/QueryHisTradeDetail [get]
  556. // @Tags 通用单据
  557. // 参考通用查询:Client_QueryHis_trade_transactiondetail
  558. func QueryHisTradeDetail(c *gin.Context) {
  559. appG := app.Gin{C: c}
  560. // 获取请求参数
  561. var req QueryHisTradeDetailReq
  562. if err := appG.C.ShouldBindQuery(&req); err != nil {
  563. logger.GetLogger().Errorf("QueryHisTradeDetail failed: %s", err.Error())
  564. appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
  565. return
  566. }
  567. datas := make([]QueryHisTradeDetailRsp, 0)
  568. engine := db.GetEngine()
  569. s := engine.Table("HIS_TRADE_TRADEDETAIL").
  570. Join("LEFT", "GOODS", "GOODS.GOODSID = HIS_TRADE_TRADEDETAIL.GOODSID").
  571. Join("LEFT", "MARKET", "MARKET.MARKETID = HIS_TRADE_TRADEDETAIL.MARKETID").
  572. Join("LEFT", "HIS_TRADE_ORDERDETAIL", "HIS_TRADE_ORDERDETAIL.ORDERID = HIS_TRADE_TRADEDETAIL.ORDERID").
  573. Select(`to_char(HIS_TRADE_TRADEDETAIL.TRADEID) as TRADEID, to_char(HIS_TRADE_TRADEDETAIL.ORDERID) as ORDERID,
  574. HIS_TRADE_TRADEDETAIL.*, CASE HIS_TRADE_TRADEDETAIL.BUILDTYPE WHEN 1 THEN HIS_TRADE_TRADEDETAIL.OPENCHARGE ELSE HIS_TRADE_TRADEDETAIL.CLOSECHARGE END as CHARGE,
  575. GOODS.GOODSCODE, GOODS.GOODSNAME,GOODS.DECIMALPLACE, GOODS.QTYDECIMALPLACE, GOODS.GOODUNITID, MARKET.MARKETNAME, MARKET.TRADEMODE,
  576. HIS_TRADE_ORDERDETAIL.LISTINGSELECTTYPE`).
  577. Where(fmt.Sprintf("HIS_TRADE_TRADEDETAIL.TRADETYPE <= 13 and HIS_TRADE_TRADEDETAIL.ISVALIDDATA = 1 and HIS_TRADE_TRADEDETAIL.ACCOUNTID in (%s)", req.AccountID)).
  578. Desc("HIS_TRADE_TRADEDETAIL.TRADETIME")
  579. if req.TradeID > 0 {
  580. s = s.And("HIS_TRADE_TRADEDETAIL.TRADEID = ?", req.TradeID)
  581. }
  582. if req.OrderID > 0 {
  583. s = s.And("HIS_TRADE_TRADEDETAIL.ORDERID = ?", req.OrderID)
  584. }
  585. if req.GoodsID > 0 {
  586. s = s.And("HIS_TRADE_TRADEDETAIL.GOODSID = ?", req.GoodsID)
  587. }
  588. if len(req.TradeMode) > 0 {
  589. s = s.And(fmt.Sprintf("MARKET.TRADEMODE in (%s)", req.TradeMode))
  590. }
  591. if req.BuildType > 0 {
  592. s = s.And("HIS_TRADE_TRADEDETAIL.BUILDTYPE = ?", req.BuildType)
  593. }
  594. if len(req.TradeType) > 0 {
  595. s = s.And(fmt.Sprintf("HIS_TRADE_TRADEDETAIL.TRADETYPE in (%s)", req.TradeType))
  596. }
  597. if len(req.StartDate) > 0 {
  598. s = s.And(fmt.Sprintf("to_date(HIS_TRADE_TRADEDETAIL.HISTRADEDATE,'yyyyMMdd') >= to_date('%s','yyyy-MM-dd')", req.StartDate))
  599. }
  600. if len(req.EndDate) > 0 {
  601. s = s.And(fmt.Sprintf("to_date(HIS_TRADE_TRADEDETAIL.HISTRADEDATE,'yyyyMMdd') <= to_date('%s','yyyy-MM-dd')", req.EndDate))
  602. }
  603. if err := s.Find(&datas); err != nil {
  604. // 查询失败
  605. logger.GetLogger().Errorf("QueryHisTradeDetail failed: %s", err.Error())
  606. appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
  607. return
  608. }
  609. // 查询成功
  610. logger.GetLogger().Debugln("QueryHisTradeDetail successed: %v", datas)
  611. for i := range datas {
  612. datas[i].calc()
  613. }
  614. appG.Response(http.StatusOK, e.SUCCESS, datas)
  615. }