Repository: freqtrade/freqtrade

Issue:
NO_API_RESPONSE 

Hi I am getting the following error after running the bot for 20 mins. I can't seem to figure out the issue
`
Traceback (most recent call last):
  File "/freqtrade/freqtrade/main.py", line 63, in _process
    gen_pair_whitelist(_CONF['stake_currency']) if dynamic_whitelist else None
  File "/freqtrade/freqtrade/main.py", line 35, in refresh_whitelist
    health = exchange.get_wallet_health()
  File "/freqtrade/freqtrade/exchange/__init__.py", line 185, in get_wallet_health
    return _API.get_wallet_health()
  File "/freqtrade/freqtrade/exchange/bittrex.py", line 174, in get_wallet_health
    raise OperationalException('{message}'.format(message=data['message']))
freqtrade.OperationalException: NO_API_RESPONSE
```Issue `/start` if you think it is safe to restart.
2017-12-04 09:38:19,290 - freqtrade - ERROR - Got OperationalException. Stopping trader ...
Traceback (most recent call last):
  File "/freqtrade/freqtrade/main.py", line 63, in _process
    gen_pair_whitelist(_CONF['stake_currency']) if dynamic_whitelist else None
  File "/freqtrade/freqtrade/main.py", line 35, in refresh_whitelist
    health = exchange.get_wallet_health()
  File "/freqtrade/freqtrade/exchange/__init__.py", line 185, in get_wallet_health
    return _API.get_wallet_health()
  File "/freqtrade/freqtrade/exchange/bittrex.py", line 174, in get_wallet_health
    raise OperationalException('{message}'.format(message=data['message']))
freqtrade.OperationalException: NO_API_RESPONSE
2017-12-04 09:38:19,292 - freqtrade.rpc - INFO - *Status:* `stopped`
2017-12-04 09:38:19,496 - freqtrade - INFO - Changing state to: STOPPED
`


Discussion:
This one should not be a fatal error I think.
This error has been causing the bot to stop allot of times. I myself had to start the bot again like 6-8x a day
Yeah, it was getting really annoying so did a bit of hack by making a bash script: run_prog.sh
and ran it in the background and didn't experience any interruptions so far. Probably not the best way but so far its running smoothly. Give this a try and see if it work:
 
`nohup bash run_prog.sh &`
run_prog.sh:
``` 
#!/bin/bash
# A script to ensure docker container is running
while true;
do
        now=$(date +"%T")
        echo "Automated script to keep docker running"
        echo "Current time: $now"
        docker start freqtrade
        sleep 900;
done                                                                                                                                 `
Can this bash script be used for python?
https://stackoverflow.com/questions/13745648/running-bash-script-from-within-python
Thanks @ala273
Running this app from bash has some pitfalls, such as being unable to restart the process. I have been testing freqtrade in dry_run and I run into this error myself. 

Obviously freqtrade was built with some safety in mind, but if you want to remove this safety, comment out this last line in the _process() function in main.py


    except OperationalException:
        rpc.send_msg('*Status:* Got OperationalException:\n```\n{traceback}```{hint}'.format(
            traceback=traceback.format_exc(),
            hint='Issue `/start` if you think it is safe to restart.'
        ))
        logger.exception('Got OperationalException. Stopping trader ...')
        #update_state(State.STOPPED) #comment out this line to prevent freqtrade from stopping on OperationalException


I do not recommend this change as god forbid your trading gets bonked but for dry_run purposes I think it's OK.
No Answer when getting a pair ticker or the wallet should be handled in my opinion without stopping the bot I think, it is really boring to have the bot stop 3/4 times a day. I’m going to look at how to handle this gracefully and will issue a PR

Resolving patch:
diff --git a/freqtrade/exchange/bittrex.py b/freqtrade/exchange/bittrex.py
--- a/freqtrade/exchange/bittrex.py
+++ b/freqtrade/exchange/bittrex.py
@@ -39,6 +39,15 @@ def __init__(self, config: dict) -> None:
             api_version=API_V2_0,
         )
 
+    @staticmethod
+    def _validate_response(response) -> None:
+        """
+        Validates the given bittrex response
+        and raises a ContentDecodingError if a non-fatal issue happened.
+        """
+        if response['message'] == 'NO_API_RESPONSE':
+            raise ContentDecodingError('Unable to decode bittrex response')
+
     @property
     def fee(self) -> float:
         # See https://bittrex.com/fees
@@ -47,6 +56,7 @@ def fee(self) -> float:
     def buy(self, pair: str, rate: float, amount: float) -> str:
         data = _API.buy_limit(pair.replace('_', '-'), amount, rate)
         if not data['success']:
+            Bittrex._validate_response(data)
             raise OperationalException('{message} params=({pair}, {rate}, {amount})'.format(
                 message=data['message'],
                 pair=pair,
@@ -57,6 +67,7 @@ def buy(self, pair: str, rate: float, amount: float) -> str:
     def sell(self, pair: str, rate: float, amount: float) -> str:
         data = _API.sell_limit(pair.replace('_', '-'), amount, rate)
         if not data['success']:
+            Bittrex._validate_response(data)
             raise OperationalException('{message} params=({pair}, {rate}, {amount})'.format(
                 message=data['message'],
                 pair=pair,
@@ -67,6 +78,7 @@ def sell(self, pair: str, rate: float, amount: float) -> str:
     def get_balance(self, currency: str) -> float:
         data = _API.get_balance(currency)
         if not data['success']:
+            Bittrex._validate_response(data)
             raise OperationalException('{message} params=({currency})'.format(
                 message=data['message'],
                 currency=currency))
@@ -75,12 +87,14 @@ def get_balance(self, currency: str) -> float:
     def get_balances(self):
         data = _API.get_balances()
         if not data['success']:
+            Bittrex._validate_response(data)
             raise OperationalException('{message}'.format(message=data['message']))
         return data['result']
 
     def get_ticker(self, pair: str) -> dict:
         data = _API.get_ticker(pair.replace('_', '-'))
         if not data['success']:
+            Bittrex._validate_response(data)
             raise OperationalException('{message} params=({pair})'.format(
                 message=data['message'],
                 pair=pair))
@@ -122,6 +136,7 @@ def get_ticker_history(self, pair: str, tick_interval: int) -> List[Dict]:
                         pair=pair))
 
         if not data['success']:
+            Bittrex._validate_response(data)
             raise OperationalException('{message} params=({pair})'.format(
                 message=data['message'],
                 pair=pair))
@@ -131,6 +146,7 @@ def get_ticker_history(self, pair: str, tick_interval: int) -> List[Dict]:
     def get_order(self, order_id: str) -> Dict:
         data = _API.get_order(order_id)
         if not data['success']:
+            Bittrex._validate_response(data)
             raise OperationalException('{message} params=({order_id})'.format(
                 message=data['message'],
                 order_id=order_id))
@@ -149,6 +165,7 @@ def get_order(self, order_id: str) -> Dict:
     def cancel_order(self, order_id: str) -> None:
         data = _API.cancel(order_id)
         if not data['success']:
+            Bittrex._validate_response(data)
             raise OperationalException('{message} params=({order_id})'.format(
                 message=data['message'],
                 order_id=order_id))
@@ -159,18 +176,21 @@ def get_pair_detail_url(self, pair: str) -> str:
     def get_markets(self) -> List[str]:
         data = _API.get_markets()
         if not data['success']:
+            Bittrex._validate_response(data)
             raise OperationalException('{message}'.format(message=data['message']))
         return [m['MarketName'].replace('-', '_') for m in data['result']]
 
     def get_market_summaries(self) -> List[Dict]:
         data = _API.get_market_summaries()
         if not data['success']:
+            Bittrex._validate_response(data)
             raise OperationalException('{message}'.format(message=data['message']))
         return data['result']
 
     def get_wallet_health(self) -> List[Dict]:
         data = _API_V2.get_wallet_health()
         if not data['success']:
+            Bittrex._validate_response(data)
             raise OperationalException('{message}'.format(message=data['message']))
         return [{
             'Currency': entry['Health']['Currency'],


Test patch: