Exchanges: Add in exchange defined tolerance settings (#647)

* Exchanges: Add in exchange defined tolerance settings to conform to min max amounts/price/notional etc (Initial)

* Add to tests fix linter

* Binance: Implement CMF and usdtMarginFutures fetching of currency information, addr nits

* binance: Add in test for tolerance set up

* exchanges: add in more tolerance settings and add tests

* nits: addr

* fix linter issue

* RPCServer: Use ordermanager instead of going direct to exchange

* Nits: Addr

* nits: glorious addr phase one

* nits: glorious nits phase 2

* exchange: move tolerance -> limits in order package add wrapper function, split binance functions to asset files

* nits: Addr thrasher + also include locking of limits struct when we update via syncer later on

* nits: mdc addr

* nits: glorious nits

* limits: unexport mutex

* limit: revert maths optim. and fix spelling

* limit: Add decimal package

* limit: don't check price on market order

* Orders: Add order execution checks on fake orders so as to always conform to tight specifications even in simulation

* binance: handle case where spot is not enabled but margin is

* backtester: add in amount conforming to back tested events to simulate realistic orders

* rm ln

* order limit: return amount when limit is nil and conformToAmount is requested

* nits: glorious nits + friends

* backtester/orders: fix tests

* nits: glorious nits

* nits: glorious nits

* RMLINE

* nits: more glorious nits!

* nits: pooosh

* binance: fix margin logic

* nits: Add warning, settings log and report item for exchange order execution limits

* backtester: add specific warnings in report output

* backtest: Adjust warnings
This commit is contained in:
Ryan O'Hara-Reid
2021-03-25 15:47:15 +11:00
committed by GitHub
parent 3c72a199f2
commit 881bab2d5a
40 changed files with 1193 additions and 105 deletions

View File

@@ -324,7 +324,7 @@ func (o *orderManager) validate(newOrder *order.Submit) error {
}
if err := newOrder.Validate(); err != nil {
return err
return fmt.Errorf("order manager: %w", err)
}
if o.cfg.EnforceLimitConfig {
@@ -359,8 +359,21 @@ func (o *orderManager) Submit(newOrder *order.Submit) (*orderSubmitResponse, err
if exch == nil {
return nil, ErrExchangeNotFound
}
var result order.SubmitResponse
result, err = exch.SubmitOrder(newOrder)
// Checks for exchange min max limits for order amounts before order
// execution can occur
err = exch.CheckOrderExecutionLimits(newOrder.AssetType,
newOrder.Pair,
newOrder.Price,
newOrder.Amount,
newOrder.Type)
if err != nil {
return nil, fmt.Errorf("order manager: exchange %s unable to place order: %w",
newOrder.Exchange,
err)
}
result, err := exch.SubmitOrder(newOrder)
if err != nil {
return nil, err
}
@@ -370,7 +383,7 @@ func (o *orderManager) Submit(newOrder *order.Submit) (*orderSubmitResponse, err
// SubmitFakeOrder runs through the same process as order submission
// but does not touch live endpoints
func (o *orderManager) SubmitFakeOrder(newOrder *order.Submit, resultingOrder order.SubmitResponse) (*orderSubmitResponse, error) {
func (o *orderManager) SubmitFakeOrder(newOrder *order.Submit, resultingOrder order.SubmitResponse, checkExchangeLimits bool) (*orderSubmitResponse, error) {
err := o.validate(newOrder)
if err != nil {
return nil, err
@@ -380,6 +393,20 @@ func (o *orderManager) SubmitFakeOrder(newOrder *order.Submit, resultingOrder or
return nil, ErrExchangeNotFound
}
if checkExchangeLimits {
// Checks for exchange min max limits for order amounts before order
// execution can occur
err = exch.CheckOrderExecutionLimits(newOrder.AssetType,
newOrder.Pair,
newOrder.Price,
newOrder.Amount,
newOrder.Type)
if err != nil {
return nil, fmt.Errorf("order manager: exchange %s unable to place order: %w",
newOrder.Exchange,
err)
}
}
return o.processSubmittedOrder(newOrder, resultingOrder)
}

View File

@@ -986,11 +986,6 @@ func (s *RPCServer) GetOrder(_ context.Context, r *gctrpc.GetOrderRequest) (*gct
// SubmitOrder submits an order specified by exchange, currency pair and asset
// type
func (s *RPCServer) SubmitOrder(_ context.Context, r *gctrpc.SubmitOrderRequest) (*gctrpc.SubmitOrderResponse, error) {
exch := s.GetExchangeByName(r.Exchange)
if exch == nil {
return nil, errExchangeNotLoaded
}
p, err := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
if err != nil {
return nil, err
@@ -1012,7 +1007,7 @@ func (s *RPCServer) SubmitOrder(_ context.Context, r *gctrpc.SubmitOrderRequest)
AssetType: a,
}
resp, err := exch.SubmitOrder(submission)
resp, err := s.OrderManager.Submit(submission)
if err != nil {
return &gctrpc.SubmitOrderResponse{}, err
}