Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix backtest errors; enforce QtyDecimalPrecision #170

Merged

Conversation

rene-post
Copy link
Contributor

For me, when I do

go run ./examples/backtesting

I get the following:

Screenshot 2022-07-12 at 22 22 49

This seems to be caused by rounding errors in market orders.
My fix enforces QtyDecimalPrecision and this gets rid of the errors.

Copy link
Owner

@rodrigo-brito rodrigo-brito left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @rene-post, I think it is not necessary for a paper wallet, but I will accept the changes to a better fit with the production mode.

In production mode, we use FormatFloat to solve this issue:

func (b *Binance) formatQuantity(pair string, value float64) string {
precision := -1
if limits, ok := b.assetsInfo[pair]; ok {
precision = int(limits.QtyDecimalPrecision)
}
return strconv.FormatFloat(value, 'f', precision, 64)
}

@rodrigo-brito rodrigo-brito merged commit dbae19a into rodrigo-brito:main Jul 12, 2022
@rene-post rene-post deleted the fix-paperwallet-market-quote branch July 12, 2022 23:07
@rene-post
Copy link
Contributor Author

Hi @rodrigo-brito, thanks for merging the pull request. For Binance you are formatting correctly for CreateMarketOrder but not for CreateMarketOrderQuote. There you use fmt.Sprintf("%.f",quantity) which could potentially lead to the same issue I ran into for the PaperWallet.

Also another question I have. You determine the precision for the quantity based on the stepSize value from the LOT_SIZE filter. I'm just curious, is there a reason you are not using baseAssetPrecision, quotePrecision, or quoteAssetPrecision? Or are these not meant to be used for that?

{
	"symbol":"BTCBUSD",
	"status":"TRADING",
	"baseAsset":"BTC",
	"baseAssetPrecision":8,
	"quoteAsset":"BUSD",
	"quotePrecision":8,
	"quoteAssetPrecision":8,
	"baseCommissionPrecision":8,
	"quoteCommissionPrecision":8,
	"orderTypes":["LIMIT","LIMIT_MAKER","MARKET","STOP_LOSS_LIMIT","TAKE_PROFIT_LIMIT"],
	"icebergAllowed":true,
	"ocoAllowed":true,
	"quoteOrderQtyMarketAllowed":true,
	"allowTrailingStop":true,
	"isSpotTradingAllowed":true,
	"isMarginTradingAllowed":true,
	"filters":[
		{"filterType":"PRICE_FILTER","minPrice":"0.01000000","maxPrice":"1000000.00000000","tickSize":"0.01000000"},
		{"filterType":"PERCENT_PRICE","multiplierUp":"5","multiplierDown":"0.2","avgPriceMins":5},
		{"filterType":"LOT_SIZE","minQty":"0.00001000","maxQty":"9000.00000000","stepSize":"0.00001000"},
		{"filterType":"MIN_NOTIONAL","minNotional":"10.00000000","applyToMarket":true,"avgPriceMins":5},
		{"filterType":"ICEBERG_PARTS","limit":10},
		{"filterType":"MARKET_LOT_SIZE","minQty":"0.00000000","maxQty":"205.49537419","stepSize":"0.00000000"},
		{"filterType":"TRAILING_DELTA","minTrailingAboveDelta":10,"maxTrailingAboveDelta":2000,"minTrailingBelowDelta":10,"maxTrailingBelowDelta":2000},
		{"filterType":"MAX_NUM_ORDERS","maxNumOrders":200},
		{"filterType":"MAX_NUM_ALGO_ORDERS","maxNumAlgoOrders":5}],
	"permissions":["SPOT","MARGIN"]
}

@rodrigo-brito
Copy link
Owner

In the first versions of the bot, I used order size without the LOT_SIZE control and Binance blocked a lot of requests.
The LOT_SIZE refers to the decimal precision. And baseAssetPrecision / quotePrecision includes non-decimal numbers.

You can read in more details here: https://binance-docs.github.io/apidocs/spot/en/#filters
But the main rules for order size are:

- quantity >= minQty
- quantity <= maxQty
- (quantity-minQty) % stepSize == 0

Then, you have to use always a size in fractions of stepSize

@rene-post
Copy link
Contributor Author

rene-post commented Jul 13, 2022

FYI

For QuoteOrderQuantity you use %.2f format in a market quote order.
According to the following link that should be limited (quoteOrderQty)
It also mentions MIN_NOTIONAL that allows you to not send orders for quantities below eg. $10 for BTCBUSD

W.r.t. the lot size; found a helper function on how to combine precision and lot size in the go-binance package:
AmountToLotSize
This seems to confirm that your approach, assuming that using the stepSize as lot argument is correct for calculating the base asset quantity. The function additionally applies the precision what probably should be the value in baseAssetPrecision

// AmountToLotSize converts an amount to a lot sized amount
func AmountToLotSize(lot float64, precision int, amount float64) float64 {
	return math.Trunc(math.Floor(amount/lot)*lot*math.Pow10(precision)) / math.Pow10(precision)
}

@rodrigo-brito
Copy link
Owner

Sure, I will do a double-check and replace this soon.
Thank you so much for the information @rene-post!

@rodrigo-brito
Copy link
Owner

@rene-post fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants