mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 00:05:15 +00:00
backtest: move fee mode functions to fee.go
This commit is contained in:
parent
8cd646668a
commit
10ed706ed6
|
@ -36,10 +36,10 @@ import (
|
|||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/cache"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/cache"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/bbgo"
|
||||
"github.com/c9s/bbgo/pkg/service"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
|
@ -138,12 +138,15 @@ func (e *Exchange) addMatchingBook(symbol string, market types.Market) {
|
|||
}
|
||||
|
||||
func (e *Exchange) _addMatchingBook(symbol string, market types.Market) {
|
||||
e.matchingBooks[symbol] = &SimplePriceMatching{
|
||||
CurrentTime: e.currentTime,
|
||||
Account: e.account,
|
||||
matching := &SimplePriceMatching{
|
||||
currentTime: e.currentTime,
|
||||
account: e.account,
|
||||
Market: market,
|
||||
closedOrders: make(map[uint64]types.Order),
|
||||
feeModeFunction: getFeeModeFunction(e.config.FeeMode),
|
||||
}
|
||||
|
||||
e.matchingBooks[symbol] = matching
|
||||
}
|
||||
|
||||
func (e *Exchange) NewStream() types.Stream {
|
||||
|
@ -257,7 +260,7 @@ func (e *Exchange) QueryTicker(ctx context.Context, symbol string) (*types.Ticke
|
|||
return nil, fmt.Errorf("matching engine is not initialized for symbol %s", symbol)
|
||||
}
|
||||
|
||||
kline := matching.LastKLine
|
||||
kline := matching.lastKLine
|
||||
return &types.Ticker{
|
||||
Time: kline.EndTime.Time(),
|
||||
Volume: kline.Volume,
|
||||
|
@ -382,7 +385,7 @@ func (e *Exchange) ConsumeKLine(k types.KLine) {
|
|||
e.currentTime = kline1m.EndTime.Time()
|
||||
// here we generate trades and order updates
|
||||
matching.processKLine(kline1m)
|
||||
matching.NextKLine = &k
|
||||
matching.nextKLine = &k
|
||||
for _, kline := range matching.klineCache {
|
||||
e.MarketDataStream.EmitKLineClosed(kline)
|
||||
for _, h := range e.Src.Callbacks {
|
||||
|
|
83
pkg/backtest/fee.go
Normal file
83
pkg/backtest/fee.go
Normal file
|
@ -0,0 +1,83 @@
|
|||
package backtest
|
||||
|
||||
import (
|
||||
"github.com/c9s/bbgo/pkg/bbgo"
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type FeeModeFunction func(order *types.Order, market *types.Market, feeRate fixedpoint.Value) (fee fixedpoint.Value, feeCurrency string)
|
||||
|
||||
func feeModeFunctionToken(order *types.Order, _ *types.Market, feeRate fixedpoint.Value) (fee fixedpoint.Value, feeCurrency string) {
|
||||
quoteQuantity := order.Quantity.Mul(order.Price)
|
||||
feeCurrency = FeeToken
|
||||
fee = quoteQuantity.Mul(feeRate)
|
||||
return fee, feeCurrency
|
||||
}
|
||||
|
||||
func feeModeFunctionNative(order *types.Order, market *types.Market, feeRate fixedpoint.Value) (fee fixedpoint.Value, feeCurrency string) {
|
||||
switch order.Side {
|
||||
|
||||
case types.SideTypeBuy:
|
||||
fee = order.Quantity.Mul(feeRate)
|
||||
feeCurrency = market.BaseCurrency
|
||||
|
||||
case types.SideTypeSell:
|
||||
quoteQuantity := order.Quantity.Mul(order.Price)
|
||||
fee = quoteQuantity.Mul(feeRate)
|
||||
feeCurrency = market.QuoteCurrency
|
||||
|
||||
}
|
||||
|
||||
return fee, feeCurrency
|
||||
}
|
||||
|
||||
func feeModeFunctionQuote(order *types.Order, market *types.Market, feeRate fixedpoint.Value) (fee fixedpoint.Value, feeCurrency string) {
|
||||
feeCurrency = market.QuoteCurrency
|
||||
|
||||
quoteQuantity := order.Quantity.Mul(order.Price)
|
||||
switch order.Side {
|
||||
|
||||
case types.SideTypeBuy:
|
||||
fee = quoteQuantity.Mul(feeRate)
|
||||
|
||||
case types.SideTypeSell:
|
||||
fee = quoteQuantity.Mul(feeRate)
|
||||
|
||||
}
|
||||
|
||||
return fee, feeCurrency
|
||||
}
|
||||
|
||||
func getFeeModeFunction(feeMode bbgo.BackTestFeeMode) FeeModeFunction {
|
||||
switch feeMode {
|
||||
|
||||
case bbgo.BackTestFeeModeNative:
|
||||
return feeModeFunctionNative
|
||||
|
||||
case bbgo.BackTestFeeModeQuote:
|
||||
return feeModeFunctionQuote
|
||||
|
||||
case bbgo.BackTestFeeModeToken:
|
||||
return feeModeFunctionToken
|
||||
|
||||
default:
|
||||
return feeModeFunctionNative
|
||||
}
|
||||
}
|
||||
|
||||
func calculateNativeOrderFee(order *types.Order, market types.Market, feeRate fixedpoint.Value) (fee fixedpoint.Value, feeCurrency string) {
|
||||
switch order.Side {
|
||||
|
||||
case types.SideTypeBuy:
|
||||
fee = order.Quantity.Mul(feeRate)
|
||||
feeCurrency = market.BaseCurrency
|
||||
|
||||
case types.SideTypeSell:
|
||||
quoteQuantity := order.Quantity.Mul(order.Price)
|
||||
fee = quoteQuantity.Mul(feeRate)
|
||||
feeCurrency = market.QuoteCurrency
|
||||
|
||||
}
|
||||
return fee, feeCurrency
|
||||
}
|
|
@ -59,12 +59,14 @@ type SimplePriceMatching struct {
|
|||
closedOrders map[uint64]types.Order
|
||||
|
||||
klineCache map[types.Interval]types.KLine
|
||||
LastPrice fixedpoint.Value
|
||||
LastKLine types.KLine
|
||||
NextKLine *types.KLine
|
||||
CurrentTime time.Time
|
||||
lastPrice fixedpoint.Value
|
||||
lastKLine types.KLine
|
||||
nextKLine *types.KLine
|
||||
currentTime time.Time
|
||||
|
||||
Account *types.Account
|
||||
feeModeFunction FeeModeFunction
|
||||
|
||||
account *types.Account
|
||||
|
||||
tradeUpdateCallbacks []func(trade types.Trade)
|
||||
orderUpdateCallbacks []func(order types.Order)
|
||||
|
@ -109,38 +111,38 @@ func (m *SimplePriceMatching) CancelOrder(o types.Order) (types.Order, error) {
|
|||
|
||||
switch o.Side {
|
||||
case types.SideTypeBuy:
|
||||
if err := m.Account.UnlockBalance(m.Market.QuoteCurrency, o.Price.Mul(o.Quantity)); err != nil {
|
||||
if err := m.account.UnlockBalance(m.Market.QuoteCurrency, o.Price.Mul(o.Quantity)); err != nil {
|
||||
return o, err
|
||||
}
|
||||
|
||||
case types.SideTypeSell:
|
||||
if err := m.Account.UnlockBalance(m.Market.BaseCurrency, o.Quantity); err != nil {
|
||||
if err := m.account.UnlockBalance(m.Market.BaseCurrency, o.Quantity); err != nil {
|
||||
return o, err
|
||||
}
|
||||
}
|
||||
|
||||
o.Status = types.OrderStatusCanceled
|
||||
m.EmitOrderUpdate(o)
|
||||
m.EmitBalanceUpdate(m.Account.Balances())
|
||||
m.EmitBalanceUpdate(m.account.Balances())
|
||||
return o, nil
|
||||
}
|
||||
|
||||
// PlaceOrder returns the created order object, executed trade (if any) and error
|
||||
func (m *SimplePriceMatching) PlaceOrder(o types.SubmitOrder) (*types.Order, *types.Trade, error) {
|
||||
if o.Type == types.OrderTypeMarket {
|
||||
if m.LastPrice.IsZero() {
|
||||
if m.lastPrice.IsZero() {
|
||||
panic("unexpected error: for market order, the last price can not be zero")
|
||||
}
|
||||
}
|
||||
|
||||
isTaker := o.Type == types.OrderTypeMarket || isLimitTakerOrder(o, m.LastPrice)
|
||||
isTaker := o.Type == types.OrderTypeMarket || isLimitTakerOrder(o, m.lastPrice)
|
||||
|
||||
// price for checking account balance, default price
|
||||
price := o.Price
|
||||
|
||||
switch o.Type {
|
||||
case types.OrderTypeMarket:
|
||||
price = m.Market.TruncatePrice(m.LastPrice)
|
||||
price = m.Market.TruncatePrice(m.lastPrice)
|
||||
|
||||
case types.OrderTypeStopMarket:
|
||||
// the actual price might be different.
|
||||
|
@ -165,17 +167,17 @@ func (m *SimplePriceMatching) PlaceOrder(o types.SubmitOrder) (*types.Order, *ty
|
|||
|
||||
switch o.Side {
|
||||
case types.SideTypeBuy:
|
||||
if err := m.Account.LockBalance(m.Market.QuoteCurrency, quoteQuantity); err != nil {
|
||||
if err := m.account.LockBalance(m.Market.QuoteCurrency, quoteQuantity); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
case types.SideTypeSell:
|
||||
if err := m.Account.LockBalance(m.Market.BaseCurrency, o.Quantity); err != nil {
|
||||
if err := m.account.LockBalance(m.Market.BaseCurrency, o.Quantity); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
m.EmitBalanceUpdate(m.Account.Balances())
|
||||
m.EmitBalanceUpdate(m.account.Balances())
|
||||
|
||||
// start from one
|
||||
orderID := incOrderID()
|
||||
|
@ -184,19 +186,19 @@ func (m *SimplePriceMatching) PlaceOrder(o types.SubmitOrder) (*types.Order, *ty
|
|||
if isTaker {
|
||||
var price fixedpoint.Value
|
||||
if order.Type == types.OrderTypeMarket {
|
||||
order.Price = m.Market.TruncatePrice(m.LastPrice)
|
||||
order.Price = m.Market.TruncatePrice(m.lastPrice)
|
||||
price = order.Price
|
||||
} else if order.Type == types.OrderTypeLimit {
|
||||
// if limit order's price is with the range of next kline
|
||||
// we assume it will be traded as a maker trade, and is traded at its original price
|
||||
// TODO: if it is treated as a maker trade, fee should be specially handled
|
||||
// otherwise, set NextKLine.Close(i.e., m.LastPrice) to be the taker traded price
|
||||
if m.NextKLine != nil && m.NextKLine.High.Compare(order.Price) > 0 && order.Side == types.SideTypeBuy {
|
||||
if m.nextKLine != nil && m.nextKLine.High.Compare(order.Price) > 0 && order.Side == types.SideTypeBuy {
|
||||
order.AveragePrice = order.Price
|
||||
} else if m.NextKLine != nil && m.NextKLine.Low.Compare(order.Price) < 0 && order.Side == types.SideTypeSell {
|
||||
} else if m.nextKLine != nil && m.nextKLine.Low.Compare(order.Price) < 0 && order.Side == types.SideTypeSell {
|
||||
order.AveragePrice = order.Price
|
||||
} else {
|
||||
order.AveragePrice = m.Market.TruncatePrice(m.LastPrice)
|
||||
order.AveragePrice = m.Market.TruncatePrice(m.lastPrice)
|
||||
}
|
||||
price = order.AveragePrice
|
||||
}
|
||||
|
@ -223,10 +225,10 @@ func (m *SimplePriceMatching) PlaceOrder(o types.SubmitOrder) (*types.Order, *ty
|
|||
// 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 {
|
||||
if err := m.account.UnlockBalance(m.Market.QuoteCurrency, amount); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
m.EmitBalanceUpdate(m.Account.Balances())
|
||||
m.EmitBalanceUpdate(m.account.Balances())
|
||||
}
|
||||
|
||||
case types.SideTypeSell:
|
||||
|
@ -234,8 +236,8 @@ func (m *SimplePriceMatching) PlaceOrder(o types.SubmitOrder) (*types.Order, *ty
|
|||
// 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)
|
||||
m.EmitBalanceUpdate(m.Account.Balances())
|
||||
m.account.AddBalance(m.Market.QuoteCurrency, amount)
|
||||
m.EmitBalanceUpdate(m.account.Balances())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,7 +275,7 @@ func (m *SimplePriceMatching) executeTrade(trade types.Trade) {
|
|||
var err error
|
||||
// execute trade, update account balances
|
||||
if trade.IsBuyer {
|
||||
err = m.Account.UseLockedBalance(m.Market.QuoteCurrency, trade.QuoteQuantity)
|
||||
err = m.account.UseLockedBalance(m.Market.QuoteCurrency, trade.QuoteQuantity)
|
||||
|
||||
// here the fee currency is the base currency
|
||||
q := trade.Quantity
|
||||
|
@ -281,16 +283,16 @@ func (m *SimplePriceMatching) executeTrade(trade types.Trade) {
|
|||
q = q.Sub(trade.Fee)
|
||||
}
|
||||
|
||||
m.Account.AddBalance(m.Market.BaseCurrency, q)
|
||||
m.account.AddBalance(m.Market.BaseCurrency, q)
|
||||
} else {
|
||||
err = m.Account.UseLockedBalance(m.Market.BaseCurrency, trade.Quantity)
|
||||
err = m.account.UseLockedBalance(m.Market.BaseCurrency, trade.Quantity)
|
||||
|
||||
// here the fee currency is the quote currency
|
||||
qq := trade.QuoteQuantity
|
||||
if trade.FeeCurrency == m.Market.QuoteCurrency {
|
||||
qq = qq.Sub(trade.Fee)
|
||||
}
|
||||
m.Account.AddBalance(m.Market.QuoteCurrency, qq)
|
||||
m.account.AddBalance(m.Market.QuoteCurrency, qq)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -298,16 +300,16 @@ func (m *SimplePriceMatching) executeTrade(trade types.Trade) {
|
|||
}
|
||||
|
||||
m.EmitTradeUpdate(trade)
|
||||
m.EmitBalanceUpdate(m.Account.Balances())
|
||||
m.EmitBalanceUpdate(m.account.Balances())
|
||||
}
|
||||
|
||||
func (m *SimplePriceMatching) getFeeRate(isMaker bool) (feeRate fixedpoint.Value) {
|
||||
// BINANCE uses 0.1% for both maker and taker
|
||||
// MAX uses 0.050% for maker and 0.15% for taker
|
||||
if isMaker {
|
||||
feeRate = m.Account.MakerFeeRate
|
||||
feeRate = m.account.MakerFeeRate
|
||||
} else {
|
||||
feeRate = m.Account.TakerFeeRate
|
||||
feeRate = m.account.TakerFeeRate
|
||||
}
|
||||
return feeRate
|
||||
}
|
||||
|
@ -320,15 +322,14 @@ func (m *SimplePriceMatching) newTradeFromOrder(order *types.Order, isMaker bool
|
|||
var fee fixedpoint.Value
|
||||
var feeCurrency string
|
||||
|
||||
if useFeeToken {
|
||||
feeCurrency = FeeToken
|
||||
fee = quoteQuantity.Mul(feeRate)
|
||||
if m.feeModeFunction != nil {
|
||||
fee, feeCurrency = m.feeModeFunction(order, &m.Market, feeRate)
|
||||
} else {
|
||||
fee, feeCurrency = calculateNativeOrderFee(order, m.Market, feeRate)
|
||||
fee, feeCurrency = feeModeFunctionQuote(order, &m.Market, feeRate)
|
||||
}
|
||||
|
||||
// update order time
|
||||
order.UpdateTime = types.Time(m.CurrentTime)
|
||||
order.UpdateTime = types.Time(m.currentTime)
|
||||
|
||||
var id = incTradeID()
|
||||
return types.Trade{
|
||||
|
@ -342,7 +343,7 @@ func (m *SimplePriceMatching) newTradeFromOrder(order *types.Order, isMaker bool
|
|||
Side: order.Side,
|
||||
IsBuyer: order.Side == types.SideTypeBuy,
|
||||
IsMaker: isMaker,
|
||||
Time: types.Time(m.CurrentTime),
|
||||
Time: types.Time(m.currentTime),
|
||||
Fee: fee,
|
||||
FeeCurrency: feeCurrency,
|
||||
}
|
||||
|
@ -458,7 +459,7 @@ func (m *SimplePriceMatching) buyToPrice(price fixedpoint.Value) (closedOrders [
|
|||
}
|
||||
|
||||
m.askOrders = askOrders
|
||||
m.LastPrice = price
|
||||
m.lastPrice = price
|
||||
|
||||
for i := range closedOrders {
|
||||
o := closedOrders[i]
|
||||
|
@ -587,7 +588,7 @@ func (m *SimplePriceMatching) sellToPrice(price fixedpoint.Value) (closedOrders
|
|||
}
|
||||
|
||||
m.bidOrders = bidOrders
|
||||
m.LastPrice = price
|
||||
m.lastPrice = price
|
||||
|
||||
for i := range closedOrders {
|
||||
o := closedOrders[i]
|
||||
|
@ -631,12 +632,12 @@ func (m *SimplePriceMatching) getOrder(orderID uint64) (types.Order, bool) {
|
|||
}
|
||||
|
||||
func (m *SimplePriceMatching) processKLine(kline types.KLine) {
|
||||
m.CurrentTime = kline.EndTime.Time()
|
||||
m.currentTime = kline.EndTime.Time()
|
||||
|
||||
if m.LastPrice.IsZero() {
|
||||
m.LastPrice = kline.Open
|
||||
if m.lastPrice.IsZero() {
|
||||
m.lastPrice = kline.Open
|
||||
} else {
|
||||
if m.LastPrice.Compare(kline.Open) > 0 {
|
||||
if m.lastPrice.Compare(kline.Open) > 0 {
|
||||
m.sellToPrice(kline.Open)
|
||||
} else {
|
||||
m.buyToPrice(kline.Open)
|
||||
|
@ -669,12 +670,12 @@ func (m *SimplePriceMatching) processKLine(kline types.KLine) {
|
|||
m.buyToPrice(kline.Close)
|
||||
}
|
||||
default: // no trade up or down
|
||||
if m.LastPrice.IsZero() {
|
||||
if m.lastPrice.IsZero() {
|
||||
m.buyToPrice(kline.Close)
|
||||
}
|
||||
}
|
||||
|
||||
m.LastKLine = kline
|
||||
m.lastKLine = kline
|
||||
}
|
||||
|
||||
func (m *SimplePriceMatching) newOrder(o types.SubmitOrder, orderID uint64) types.Order {
|
||||
|
@ -685,27 +686,11 @@ func (m *SimplePriceMatching) newOrder(o types.SubmitOrder, orderID uint64) type
|
|||
Status: types.OrderStatusNew,
|
||||
ExecutedQuantity: fixedpoint.Zero,
|
||||
IsWorking: true,
|
||||
CreationTime: types.Time(m.CurrentTime),
|
||||
UpdateTime: types.Time(m.CurrentTime),
|
||||
CreationTime: types.Time(m.currentTime),
|
||||
UpdateTime: types.Time(m.currentTime),
|
||||
}
|
||||
}
|
||||
|
||||
func calculateNativeOrderFee(order *types.Order, market types.Market, feeRate fixedpoint.Value) (fee fixedpoint.Value, feeCurrency string) {
|
||||
switch order.Side {
|
||||
|
||||
case types.SideTypeBuy:
|
||||
fee = order.Quantity.Mul(feeRate)
|
||||
feeCurrency = market.BaseCurrency
|
||||
|
||||
case types.SideTypeSell:
|
||||
quoteQuantity := order.Quantity.Mul(order.Price)
|
||||
fee = quoteQuantity.Mul(feeRate)
|
||||
feeCurrency = market.QuoteCurrency
|
||||
|
||||
}
|
||||
return fee, feeCurrency
|
||||
}
|
||||
|
||||
func isTakerOrder(o types.Order) bool {
|
||||
if o.AveragePrice.IsZero() {
|
||||
return false
|
||||
|
|
|
@ -44,11 +44,11 @@ func TestSimplePriceMatching_orderUpdate(t *testing.T) {
|
|||
|
||||
t1 := time.Date(2021, 7, 1, 0, 0, 0, 0, time.UTC)
|
||||
engine := &SimplePriceMatching{
|
||||
Account: account,
|
||||
account: account,
|
||||
Market: market,
|
||||
CurrentTime: t1,
|
||||
currentTime: t1,
|
||||
closedOrders: make(map[uint64]types.Order),
|
||||
LastPrice: fixedpoint.NewFromFloat(25000),
|
||||
lastPrice: fixedpoint.NewFromFloat(25000),
|
||||
}
|
||||
|
||||
orderUpdateCnt := 0
|
||||
|
@ -97,11 +97,11 @@ func TestSimplePriceMatching_CancelOrder(t *testing.T) {
|
|||
market := getTestMarket()
|
||||
t1 := time.Date(2021, 7, 1, 0, 0, 0, 0, time.UTC)
|
||||
engine := &SimplePriceMatching{
|
||||
Account: account,
|
||||
account: account,
|
||||
Market: market,
|
||||
CurrentTime: t1,
|
||||
currentTime: t1,
|
||||
closedOrders: make(map[uint64]types.Order),
|
||||
LastPrice: fixedpoint.NewFromFloat(30000.0),
|
||||
lastPrice: fixedpoint.NewFromFloat(30000.0),
|
||||
}
|
||||
|
||||
createdOrder1, trade1, err := engine.PlaceOrder(newLimitOrder("BTCUSDT", types.SideTypeBuy, 20000.0, 0.1))
|
||||
|
@ -139,11 +139,11 @@ func TestSimplePriceMatching_processKLine(t *testing.T) {
|
|||
|
||||
t1 := time.Date(2021, 7, 1, 0, 0, 0, 0, time.UTC)
|
||||
engine := &SimplePriceMatching{
|
||||
Account: account,
|
||||
account: account,
|
||||
Market: market,
|
||||
CurrentTime: t1,
|
||||
currentTime: t1,
|
||||
closedOrders: make(map[uint64]types.Order),
|
||||
LastPrice: fixedpoint.NewFromFloat(30000.0),
|
||||
lastPrice: fixedpoint.NewFromFloat(30000.0),
|
||||
}
|
||||
|
||||
for i := 0; i <= 5; i++ {
|
||||
|
@ -216,10 +216,10 @@ func TestSimplePriceMatching_LimitBuyTakerOrder(t *testing.T) {
|
|||
account := getTestAccount()
|
||||
market := getTestMarket()
|
||||
engine := &SimplePriceMatching{
|
||||
Account: account,
|
||||
account: account,
|
||||
Market: market,
|
||||
closedOrders: make(map[uint64]types.Order),
|
||||
LastPrice: fixedpoint.NewFromFloat(19000.0),
|
||||
lastPrice: fixedpoint.NewFromFloat(19000.0),
|
||||
}
|
||||
|
||||
takerOrder := types.SubmitOrder{
|
||||
|
@ -256,10 +256,10 @@ func TestSimplePriceMatching_StopLimitOrderBuy(t *testing.T) {
|
|||
account := getTestAccount()
|
||||
market := getTestMarket()
|
||||
engine := &SimplePriceMatching{
|
||||
Account: account,
|
||||
account: account,
|
||||
Market: market,
|
||||
closedOrders: make(map[uint64]types.Order),
|
||||
LastPrice: fixedpoint.NewFromFloat(19000.0),
|
||||
lastPrice: fixedpoint.NewFromFloat(19000.0),
|
||||
}
|
||||
|
||||
stopBuyOrder := types.SubmitOrder{
|
||||
|
@ -299,7 +299,7 @@ func TestSimplePriceMatching_StopLimitOrderBuy(t *testing.T) {
|
|||
assert.Equal(t, "21001", trades[0].Price.String())
|
||||
assert.Equal(t, "22000", closedOrders[0].Price.String(), "order.Price should not be adjusted")
|
||||
|
||||
assert.Equal(t, fixedpoint.NewFromFloat(21001.0).String(), engine.LastPrice.String())
|
||||
assert.Equal(t, fixedpoint.NewFromFloat(21001.0).String(), engine.lastPrice.String())
|
||||
|
||||
stopOrder2 := types.SubmitOrder{
|
||||
Symbol: market.Symbol,
|
||||
|
@ -326,10 +326,10 @@ func TestSimplePriceMatching_StopLimitOrderSell(t *testing.T) {
|
|||
account := getTestAccount()
|
||||
market := getTestMarket()
|
||||
engine := &SimplePriceMatching{
|
||||
Account: account,
|
||||
account: account,
|
||||
Market: market,
|
||||
closedOrders: make(map[uint64]types.Order),
|
||||
LastPrice: fixedpoint.NewFromFloat(22000.0),
|
||||
lastPrice: fixedpoint.NewFromFloat(22000.0),
|
||||
}
|
||||
|
||||
stopSellOrder := types.SubmitOrder{
|
||||
|
@ -370,7 +370,7 @@ func TestSimplePriceMatching_StopLimitOrderSell(t *testing.T) {
|
|||
assert.Equal(t, types.OrderTypeLimit, closedOrders[0].Type)
|
||||
assert.Equal(t, "20000", closedOrders[0].Price.String(), "limit order price should not be changed")
|
||||
assert.Equal(t, "20990", trades[0].Price.String())
|
||||
assert.Equal(t, "20990", engine.LastPrice.String())
|
||||
assert.Equal(t, "20990", engine.lastPrice.String())
|
||||
|
||||
// place a stop limit sell order with a higher price than the current price
|
||||
stopOrder2 := types.SubmitOrder{
|
||||
|
@ -395,7 +395,7 @@ func TestSimplePriceMatching_StopLimitOrderSell(t *testing.T) {
|
|||
assert.Equal(t, types.OrderStatusFilled, closedOrders[0].Status)
|
||||
assert.Equal(t, types.OrderTypeLimit, closedOrders[0].Type)
|
||||
assert.Equal(t, "21000", trades[0].Price.String(), "trade price should be the kline price not the order price")
|
||||
assert.Equal(t, "21000", engine.LastPrice.String(), "engine last price should be updated correctly")
|
||||
assert.Equal(t, "21000", engine.lastPrice.String(), "engine last price should be updated correctly")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,10 +403,10 @@ func TestSimplePriceMatching_StopMarketOrderSell(t *testing.T) {
|
|||
account := getTestAccount()
|
||||
market := getTestMarket()
|
||||
engine := &SimplePriceMatching{
|
||||
Account: account,
|
||||
account: account,
|
||||
Market: market,
|
||||
closedOrders: make(map[uint64]types.Order),
|
||||
LastPrice: fixedpoint.NewFromFloat(22000.0),
|
||||
lastPrice: fixedpoint.NewFromFloat(22000.0),
|
||||
}
|
||||
|
||||
stopOrder := types.SubmitOrder{
|
||||
|
@ -440,7 +440,7 @@ func TestSimplePriceMatching_PlaceLimitOrder(t *testing.T) {
|
|||
account := getTestAccount()
|
||||
market := getTestMarket()
|
||||
engine := &SimplePriceMatching{
|
||||
Account: account,
|
||||
account: account,
|
||||
Market: market,
|
||||
closedOrders: make(map[uint64]types.Order),
|
||||
}
|
||||
|
@ -540,10 +540,10 @@ func TestSimplePriceMatching_LimitTakerOrder(t *testing.T) {
|
|||
account := getTestAccount()
|
||||
market := getTestMarket()
|
||||
engine := &SimplePriceMatching{
|
||||
Account: account,
|
||||
account: account,
|
||||
Market: market,
|
||||
closedOrders: make(map[uint64]types.Order),
|
||||
LastPrice: fixedpoint.NewFromFloat(20000.0),
|
||||
lastPrice: fixedpoint.NewFromFloat(20000.0),
|
||||
}
|
||||
|
||||
closedOrder, trade, err := engine.PlaceOrder(newLimitOrder("BTCUSDT", types.SideTypeBuy, 21000.0, 1.0))
|
||||
|
|
Loading…
Reference in New Issue
Block a user