From 60a7f8614c003cae8fb9ba1fe99f1ce377997b24 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 10 Oct 2017 19:04:05 +0300 Subject: [PATCH 01/31] upgrade dependencies --- requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index b7bf943ad..be3a292f0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ -e git+https://github.com/ericsomdahl/python-bittrex.git@d7033d0#egg=python-bittrex -SQLAlchemy==1.1.13 +SQLAlchemy==1.1.14 python-telegram-bot==8.0 arrow==0.10.0 requests==2.18.4 @@ -11,10 +11,10 @@ scipy==0.19.1 jsonschema==2.6.0 numpy==1.13.3 TA-Lib==0.4.10 -pytest==3.2.2 +pytest==3.2.3 pytest-mock==1.6.3 pytest-cov==2.5.1 # Required for plotting data -#matplotlib==2.0.2 +#matplotlib==2.1.0 #PYQT5==5.9 \ No newline at end of file From 0c8c149b86c2097c0e1889ab86a86c2b6c8889ce Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Wed, 11 Oct 2017 13:09:57 +0300 Subject: [PATCH 02/31] Fix the command for running backtesting in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d9eb017ff..5779d983a 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ $ pytest This will by default skip the slow running backtest set. To run backtest set: ``` -$ BACKTEST=true pytest +$ BACKTEST=true pytest -s freqtrade/tests/test_backtesting.py ``` #### Docker From d76476040a016de39259561d852e38844586137b Mon Sep 17 00:00:00 2001 From: xsmile Date: Wed, 11 Oct 2017 19:51:37 +0200 Subject: [PATCH 03/31] Bittrex provider remove redundant 'name' property and pair validation call --- freqtrade/exchange/bittrex.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/freqtrade/exchange/bittrex.py b/freqtrade/exchange/bittrex.py index d2fd08ddc..cb85aaf87 100644 --- a/freqtrade/exchange/bittrex.py +++ b/freqtrade/exchange/bittrex.py @@ -26,10 +26,6 @@ class Bittrex(Exchange): # Sleep time to avoid rate limits, used in the main loop SLEEP_TIME: float = 25 - @property - def name(self) -> str: - return self.__class__.__name__ - @property def sleep_time(self) -> float: return self.SLEEP_TIME @@ -40,13 +36,6 @@ class Bittrex(Exchange): _EXCHANGE_CONF.update(config) _API = _Bittrex(api_key=_EXCHANGE_CONF['key'], api_secret=_EXCHANGE_CONF['secret']) - # Check if all pairs are available - markets = self.get_markets() - exchange_name = self.name - for pair in _EXCHANGE_CONF['pair_whitelist']: - if pair not in markets: - raise RuntimeError('Pair {} is not available at {}'.format(pair, exchange_name)) - def buy(self, pair: str, rate: float, amount: float) -> str: data = _API.buy_limit(pair.replace('_', '-'), amount, rate) if not data['success']: From eecc45f8ba8baae71fc4902a09d221dd40b22102 Mon Sep 17 00:00:00 2001 From: xsmile Date: Wed, 11 Oct 2017 20:04:31 +0200 Subject: [PATCH 04/31] set exchange in analyze.__main__ to fix plotting requires #64 --- freqtrade/analyze.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index 159e1d137..f4f6d0077 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -6,7 +6,8 @@ import arrow import talib.abstract as ta from pandas import DataFrame -from freqtrade.exchange import get_ticker_history +from freqtrade import exchange +from freqtrade.exchange import Bittrex, get_ticker_history logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') @@ -143,6 +144,7 @@ def plot_dataframe(dataframe: DataFrame, pair: str) -> None: if __name__ == '__main__': # Install PYQT5==5.9 manually if you want to test this helper function while True: + exchange.EXCHANGE = Bittrex({'key': '', 'secret': ''}) test_pair = 'BTC_ETH' # for pair in ['BTC_ANT', 'BTC_ETH', 'BTC_GNT', 'BTC_ETC']: # get_buy_signal(pair) From d266171ed8645829bbbeb29f7cdb18340670d267 Mon Sep 17 00:00:00 2001 From: Roland Venesz Date: Fri, 13 Oct 2017 15:47:13 +0200 Subject: [PATCH 05/31] Docker improvements (faster and more secure builds) --- .dockerignore | 6 ++++++ Dockerfile | 21 ++++++++++++--------- README.md | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..9f4726bfb --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +.git +.gitignore +Dockerfile +.dockerignore +config.json* +*.sqlite diff --git a/Dockerfile b/Dockerfile index bd303769d..75929a5e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,20 +1,23 @@ -FROM python:3.6.2 - -RUN apt-get update -RUN apt-get -y install build-essential +FROM python:3.6.2 # Install TA-lib -RUN wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz -RUN tar zxvf ta-lib-0.4.0-src.tar.gz -RUN cd ta-lib && ./configure && make && make install +RUN apt-get update && apt-get -y install build-essential && apt-get clean +RUN curl -L http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz | \ + tar xzvf - && \ + cd ta-lib && \ + ./configure && make && make install && \ + cd .. && rm -rf ta-lib ENV LD_LIBRARY_PATH /usr/local/lib # Prepare environment RUN mkdir /freqtrade -COPY . /freqtrade/ WORKDIR /freqtrade -# Install dependencies and execute +# Install dependencies +COPY requirements.txt /freqtrade/ RUN pip install -r requirements.txt + +# Install and execute +COPY . /freqtrade/ RUN pip install -e . CMD ["freqtrade"] diff --git a/README.md b/README.md index d9eb017ff..81c63ba75 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ See the example below: }, ``` -`stoploss` is loss in percentage that should trigger a sale. +`stoploss` is loss in percentage that should trigger a sale. For example value `-0.10` will cause immediate sell if the profit dips below -10% for a given trade. This parameter is optional. @@ -47,7 +47,9 @@ Possible values are `running` or `stopped`. (default=`running`) If the value is `stopped` the bot has to be started with `/start` first. `ask_last_balance` sets the bidding price. Value `0.0` will use `ask` price, `1.0` will -use the `last` price and values between those interpolate between ask and last price. Using `ask` price will guarantee quick success in bid, but bot will also end up paying more then would probably have been necessary. +use the `last` price and values between those interpolate between ask and last +price. Using `ask` price will guarantee quick success in bid, but bot will also +end up paying more then would probably have been necessary. The other values should be self-explanatory, if not feel free to raise a github issue. @@ -88,12 +90,52 @@ $ BACKTEST=true pytest ``` #### Docker + +Building the image: + ``` $ cd freqtrade $ docker build -t freqtrade . -$ docker run --rm -it freqtrade ``` +For security reasons, your configuration file will not be included in the +image, you will need to bind mount it. It is also advised to bind mount +a SQLite database file (see second example) to keep it between updates. + +You can run a one-off container that is immediately deleted upon exiting with +the following command (config.json must be in the current working directory): + +``` +$ docker run --rm -v `pwd`/config.json:/freqtrade/config.json -it freqtrade +``` + +To run a restartable instance in the background (feel free to place your +configuration and database files wherever it feels comfortable on your +filesystem): + +``` +$ cd ~/.freq +$ touch tradesv2.sqlite +$ docker run -d \ + --name freqtrade \ + -v ~/.freq/config.json:/freqtrade/config.json \ + -v ~/.freq/tradesv2.sqlite:/freqtrade/tradesv2.sqlite \ + freqtrade +``` + +You can then use the following commands to monitor and manage your container: + +``` +$ docker logs freqtrade +$ docker logs -f freqtrade +$ docker restart freqtrade +$ docker stop freqtrade +$ docker start freqtrade +``` + +With the above setup you do not need to rebuild the image for configuration +changes, it will suffice to edit `config.json` and restart the container. + #### Contributing Feel like our bot is missing a feature? We welcome your pull requests! Few pointers for contributions: From 37f6c213f619717dfe2a05f4abe5d92f2bbd9f31 Mon Sep 17 00:00:00 2001 From: dertione Date: Fri, 13 Oct 2017 15:50:50 +0200 Subject: [PATCH 06/31] fork test --- freqtrade/tests/testdata/download_backtest_data.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 freqtrade/tests/testdata/download_backtest_data.py diff --git a/freqtrade/tests/testdata/download_backtest_data.py b/freqtrade/tests/testdata/download_backtest_data.py new file mode 100644 index 000000000..463087588 --- /dev/null +++ b/freqtrade/tests/testdata/download_backtest_data.py @@ -0,0 +1,13 @@ +#!/usr/bin/python3.6 + +from urllib.request import urlopen + +currencies = ["ok","neo","dash","etc","eth","snt"] + +for cur in currencies: + url = 'https://bittrex.com/Api/v2.0/pub/market/GetTicks?marketName=BTC-'+cur+'&tickInterval=fiveMin' + x = urlopen(url) + data = x.read() + str2 = str(data,'utf-8') + with open("btc-"+cur+".json", "w") as fichier: + fichier.write(str2) From afd1a0bf9b2d8bce712018c09bdfd230aea2bf6d Mon Sep 17 00:00:00 2001 From: dertione Date: Sat, 14 Oct 2017 14:40:26 +0200 Subject: [PATCH 07/31] update for pylint --- .../tests/testdata/download_backtest_data.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/freqtrade/tests/testdata/download_backtest_data.py b/freqtrade/tests/testdata/download_backtest_data.py index 463087588..6aef5f9f0 100644 --- a/freqtrade/tests/testdata/download_backtest_data.py +++ b/freqtrade/tests/testdata/download_backtest_data.py @@ -1,13 +1,16 @@ -#!/usr/bin/python3.6 +"""This module download automatically json data of crypto currencies in bittrex""" +#!/usr/bin/env python3 from urllib.request import urlopen -currencies = ["ok","neo","dash","etc","eth","snt"] +CURRENCIES = ["ok", "neo", "dash", "etc", "eth", "snt"] -for cur in currencies: - url = 'https://bittrex.com/Api/v2.0/pub/market/GetTicks?marketName=BTC-'+cur+'&tickInterval=fiveMin' +for cur in CURRENCIES: + url1 = 'https://bittrex.com/Api/v2.0/pub/market/GetTicks?marketName=BTC-' + url2 = '&tickInterval=fiveMin' + url = url1+cur+url2 x = urlopen(url) - data = x.read() - str2 = str(data,'utf-8') - with open("btc-"+cur+".json", "w") as fichier: - fichier.write(str2) + json_data = x.read() + json_str = str(json_data, 'utf-8') + with open("btc-"+cur+".json", "w") as file: + file.write(json_str) From 2c4d0144ba6a9862500893458ea6c62316e332d6 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sun, 15 Oct 2017 14:40:02 +0300 Subject: [PATCH 08/31] Add note about binding sqlite with dry_run enabled --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e6bb944a2..2e59241fc 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ $ docker run -d \ -v ~/.freq/tradesv2.sqlite:/freqtrade/tradesv2.sqlite \ freqtrade ``` +If you are using `dry_run=True` you need to bind `tradesv2.dry_run.sqlite` instead of `tradesv2.sqlite`. You can then use the following commands to monitor and manage your container: @@ -133,7 +134,7 @@ $ docker stop freqtrade $ docker start freqtrade ``` -With the above setup you do not need to rebuild the image for configuration +You do not need to rebuild the image for configuration changes, it will suffice to edit `config.json` and restart the container. #### Contributing From bf6f563df29e7d9c67e1cbffcdf1efd7310b8da5 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sun, 15 Oct 2017 16:54:26 +0300 Subject: [PATCH 09/31] small tweaks to buy strategy and it's visualization --- freqtrade/analyze.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index f4f6d0077..e3148349f 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -31,15 +31,13 @@ def populate_indicators(dataframe: DataFrame) -> DataFrame: """ Adds several different TA indicators to the given DataFrame """ - dataframe['sar'] = ta.SAR(dataframe, 0.02, 0.22) dataframe['adx'] = ta.ADX(dataframe) stoch = ta.STOCHF(dataframe) dataframe['fastd'] = stoch['fastd'] dataframe['fastk'] = stoch['fastk'] dataframe['blower'] = ta.BBANDS(dataframe, nbdevup=2, nbdevdn=2)['lowerband'] - dataframe['cci'] = ta.CCI(dataframe, timeperiod=5) - dataframe['sma'] = ta.SMA(dataframe, timeperiod=100) - dataframe['tema'] = ta.TEMA(dataframe, timeperiod=4) + dataframe['sma'] = ta.SMA(dataframe, timeperiod=30) + dataframe['tema'] = ta.TEMA(dataframe, timeperiod=9) dataframe['mfi'] = ta.MFI(dataframe) return dataframe @@ -50,14 +48,12 @@ def populate_buy_trend(dataframe: DataFrame) -> DataFrame: :param dataframe: DataFrame :return: DataFrame with buy column """ - dataframe.loc[ (dataframe['close'] < dataframe['sma']) & - (dataframe['cci'] < -100) & (dataframe['tema'] <= dataframe['blower']) & - (dataframe['mfi'] < 30) & - (dataframe['fastd'] < 20) & - (dataframe['adx'] > 20), + (dataframe['mfi'] < 25) & + (dataframe['fastd'] < 25) & + (dataframe['adx'] > 30), 'buy'] = 1 dataframe.loc[dataframe['buy'] == 1, 'buy_price'] = dataframe['close'] @@ -120,20 +116,26 @@ def plot_dataframe(dataframe: DataFrame, pair: str) -> None: import matplotlib.pyplot as plt # Two subplots sharing x axis - fig, (ax1, ax2) = plt.subplots(2, sharex=True) + fig, (ax1, ax2, ax3) = plt.subplots(3, sharex=True) fig.suptitle(pair, fontsize=14, fontweight='bold') - ax1.plot(dataframe.index.values, dataframe['sar'], 'g_', label='pSAR') ax1.plot(dataframe.index.values, dataframe['close'], label='close') # ax1.plot(dataframe.index.values, dataframe['sell'], 'ro', label='sell') ax1.plot(dataframe.index.values, dataframe['sma'], '--', label='SMA') + ax1.plot(dataframe.index.values, dataframe['tema'], ':', label='TEMA') + ax1.plot(dataframe.index.values, dataframe['blower'], '-.', label='BB low') ax1.plot(dataframe.index.values, dataframe['buy_price'], 'bo', label='buy') ax1.legend() - # ax2.plot(dataframe.index.values, dataframe['adx'], label='ADX') + ax2.plot(dataframe.index.values, dataframe['adx'], label='ADX') ax2.plot(dataframe.index.values, dataframe['mfi'], label='MFI') # ax2.plot(dataframe.index.values, [25] * len(dataframe.index.values)) ax2.legend() + ax3.plot(dataframe.index.values, dataframe['fastk'], label='k') + ax3.plot(dataframe.index.values, dataframe['fastd'], label='d') + ax3.plot(dataframe.index.values, [20] * len(dataframe.index.values)) + ax3.legend() + # Fine-tune figure; make subplots close to each other and hide x ticks for # all but bottom plot. fig.subplots_adjust(hspace=0) From c9741cb2917a0fb2fd0963e305b363cc57ae50ec Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sun, 15 Oct 2017 16:58:23 +0300 Subject: [PATCH 10/31] adjust roi settings for faster trades --- README.md | 9 ++++----- config.json.example | 8 ++++---- freqtrade/tests/test_backtesting.py | 8 ++++---- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 2e59241fc..4388f00e3 100644 --- a/README.md +++ b/README.md @@ -30,11 +30,10 @@ in minutes and the value is the minimum ROI in percent. See the example below: ``` "minimal_roi": { - "2880": 0.005, # Sell after 48 hours if there is at least 0.5% profit - "1440": 0.01, # Sell after 24 hours if there is at least 1% profit - "720": 0.02, # Sell after 12 hours if there is at least 2% profit - "360": 0.02, # Sell after 6 hours if there is at least 2% profit - "0": 0.025 # Sell immediately if there is at least 2.5% profit + "50": 0.0, # Sell after 30 minutes if the profit is not negative + "40": 0.01, # Sell after 25 minutes if there is at least 1% profit + "30": 0.02, # Sell after 15 minutes if there is at least 2% profit + "0": 0.045 # Sell immediately if there is at least 4.5% profit }, ``` diff --git a/config.json.example b/config.json.example index d2ae679db..685189087 100644 --- a/config.json.example +++ b/config.json.example @@ -4,10 +4,10 @@ "stake_amount": 0.05, "dry_run": false, "minimal_roi": { - "60": 0.0, - "40": 0.01, - "20": 0.02, - "0": 0.03 + "50": 0.0, + "40": 0.01, + "30": 0.02, + "0": 0.045 }, "stoploss": -0.40, "bid_strategy": { diff --git a/freqtrade/tests/test_backtesting.py b/freqtrade/tests/test_backtesting.py index fb3b7e511..d008c4ae6 100644 --- a/freqtrade/tests/test_backtesting.py +++ b/freqtrade/tests/test_backtesting.py @@ -18,7 +18,7 @@ def print_results(results): len(results.index), results.profit.mean() * 100.0, results.profit.sum(), - results.duration.mean()*5 + results.duration.mean() * 5 )) @pytest.fixture @@ -30,10 +30,10 @@ def pairs(): def conf(): return { "minimal_roi": { - "60": 0.0, + "50": 0.0, "40": 0.01, - "20": 0.02, - "0": 0.03 + "30": 0.02, + "0": 0.045 }, "stoploss": -0.40 } From 389f9b45bb49d9f9fe69ed6d4e0ffbcec207135b Mon Sep 17 00:00:00 2001 From: dertione Date: Sun, 15 Oct 2017 17:24:49 +0200 Subject: [PATCH 11/31] update pylint 10/10 --- .../tests/testdata/download_backtest_data.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/freqtrade/tests/testdata/download_backtest_data.py b/freqtrade/tests/testdata/download_backtest_data.py index 6aef5f9f0..1119aac42 100644 --- a/freqtrade/tests/testdata/download_backtest_data.py +++ b/freqtrade/tests/testdata/download_backtest_data.py @@ -1,16 +1,16 @@ -"""This module download automatically json data of crypto currencies in bittrex""" #!/usr/bin/env python3 +"""This script generate json data from bittrex""" + from urllib.request import urlopen CURRENCIES = ["ok", "neo", "dash", "etc", "eth", "snt"] for cur in CURRENCIES: - url1 = 'https://bittrex.com/Api/v2.0/pub/market/GetTicks?marketName=BTC-' - url2 = '&tickInterval=fiveMin' - url = url1+cur+url2 - x = urlopen(url) - json_data = x.read() - json_str = str(json_data, 'utf-8') - with open("btc-"+cur+".json", "w") as file: - file.write(json_str) + url1 = 'https://bittrex.com/Api/v2.0/pub/market/GetTicks?marketName=BTC-' + url = url1+cur+'&tickInterval=fiveMin' + x = urlopen(url) + json_data = x.read() + json_str = str(json_data, 'utf-8') + with open('btc-'+cur+'.json', 'w') as file: + file.write(json_str) From d4f8b3ebbc14db2e574fab81fc425d2f033711ab Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Thu, 19 Oct 2017 17:12:08 +0300 Subject: [PATCH 12/31] remove setup.cfg as it's not used but it messes with running a single test --- setup.cfg | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 setup.cfg diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index ea59030de..000000000 --- a/setup.cfg +++ /dev/null @@ -1,5 +0,0 @@ -[aliases] -test=pytest - -[tool:pytest] -addopts = --cov=freqtrade --cov-config=.coveragerc freqtrade/tests/ From 1792e0fb9b0576fb7e0480c373b776128be3ddc0 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Thu, 19 Oct 2017 17:12:49 +0300 Subject: [PATCH 13/31] use hyperopt to find optimal parameter values for indicators --- freqtrade/tests/test_hyperopt.py | 124 +++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 freqtrade/tests/test_hyperopt.py diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py new file mode 100644 index 000000000..72704647f --- /dev/null +++ b/freqtrade/tests/test_hyperopt.py @@ -0,0 +1,124 @@ +# pragma pylint: disable=missing-docstring +import json +import logging +import os +from functools import reduce + +import pytest +import arrow +from pandas import DataFrame + +import hyperopt.pyll.stochastic + +from hyperopt import fmin, tpe, hp + +from freqtrade.analyze import analyze_ticker +from freqtrade.main import should_sell +from freqtrade.persistence import Trade + +logging.disable(logging.DEBUG) # disable debug logs that slow backtesting a lot + +def print_results(results): + print('Made {} buys. Average profit {:.2f}%. Total profit was {:.3f}. Average duration {:.1f} mins.'.format( + len(results.index), + results.profit.mean() * 100.0, + results.profit.sum(), + results.duration.mean() * 5 + )) + +@pytest.fixture +def pairs(): + return ['btc-neo', 'btc-eth', 'btc-omg', 'btc-edg', 'btc-pay', + 'btc-pivx', 'btc-qtum', 'btc-mtl', 'btc-etc', 'btc-ltc'] + +@pytest.fixture +def conf(): + return { + "minimal_roi": { + "50": 0.0, + "40": 0.01, + "30": 0.02, + "0": 0.045 + }, + "stoploss": -0.40 + } + + +def backtest(conf, pairs, mocker, buy_strategy): + trades = [] + mocker.patch.dict('freqtrade.main._CONF', conf) + for pair in pairs: + with open('freqtrade/tests/testdata/'+pair+'.json') as data_file: + data = json.load(data_file) + + mocker.patch('freqtrade.analyze.get_ticker_history', return_value=data) + mocker.patch('arrow.utcnow', return_value=arrow.get('2017-08-20T14:50:00')) + mocker.patch('freqtrade.analyze.populate_buy_trend', side_effect=buy_strategy) + ticker = analyze_ticker(pair) + # for each buy point + for index, row in ticker[ticker.buy == 1].iterrows(): + trade = Trade( + open_rate=row['close'], + open_date=arrow.get(row['date']).datetime, + amount=1, + ) + # calculate win/lose forwards from buy point + for index2, row2 in ticker[index:].iterrows(): + if should_sell(trade, row2['close'], arrow.get(row2['date']).datetime): + current_profit = (row2['close'] - trade.open_rate) / trade.open_rate + + trades.append((pair, current_profit, index2 - index)) + break + + labels = ['currency', 'profit', 'duration'] + results = DataFrame.from_records(trades, columns=labels) + + print_results(results) + if len(results.index) < 800: + return 0 + return results.profit.sum() / results.duration.mean() + +def buy_strategy_generator(params): + print(params) + def populate_buy_trend(dataframe: DataFrame) -> DataFrame: + conditions = [] + conditions.append(dataframe['close'] < dataframe['sma']) + conditions.append(dataframe['tema'] <= dataframe['blower']) + if params['mfi']['enabled']: + conditions.append(dataframe['mfi'] < params['mfi']['value']) + if params['fastd']['enabled']: + conditions.append(dataframe['fastd'] < params['fastd']['value']) + if params['adx']['enabled']: + conditions.append(dataframe['adx'] > params['adx']['value']) + + dataframe.loc[ + reduce(lambda x, y: x & y, conditions), + 'buy'] = 1 + dataframe.loc[dataframe['buy'] == 1, 'buy_price'] = dataframe['close'] + + return dataframe + return populate_buy_trend + +@pytest.mark.skipif(not os.environ.get('BACKTEST', False), reason="BACKTEST not set") +def test_hyperopt(conf, pairs, mocker): + + def optimizer(params): + return backtest(conf, pairs, mocker, buy_strategy_generator(params)) + + space = { + 'mfi': hp.choice('mfi', [ + {'enabled': False}, + {'enabled': True, 'value': hp.uniform('mfi-value', 10, 50)} + ]), + 'fastd': hp.choice('fastd', [ + {'enabled': False}, + {'enabled': True, 'value': hp.uniform('fastd-value', 10, 50)} + ]), + 'adx': hp.choice('adx', [ + {'enabled': False}, + {'enabled': True, 'value': hp.uniform('adx-value', 10, 50)} + ]), + } + + # print(hyperopt.pyll.stochastic.sample(space)) + print(fmin(fn=optimizer, space=space, algo=tpe.suggest, max_evals=2)) From 4feb038d0a5b0ccc652cf58234749a8d7bfb4567 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Thu, 19 Oct 2017 17:46:41 +0300 Subject: [PATCH 14/31] add hyperopt dependencies --- requirements.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/requirements.txt b/requirements.txt index be3a292f0..82bb1d952 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,6 +14,9 @@ TA-Lib==0.4.10 pytest==3.2.3 pytest-mock==1.6.3 pytest-cov==2.5.1 +hyperopt==0.1 +# do not upgrade networkx before this is fixed https://github.com/hyperopt/hyperopt/issues/325 +networkx==1.11 # Required for plotting data #matplotlib==2.1.0 From ff100bdac4201f473562e0760ddca92b365db0b6 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Thu, 19 Oct 2017 18:29:57 +0300 Subject: [PATCH 15/31] the optimizer expects values in the order of smaller is better --- freqtrade/tests/test_hyperopt.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index 72704647f..69da3b6b6 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -74,9 +74,9 @@ def backtest(conf, pairs, mocker, buy_strategy): results = DataFrame.from_records(trades, columns=labels) print_results(results) - if len(results.index) < 800: - return 0 - return results.profit.sum() / results.duration.mean() + if len(results.index) < 800: + return 100000 # return large number to "ignore" this result + return results.duration.mean() / results.profit.sum() # the smaller the better def buy_strategy_generator(params): print(params) @@ -121,4 +121,4 @@ def test_hyperopt(conf, pairs, mocker): } # print(hyperopt.pyll.stochastic.sample(space)) - print(fmin(fn=optimizer, space=space, algo=tpe.suggest, max_evals=2)) + print('Best parameters {}'.format(fmin(fn=optimizer, space=space, algo=tpe.suggest, max_evals=10))) From bbb2c7cf62294a2a35e7f04d852250c9d5c468c2 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Fri, 20 Oct 2017 10:39:04 +0300 Subject: [PATCH 16/31] more parametrizing. adjust ranges for previous parameters --- freqtrade/tests/test_hyperopt.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index 69da3b6b6..011fd48e5 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -82,7 +82,8 @@ def buy_strategy_generator(params): print(params) def populate_buy_trend(dataframe: DataFrame) -> DataFrame: conditions = [] - conditions.append(dataframe['close'] < dataframe['sma']) + if params['below_sma']['enabled']: + conditions.append(dataframe['close'] < dataframe['sma']) conditions.append(dataframe['tema'] <= dataframe['blower']) if params['mfi']['enabled']: conditions.append(dataframe['mfi'] < params['mfi']['value']) @@ -108,15 +109,19 @@ def test_hyperopt(conf, pairs, mocker): space = { 'mfi': hp.choice('mfi', [ {'enabled': False}, - {'enabled': True, 'value': hp.uniform('mfi-value', 10, 50)} + {'enabled': True, 'value': hp.uniform('mfi-value', 2, 40)} ]), 'fastd': hp.choice('fastd', [ {'enabled': False}, - {'enabled': True, 'value': hp.uniform('fastd-value', 10, 50)} + {'enabled': True, 'value': hp.uniform('fastd-value', 2, 40)} ]), 'adx': hp.choice('adx', [ {'enabled': False}, - {'enabled': True, 'value': hp.uniform('adx-value', 10, 50)} + {'enabled': True, 'value': hp.uniform('adx-value', 2, 40)} + ]), + 'below_sma': hp.choice('below_sma', [ + {'enabled': False}, + {'enabled': True} ]), } From 1196983d5f60a81b845ca83c4fb204033f92018a Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Fri, 20 Oct 2017 10:39:36 +0300 Subject: [PATCH 17/31] change objective to emphasize shorter trades and include average profit --- freqtrade/tests/test_hyperopt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index 011fd48e5..f1ce196af 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -76,7 +76,7 @@ def backtest(conf, pairs, mocker, buy_strategy): print_results(results) if len(results.index) < 800: return 100000 # return large number to "ignore" this result - return results.duration.mean() / results.profit.sum() # the smaller the better + return results.duration.mean() * results.duration.mean() / results.profit.sum() / results.profit.mean() # the smaller the better def buy_strategy_generator(params): print(params) From 3f7a583de66ae2f9d62e76124e2001efecf81c3e Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Fri, 20 Oct 2017 12:56:44 +0300 Subject: [PATCH 18/31] add SAR to hyperopt. add over/under sma options to hyperopt --- freqtrade/analyze.py | 3 ++- freqtrade/tests/test_hyperopt.py | 13 ++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index e3148349f..657ffb14e 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -31,12 +31,13 @@ def populate_indicators(dataframe: DataFrame) -> DataFrame: """ Adds several different TA indicators to the given DataFrame """ + dataframe['sar'] = ta.SAR(dataframe) dataframe['adx'] = ta.ADX(dataframe) stoch = ta.STOCHF(dataframe) dataframe['fastd'] = stoch['fastd'] dataframe['fastk'] = stoch['fastk'] dataframe['blower'] = ta.BBANDS(dataframe, nbdevup=2, nbdevdn=2)['lowerband'] - dataframe['sma'] = ta.SMA(dataframe, timeperiod=30) + dataframe['sma'] = ta.SMA(dataframe, timeperiod=40) dataframe['tema'] = ta.TEMA(dataframe, timeperiod=9) dataframe['mfi'] = ta.MFI(dataframe) return dataframe diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index f1ce196af..b32dda382 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -84,6 +84,8 @@ def buy_strategy_generator(params): conditions = [] if params['below_sma']['enabled']: conditions.append(dataframe['close'] < dataframe['sma']) + if params['over_sma']['enabled']: + conditions.append(dataframe['close'] > dataframe['sma']) conditions.append(dataframe['tema'] <= dataframe['blower']) if params['mfi']['enabled']: conditions.append(dataframe['mfi'] < params['mfi']['value']) @@ -91,7 +93,8 @@ def buy_strategy_generator(params): conditions.append(dataframe['fastd'] < params['fastd']['value']) if params['adx']['enabled']: conditions.append(dataframe['adx'] > params['adx']['value']) - + if params['over_sar']['enabled']: + conditions.append(dataframe['close'] > dataframe['sar']) dataframe.loc[ reduce(lambda x, y: x & y, conditions), 'buy'] = 1 @@ -123,6 +126,14 @@ def test_hyperopt(conf, pairs, mocker): {'enabled': False}, {'enabled': True} ]), + 'over_sma': hp.choice('over_sma', [ + {'enabled': False}, + {'enabled': True} + ]), + 'over_sar': hp.choice('over_sar', [ + {'enabled': False}, + {'enabled': True} + ]), } # print(hyperopt.pyll.stochastic.sample(space)) From 0fbca8b8efbd149a790a22786a73b0c4dc8dd3be Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Fri, 20 Oct 2017 13:14:28 +0300 Subject: [PATCH 19/31] add CCI to hyperopt --- freqtrade/analyze.py | 1 + freqtrade/tests/test_hyperopt.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index 657ffb14e..11baa8558 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -40,6 +40,7 @@ def populate_indicators(dataframe: DataFrame) -> DataFrame: dataframe['sma'] = ta.SMA(dataframe, timeperiod=40) dataframe['tema'] = ta.TEMA(dataframe, timeperiod=9) dataframe['mfi'] = ta.MFI(dataframe) + dataframe['cci'] = ta.CCI(dataframe) return dataframe diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index b32dda382..89531d516 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -93,6 +93,8 @@ def buy_strategy_generator(params): conditions.append(dataframe['fastd'] < params['fastd']['value']) if params['adx']['enabled']: conditions.append(dataframe['adx'] > params['adx']['value']) + if params['cci']['enabled']: + conditions.append(dataframe['cci'] < params['cci']['value']) if params['over_sar']['enabled']: conditions.append(dataframe['close'] > dataframe['sar']) dataframe.loc[ @@ -122,6 +124,10 @@ def test_hyperopt(conf, pairs, mocker): {'enabled': False}, {'enabled': True, 'value': hp.uniform('adx-value', 2, 40)} ]), + 'cci': hp.choice('cci', [ + {'enabled': False}, + {'enabled': True, 'value': hp.uniform('cci-value', -200, -100)} + ]), 'below_sma': hp.choice('below_sma', [ {'enabled': False}, {'enabled': True} From ce2966dd7fb3a20d7c88e7274df4126905b71109 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Fri, 20 Oct 2017 18:29:38 +0300 Subject: [PATCH 20/31] add uptrend_sma to hyperopt --- freqtrade/tests/test_hyperopt.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index 89531d516..d0756b690 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -97,6 +97,9 @@ def buy_strategy_generator(params): conditions.append(dataframe['cci'] < params['cci']['value']) if params['over_sar']['enabled']: conditions.append(dataframe['close'] > dataframe['sar']) + if params['uptrend_sma']['enabled']: + prevsma = dataframe['sma'].shift(1) + conditions.append(dataframe['sma'] > prevsma) dataframe.loc[ reduce(lambda x, y: x & y, conditions), 'buy'] = 1 @@ -140,6 +143,10 @@ def test_hyperopt(conf, pairs, mocker): {'enabled': False}, {'enabled': True} ]), + 'uptrend_sma': hp.choice('uptrend_sma', [ + {'enabled': False}, + {'enabled': True} + ]), } # print(hyperopt.pyll.stochastic.sample(space)) From 146c254c0fe6a6297561c165736e149af88fb9b4 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sat, 21 Oct 2017 10:26:38 +0300 Subject: [PATCH 21/31] start adding other triggers than just the lower BBands --- freqtrade/tests/test_hyperopt.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index d0756b690..ad6c1d619 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -82,11 +82,11 @@ def buy_strategy_generator(params): print(params) def populate_buy_trend(dataframe: DataFrame) -> DataFrame: conditions = [] + # GUARDS AND TRENDS if params['below_sma']['enabled']: conditions.append(dataframe['close'] < dataframe['sma']) if params['over_sma']['enabled']: conditions.append(dataframe['close'] > dataframe['sma']) - conditions.append(dataframe['tema'] <= dataframe['blower']) if params['mfi']['enabled']: conditions.append(dataframe['mfi'] < params['mfi']['value']) if params['fastd']['enabled']: @@ -100,6 +100,15 @@ def buy_strategy_generator(params): if params['uptrend_sma']['enabled']: prevsma = dataframe['sma'].shift(1) conditions.append(dataframe['sma'] > prevsma) + + prev_fastd = dataframe['fastd'].shift(1) + # TRIGGERS + triggers = { + 'lower_bb': dataframe['tema'] <= dataframe['blower'], + 'faststoch10': (dataframe['fastd'] >= 10) & (prev_fastd < 10), + } + conditions.append(triggers.get(params['trigger']['type'])) + dataframe.loc[ reduce(lambda x, y: x & y, conditions), 'buy'] = 1 @@ -147,6 +156,10 @@ def test_hyperopt(conf, pairs, mocker): {'enabled': False}, {'enabled': True} ]), + 'trigger': hp.choice('trigger', [ + {'type': 'lower_bb'}, + {'type': 'faststoch10'} + ]), } # print(hyperopt.pyll.stochastic.sample(space)) From f79b44eefe065f957852dda9e4e14d0062216421 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sat, 21 Oct 2017 10:28:02 +0300 Subject: [PATCH 22/31] adjust ROI map for shorter trades --- freqtrade/tests/test_hyperopt.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index ad6c1d619..9576a2173 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -35,10 +35,10 @@ def pairs(): def conf(): return { "minimal_roi": { - "50": 0.0, - "40": 0.01, - "30": 0.02, - "0": 0.045 + "40": 0.0, + "30": 0.01, + "20": 0.02, + "0": 0.04 }, "stoploss": -0.40 } From 17b984a7cd108ec41e96ac5893074e97fd11a05f Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sat, 21 Oct 2017 10:28:43 +0300 Subject: [PATCH 23/31] adjust objective function to emphasize trade lenghts more --- freqtrade/tests/test_hyperopt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index 9576a2173..245481b93 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -74,9 +74,9 @@ def backtest(conf, pairs, mocker, buy_strategy): results = DataFrame.from_records(trades, columns=labels) print_results(results) - if len(results.index) < 800: + if len(results.index) < 800: # require at least 800 trades return 100000 # return large number to "ignore" this result - return results.duration.mean() * results.duration.mean() / results.profit.sum() / results.profit.mean() # the smaller the better + return results.duration.mean() ** 3 / results.profit.sum() / results.profit.mean() # the smaller the better def buy_strategy_generator(params): print(params) From 913488910cadb16b49ebd41be68f5eea252cffbe Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sat, 21 Oct 2017 10:29:05 +0300 Subject: [PATCH 24/31] bump minimum evaluations to 40 rounds --- freqtrade/tests/test_hyperopt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index 245481b93..6cdaa9045 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -163,4 +163,4 @@ def test_hyperopt(conf, pairs, mocker): } # print(hyperopt.pyll.stochastic.sample(space)) - print('Best parameters {}'.format(fmin(fn=optimizer, space=space, algo=tpe.suggest, max_evals=10))) + print('Best parameters {}'.format(fmin(fn=optimizer, space=space, algo=tpe.suggest, max_evals=40))) From 35838f5e64fca3c28c520094ea90afd2b54104d8 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sat, 21 Oct 2017 11:07:29 +0300 Subject: [PATCH 25/31] upgrade to latest telegram lib --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index be3a292f0..3483bc50e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -e git+https://github.com/ericsomdahl/python-bittrex.git@d7033d0#egg=python-bittrex SQLAlchemy==1.1.14 -python-telegram-bot==8.0 +python-telegram-bot==8.1.1 arrow==0.10.0 requests==2.18.4 urllib3==1.22 diff --git a/setup.py b/setup.py index e89fd2eee..eced2b5b3 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ setup(name='freqtrade', install_requires=[ 'python-bittrex==0.1.3', 'SQLAlchemy==1.1.13', - 'python-telegram-bot==8.0', + 'python-telegram-bot==8.1.1', 'arrow==0.10.0', 'requests==2.18.4', 'urllib3==1.22', From d32ff3410cc0de9dd9b29f1d7c950ebef8adb01a Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sat, 21 Oct 2017 11:08:08 +0300 Subject: [PATCH 26/31] add help command to telegram bot --- freqtrade/rpc/telegram.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 5312125ed..4b320eb85 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -45,6 +45,7 @@ def init(config: dict) -> None: CommandHandler('stop', _stop), CommandHandler('forcesell', _forcesell), CommandHandler('performance', _performance), + CommandHandler('help', _help), ] for handle in handles: _updater.dispatcher.add_handler(handle) @@ -301,6 +302,27 @@ def _performance(bot: Bot, update: Update) -> None: send_msg(message, parse_mode=ParseMode.HTML) +@authorized_only +def _help(bot: Bot, update: Update) -> None: + """ + Handler for /help. + Show commands of the bot + :param bot: telegram bot + :param update: message update + :return: None + """ + message = """ +*/start:* `Starts the trader` +*/stop:* `Stops the trader` +*/status:* `Lists all open trades` +*/profit:* `Lists cumulative profit from all finished trades` +*/forcesell :* `Instantly sells the given trade, regardless of profit` +*/performance:* `Show performance of each finished trade grouped by pair` +*/help:* `This help message` + """ + send_msg(message, bot=bot) + + def send_msg(msg: str, bot: Bot = None, parse_mode: ParseMode = ParseMode.MARKDOWN) -> None: """ Send given markdown message From 57acf85b42027203877e6446dd930a35746cce7f Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sun, 22 Oct 2017 17:11:01 +0300 Subject: [PATCH 27/31] try a different objective function --- freqtrade/tests/test_hyperopt.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index 6cdaa9045..285309db5 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -74,9 +74,12 @@ def backtest(conf, pairs, mocker, buy_strategy): results = DataFrame.from_records(trades, columns=labels) print_results(results) - if len(results.index) < 800: # require at least 800 trades - return 100000 # return large number to "ignore" this result - return results.duration.mean() ** 3 / results.profit.sum() / results.profit.mean() # the smaller the better + + # set the value below to suit your number concurrent trades so its realistic to 20days of data + TARGET_TRADES = 1200 + if results.profit.sum() == 0 or results.profit.mean() == 0: + return 49999999999 # avoid division by zero, return huge value to discard result + return abs(len(results.index) - 1200.1) / (results.profit.sum() ** 2) * results.duration.mean() # the smaller the better def buy_strategy_generator(params): print(params) From 37004e331a21d6b1e1e7533d531eee27222439e5 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sun, 22 Oct 2017 17:14:55 +0300 Subject: [PATCH 28/31] remove unused import and commented out code --- freqtrade/tests/test_hyperopt.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index 285309db5..486ffbece 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -8,8 +8,6 @@ import pytest import arrow from pandas import DataFrame -import hyperopt.pyll.stochastic - from hyperopt import fmin, tpe, hp from freqtrade.analyze import analyze_ticker @@ -165,5 +163,4 @@ def test_hyperopt(conf, pairs, mocker): ]), } - # print(hyperopt.pyll.stochastic.sample(space)) print('Best parameters {}'.format(fmin(fn=optimizer, space=space, algo=tpe.suggest, max_evals=40))) From 6f5307fda7b44be6843128f0bf84c5546ff5fef4 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sun, 22 Oct 2017 17:15:57 +0300 Subject: [PATCH 29/31] use more aggressive stop loss for hyperopt --- freqtrade/tests/test_hyperopt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index 486ffbece..167e0d9ab 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -38,7 +38,7 @@ def conf(): "20": 0.02, "0": 0.04 }, - "stoploss": -0.40 + "stoploss": -0.05 } From f6ef8383bbcb1afee5bf1e08d28eab071f740c03 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sun, 22 Oct 2017 21:50:07 +0300 Subject: [PATCH 30/31] remove filtering from analyze that is super slow and not really needed --- freqtrade/analyze.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index 11baa8558..310754754 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -24,7 +24,7 @@ def parse_ticker_dataframe(ticker: list, minimum_date: arrow.Arrow) -> DataFrame .drop('BV', 1) \ .rename(columns={'C':'close', 'V':'volume', 'O':'open', 'H':'high', 'L':'low', 'T':'date'}) \ .sort_values('date') - return df[df['date'].map(arrow.get) > minimum_date] + return df def populate_indicators(dataframe: DataFrame) -> DataFrame: From ff4fcdc76052e61be6d1bf6a490c206bd8c32eda Mon Sep 17 00:00:00 2001 From: gcarq Date: Tue, 24 Oct 2017 18:14:31 +0200 Subject: [PATCH 31/31] version bump --- freqtrade/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/__init__.py b/freqtrade/__init__.py index db6fd3728..44a21be08 100644 --- a/freqtrade/__init__.py +++ b/freqtrade/__init__.py @@ -1,3 +1,3 @@ -__version__ = '0.11.0' +__version__ = '0.12.0' from . import main