123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- package util
- import (
- "errors"
- "git.beejay.kim/Gshopper/sentio"
- "math"
- )
- const TradingRange = .02
- func NewOrder(
- m sentio.Market,
- s sentio.Strategy,
- action sentio.Action,
- quotes map[string]sentio.Quote,
- rm sentio.RiskManager,
- ) (opts sentio.OrderOptions, err error) {
- var (
- side sentio.Side
- bid float64
- ok bool
- )
- if side = sentio.ActionToSide(action); sentio.BASE == side {
- err = errors.New("`CreateOrder`: do nothing while `sentio.BASE`")
- return
- }
- if opts.Symbol, ok = s.PositionSymbols()[side]; !ok {
- err = errors.New("`CreateOrder`: unknown Side for the current strategy")
- }
- bid = sentio.ToFixed(quotes[opts.Symbol].BidPrice, 2)
- opts.Action = sentio.Action_BUY
- opts.TakeProfit = sentio.ToFixed(rm.TakeProfit(opts.Symbol, bid), 2)
- opts.StopLoss = sentio.ToFixed(rm.StopLoss(opts.Symbol, bid), 2)
- // Prevent orders those have too small expected profit
- if opts.TakeProfit < bid*(1+TradingRange) {
- err = sentio.ErrLowTakeProfit
- return
- }
- // Prevent cases when order will be closed ASAP they were opened.
- // Also, Alpaca requires at least 0.01 gap against base_price
- if opts.StopLoss > bid*(1-TradingRange) {
- err = sentio.ErrHighStoploss
- return
- }
- // Invert OrderOptions if we will do SHORT for BASE symbol
- if sentio.SHORT == side && s.PositionSymbols()[sentio.BASE] == opts.Symbol {
- tmp := opts.StopLoss
- opts.StopLoss = opts.TakeProfit
- opts.TakeProfit = tmp
- opts.Action = sentio.Action_SELL
- }
- var (
- account sentio.MarketAccount
- cash float64
- ratio float64
- )
- if account, err = m.Account(); err != nil {
- return
- }
- cash = account.GetCash(false)
- if budget := m.MaxBudget(); budget > 0 && cash > budget {
- cash = budget
- }
- if cash <= bid {
- err = sentio.ErrTooSmallOrder
- return
- }
- if ratio = rm.GetOrderSize(opts.Symbol, bid); ratio <= 0 {
- err = sentio.ErrRiskManagementPrevent
- return
- }
- if opts.Size = uint(math.Floor(cash * ratio / bid)); opts.Size < 1 {
- err = sentio.ErrTooSmallOrder
- }
- return opts, nil
- }
- func CloseAllOrders(m sentio.Market, s sentio.Strategy) error {
- var (
- symbols = Symbols(s)
- orders []sentio.Order
- err error
- )
- if orders, err = m.Orders(sentio.OrderListCriteria{
- Status: "open",
- Symbols: symbols,
- }); err != nil {
- return err
- }
- for i := range orders {
- if _, err = m.CloseOrder(orders[i], nil); err != nil {
- return err
- }
- }
- return nil
- }
|