Преглед изворни кода

Refactoring

- Market: deprecate Cooldown()
- Strategy: deprecate Cooldown(periods uint8)
- QQQ15: prevent new orders if we just closed one
- Utils.CreateOrder: return sentio.ErrHighStoploss if base_price-0.011 <= stoploss
Alexey Kim пре 4 дана
родитељ
комит
e0339a88d5
6 измењених фајлова са 30 додато и 163 уклоњено
  1. 9 0
      errors.go
  2. 0 7
      market.go
  3. 0 142
      strategy.go
  4. 10 6
      strategy/alpaca/qqq15/strategy.go
  5. 10 7
      strategy/alpaca/qqq15_nodelay/strategy.go
  6. 1 1
      util/order.go

+ 9 - 0
errors.go

@@ -0,0 +1,9 @@
+package sentio
+
+import "errors"
+
+var (
+	ErrMarketClosed  = errors.New("market is closed")
+	ErrTooSmallOrder = errors.New("too small order size")
+	ErrHighStoploss  = errors.New("base price is lower than stoploss")
+)

+ 0 - 7
market.go

@@ -1,19 +1,12 @@
 package sentio
 
 import (
-	"errors"
 	"time"
 )
 
-var (
-	ErrMarketClosed  = errors.New("market is closed")
-	ErrTooSmallOrder = errors.New("too small order size")
-)
-
 type Market interface {
 	Clock() Clock
 	IsOpen() bool
-	Cooldown() uint8
 
 	Connect(done chan struct{}) (chan MarketConnection, error)
 	Subscribe(symbols ...string) error

+ 0 - 142
strategy.go

@@ -1,9 +1,5 @@
 package sentio
 
-import (
-	"time"
-)
-
 type Strategy interface {
 	Name() string
 
@@ -12,144 +8,6 @@ type Strategy interface {
 	PositionSymbols() map[Side]string
 	PositionProbabilities() map[Side]float64
 	Interval() uint8
-	Cooldown(periods uint8) time.Duration
 
 	Handle(market Market, probability Probability) error
 }
-
-//type BaseStrategy struct {
-//	Strategy
-//}
-//
-//func (strategy BaseStrategy) Symbols() []string {
-//	var symbols []string
-//
-//	for side, s := range strategy.PositionSymbols() {
-//		if BASE == side {
-//			continue
-//		}
-//
-//		symbols = append(symbols, s)
-//	}
-//
-//	return symbols
-//}
-//
-//func (strategy BaseStrategy) CloseAllOrders(market Market) error {
-//	var (
-//		symbols = strategy.Symbols()
-//		orders  []Order
-//		err     error
-//	)
-//
-//	if orders, err = market.Orders(OrderListCriteria{
-//		Status:  "open",
-//		Symbols: symbols,
-//		Nested:  true,
-//	}); err != nil {
-//		return err
-//	}
-//
-//	for i := range orders {
-//		if _, err = market.CloseOrder(orders[i].GetId()); err != nil {
-//			return err
-//		}
-//	}
-//
-//	return nil
-//}
-//
-//func (strategy BaseStrategy) AtrStopLoss(market Market, symbols ...string) (map[string]float64, error) {
-//	var (
-//		stoplosses map[string]float64
-//		bars       map[string][]Bar
-//		err        error
-//	)
-//
-//	if bars, err = market.HistoricalBars(symbols, time.Minute, nil); err != nil {
-//		return nil, err
-//	}
-//
-//	if bars == nil || len(bars) < ATR_PERIOD {
-//		return nil, errors.New("AtrStopLoss: could not calculate stoploss for too short timeseries")
-//	}
-//
-//	stoplosses = make(map[string]float64)
-//	for s := range bars {
-//		h := make([]float64, len(bars[s]))
-//		l := make([]float64, len(bars[s]))
-//		c := make([]float64, len(bars[s]))
-//
-//		for i := range bars[s] {
-//			h[i] = bars[s][i].High
-//			l[i] = bars[s][i].Low
-//			c[i] = bars[s][i].Close
-//		}
-//
-//		trailing := indicator.AtrTrailingStopLoss(h, l, c, ATR_PERIOD, ATR_MULTIPLIER, ATR_HHV)
-//		stoplosses[s] = trailing[len(trailing)-1]
-//	}
-//
-//	return stoplosses, nil
-//}
-//
-//func (strategy BaseStrategy) CreateOrder(m Market, t Side, proba Probability, p Portfolio, q map[string]Quote, sl map[string]float64) error {
-//	var (
-//		symbol    = strategy.PositionSymbols()[t]
-//		position  Position
-//		account   MarketAccount
-//		has       = false
-//		threshold float64
-//		size      uint
-//		ok        bool
-//		err       error
-//	)
-//
-//	// ensure portfolio
-//	position, has = p.Get(symbol)
-//
-//	// define threshold
-//	if threshold, ok = strategy.PositionProbabilities()[t]; !ok {
-//		threshold = -1
-//	}
-//
-//	if threshold == -1 || symbol == "" {
-//		return nil
-//	}
-//
-//	// Prevent Market.CreateOrder when BidPrice less than ATR_STOPLOSS_THRESHOLD
-//	if q[symbol].BidPrice/sl[symbol] < ATR_STOPLOSS_THRESHOLD {
-//		return nil
-//	}
-//
-//	if account, err = m.Account(); err != nil {
-//		return err
-//	}
-//
-//	if account.GetCash() < q[symbol].BidPrice {
-//		return ErrTooSmallOrder
-//	}
-//
-//	if !has && proba.Value > threshold {
-//
-//		// create a new order
-//		if size = uint(math.Floor(account.GetCash() * .7 / q[symbol].BidPrice)); size < 1 {
-//			return ErrTooSmallOrder
-//		}
-//
-//		_, err = m.CreateOrder(symbol, size, sl[symbol])
-//		return err
-//
-//	} else if has && position.GetAvgPrice()/position.GetCurrentPrice() > EXTRA_POSITION_THRESHOLD {
-//
-//		// create an extra position
-//		if size = uint(math.Floor(account.GetCash() * .5 / q[symbol].BidPrice)); size < 1 {
-//			return ErrTooSmallOrder
-//		}
-//
-//		_, err = m.CreateOrder(symbol, size, sl[symbol])
-//		return err
-//	}
-//
-//	return nil
-//}

+ 10 - 6
strategy/alpaca/qqq15/strategy.go

@@ -9,8 +9,8 @@ import (
 
 const (
 	ATR_MULTIPLIER = 1.5
-	ATR_PERIOD     = 5
-	ATR_HHV        = 4
+	ATR_PERIOD     = 4
+	ATR_HHV        = 5
 )
 
 var Strategy = qqq{}
@@ -33,10 +33,6 @@ func (strategy qqq) Interval() uint8 {
 	return 5
 }
 
-func (strategy qqq) Cooldown(periods uint8) time.Duration {
-	return time.Minute * time.Duration(strategy.Interval()*periods)
-}
-
 func (strategy qqq) PositionSymbols() map[sentio.Side]string {
 	return map[sentio.Side]string{
 		sentio.BASE:  "QQQ",
@@ -86,6 +82,7 @@ func (strategy qqq) Handle(market sentio.Market, probability sentio.Probability)
 	}
 
 	// update stoplosses or close running orders
+	hasClosedOrders := false
 	for i := range orders {
 		if strategy.PositionSymbols()[sentio.LONG] == orders[i].GetSymbol() &&
 			probability.Value < 1.0008 {
@@ -93,6 +90,7 @@ func (strategy qqq) Handle(market sentio.Market, probability sentio.Probability)
 				return err
 			}
 
+			hasClosedOrders = true
 			continue
 		}
 
@@ -102,6 +100,7 @@ func (strategy qqq) Handle(market sentio.Market, probability sentio.Probability)
 				return err
 			}
 
+			hasClosedOrders = true
 			continue
 		}
 
@@ -114,6 +113,11 @@ func (strategy qqq) Handle(market sentio.Market, probability sentio.Probability)
 		}
 	}
 
+	// Prevent new orders if we just closed one
+	if hasClosedOrders {
+		return nil
+	}
+
 	if probability.TS.Add(time.Minute * time.Duration(int64(strategy.Interval()/2))).Before(now.Round(time.Minute)) {
 		return nil
 	}

+ 10 - 7
strategy/alpaca/qqq15_nodelay/strategy.go

@@ -4,13 +4,12 @@ import (
 	"git.beejay.kim/Gshopper/sentio"
 	"git.beejay.kim/Gshopper/sentio/indicator"
 	"git.beejay.kim/Gshopper/sentio/util"
-	"time"
 )
 
 const (
 	ATR_MULTIPLIER = 1.5
-	ATR_PERIOD     = 5
-	ATR_HHV        = 4
+	ATR_PERIOD     = 4
+	ATR_HHV        = 5
 )
 
 var Strategy = qqq{}
@@ -33,10 +32,6 @@ func (strategy qqq) Interval() uint8 {
 	return 5
 }
 
-func (strategy qqq) Cooldown(periods uint8) time.Duration {
-	return time.Minute * time.Duration(strategy.Interval()*periods)
-}
-
 func (strategy qqq) PositionSymbols() map[sentio.Side]string {
 	return map[sentio.Side]string{
 		sentio.BASE:  "QQQ",
@@ -86,6 +81,7 @@ func (strategy qqq) Handle(market sentio.Market, probability sentio.Probability)
 	}
 
 	// update stoplosses or close running orders
+	hasClosedOrders := false
 	for i := range orders {
 		if strategy.PositionSymbols()[sentio.LONG] == orders[i].GetSymbol() &&
 			probability.Value < 1.0008 {
@@ -93,6 +89,7 @@ func (strategy qqq) Handle(market sentio.Market, probability sentio.Probability)
 				return err
 			}
 
+			hasClosedOrders = true
 			continue
 		}
 
@@ -102,6 +99,7 @@ func (strategy qqq) Handle(market sentio.Market, probability sentio.Probability)
 				return err
 			}
 
+			hasClosedOrders = true
 			continue
 		}
 
@@ -114,6 +112,11 @@ func (strategy qqq) Handle(market sentio.Market, probability sentio.Probability)
 		}
 	}
 
+	// Prevent new orders if we just closed one
+	if hasClosedOrders {
+		return nil
+	}
+
 	//if probability.TS.Add(time.Minute * time.Duration(int64(strategy.Interval()/2))).Before(now.Round(time.Minute)) {
 	//	return nil
 	//}

+ 1 - 1
util/order.go

@@ -54,7 +54,7 @@ func CreateOrder(
 	// Prevent cases when order will be closed ASAP they were opened.
 	// Also, Alpaca requires at least 0.01 gap against base_price
 	if sl[symbol] >= q[symbol].BidPrice-0.011 {
-		return sentio.ErrTooSmallOrder
+		return sentio.ErrHighStoploss
 	}
 
 	if account, err = m.Account(); err != nil {