Repository: freqtrade/freqtrade

Issue:
bibox fetchcurrencies error
Hello,
I am testing other exchanges and saw the following error:

2019-11-05 12:32:07,463 - freqtrade.exchange.exchange - WARNING - Unable to initialize markets. Reason: bibox fetchCurrencies is an authenticated endpoint, therefore it requires 'apiKey' and 'secret' credentials. If you don't need currency details, set exchange.has['fetchCurrencies'] = False before calling its methods.
2019-11-05 12:32:07,463 - freqtrade - ERROR - Fatal exception!

Seems like bibox requires auth via API before fetching currencies.
Can we add an option in config file like requireauth (true/false) so code can pass it ?



Discussion:
What's the command you use?

For Utils (and backtesting), we (intentionally) remove the credentials.
this will protect your API keys - since they'll not be exposed to the network without need.

For dry / live runs - keys are not removed so you should be able to use that mode.

#2476 will introduce one method where this is done (not spread across the codebase) - so to do tests with unsupported exchanges, one simple return-statement will suffice.

Since this is an edge-case on a unsupported exchange - i don't think it makes sense to expose it via a configuration setting - only users with experience with the freqtrade code should try to implement new exchanges - since more configuration may be required depending on the exchange's functioning.

Should we support this exchange in the future, we may decide on a different approach - until then, #2476 will allow to do just what you ask by adding one "return" statement at the beginning of that function.
hope this works for you... ? 
Ok i will wait for 2476. I already put my credentials in my config-bibox.json but nobody reads them.
Seems like for any tests (job)  on that exchange need to pass credentials.
that's possible - but honestly, if it fails "this early" there are high hopes that it'll fail later down the road too...

you can look at [the new exchange docs](https://www.freqtrade.io/en/latest/developer/#implement-a-new-exchange-wip)  in the meantime to verify if ohlcv data is available or not ... (and with enough candles per call).
Ok then leave it. I was trying to test as much as possible exchanges which can work with freqtrade.
At least most of high volume ones.
Seems like bibox is too complicated.
Lets close the ticket for now.
well that's not said - maybe the auth is the only thing that's blocking it - and if it is, we can find ways around it (but i wouldn't implement these if it won't work in the future anyway).

Just pointed out the checks i did before deciding if an exchange has good hopes to work ... ;) 

I have a solution in my stashes... (got to it when was testing `list-pairs` for all available exchanges)

#2476 does not close it

from #2476:

> It does not say that it will work without credentials, it says that it needs credentials for fetchCurrencies()...

yes - but fetchCurrencies() is part of load_markets() - which IS a requirement for everything we use (including list-markets)...

>#2476 does not close it

i disgree for 2 reasons:
* the user closed it, not me nor the PR
* it enables testing of this exchange. I would not invest any time in trying to make something configurable where we're not sure it'll work in the end ... 
The reason for this issue is the following in ccxt:

https://github.com/ccxt/ccxt/blob/be6786335454db25171ed8d742605309abe47215/python/ccxt/base/exchange.py#L1252-L1254

for bibox, the ccxt exchange implementation does not contain exchange-specific fetch_markets, so this one is called. However, it does contain fetch_currencies(), as you can see from the code above, `load_markets()` calls `fetch_currencies()`.

Actually, `fetch_currencies()` is not really needed here (it's useful, provides many details on currencies, but this info is not really needed in the generic `load_markets()`). This API entry on bibox exchange is private and causes this error.

As you can see, if `self.has['fetchCurrencies']` is False, the generic implementation will gracefully fallback to calling the generic `set_markets()`. That's what is needed for this exchange: simply set ccxt's `has['fetchCurrencies'] = False` for bibox.

The solution to this is simpler than we thought it is.
Please put the following in your config (the key is the line with "has") - the rest should be in the default-configuration already.

```
        "ccxt_config": {
            "enableRateLimit": true,
            "has": {"fetchCurrencies": false}
        },
        "ccxt_async_config": {
            "enableRateLimit": true,
            "rateLimit": 500,
            "has": {"fetchCurrencies": false}
        },

```

You'll then need to use `freqtrade --config ThisConfig.json list-pairs` (and other commands). 
Please let us know if the exchange shows other problems.
This should in this case be in a `config_bibox.json.example` then.

Should the exchange be confirmed working - and all other operations work, then yes (or it'll be subclassed to make this easier).

However for now it's for testing by @sanitariu only, since noone of us has an account on this exchange.
Yes thank you for the fixes. I am going to test it now by downloading data and other commands....
I confirm that after adding "has": {"fetchCurrencies": false} the following commands at bibox are working: 'list-timeframes', 'list-markets', 'list-pairs', 'download-data'
I may try real trading now if i find good pairs.
Thank you for the fixes !!! Very good support from you people :)
Let us know if the "rest" works, so we can add this "fetchCurrencies:false" fix permanently for this exchange - removing this "circumstance", thanks.


Opened the issue back till the reporting results for the 'rest', so it's still open...


Resolving patch:
diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py
--- a/freqtrade/exchange/__init__.py
+++ b/freqtrade/exchange/__init__.py
@@ -15,3 +15,4 @@
                                          symbol_is_pair)
 from freqtrade.exchange.kraken import Kraken  # noqa: F401
 from freqtrade.exchange.binance import Binance  # noqa: F401
+from freqtrade.exchange.bibox import Bibox  # noqa: F401
diff --git a/freqtrade/exchange/bibox.py b/freqtrade/exchange/bibox.py
new file mode 100644
--- /dev/null
+++ b/freqtrade/exchange/bibox.py
@@ -0,0 +1,22 @@
+""" Bibox exchange subclass """
+import logging
+from typing import Dict
+
+from freqtrade.exchange import Exchange
+
+logger = logging.getLogger(__name__)
+
+
+class Bibox(Exchange):
+    """
+    Bibox exchange class. Contains adjustments needed for Freqtrade to work
+    with this exchange.
+
+    Please note that this exchange is not included in the list of exchanges
+    officially supported by the Freqtrade development team. So some features
+    may still not work as expected.
+    """
+
+    # fetchCurrencies API point requires authentication for Bibox,
+    # so switch it off for Freqtrade load_markets()
+    _ccxt_config: Dict = {"has": {"fetchCurrencies": False}}
diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py
--- a/freqtrade/exchange/exchange.py
+++ b/freqtrade/exchange/exchange.py
@@ -30,6 +30,9 @@ class Exchange:
 
     _config: Dict = {}
 
+    # Parameters to add directly to ccxt sync/async initialization.
+    _ccxt_config: Dict = {}
+
     # Parameters to add directly to buy/sell calls (like agreeing to trading agreement)
     _params: Dict = {}
 
@@ -91,10 +94,17 @@ def __init__(self, config: dict, validate: bool = True) -> None:
         self._trades_pagination_arg = self._ft_has['trades_pagination_arg']
 
         # Initialize ccxt objects
+        ccxt_config = self._ccxt_config.copy()
+        ccxt_config = deep_merge_dicts(exchange_config.get('ccxt_config', {}),
+                                       ccxt_config)
         self._api = self._init_ccxt(
-            exchange_config, ccxt_kwargs=exchange_config.get('ccxt_config'))
+            exchange_config, ccxt_kwargs=ccxt_config)
+
+        ccxt_async_config = self._ccxt_config.copy()
+        ccxt_async_config = deep_merge_dicts(exchange_config.get('ccxt_async_config', {}),
+                                             ccxt_async_config)
         self._api_async = self._init_ccxt(
-            exchange_config, ccxt_async, ccxt_kwargs=exchange_config.get('ccxt_async_config'))
+            exchange_config, ccxt_async, ccxt_kwargs=ccxt_async_config)
 
         logger.info('Using Exchange "%s"', self.name)
 


Test patch: