From d23b3ccc5e8c01825a2e3c0fde77d6552495e731 Mon Sep 17 00:00:00 2001 From: creslinux Date: Fri, 27 Jul 2018 08:55:36 +0000 Subject: [PATCH 1/9] odd cut and paste error fixed. --- freqtrade/constants.py | 1 + freqtrade/exchange/__init__.py | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/freqtrade/constants.py b/freqtrade/constants.py index c27cd875c..ecaf158ec 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -124,6 +124,7 @@ CONF_SCHEMA = { 'type': 'object', 'properties': { 'name': {'type': 'string'}, + 'sandbox': {'type': 'boolean'}, 'key': {'type': 'string'}, 'secret': {'type': 'string'}, 'pair_whitelist': { diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 972ff49ca..35cf3d6d5 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -95,6 +95,11 @@ class Exchange(object): except (KeyError, AttributeError): raise OperationalException(f'Exchange {name} is not supported') + # check if config requests sanbox, if so use ['test'] from url + if (exchange_config.get('sandbox')): + api.urls['api'] = api.urls['test']; + # exchange.urls['api'] = exchange.urls['test']; + return api @property From 7efa81073a5dca5ffc89f469b2c4dcf774a433c4 Mon Sep 17 00:00:00 2001 From: creslinux Date: Fri, 27 Jul 2018 09:10:09 +0000 Subject: [PATCH 2/9] Removed ; at line end. --- freqtrade/exchange/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 35cf3d6d5..64ada5ef6 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -97,8 +97,7 @@ class Exchange(object): # check if config requests sanbox, if so use ['test'] from url if (exchange_config.get('sandbox')): - api.urls['api'] = api.urls['test']; - # exchange.urls['api'] = exchange.urls['test']; + api.urls['api'] = api.urls['test'] return api From b2b81c8b2dbb7db6cae0ccf28069c9ef633bd526 Mon Sep 17 00:00:00 2001 From: creslinux Date: Fri, 27 Jul 2018 20:18:12 +0000 Subject: [PATCH 3/9] Update documentation with hot to sandbox test. Allowing end-to-end GDAX API use without risking real money. --- README.md | 2 + docs/index.md | 1 + docs/sandbox-testing.md | 142 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 docs/sandbox-testing.md diff --git a/README.md b/README.md index c1705ff41..3d4c81580 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ hesitate to read the source code and understand the mechanism of this bot. - [Strategy Optimization](https://github.com/freqtrade/freqtrade/blob/develop/docs/bot-optimization.md) - [Backtesting](https://github.com/freqtrade/freqtrade/blob/develop/docs/backtesting.md) - [Hyperopt](https://github.com/freqtrade/freqtrade/blob/develop/docs/hyperopt.md) + - [Sandbox Testing](https://github.com/freqtrade/freqtrade/blob/develop/docs/sandbox-testing.md) - [Basic Usage](#basic-usage) - [Bot commands](#bot-commands) - [Telegram RPC commands](#telegram-rpc-commands) @@ -61,6 +62,7 @@ hesitate to read the source code and understand the mechanism of this bot. - [Requirements](#requirements) - [Min hardware required](#min-hardware-required) - [Software requirements](#software-requirements) + ## Quick start diff --git a/docs/index.md b/docs/index.md index f76bb125d..730f1095e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -33,3 +33,4 @@ Pull-request. Do not hesitate to reach us on - [Run tests & Check PEP8 compliance](https://github.com/freqtrade/freqtrade/blob/develop/CONTRIBUTING.md) - [FAQ](https://github.com/freqtrade/freqtrade/blob/develop/docs/faq.md) - [SQL cheatsheet](https://github.com/freqtrade/freqtrade/blob/develop/docs/sql_cheatsheet.md) +- [Sandbox Testing](https://github.com/freqtrade/freqtrade/blob/develop/docs/sandbox-testing.md)) diff --git a/docs/sandbox-testing.md b/docs/sandbox-testing.md new file mode 100644 index 000000000..57e40e623 --- /dev/null +++ b/docs/sandbox-testing.md @@ -0,0 +1,142 @@ +# Sandbox API testing +Where an exchange provides a sandbox for risk-free integration, or end-to-end, testing CCXT provides access to these. + +This document is a *light overview of configuring Freqtrade and GDAX sandbox. +This can be useful to developers and trader alike as Freqtrade is quite customisable. + +When testing your API connectivity, make sure to use the following URLs. +***Website** +https://public.sandbox.gdax.com +***REST API** +https://api-public.sandbox.gdax.com + +--- +# Configure a Sandbox account on Gdax +Aim of this document section +- An sanbox account +- create 2FA (needed to create an API) +- Add test 50BTC to account +- Create : +- - API-KEY +- - API-Secret +- - API Password + +## Acccount + +This link will redirect to the sandbox main page to login / create account dialogues: +https://public.sandbox.pro.coinbase.com/orders/ + +After registration and Email confimation you wil be redirected into your sanbox account. It is easy to verify youre in sandbox by checking the URL bar. +> https://public.sandbox.pro.coinbase.com/ + +## Enable 2Fa (a prerequisite to creating sandbox API Keys) +From within sand box site select your profile, top right. +>Or as a direct link: https://public.sandbox.pro.coinbase.com/profile + +From the menu panel to the left of the screen select +> Security: "*View or Update*" + +In the new site select "enable authenticator" as typical google auth. +- open Google Authenticator on your phone +- scan barcode +- enter your generated 2fa + +## Enable API Access +From within sandbox select profile>api>create api-keys +>or as a direct link: https://public.sandbox.pro.coinbase.com/profile/api + +Ensure **view** and **trade** are "checked" and sumbit your 2Fa +- COPY AND PASTE THE PASSPHRASE into a notepade this will be needed later +- COPY AND PASTE THE API SECRET popup into a notepad this will needed later +- COPY AND PASTE THE API KEY into a notepad this will needed later + +## Add 50 BTC test funds +To add funds, use the web interface deposit and withdraw buttons. +Select Wallets. +> Or as a direct link: https://public.sandbox.pro.coinbase.com/wallets + +- Deposits (bottom left of screen) +- - Deposit Funds Bitcoin +- - - Coinbase BTC Wallet +- - - - MAx (50 BTC) +- - - - - Deposit + +--- +# Configure Freqtrade to use Gax Sandbox + +The aim of this document section + - enable sandbox URLs in Freqtrade + - Configure API + - - secret + - - key + - - passphrase + +## Sandbox URLs +Freqtrade makes use of CCXT which in turn provides a list of URLs to Freqtrade. +These incldue ['test'] and ['api']. +- [Test] if available will point to an Exchanges sandbox. +- [Api] normally used, and resolves to live API target on the exchange + +To make use of sandbox / test add "sandbox": true, to your config.json +``` + "exchange": { + "name": "gdax", + "sandbox": true, + "key": "5wowfxemogxeowo;heiohgmd", + "secret": "/ZMH1P62rCVmwefewrgcewX8nh4gob+lywxfwfxwwfxwfNsH1ySgvWCUR/w==", + "password": "1bkjfkhfhfu6sr", + "pair_whitelist": [ + "BTC/USD" +``` +Also insert your +- api-key (noted earlier) +- api-secret (noted earlier) +- password (the passphrase - noted earlier) + +--- +## You should now be ready to test your sandbox! +Ensure Freqtrade logs show the sandbox URL, and trades made are shown in sandbox. +** Typically the BTC/USD has the most activity in sandbox to test against. + +## GDAX - Old Candles problem +It is my experience that GDAX sandbox candles may be 20+- minutes out of date. This can cause trades to fail as one of Freqtrades safety checks + +To disable this check, edit: +>strategy/interface.py +Look for the following section: +``` + # Check if dataframe is out of date + signal_date = arrow.get(latest['date']) + interval_minutes = constants.TICKER_INTERVAL_MINUTES[interval] + if signal_date < (arrow.utcnow().shift(minutes=-(interval_minutes * 2 + 5))): + logger.warning( + 'Outdated history for pair %s. Last tick is %s minutes old', + pair, + (arrow.utcnow() - signal_date).seconds // 60 + ) + return False, False +``` + +And Hash out as follows: +``` + # # Check if dataframe is out of date + # signal_date = arrow.get(latest['date']) + # interval_minutes = constants.TICKER_INTERVAL_MINUTES[interval] + # if signal_date < (arrow.utcnow().shift(minutes=-(interval_minutes * 2 + 5))): + # logger.warning( + # 'Outdated history for pair %s. Last tick is %s minutes old', + # pair, + # (arrow.utcnow() - signal_date).seconds // 60 + # ) + # return False, False + ``` + + + + + + + + + + From 8648ac9da23176f7075c0ecedf084cbca830efba Mon Sep 17 00:00:00 2001 From: creslinux Date: Sat, 28 Jul 2018 17:42:56 +0000 Subject: [PATCH 4/9] Update documentation with hot to sandbox test. Allowing end-to-end GDAX API use without risking real money. --- docs/sandbox-testing.md | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/docs/sandbox-testing.md b/docs/sandbox-testing.md index 57e40e623..86bb30799 100644 --- a/docs/sandbox-testing.md +++ b/docs/sandbox-testing.md @@ -26,7 +26,7 @@ Aim of this document section This link will redirect to the sandbox main page to login / create account dialogues: https://public.sandbox.pro.coinbase.com/orders/ -After registration and Email confimation you wil be redirected into your sanbox account. It is easy to verify youre in sandbox by checking the URL bar. +After registration and Email confimation you wil be redirected into your sanbox account. It is easy to verify you're in sandbox by checking the URL bar. > https://public.sandbox.pro.coinbase.com/ ## Enable 2Fa (a prerequisite to creating sandbox API Keys) @@ -46,9 +46,9 @@ From within sandbox select profile>api>create api-keys >or as a direct link: https://public.sandbox.pro.coinbase.com/profile/api Ensure **view** and **trade** are "checked" and sumbit your 2Fa -- COPY AND PASTE THE PASSPHRASE into a notepade this will be needed later -- COPY AND PASTE THE API SECRET popup into a notepad this will needed later -- COPY AND PASTE THE API KEY into a notepad this will needed later +- **Copy and paste the Passphase** into a notepade this will be needed later +- **Copy and paste the API Secret** popup into a notepad this will needed later +- **Copy and paste the API Key** into a notepad this will needed later ## Add 50 BTC test funds To add funds, use the web interface deposit and withdraw buttons. @@ -58,7 +58,7 @@ Select Wallets. - Deposits (bottom left of screen) - - Deposit Funds Bitcoin - - - Coinbase BTC Wallet -- - - - MAx (50 BTC) +- - - - Max (50 BTC) - - - - - Deposit --- @@ -130,13 +130,4 @@ And Hash out as follows: # ) # return False, False ``` - - - - - - - - - - + \ No newline at end of file From 0a059662b3c46994f25fb2689bdd1926aaa72ec5 Mon Sep 17 00:00:00 2001 From: creslinux Date: Sat, 28 Jul 2018 20:32:10 +0000 Subject: [PATCH 5/9] Submitting with unit test for the working scenario. Strongly recommend core team check the unit test is even targetting the correct code in exchange/__init__.py I have a real knowledge gap on mocker, in so far as how tests map to what they're targeting. --- freqtrade/exchange/__init__.py | 12 ++++++--- freqtrade/tests/exchange/test_exchange.py | 30 +++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 64ada5ef6..670d9d3a5 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -95,9 +95,7 @@ class Exchange(object): except (KeyError, AttributeError): raise OperationalException(f'Exchange {name} is not supported') - # check if config requests sanbox, if so use ['test'] from url - if (exchange_config.get('sandbox')): - api.urls['api'] = api.urls['test'] + self.set_sandbox(api, exchange_config, name) return api @@ -111,6 +109,14 @@ class Exchange(object): """exchange ccxt id""" return self._api.id + def set_sandbox(self, api, exchange_config: dict, name: str): + if exchange_config.get('sandbox'): + if api.urls.get('test'): + api.urls['api'] = api.urls['test'] + else: + logger.warning(self, "No Sandbox URL in CCXT, exiting. Please check your config.json") + raise OperationalException(f'Exchange {name} does not provide a sandbox api') + def validate_pairs(self, pairs: List[str]) -> None: """ Checks if all given pairs are tradable on the current exchange. diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py index 282d8ef01..1a0287857 100644 --- a/freqtrade/tests/exchange/test_exchange.py +++ b/freqtrade/tests/exchange/test_exchange.py @@ -51,6 +51,36 @@ def test_init_exception(default_conf, mocker): mocker.patch("ccxt.binance", MagicMock(side_effect=AttributeError)) Exchange(default_conf) +def test_set_sandbox(default_conf, mocker): + """ + Test working scenario + """ + api_mock = MagicMock() + api_mock.load_markets = MagicMock(return_value={ + 'ETH/BTC': '', 'LTC/BTC': '', 'XRP/BTC': '', 'NEO/BTC': '' + }) + url_mock = PropertyMock(return_value={'test': "api-public.sandbox.gdax.com", 'api': 'https://api.gdax.com'}) + type(api_mock).urls = url_mock + mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) + mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock()) + Exchange(default_conf) + +# def test_set_sandbox_exception(default_conf, mocker): +# """ +# Test Fail scenario +# """ +# api_mock = MagicMock() +# api_mock.load_markets = MagicMock(return_value={ +# 'ETH/BTC': '', 'LTC/BTC': '', 'XRP/BTC': '', 'NEO/BTC': '' +# }) +# url_mock = PropertyMock(return_value={'api': 'https://api.gdax.com'}) +# type(api_mock).urls = url_mock +# +# mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) +# mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock()) +# +# with pytest.raises(OperationalException, match=r'does not provide a sandbox api'): +# Exchange(default_conf) def test_validate_pairs(default_conf, mocker): api_mock = MagicMock() From fc06d028b8b857368f202495dbf18f44d8945eac Mon Sep 17 00:00:00 2001 From: creslinux Date: Sun, 29 Jul 2018 08:02:04 +0000 Subject: [PATCH 6/9] Unit tests for sandbox pass / fail scenarios Big Wave of appreciation to xmatthias for the guidence on how Mocker works --- freqtrade/tests/exchange/test_exchange.py | 43 ++++++++++++++--------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py index 1a0287857..862229bea 100644 --- a/freqtrade/tests/exchange/test_exchange.py +++ b/freqtrade/tests/exchange/test_exchange.py @@ -63,24 +63,33 @@ def test_set_sandbox(default_conf, mocker): type(api_mock).urls = url_mock mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock()) - Exchange(default_conf) -# def test_set_sandbox_exception(default_conf, mocker): -# """ -# Test Fail scenario -# """ -# api_mock = MagicMock() -# api_mock.load_markets = MagicMock(return_value={ -# 'ETH/BTC': '', 'LTC/BTC': '', 'XRP/BTC': '', 'NEO/BTC': '' -# }) -# url_mock = PropertyMock(return_value={'api': 'https://api.gdax.com'}) -# type(api_mock).urls = url_mock -# -# mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) -# mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock()) -# -# with pytest.raises(OperationalException, match=r'does not provide a sandbox api'): -# Exchange(default_conf) + exchange = Exchange(default_conf) + liveurl = exchange._api.urls['api'] + default_conf['exchange']['sandbox'] = True + exchange.set_sandbox(exchange._api, default_conf['exchange'], 'Logname') + assert exchange._api.urls['api'] != liveurl + +def test_set_sandbox_exception(default_conf, mocker): + """ + Test Fail scenario + """ + api_mock = MagicMock() + api_mock.load_markets = MagicMock(return_value={ + 'ETH/BTC': '', 'LTC/BTC': '', 'XRP/BTC': '', 'NEO/BTC': '' + }) + url_mock = PropertyMock(return_value={'api': 'https://api.gdax.com'}) + type(api_mock).urls = url_mock + + mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) + mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock()) + + with pytest.raises(OperationalException, match=r'does not provide a sandbox api'): + exchange = Exchange(default_conf) + default_conf['exchange']['sandbox'] = True + exchange.set_sandbox(exchange._api, default_conf['exchange'], 'Logname') + assert exchange._api.urls.get('test') == False + def test_validate_pairs(default_conf, mocker): api_mock = MagicMock() From 1e804c0df582589ed6e500d7a1b6a172a60e6ed4 Mon Sep 17 00:00:00 2001 From: creslinux Date: Sun, 29 Jul 2018 08:10:55 +0000 Subject: [PATCH 7/9] flake 8 --- freqtrade/exchange/__init__.py | 3 ++- freqtrade/tests/exchange/test_exchange.py | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 670d9d3a5..139b1c667 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -114,7 +114,8 @@ class Exchange(object): if api.urls.get('test'): api.urls['api'] = api.urls['test'] else: - logger.warning(self, "No Sandbox URL in CCXT, exiting. Please check your config.json") + logger.warning(self, "No Sandbox URL in CCXT, exiting. " + "Please check your config.json") raise OperationalException(f'Exchange {name} does not provide a sandbox api') def validate_pairs(self, pairs: List[str]) -> None: diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py index 862229bea..2c58d928c 100644 --- a/freqtrade/tests/exchange/test_exchange.py +++ b/freqtrade/tests/exchange/test_exchange.py @@ -51,6 +51,7 @@ def test_init_exception(default_conf, mocker): mocker.patch("ccxt.binance", MagicMock(side_effect=AttributeError)) Exchange(default_conf) + def test_set_sandbox(default_conf, mocker): """ Test working scenario @@ -59,7 +60,8 @@ def test_set_sandbox(default_conf, mocker): api_mock.load_markets = MagicMock(return_value={ 'ETH/BTC': '', 'LTC/BTC': '', 'XRP/BTC': '', 'NEO/BTC': '' }) - url_mock = PropertyMock(return_value={'test': "api-public.sandbox.gdax.com", 'api': 'https://api.gdax.com'}) + url_mock = PropertyMock(return_value={'test': "api-public.sandbox.gdax.com", + 'api': 'https://api.gdax.com'}) type(api_mock).urls = url_mock mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock()) @@ -70,6 +72,7 @@ def test_set_sandbox(default_conf, mocker): exchange.set_sandbox(exchange._api, default_conf['exchange'], 'Logname') assert exchange._api.urls['api'] != liveurl + def test_set_sandbox_exception(default_conf, mocker): """ Test Fail scenario @@ -88,7 +91,6 @@ def test_set_sandbox_exception(default_conf, mocker): exchange = Exchange(default_conf) default_conf['exchange']['sandbox'] = True exchange.set_sandbox(exchange._api, default_conf['exchange'], 'Logname') - assert exchange._api.urls.get('test') == False def test_validate_pairs(default_conf, mocker): From c85c7a3a77a9cbf60b89ed8c2c2e18511c9d23af Mon Sep 17 00:00:00 2001 From: creslinux Date: Sun, 29 Jul 2018 09:12:05 +0000 Subject: [PATCH 8/9] Documentation fixes. --- docs/sandbox-testing.md | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/docs/sandbox-testing.md b/docs/sandbox-testing.md index 86bb30799..572fbccef 100644 --- a/docs/sandbox-testing.md +++ b/docs/sandbox-testing.md @@ -36,7 +36,7 @@ From within sand box site select your profile, top right. From the menu panel to the left of the screen select > Security: "*View or Update*" -In the new site select "enable authenticator" as typical google auth. +In the new site select "enable authenticator" as typical google Authenticator. - open Google Authenticator on your phone - scan barcode - enter your generated 2fa @@ -45,14 +45,16 @@ In the new site select "enable authenticator" as typical google auth. From within sandbox select profile>api>create api-keys >or as a direct link: https://public.sandbox.pro.coinbase.com/profile/api -Ensure **view** and **trade** are "checked" and sumbit your 2Fa +Click on "create one" and ensure **view** and **trade** are "checked" and sumbit your 2Fa - **Copy and paste the Passphase** into a notepade this will be needed later - **Copy and paste the API Secret** popup into a notepad this will needed later - **Copy and paste the API Key** into a notepad this will needed later ## Add 50 BTC test funds To add funds, use the web interface deposit and withdraw buttons. -Select Wallets. + + +To begin select 'Wallets' from the top menu. > Or as a direct link: https://public.sandbox.pro.coinbase.com/wallets - Deposits (bottom left of screen) @@ -61,11 +63,12 @@ Select Wallets. - - - - Max (50 BTC) - - - - - Deposit +*This process may be repeated for other currencies, ETH as example* --- # Configure Freqtrade to use Gax Sandbox The aim of this document section - - enable sandbox URLs in Freqtrade + - Enable sandbox URLs in Freqtrade - Configure API - - secret - - key @@ -73,9 +76,9 @@ The aim of this document section ## Sandbox URLs Freqtrade makes use of CCXT which in turn provides a list of URLs to Freqtrade. -These incldue ['test'] and ['api']. -- [Test] if available will point to an Exchanges sandbox. -- [Api] normally used, and resolves to live API target on the exchange +These include `['test']` and `['api']`. +- `[Test]` if available will point to an Exchanges sandbox. +- `[Api]` normally used, and resolves to live API target on the exchange To make use of sandbox / test add "sandbox": true, to your config.json ``` @@ -117,7 +120,7 @@ Look for the following section: return False, False ``` -And Hash out as follows: +You could Hash out the entire check as follows: ``` # # Check if dataframe is out of date # signal_date = arrow.get(latest['date']) @@ -130,4 +133,19 @@ And Hash out as follows: # ) # return False, False ``` - \ No newline at end of file + + Or inrease the timeout to offer a level of protection/alignment of this test to freqtrade in live. + + As example, to allow an additional 30 minutes. "(interval_minutes * 2 + 5 + 30)" + ``` + # Check if dataframe is out of date + signal_date = arrow.get(latest['date']) + interval_minutes = constants.TICKER_INTERVAL_MINUTES[interval] + if signal_date < (arrow.utcnow().shift(minutes=-(interval_minutes * 2 + 5 + 30))): + logger.warning( + 'Outdated history for pair %s. Last tick is %s minutes old', + pair, + (arrow.utcnow() - signal_date).seconds // 60 + ) + return False, False +``` \ No newline at end of file From dd71071740bb6017fce4dad3bd94403d92564b24 Mon Sep 17 00:00:00 2001 From: creslinux Date: Sun, 29 Jul 2018 09:15:13 +0000 Subject: [PATCH 9/9] Added logger.info when Sandbox is enabled. --- freqtrade/exchange/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 139b1c667..c57986658 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -113,6 +113,7 @@ class Exchange(object): if exchange_config.get('sandbox'): if api.urls.get('test'): api.urls['api'] = api.urls['test'] + logger.info("Enabled Sandbox API on %s", name) else: logger.warning(self, "No Sandbox URL in CCXT, exiting. " "Please check your config.json")