strategy.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package main
  2. import (
  3. "git.beejay.kim/Gshopper/sentio"
  4. )
  5. var Strategy = alpacaQQQ{}
  6. type alpacaQQQ struct{}
  7. func (s alpacaQQQ) Name() string {
  8. return "Alpaca: QQQ [TQQQ : SQQQ]"
  9. }
  10. func (s alpacaQQQ) Model() string {
  11. return "price_return_vqqq_15"
  12. }
  13. func (s alpacaQQQ) MarketId() string {
  14. return "alpaca"
  15. }
  16. func (s alpacaQQQ) PositionSymbols() map[sentio.Side]string {
  17. return map[sentio.Side]string{
  18. sentio.BASE: "QQQ",
  19. sentio.LONG: "TQQQ",
  20. sentio.SHORT: "SQQQ",
  21. }
  22. }
  23. func (s alpacaQQQ) Interval() uint8 {
  24. return 5
  25. }
  26. func (s alpacaQQQ) Handle(market sentio.Market, proba float64) ([]sentio.StrategyOrder, error) {
  27. var (
  28. portfolio sentio.Portfolio
  29. orders []sentio.StrategyOrder
  30. err error
  31. )
  32. if portfolio, err = market.Portfolio(); err != nil {
  33. return nil, err
  34. }
  35. for side, symbol := range s.PositionSymbols() {
  36. var (
  37. position sentio.Position
  38. ok bool
  39. t = market.Time().Now()
  40. )
  41. // no need to trade BASE quote
  42. if sentio.BASE == side {
  43. continue
  44. }
  45. // skip too early trades
  46. if t.Hour() == 9 && t.Minute() < 40 {
  47. continue
  48. }
  49. if portfolio != nil {
  50. position, ok = portfolio.Get(symbol)
  51. ok = ok && position != nil && position.GetSize() != 0
  52. } else {
  53. ok = false
  54. }
  55. // Close positions before market closed
  56. if ok && t.Hour() == 15 && t.Minute() > 45 {
  57. orders = append(orders, sentio.StrategyOrder{
  58. Symbol: symbol,
  59. Action: sentio.OrderSell,
  60. Ratio: 1,
  61. })
  62. continue
  63. }
  64. if proba < 0 {
  65. continue
  66. }
  67. // Close LONG position
  68. if ok && sentio.LONG == side && proba < 1.0001 {
  69. return []sentio.StrategyOrder{{
  70. Symbol: symbol,
  71. Action: sentio.OrderSell,
  72. Ratio: 1,
  73. }}, nil
  74. }
  75. // Close SHORT position
  76. if ok && sentio.SHORT == side && proba > .9999 {
  77. return []sentio.StrategyOrder{{
  78. Symbol: symbol,
  79. Action: sentio.OrderSell,
  80. Ratio: 1,
  81. }}, nil
  82. }
  83. if t.Hour() == 15 && t.Minute() > 35 {
  84. continue
  85. }
  86. if sentio.LONG == side && proba > 1 {
  87. size := float64(0)
  88. if ok && position.GetAvgPrice() > position.GetCurrentPrice() {
  89. // extra position with cheaper price
  90. size = .4
  91. } else if !ok && proba > 1.00065 {
  92. // new trade position
  93. size = .6
  94. }
  95. if size > 0 {
  96. orders = append(orders, sentio.StrategyOrder{
  97. Symbol: symbol,
  98. Action: sentio.OrderBuy,
  99. Ratio: size,
  100. })
  101. }
  102. continue
  103. }
  104. if sentio.SHORT == side && proba < 1 {
  105. size := float64(0)
  106. if ok && position.GetAvgPrice() > position.GetCurrentPrice() {
  107. // extra position with cheaper price
  108. size = .4
  109. } else if !ok && proba < .9992 {
  110. // new trade position
  111. size = .6
  112. }
  113. if size > 0 {
  114. orders = append(orders, sentio.StrategyOrder{
  115. Symbol: symbol,
  116. Action: sentio.OrderBuy,
  117. Ratio: size,
  118. })
  119. }
  120. continue
  121. }
  122. }
  123. return orders, nil
  124. }