order.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package util
  2. import (
  3. "errors"
  4. "git.beejay.kim/Gshopper/sentio"
  5. "math"
  6. )
  7. func CreateOrder(
  8. m sentio.Market,
  9. s sentio.Strategy,
  10. action sentio.Action,
  11. quotes map[string]sentio.Quote,
  12. rm sentio.RiskManager,
  13. budget float64,
  14. ) error {
  15. var (
  16. symbol string
  17. account sentio.MarketAccount
  18. size uint
  19. side sentio.Side
  20. bid float64
  21. tp float64
  22. sl float64
  23. ok bool
  24. err error
  25. )
  26. if side = sentio.ActionToSide(action); sentio.BASE == side {
  27. return errors.New("`CreateOrder`: do nothing while `sentio.BASE`")
  28. }
  29. if symbol, ok = s.PositionSymbols()[side]; !ok {
  30. return errors.New("`CreateOrder`: unknown Side for the current strategy")
  31. }
  32. bid = sentio.ToFixed(quotes[symbol].BidPrice, 2)
  33. tp = sentio.ToFixed(rm.TakeProfit(symbol, bid, false), 2)
  34. sl = sentio.ToFixed(rm.StopLoss(symbol, bid, false), 2)
  35. // Prevent orders those have too small expected profit
  36. if tp < bid+0.02 {
  37. return sentio.ErrLowTakeProfit
  38. }
  39. // Prevent cases when order will be closed ASAP they were opened.
  40. // Also, Alpaca requires at least 0.01 gap against base_price
  41. if sl > bid-0.01 {
  42. return sentio.ErrHighStoploss
  43. }
  44. if account, err = m.Account(); err != nil {
  45. return err
  46. }
  47. if account.GetCash() < bid {
  48. return sentio.ErrTooSmallOrder
  49. }
  50. var (
  51. ratio float64
  52. )
  53. if ratio = rm.GetOrderSize(symbol, bid); ratio <= 0 {
  54. return sentio.ErrRiskManagementPrevent
  55. }
  56. cash := account.GetCash()
  57. if budget > 0 && cash > budget {
  58. cash = budget
  59. }
  60. // create a new order
  61. if size = uint(math.Floor(cash * ratio / bid)); size < 1 {
  62. return sentio.ErrTooSmallOrder
  63. }
  64. _, err = m.CreateOrder(symbol, 0, size, rm)
  65. return err
  66. }
  67. func CloseAllOrders(m sentio.Market, s sentio.Strategy) error {
  68. var (
  69. symbols = Symbols(s)
  70. orders []sentio.Order
  71. err error
  72. )
  73. if orders, err = m.Orders(sentio.OrderListCriteria{
  74. Status: "open",
  75. Symbols: symbols,
  76. }); err != nil {
  77. return err
  78. }
  79. for i := range orders {
  80. if _, err = m.CloseOrder(orders[i], nil); err != nil {
  81. return err
  82. }
  83. }
  84. return nil
  85. }