Merge branch 'develop' of freqtrade into fix/636

This commit is contained in:
gcarq 2018-06-09 00:37:46 +02:00
commit 5851cc70a7
21 changed files with 284 additions and 94 deletions

View File

@ -1,8 +1,10 @@
# Bot Optimization
This page explains where to customize your strategies, and add new
indicators.
This page explains where to customize your strategies, and add new
indicators.
## Table of Contents
- [Install a custom strategy file](#install-a-custom-strategy-file)
- [Customize your strategy](#change-your-strategy)
- [Add more Indicator](#add-more-indicator)
@ -11,10 +13,12 @@ indicators.
Since the version `0.16.0` the bot allows using custom strategy file.
## Install a custom strategy file
This is very simple. Copy paste your strategy file into the folder
This is very simple. Copy paste your strategy file into the folder
`user_data/strategies`.
Let assume you have a class called `AwesomeStrategy` in the file `awesome-strategy.py`:
1. Move your file into `user_data/strategies` (you should have `user_data/strategies/awesome-strategy.py`
2. Start the bot with the param `--strategy AwesomeStrategy` (the parameter is the class name)
@ -23,12 +27,14 @@ python3 ./freqtrade/main.py --strategy AwesomeStrategy
```
## Change your strategy
The bot includes a default strategy file. However, we recommend you to
The bot includes a default strategy file. However, we recommend you to
use your own file to not have to lose your parameters every time the default
strategy file will be updated on Github. Put your custom strategy file
into the folder `user_data/strategies`.
A strategy file contains all the information needed to build a good strategy:
- Buy strategy rules
- Sell strategy rules
- Minimal ROI recommended
@ -37,12 +43,13 @@ A strategy file contains all the information needed to build a good strategy:
The bot also include a sample strategy called `TestStrategy` you can update: `user_data/strategies/test_strategy.py`.
You can test it with the parameter: `--strategy TestStrategy`
```bash
``` bash
python3 ./freqtrade/main.py --strategy AwesomeStrategy
```
### Specify custom strategy location
If you want to use a strategy from a different folder you can pass `--strategy-path`
```bash
@ -52,11 +59,13 @@ python3 ./freqtrade/main.py --strategy AwesomeStrategy --strategy-path /some/fol
**For the following section we will use the [user_data/strategies/test_strategy.py](https://github.com/freqtrade/freqtrade/blob/develop/user_data/strategies/test_strategy.py)
file as reference.**
### Buy strategy
Edit the method `populate_buy_trend()` into your strategy file to
### Buy strategy
Edit the method `populate_buy_trend()` into your strategy file to
update your buy strategy.
Sample from `user_data/strategies/test_strategy.py`:
Sample from `user_data/strategies/test_strategy.py`:
```python
def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame:
"""
@ -76,10 +85,11 @@ def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame:
```
### Sell strategy
Edit the method `populate_sell_trend()` into your strategy file to
update your sell strategy.
Sample from `user_data/strategies/test_strategy.py`:
Edit the method `populate_sell_trend()` into your strategy file to update your sell strategy.
Sample from `user_data/strategies/test_strategy.py`:
```python
def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame:
"""
@ -98,11 +108,13 @@ def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame:
```
## Add more Indicator
As you have seen, buy and sell strategies need indicators. You can add
As you have seen, buy and sell strategies need indicators. You can add
more indicators by extending the list contained in
the method `populate_indicators()` from your strategy file.
Sample:
```python
def populate_indicators(dataframe: DataFrame) -> DataFrame:
"""
@ -137,16 +149,25 @@ def populate_indicators(dataframe: DataFrame) -> DataFrame:
return dataframe
```
**Want more indicators example?**
Look into the [user_data/strategies/test_strategy.py](https://github.com/freqtrade/freqtrade/blob/develop/user_data/strategies/test_strategy.py).
### Want more indicator examples
Look into the [user_data/strategies/test_strategy.py](https://github.com/freqtrade/freqtrade/blob/develop/user_data/strategies/test_strategy.py).
Then uncomment indicators you need.
### Where is the default strategy?
The default buy strategy is located in the file
[freqtrade/default_strategy.py](https://github.com/freqtrade/freqtrade/blob/develop/freqtrade/strategy/default_strategy.py).
The default buy strategy is located in the file
[freqtrade/default_strategy.py](https://github.com/freqtrade/freqtrade/blob/develop/freqtrade/strategy/default_strategy.py).
### Further strategy ideas
To get additional Ideas for strategies, head over to our [strategy repository](https://github.com/freqtrade/freqtrade-strategies). Feel free to use them as they are - but results will depend on the current market situation, pairs used etc. - therefore please backtest the strategy for your exchange/desired pairs first, evaluate carefully, use at your own risk.
Feel free to use any of them as inspiration for your own strategies.
We're happy to accept Pull Requests containing new Strategies to that repo.
We also got a *strategy-sharing* channel in our [Slack community](https://join.slack.com/t/highfrequencybot/shared_invite/enQtMjQ5NTM0OTYzMzY3LWMxYzE3M2MxNDdjMGM3ZTYwNzFjMGIwZGRjNTc3ZGU3MGE3NzdmZGMwNmU3NDM5ZTNmM2Y3NjRiNzk4NmM4OGE) which is a great place to get and/or share ideas.
## Next step
Now you have a perfect strategy you probably want to backtesting it.
Now you have a perfect strategy you probably want to backtest it.
Your next step is to learn [How to use the Backtesting](https://github.com/freqtrade/freqtrade/blob/develop/docs/backtesting.md).

View File

@ -15,7 +15,6 @@ To understand how to set up the bot please read the [Bot Configuration](https://
- [MacOS](#macos)
- [Setup Config and virtual env](#setup-config-and-virtual-env)
* [Windows](#windows)
<!-- /TOC -->
@ -35,7 +34,9 @@ usage:
```
### --install
This script will install everything you need to run the bot:
* Mandatory software as: `Python3`, `ta-lib`, `wget`
* Setup your virtualenv
* Configure your `config.json` file
@ -43,12 +44,15 @@ This script will install everything you need to run the bot:
This script is a combination of `install script` `--reset`, `--config`
### --update
Update parameter will pull the last version of your current branch and update your virtualenv.
### --reset
Reset parameter will hard reset your branch (only if you are on `master` or `develop`) and recreate your virtualenv.
### --config
Config parameter is a `config.json` configurator. This script will ask you questions to setup your bot and create your `config.json`.
------
@ -63,7 +67,6 @@ Start by downloading Docker for your platform:
Once you have Docker installed, simply create the config file (e.g. `config.json`) and then create a Docker image for `freqtrade` using the Dockerfile in this repo.
### 1. Prepare the Bot
#### 1.1. Clone the git repository
@ -95,16 +98,17 @@ cp -n config.json.example config.json
#### 1.5. Create your database file *(optional - the bot will create it if it is missing)*
Production
```bash
touch tradesv3.sqlite
````
Dry-Run
```bash
touch tradesv3.dryrun.sqlite
```
### 2. Build the Docker image
```bash
@ -114,7 +118,6 @@ docker build -t 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 an SQLite database file (see the "5. Run a restartable docker image" section) to keep it between updates.
### 3. Verify the Docker image
After the build process you can verify that the image was created with:
@ -123,7 +126,6 @@ After the build process you can verify that the image was created with:
docker images
```
### 4. Run the Docker image
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):
@ -132,16 +134,16 @@ You can run a one-off container that is immediately deleted upon exiting with th
docker run --rm -v /etc/localtime:/etc/localtime:ro -v `pwd`/config.json:/freqtrade/config.json -it freqtrade
```
There is known issue in OSX Docker versions after 17.09.1, whereby /etc/localtime cannot be shared causing Docker to not start. A work-around for this is to start with the following cmd.
There is known issue in OSX Docker versions after 17.09.1, whereby /etc/localtime cannot be shared causing Docker to not start. A work-around for this is to start with the following cmd.
```bash
docker run --rm -e TZ=`ls -la /etc/localtime | cut -d/ -f8-9` -v `pwd`/config.json:/freqtrade/config.json -it freqtrade
```
More information on this docker issue and work-around can be read here: https://github.com/docker/for-mac/issues/2396
More information on this docker issue and work-around can be read [here](https://github.com/docker/for-mac/issues/2396)
In this example, the database will be created inside the docker instance and will be lost when you will refresh your image.
### 5. Run a restartable docker image
To run a restartable instance in the background (feel free to place your configuration and database files wherever it feels comfortable on your filesystem).
@ -164,6 +166,7 @@ docker run -d \
-v ~/.freqtrade/tradesv3.sqlite:/freqtrade/tradesv3.sqlite \
freqtrade --db-url sqlite:///tradesv3.sqlite
```
NOTE: db-url defaults to `sqlite:///tradesv3.sqlite` but it defaults to `sqlite://` if `dry_run=True` is being used.
To override this behaviour use a custom db-url value: i.e.: `--db-url sqlite:///tradesv3.dryrun.sqlite`
@ -190,13 +193,13 @@ We've included/collected install instructions for Ubuntu 16.04, MacOS, and Windo
### Requirements
Click each one for install guide:
* [Python 3.6.x](http://docs.python-guide.org/en/latest/starting/installation/), note the bot was not tested on Python >= 3.7.x
* [pip](https://pip.pypa.io/en/stable/installing/)
* [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
* [virtualenv](https://virtualenv.pypa.io/en/stable/installation/) (Recommended)
* [TA-Lib](https://mrjbq7.github.io/ta-lib/install.html)
### Linux - Ubuntu 16.04
#### 1. Install Python 3.6, Git, and wget
@ -240,17 +243,12 @@ Clone the git repository:
git clone https://github.com/freqtrade/freqtrade.git
```
Optionally checkout the develop branch:
```bash
git checkout develop
```
#### 5. Configure `freqtrade` as a `systemd` service
From the freqtrade repo... copy `freqtrade.service` to your systemd user directory (usually `~/.config/systemd/user`) and update `WorkingDirectory` and `ExecStart` to match your setup.
After that you can start the daemon with:
```bash
systemctl --user start freqtrade
```
@ -261,7 +259,6 @@ For this to be persistent (run when user is logged out) you'll need to enable `l
sudo loginctl enable-linger "$USER"
```
### MacOS
#### 1. Install Python 3.6, git, wget and ta-lib
@ -296,7 +293,6 @@ Optionally checkout the develop branch:
git checkout develop
```
### Setup Config and virtual env
#### 1. Initialize the configuration
@ -308,7 +304,6 @@ cp config.json.example config.json
> *To edit the config please refer to [Bot Configuration](https://github.com/freqtrade/freqtrade/blob/develop/docs/configuration.md).*
#### 2. Setup your Python virtual environment (virtualenv)
```bash
@ -331,27 +326,41 @@ python3.6 ./freqtrade/main.py -c config.json
## Windows
We recommend that Windows users use [Docker](#docker) as this will work
much easier and smoother (also more secure).
We recommend that Windows users use [Docker](#docker) as this will work much easier and smoother (also more secure).
### Install freqtrade
If that is not possible, try using the Windows Linux subsystem (WSL) - for which the Ubuntu instructions should work.
If that is not available on your system, feel free to try the instructions below, which led to success for some.
### Install freqtrade manually
#### Clone the git repository
```bash
git clone https://github.com/freqtrade/freqtrade.git
```
copy paste `config.json` to ``\path\freqtrade-develop\freqtrade`
#### install ta-lib
Install ta-lib according to the [ta-lib documentation](https://github.com/mrjbq7/ta-lib#windows).
As compiling from source on windows has heavy dependencies (requires a partial visual studio installation), there is also a repository of inofficial precompiled windows Wheels [here](https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib), which needs to be downloaded and installed using `pip install TA_Lib0.4.17cp36cp36mwin32.whl` (make sure to use the version matching your python version)
```cmd
>cd \path\freqtrade-develop
>python -m venv .env
>cd .env\Scripts
>activate.bat
>cd \path\freqtrade-develop
REM optionally install ta-lib from wheel
REM >pip install TA_Lib0.4.17cp36cp36mwin32.whl
>pip install -r requirements.txt
>pip install -e .
>cd freqtrade
>python main.py
>python freqtrade\main.py
```
> Thanks [Owdr](https://github.com/Owdr) for the commands. Source: [Issue #222](https://github.com/freqtrade/freqtrade/issues/222)
Now you have an environment ready, the next step is
[Bot Configuration](https://github.com/freqtrade/freqtrade/blob/develop/docs/configuration.md)...

View File

@ -62,6 +62,7 @@ class Analyze(object):
'close': 'last',
'volume': 'max',
})
frame.drop(frame.tail(1).index, inplace=True) # eliminate partial candle
return frame
def populate_indicators(self, dataframe: DataFrame) -> DataFrame:

View File

@ -165,6 +165,11 @@ class Arguments(object):
@staticmethod
def optimizer_shared_options(parser: argparse.ArgumentParser) -> None:
"""
Parses given common arguments for Backtesting and Hyperopt scripts.
:param parser:
:return:
"""
parser.add_argument(
'-i', '--ticker-interval',
help='specify ticker interval (1m, 5m, 30m, 1h, 1d)',
@ -243,7 +248,7 @@ class Arguments(object):
:return: Start and End range period
"""
if text is None:
return TimeRange()
return TimeRange(None, None, 0, 0)
syntax = [(r'^-(\d{8})$', (None, 'date')),
(r'^(\d{8})-$', ('date', None)),
(r'^(\d{8})-(\d{8})$', ('date', 'date')),
@ -298,28 +303,34 @@ class Arguments(object):
'--pairs-file',
help='File containing a list of pairs to download',
dest='pairs_file',
default=None
default=None,
metavar='PATH',
)
self.parser.add_argument(
'--export',
help='Export files to given dir',
dest='export',
default=None)
default=None,
metavar='PATH',
)
self.parser.add_argument(
'--days',
help='Download data for number of days',
dest='days',
type=int,
default=None)
metavar='INT',
default=None
)
self.parser.add_argument(
'--exchange',
help='Exchange name (default: %(default)s)',
dest='exchange',
type=str,
default='bittrex')
default='bittrex'
)
self.parser.add_argument(
'-t', '--timeframes',

View File

@ -61,11 +61,9 @@ class Configuration(object):
with open(path) as file:
conf = json.load(file)
except FileNotFoundError:
logger.critical(
'Config file "%s" not found. Please create your config file',
path
)
exit(0)
raise OperationalException(
'Config file "{}" not found!'
' Please create a config file or check whether it exists.'.format(path))
if 'internals' not in conf:
conf['internals'] = {}

View File

@ -277,7 +277,7 @@ def get_ticker(pair: str, refresh: Optional[bool] = True) -> dict:
'bid': float(data['bid']),
'ask': float(data['ask']),
}
except KeyError as e:
except KeyError:
logger.debug("Could not cache ticker data for %s", pair)
return data
except (ccxt.NetworkError, ccxt.ExchangeError) as e:

View File

@ -192,6 +192,7 @@ class CryptoToFiatConverter(object):
# return 0 for unsupported stake currencies (fiat-convert should not break the bot)
logger.warning("unsupported crypto-symbol %s - returning 0.0", crypto_symbol)
return 0.0
try:
return float(
self._coinmarketcap.ticker(

View File

@ -85,7 +85,7 @@ def load_data(datadir: str,
ticker_interval: str,
pairs: Optional[List[str]] = None,
refresh_pairs: Optional[bool] = False,
timerange: TimeRange = TimeRange()) -> Dict[str, List]:
timerange: TimeRange = TimeRange(None, None, 0, 0)) -> Dict[str, List]:
"""
Loads ticker history data for the given parameters
:return: dict
@ -125,7 +125,7 @@ def make_testdata_path(datadir: str) -> str:
def download_pairs(datadir, pairs: List[str],
ticker_interval: str,
timerange: TimeRange = TimeRange()) -> bool:
timerange: TimeRange = TimeRange(None, None, 0, 0)) -> bool:
"""For each pairs passed in parameters, download the ticker intervals"""
for pair in pairs:
try:

View File

@ -317,7 +317,7 @@ def test_tickerdata_to_dataframe(default_conf, mocker) -> None:
backtesting = Backtesting(default_conf)
data = backtesting.tickerdata_to_dataframe(tickerlist)
assert len(data['UNITTEST/BTC']) == 100
assert len(data['UNITTEST/BTC']) == 99
# Load Analyze to compare the result between Backtesting function and Analyze are the same
analyze = Analyze(default_conf)
@ -341,7 +341,7 @@ def test_get_timeframe(default_conf, mocker) -> None:
)
min_date, max_date = backtesting.get_timeframe(data)
assert min_date.isoformat() == '2017-11-04T23:02:00+00:00'
assert max_date.isoformat() == '2017-11-14T22:59:00+00:00'
assert max_date.isoformat() == '2017-11-14T22:58:00+00:00'
def test_generate_text_table(default_conf, mocker):
@ -478,7 +478,7 @@ def test_processed(default_conf, mocker) -> None:
def test_backtest_pricecontours(default_conf, fee, mocker) -> None:
mocker.patch('freqtrade.optimize.backtesting.exchange.get_fee', fee)
tests = [['raise', 17], ['lower', 0], ['sine', 17]]
tests = [['raise', 17], ['lower', 0], ['sine', 16]]
for [contour, numres] in tests:
simple_backtest(default_conf, contour, numres, mocker)

View File

@ -46,7 +46,7 @@ def test_analyze_object() -> None:
def test_dataframe_correct_length(result):
dataframe = Analyze.parse_ticker_dataframe(result)
assert len(result.index) == len(dataframe.index)
assert len(result.index) - 1 == len(dataframe.index) # last partial candle removed
def test_dataframe_correct_columns(result):
@ -188,4 +188,4 @@ def test_tickerdata_to_dataframe(default_conf) -> None:
tick = load_tickerdata_file(None, 'UNITTEST/BTC', '1m', timerange=timerange)
tickerlist = {'UNITTEST/BTC': tick}
data = analyze.tickerdata_to_dataframe(tickerlist)
assert len(data['UNITTEST/BTC']) == 100
assert len(data['UNITTEST/BTC']) == 99 # partial candle was removed

View File

@ -174,3 +174,19 @@ def test_parse_args_hyperopt_custom() -> None:
assert call_args.subparser == 'hyperopt'
assert call_args.spaces == ['buy']
assert call_args.func is not None
def test_testdata_dl_options() -> None:
args = [
'--pairs-file', 'file_with_pairs',
'--export', 'export/folder',
'--days', '30',
'--exchange', 'binance'
]
arguments = Arguments(args, '')
arguments.testdata_dl_options()
args = arguments.parse_args()
assert args.pairs_file == 'file_with_pairs'
assert args.export == 'export/folder'
assert args.days == 30
assert args.exchange == 'binance'

View File

@ -85,7 +85,7 @@ def test_load_config_max_open_trades_zero(default_conf, mocker, caplog) -> None:
assert log_has('Validating configuration ...', caplog.record_tuples)
def test_load_config_file_exception(mocker, caplog) -> None:
def test_load_config_file_exception(mocker) -> None:
"""
Test Configuration._load_config_file() method
"""
@ -95,12 +95,8 @@ def test_load_config_file_exception(mocker, caplog) -> None:
)
configuration = Configuration(Namespace())
with pytest.raises(SystemExit):
with pytest.raises(OperationalException, match=r'.*Config file "somefile" not found!*'):
configuration._load_config_file('somefile')
assert log_has(
'Config file "somefile" not found. Please create your config file',
caplog.record_tuples
)
def test_load_config(default_conf, mocker) -> None:

View File

@ -9,7 +9,7 @@ import pytest
from requests.exceptions import RequestException
from freqtrade.fiat_convert import CryptoFiat, CryptoToFiatConverter
from freqtrade.tests.conftest import patch_coinmarketcap
from freqtrade.tests.conftest import log_has, patch_coinmarketcap
def test_pair_convertion_object():
@ -90,6 +90,13 @@ def test_fiat_convert_find_price(mocker):
assert fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='EUR') == 13000.2
def test_fiat_convert_unsupported_crypto(mocker, caplog):
mocker.patch('freqtrade.fiat_convert.CryptoToFiatConverter._cryptomap', return_value=[])
fiat_convert = CryptoToFiatConverter()
assert fiat_convert._find_price(crypto_symbol='CRYPTO_123', fiat_symbol='EUR') == 0.0
assert log_has('unsupported crypto-symbol CRYPTO_123 - returning 0.0', caplog.record_tuples)
def test_fiat_convert_get_price(mocker):
api_mock = MagicMock(return_value={
'price_usd': 28000.0,
@ -161,7 +168,8 @@ def test_fiat_init_network_exception(mocker):
fiat_convert._cryptomap = {}
fiat_convert._load_cryptomap()
assert len(fiat_convert._cryptomap) == 0
length_cryptomap = len(fiat_convert._cryptomap)
assert length_cryptomap == 0
def test_fiat_convert_without_network():
@ -175,3 +183,22 @@ def test_fiat_convert_without_network():
assert fiat_convert._coinmarketcap is None
assert fiat_convert._find_price(crypto_symbol='BTC', fiat_symbol='USD') == 0.0
CryptoToFiatConverter._coinmarketcap = cmc_temp
def test_convert_amount(mocker):
mocker.patch('freqtrade.fiat_convert.CryptoToFiatConverter.get_price', return_value=12345.0)
fiat_convert = CryptoToFiatConverter()
result = fiat_convert.convert_amount(
crypto_amount=1.23,
crypto_symbol="BTC",
fiat_symbol="USD"
)
assert result == 15184.35
result = fiat_convert.convert_amount(
crypto_amount=1.23,
crypto_symbol="BTC",
fiat_symbol="BTC"
)
assert result == 1.23

View File

@ -569,8 +569,10 @@ def test_process_maybe_execute_sell(mocker, default_conf, limit_buy_order, caplo
trade.open_fee = 0.001
assert not freqtrade.process_maybe_execute_sell(trade)
# Test amount not modified by fee-logic
assert not log_has('Applying fee to amount for Trade {} from 90.99181073 to 90.81'.format(
trade), caplog.record_tuples)
assert not log_has(
'Applying fee to amount for Trade {} from 90.99181073 to 90.81'.format(trade),
caplog.record_tuples
)
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount', return_value=90.81)
# test amount modified by fee-logic
@ -581,6 +583,38 @@ def test_process_maybe_execute_sell(mocker, default_conf, limit_buy_order, caplo
# Assert we call handle_trade() if trade is feasible for execution
assert freqtrade.process_maybe_execute_sell(trade)
regexp = re.compile('Found open order for.*')
assert filter(regexp.match, caplog.record_tuples)
def test_process_maybe_execute_sell_exception(mocker, default_conf,
limit_buy_order, caplog) -> None:
"""
Test the exceptions in process_maybe_execute_sell()
"""
freqtrade = get_patched_freqtradebot(mocker, default_conf)
mocker.patch('freqtrade.freqtradebot.exchange.get_order', return_value=limit_buy_order)
trade = MagicMock()
trade.open_order_id = '123'
trade.open_fee = 0.001
# Test raise of OperationalException exception
mocker.patch(
'freqtrade.freqtradebot.FreqtradeBot.get_real_amount',
side_effect=OperationalException()
)
freqtrade.process_maybe_execute_sell(trade)
assert log_has('could not update trade amount: ', caplog.record_tuples)
# Test raise of DependencyException exception
mocker.patch(
'freqtrade.freqtradebot.FreqtradeBot.get_real_amount',
side_effect=DependencyException()
)
freqtrade.process_maybe_execute_sell(trade)
assert log_has('Unable to sell trade: ', caplog.record_tuples)
def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, fee, mocker) -> None:
"""
@ -1355,7 +1389,7 @@ def test_get_real_amount_no_trade(default_conf, buy_order_fee, caplog, mocker):
caplog.record_tuples)
def test_get_real_amount_stake(default_conf, trades_for_order, buy_order_fee, caplog, mocker):
def test_get_real_amount_stake(default_conf, trades_for_order, buy_order_fee, mocker):
"""
Test get_real_amount - fees in Stake currency
"""
@ -1507,3 +1541,28 @@ def test_get_real_amount_invalid(default_conf, trades_for_order, buy_order_fee,
freqtrade = FreqtradeBot(default_conf)
# Amount does not change
assert freqtrade.get_real_amount(trade, buy_order_fee) == amount
def test_get_real_amount_open_trade(default_conf, mocker):
"""
Test get_real_amount condition trade.fee_open == 0 or order['status'] == 'open'
"""
patch_get_signal(mocker)
patch_RPCManager(mocker)
patch_coinmarketcap(mocker)
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
amount = 12345
trade = Trade(
pair='LTC/ETH',
amount=amount,
exchange='binance',
open_rate=0.245441,
open_order_id="123456"
)
order = {
'id': 'mocked_order',
'amount': amount,
'status': 'open',
}
freqtrade = FreqtradeBot(default_conf)
assert freqtrade.get_real_amount(trade, order) == amount

View File

@ -7,6 +7,7 @@ from unittest.mock import MagicMock
import pytest
from freqtrade import OperationalException
from freqtrade.main import main, set_loggers
from freqtrade.tests.conftest import log_has
@ -60,7 +61,7 @@ def test_set_loggers() -> None:
assert value2 is logging.INFO
def test_main(mocker, caplog) -> None:
def test_main_fatal_exception(mocker, default_conf, caplog) -> None:
"""
Test main() function
In this test we are skipping the while True loop by throwing an exception.
@ -68,26 +69,74 @@ def test_main(mocker, caplog) -> None:
mocker.patch.multiple(
'freqtrade.freqtradebot.FreqtradeBot',
_init_modules=MagicMock(),
worker=MagicMock(
side_effect=KeyboardInterrupt
),
worker=MagicMock(side_effect=Exception),
clean=MagicMock(),
)
mocker.patch(
'freqtrade.configuration.Configuration._load_config_file',
lambda *args, **kwargs: default_conf
)
mocker.patch('freqtrade.freqtradebot.CryptoToFiatConverter', MagicMock())
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
args = ['-c', 'config.json.example']
# Test Main + the KeyboardInterrupt exception
with pytest.raises(SystemExit) as pytest_wrapped_e:
main(args)
log_has('Starting freqtrade', caplog.record_tuples)
log_has('Got SIGINT, aborting ...', caplog.record_tuples)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 42
# Test the BaseException case
mocker.patch(
'freqtrade.freqtradebot.FreqtradeBot.worker',
MagicMock(side_effect=BaseException)
)
with pytest.raises(SystemExit):
main(args)
log_has('Got fatal exception!', caplog.record_tuples)
assert log_has('Using config: config.json.example ...', caplog.record_tuples)
assert log_has('Fatal exception!', caplog.record_tuples)
def test_main_keyboard_interrupt(mocker, default_conf, caplog) -> None:
"""
Test main() function
In this test we are skipping the while True loop by throwing an exception.
"""
mocker.patch.multiple(
'freqtrade.freqtradebot.FreqtradeBot',
_init_modules=MagicMock(),
worker=MagicMock(side_effect=KeyboardInterrupt),
clean=MagicMock(),
)
mocker.patch(
'freqtrade.configuration.Configuration._load_config_file',
lambda *args, **kwargs: default_conf
)
mocker.patch('freqtrade.freqtradebot.CryptoToFiatConverter', MagicMock())
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
args = ['-c', 'config.json.example']
# Test Main + the KeyboardInterrupt exception
with pytest.raises(SystemExit):
main(args)
assert log_has('Using config: config.json.example ...', caplog.record_tuples)
assert log_has('SIGINT received, aborting ...', caplog.record_tuples)
def test_main_operational_exception(mocker, default_conf, caplog) -> None:
"""
Test main() function
In this test we are skipping the while True loop by throwing an exception.
"""
mocker.patch.multiple(
'freqtrade.freqtradebot.FreqtradeBot',
_init_modules=MagicMock(),
worker=MagicMock(side_effect=OperationalException('Oh snap!')),
clean=MagicMock(),
)
mocker.patch(
'freqtrade.configuration.Configuration._load_config_file',
lambda *args, **kwargs: default_conf
)
mocker.patch('freqtrade.freqtradebot.CryptoToFiatConverter', MagicMock())
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
args = ['-c', 'config.json.example']
# Test Main + the KeyboardInterrupt exception
with pytest.raises(SystemExit):
main(args)
assert log_has('Using config: config.json.example ...', caplog.record_tuples)
assert log_has('Oh snap!', caplog.record_tuples)

View File

@ -39,7 +39,7 @@ def test_datesarray_to_datetimearray(ticker_history):
assert dates[0].minute == 50
date_len = len(dates)
assert date_len == 3
assert date_len == 2
def test_common_datearray(default_conf) -> None:

View File

@ -1,5 +1,4 @@
if [ ! -f "ta-lib/CHANGELOG.TXT" ]; then
curl -O -L http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz
tar zxvf ta-lib-0.4.0-src.tar.gz
cd ta-lib && ./configure && make && sudo make install && cd ..
else

View File

@ -1,4 +1,4 @@
ccxt==1.14.155
ccxt==1.14.160
SQLAlchemy==1.2.8
python-telegram-bot==10.1.0
arrow==0.12.1

View File

@ -93,7 +93,7 @@ def plot_profit(args: Namespace) -> None:
'Impossible to load the strategy. Please check the file "user_data/strategies/%s.py"',
config.get('strategy')
)
exit(0)
exit(1)
# Load the profits results
try:
@ -104,7 +104,7 @@ def plot_profit(args: Namespace) -> None:
logger.critical(
'File "backtest-result.json" not found. This script require backtesting '
'results to run.\nPlease run a backtesting with the parameter --export.')
exit(0)
exit(1)
# Take pairs from the cli otherwise switch to the pair in the config file
if args.pair:

View File

@ -5,3 +5,6 @@ max-complexity = 12
[mypy]
ignore_missing_imports = True
[mypy-freqtrade.tests.*]
ignore_errors = True

BIN
ta-lib-0.4.0-src.tar.gz Normal file

Binary file not shown.