package util import ( "errors" "git.beejay.kim/Gshopper/sentio" "math" ) func CreateOrder( m sentio.Market, s sentio.Strategy, action sentio.Action, quotes map[string]sentio.Quote, rm sentio.RiskManager, ) error { var ( symbol string account sentio.MarketAccount size uint side sentio.Side bid float64 tp float64 sl float64 ok bool err error ) if side = sentio.ActionToSide(action); sentio.BASE == side { return errors.New("`CreateOrder`: do nothing while `sentio.BASE`") } if symbol, ok = s.PositionSymbols()[side]; !ok { return errors.New("`CreateOrder`: unknown Side for the current strategy") } bid = sentio.ToFixed(quotes[symbol].BidPrice, 2) tp = sentio.ToFixed(rm.TakeProfit(symbol, bid, false), 2) sl = sentio.ToFixed(rm.StopLoss(symbol, bid, false), 2) // Prevent orders those have too small expected profit if tp < bid+0.02 { return sentio.ErrLowTakeProfit } // Prevent cases when order will be closed ASAP they were opened. // Also, Alpaca requires at least 0.01 gap against base_price if sl > bid-0.01 { return sentio.ErrHighStoploss } if account, err = m.Account(); err != nil { return err } var ( cash = account.GetCash() ratio float64 ) if budget := m.MaxBudget(); budget > 0 && cash > budget { cash = budget } if cash < bid { return sentio.ErrTooSmallOrder } if ratio = rm.GetOrderSize(symbol, bid); ratio <= 0 { return sentio.ErrRiskManagementPrevent } // create a new order if size = uint(math.Floor(cash * ratio / bid)); size < 1 { return sentio.ErrTooSmallOrder } _, err = m.CreateOrder(symbol, 0, size, rm) return err } 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 }