Repository: freqtrade/freqtrade

Issue:
Pax balance not detected
Version 2019.5
Bot won't detect pax base, will update to newest to see if fixed. Will also assumes that this is the same issue for other stable coins that are not tether 

Last version of CCTX
Running 2019.6
Exchange Binance
Edited to add more information about the issue
Pax balance not detected
Version 2019.5
Bot won't detect pax base, will update to newest to see if fixed. Will also assumes that this is the same issue for other stable coins that are not tether 

Last version of CCTX
Running 2019.6
Exchange Binance
Edited to add more information about the issue


Discussion:
This is lacking quite some information.

What exchange are you using?
what version of ccxt?

Edit: did you get any message while starting the bot?
> This is lacking quite some information.
> 
> What exchange are you using?
> what version of ccxt?
> 
> Edit: did you get any message while starting the bot?

No, no specific message.
So what's the behaviour you observed? "does not detect" is very generic ... 
I also did not get the issue...
Basically when you click Balance it says I have PAX < 1, and is not included in the overall calculation of my balance.
This means that it does recognize that you have PAX in your account - however it's < 1$, which is excluded due to "binance dust", which has the potential to show a very large amount of coins with almost 0 balance.

The limit is 0.0001 BTC - which is ~0.91$ at this moment (according to google - but it'll fluctuate a lot ).
Even if you have this balance, it'll be below every limit you could use as stake-currency due to binance having min_notational / lotsize.
@xmatthias I'm aware, I was holding around 1500 PAX so that was not the case.
without the related logs i doubt we have a chance to recreate this problem (also, i don't currently hold PAX ...)
It's simply to re-create this issue, you simply buy PAX and query for balance, i can do one, give me a few minutes

I suspect that other stable pairs do give the same issues, so testing for TUSD, USDC and so on is also trivial as they should be worth 1$ USD

There's nothing on the logs 
@xmatthias 
````
2019-07-03 01:34:26,838 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:31,840 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:36,844 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:41,844 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:46,847 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:51,853 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:56,854 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:57,793 - freqtrade.rpc.telegram - INFO - Executing handler: _balance for chat_id: 146554112
2019-07-03 01:35:01,859 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:35:05,848 - freqtrade.rpc.telegram - INFO - Executing handler: _balance for chat_id: 146554112
2019-07-03 01:35:05,878 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for ETH/BTC
2019-07-03 01:35:05,879 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for BNB/BTC
2019-07-03 01:35:05,879 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for BTC/USDT
2019-07-03 01:35:05,879 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for OMG/BTC
2019-07-03 01:35:05,879 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for ONG/BTC
2019-07-03 01:35:05,880 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for PAX/BTC
2019-07-03 01:35:05,880 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for FTM/BTC
2019-07-03 01:35:06,863 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:35:11,869 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:35:16,868 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
```
`

What's the configuration you use for this? (mainly interrested in stake_currency)
Do other currencies you have in your account show up fine?

how exactly is the telegram output? (does it include `PAX: not showing <1$ amount`)?

Testing the below code returns all zeroes. 
Is this some kind of delisted coin? (sorry if that should be clear, but i have no idea about PAX).

```python
import ccxt
ct = ccxt.binance()
ct.fetch_ticker('PAX/BTC')
```

``` output
{'symbol': 'PAX/BTC',
 'timestamp': 1558080536929,
 'datetime': '2019-05-17T08:08:56.929Z',
 'high': 0.0,
 'low': 0.0,
 'bid': 0.0,
 'bidVolume': 0.0,
 'ask': 0.0,
 'askVolume': 0.0,
 'vwap': 0.0,
 'open': 0.0,
 'close': 0.0,
 'last': 0.0,
 'previousClose': 0.00025175,
 'change': 0.0,
 'percentage': 0.0,
 'average': None,
 'baseVolume': 0.0,
 'quoteVolume': 0.0,
 'info': {'symbol': 'PAXBTC',
  'priceChange': '0.00000000',
  'priceChangePercent': '0',
  'weightedAvgPrice': '0',
  'prevClosePrice': '0.00025175',
  'lastPrice': '0.00000000',
  'lastQty': '0.00000000',
  'bidPrice': '0.00000000',
  'bidQty': '0.00000000',
  'askPrice': '0.00000000',
  'askQty': '0.00000000',
  'openPrice': '0.00000000',
  'highPrice': '0.00000000',
  'lowPrice': '0.00000000',
  'volume': '0.00000000',
  'quoteVolume': '0.00000000',
  'openTime': 1557994136929,
  'closeTime': 1558080536929,
  'firstId': -1,
  'lastId': -1,
  'count': 0}}
```

Since this returns 0 (and not an exception which would be expected from a non-existing pair) we exclude the pair, since 1500 * 0 is 0.


Seems like the market was switched to be "BTC/PAX" (but the old combination is still returned as ticker).

Should be easy to fix - but i'll need to think of a way to get this working for all pairs, not just the ones we get issues for.
This is lacking quite some information.

What exchange are you using?
what version of ccxt?

Edit: did you get any message while starting the bot?
> This is lacking quite some information.
> 
> What exchange are you using?
> what version of ccxt?
> 
> Edit: did you get any message while starting the bot?

No, no specific message.
So what's the behaviour you observed? "does not detect" is very generic ... 
I also did not get the issue...
Basically when you click Balance it says I have PAX < 1, and is not included in the overall calculation of my balance.
This means that it does recognize that you have PAX in your account - however it's < 1$, which is excluded due to "binance dust", which has the potential to show a very large amount of coins with almost 0 balance.

The limit is 0.0001 BTC - which is ~0.91$ at this moment (according to google - but it'll fluctuate a lot ).
Even if you have this balance, it'll be below every limit you could use as stake-currency due to binance having min_notational / lotsize.
@xmatthias I'm aware, I was holding around 1500 PAX so that was not the case.
without the related logs i doubt we have a chance to recreate this problem (also, i don't currently hold PAX ...)
It's simply to re-create this issue, you simply buy PAX and query for balance, i can do one, give me a few minutes

I suspect that other stable pairs do give the same issues, so testing for TUSD, USDC and so on is also trivial as they should be worth 1$ USD

There's nothing on the logs 
@xmatthias 
````
2019-07-03 01:34:26,838 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:31,840 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:36,844 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:41,844 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:46,847 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:51,853 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:56,854 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:34:57,793 - freqtrade.rpc.telegram - INFO - Executing handler: _balance for chat_id: 146554112
2019-07-03 01:35:01,859 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:35:05,848 - freqtrade.rpc.telegram - INFO - Executing handler: _balance for chat_id: 146554112
2019-07-03 01:35:05,878 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for ETH/BTC
2019-07-03 01:35:05,879 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for BNB/BTC
2019-07-03 01:35:05,879 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for BTC/USDT
2019-07-03 01:35:05,879 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for OMG/BTC
2019-07-03 01:35:05,879 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for ONG/BTC
2019-07-03 01:35:05,880 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for PAX/BTC
2019-07-03 01:35:05,880 - freqtrade.exchange.exchange - INFO - returning cached ticker-data for FTM/BTC
2019-07-03 01:35:06,863 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:35:11,869 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
2019-07-03 01:35:16,868 - freqtrade.freqtradebot - INFO - Found no buy signals for whitelisted currencies. Trying again..
```
`

What's the configuration you use for this? (mainly interrested in stake_currency)
Do other currencies you have in your account show up fine?

how exactly is the telegram output? (does it include `PAX: not showing <1$ amount`)?

Testing the below code returns all zeroes. 
Is this some kind of delisted coin? (sorry if that should be clear, but i have no idea about PAX).

```python
import ccxt
ct = ccxt.binance()
ct.fetch_ticker('PAX/BTC')
```

``` output
{'symbol': 'PAX/BTC',
 'timestamp': 1558080536929,
 'datetime': '2019-05-17T08:08:56.929Z',
 'high': 0.0,
 'low': 0.0,
 'bid': 0.0,
 'bidVolume': 0.0,
 'ask': 0.0,
 'askVolume': 0.0,
 'vwap': 0.0,
 'open': 0.0,
 'close': 0.0,
 'last': 0.0,
 'previousClose': 0.00025175,
 'change': 0.0,
 'percentage': 0.0,
 'average': None,
 'baseVolume': 0.0,
 'quoteVolume': 0.0,
 'info': {'symbol': 'PAXBTC',
  'priceChange': '0.00000000',
  'priceChangePercent': '0',
  'weightedAvgPrice': '0',
  'prevClosePrice': '0.00025175',
  'lastPrice': '0.00000000',
  'lastQty': '0.00000000',
  'bidPrice': '0.00000000',
  'bidQty': '0.00000000',
  'askPrice': '0.00000000',
  'askQty': '0.00000000',
  'openPrice': '0.00000000',
  'highPrice': '0.00000000',
  'lowPrice': '0.00000000',
  'volume': '0.00000000',
  'quoteVolume': '0.00000000',
  'openTime': 1557994136929,
  'closeTime': 1558080536929,
  'firstId': -1,
  'lastId': -1,
  'count': 0}}
```

Since this returns 0 (and not an exception which would be expected from a non-existing pair) we exclude the pair, since 1500 * 0 is 0.


Seems like the market was switched to be "BTC/PAX" (but the old combination is still returned as ticker).

Should be easy to fix - but i'll need to think of a way to get this working for all pairs, not just the ones we get issues for.

Resolving patch:
diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py
--- a/freqtrade/exchange/exchange.py
+++ b/freqtrade/exchange/exchange.py
@@ -270,6 +270,15 @@ def validate_pairs(self, pairs: List[str]) -> None:
                     f'Pair {pair} is not available on {self.name}. '
                     f'Please remove {pair} from your whitelist.')
 
+    def get_valid_pair_combination(self, curr_1, curr_2) -> str:
+        """
+        Get valid pair combination of curr_1 and curr_2 by trying both combinations.
+        """
+        for pair in [f"{curr_1}/{curr_2}", f"{curr_2}/{curr_1}"]:
+            if pair in self.markets and self.markets[pair].get('active'):
+                return pair
+        raise DependencyException(f"Could not combine {curr_1} and {curr_2} to get a valid pair.")
+
     def validate_timeframes(self, timeframe: List[str]) -> None:
         """
         Checks if ticker interval from config is a supported timeframe on the exchange
@@ -501,7 +510,7 @@ def get_tickers(self) -> Dict:
     def get_ticker(self, pair: str, refresh: Optional[bool] = True) -> dict:
         if refresh or pair not in self._cached_ticker.keys():
             try:
-                if pair not in self._api.markets:
+                if pair not in self._api.markets or not self._api.markets[pair].get('active'):
                     raise DependencyException(f"Pair {pair} not available")
                 data = self._api.fetch_ticker(pair)
                 try:
diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py
--- a/freqtrade/rpc/rpc.py
+++ b/freqtrade/rpc/rpc.py
@@ -281,10 +281,11 @@ def _rpc_balance(self, fiat_display_currency: str) -> Dict:
                 rate = 1.0
             else:
                 try:
-                    if coin in('USDT', 'USD', 'EUR'):
-                        rate = 1.0 / self._freqtrade.get_sell_rate('BTC/' + coin, False)
+                    pair = self._freqtrade.exchange.get_valid_pair_combination(coin, "BTC")
+                    if pair.startswith("BTC"):
+                        rate = 1.0 / self._freqtrade.get_sell_rate(pair, False)
                     else:
-                        rate = self._freqtrade.get_sell_rate(coin + '/BTC', False)
+                        rate = self._freqtrade.get_sell_rate(pair, False)
                 except (TemporaryError, DependencyException):
                     logger.warning(f" Could not get rate for pair {coin}.")
                     continue


Test patch:
diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py
--- a/freqtrade/tests/exchange/test_exchange.py
+++ b/freqtrade/tests/exchange/test_exchange.py
@@ -910,7 +910,7 @@ def test_get_ticker(default_conf, mocker, exchange_name):
         'last': 0.0001,
     }
     api_mock.fetch_ticker = MagicMock(return_value=tick)
-    api_mock.markets = {'ETH/BTC': {}}
+    api_mock.markets = {'ETH/BTC': {'active': True}}
     exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
     # retrieve original ticker
     ticker = exchange.get_ticker(pair='ETH/BTC')
@@ -1455,10 +1455,11 @@ def test_stoploss_limit_order_dry_run(default_conf, mocker):
 
 
 def test_merge_ft_has_dict(default_conf, mocker):
-    mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=MagicMock()))
-    mocker.patch('freqtrade.exchange.Exchange._load_async_markets', MagicMock())
-    mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock())
-    mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
+    mocker.patch.multiple('freqtrade.exchange.Exchange',
+                          _init_ccxt=MagicMock(return_value=MagicMock()),
+                          _load_async_markets=MagicMock(),
+                          validate_pairs=MagicMock(),
+                          validate_timeframes=MagicMock())
     ex = Exchange(default_conf)
     assert ex._ft_has == Exchange._ft_has_default
 
@@ -1479,3 +1480,18 @@ def test_merge_ft_has_dict(default_conf, mocker):
     assert ex._ft_has != Exchange._ft_has_default
     assert not ex._ft_has['stoploss_on_exchange']
     assert ex._ft_has['DeadBeef'] == 20
+
+
+def test_get_valid_pair_combination(default_conf, mocker, markets):
+    mocker.patch.multiple('freqtrade.exchange.Exchange',
+                          _init_ccxt=MagicMock(return_value=MagicMock()),
+                          _load_async_markets=MagicMock(),
+                          validate_pairs=MagicMock(),
+                          validate_timeframes=MagicMock(),
+                          markets=PropertyMock(return_value=markets))
+    ex = Exchange(default_conf)
+
+    assert ex.get_valid_pair_combination("ETH", "BTC") == "ETH/BTC"
+    assert ex.get_valid_pair_combination("BTC", "ETH") == "ETH/BTC"
+    with pytest.raises(DependencyException, match=r"Could not combine.* to get a valid pair."):
+        ex.get_valid_pair_combination("NOPAIR", "ETH")
diff --git a/freqtrade/tests/rpc/test_rpc.py b/freqtrade/tests/rpc/test_rpc.py
--- a/freqtrade/tests/rpc/test_rpc.py
+++ b/freqtrade/tests/rpc/test_rpc.py
@@ -324,7 +324,7 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, fee, markets,
     assert prec_satoshi(stats['best_rate'], 6.2)
 
 
-def test_rpc_balance_handle(default_conf, mocker):
+def test_rpc_balance_handle_error(default_conf, mocker):
     mock_balance = {
         'BTC': {
             'free': 10.0,
@@ -371,6 +371,72 @@ def test_rpc_balance_handle(default_conf, mocker):
     assert result['total'] == 12.0
 
 
+def test_rpc_balance_handle(default_conf, mocker):
+    mock_balance = {
+        'BTC': {
+            'free': 10.0,
+            'total': 12.0,
+            'used': 2.0,
+        },
+        'ETH': {
+            'free': 1.0,
+            'total': 5.0,
+            'used': 4.0,
+        },
+        'PAX': {
+            'free': 5.0,
+            'total': 10.0,
+            'used': 5.0,
+        }
+    }
+
+    mocker.patch.multiple(
+        'freqtrade.rpc.fiat_convert.Market',
+        ticker=MagicMock(return_value={'price_usd': 15000.0}),
+    )
+    patch_exchange(mocker)
+    mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
+    mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
+    mocker.patch.multiple(
+        'freqtrade.exchange.Exchange',
+        get_balances=MagicMock(return_value=mock_balance),
+        get_ticker=MagicMock(
+            side_effect=lambda p, r: {'bid': 100} if p == "BTC/PAX" else {'bid': 0.01}),
+        get_valid_pair_combination=MagicMock(
+            side_effect=lambda a, b: f"{b}/{a}" if a == "PAX" else f"{a}/{b}")
+    )
+
+    freqtradebot = FreqtradeBot(default_conf)
+    patch_get_signal(freqtradebot, (True, False))
+    rpc = RPC(freqtradebot)
+    rpc._fiat_converter = CryptoToFiatConverter()
+
+    result = rpc._rpc_balance(default_conf['fiat_display_currency'])
+    assert prec_satoshi(result['total'], 12.15)
+    assert prec_satoshi(result['value'], 182250)
+    assert 'USD' == result['symbol']
+    assert result['currencies'] == [
+        {'currency': 'BTC',
+            'available': 10.0,
+            'balance': 12.0,
+            'pending': 2.0,
+            'est_btc': 12.0,
+         },
+        {'available': 1.0,
+         'balance': 5.0,
+         'currency': 'ETH',
+         'est_btc': 0.05,
+         'pending': 4.0
+         },
+        {'available': 5.0,
+         'balance': 10.0,
+         'currency': 'PAX',
+         'est_btc': 0.1,
+         'pending': 5.0}
+    ]
+    assert result['total'] == 12.15
+
+
 def test_rpc_start(mocker, default_conf) -> None:
     patch_exchange(mocker)
     mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
diff --git a/freqtrade/tests/rpc/test_rpc_apiserver.py b/freqtrade/tests/rpc/test_rpc_apiserver.py
--- a/freqtrade/tests/rpc/test_rpc_apiserver.py
+++ b/freqtrade/tests/rpc/test_rpc_apiserver.py
@@ -244,6 +244,8 @@ def mock_ticker(symbol, refresh):
         }
     mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value=rpc_balance)
     mocker.patch('freqtrade.exchange.Exchange.get_ticker', side_effect=mock_ticker)
+    mocker.patch('freqtrade.exchange.Exchange.get_valid_pair_combination',
+                 side_effect=lambda a, b: f"{a}/{b}")
 
     rc = client_get(client, f"{BASE_URI}/balance")
     assert_response(rc)
diff --git a/freqtrade/tests/rpc/test_rpc_telegram.py b/freqtrade/tests/rpc/test_rpc_telegram.py
--- a/freqtrade/tests/rpc/test_rpc_telegram.py
+++ b/freqtrade/tests/rpc/test_rpc_telegram.py
@@ -518,6 +518,8 @@ def mock_ticker(symbol, refresh):
 
     mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value=rpc_balance)
     mocker.patch('freqtrade.exchange.Exchange.get_ticker', side_effect=mock_ticker)
+    mocker.patch('freqtrade.exchange.Exchange.get_valid_pair_combination',
+                 side_effect=lambda a, b: f"{a}/{b}")
 
     msg_mock = MagicMock()
     mocker.patch.multiple(