# Buggy code
def send_msg(self, msg: Dict[str, Any]) -> None:
    """Send a message to telegram channel"""

    if msg["type"] == RPCMessageType.BUY_NOTIFICATION:
        if self._fiat_converter:
            msg["stake_amount_fiat"] = self._fiat_converter.convert_amount(
                msg["stake_amount"], msg["stake_currency"], msg["fiat_currency"]
            )
        else:
            msg["stake_amount_fiat"] = 0

        message = (
            "*{exchange}:* Buying {pair}\n"
            "at rate `{limit:.8f}\n"
            "({stake_amount:.6f} {stake_currency}"
        ).format(**msg)

        if msg.get("fiat_currency", None):
            message += ",{stake_amount_fiat:.3f} {fiat_currency}".format(**msg)
        message += ")`"

    elif msg["type"] == RPCMessageType.SELL_NOTIFICATION:
        msg["amount"] = round(msg["amount"], 8)
        msg["profit_percent"] = round(msg["profit_percent"] * 100, 2)
        msg["duration"] = msg["close_date"].replace(microsecond=0) - msg[
            "open_date"
        ].replace(microsecond=0)
        msg["duration_min"] = msg["duration"].total_seconds() / 60

        message = (
            "*{exchange}:* Selling {pair}\n"
            "*Rate:* `{limit:.8f}`\n"
            "*Amount:* `{amount:.8f}`\n"
            "*Open Rate:* `{open_rate:.8f}`\n"
            "*Current Rate:* `{current_rate:.8f}`\n"
            "*Sell Reason:* `{sell_reason}`\n"
            "*Duration:* `{duration} ({duration_min:.1f} min)`\n"
            "*Profit:* `{profit_percent:.2f}%`"
        ).format(**msg)

        # Check if all sell properties are available.
        # This might not be the case if the message origin is triggered by /forcesell
        if (
            all(prop in msg for prop in ["gain", "fiat_currency", "stake_currency"])
            and self._fiat_converter
        ):
            msg["profit_fiat"] = self._fiat_converter.convert_amount(
                msg["profit_amount"], msg["stake_currency"], msg["fiat_currency"]
            )
            message += (
                "` ({gain}: {profit_amount:.8f} {stake_currency}`"
                "` / {profit_fiat:.3f} {fiat_currency})`"
            ).format(**msg)

    elif msg["type"] == RPCMessageType.STATUS_NOTIFICATION:
        message = "*Status:* `{status}`".format(**msg)

    elif msg["type"] == RPCMessageType.WARNING_NOTIFICATION:
        message = "*Warning:* `{status}`".format(**msg)

    elif msg["type"] == RPCMessageType.CUSTOM_NOTIFICATION:
        message = "{status}".format(**msg)

    else:
        raise NotImplementedError("Unknown message type: {}".format(msg["type"]))

    self._send_msg(message)


# Traceback (Exception)
2020-02-20 22:47:28,025 - freqtrade - ERROR - Fatal exception!
Traceback (most recent call last):
File "/opt/tradebot/freqtrade/.env/lib/python3.7/site-packages/talib/__init__.py", line 20, in wrapper
for arg in chain(args, kwargs.values())
StopIteration

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/freqtrade/freqtrade/main.py", line 36, in main
return_code = args['func'](args)
File "/freqtrade/freqtrade/commands/optimize_commands.py", line 76, in start_hyperopt
hyperopt.start()
File "/freqtrade/freqtrade/optimize/hyperopt.py", line 488, in start
preprocessed = self.backtesting.strategy.tickerdata_to_dataframe(data)
File "/freqtrade/freqtrade/strategy/interface.py", line 448, in tickerdata_to_dataframe
for pair, pair_data in tickerdata.items()}
File "/freqtrade/freqtrade/strategy/interface.py", line 448, in <dictcomp>
for pair, pair_data in tickerdata.items()}
File "/freqtrade/freqtrade/strategy/interface.py", line 464, in advise_indicators
return self.populate_indicators(dataframe, metadata)
File "/freqtrade/user_data/strategies/MyDev.py", line 205, in populate_indicators
dataframe['mfi'] = ta.MFI(dataframe)
File "talib/_abstract.pxi", line 352, in talib._ta_lib.Function.__call__
File "talib/_abstract.pxi", line 383, in talib._ta_lib.Function.__call_function
File "/opt/tradebot/freqtrade/.env/lib/python3.7/site-packages/talib/__init__.py", line 24, in wrapper
return func(*args, **kwargs)
File "talib/_func.pxi", line 8454, in talib._ta_lib.MFI
Exception: volume is not double

# Fixed code
def send_msg(self, msg: Dict[str, Any]) -> None:
    """Send a message to telegram channel"""

    if msg["type"] == RPCMessageType.BUY_NOTIFICATION:
        if self._fiat_converter:
            msg["stake_amount_fiat"] = self._fiat_converter.convert_amount(
                msg["stake_amount"], msg["stake_currency"], msg["fiat_currency"]
            )
        else:
            msg["stake_amount_fiat"] = 0

        message = (
            "*{exchange}:* Buying {pair}\n"
            "*Amount:* `{amount:.8f}`\n"
            "*Open Rate:* `{limit:.8f}`\n"
            "*Current Rate:* `{current_rate:.8f}`\n"
            "*Total:* `({stake_amount:.6f} {stake_currency}"
        ).format(**msg)

        if msg.get("fiat_currency", None):
            message += ", {stake_amount_fiat:.3f} {fiat_currency}".format(**msg)
        message += ")`"

    elif msg["type"] == RPCMessageType.BUY_CANCEL_NOTIFICATION:
        message = "*{exchange}:* Cancelling Open Buy Order for {pair}".format(**msg)

    elif msg["type"] == RPCMessageType.SELL_NOTIFICATION:
        msg["amount"] = round(msg["amount"], 8)
        msg["profit_percent"] = round(msg["profit_percent"] * 100, 2)
        msg["duration"] = msg["close_date"].replace(microsecond=0) - msg[
            "open_date"
        ].replace(microsecond=0)
        msg["duration_min"] = msg["duration"].total_seconds() / 60

        message = (
            "*{exchange}:* Selling {pair}\n"
            "*Amount:* `{amount:.8f}`\n"
            "*Open Rate:* `{open_rate:.8f}`\n"
            "*Current Rate:* `{current_rate:.8f}`\n"
            "*Close Rate:* `{limit:.8f}`\n"
            "*Sell Reason:* `{sell_reason}`\n"
            "*Duration:* `{duration} ({duration_min:.1f} min)`\n"
            "*Profit:* `{profit_percent:.2f}%`"
        ).format(**msg)

        # Check if all sell properties are available.
        # This might not be the case if the message origin is triggered by /forcesell
        if (
            all(prop in msg for prop in ["gain", "fiat_currency", "stake_currency"])
            and self._fiat_converter
        ):
            msg["profit_fiat"] = self._fiat_converter.convert_amount(
                msg["profit_amount"], msg["stake_currency"], msg["fiat_currency"]
            )
            message += (
                " `({gain}: {profit_amount:.8f} {stake_currency}"
                " / {profit_fiat:.3f} {fiat_currency})`"
            ).format(**msg)

    elif msg["type"] == RPCMessageType.SELL_CANCEL_NOTIFICATION:
        message = "*{exchange}:* Cancelling Open Sell Order for {pair}".format(**msg)

    elif msg["type"] == RPCMessageType.STATUS_NOTIFICATION:
        message = "*Status:* `{status}`".format(**msg)

    elif msg["type"] == RPCMessageType.WARNING_NOTIFICATION:
        message = "*Warning:* `{status}`".format(**msg)

    elif msg["type"] == RPCMessageType.CUSTOM_NOTIFICATION:
        message = "{status}".format(**msg)

    else:
        raise NotImplementedError("Unknown message type: {}".format(msg["type"]))

    self._send_msg(message)