collect error object instead of logging

This commit is contained in:
c9s 2020-11-09 15:29:40 +08:00
parent 8414f406bf
commit 1e129e4c86
2 changed files with 71 additions and 24 deletions

View File

@ -87,18 +87,22 @@ type BasicRiskController struct {
func (c *BasicRiskController) ProcessOrders(session *ExchangeSession, orders ...types.SubmitOrder) (outOrders []types.SubmitOrder, errs []error) { func (c *BasicRiskController) ProcessOrders(session *ExchangeSession, orders ...types.SubmitOrder) (outOrders []types.SubmitOrder, errs []error) {
balances := session.Account.Balances() balances := session.Account.Balances()
addError := func(err error) {
errs = append(errs, err)
}
accumulativeQuoteAmount := 0.0 accumulativeQuoteAmount := 0.0
accumulativeBaseSellQuantity := 0.0 accumulativeBaseSellQuantity := 0.0
for _, order := range orders { for _, order := range orders {
lastPrice, ok := session.LastPrice(order.Symbol) lastPrice, ok := session.LastPrice(order.Symbol)
if !ok { if !ok {
errs = append(errs, errors.Errorf("the last price of symbol %q is not found", order.Symbol)) addError(errors.Errorf("the last price of symbol %q is not found, order: %s", order.Symbol, order.String()))
continue continue
} }
market, ok := session.Market(order.Symbol) market, ok := session.Market(order.Symbol)
if !ok { if !ok {
errs = append(errs, errors.Errorf("the market config of symbol %q is not found", order.Symbol)) addError(errors.Errorf("the market config of symbol %q is not found, order: %s", order.Symbol, order.String()))
continue continue
} }
@ -114,14 +118,14 @@ func (c *BasicRiskController) ProcessOrders(session *ExchangeSession, orders ...
// Critical conditions for placing buy orders // Critical conditions for placing buy orders
quoteBalance, ok := balances[market.QuoteCurrency] quoteBalance, ok := balances[market.QuoteCurrency]
if !ok { if !ok {
c.Logger.Errorf("can not place buy order, quote balance %s not found", market.QuoteCurrency) addError(errors.Errorf("can not place buy order, quote balance %s not found", market.QuoteCurrency))
continue continue
} }
if quoteBalance.Available < c.MinQuoteBalance.Float64() { if quoteBalance.Available < c.MinQuoteBalance.Float64() {
c.Logger.WithError(ErrQuoteBalanceLevelTooLow).Errorf("can not place buy order, quote balance level is too low: %s < %s", addError(errors.Wrapf(ErrQuoteBalanceLevelTooLow, "can not place buy order, quote balance level is too low: %s < %s, order: %s",
types.USD.FormatMoneyFloat64(quoteBalance.Available), types.USD.FormatMoneyFloat64(quoteBalance.Available),
types.USD.FormatMoneyFloat64(c.MinQuoteBalance.Float64())) types.USD.FormatMoneyFloat64(c.MinQuoteBalance.Float64()), order.String()))
continue continue
} }
@ -135,7 +139,11 @@ func (c *BasicRiskController) ProcessOrders(session *ExchangeSession, orders ...
quoteAssetQuota := math.Max(0.0, quoteBalance.Available-c.MinQuoteBalance.Float64()) quoteAssetQuota := math.Max(0.0, quoteBalance.Available-c.MinQuoteBalance.Float64())
if quoteAssetQuota < market.MinAmount { if quoteAssetQuota < market.MinAmount {
c.Logger.WithError(ErrInsufficientQuoteBalance).Errorf("can not place buy order, insufficient quote balance: quota %f < min amount %f", quoteAssetQuota, market.MinAmount) addError(
errors.Wrapf(
ErrInsufficientQuoteBalance,
"can not place buy order, insufficient quote balance: quota %f < min amount %f, order: %s",
quoteAssetQuota, market.MinAmount, order.String()))
continue continue
} }
@ -144,7 +152,13 @@ func (c *BasicRiskController) ProcessOrders(session *ExchangeSession, orders ...
// if MaxBaseAssetBalance is enabled, we should check the current base asset balance // if MaxBaseAssetBalance is enabled, we should check the current base asset balance
if baseBalance, hasBaseAsset := balances[market.BaseCurrency]; hasBaseAsset && c.MaxBaseAssetBalance > 0 { if baseBalance, hasBaseAsset := balances[market.BaseCurrency]; hasBaseAsset && c.MaxBaseAssetBalance > 0 {
if baseBalance.Available > c.MaxBaseAssetBalance.Float64() { if baseBalance.Available > c.MaxBaseAssetBalance.Float64() {
c.Logger.WithError(ErrAssetBalanceLevelTooHigh).Errorf("should not place buy order, asset balance level is too high: %f > %f", baseBalance.Available, c.MaxBaseAssetBalance.Float64()) addError(
errors.Wrapf(
ErrAssetBalanceLevelTooHigh,
"should not place buy order, asset balance level is too high: %f > %f, order: %s",
baseBalance.Available,
c.MaxBaseAssetBalance.Float64(),
order.String()))
continue continue
} }
@ -157,7 +171,12 @@ func (c *BasicRiskController) ProcessOrders(session *ExchangeSession, orders ...
// if the amount is still too small, we should skip it. // if the amount is still too small, we should skip it.
notional := quantity * lastPrice notional := quantity * lastPrice
if notional < market.MinAmount { if notional < market.MinAmount {
c.Logger.Errorf("can not place buy order, quote amount too small: notional %f < min amount %f", notional, market.MinAmount) addError(
errors.Errorf(
"can not place buy order, quote amount too small: notional %f < min amount %f, order: %s",
notional,
market.MinAmount,
order.String()))
continue continue
} }
@ -167,7 +186,11 @@ func (c *BasicRiskController) ProcessOrders(session *ExchangeSession, orders ...
// Critical conditions for placing SELL orders // Critical conditions for placing SELL orders
baseAssetBalance, ok := balances[market.BaseCurrency] baseAssetBalance, ok := balances[market.BaseCurrency]
if !ok { if !ok {
c.Logger.Errorf("can not place sell order, no base asset balance %s", market.BaseCurrency) addError(
errors.Errorf(
"can not place sell order, no base asset balance %s, order: %s",
market.BaseCurrency,
order.String()))
continue continue
} }
@ -179,13 +202,21 @@ func (c *BasicRiskController) ProcessOrders(session *ExchangeSession, orders ...
if c.MinBaseAssetBalance > 0 { if c.MinBaseAssetBalance > 0 {
if baseAssetBalance.Available < c.MinBaseAssetBalance.Float64() { if baseAssetBalance.Available < c.MinBaseAssetBalance.Float64() {
c.Logger.WithError(ErrAssetBalanceLevelTooLow).Errorf("asset balance level is too low: %f > %f", baseAssetBalance.Available, c.MinBaseAssetBalance.Float64()) addError(
errors.Wrapf(
ErrAssetBalanceLevelTooLow,
"asset balance level is too low: %f > %f", baseAssetBalance.Available, c.MinBaseAssetBalance.Float64()))
continue continue
} }
quantity = math.Min(quantity, baseAssetBalance.Available-c.MinBaseAssetBalance.Float64()) quantity = math.Min(quantity, baseAssetBalance.Available-c.MinBaseAssetBalance.Float64())
if quantity < market.MinQuantity { if quantity < market.MinQuantity {
c.Logger.WithError(ErrInsufficientAssetBalance).Errorf("insufficient asset balance: %f > minimal quantity %f", baseAssetBalance.Available, market.MinQuantity) addError(
errors.Wrapf(
ErrInsufficientAssetBalance,
"insufficient asset balance: %f > minimal quantity %f",
baseAssetBalance.Available,
market.MinQuantity))
continue continue
} }
} }
@ -196,12 +227,22 @@ func (c *BasicRiskController) ProcessOrders(session *ExchangeSession, orders ...
notional := quantity * lastPrice notional := quantity * lastPrice
if notional < market.MinNotional { if notional < market.MinNotional {
c.Logger.Errorf("can not place sell order, notional %f < min notional: %f", notional, market.MinNotional) addError(
errors.Errorf(
"can not place sell order, notional %f < min notional: %f, order: %s",
notional,
market.MinNotional,
order.String()))
continue continue
} }
if quantity < market.MinLot { if quantity < market.MinLot {
c.Logger.Errorf("can not place sell order, quantity %f is less than the minimal lot %f", quantity, market.MinLot) addError(
errors.Errorf(
"can not place sell order, quantity %f is less than the minimal lot %f, order: %s",
quantity,
market.MinLot,
order.String()))
continue continue
} }

View File

@ -1,6 +1,7 @@
package types package types
import ( import (
"fmt"
"time" "time"
"github.com/slack-go/slack" "github.com/slack-go/slack"
@ -61,17 +62,8 @@ type SubmitOrder struct {
TimeInForce string `json:"timeInForce" db:"time_in_force"` // GTC, IOC, FOK TimeInForce string `json:"timeInForce" db:"time_in_force"` // GTC, IOC, FOK
} }
type Order struct { func (o *SubmitOrder) String() string {
SubmitOrder return fmt.Sprintf("SubmitOrder %s %s %s %f @ %f", o.Symbol, o.Type, o.Side, o.Quantity, o.Price)
Exchange string `json:"exchange" db:"exchange"`
GID uint64 `json:"gid" db:"gid"`
OrderID uint64 `json:"orderID" db:"order_id"` // order id
Status OrderStatus `json:"status" db:"status"`
ExecutedQuantity float64 `json:"executedQuantity" db:"executed_quantity"`
IsWorking bool `json:"isWorking" db:"is_working"`
CreationTime time.Time `json:"creationTime" db:"created_at"`
UpdateTime time.Time `json:"updateTime" db:"updated_at"`
} }
func (o *SubmitOrder) SlackAttachment() slack.Attachment { func (o *SubmitOrder) SlackAttachment() slack.Attachment {
@ -92,3 +84,17 @@ func (o *SubmitOrder) SlackAttachment() slack.Attachment {
Fields: fields, Fields: fields,
} }
} }
type Order struct {
SubmitOrder
Exchange string `json:"exchange" db:"exchange"`
GID uint64 `json:"gid" db:"gid"`
OrderID uint64 `json:"orderID" db:"order_id"` // order id
Status OrderStatus `json:"status" db:"status"`
ExecutedQuantity float64 `json:"executedQuantity" db:"executed_quantity"`
IsWorking bool `json:"isWorking" db:"is_working"`
CreationTime time.Time `json:"creationTime" db:"created_at"`
UpdateTime time.Time `json:"updateTime" db:"updated_at"`
}