mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-21 22:43:52 +00:00
backtest: fix limit taker lock issue
This commit is contained in:
parent
d7dbfd7613
commit
6c4d5041ba
|
@ -178,6 +178,8 @@ func (m *SimplePriceMatching) PlaceOrder(o types.SubmitOrder) (*types.Order, *ty
|
|||
if isTaker {
|
||||
if order.Type == types.OrderTypeMarket {
|
||||
order.Price = m.LastPrice
|
||||
} else if order.Type == types.OrderTypeLimit {
|
||||
order.AveragePrice = m.LastPrice
|
||||
}
|
||||
|
||||
// emit the order update for Status:New
|
||||
|
@ -197,6 +199,33 @@ func (m *SimplePriceMatching) PlaceOrder(o types.SubmitOrder) (*types.Order, *ty
|
|||
|
||||
m.EmitOrderUpdate(order2)
|
||||
|
||||
// unlock the rest balances for limit taker
|
||||
if order.Type == types.OrderTypeLimit {
|
||||
if order.AveragePrice.IsZero() {
|
||||
return nil, nil, fmt.Errorf("the average price of the given limit taker order can not be zero")
|
||||
}
|
||||
|
||||
switch o.Side {
|
||||
case types.SideTypeBuy:
|
||||
// limit buy taker, the order price is higher than the current best ask price
|
||||
// the executed price is lower than the given price, so we will use less quote currency to buy the base asset.
|
||||
amount := order.Price.Sub(order.AveragePrice).Mul(order.Quantity)
|
||||
if amount.Sign() > 0 {
|
||||
if err := m.Account.UnlockBalance(m.Market.QuoteCurrency, amount); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
case types.SideTypeSell:
|
||||
// limit sell taker, the order price is lower than the current best bid price
|
||||
// the executed price is higher than the given price, so we will get more quote currency back
|
||||
amount := order.AveragePrice.Sub(order.Price).Mul(order.Quantity)
|
||||
if amount.Sign() > 0 {
|
||||
m.Account.AddBalance(m.Market.QuoteCurrency, amount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// let the exchange emit the "FILLED" order update (we need the closed order)
|
||||
// m.EmitOrderUpdate(order2)
|
||||
return &order2, &trade, nil
|
||||
|
|
|
@ -208,6 +208,46 @@ func getTestAccount() *types.Account {
|
|||
return account
|
||||
}
|
||||
|
||||
func TestSimplePriceMatching_LimitBuyTakerOrder(t *testing.T) {
|
||||
account := getTestAccount()
|
||||
market := getTestMarket()
|
||||
engine := &SimplePriceMatching{
|
||||
Account: account,
|
||||
Market: market,
|
||||
closedOrders: make(map[uint64]types.Order),
|
||||
LastPrice: fixedpoint.NewFromFloat(19000.0),
|
||||
}
|
||||
|
||||
takerOrder := types.SubmitOrder{
|
||||
Symbol: market.Symbol,
|
||||
Side: types.SideTypeBuy,
|
||||
Type: types.OrderTypeLimit,
|
||||
Quantity: fixedpoint.NewFromFloat(0.1),
|
||||
Price: fixedpoint.NewFromFloat(20000.0),
|
||||
TimeInForce: types.TimeInForceGTC,
|
||||
}
|
||||
createdOrder, trade, err := engine.PlaceOrder(takerOrder)
|
||||
assert.NoError(t, err)
|
||||
t.Logf("created order: %+v", createdOrder)
|
||||
t.Logf("executed trade: %+v", trade)
|
||||
|
||||
assert.Equal(t, "19000", trade.Price.String())
|
||||
assert.Equal(t, "19000", createdOrder.AveragePrice.String())
|
||||
assert.Equal(t, "20000", createdOrder.Price.String())
|
||||
|
||||
usdt, ok := account.Balance("USDT")
|
||||
assert.True(t, ok)
|
||||
assert.True(t, usdt.Locked.IsZero())
|
||||
|
||||
btc, ok := account.Balance("BTC")
|
||||
assert.True(t, ok)
|
||||
assert.True(t, btc.Locked.IsZero())
|
||||
assert.Equal(t, fixedpoint.NewFromFloat(100.0).Add(createdOrder.Quantity).String(), btc.Available.String())
|
||||
|
||||
usedQuoteAmount := createdOrder.AveragePrice.Mul(createdOrder.Quantity)
|
||||
assert.Equal(t, usdt.Available.String(), fixedpoint.NewFromFloat(1000000.0).Sub(usedQuoteAmount).String())
|
||||
}
|
||||
|
||||
func TestSimplePriceMatching_StopLimitOrderBuy(t *testing.T) {
|
||||
account := getTestAccount()
|
||||
market := getTestMarket()
|
||||
|
|
Loading…
Reference in New Issue
Block a user