Hello I've trying to liquidate a position in cryptos ("EURUSDT") but for some reason after my first open-close position some minimun capital keeps invested in amount of 0.00000683994. I've been trying with self.liquidate(self._btc) and self.set_holdings(self._btc, 0) but that amount stills remaining (I notice this because I'm using a if with self.portfolio.invested for liquidate). I attach my orders info, code and backtest. I hope someone read and find some solution or reason why is this. And thanks in advance
Date TimeSymbolTypePriceQuantityStatusTag-2021-01-01 01:05:00BTCUSDTSell Market
Fill: 29,239.00 USDT
-0.00341997Filled 2021-01-01 01:05:00BTCUSDT- 0Submitted 2021-01-01 01:05:00BTCUSDT-
Fill: 29,239.00 USDT
-0.00341997Filled -2021-01-01 03:40:00BTCUSDTBuy Market
Fill: 29,087.00 USDT
0.00341997FilledLiquidated2021-01-01 03:40:00BTCUSDT- 0Submitted 2021-01-01 03:40:00BTCUSDT-
Fill: 29,087.00 USDT
0.00341313006Filled -2021-01-01 03:45:00BTCUSDTBuy Market 0.00000683Invalid 2021-01-01 03:45:00BTCUSDT- 0InvalidBrokerageModel declared unable to submit order: [3] Warning - Code: NotSupported - The minimum order size (in quote currency) for BTCUSDT is 0.00004. Order quantity was 0.00000683.
Mia Alissi
Here is a review of 'Juan’s' code for logical bugs that could cause tiny leftover crypto "dust" positions after liquidation, with a summary and advice for fixing:
Findings - Code Logic/Behavior Issues:
Order Sizing Not Adjusted for Exchange Minimums:
When you place market orders with
self.market_order(self._btc, self.money / precio)
(or negative for sell), you do not ensure the order quantity (BTC) is an exact multiple of the exchange's minimum order size. For example, if Bitfinex enforces a minimum order size of 0.00004 BTC, but your calculation creates a value like 0.00341313, after round-trip trading, you can end up holding a residual (dust) less than 0.00004.self.liquidate and self.set_holdings(…, 0) Cannot Remove Dust:
If
self.portfolio[self._btc].quantity
drops below the minimum lot size, bothself.liquidate(self._btc)
andself.set_holdings(self._btc, 0)
will repeatedly fail to clear the position, due to minimum-order logic at the brokerage/exchange level.Incorrect Reliance on self.portfolio.invested:
This property can be
True
even if the position is a trivial, non-closable dust amount.No Manual Rounding/Truncating of Position Sizes:
Your code never truncates order sizes to the allowed minimum-multiple granularity, nor does it prevent further "rounding errors" from accumulating.
Summary of the Bug:
The "dust" (e.g., 0.000006) remains in your portfolio because after buy/sell actions, the position size is below the minimum threshold required for a legal trade on the exchange (in this case, Bitfinex's 0.00004 BTC). Since neither Liquidate nor set_holdings can clear such tiny amounts, your logic keeps treating the position as "open", but it's un-actionable, causing confusion.
What to Do Instead (How to Fix):
Before placing any market order, always round down the order size so it is an exact multiple of the exchange's minimum order, and never attempt to trade amounts smaller than this.
Example pseudocode:
Only submit the order if
qty >= minimum
.Avoid repeated liquidate or set_holdings calls for quantities already below the exchange minimum; just skip the call.
Accept that dust less than the minimum can't be removed by orders; disregard these for logical 'flat' state in your logic.
In Short:
The code allows rounding errors and does not enforce minimum increments per exchange rules for crypto order sizing, which leads to non-zero, untradeable remnants after liquidation. Add logic to always round/truncate every order size to a valid minimum, and don’t try to liquidate if below that threshold.
Let me know if you want a code example showing how to implement the correct order truncating and minimum checks!
Sources: Opening Range Breakout for Stocks in Play
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Juan Caicedo
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!