account.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. package lmaxapi
  2. import "tickserver/api/lmaxapi/request"
  3. import "tickserver/api/lmaxapi/response"
  4. import "math"
  5. import "log"
  6. import "errors"
  7. type Account struct {
  8. positionList *PositionList
  9. orderList *OrderList
  10. state *response.AccountStateEvent
  11. detail *response.AccountDetails
  12. mtf *Mtf
  13. inId map[string]string
  14. clientId int64
  15. }
  16. func NewAccount(mtf *Mtf, positionList *PositionList, orderList *OrderList, clientId int64) *Account {
  17. account := &Account{}
  18. if orderList == nil {
  19. orderList = NewOrderList(mtf)
  20. }
  21. if positionList == nil {
  22. positionList = NewPositionList(mtf, orderList)
  23. }
  24. account.positionList = positionList
  25. account.orderList = orderList
  26. account.mtf = mtf
  27. account.clientId = clientId
  28. account.inId = make(map[string]string)
  29. return account
  30. }
  31. func (this *Account) GetId() int64 {
  32. return this.state.AccountId
  33. }
  34. func (this *Account) HasInId(id string) bool {
  35. if _, ok := this.inId[id]; ok {
  36. return true
  37. }
  38. return false
  39. }
  40. var ErrFindServerInId = errors.New("ErrFindServerInId")
  41. func (this *Account) GetInId(id string) (string, error) {
  42. if serverId, ok := this.inId[id]; ok {
  43. return serverId, nil
  44. }
  45. return "", ErrFindServerInId
  46. }
  47. func (this *Account) DelInId(id string) {
  48. delete(this.inId, id)
  49. }
  50. func (this *Account) SetInId(id string, serverId string) {
  51. this.inId[id] = serverId
  52. }
  53. func (this *Account) SetState(account *response.AccountStateEvent) *response.Instrument {
  54. this.state = account
  55. // log.Println("[Account][SetState]", account)
  56. return nil
  57. }
  58. func (this *Account) SetDetail(account *response.AccountDetails) *response.Instrument {
  59. this.detail = account
  60. // log.Println("[Account][SetDetail]", account)
  61. return nil
  62. }
  63. func (this *Account) SetRejected(event *response.InstructionRejectedEvent) {
  64. }
  65. func (this *Account) GetState() *response.AccountStateEvent {
  66. if this.state == nil {
  67. return nil
  68. }
  69. account := *this.state
  70. return &account
  71. }
  72. type TickEvent struct {
  73. ob2 *response.OrderBookEvent
  74. fetchUpdated bool
  75. isCopy bool
  76. }
  77. func NewTickEvent(ob2 *response.OrderBookEvent, fetchUpdated bool, isCopy bool) *TickEvent {
  78. req := &TickEvent{}
  79. req.ob2 = ob2
  80. req.fetchUpdated = fetchUpdated
  81. req.isCopy = isCopy
  82. return req
  83. }
  84. func (event *TickEvent) GetOb2() *response.OrderBookEvent {
  85. return event.ob2
  86. }
  87. type AccountUpdated struct {
  88. Req interface{}
  89. orders []*response.OrderEvent
  90. positions []*response.PositionEvent
  91. account *response.AccountStateEvent
  92. }
  93. func (this *AccountUpdated) GetOrders() []*response.OrderEvent {
  94. return this.orders
  95. }
  96. func (this *AccountUpdated) GetPositions() []*response.PositionEvent {
  97. return this.positions
  98. }
  99. func (this *AccountUpdated) GetAccount() *response.AccountStateEvent {
  100. return this.account
  101. }
  102. func (this *Account) UpdateTick(event *TickEvent) *AccountUpdated {
  103. up := &AccountUpdated{}
  104. up.positions = this.positionList.UpdateTick(event)
  105. up.orders = this.orderList.UpdateTick(event)
  106. if len(up.positions) > 0 || len(up.orders) > 0 {
  107. this.updateAccount()
  108. up.account = this.GetState()
  109. }
  110. return up
  111. }
  112. func (this *Account) SetPosition(event *response.PositionEvent) {
  113. this.positionList.SetPosition(event)
  114. this.updateAccount()
  115. }
  116. func (this *Account) SetOrder(event *response.OrderEvent) {
  117. this.orderList.SetOrder(event)
  118. }
  119. func (this *Account) UpdateOrder(event *response.OrderEvent) *AccountUpdated {
  120. orders := this.orderList.UpdateOrder(event)
  121. update := &AccountUpdated{}
  122. update.orders = orders
  123. //更新position 并更新wallet
  124. prev := this.positionList.GetPosition(event.InstrumentId)
  125. update.positions = append(update.positions, this.positionList.updateByOrder(event.InstrumentId))
  126. current := update.positions[0]
  127. inst := this.mtf.getInstument(event.InstrumentId)
  128. if inst == nil {
  129. return nil
  130. }
  131. if inst.AssetClass == "SPOT" { //如果是现货
  132. if current.LongUnfilledQuantity > 0 { //buy
  133. wallet := this.getWallet(inst.Currency)
  134. wallet.Freeze = current.LongUnfilledCost
  135. wallet.Balance += prev.OpenCost - current.OpenCost
  136. this.setWallet(wallet)
  137. } else {
  138. wallet := this.getWallet(inst.UnitOfMeasure)
  139. wallet.Freeze = -current.ShortUnfilledQuantity
  140. wallet.Balance += prev.OpenQuantity - current.OpenQuantity
  141. this.setWallet(wallet)
  142. }
  143. }
  144. this.updateAccount()
  145. update.account = this.state
  146. return update
  147. }
  148. func (this *Account) SetExecution(event *response.ExecutionEvent) {
  149. this.updateByExecution(positionChange{}, &event.OrderEvent)
  150. this.updateAccount()
  151. }
  152. //Execution
  153. func (this *Account) updateByExecution(pchange positionChange, event *response.OrderEvent) {
  154. if len(event.Executions) == 0 {
  155. return
  156. }
  157. inst := this.mtf.getInstument(event.InstrumentId)
  158. if inst == nil {
  159. return
  160. }
  161. //开仓:
  162. free := this.calcCommission(event)
  163. if pchange.quantity == 0 || sameSign(pchange.quantity, event.Executions[0].Quantity) {
  164. this.updateWalletItem(inst.Currency, -free)
  165. log.Println("open order Commission:", free)
  166. } else { //平仓的话,要包括 费用 + 盈利
  167. closeCost := 0.0
  168. totalq := 0.0
  169. for i := 0; i < len(event.Executions); i++ {
  170. quantity := event.Executions[i].Quantity
  171. price := event.Executions[i].Price
  172. dq := quantity
  173. if math.Abs(pchange.quantity)-math.Abs(totalq+quantity) < 0 {
  174. dq = -(pchange.quantity + totalq)
  175. }
  176. closeCost += dq * price * inst.ContractSize
  177. totalq += dq
  178. if math.Abs(pchange.quantity+totalq) < 0.000001 {
  179. break
  180. }
  181. }
  182. realisedpl := -(closeCost + (-totalq)*pchange.cost/pchange.quantity)
  183. log.Println("close order info:", closeCost, pchange.cost, realisedpl, free)
  184. this.updateWalletItem(inst.Currency, realisedpl-free)
  185. }
  186. }
  187. func (this *Account) updateWalletItem(currency string, money float64) {
  188. wallet := this.state.Wallets
  189. for i := 0; i < len(wallet); i++ {
  190. if wallet[i].Currency == currency {
  191. wallet[i].Balance += money
  192. break
  193. }
  194. }
  195. }
  196. type RateEvent struct {
  197. erate *response.ExchangeRateEvent
  198. fetchUpdated bool
  199. isCopy bool
  200. }
  201. func NewRateEvent(erate *response.ExchangeRateEvent, fetchUpdated bool, isCopy bool) *RateEvent {
  202. req := &RateEvent{}
  203. req.erate = erate
  204. req.isCopy = isCopy
  205. req.fetchUpdated = fetchUpdated
  206. return req
  207. }
  208. type AccountInfo struct {
  209. ob2 []*response.OrderBookEvent
  210. erate []*response.ExchangeRateEvent
  211. accountState *response.AccountStateEvent
  212. orders *response.Orders
  213. positions *response.Positions
  214. }
  215. func (this *AccountInfo) GetAllOb2() []*response.OrderBookEvent {
  216. return this.ob2
  217. }
  218. func (this *AccountInfo) GetAllRate() []*response.ExchangeRateEvent {
  219. return this.erate
  220. }
  221. func (this *AccountInfo) GetAccount() *response.AccountStateEvent {
  222. return this.accountState
  223. }
  224. func (this *AccountInfo) GetOrders() *response.Orders {
  225. return this.orders
  226. }
  227. func (this *AccountInfo) GetPositions() *response.Positions {
  228. return this.positions
  229. }
  230. func (event *RateEvent) GetRate() *response.ExchangeRateEvent {
  231. return event.erate
  232. }
  233. var ErrInstrumentNotFound = errors.New("ErrInstrumentNotFound")
  234. var ErrNoMargin = errors.New("ErrNoMargin")
  235. func (this *Account) CheckMargin(msg *Message) error {
  236. if msg.Type == MsgCancelOrder || msg.Type == MsgAmendOrder || msg.Type == MsgCloseOrder {
  237. return nil
  238. }
  239. if msg.Type == MsgPlaceOrder {
  240. req := msg.Data.(*request.OrderRequest)
  241. inst := this.mtf.getInstument(req.InstrumentId)
  242. if inst == nil {
  243. return ErrInstrumentNotFound
  244. }
  245. if inst.AssetClass == "SPOT" { //现货购买,直接判断balance 是否足够
  246. if req.Quantity > 0 { //buy
  247. wallet := this.getWallet(inst.Currency)
  248. money := wallet.Balance
  249. if req.Quantity*req.Price < money {
  250. return ErrNoMargin
  251. }
  252. } else { // sell
  253. wallet := this.getWallet(inst.UnitOfMeasure)
  254. money := wallet.Balance
  255. if req.Quantity+money < 0 {
  256. return ErrNoMargin
  257. }
  258. }
  259. }
  260. }
  261. return nil
  262. }
  263. //获取钱包信息
  264. func (this *Account) getWallet(currency string) response.Wallet {
  265. wallet := this.state.Wallets
  266. for i := 0; i < len(wallet); i++ {
  267. if wallet[i].Currency == currency {
  268. return wallet[i]
  269. }
  270. }
  271. w := response.Wallet{}
  272. w.Currency = currency
  273. return w
  274. }
  275. func (this *Account) setWallet(w response.Wallet) {
  276. wallet := this.state.Wallets
  277. var isset bool
  278. for i := 0; i < len(wallet); i++ {
  279. if wallet[i].Currency == w.Currency {
  280. wallet[i] = w
  281. isset = true
  282. }
  283. }
  284. if !isset {
  285. this.state.Wallets = append(this.state.Wallets, w)
  286. }
  287. if w.Currency == this.detail.Currency {
  288. this.state.Balance = w.Balance
  289. this.state.Freeze = w.Freeze
  290. }
  291. }
  292. func (this *Account) UpdateRate(event *RateEvent) *AccountUpdated {
  293. up := &AccountUpdated{}
  294. up.positions = this.positionList.UpdateRate(event)
  295. up.orders = this.orderList.UpdateRate(event)
  296. if len(up.positions) > 0 || len(up.orders) > 0 || this.hasCurrency(event.erate.From) {
  297. this.updateAccount()
  298. up.account = this.GetState()
  299. }
  300. return up
  301. }
  302. func (this *Account) hasCurrency(currency string) bool {
  303. for i := 0; i < len(this.state.Wallets); i++ {
  304. if this.state.Wallets[i].Currency == currency {
  305. return true
  306. }
  307. }
  308. return false
  309. }
  310. type walletInfo struct {
  311. Currency string
  312. Balance float64
  313. Profit float64
  314. Margin float64
  315. exchangeRate *response.ExchangeRateEvent
  316. }
  317. type workingMargin struct {
  318. buy float64
  319. sell float64
  320. }
  321. func (this *Account) noPositionWorkingOrderMargin(info map[string]*walletInfo) {
  322. margins := make(map[int64]*workingMargin)
  323. for i := 0; i < len(this.orderList.data); i++ {
  324. o := this.orderList.data[i]
  325. if _, ok := this.positionList.perSymbol[o.InstrumentId]; ok {
  326. continue
  327. }
  328. if o.IsWorking() {
  329. if _, ok := margins[o.InstrumentId]; !ok {
  330. margins[o.InstrumentId] = &workingMargin{}
  331. }
  332. if o.Quantity > 0 {
  333. margins[o.InstrumentId].buy += o.Margin
  334. } else {
  335. margins[o.InstrumentId].sell += o.Margin
  336. }
  337. }
  338. }
  339. for key, item := range margins {
  340. w := this.initWalletInfo(key, info)
  341. if w == nil {
  342. continue
  343. }
  344. if item.buy > item.sell {
  345. w.Margin += item.buy
  346. } else {
  347. w.Margin += item.sell
  348. }
  349. }
  350. }
  351. func (this *Account) initWalletInfo(instId int64, info map[string]*walletInfo) *walletInfo {
  352. inst, ok := this.mtf.instrument[instId]
  353. if !ok {
  354. return nil
  355. }
  356. symbol := inst.Currency
  357. w, ok := info[symbol]
  358. if !ok {
  359. w = &walletInfo{}
  360. info[symbol] = w
  361. w.Currency = symbol
  362. w.exchangeRate = this.mtf.getExchangeRate(symbol)
  363. }
  364. return w
  365. }
  366. //更新钱包,每天五点开始更新
  367. func (this *Account) updateWallets() {
  368. balance := 0.0
  369. wallet := this.state.Wallets
  370. for i := 0; i < len(wallet); i++ {
  371. if wallet[i].Currency == this.detail.Currency {
  372. balance += wallet[i].Balance
  373. continue
  374. }
  375. if data, ok := this.mtf.erate[wallet[i].Currency+"/"+this.detail.Currency]; ok {
  376. money := doRateExchange(wallet[i].Balance, data)
  377. data.Wallet = 0
  378. //send a log event
  379. //mtf.server.SendPrivate()
  380. balance += money
  381. }
  382. }
  383. w := response.Wallet{}
  384. w.Currency = this.detail.Currency
  385. w.Balance = balance
  386. this.state.Wallets = nil
  387. this.state.Wallets = append(this.state.Wallets, w)
  388. }
  389. //利息计算,每天的五点进行,计算方法见trade manal
  390. func (this *Account) updateSwap() {
  391. //计算position的Open量,然后进行处理
  392. for _, position := range this.positionList.perSymbol {
  393. inst := this.mtf.getInstument(position.InstrumentId)
  394. if position.OpenQuantity == 0 {
  395. continue
  396. }
  397. money := 0.0
  398. if position.OpenQuantity > 0 {
  399. money = position.OpenQuantity * inst.LongSwapPoints
  400. } else {
  401. money = position.OpenQuantity * inst.ShortSwapPoints
  402. }
  403. if inst.Currency != this.detail.Currency {
  404. if data, ok := this.mtf.erate[inst.Currency+"/"+this.detail.Currency]; ok {
  405. money = doRateExchange2(money, data)
  406. } else {
  407. log.Println("updateSwap::no exchange rate")
  408. continue
  409. }
  410. }
  411. //更新钱包:
  412. wallet := this.state.Wallets
  413. for i := 0; i < len(wallet); i++ {
  414. if wallet[i].Currency == inst.Currency {
  415. wallet[i].Balance += money
  416. break
  417. }
  418. }
  419. }
  420. }
  421. //佣金计算
  422. //1. 如果订单是分裂的,如何计算?关键是这个问题
  423. //2. 这个函数只计算当前订单增加的佣金,历史的佣金情况我们要自己累积
  424. func (this *Account) calcCommission(order *response.OrderEvent) float64 {
  425. inst := this.mtf.getInstument(order.InstrumentId)
  426. if inst == nil {
  427. return 0.0
  428. }
  429. ret := float64(0)
  430. for i := 0; i < len(order.Executions); i++ {
  431. dt := inst.AggressiveCommissionRate * order.Executions[i].Price * order.Executions[i].Quantity * inst.ContractSize
  432. if dt < 0 {
  433. dt = -dt
  434. }
  435. ret += dt / float64(10000)
  436. }
  437. return ret
  438. }
  439. var moneyPrec = 4
  440. func (this *Account) updateAccount() {
  441. if this.state == nil {
  442. return
  443. }
  444. balance := 0.0
  445. wallet := this.state.Wallets
  446. info := make(map[string]*walletInfo)
  447. for i := 0; i < len(wallet); i++ {
  448. symbol := wallet[i].Currency
  449. w := &walletInfo{}
  450. info[symbol] = w
  451. w.Currency = symbol
  452. w.Balance = wallet[i].Balance
  453. // log.Println(wallet[i])
  454. // log.Println(this.detail)
  455. if wallet[i].Currency == this.detail.Currency {
  456. balance += wallet[i].Balance
  457. continue
  458. }
  459. if data, ok := this.mtf.erate[wallet[i].Currency+"/"+this.detail.Currency]; ok {
  460. data.Wallet = wallet[i].Balance
  461. balance += doRateExchange(data.Wallet, data)
  462. w.exchangeRate = data
  463. }
  464. }
  465. for _, position := range this.positionList.perSymbol {
  466. w := this.initWalletInfo(position.InstrumentId, info)
  467. if w == nil {
  468. continue
  469. }
  470. w.Profit += position.Profit
  471. w.Margin += position.Margin
  472. }
  473. this.noPositionWorkingOrderMargin(info)
  474. equity := 0.0
  475. availableFunds := 0.0
  476. //做汇总
  477. for _, w := range info {
  478. equity += doRateExchange(w.Balance+w.Profit, w.exchangeRate)
  479. availableFunds += doRateExchange(w.Balance+w.Profit-w.Margin, w.exchangeRate)
  480. }
  481. balance = round(balance, moneyPrec)
  482. equity = round(equity, moneyPrec)
  483. availableFunds = round(availableFunds, moneyPrec)
  484. profit := round(equity-balance, moneyPrec)
  485. margin := round(equity-availableFunds, moneyPrec)
  486. this.state.UnrealisedProfitAndLoss = profit
  487. this.state.Margin = margin
  488. this.state.AvailableFunds = availableFunds
  489. this.state.AvailableToWithdraw = availableFunds
  490. this.state.Balance = balance
  491. this.state.Equity = equity
  492. }
  493. func round(val float64, prec int) float64 {
  494. var rounder float64
  495. n := math.Pow(10, float64(prec))
  496. intermed := val * n
  497. delta := intermed - math.Floor(intermed)
  498. if delta >= 0.5 {
  499. rounder = math.Ceil(intermed)
  500. } else {
  501. rounder = math.Floor(intermed)
  502. }
  503. return rounder / n
  504. }
  505. func doRateExchange(money float64, exchangeRate *response.ExchangeRateEvent) float64 {
  506. if exchangeRate != nil {
  507. if money > 0 {
  508. money *= exchangeRate.Buy
  509. } else {
  510. money *= exchangeRate.Sell
  511. }
  512. return money
  513. }
  514. return money
  515. }
  516. func doRateExchange2(money float64, exchangeRate *response.ExchangeRateEvent) float64 {
  517. if exchangeRate != nil {
  518. if money > 0 {
  519. money /= exchangeRate.Buy
  520. } else {
  521. money /= exchangeRate.Sell
  522. }
  523. return money
  524. }
  525. return money
  526. }
  527. //在交易模式下面,初始化在一次运行只初始化一次。
  528. //在仓单管理模式下面,初始化会初始化多次。(比如断线后会重置)
  529. //订单的更新:
  530. //在tick变化, exchangerate变化的情况下更新
  531. //在某次执行的时候更新
  532. func (this *Account) Init(event *InitEvent) *AccountUpdated {
  533. // log.Println("[Account][Init]", this.detail)
  534. //删除已经不存在的order 和 position
  535. updated := &AccountUpdated{}
  536. mpositon := make(map[int64]*response.PositionEvent)
  537. for i := 0; i < len(event.Position); i++ {
  538. mpositon[event.Position[i].InstrumentId] = event.Position[i]
  539. }
  540. morder := make(map[string]*response.OrderEvent)
  541. for i := 0; i < len(event.Order); i++ {
  542. morder[event.Order[i].OrderId] = event.Order[i]
  543. }
  544. //订单不存在,设置成平仓
  545. for i := 0; i < len(this.orderList.data); i++ {
  546. o := this.orderList.data[i]
  547. if _, ok := morder[o.OrderId]; !ok {
  548. o.SetClosed()
  549. tmp := *o
  550. updated.orders = append(updated.orders, &tmp)
  551. }
  552. }
  553. //会发送消息给客户端端,这个函数
  554. this.orderList.deleteClosed()
  555. for _, position := range this.positionList.perSymbol {
  556. if _, ok := mpositon[position.InstrumentId]; !ok {
  557. position.OpenQuantity = 0
  558. tmp := *position
  559. updated.positions = append(updated.positions, &tmp)
  560. }
  561. }
  562. this.positionList.deleteClosed()
  563. for i := 0; i < len(event.Order); i++ {
  564. this.SetOrder(event.Order[i])
  565. }
  566. for i := 0; i < len(event.Position); i++ {
  567. this.positionList.SetPosition(event.Position[i])
  568. }
  569. this.updateAccount()
  570. updated.account = this.GetState()
  571. return updated
  572. }
  573. type positionChange struct {
  574. quantity float64
  575. cost float64
  576. }
  577. func (this *Account) SetOneExecution(event *OneExecutionEvent) *AccountUpdated {
  578. updated := &AccountUpdated{}
  579. pchange := make(map[int64]*positionChange)
  580. for i := 0; i < len(event.Order); i++ {
  581. instrumentId := event.Order[i].InstrumentId
  582. if _, ok := pchange[instrumentId]; !ok {
  583. pchange[instrumentId] = &positionChange{}
  584. prevp, ok := this.positionList.perSymbol[instrumentId]
  585. if !ok {
  586. pchange[instrumentId].quantity = 0
  587. pchange[instrumentId].cost = 0
  588. } else {
  589. pchange[instrumentId].quantity = prevp.OpenQuantity
  590. pchange[instrumentId].cost = prevp.OpenCost
  591. }
  592. }
  593. updated.orders = append(updated.orders, event.Order[i])
  594. if event.Order[i].IsStopProft() {
  595. continue
  596. }
  597. this.orderList.SetOrder(event.Order[i])
  598. position := this.positionList.updateByOrder(instrumentId)
  599. if position != nil {
  600. updated.positions = append(updated.positions, position)
  601. }
  602. }
  603. for i := 0; i < len(event.Order); i++ {
  604. if event.Order[i].IsExecution() {
  605. //主要是在close的情况下,更新钱包的信息
  606. instrumentId := event.Order[i].InstrumentId
  607. this.updateByExecution(*pchange[instrumentId], event.Order[i])
  608. }
  609. }
  610. this.positionList.deleteClosed()
  611. this.updateAccount()
  612. updated.account = this.GetState()
  613. return updated
  614. }
  615. func sameSign(a float64, b float64) bool {
  616. if a == b {
  617. return true
  618. }
  619. if a > 0 && b > 0 {
  620. return true
  621. }
  622. if a < 0 && b < 0 {
  623. return true
  624. }
  625. return false
  626. }