Repository: freqtrade/freqtrade

Issue:
WARNING - Unable to sell trade: Insufficient funds to create limit sell order on market
## Step 1: Have you search for this issue before posting it?

I've only found closed issues similar to mine but mine differs.

## Step 2: Describe your environment

I'm running the dockerized development version (latest one)

  * Branch: Develop

## Step 3: Describe the problem:

Here are the logs:
```
2019-12-09 04:38:43,639 - freqtrade.freqtradebot - INFO - Buy signal found: about create a new trade with stake_amount: 21.63581523 ...
2019-12-09 04:38:43,639 - freqtrade.freqtradebot - INFO - Using Last Ask / Last Price
2019-12-09 04:38:44,353 - freqtrade.rpc.rpc_manager - INFO - Sending rpc message: {'type': buy, 'exchange': 'Binance', 'pair': 'KEY/USDT', 'limit': 0.002245, 'order_type': 'limit', 'stake_amount': 21.635065, 'stake_currency': 'USDT', 'fiat_currency': 'EUR'}
2019-12-09 04:39:14,437 - freqtrade.rpc.fiat_convert - ERROR - Error in _find_price: HTTPSConnectionPool(host='api.coinmarketcap.com', port=443): Read timed out. (read timeout=30)
2019-12-09 04:39:14,599 - freqtrade.freqtradebot - INFO - Found open order for Trade(id=None, pair=KEY/USDT, amount=9637.00000000, open_rate=0.00224500, open_since=closed)
2019-12-09 04:39:14,830 - freqtrade.freqtradebot - INFO - Applying fee on amount for Trade(id=None, pair=KEY/USDT, amount=9637.00000000, open_rate=0.00224500, open_since=closed) failed: myTrade-Dict empty found
2019-12-09 04:39:14,830 - freqtrade.persistence - INFO - Updating trade (id=None) ...
2019-12-09 04:39:14,830 - freqtrade.persistence - INFO - LIMIT_BUY has been fulfilled for Trade(id=None, pair=KEY/USDT, amount=9637.00000000, open_rate=0.00224500, open_since=closed).
2019-12-09 04:39:15,328 - freqtrade.wallets - INFO - Wallets synced.
2019-12-09 04:39:15,823 - freqtrade.wallets - INFO - Wallets synced.
2019-12-09 04:39:16,576 - freqtrade.freqtradebot - INFO - Bot heartbeat. PID=1
2019-12-09 04:40:45,342 - freqtrade.freqtradebot - WARNING - Unable to sell trade: Insufficient funds to create limit sell order on market KEY/USDT.Tried to sell amount 9637.0 at rate 0.002265.Message: binance Account has insufficient balance for requested action.
```
The only way to solve this Is to manually update the record corresponding to the transaction.


Discussion:
When you say "latest", we'll still need the version you're using, since "latest" tends to be very time-dependant.

you can find that from the docker container as follows: 
```
#  docker exec <containername> cat freqtrade_commit
 docker exec freqtrade cat freqtrade_commit
```

I assume this happens on binance, with BNB fees turned off (or no BNB available)... ? 

the key here is the following line:
```
2019-12-09 04:39:14,830 - freqtrade.freqtradebot - INFO - Applying fee on amount for Trade(id=None, pair=KEY/USDT, amount=9637.00000000, open_rate=0.00224500, open_since=closed) failed: myTrade-Dict empty found
```

This prevents the bot from updating the fee (i assume you don't have 9637 KEY in your account, but 9636.xx KEY).

Now there's multiple possibilities why this can happen... to analyze this further:
please log into your exchange, look at the orders for KEY.

Info we'll need:
* time the order was made (and when it executed)
* fee amount (in BNB or in KEY or in USDT)
Here is the commit:
`8dd9b5c6fba973b98defc0f9a9e2e3c01af735dd`
BNB fees are turned on but no BNB is available (once a day I convert small amounts of different currencies to BNB).
The time the order was made is 12-09 10:47:50 and the fee is 0.02121791 USDT.
This isn't the only time it happened by the way. It happens pretty often and It just happened with CTXC/USDT
The timestamps somehow does not add up.

What's your timezone ... ? 

you say the order was at `12-09 10:47:50` - the logs indicate a buy at `2019-12-09 04:38:44` - and (attempted) sell at `04:40:45`. That would indicate a timezone of +6:10 (+6:11, to be precise)... 

I don't know any timezone that has a time-scale below 30 minutes - so i think the time is somehow off (probably on the server ...) ? 

Potentially related to #2383 
I'm sorry, I picked the wrong order. Here are the right details (My time zone is +1):
Date : 12-09 05:38:44
Fees: 9.637 KEY
hmm, as in the old issue, we'll need more info again ... unfortunately this is something that's very hard to recreate - since i've done quite some trades on binance, and didn't have this problem in quite some time (apart from when i was recreating #2383 - but i intentionally used a different timezone there).

Please run the following (with your api-key / secret)... 

``` python

import ccxt
from datetime import datetime
ct = ccxt.Binance({'apiKey': 'yourkey', 'secret': 'yoursecret'})
# ct.fetch_order('order_id', 'pair')
ct.fetch_orders(symbol='KEY/USDT', since=int(datetime(2019, 12, 9, 4, 3).timestamp()))
```
It didn't print anything, so I added a print on fetch_orders. Here's the output:
`[{'info': {'symbol': 'KEYUSDT', 'orderId': 2987432, 'orderListId': -1, 'clientOrderId': 'MU4ImlTohG3i607uzE15Fd', 'price': '0.00224500', 'origQty': '9637.00000000', 'executedQty': '9637.00000000', 'cummulativeQuoteQty': '21.63506500', 'status': 'FILLED', 'timeInForce': 'GTC', 'type': 'LIMIT', 'side': 'BUY', 'stopPrice': '0.00000000', 'icebergQty': '0.00000000', 'time': 1575866324246, 'updateTime': 1575866324246, 'isWorking': True, 'origQuoteOrderQty': '0.00000000'}, 'id': '2987432', 'timestamp': 1575866324246, 'datetime': '2019-12-09T04:38:44.246Z', 'lastTradeTimestamp': None, 'symbol': 'KEY/USDT', 'type': 'limit', 'side': 'buy', 'price': 0.002245, 'amount': 9637.0, 'cost': 21.635065, 'average': 0.002245, 'filled': 9637.0, 'remaining': 0.0, 'status': 'closed', 'fee': None, 'trades': None}, {'info': {'symbol': 'KEYUSDT', 'orderId': 2999697, 'orderListId': -1, 'clientOrderId': '2DBY8K0r578BRgo2Zs4lEl', 'price': '0.00220400', 'origQty': '9627.00000000', 'executedQty': '9627.00000000', 'cummulativeQuoteQty': '21.21790800', 'status': 'FILLED', 'timeInForce': 'GTC', 'type': 'LIMIT', 'side': 'SELL', 'stopPrice': '0.00000000', 'icebergQty': '0.00000000', 'time': 1575884870651, 'updateTime': 1575884870651, 'isWorking': True, 'origQuoteOrderQty': '0.00000000'}, 'id': '2999697', 'timestamp': 1575884870651, 'datetime': '2019-12-09T09:47:50.651Z', 'lastTradeTimestamp': None, 'symbol': 'KEY/USDT', 'type': 'limit', 'side': 'sell', 'price': 0.002204, 'amount': 9627.0, 'cost': 21.217908, 'average': 0.0022040000000000002, 'filled': 9627.0, 'remaining': 0.0, 'status': 'closed', 'fee': None, 'trades': None}]`

Resolving patch:
diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py
--- a/freqtrade/freqtradebot.py
+++ b/freqtrade/freqtradebot.py
@@ -892,6 +892,27 @@ def handle_timedout_limit_sell(self, trade: Trade, order: Dict) -> bool:
         # TODO: figure out how to handle partially complete sell orders
         return False
 
+    def _safe_sell_amount(self, pair: str, amount: float) -> float:
+        """
+        Get sellable amount.
+        Should be trade.amount - but will fall back to the available amount if necessary.
+        This should cover cases where get_real_amount() was not able to update the amount
+        for whatever reason.
+        :param pair: Pair we're trying to sell
+        :param amount: amount we expect to be available
+        :return: amount to sell
+        :raise: DependencyException: if available balance is not within 2% of the available amount.
+        """
+        wallet_amount = self.wallets.get_free(pair.split('/')[0])
+        logger.debug(f"{pair} - Wallet: {wallet_amount} - Trade-amount: {amount}")
+        if wallet_amount > amount:
+            return amount
+        elif wallet_amount > amount * 0.98:
+            logger.info(f"{pair} - Falling back to wallet-amount.")
+            return wallet_amount
+        else:
+            raise DependencyException("Not enough amount to sell.")
+
     def execute_sell(self, trade: Trade, limit: float, sell_reason: SellType) -> None:
         """
         Executes a limit sell for the given trade and limit
@@ -922,10 +943,12 @@ def execute_sell(self, trade: Trade, limit: float, sell_reason: SellType) -> Non
             # Emergencysells (default to market!)
             ordertype = self.strategy.order_types.get("emergencysell", "market")
 
+        amount = self._safe_sell_amount(trade.pair, trade.amount)
+
         # Execute sell and update trade record
         order = self.exchange.sell(pair=str(trade.pair),
                                    ordertype=ordertype,
-                                   amount=trade.amount, rate=limit,
+                                   amount=amount, rate=limit,
                                    time_in_force=self.strategy.order_time_in_force['sell']
                                    )
 


Test patch:
diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py
--- a/tests/test_freqtradebot.py
+++ b/tests/test_freqtradebot.py
@@ -887,7 +887,7 @@ def test_execute_buy(mocker, default_conf, fee, limit_buy_order) -> None:
         'freqtrade.freqtradebot.FreqtradeBot',
         get_target_bid=get_bid,
         _get_min_pair_stake_amount=MagicMock(return_value=1)
-        )
+    )
     buy_mm = MagicMock(return_value={'id': limit_buy_order['id']})
     mocker.patch.multiple(
         'freqtrade.exchange.Exchange',
@@ -1682,6 +1682,7 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, fee, mock
     time.sleep(0.01)  # Race condition fix
     trade.update(limit_buy_order)
     assert trade.is_open is True
+    freqtrade.wallets.update()
 
     patch_get_signal(freqtrade, value=(False, True))
     assert freqtrade.handle_trade(trade) is True
@@ -2326,6 +2327,7 @@ def test_execute_sell_down_stoploss_on_exchange_dry_run(default_conf, ticker, fe
 def test_execute_sell_sloe_cancel_exception(mocker, default_conf, ticker, fee, caplog) -> None:
     freqtrade = get_patched_freqtradebot(mocker, default_conf)
     mocker.patch('freqtrade.exchange.Exchange.cancel_order', side_effect=InvalidOrderException())
+    mocker.patch('freqtrade.wallets.Wallets.get_free', MagicMock(return_value=300))
     sellmock = MagicMock()
     patch_exchange(mocker)
     mocker.patch.multiple(
@@ -2548,6 +2550,7 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order,
 
     trade = Trade.query.first()
     trade.update(limit_buy_order)
+    freqtrade.wallets.update()
     patch_get_signal(freqtrade, value=(False, True))
     assert freqtrade.handle_trade(trade) is True
     assert trade.sell_reason == SellType.SELL_SIGNAL.value
@@ -2578,6 +2581,7 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order,
 
     trade = Trade.query.first()
     trade.update(limit_buy_order)
+    freqtrade.wallets.update()
     patch_get_signal(freqtrade, value=(False, True))
     assert freqtrade.handle_trade(trade) is True
     assert trade.sell_reason == SellType.SELL_SIGNAL.value
@@ -2603,7 +2607,7 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, fee, mocker
     freqtrade = FreqtradeBot(default_conf)
     patch_get_signal(freqtrade)
     freqtrade.strategy.stop_loss_reached = MagicMock(return_value=SellCheckTuple(
-            sell_flag=False, sell_type=SellType.NONE))
+        sell_flag=False, sell_type=SellType.NONE))
     freqtrade.create_trades()
 
     trade = Trade.query.first()
@@ -2638,11 +2642,87 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, fee, mocke
 
     trade = Trade.query.first()
     trade.update(limit_buy_order)
+    freqtrade.wallets.update()
     patch_get_signal(freqtrade, value=(False, True))
     assert freqtrade.handle_trade(trade) is True
     assert trade.sell_reason == SellType.SELL_SIGNAL.value
 
 
+def test_sell_not_enough_balance(default_conf, limit_buy_order,
+                                 fee, mocker, caplog) -> None:
+    patch_RPCManager(mocker)
+    patch_exchange(mocker)
+    mocker.patch.multiple(
+        'freqtrade.exchange.Exchange',
+        fetch_ticker=MagicMock(return_value={
+            'bid': 0.00002172,
+            'ask': 0.00002173,
+            'last': 0.00002172
+        }),
+        buy=MagicMock(return_value={'id': limit_buy_order['id']}),
+        get_fee=fee,
+    )
+
+    freqtrade = FreqtradeBot(default_conf)
+    patch_get_signal(freqtrade)
+    freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
+
+    freqtrade.create_trades()
+
+    trade = Trade.query.first()
+    amnt = trade.amount
+    trade.update(limit_buy_order)
+    patch_get_signal(freqtrade, value=(False, True))
+    mocker.patch('freqtrade.wallets.Wallets.get_free', MagicMock(return_value=trade.amount * 0.985))
+
+    assert freqtrade.handle_trade(trade) is True
+    assert log_has_re(r'.*Falling back to wallet-amount.', caplog)
+    assert trade.amount != amnt
+
+
+def test__safe_sell_amount(default_conf, fee, caplog, mocker):
+    patch_RPCManager(mocker)
+    patch_exchange(mocker)
+    amount = 95.33
+    amount_wallet = 95.29
+    mocker.patch('freqtrade.wallets.Wallets.get_free', MagicMock(return_value=amount_wallet))
+    trade = Trade(
+        pair='LTC/ETH',
+        amount=amount,
+        exchange='binance',
+        open_rate=0.245441,
+        open_order_id="123456",
+        fee_open=fee.return_value,
+        fee_close=fee.return_value,
+    )
+    freqtrade = FreqtradeBot(default_conf)
+    patch_get_signal(freqtrade)
+
+    assert freqtrade._safe_sell_amount(trade.pair, trade.amount) == amount_wallet
+    assert log_has_re(r'.*Falling back to wallet-amount.', caplog)
+
+
+def test__safe_sell_amount_error(default_conf, fee, caplog, mocker):
+    patch_RPCManager(mocker)
+    patch_exchange(mocker)
+    amount = 95.33
+    amount_wallet = 91.29
+    mocker.patch('freqtrade.wallets.Wallets.get_free', MagicMock(return_value=amount_wallet))
+    trade = Trade(
+        pair='LTC/ETH',
+        amount=amount,
+        exchange='binance',
+        open_rate=0.245441,
+        open_order_id="123456",
+        fee_open=fee.return_value,
+        fee_close=fee.return_value,
+    )
+    freqtrade = FreqtradeBot(default_conf)
+    patch_get_signal(freqtrade)
+    with pytest.raises(DependencyException, match=r"Not enough amount to sell."):
+        assert freqtrade._safe_sell_amount(trade.pair, trade.amount)
+
+
 def test_locked_pairs(default_conf, ticker, fee, ticker_sell_down, mocker, caplog) -> None:
     patch_RPCManager(mocker)
     patch_exchange(mocker)
@@ -2703,6 +2783,7 @@ def test_ignore_roi_if_buy_signal(default_conf, limit_buy_order, fee, mocker) ->
 
     trade = Trade.query.first()
     trade.update(limit_buy_order)
+    freqtrade.wallets.update()
     patch_get_signal(freqtrade, value=(True, True))
     assert freqtrade.handle_trade(trade) is False
 
@@ -3440,6 +3521,7 @@ def test_order_book_ask_strategy(default_conf, limit_buy_order, limit_sell_order
 
     time.sleep(0.01)  # Race condition fix
     trade.update(limit_buy_order)
+    freqtrade.wallets.update()
     assert trade.is_open is True
 
     patch_get_signal(freqtrade, value=(False, True))
diff --git a/tests/test_integration.py b/tests/test_integration.py
--- a/tests/test_integration.py
+++ b/tests/test_integration.py
@@ -71,7 +71,7 @@ def test_may_execute_sell_stoploss_on_exchange_multi(default_conf, ticker, fee,
     )
     mocker.patch("freqtrade.strategy.interface.IStrategy.should_sell", should_sell_mock)
     wallets_mock = mocker.patch("freqtrade.wallets.Wallets.update", MagicMock())
-    mocker.patch("freqtrade.wallets.Wallets.get_free", MagicMock(return_value=1))
+    mocker.patch("freqtrade.wallets.Wallets.get_free", MagicMock(return_value=1000))
 
     freqtrade = get_patched_freqtradebot(mocker, default_conf)
     freqtrade.strategy.order_types['stoploss_on_exchange'] = True