tradexx.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  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'"` // 商品id
  40. HOLDERTYPE int32 `json:"holdertype" xorm:"'HOLDERTYPE'"` // 持仓类别 - 1:单边持仓 2:双边持仓
  41. TRADEPROPERTY int32 `json:"tradeproperty" xorm:"'TRADEPROPERTY'"` // 交易属性
  42. BUYORSELL int32 `json:"buyorsell" xorm:"'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. }
  58. func (r *TradePosition) calc() {
  59. fNegativePower10 := func(n int, vl ...*SFLOAT64) {
  60. for i := range vl {
  61. vl[i].Power10(n * -1)
  62. }
  63. }
  64. // 数量 按成交量小数位缩小
  65. fNegativePower10(r.QTYDECIMALPLACE, &r.ORIQTY, &r.QTY, &r.FROZENQTY,
  66. &r.OTHERFROZENQTY, &r.CUROPENQTY, &r.CURCLOSEQTY)
  67. if r.AGREEUNIT > 1e-8 {
  68. r.HOLDERPRICE = r.AMOUNT / r.QTY / SFLOAT64(r.AGREEUNIT)
  69. r.HOLDERPRICE.Round(3)
  70. }
  71. if d, ok := mtpcache.GetQuotePrice(r.GOODSCODE); ok {
  72. r.LASTPRICE.SetByInt64(d, r.DECIMALPLACE)
  73. r.POSTIONPL = (r.LASTPRICE - r.HOLDERPRICE) * r.QTY * SFLOAT64(r.AGREEUNIT)
  74. r.POSTIONPL.Round(2)
  75. }
  76. }
  77. func (r *TradePosition) buildSql() string {
  78. var sqlId utils.SQLVal = `
  79. with gtmp as
  80. (select g.goodsid,
  81. g.goodsname,
  82. g.goodscode,
  83. g.decimalplace,
  84. g.qtydecimalplace,
  85. g.agreeunit,
  86. g.marketid,
  87. g.goodunitid,
  88. g.currencyid,
  89. e.enumdicname,
  90. e2.enumdicname currencyname,
  91. m.marketname,
  92. m.trademode
  93. from goods g
  94. left join enumdicitem e
  95. on g.goodunitid = e.enumitemname
  96. and e.enumdiccode = 'goodsunit'
  97. left join enumdicitem e2
  98. on g.currencyid = e2.enumitemname
  99. and e2.enumdiccode = 'currency'
  100. left join market m
  101. on g.marketid = m.marketid),
  102. utmp as
  103. (select ta.accountid,
  104. ta.accountname taname,
  105. u.userid,
  106. u.accountname username
  107. from taaccount ta
  108. left join useraccount u
  109. on ta.relateduserid = u.userid)
  110. select k.*, t1.*, t2.*
  111. from (select t.accountid,
  112. t.goodsid,
  113. t.holdertype,
  114. t.usedmargin,
  115. t.tradeproperty,
  116. 0 as buyorsell,
  117. t.buypositionqty as oriqty,
  118. t.buyholderamount as oriamount,
  119. t.buycurpositionqty as qty,
  120. t.buycurholderamount as amount,
  121. t.buyfrozenqty as frozenqty,
  122. t.buyotherfrozenqty as otherfrozenqty,
  123. t.buyopentotalqty curopenqty,
  124. t.buyclosetotalqty curcloseqty
  125. from tradeposition t
  126. where t.buycurpositionqty > 0
  127. union all
  128. select t.accountid,
  129. t.goodsid,
  130. t.holdertype,
  131. t.usedmargin,
  132. t.tradeproperty,
  133. 1 as buyorsell,
  134. t.sellpositionqty as oriqty,
  135. t.sellholderamount as oriamount,
  136. t.sellcurpositionqty as qty,
  137. t.sellcurholderamount as amount,
  138. t.sellfrozenqty as frozenqty,
  139. t.sellotherfrozenqty as otherfrozenqty,
  140. t.sellopentotalqty as curopenqty,
  141. t.sellclosetotalqty as curcloseqty
  142. from tradeposition t
  143. where t.sellcurpositionqty > 0) k
  144. left join gtmp t1
  145. on k.goodsid = t1.goodsid
  146. left join utmp t2
  147. on k.accountid = t2.accountid
  148. where 1 = 1
  149. `
  150. return sqlId.String()
  151. }
  152. // GetDataEx 获取持仓汇总
  153. func (r *TradePosition) GetDataEx() (interface{}, error) {
  154. sData := make([]TradePosition, 0)
  155. err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
  156. for i := range sData {
  157. sData[i].calc()
  158. }
  159. return sData, err
  160. }
  161. // TradeHolderDetail 持仓明细
  162. type TradeHolderDetail struct {
  163. TRADEID string `json:"tradeid" xorm:"TRADEID" form:"tradeid"` // 成交单号(101+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx)
  164. TRADEDATE string `json:"tradedate" xorm:"TRADEDATE" form:"tradedate"` // 交易日(yyyyMMdd)
  165. MARKETID int32 `json:"marketid" xorm:"MARKETID" form:"marketid"` // 市场ID
  166. GOODSID int32 `json:"goodsid" xorm:"GOODSID" form:"goodsid"` // 商品ID
  167. ACCOUNTID int64 `json:"accountid" xorm:"ACCOUNTID" form:"accountid"` // 账号ID
  168. BUYORSELL int32 `json:"buyorsell" xorm:"BUYORSELL"` // 方向 - 0:买 1:卖
  169. OPENQTY SFLOAT64 `json:"openqty" xorm:"OPENQTY"` // 建仓数量
  170. HOLDERQTY SFLOAT64 `json:"holderqty" xorm:"HOLDERQTY"` // 持仓数量
  171. FREEZEQTY SFLOAT64 `json:"freezeqty" xorm:"FREEZEQTY"` // 冻结数量
  172. OPENPRICE float64 `json:"openprice" xorm:"OPENPRICE"` // 建仓价格
  173. HOLDERPRICE float64 `json:"holderprice" xorm:"HOLDERPRICE"` // 持仓价格
  174. TRADEAMOUNT float64 `json:"tradeamount" xorm:"TRADEAMOUNT"` // 成交金额
  175. HOLDERAMOUNT float64 `json:"holderamount" xorm:"HOLDERAMOUNT"` // 持仓金额
  176. RELEASEAMOUNT float64 `json:"releaseamount" xorm:"RELEASEAMOUNT"` // 释放持仓金额
  177. HOLDERDAYS int32 `json:"holderdays" xorm:"HOLDERDAYS"` // 剩余冻结天数
  178. TRADETIME string `json:"tradetime" xorm:"TRADETIME"` // 交易时间
  179. TRADEPROPERTY int32 `json:"tradeproperty" xorm:"TRADEPROPERTY"` // 交易属性
  180. OPTIONTYPE int32 `json:"optiontype" xorm:"OPTIONTYPE"` // 期权类型 - 1:认购(看涨) 2:认沽(看跌)
  181. PREMIUM float64 `json:"premium" xorm:"PREMIUM"` // 权利金
  182. EXPIRETYPE int32 `json:"expiretype" xorm:"EXPIRETYPE"` // 行权日类型 - 1:滚动行权 2:固定日行权
  183. EXPIRECYCLE int32 `json:"expirecycle" xorm:"EXPIRECYCLE"` // 行权周期(天) - 1:滚动行权时填写
  184. EXPIREDATE string `json:"expiredate" xorm:"EXPIREDATE" form:"expiredate"` // 行权日(yyyyMMdd) - 到期日
  185. ISPREEXERCISE int32 `json:"ispreexercise" xorm:"ISPREEXERCISE"` // 是否预申报- 0:否 1:是 2:不可行权
  186. PREEXERCISEPRICE float64 `json:"preexerciseprice" xorm:"PREEXERCISEPRICE"` // 预申报价格
  187. ISCONFIRMEXERCISE int32 `json:"isconfirmexercise" xorm:"ISCONFIRMEXERCISE"` // 是否确认行权- 0:否 1:是
  188. HOLDERCREDIT float64 `json:"holdercredit" xorm:"HOLDERCREDIT"` // 持仓授信金额
  189. RELEASEHOLDERCREDIT float64 `json:"releaseholdercredit" xorm:"RELEASEHOLDERCREDIT"` // 释放持仓授信金额
  190. TradeGoodsEx `xorm:"extends"`
  191. TradeAccountEx `xorm:"extends"`
  192. FtAccountIDs string `json:"-" form:"accids"` // 资金账号,逗号隔开
  193. FtTradeMode string `json:"-" form:"trademodes"` // 交易模式筛选, 逗号隔开
  194. FtMarketIDs string `json:"-" form:"marketids"` // 市场id, 逗号隔开
  195. }
  196. func (r *TradeHolderDetail) calc() {
  197. if r.QTYDECIMALPLACE != 0 {
  198. r.OPENQTY.Power10(r.QTYDECIMALPLACE * -1)
  199. r.HOLDERQTY.Power10(r.QTYDECIMALPLACE * -1)
  200. r.FREEZEQTY.Power10(r.QTYDECIMALPLACE * -1)
  201. }
  202. }
  203. func (r *TradeHolderDetail) buildSql() string {
  204. var sqlId utils.SQLVal = `
  205. with gtmp as
  206. (select g.goodsid,
  207. g.goodsname,
  208. g.goodscode,
  209. g.decimalplace,
  210. g.qtydecimalplace,
  211. g.agreeunit,
  212. g.marketid,
  213. g.goodunitid,
  214. g.currencyid,
  215. g.refgoodsid,
  216. g.refgoodscode,
  217. e.enumdicname,
  218. e2.enumdicname currencyname,
  219. m.marketname,
  220. m.trademode
  221. from goods g
  222. left join enumdicitem e
  223. on g.goodunitid = e.enumitemname
  224. and e.enumdiccode = 'goodsunit'
  225. left join enumdicitem e2
  226. on g.currencyid = e2.enumitemname
  227. and e2.enumdiccode = 'currency'
  228. left join market m
  229. on g.marketid = m.marketid),
  230. utmp as
  231. (select ta.accountid,
  232. ta.accountname taname,
  233. u.userid,
  234. u.accountname username
  235. from taaccount ta
  236. left join useraccount u
  237. on ta.relateduserid = u.userid)
  238. SELECT to_char(t.TRADEID) TRADEID,
  239. t.TRADEDATE,
  240. t.MARKETID,
  241. t.GOODSID,
  242. t.ACCOUNTID,
  243. t.BUYORSELL,
  244. t.OPENQTY,
  245. t.HOLDERQTY,
  246. t.FREEZEQTY,
  247. t.OPENPRICE,
  248. t.HOLDERPRICE,
  249. t.TRADEAMOUNT,
  250. t.HOLDERAMOUNT,
  251. t.RELEASEAMOUNT,
  252. t.HOLDERDAYS,
  253. to_char(t.TRADETIME, 'yyyy-mm-dd hh24:mi:ss') TRADETIME,
  254. t.TRADEPROPERTY,
  255. t.OPTIONTYPE,
  256. t.PREMIUM,
  257. t.EXPIRETYPE,
  258. t.EXPIRECYCLE,
  259. t.EXPIREDATE,
  260. t.ISPREEXERCISE,
  261. t.PREEXERCISEPRICE,
  262. t.ISCONFIRMEXERCISE,
  263. t.HOLDERCREDIT,
  264. t.RELEASEHOLDERCREDIT,
  265. gtmp.*,
  266. utmp.*
  267. FROM TRADE_HOLDERDETAIL t
  268. LEFT JOIN gtmp on t.goodsid=gtmp.goodsid
  269. LEFT JOIN utmp on t.accountid=utmp.accountid
  270. WHERE 1 = 1 and t.HOLDERQTY > 0
  271. `
  272. sqlId.AndEx("utmp.userid", r.USERID, r.USERID > 0)
  273. sqlId.AndEx("t.goodsid", r.GOODSID, r.GOODSID > 0)
  274. sqlId.JoinEx(r.FtTradeMode != "", fmt.Sprintf(" and gtmp.trademode in(%v)", r.FtTradeMode))
  275. sqlId.JoinEx(r.FtMarketIDs != "", fmt.Sprintf(" and gtmp.marketid in(%v)", r.FtMarketIDs))
  276. sqlId.JoinEx(r.FtAccountIDs != "", fmt.Sprintf(" and t.accountid in(%v)", r.FtAccountIDs))
  277. return sqlId.String()
  278. }
  279. // GetDataEx 获取持仓明细
  280. func (r *TradeHolderDetail) GetDataEx() (interface{}, error) {
  281. sData := make([]TradeHolderDetail, 0)
  282. err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
  283. for i := range sData {
  284. sData[i].calc()
  285. }
  286. return sData, err
  287. }