tradexx.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /**
  2. * @Author: zou.yingbin
  3. * @Create : 2021/8/13 10:04
  4. * @Modify : 2021/8/13 10:04
  5. */
  6. package models
  7. import (
  8. "fmt"
  9. "mtp2_if/db"
  10. "mtp2_if/mtpcache"
  11. "mtp2_if/utils"
  12. )
  13. // TradeGoodsEx 交易商品相关字段
  14. type TradeGoodsEx struct {
  15. GOODSNAME string `json:"goodsname" xorm:"'GOODSNAME'"` // 商品名称
  16. GOODSCODE string `json:"goodscode" xorm:"'GOODSCODE'"` // 商品代码
  17. DECIMALPLACE int `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 商品价格小数位
  18. QTYDECIMALPLACE int `json:"qtydecimalplace" xorm:"'QTYDECIMALPLACE'"` // 商品成交量小数位
  19. AGREEUNIT float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约乘数
  20. MARKETID int32 `json:"marketid" xorm:"'MARKETID'"` // 市场id
  21. MARKETNAME string `json:"marketname" xorm:"'MARKETNAME'"` // 市场名称
  22. GOODUNITID int32 `json:"goodunitid" xorm:"'GOODUNITID'"` // 商品单位id
  23. CURRENCYID int32 `json:"currencyid" xorm:"'CURRENCYID'"` // 商品币种id
  24. CURRENCYNAME string `json:"currencyname" xorm:"'CURRENCYNAME'"` // 币种名称
  25. ENUMDICNAME string `json:"enumdicname" xorm:"'ENUMDICNAME'"` // 商品单位名称
  26. TRADEMODE int32 `json:"trademode" xorm:"'TRADEMODE'"` // 交易模式 - 10:做市 13:竞价 15:通道交易 16:挂牌点选 17:仓单贸易 18:期权 19:竞拍-降价式 20:竞拍-竞价式 21:竞拍-大宗式 22:受托竞价 46:掉期
  27. REFGOODSID int64 `json:"refgoodsid" xorm:"'REFGOODSID'"` // 标的合约id
  28. REFGOODSCODE string `json:"refgoodscode" xorm:"'REFGOODSCODE'"` // 标的合约代码
  29. }
  30. // TradeAccountEx 交易账户相关字段
  31. type TradeAccountEx struct {
  32. TANAME string `json:"taname" xorm:"'TANAME'"` // 资金账号名称
  33. USERID int64 `json:"userid" xorm:"'USERID'" form:"userid"` // 用户id
  34. USERNAME string `json:"username" xorm:"'USERNAME'"` // 用户名称
  35. }
  36. // TradePosition 持仓汇总
  37. type TradePosition struct {
  38. ACCOUNTID int64 `json:"accountid" xorm:"'ACCOUNTID'"` // 账户id
  39. GOODSID int32 `json:"goodsid" xorm:"'GOODSID'" form:"goodsid"` // 商品id
  40. HOLDERTYPE int32 `json:"holdertype" xorm:"'HOLDERTYPE'"` // 持仓类别 - 1:单边持仓 2:双边持仓
  41. TRADEPROPERTY int32 `json:"tradeproperty" xorm:"'TRADEPROPERTY'"` // 交易属性
  42. BUYORSELL int32 `json:"buyorsell" xorm:"'BUYORSELL'" form:"buyorsell"` // 买卖方向 0-买 1-卖
  43. USEDMARGIN SFLOAT64 `json:"usedmargin" xorm:"'USEDMARGIN'"` // 占用保证金
  44. ORIQTY SFLOAT64 `json:"oriqty" xorm:"'ORIQTY'"` // 期初持仓数量
  45. QTY SFLOAT64 `json:"qty" xorm:"'QTY'"` // 持仓数量
  46. FROZENQTY SFLOAT64 `json:"frozenqty" xorm:"'FROZENQTY'"` // 冻结数量
  47. OTHERFROZENQTY SFLOAT64 `json:"otherfrozenqty" xorm:"'OTHERFROZENQTY'"` // 其它冻结数量
  48. CUROPENQTY SFLOAT64 `json:"curopenqty" xorm:"'CUROPENQTY'"` // 今日开仓数量
  49. CURCLOSEQTY SFLOAT64 `json:"curcloseqty" xorm:"'CURCLOSEQTY'"` // 今日平仓数量
  50. ORIAMOUNT SFLOAT64 `json:"oriamount" xorm:"'ORIAMOUNT'"` // 期初持仓金额
  51. AMOUNT SFLOAT64 `json:"amount" xorm:"'AMOUNT'"` // 持仓金额
  52. TradeGoodsEx `xorm:"extends"`
  53. TradeAccountEx `xorm:"extends"`
  54. HOLDERPRICE SFLOAT64 `json:"holderprice"` // 持仓均价 = 持仓金额 / 持仓数量 / 合约剩数 保留3位小数
  55. LASTPRICE SFLOAT64 `json:"lastprice"` // 最新价 从盘面上获取
  56. POSTIONPL SFLOAT64 `json:"postionpl"` // 持仓盈亏(浮动盈亏)
  57. ENABLEQTY SFLOAT64 `json:"enableqty"` // 可用数量
  58. FtAccountIDs string `json:"-" form:"accids"` // 资金账号,逗号隔开
  59. FtTradeMode string `json:"-" form:"trademodes"` // 交易模式筛选, 逗号隔开
  60. FtMarketIDs string `json:"-" form:"marketids"` // 市场id, 逗号隔开
  61. }
  62. func (r *TradePosition) calc() {
  63. fNegativePower10 := func(n int, vl ...*SFLOAT64) {
  64. for i := range vl {
  65. vl[i].Power10(n * -1)
  66. }
  67. }
  68. r.ENABLEQTY = r.QTY - r.FROZENQTY - r.OTHERFROZENQTY
  69. // 数量 按成交量小数位缩小
  70. fNegativePower10(r.QTYDECIMALPLACE, &r.ORIQTY, &r.QTY, &r.FROZENQTY,
  71. &r.OTHERFROZENQTY, &r.CUROPENQTY, &r.CURCLOSEQTY, &r.ENABLEQTY)
  72. if r.AGREEUNIT > 1e-8 {
  73. r.HOLDERPRICE = r.AMOUNT / r.QTY / SFLOAT64(r.AGREEUNIT)
  74. r.HOLDERPRICE.Round(3)
  75. }
  76. if d, ok := mtpcache.GetQuotePrice(r.GOODSCODE); ok {
  77. r.LASTPRICE.SetByInt64(d, r.DECIMALPLACE)
  78. r.POSTIONPL = (r.LASTPRICE - r.HOLDERPRICE) * r.QTY * SFLOAT64(r.AGREEUNIT)
  79. r.POSTIONPL.Round(2)
  80. }
  81. }
  82. func (r *TradePosition) buildSql() string {
  83. var sqlId utils.SQLVal = `
  84. with gtmp as
  85. (select g.goodsid,
  86. g.goodsname,
  87. g.goodscode,
  88. g.decimalplace,
  89. g.qtydecimalplace,
  90. g.agreeunit,
  91. g.marketid,
  92. g.goodunitid,
  93. g.currencyid,
  94. e.enumdicname,
  95. e2.enumdicname currencyname,
  96. m.marketname,
  97. m.trademode
  98. from goods g
  99. left join enumdicitem e
  100. on g.goodunitid = e.enumitemname
  101. and e.enumdiccode = 'goodsunit'
  102. left join enumdicitem e2
  103. on g.currencyid = e2.enumitemname
  104. and e2.enumdiccode = 'currency'
  105. left join market m
  106. on g.marketid = m.marketid),
  107. utmp as
  108. (select ta.accountid,
  109. ta.accountname taname,
  110. u.userid,
  111. u.accountname username
  112. from taaccount ta
  113. left join useraccount u
  114. on ta.relateduserid = u.userid)
  115. select k.*, t1.*, t2.*
  116. from (select t.accountid,
  117. t.goodsid,
  118. t.holdertype,
  119. t.usedmargin,
  120. t.tradeproperty,
  121. 0 as buyorsell,
  122. t.buypositionqty as oriqty,
  123. t.buyholderamount as oriamount,
  124. t.buycurpositionqty as qty,
  125. t.buycurholderamount as amount,
  126. t.buyfrozenqty as frozenqty,
  127. t.buyotherfrozenqty as otherfrozenqty,
  128. t.buyopentotalqty curopenqty,
  129. t.buyclosetotalqty curcloseqty
  130. from tradeposition t
  131. where t.buycurpositionqty > 0
  132. union all
  133. select t.accountid,
  134. t.goodsid,
  135. t.holdertype,
  136. t.usedmargin,
  137. t.tradeproperty,
  138. 1 as buyorsell,
  139. t.sellpositionqty as oriqty,
  140. t.sellholderamount as oriamount,
  141. t.sellcurpositionqty as qty,
  142. t.sellcurholderamount as amount,
  143. t.sellfrozenqty as frozenqty,
  144. t.sellotherfrozenqty as otherfrozenqty,
  145. t.sellopentotalqty as curopenqty,
  146. t.sellclosetotalqty as curcloseqty
  147. from tradeposition t
  148. where t.sellcurpositionqty > 0) k
  149. left join gtmp t1
  150. on k.goodsid = t1.goodsid
  151. left join utmp t2
  152. on k.accountid = t2.accountid
  153. where 1 = 1
  154. `
  155. sqlId.AndEx("utmp.userid", r.USERID, r.USERID > 0)
  156. sqlId.AndEx("t.goodsid", r.GOODSID, r.GOODSID > 0)
  157. sqlId.AndEx("t.BUYORSELL", r.BUYORSELL, r.BUYORSELL != -1)
  158. sqlId.JoinEx(r.FtTradeMode != "", fmt.Sprintf(" and t1.trademode in(%v)", r.FtTradeMode))
  159. sqlId.JoinEx(r.FtMarketIDs != "", fmt.Sprintf(" and t1.marketid in(%v)", r.FtMarketIDs))
  160. sqlId.JoinEx(r.FtAccountIDs != "", fmt.Sprintf(" and k.accountid in(%v)", r.FtAccountIDs))
  161. return sqlId.String()
  162. }
  163. // GetDataEx 获取持仓汇总
  164. func (r *TradePosition) GetDataEx() (interface{}, error) {
  165. sData := make([]TradePosition, 0)
  166. err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
  167. for i := range sData {
  168. sData[i].calc()
  169. }
  170. return sData, err
  171. }
  172. // TradeHolderDetail 持仓明细
  173. type TradeHolderDetail struct {
  174. TRADEID string `json:"tradeid" xorm:"TRADEID" form:"tradeid"` // 成交单号(101+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx)
  175. TRADEDATE string `json:"tradedate" xorm:"TRADEDATE" form:"tradedate"` // 交易日(yyyyMMdd)
  176. MARKETID int32 `json:"marketid" xorm:"MARKETID" form:"marketid"` // 市场ID
  177. GOODSID int32 `json:"goodsid" xorm:"GOODSID" form:"goodsid"` // 商品ID
  178. ACCOUNTID int64 `json:"accountid" xorm:"ACCOUNTID" form:"accountid"` // 账号ID
  179. BUYORSELL int32 `json:"buyorsell" xorm:"BUYORSELL" form:"buyorsell"` // 方向 - 0:买 1:卖
  180. OPENQTY SFLOAT64 `json:"openqty" xorm:"OPENQTY"` // 建仓数量
  181. HOLDERQTY SFLOAT64 `json:"holderqty" xorm:"HOLDERQTY"` // 持仓数量
  182. FREEZEQTY SFLOAT64 `json:"freezeqty" xorm:"FREEZEQTY"` // 冻结数量
  183. OPENPRICE float64 `json:"openprice" xorm:"OPENPRICE"` // 建仓价格
  184. HOLDERPRICE float64 `json:"holderprice" xorm:"HOLDERPRICE"` // 持仓价格
  185. TRADEAMOUNT float64 `json:"tradeamount" xorm:"TRADEAMOUNT"` // 成交金额
  186. HOLDERAMOUNT float64 `json:"holderamount" xorm:"HOLDERAMOUNT"` // 持仓金额
  187. RELEASEAMOUNT float64 `json:"releaseamount" xorm:"RELEASEAMOUNT"` // 释放持仓金额
  188. HOLDERDAYS int32 `json:"holderdays" xorm:"HOLDERDAYS"` // 剩余冻结天数
  189. TRADETIME string `json:"tradetime" xorm:"TRADETIME"` // 交易时间
  190. TRADEPROPERTY int32 `json:"tradeproperty" xorm:"TRADEPROPERTY"` // 交易属性
  191. OPTIONTYPE int32 `json:"optiontype" xorm:"OPTIONTYPE"` // 期权类型 - 1:认购(看涨) 2:认沽(看跌)
  192. PREMIUM float64 `json:"premium" xorm:"PREMIUM"` // 权利金
  193. EXPIRETYPE int32 `json:"expiretype" xorm:"EXPIRETYPE"` // 行权日类型 - 1:滚动行权 2:固定日行权
  194. EXPIRECYCLE int32 `json:"expirecycle" xorm:"EXPIRECYCLE"` // 行权周期(天) - 1:滚动行权时填写
  195. EXPIREDATE string `json:"expiredate" xorm:"EXPIREDATE" form:"expiredate"` // 行权日(yyyyMMdd) - 到期日
  196. ISPREEXERCISE int32 `json:"ispreexercise" xorm:"ISPREEXERCISE"` // 是否预申报- 0:否 1:是 2:不可行权
  197. PREEXERCISEPRICE float64 `json:"preexerciseprice" xorm:"PREEXERCISEPRICE"` // 预申报价格
  198. ISCONFIRMEXERCISE int32 `json:"isconfirmexercise" xorm:"ISCONFIRMEXERCISE"` // 是否确认行权- 0:否 1:是
  199. HOLDERCREDIT float64 `json:"holdercredit" xorm:"HOLDERCREDIT"` // 持仓授信金额
  200. RELEASEHOLDERCREDIT float64 `json:"releaseholdercredit" xorm:"RELEASEHOLDERCREDIT"` // 释放持仓授信金额
  201. TradeGoodsEx `xorm:"extends"`
  202. TradeAccountEx `xorm:"extends"`
  203. FtAccountIDs string `json:"-" form:"accids"` // 资金账号,逗号隔开
  204. FtTradeMode string `json:"-" form:"trademodes"` // 交易模式筛选, 逗号隔开
  205. FtMarketIDs string `json:"-" form:"marketids"` // 市场id, 逗号隔开
  206. }
  207. func (r *TradeHolderDetail) calc() {
  208. if r.QTYDECIMALPLACE != 0 {
  209. r.OPENQTY.Power10(r.QTYDECIMALPLACE * -1)
  210. r.HOLDERQTY.Power10(r.QTYDECIMALPLACE * -1)
  211. r.FREEZEQTY.Power10(r.QTYDECIMALPLACE * -1)
  212. }
  213. }
  214. func (r *TradeHolderDetail) buildSql() string {
  215. var sqlId utils.SQLVal = `
  216. with gtmp as
  217. (select g.goodsid,
  218. g.goodsname,
  219. g.goodscode,
  220. g.decimalplace,
  221. g.qtydecimalplace,
  222. g.agreeunit,
  223. g.marketid,
  224. g.goodunitid,
  225. g.currencyid,
  226. g.refgoodsid,
  227. g.refgoodscode,
  228. e.enumdicname,
  229. e2.enumdicname currencyname,
  230. m.marketname,
  231. m.trademode
  232. from goods g
  233. left join enumdicitem e
  234. on g.goodunitid = e.enumitemname
  235. and e.enumdiccode = 'goodsunit'
  236. left join enumdicitem e2
  237. on g.currencyid = e2.enumitemname
  238. and e2.enumdiccode = 'currency'
  239. left join market m
  240. on g.marketid = m.marketid),
  241. utmp as
  242. (select ta.accountid,
  243. ta.accountname taname,
  244. u.userid,
  245. u.accountname username
  246. from taaccount ta
  247. left join useraccount u
  248. on ta.relateduserid = u.userid)
  249. SELECT to_char(t.TRADEID) TRADEID,
  250. t.TRADEDATE,
  251. t.MARKETID,
  252. t.GOODSID,
  253. t.ACCOUNTID,
  254. t.BUYORSELL,
  255. t.OPENQTY,
  256. t.HOLDERQTY,
  257. t.FREEZEQTY,
  258. t.OPENPRICE,
  259. t.HOLDERPRICE,
  260. t.TRADEAMOUNT,
  261. t.HOLDERAMOUNT,
  262. t.RELEASEAMOUNT,
  263. t.HOLDERDAYS,
  264. to_char(t.TRADETIME, 'yyyy-mm-dd hh24:mi:ss') TRADETIME,
  265. t.TRADEPROPERTY,
  266. t.OPTIONTYPE,
  267. t.PREMIUM,
  268. t.EXPIRETYPE,
  269. t.EXPIRECYCLE,
  270. t.EXPIREDATE,
  271. t.ISPREEXERCISE,
  272. t.PREEXERCISEPRICE,
  273. t.ISCONFIRMEXERCISE,
  274. t.HOLDERCREDIT,
  275. t.RELEASEHOLDERCREDIT,
  276. gtmp.*,
  277. utmp.*
  278. FROM TRADE_HOLDERDETAIL t
  279. LEFT JOIN gtmp on t.goodsid=gtmp.goodsid
  280. LEFT JOIN utmp on t.accountid=utmp.accountid
  281. WHERE 1 = 1 and t.HOLDERQTY > 0
  282. `
  283. sqlId.AndEx("utmp.userid", r.USERID, r.USERID > 0)
  284. sqlId.AndEx("t.goodsid", r.GOODSID, r.GOODSID > 0)
  285. sqlId.AndEx("t.BUYORSELL", r.BUYORSELL, r.BUYORSELL != -1)
  286. sqlId.JoinEx(r.FtTradeMode != "", fmt.Sprintf(" and gtmp.trademode in(%v)", r.FtTradeMode))
  287. sqlId.JoinEx(r.FtMarketIDs != "", fmt.Sprintf(" and gtmp.marketid in(%v)", r.FtMarketIDs))
  288. sqlId.JoinEx(r.FtAccountIDs != "", fmt.Sprintf(" and t.accountid in(%v)", r.FtAccountIDs))
  289. sqlId.OrderByDesc("t.TRADETIME")
  290. return sqlId.String()
  291. }
  292. // GetDataEx 获取持仓明细
  293. func (r *TradeHolderDetail) GetDataEx() (interface{}, error) {
  294. sData := make([]TradeHolderDetail, 0)
  295. err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
  296. for i := range sData {
  297. sData[i].calc()
  298. }
  299. return sData, err
  300. }