mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-09 07:26:48 +00:00
order: slight optimizations (#917)
* order: slight optimizations * orders: add benchmarks, small optimize and change order side to uin8 for comparitive optimizations. * orders: continue to convert string type -> uint * orders/backtester: interim move type to orders package, later can expand or deprecate. * orders: handle errors * orders: optimize filters and remove error returns when its clearly not needed * orders: remove log call * backtester: zero value check * orders/futures: zero value -> flag * linter: fix * linter: more fixes * linters: rides again * glorious: nits * common: Add zero value unix check for time values; also addresses glorious nits * glorious scott: nits Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io>
This commit is contained in:
@@ -14,7 +14,22 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/validate"
|
||||
)
|
||||
|
||||
var errTimeInForceConflict = errors.New("multiple time in force options applied")
|
||||
const (
|
||||
orderSubmissionValidSides = Buy | Sell | Bid | Ask | Long | Short
|
||||
shortSide = Short | Sell | Ask
|
||||
longSide = Long | Buy | Bid
|
||||
inactiveStatuses = Filled | Cancelled | InsufficientBalance | MarketUnavailable | Rejected | PartiallyCancelled | Expired | Closed | AnyStatus | Cancelling
|
||||
activeStatuses = Active | Open | PartiallyFilled | New | PendingCancel | Hidden | AutoDeleverage | Pending
|
||||
bypassSideFilter = UnknownSide | AnySide
|
||||
bypassTypeFilter = UnknownType | AnyType
|
||||
)
|
||||
|
||||
var (
|
||||
errTimeInForceConflict = errors.New("multiple time in force options applied")
|
||||
errUnrecognisedOrderSide = errors.New("unrecognised order side")
|
||||
errUnrecognisedOrderType = errors.New("unrecognised order type")
|
||||
errUnrecognisedOrderStatus = errors.New("unrecognised order status")
|
||||
)
|
||||
|
||||
// Validate checks the supplied data and returns whether or not it's valid
|
||||
func (s *Submit) Validate(opt ...validate.Checker) error {
|
||||
@@ -30,10 +45,7 @@ func (s *Submit) Validate(opt ...validate.Checker) error {
|
||||
return ErrAssetNotSet
|
||||
}
|
||||
|
||||
if s.Side != Buy &&
|
||||
s.Side != Sell &&
|
||||
s.Side != Bid &&
|
||||
s.Side != Ask {
|
||||
if s.Side == UnknownSide || orderSubmissionValidSides&s.Side != s.Side {
|
||||
return ErrSideIsInvalid
|
||||
}
|
||||
|
||||
@@ -145,15 +157,15 @@ func (d *Detail) UpdateOrderFromDetail(m *Detail) {
|
||||
d.WalletAddress = m.WalletAddress
|
||||
updated = true
|
||||
}
|
||||
if m.Type != "" && m.Type != d.Type {
|
||||
if m.Type != UnknownType && m.Type != d.Type {
|
||||
d.Type = m.Type
|
||||
updated = true
|
||||
}
|
||||
if m.Side != "" && m.Side != d.Side {
|
||||
if m.Side != UnknownSide && m.Side != d.Side {
|
||||
d.Side = m.Side
|
||||
updated = true
|
||||
}
|
||||
if m.Status != "" && m.Status != d.Status {
|
||||
if m.Status != UnknownStatus && m.Status != d.Status {
|
||||
d.Status = m.Status
|
||||
updated = true
|
||||
}
|
||||
@@ -161,53 +173,51 @@ func (d *Detail) UpdateOrderFromDetail(m *Detail) {
|
||||
d.AssetType = m.AssetType
|
||||
updated = true
|
||||
}
|
||||
if m.Trades != nil {
|
||||
for x := range m.Trades {
|
||||
var found bool
|
||||
for y := range d.Trades {
|
||||
if d.Trades[y].TID != m.Trades[x].TID {
|
||||
continue
|
||||
}
|
||||
found = true
|
||||
if d.Trades[y].Fee != m.Trades[x].Fee {
|
||||
d.Trades[y].Fee = m.Trades[x].Fee
|
||||
updated = true
|
||||
}
|
||||
if m.Trades[x].Price != 0 && d.Trades[y].Price != m.Trades[x].Price {
|
||||
d.Trades[y].Price = m.Trades[x].Price
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Side != m.Trades[x].Side {
|
||||
d.Trades[y].Side = m.Trades[x].Side
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Type != m.Trades[x].Type {
|
||||
d.Trades[y].Type = m.Trades[x].Type
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Description != m.Trades[x].Description {
|
||||
d.Trades[y].Description = m.Trades[x].Description
|
||||
updated = true
|
||||
}
|
||||
if m.Trades[x].Amount != 0 && d.Trades[y].Amount != m.Trades[x].Amount {
|
||||
d.Trades[y].Amount = m.Trades[x].Amount
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Timestamp != m.Trades[x].Timestamp {
|
||||
d.Trades[y].Timestamp = m.Trades[x].Timestamp
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].IsMaker != m.Trades[x].IsMaker {
|
||||
d.Trades[y].IsMaker = m.Trades[x].IsMaker
|
||||
updated = true
|
||||
}
|
||||
for x := range m.Trades {
|
||||
var found bool
|
||||
for y := range d.Trades {
|
||||
if d.Trades[y].TID != m.Trades[x].TID {
|
||||
continue
|
||||
}
|
||||
if !found {
|
||||
d.Trades = append(d.Trades, m.Trades[x])
|
||||
found = true
|
||||
if d.Trades[y].Fee != m.Trades[x].Fee {
|
||||
d.Trades[y].Fee = m.Trades[x].Fee
|
||||
updated = true
|
||||
}
|
||||
if m.Trades[x].Price != 0 && d.Trades[y].Price != m.Trades[x].Price {
|
||||
d.Trades[y].Price = m.Trades[x].Price
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Side != m.Trades[x].Side {
|
||||
d.Trades[y].Side = m.Trades[x].Side
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Type != m.Trades[x].Type {
|
||||
d.Trades[y].Type = m.Trades[x].Type
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Description != m.Trades[x].Description {
|
||||
d.Trades[y].Description = m.Trades[x].Description
|
||||
updated = true
|
||||
}
|
||||
if m.Trades[x].Amount != 0 && d.Trades[y].Amount != m.Trades[x].Amount {
|
||||
d.Trades[y].Amount = m.Trades[x].Amount
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Timestamp != m.Trades[x].Timestamp {
|
||||
d.Trades[y].Timestamp = m.Trades[x].Timestamp
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].IsMaker != m.Trades[x].IsMaker {
|
||||
d.Trades[y].IsMaker = m.Trades[x].IsMaker
|
||||
updated = true
|
||||
}
|
||||
m.RemainingAmount -= m.Trades[x].Amount
|
||||
}
|
||||
if !found {
|
||||
d.Trades = append(d.Trades, m.Trades[x])
|
||||
updated = true
|
||||
}
|
||||
m.RemainingAmount -= m.Trades[x].Amount
|
||||
}
|
||||
if m.RemainingAmount > 0 && m.RemainingAmount != d.RemainingAmount {
|
||||
d.RemainingAmount = m.RemainingAmount
|
||||
@@ -309,15 +319,15 @@ func (d *Detail) UpdateOrderFromModify(m *Modify) {
|
||||
d.WalletAddress = m.WalletAddress
|
||||
updated = true
|
||||
}
|
||||
if m.Type != "" && m.Type != d.Type {
|
||||
if m.Type != UnknownType && m.Type != d.Type {
|
||||
d.Type = m.Type
|
||||
updated = true
|
||||
}
|
||||
if m.Side != "" && m.Side != d.Side {
|
||||
if m.Side != UnknownSide && m.Side != d.Side {
|
||||
d.Side = m.Side
|
||||
updated = true
|
||||
}
|
||||
if m.Status != "" && m.Status != d.Status {
|
||||
if m.Status != UnknownStatus && m.Status != d.Status {
|
||||
d.Status = m.Status
|
||||
updated = true
|
||||
}
|
||||
@@ -325,53 +335,51 @@ func (d *Detail) UpdateOrderFromModify(m *Modify) {
|
||||
d.AssetType = m.AssetType
|
||||
updated = true
|
||||
}
|
||||
if m.Trades != nil {
|
||||
for x := range m.Trades {
|
||||
var found bool
|
||||
for y := range d.Trades {
|
||||
if d.Trades[y].TID != m.Trades[x].TID {
|
||||
continue
|
||||
}
|
||||
found = true
|
||||
if d.Trades[y].Fee != m.Trades[x].Fee {
|
||||
d.Trades[y].Fee = m.Trades[x].Fee
|
||||
updated = true
|
||||
}
|
||||
if m.Trades[x].Price != 0 && d.Trades[y].Price != m.Trades[x].Price {
|
||||
d.Trades[y].Price = m.Trades[x].Price
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Side != m.Trades[x].Side {
|
||||
d.Trades[y].Side = m.Trades[x].Side
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Type != m.Trades[x].Type {
|
||||
d.Trades[y].Type = m.Trades[x].Type
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Description != m.Trades[x].Description {
|
||||
d.Trades[y].Description = m.Trades[x].Description
|
||||
updated = true
|
||||
}
|
||||
if m.Trades[x].Amount != 0 && d.Trades[y].Amount != m.Trades[x].Amount {
|
||||
d.Trades[y].Amount = m.Trades[x].Amount
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Timestamp != m.Trades[x].Timestamp {
|
||||
d.Trades[y].Timestamp = m.Trades[x].Timestamp
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].IsMaker != m.Trades[x].IsMaker {
|
||||
d.Trades[y].IsMaker = m.Trades[x].IsMaker
|
||||
updated = true
|
||||
}
|
||||
for x := range m.Trades {
|
||||
var found bool
|
||||
for y := range d.Trades {
|
||||
if d.Trades[y].TID != m.Trades[x].TID {
|
||||
continue
|
||||
}
|
||||
if !found {
|
||||
d.Trades = append(d.Trades, m.Trades[x])
|
||||
found = true
|
||||
if d.Trades[y].Fee != m.Trades[x].Fee {
|
||||
d.Trades[y].Fee = m.Trades[x].Fee
|
||||
updated = true
|
||||
}
|
||||
if m.Trades[x].Price != 0 && d.Trades[y].Price != m.Trades[x].Price {
|
||||
d.Trades[y].Price = m.Trades[x].Price
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Side != m.Trades[x].Side {
|
||||
d.Trades[y].Side = m.Trades[x].Side
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Type != m.Trades[x].Type {
|
||||
d.Trades[y].Type = m.Trades[x].Type
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Description != m.Trades[x].Description {
|
||||
d.Trades[y].Description = m.Trades[x].Description
|
||||
updated = true
|
||||
}
|
||||
if m.Trades[x].Amount != 0 && d.Trades[y].Amount != m.Trades[x].Amount {
|
||||
d.Trades[y].Amount = m.Trades[x].Amount
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].Timestamp != m.Trades[x].Timestamp {
|
||||
d.Trades[y].Timestamp = m.Trades[x].Timestamp
|
||||
updated = true
|
||||
}
|
||||
if d.Trades[y].IsMaker != m.Trades[x].IsMaker {
|
||||
d.Trades[y].IsMaker = m.Trades[x].IsMaker
|
||||
updated = true
|
||||
}
|
||||
m.RemainingAmount -= m.Trades[x].Amount
|
||||
}
|
||||
if !found {
|
||||
d.Trades = append(d.Trades, m.Trades[x])
|
||||
updated = true
|
||||
}
|
||||
m.RemainingAmount -= m.Trades[x].Amount
|
||||
}
|
||||
if m.RemainingAmount > 0 && m.RemainingAmount != d.RemainingAmount {
|
||||
d.RemainingAmount = m.RemainingAmount
|
||||
@@ -401,13 +409,13 @@ func (d *Detail) MatchFilter(f *Filter) bool {
|
||||
if f.ID != "" && d.ID != f.ID {
|
||||
return false
|
||||
}
|
||||
if f.Type != "" && f.Type != AnyType && d.Type != f.Type {
|
||||
if f.Type != UnknownType && f.Type != AnyType && d.Type != f.Type {
|
||||
return false
|
||||
}
|
||||
if f.Side != "" && f.Side != AnySide && d.Side != f.Side {
|
||||
if f.Side != UnknownSide && f.Side != AnySide && d.Side != f.Side {
|
||||
return false
|
||||
}
|
||||
if f.Status != "" && f.Status != AnyStatus && d.Status != f.Status {
|
||||
if f.Status != UnknownStatus && f.Status != AnyStatus && d.Status != f.Status {
|
||||
return false
|
||||
}
|
||||
if f.ClientOrderID != "" && d.ClientOrderID != f.ClientOrderID {
|
||||
@@ -428,25 +436,21 @@ func (d *Detail) MatchFilter(f *Filter) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsActive returns true if an order has a status that indicates it is
|
||||
// currently available on the exchange
|
||||
// IsActive returns true if an order has a status that indicates it is currently
|
||||
// available on the exchange
|
||||
func (d *Detail) IsActive() bool {
|
||||
if d.Amount <= 0 || d.Amount <= d.ExecutedAmount {
|
||||
return false
|
||||
}
|
||||
return d.Status == Active || d.Status == Open || d.Status == PartiallyFilled || d.Status == New ||
|
||||
d.Status == AnyStatus || d.Status == PendingCancel || d.Status == Hidden || d.Status == UnknownStatus ||
|
||||
d.Status == AutoDeleverage || d.Status == Pending
|
||||
return d.Status != UnknownStatus &&
|
||||
d.Amount > 0 &&
|
||||
d.Amount > d.ExecutedAmount &&
|
||||
activeStatuses&d.Status == d.Status
|
||||
}
|
||||
|
||||
// IsInactive returns true if an order has a status that indicates it is
|
||||
// currently not available on the exchange
|
||||
func (d *Detail) IsInactive() bool {
|
||||
if d.Amount <= 0 || d.Amount <= d.ExecutedAmount {
|
||||
return true
|
||||
}
|
||||
return d.Status == Filled || d.Status == Cancelled || d.Status == InsufficientBalance || d.Status == MarketUnavailable ||
|
||||
d.Status == Rejected || d.Status == PartiallyCancelled || d.Status == Expired || d.Status == Closed
|
||||
return d.Amount <= 0 ||
|
||||
d.Amount <= d.ExecutedAmount ||
|
||||
inactiveStatuses&d.Status == d.Status
|
||||
}
|
||||
|
||||
// GenerateInternalOrderID sets a new V4 order ID or a V5 order ID if
|
||||
@@ -474,50 +478,151 @@ func (d *Detail) Copy() Detail {
|
||||
|
||||
// String implements the stringer interface
|
||||
func (t Type) String() string {
|
||||
return string(t)
|
||||
switch t {
|
||||
case AnyType:
|
||||
return "ANY"
|
||||
case Limit:
|
||||
return "LIMIT"
|
||||
case Market:
|
||||
return "MARKET"
|
||||
case PostOnly:
|
||||
return "POST_ONLY"
|
||||
case ImmediateOrCancel:
|
||||
return "IMMEDIATE_OR_CANCEL"
|
||||
case Stop:
|
||||
return "STOP"
|
||||
case StopLimit:
|
||||
return "STOP LIMIT"
|
||||
case StopMarket:
|
||||
return "STOP MARKET"
|
||||
case TakeProfit:
|
||||
return "TAKE PROFIT"
|
||||
case TakeProfitMarket:
|
||||
return "TAKE PROFIT MARKET"
|
||||
case TrailingStop:
|
||||
return "TRAILING_STOP"
|
||||
case FillOrKill:
|
||||
return "FOK"
|
||||
case IOS:
|
||||
return "IOS"
|
||||
case Liquidation:
|
||||
return "LIQUIDATION"
|
||||
case Trigger:
|
||||
return "TRIGGER"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
// Lower returns the type lower case string
|
||||
func (t Type) Lower() string {
|
||||
return strings.ToLower(string(t))
|
||||
return strings.ToLower(t.String())
|
||||
}
|
||||
|
||||
// Title returns the type titleized, eg "Limit"
|
||||
func (t Type) Title() string {
|
||||
return strings.Title(strings.ToLower(string(t))) // nolint:staticcheck // Ignore Title usage warning
|
||||
return strings.Title(strings.ToLower(t.String())) // nolint:staticcheck // Ignore Title usage warning
|
||||
}
|
||||
|
||||
// String implements the stringer interface
|
||||
func (s Side) String() string {
|
||||
return string(s)
|
||||
switch s {
|
||||
case Buy:
|
||||
return "BUY"
|
||||
case Sell:
|
||||
return "SELL"
|
||||
case Bid:
|
||||
return "BID"
|
||||
case Ask:
|
||||
return "ASK"
|
||||
case Long:
|
||||
return "LONG"
|
||||
case Short:
|
||||
return "SHORT"
|
||||
case AnySide:
|
||||
return "ANY"
|
||||
// Backtester signal types below.
|
||||
case DoNothing:
|
||||
return "DO NOTHING"
|
||||
case TransferredFunds:
|
||||
return "TRANSFERRED FUNDS"
|
||||
case CouldNotBuy:
|
||||
return "COULD NOT BUY"
|
||||
case CouldNotSell:
|
||||
return "COULD NOT SELL"
|
||||
case MissingData:
|
||||
return "MISSING DATA"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
// Lower returns the side lower case string
|
||||
func (s Side) Lower() string {
|
||||
return strings.ToLower(string(s))
|
||||
return strings.ToLower(s.String())
|
||||
}
|
||||
|
||||
// Title returns the side titleized, eg "Buy"
|
||||
func (s Side) Title() string {
|
||||
return strings.Title(strings.ToLower(string(s))) // nolint:staticcheck // Ignore Title usage warning
|
||||
return strings.Title(strings.ToLower(s.String())) // nolint:staticcheck // Ignore Title usage warning
|
||||
}
|
||||
|
||||
// IsShort returns if the side is short
|
||||
func (s Side) IsShort() bool {
|
||||
return s == Short || s == Sell
|
||||
return s != UnknownSide && shortSide&s == s
|
||||
}
|
||||
|
||||
// IsLong returns if the side is long
|
||||
func (s Side) IsLong() bool {
|
||||
return s == Long || s == Buy
|
||||
return s != UnknownSide && longSide&s == s
|
||||
}
|
||||
|
||||
// String implements the stringer interface
|
||||
func (s Status) String() string {
|
||||
return string(s)
|
||||
switch s {
|
||||
case AnyStatus:
|
||||
return "ANY"
|
||||
case New:
|
||||
return "NEW"
|
||||
case Active:
|
||||
return "ACTIVE"
|
||||
case PartiallyCancelled:
|
||||
return "PARTIALLY_CANCELLED"
|
||||
case PartiallyFilled:
|
||||
return "PARTIALLY_FILLED"
|
||||
case Filled:
|
||||
return "FILLED"
|
||||
case Cancelled:
|
||||
return "CANCELLED"
|
||||
case PendingCancel:
|
||||
return "PENDING_CANCEL"
|
||||
case InsufficientBalance:
|
||||
return "INSUFFICIENT_BALANCE"
|
||||
case MarketUnavailable:
|
||||
return "MARKET_UNAVAILABLE"
|
||||
case Rejected:
|
||||
return "REJECTED"
|
||||
case Expired:
|
||||
return "EXPIRED"
|
||||
case Hidden:
|
||||
return "HIDDEN"
|
||||
case Open:
|
||||
return "OPEN"
|
||||
case AutoDeleverage:
|
||||
return "ADL"
|
||||
case Closed:
|
||||
return "CLOSED"
|
||||
case Pending:
|
||||
return "PENDING"
|
||||
case Cancelling:
|
||||
return "CANCELLING"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
// InferCostsAndTimes infer order costs using execution information and times when available
|
||||
// InferCostsAndTimes infer order costs using execution information and times
|
||||
// when available
|
||||
func (d *Detail) InferCostsAndTimes() {
|
||||
if d.CostAsset.IsEmpty() {
|
||||
d.CostAsset = d.Pair.Quote
|
||||
@@ -547,83 +652,86 @@ func (d *Detail) InferCostsAndTimes() {
|
||||
}
|
||||
}
|
||||
|
||||
// FilterOrdersBySide removes any order details that don't match the
|
||||
// order status provided
|
||||
// FilterOrdersBySide removes any order details that don't match the order
|
||||
// status provided
|
||||
func FilterOrdersBySide(orders *[]Detail, side Side) {
|
||||
if side == "" || side == AnySide {
|
||||
if bypassSideFilter&side == side || len(*orders) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var filteredOrders []Detail
|
||||
target := 0
|
||||
for i := range *orders {
|
||||
if strings.EqualFold(string((*orders)[i].Side), string(side)) {
|
||||
filteredOrders = append(filteredOrders, (*orders)[i])
|
||||
if (*orders)[i].Side == side {
|
||||
(*orders)[target] = (*orders)[i]
|
||||
target++
|
||||
}
|
||||
}
|
||||
|
||||
*orders = filteredOrders
|
||||
*orders = (*orders)[:target]
|
||||
}
|
||||
|
||||
// FilterOrdersByType removes any order details that don't match the order type
|
||||
// provided
|
||||
func FilterOrdersByType(orders *[]Detail, orderType Type) {
|
||||
if orderType == "" || orderType == AnyType {
|
||||
if bypassTypeFilter&orderType == orderType || len(*orders) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var filteredOrders []Detail
|
||||
target := 0
|
||||
for i := range *orders {
|
||||
if strings.EqualFold(string((*orders)[i].Type), string(orderType)) {
|
||||
filteredOrders = append(filteredOrders, (*orders)[i])
|
||||
if (*orders)[i].Type == orderType {
|
||||
(*orders)[target] = (*orders)[i]
|
||||
target++
|
||||
}
|
||||
}
|
||||
|
||||
*orders = filteredOrders
|
||||
*orders = (*orders)[:target]
|
||||
}
|
||||
|
||||
// FilterOrdersByTimeRange removes any OrderDetails outside of the time range
|
||||
func FilterOrdersByTimeRange(orders *[]Detail, startTime, endTime time.Time) {
|
||||
if startTime.IsZero() ||
|
||||
endTime.IsZero() ||
|
||||
startTime.Unix() == 0 ||
|
||||
endTime.Unix() == 0 ||
|
||||
endTime.Before(startTime) {
|
||||
return
|
||||
func FilterOrdersByTimeRange(orders *[]Detail, startTime, endTime time.Time) error {
|
||||
if len(*orders) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var filteredOrders []Detail
|
||||
if err := common.StartEndTimeCheck(startTime, endTime); err != nil {
|
||||
if errors.Is(err, common.ErrDateUnset) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("cannot filter orders by time range %w", err)
|
||||
}
|
||||
|
||||
target := 0
|
||||
for i := range *orders {
|
||||
if ((*orders)[i].Date.Unix() >= startTime.Unix() && (*orders)[i].Date.Unix() <= endTime.Unix()) ||
|
||||
(*orders)[i].Date.IsZero() {
|
||||
filteredOrders = append(filteredOrders, (*orders)[i])
|
||||
(*orders)[target] = (*orders)[i]
|
||||
target++
|
||||
}
|
||||
}
|
||||
|
||||
*orders = filteredOrders
|
||||
*orders = (*orders)[:target]
|
||||
return nil
|
||||
}
|
||||
|
||||
// FilterOrdersByCurrencies removes any order details that do not match the
|
||||
// provided currency list. It is forgiving in that the provided currencies can
|
||||
// match quote or base currencies
|
||||
func FilterOrdersByCurrencies(orders *[]Detail, currencies []currency.Pair) {
|
||||
if len(currencies) == 0 {
|
||||
return
|
||||
}
|
||||
if len(currencies) == 1 && currencies[0].IsEmpty() {
|
||||
// FilterOrdersByPairs removes any order details that do not match the
|
||||
// provided currency pairs list. It is forgiving in that the provided pairs can
|
||||
// match quote or base pairs
|
||||
func FilterOrdersByPairs(orders *[]Detail, pairs []currency.Pair) {
|
||||
if len(pairs) == 0 ||
|
||||
(len(pairs) == 1 && pairs[0].IsEmpty()) ||
|
||||
len(*orders) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var filteredOrders []Detail
|
||||
for i := range *orders {
|
||||
for _, c := range currencies {
|
||||
if (*orders)[i].Pair.EqualIncludeReciprocal(c) {
|
||||
filteredOrders = append(filteredOrders, (*orders)[i])
|
||||
target := 0
|
||||
for x := range *orders {
|
||||
for y := range pairs {
|
||||
if (*orders)[x].Pair.EqualIncludeReciprocal(pairs[y]) {
|
||||
(*orders)[target] = (*orders)[x]
|
||||
target++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*orders = filteredOrders
|
||||
*orders = (*orders)[:target]
|
||||
}
|
||||
|
||||
func (b ByPrice) Len() int {
|
||||
@@ -735,23 +843,23 @@ func SortOrdersBySide(orders *[]Detail, reverse bool) {
|
||||
// and returning a real Side
|
||||
func StringToOrderSide(side string) (Side, error) {
|
||||
side = strings.ToUpper(side)
|
||||
switch Side(side) {
|
||||
case Buy:
|
||||
switch side {
|
||||
case Buy.String():
|
||||
return Buy, nil
|
||||
case Sell:
|
||||
case Sell.String():
|
||||
return Sell, nil
|
||||
case Bid:
|
||||
case Bid.String():
|
||||
return Bid, nil
|
||||
case Ask:
|
||||
case Ask.String():
|
||||
return Ask, nil
|
||||
case Long:
|
||||
case Long.String():
|
||||
return Long, nil
|
||||
case Short:
|
||||
case Short.String():
|
||||
return Short, nil
|
||||
case AnySide:
|
||||
case AnySide.String():
|
||||
return AnySide, nil
|
||||
default:
|
||||
return UnknownSide, errors.New(side + " not recognised as order side")
|
||||
return UnknownSide, fmt.Errorf("'%s' %w", side, errUnrecognisedOrderSide)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,7 +891,7 @@ func StringToOrderType(oType string) (Type, error) {
|
||||
case Trigger.String():
|
||||
return Trigger, nil
|
||||
default:
|
||||
return UnknownType, errors.New(oType + " not recognised as order type")
|
||||
return UnknownType, fmt.Errorf("'%v' %w", oType, errUnrecognisedOrderType)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -822,8 +930,10 @@ func StringToOrderStatus(status string) (Status, error) {
|
||||
return InsufficientBalance, nil
|
||||
case MarketUnavailable.String():
|
||||
return MarketUnavailable, nil
|
||||
case Cancelling.String():
|
||||
return Cancelling, nil
|
||||
default:
|
||||
return UnknownStatus, errors.New(status + " not recognised as order status")
|
||||
return UnknownStatus, fmt.Errorf("'%s' %w", status, errUnrecognisedOrderStatus)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -891,7 +1001,7 @@ func (g *GetOrdersRequest) Validate(opt ...validate.Checker) error {
|
||||
return ErrGetOrdersRequestIsNil
|
||||
}
|
||||
if !g.AssetType.IsValid() {
|
||||
return fmt.Errorf("assetType %v not supported", g.AssetType)
|
||||
return fmt.Errorf("%v %w", g.AssetType, asset.ErrNotSupported)
|
||||
}
|
||||
var errs common.Errors
|
||||
for _, o := range opt {
|
||||
@@ -917,7 +1027,7 @@ func (m *Modify) Validate(opt ...validate.Checker) error {
|
||||
return ErrPairIsEmpty
|
||||
}
|
||||
|
||||
if m.AssetType.String() == "" {
|
||||
if m.AssetType == asset.Empty {
|
||||
return ErrAssetNotSet
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user