Browse Source

BaseStrategy

- refactoring
Alexey Kim 3 days ago
parent
commit
239b436773
2 changed files with 274 additions and 6 deletions
  1. 137 3
      strategy/alpaca/qqq15/strategy.go
  2. 137 3
      strategy/alpaca/qqq15_nodelay/strategy.go

+ 137 - 3
strategy/alpaca/qqq15/strategy.go

@@ -1,15 +1,16 @@
 package main
 
 import (
+	"errors"
 	"git.beejay.kim/Gshopper/sentio"
+	"git.beejay.kim/Gshopper/sentio/indicator"
+	"math"
 	"time"
 )
 
 var Strategy = qqq{}
 
-type qqq struct {
-	sentio.BaseStrategy
-}
+type qqq struct{}
 
 func (strategy qqq) Name() string {
 	return "Alpaca: QQQ [TQQQ : SQQQ]"
@@ -139,3 +140,136 @@ func (strategy qqq) Handle(market sentio.Market, probability sentio.Probability)
 
 	return strategy.CreateOrder(market, t, probability, portfolio, quotes, stoplosses)
 }
+
+func (strategy qqq) Symbols() []string {
+	var symbols []string
+
+	for side, s := range strategy.PositionSymbols() {
+		if sentio.BASE == side {
+			continue
+		}
+
+		symbols = append(symbols, s)
+	}
+
+	return symbols
+}
+
+func (strategy qqq) CloseAllOrders(market sentio.Market) error {
+	var (
+		symbols = strategy.Symbols()
+		orders  []sentio.Order
+		err     error
+	)
+
+	if orders, err = market.Orders(sentio.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 qqq) AtrStopLoss(market sentio.Market, symbols ...string) (map[string]float64, error) {
+	var (
+		stoplosses map[string]float64
+		bars       map[string][]sentio.Bar
+		err        error
+	)
+
+	if bars, err = market.HistoricalBars(symbols, time.Minute, nil); err != nil {
+		return nil, err
+	}
+
+	if bars == nil || len(bars) < sentio.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, sentio.ATR_PERIOD, sentio.ATR_MULTIPLIER, sentio.ATR_HHV)
+		stoplosses[s] = trailing[len(trailing)-1]
+	}
+
+	return stoplosses, nil
+}
+
+func (strategy qqq) CreateOrder(m sentio.Market, t sentio.Side, proba sentio.Probability, p sentio.Portfolio, q map[string]sentio.Quote, sl map[string]float64) error {
+	var (
+		symbol    = strategy.PositionSymbols()[t]
+		position  sentio.Position
+		account   sentio.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] < sentio.ATR_STOPLOSS_THRESHOLD {
+		return nil
+	}
+
+	if account, err = m.Account(); err != nil {
+		return err
+	}
+
+	if account.GetCash() < q[symbol].BidPrice {
+		return sentio.ErrTooSmallOrder
+	}
+
+	if !has && proba.Value > threshold {
+
+		// create a new order
+		if size = uint(math.Floor(account.GetCash() * .7 / q[symbol].BidPrice)); size < 1 {
+			return sentio.ErrTooSmallOrder
+		}
+
+		_, err = m.CreateOrder(symbol, size, sl[symbol])
+		return err
+
+	} else if has && position.GetAvgPrice()/position.GetCurrentPrice() > sentio.EXTRA_POSITION_THRESHOLD {
+
+		// create an extra position
+		if size = uint(math.Floor(account.GetCash() * .5 / q[symbol].BidPrice)); size < 1 {
+			return sentio.ErrTooSmallOrder
+		}
+
+		_, err = m.CreateOrder(symbol, size, sl[symbol])
+		return err
+	}
+
+	return nil
+}

+ 137 - 3
strategy/alpaca/qqq15_nodelay/strategy.go

@@ -1,15 +1,16 @@
 package main
 
 import (
+	"errors"
 	"git.beejay.kim/Gshopper/sentio"
+	"git.beejay.kim/Gshopper/sentio/indicator"
+	"math"
 	"time"
 )
 
 var Strategy = qqq{}
 
-type qqq struct {
-	sentio.BaseStrategy
-}
+type qqq struct{}
 
 func (strategy qqq) Name() string {
 	return "Alpaca: QQQ [TQQQ : SQQQ]"
@@ -139,3 +140,136 @@ func (strategy qqq) Handle(market sentio.Market, probability sentio.Probability)
 
 	return strategy.CreateOrder(market, t, probability, portfolio, quotes, stoplosses)
 }
+
+func (strategy qqq) Symbols() []string {
+	var symbols []string
+
+	for side, s := range strategy.PositionSymbols() {
+		if sentio.BASE == side {
+			continue
+		}
+
+		symbols = append(symbols, s)
+	}
+
+	return symbols
+}
+
+func (strategy qqq) CloseAllOrders(market sentio.Market) error {
+	var (
+		symbols = strategy.Symbols()
+		orders  []sentio.Order
+		err     error
+	)
+
+	if orders, err = market.Orders(sentio.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 qqq) AtrStopLoss(market sentio.Market, symbols ...string) (map[string]float64, error) {
+	var (
+		stoplosses map[string]float64
+		bars       map[string][]sentio.Bar
+		err        error
+	)
+
+	if bars, err = market.HistoricalBars(symbols, time.Minute, nil); err != nil {
+		return nil, err
+	}
+
+	if bars == nil || len(bars) < sentio.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, sentio.ATR_PERIOD, sentio.ATR_MULTIPLIER, sentio.ATR_HHV)
+		stoplosses[s] = trailing[len(trailing)-1]
+	}
+
+	return stoplosses, nil
+}
+
+func (strategy qqq) CreateOrder(m sentio.Market, t sentio.Side, proba sentio.Probability, p sentio.Portfolio, q map[string]sentio.Quote, sl map[string]float64) error {
+	var (
+		symbol    = strategy.PositionSymbols()[t]
+		position  sentio.Position
+		account   sentio.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] < sentio.ATR_STOPLOSS_THRESHOLD {
+		return nil
+	}
+
+	if account, err = m.Account(); err != nil {
+		return err
+	}
+
+	if account.GetCash() < q[symbol].BidPrice {
+		return sentio.ErrTooSmallOrder
+	}
+
+	if !has && proba.Value > threshold {
+
+		// create a new order
+		if size = uint(math.Floor(account.GetCash() * .7 / q[symbol].BidPrice)); size < 1 {
+			return sentio.ErrTooSmallOrder
+		}
+
+		_, err = m.CreateOrder(symbol, size, sl[symbol])
+		return err
+
+	} else if has && position.GetAvgPrice()/position.GetCurrentPrice() > sentio.EXTRA_POSITION_THRESHOLD {
+
+		// create an extra position
+		if size = uint(math.Floor(account.GetCash() * .5 / q[symbol].BidPrice)); size < 1 {
+			return sentio.ErrTooSmallOrder
+		}
+
+		_, err = m.CreateOrder(symbol, size, sl[symbol])
+		return err
+	}
+
+	return nil
+}