Repository: freqtrade/freqtrade

Issue:
ZeroDivisionError: float division by zero
<!-- 
Have you searched for similar issues before posting it?

If you have discovered a bug in the bot, please [search our issue tracker](https://github.com/freqtrade/freqtrade/issues?q=is%3Aissue). 
If it hasn't been reported, please create a new issue.

Please do not use bug reports to request new features.
-->

## Describe your environment

  * Operating system: Ubuntu Server, raspberry pi 3
  * Latest develop_pi docker version
  
Note: All issues other than enhancement requests will be closed without further comment if the above template is deleted or not filled out.

## Describe the problem:

After executing some buys, it is now crashing over and over again.

  ```
2020-06-02 15:54:45,752 - freqtrade.persistence - INFO - Found open trade: Trade(id=24, pair=XMR/USD, amount=0.30576364, open_rate=65.41000000, open_since=2020-06-02 15:20:27)
2020-06-02 15:54:45,754 - freqtrade.persistence - INFO - Found open trade: Trade(id=25, pair=ETH/USD, amount=0.08561643, open_rate=233.60000000, open_since=2020-06-02 15:25:31)
2020-06-02 15:54:45,755 - freqtrade.persistence - INFO - Found open trade: Trade(id=26, pair=XRP/USD, amount=100.10511036, open_rate=0.19979000, open_since=2020-06-02 15:35:34)
2020-06-02 15:54:45,756 - freqtrade.persistence - INFO - Found open trade: Trade(id=27, pair=BCH/USD, amount=0.00004993, open_rate=247.40000000, open_since=2020-06-02 15:40:46)
2020-06-02 15:54:45,758 - freqtrade.persistence - INFO - Found open trade: Trade(id=28, pair=LTC/USD, amount=0.44023772, open_rate=45.43000000, open_since=2020-06-02 15:41:04)
2020-06-02 15:54:59,369 - freqtrade.freqtradebot - INFO - Found open order for Trade(id=27, pair=BCH/USD, amount=0.00004993, open_rate=247.40000000, open_since=2020-06-02 15:40:46)
2020-06-02 15:54:59,370 - freqtrade.commands.trade_commands - ERROR - float division by zero
2020-06-02 15:54:59,371 - freqtrade.commands.trade_commands - ERROR - Fatal exception!
Traceback (most recent call last):
  File "/freqtrade/freqtrade/commands/trade_commands.py", line 20, in start_trading
    worker.run()
  File "/freqtrade/freqtrade/worker.py", line 73, in run
    state = self._worker(old_state=state)
  File "/freqtrade/freqtrade/worker.py", line 107, in _worker
    self._throttle(func=self._process_running, throttle_secs=self._throttle_secs)
  File "/freqtrade/freqtrade/worker.py", line 128, in _throttle
    result = func(*args, **kwargs)
  File "/freqtrade/freqtrade/worker.py", line 141, in _process_running
    self.freqtrade.process()
  File "/freqtrade/freqtrade/freqtradebot.py", line 156, in process
    self.check_handle_timedout()
  File "/freqtrade/freqtrade/freqtradebot.py", line 894, in check_handle_timedout
    fully_cancelled = self.update_trade_state(trade, order)
  File "/freqtrade/freqtrade/freqtradebot.py", line 1207, in update_trade_state
    new_amount = self.get_real_amount(trade, order, order_amount)
  File "/freqtrade/freqtrade/freqtradebot.py", line 1262, in get_real_amount
    fee_cost, fee_currency, fee_rate = self.exchange.extract_cost_curr_rate(order)
  File "/freqtrade/freqtrade/exchange/exchange.py", line 1128, in extract_cost_curr_rate
    self.calculate_fee_rate(order))
  File "/freqtrade/freqtrade/exchange/exchange.py", line 1107, in calculate_fee_rate
    return round(order['fee']['cost'] / order['cost'], 8)
ZeroDivisionError: float division by zero
  ```



Discussion:
can you please run `freqtrade show-trades --trade-ids 27 --print-json` and post the output here.

or, since you're in docker, it'll probably someting around
`docker-compose run --rm freqtrade show-trades --trade-ids 27 --print-json`

We'll probably need some more information after that - but i hope this will give us a starting point as to why it's crashing (or at least for further queries)
```
2020-06-02 17:20:54,326 - freqtrade.commands.list_commands - INFO - Printing 1 Trades:
[
    {
        "trade_id": 27,
        "pair": "BCH/USD",
        "is_open": false,
        "fee_open": 0.0016,
        "fee_open_cost": null,
        "fee_open_currency": null,
        "fee_close": 0.0016,
        "fee_close_cost": null,
        "fee_close_currency": null,
        "open_date_hum": "2 hours ago",
        "open_date": "2020-06-02 15:40:46",
        "open_timestamp": 1591112446009,
        "close_date_hum": null,
        "close_date": null,
        "close_timestamp": null,
        "open_rate": 247.4,
        "open_rate_requested": 247.4,
        "open_trade_price": 20.032,
        "close_rate": null,
        "close_rate_requested": null,
        "amount": 4.993e-05,
        "stake_amount": 0.01235268,
        "close_profit": null,
        "close_profit_abs": null,
        "sell_reason": null,
        "sell_order_status": null,
        "stop_loss": 185.55,
        "stop_loss_pct": -25.0,
        "stoploss_order_id": null,
        "stoploss_last_update": "2020-06-02 15:51:52",
        "stoploss_last_update_timestamp": 1591113112124,
        "initial_stop_loss": 185.55,
        "initial_stop_loss_pct": -25.0,
        "min_rate": null,
        "max_rate": 0.0,
        "strategy": "Quickie",
        "ticker_interval": 5,
        "open_order_id": "O5Y7Z7-CBQPL-V3QWID",
        "exchange": "kraken"
    }
]
```
I assume you changed this trade to "isopen=false" ? 

either way - next step:
start a python shell (should work with docker as follows):

```
docker-compose run --rm --entrypoint python freqtrade 
```

then within that (hopefully opening python shell):

``` python
import ccxt

ct = ccxt.kraken({'apiKey': '<yourapikey>', 'secret': '<yourSecretkey>'})
print(ct.fetch_order('O5Y7Z7-CBQPL-V3QWID', 'BCH/USD'))
```

There is an additional question - what did happen on the exchange? (if you look at the UI) ... did the trade fill? was it half-filled? was it cancelled? ... 
Correct, I tried closing the trade in the DB to see if it would skip over it and continue trading.

the trade was canceled on Kraken.

```
{'info': {'id': 'O5Y7Z7-CBQPL-V3QWID', 'refid': None, 'userref': 0, 'status': 'canceled', 'reason': 'User requested', 'opentm': 1591112445.9233, 'closetm': 1591113058.2398, 'starttm': 0, 'expiretm': 0, 'descr': {'pair': 'BCHUSD', 'type': 'buy', 'ordertype': 'limit', 'price': '247.4', 'price2': '0', 'leverage': 'none', 'order': 'buy 0.08084074 BCHUSD @ limit 247.4', 'close': ''}, 'vol': '0.08084074', 'vol_exec': '0.00004993', 'cost': '0', 'fee': '0', 'price': '247.4', 'stopprice': '0.000000', 'limitprice': '0.000000', 'misc': 'partial', 'oflags': 'fciq', 'trades': ['TA3DTC-ARNY3-KJKSY2', 'TZBJKV-CFB5U-HBJIO4']}, 'id': 'O5Y7Z7-CBQPL-V3QWID', 'clientOrderId': '0', 'timestamp': 1591112445923, 'datetime': '2020-06-02T15:40:45.923Z', 'lastTradeTimestamp': None, 'status': 'canceled', 'symbol': 'BCH/USD', 'type': 'limit', 'side': 'buy', 'price': 247.4, 'cost': 0.0, 'amount': 0.08084074, 'filled': 4.993e-05, 'average': 247.4, 'remaining': 0.08079080999999999, 'fee': {'cost': 0.0, 'rate': None, 'currency': 'USD'}, 'trades': [{'id': 'TA3DTC-ARNY3-KJKSY2', 'order': 'O5Y7Z7-CBQPL-V3QWID', 'info': 'TA3DTC-ARNY3-KJKSY2', 'timestamp': None, 'datetime': None, 'symbol': 'BCH/USD', 'type': None, 'side': None, 'takerOrMaker': None, 'price': None, 'amount': None, 'cost': None, 'fee': None}, {'id': 'TZBJKV-CFB5U-HBJIO4', 'order': 'O5Y7Z7-CBQPL-V3QWID', 'info': 'TZBJKV-CFB5U-HBJIO4', 'timestamp': None, 'datetime': None, 'symbol': 'BCH/USD', 'type': None, 'side': None, 'takerOrMaker': None, 'price': None, 'amount': None, 'cost': None, 'fee': None}]}
```

 
![image](https://user-images.githubusercontent.com/1781970/83555245-014ff880-a4dc-11ea-9d37-8593c446b1e1.png)

Resolving patch:
diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py
--- a/freqtrade/exchange/exchange.py
+++ b/freqtrade/exchange/exchange.py
@@ -1104,9 +1104,12 @@ def calculate_fee_rate(self, order: Dict) -> Optional[float]:
                 order['fee']['cost'] / safe_value_fallback(order, order, 'filled', 'amount'), 8)
         elif fee_curr in self.get_pair_quote_currency(order['symbol']):
             # Quote currency - divide by cost
-            return round(order['fee']['cost'] / order['cost'], 8)
+            return round(order['fee']['cost'] / order['cost'], 8) if order['cost'] else None
         else:
             # If Fee currency is a different currency
+            if not order['cost']:
+                # If cost is None or 0.0 -> falsy, return None
+                return None
             try:
                 comb = self.get_valid_pair_combination(fee_curr, self._config['stake_currency'])
                 tick = self.fetch_ticker(comb)


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1590,6 +1590,7 @@ def buy_order_fee():
         'datetime': str(arrow.utcnow().shift(minutes=-601).datetime),
         'price': 0.245441,
         'amount': 8.0,
+        'cost': 1.963528,
         'remaining': 90.99181073,
         'status': 'closed',
         'fee': None
diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py
--- a/tests/exchange/test_exchange.py
+++ b/tests/exchange/test_exchange.py
@@ -2192,12 +2192,18 @@ def test_extract_cost_curr_rate(mocker, default_conf, order, expected) -> None:
         'fee': {'currency': 'NEO', 'cost': 0.0012}}, 0.001944),
     ({'symbol': 'ETH/BTC', 'amount': 2.21, 'cost': 0.02992561,
         'fee': {'currency': 'NEO', 'cost': 0.00027452}}, 0.00074305),
-    # TODO: More tests here!
     # Rate included in return - return as is
     ({'symbol': 'ETH/BTC', 'amount': 0.04, 'cost': 0.05,
         'fee': {'currency': 'USDT', 'cost': 0.34, 'rate': 0.01}}, 0.01),
     ({'symbol': 'ETH/BTC', 'amount': 0.04, 'cost': 0.05,
         'fee': {'currency': 'USDT', 'cost': 0.34, 'rate': 0.005}}, 0.005),
+    # 0.1% filled - no costs (kraken - #3431)
+    ({'symbol': 'ETH/BTC', 'amount': 0.04, 'cost': 0.0,
+      'fee': {'currency': 'BTC', 'cost': 0.0, 'rate': None}}, None),
+    ({'symbol': 'ETH/BTC', 'amount': 0.04, 'cost': 0.0,
+      'fee': {'currency': 'ETH', 'cost': 0.0, 'rate': None}}, 0.0),
+    ({'symbol': 'ETH/BTC', 'amount': 0.04, 'cost': 0.0,
+      'fee': {'currency': 'NEO', 'cost': 0.0, 'rate': None}}, None),
 ])
 def test_calculate_fee_rate(mocker, default_conf, order, expected) -> None:
     mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', return_value={'last': 0.081})