Merge branch 'develop' into align_userdata

This commit is contained in:
Matthias
2019-08-10 20:15:07 +02:00
33 changed files with 1007 additions and 368 deletions

View File

@@ -135,7 +135,7 @@ AVAILABLE_CLI_OPTIONS = {
),
"strategy_list": Arg(
'--strategy-list',
help='Provide a comma-separated list of strategies to backtest. '
help='Provide a space-separated list of strategies to backtest. '
'Please note that ticker-interval needs to be set either in config '
'or via command line. When using this together with `--export trades`, '
'the strategy-name is injected into the filename '

View File

@@ -1,9 +1,7 @@
"""
This module contains the configuration class
"""
import json
import logging
import sys
import warnings
from argparse import Namespace
from pathlib import Path
@@ -13,6 +11,7 @@ from freqtrade import OperationalException, constants
from freqtrade.configuration.check_exchange import check_exchange
from freqtrade.configuration.directory_operations import create_datadir, create_userdata_dir
from freqtrade.configuration.json_schema import validate_config_schema
from freqtrade.configuration.load_config import load_config_file
from freqtrade.loggers import setup_logging
from freqtrade.misc import deep_merge_dicts
from freqtrade.state import RunMode
@@ -53,24 +52,7 @@ class Configuration(object):
logger.info('Using config: %s ...', path)
# Merge config options, overwriting old values
config = deep_merge_dicts(self._load_config_file(path), config)
return config
def _load_config_file(self, path: str) -> Dict[str, Any]:
"""
Loads a config file from the given path
:param path: path as str
:return: configuration as dictionary
"""
try:
# Read config from stdin if requested in the options
with open(path) if path != '-' else sys.stdin as file:
config = json.load(file)
except FileNotFoundError:
raise OperationalException(
f'Config file "{path}" not found!'
' Please create a config file or check whether it exists.')
config = deep_merge_dicts(load_config_file(path), config)
return config

View File

@@ -0,0 +1,30 @@
"""
This module contain functions to load the configuration file
"""
import json
import logging
import sys
from typing import Any, Dict
from freqtrade import OperationalException
logger = logging.getLogger(__name__)
def load_config_file(path: str) -> Dict[str, Any]:
"""
Loads a config file from the given path
:param path: path as str
:return: configuration as dictionary
"""
try:
# Read config from stdin if requested in the options
with open(path) if path != '-' else sys.stdin as file:
config = json.load(file)
except FileNotFoundError:
raise OperationalException(
f'Config file "{path}" not found!'
' Please create a config file or check whether it exists.')
return config

View File

@@ -725,7 +725,8 @@ class Exchange(object):
return []
try:
# Allow 5s offset to catch slight time offsets (discovered in #1185)
my_trades = self._api.fetch_my_trades(pair, since.timestamp() - 5)
# since needs to be int in milliseconds
my_trades = self._api.fetch_my_trades(pair, int((since.timestamp() - 5) * 1000))
matched_trades = [trade for trade in my_trades if trade['order'] == order_id]
return matched_trades

View File

@@ -10,8 +10,8 @@ from pathlib import Path
from typing import Any, Dict, List, NamedTuple, Optional
from pandas import DataFrame
from tabulate import tabulate
from freqtrade import OperationalException
from freqtrade.configuration import Arguments
from freqtrade.data import history
from freqtrade.data.dataprovider import DataProvider
@@ -21,6 +21,7 @@ from freqtrade.persistence import Trade
from freqtrade.resolvers import ExchangeResolver, StrategyResolver
from freqtrade.state import RunMode
from freqtrade.strategy.interface import IStrategy, SellType
from tabulate import tabulate
logger = logging.getLogger(__name__)
@@ -88,6 +89,9 @@ class Backtesting(object):
Load strategy into backtesting
"""
self.strategy = strategy
if "ticker_interval" not in self.config:
raise OperationalException("Ticker-interval needs to be set in either configuration "
"or as cli argument `--ticker-interval 5m`")
self.ticker_interval = self.config.get('ticker_interval')
self.ticker_interval_mins = timeframe_to_minutes(self.ticker_interval)
@@ -373,7 +377,9 @@ class Backtesting(object):
continue
trade_count_lock[row.date] = trade_count_lock.get(row.date, 0) + 1
trade_entry = self._get_sell_trade_entry(pair, row, ticker[pair][indexes[pair]:],
# since indexes has been incremented before, we need to go one step back to
# also check the buying candle for sell conditions.
trade_entry = self._get_sell_trade_entry(pair, row, ticker[pair][indexes[pair]-1:],
trade_count_lock, stake_amount,
max_open_trades)

View File

@@ -5,7 +5,7 @@ from typing import Any, Callable, Dict, List
import talib.abstract as ta
from pandas import DataFrame
from skopt.space import Categorical, Dimension, Integer, Real
from skopt.space import Categorical, Dimension, Integer
import freqtrade.vendor.qtpylib.indicators as qtpylib
from freqtrade.optimize.hyperopt_interface import IHyperOpt
@@ -13,10 +13,9 @@ from freqtrade.optimize.hyperopt_interface import IHyperOpt
class DefaultHyperOpts(IHyperOpt):
"""
Default hyperopt provided by freqtrade bot.
Default hyperopt provided by the Freqtrade bot.
You can override it with your own hyperopt
"""
@staticmethod
def populate_indicators(dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['adx'] = ta.ADX(dataframe)
@@ -156,42 +155,6 @@ class DefaultHyperOpts(IHyperOpt):
'sell-sar_reversal'], name='sell-trigger')
]
@staticmethod
def generate_roi_table(params: Dict) -> Dict[int, float]:
"""
Generate the ROI table that will be used by Hyperopt
"""
roi_table = {}
roi_table[0] = params['roi_p1'] + params['roi_p2'] + params['roi_p3']
roi_table[params['roi_t3']] = params['roi_p1'] + params['roi_p2']
roi_table[params['roi_t3'] + params['roi_t2']] = params['roi_p1']
roi_table[params['roi_t3'] + params['roi_t2'] + params['roi_t1']] = 0
return roi_table
@staticmethod
def stoploss_space() -> List[Dimension]:
"""
Stoploss Value to search
"""
return [
Real(-0.5, -0.02, name='stoploss'),
]
@staticmethod
def roi_space() -> List[Dimension]:
"""
Values to search for each ROI steps
"""
return [
Integer(10, 120, name='roi_t1'),
Integer(10, 60, name='roi_t2'),
Integer(10, 40, name='roi_t3'),
Real(0.01, 0.04, name='roi_p1'),
Real(0.01, 0.07, name='roi_p2'),
Real(0.01, 0.20, name='roi_p3'),
]
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on TA indicators. Should be a copy of from strategy

View File

@@ -7,7 +7,7 @@ from abc import ABC, abstractmethod
from typing import Dict, Any, Callable, List
from pandas import DataFrame
from skopt.space import Dimension
from skopt.space import Dimension, Integer, Real
class IHyperOpt(ABC):
@@ -26,56 +26,80 @@ class IHyperOpt(ABC):
@abstractmethod
def populate_indicators(dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Populate indicators that will be used in the Buy and Sell strategy
:param dataframe: Raw data from the exchange and parsed by parse_ticker_dataframe()
:return: a Dataframe with all mandatory indicators for the strategies
Populate indicators that will be used in the Buy and Sell strategy.
:param dataframe: Raw data from the exchange and parsed by parse_ticker_dataframe().
:return: A Dataframe with all mandatory indicators for the strategies.
"""
@staticmethod
@abstractmethod
def buy_strategy_generator(params: Dict[str, Any]) -> Callable:
"""
Create a buy strategy generator
Create a buy strategy generator.
"""
@staticmethod
@abstractmethod
def sell_strategy_generator(params: Dict[str, Any]) -> Callable:
"""
Create a sell strategy generator
Create a sell strategy generator.
"""
@staticmethod
@abstractmethod
def indicator_space() -> List[Dimension]:
"""
Create an indicator space
Create an indicator space.
"""
@staticmethod
@abstractmethod
def sell_indicator_space() -> List[Dimension]:
"""
Create a sell indicator space
Create a sell indicator space.
"""
@staticmethod
@abstractmethod
def generate_roi_table(params: Dict) -> Dict[int, float]:
"""
Create an roi table
Create a ROI table.
Generates the ROI table that will be used by Hyperopt.
You may override it in your custom Hyperopt class.
"""
roi_table = {}
roi_table[0] = params['roi_p1'] + params['roi_p2'] + params['roi_p3']
roi_table[params['roi_t3']] = params['roi_p1'] + params['roi_p2']
roi_table[params['roi_t3'] + params['roi_t2']] = params['roi_p1']
roi_table[params['roi_t3'] + params['roi_t2'] + params['roi_t1']] = 0
return roi_table
@staticmethod
@abstractmethod
def stoploss_space() -> List[Dimension]:
"""
Create a stoploss space
Create a stoploss space.
Defines range of stoploss values to search.
You may override it in your custom Hyperopt class.
"""
return [
Real(-0.5, -0.02, name='stoploss'),
]
@staticmethod
@abstractmethod
def roi_space() -> List[Dimension]:
"""
Create a roi space
Create a ROI space.
Defines values to search for each ROI steps.
You may override it in your custom Hyperopt class.
"""
return [
Integer(10, 120, name='roi_t1'),
Integer(10, 60, name='roi_t2'),
Integer(10, 40, name='roi_t3'),
Real(0.01, 0.04, name='roi_p1'),
Real(0.01, 0.07, name='roi_p2'),
Real(0.01, 0.20, name='roi_p3'),
]

View File

@@ -39,7 +39,7 @@ class SharpeHyperOptLoss(IHyperOptLoss):
sharp_ratio = expected_yearly_return / np.std(total_profit) * np.sqrt(365)
else:
# Define high (negative) sharpe ratio to be clear that this is NOT optimal.
sharp_ratio = 20.
sharp_ratio = -20.
# print(expected_yearly_return, np.std(total_profit), sharp_ratio)
return -sharp_ratio

View File

@@ -45,7 +45,7 @@ def get_args(args):
def patched_configuration_load_config_file(mocker, config) -> None:
mocker.patch(
'freqtrade.configuration.configuration.Configuration._load_config_file',
'freqtrade.configuration.configuration.load_config_file',
lambda *args, **kwargs: config
)

View File

@@ -2,7 +2,7 @@
# pragma pylint: disable=protected-access
import copy
import logging
from datetime import datetime
from datetime import datetime, timezone
from random import randint
from unittest.mock import MagicMock, Mock, PropertyMock
@@ -11,8 +11,8 @@ import ccxt
import pytest
from pandas import DataFrame
from freqtrade import (DependencyException, OperationalException,
TemporaryError, InvalidOrderException)
from freqtrade import (DependencyException, InvalidOrderException,
OperationalException, TemporaryError)
from freqtrade.exchange import Binance, Exchange, Kraken
from freqtrade.exchange.exchange import API_RETRY_COUNT
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
@@ -1361,7 +1361,7 @@ def test_name(default_conf, mocker, exchange_name):
@pytest.mark.parametrize("exchange_name", EXCHANGES)
def test_get_trades_for_order(default_conf, mocker, exchange_name):
order_id = 'ABCD-ABCD'
since = datetime(2018, 5, 5)
since = datetime(2018, 5, 5, tzinfo=timezone.utc)
default_conf["dry_run"] = False
mocker.patch('freqtrade.exchange.Exchange.exchange_has', return_value=True)
api_mock = MagicMock()
@@ -1391,6 +1391,13 @@ def test_get_trades_for_order(default_conf, mocker, exchange_name):
orders = exchange.get_trades_for_order(order_id, 'LTC/BTC', since)
assert len(orders) == 1
assert orders[0]['price'] == 165
assert api_mock.fetch_my_trades.call_count == 1
# since argument should be
assert isinstance(api_mock.fetch_my_trades.call_args[0][1], int)
assert api_mock.fetch_my_trades.call_args[0][0] == 'LTC/BTC'
# Same test twice, hardcoded number and doing the same calculation
assert api_mock.fetch_my_trades.call_args[0][1] == 1525478395000
assert api_mock.fetch_my_trades.call_args[0][1] == int(since.timestamp() - 5) * 1000
ccxt_exceptionhandlers(mocker, default_conf, api_mock, exchange_name,
'get_trades_for_order', 'fetch_my_trades',

View File

@@ -14,9 +14,8 @@ from freqtrade.tests.optimize import (BTContainer, BTrade,
_get_frame_time_from_offset,
tests_ticker_interval)
# Test 0 Sell signal sell
# Test 0: Sell with signal sell in candle 3
# Test with Stop-loss at 1%
# TC0: Sell signal in candle 3
tc0 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5025, 4975, 4987, 6172, 1, 0],
@@ -29,9 +28,8 @@ tc0 = BTContainer(data=[
trades=[BTrade(sell_reason=SellType.SELL_SIGNAL, open_tick=1, close_tick=4)]
)
# Test 1 Minus 8% Close
# Test 1: Stop-Loss Triggered 1% loss
# Test with Stop-loss at 1%
# TC1: Stop-Loss Triggered 1% loss
tc1 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5025, 4975, 4987, 6172, 1, 0],
@@ -45,9 +43,8 @@ tc1 = BTContainer(data=[
)
# Test 2 Minus 4% Low, minus 1% close
# Test 2: Minus 4% Low, minus 1% close
# Test with Stop-Loss at 3%
# TC2: Stop-Loss Triggered 3% Loss
tc2 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5025, 4975, 4987, 6172, 1, 0],
@@ -61,12 +58,12 @@ tc2 = BTContainer(data=[
)
# Test 3 Candle drops 4%, Recovers 1%.
# Entry Criteria Met
# Candle drops 20%
# Test with Stop-Loss at 2%
# TC3: Trade-A: Stop-Loss Triggered 2% Loss
# Trade-B: Stop-Loss Triggered 2% Loss
# Test 3: Multiple trades.
# Candle drops 4%, Recovers 1%.
# Entry Criteria Met
# Candle drops 20%
# Trade-A: Stop-Loss Triggered 2% Loss
# Trade-B: Stop-Loss Triggered 2% Loss
tc3 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5025, 4975, 4987, 6172, 1, 0],
@@ -81,10 +78,10 @@ tc3 = BTContainer(data=[
BTrade(sell_reason=SellType.STOP_LOSS, open_tick=4, close_tick=5)]
)
# Test 4 Minus 3% / recovery +15%
# Test 4: Minus 3% / recovery +15%
# Candle Data for test 3 Candle drops 3% Closed 15% up
# Test with Stop-loss at 2% ROI 6%
# TC4: Stop-Loss Triggered 2% Loss
# Stop-Loss Triggered 2% Loss
tc4 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5025, 4975, 4987, 6172, 1, 0],
@@ -97,9 +94,8 @@ tc4 = BTContainer(data=[
trades=[BTrade(sell_reason=SellType.STOP_LOSS, open_tick=1, close_tick=2)]
)
# Test 5 / Drops 0.5% Closes +20%
# Set stop-loss at 1% ROI 3%
# TC5: ROI triggers 3% Gain
# Test 5: Drops 0.5% Closes +20%, ROI triggers 3% Gain
# stop-loss: 1%, ROI: 3%
tc5 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5025, 4980, 4987, 6172, 1, 0],
@@ -112,9 +108,8 @@ tc5 = BTContainer(data=[
trades=[BTrade(sell_reason=SellType.ROI, open_tick=1, close_tick=3)]
)
# Test 6 / Drops 3% / Recovers 6% Positive / Closes 1% positve
# Set stop-loss at 2% ROI at 5%
# TC6: Stop-Loss triggers 2% Loss
# Test 6: Drops 3% / Recovers 6% Positive / Closes 1% positve, Stop-Loss triggers 2% Loss
# stop-loss: 2% ROI: 5%
tc6 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5025, 4975, 4987, 6172, 1, 0],
@@ -127,9 +122,8 @@ tc6 = BTContainer(data=[
trades=[BTrade(sell_reason=SellType.STOP_LOSS, open_tick=1, close_tick=2)]
)
# Test 7 - 6% Positive / 1% Negative / Close 1% Positve
# Set stop-loss at 2% ROI at 3%
# TC7: ROI Triggers 3% Gain
# Test 7: 6% Positive / 1% Negative / Close 1% Positve, ROI Triggers 3% Gain
# stop-loss: 2% ROI: 3%
tc7 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5025, 4975, 4987, 6172, 1, 0],
@@ -143,9 +137,8 @@ tc7 = BTContainer(data=[
)
# Test 8 - trailing_stop should raise so candle 3 causes a stoploss.
# Set stop-loss at 10%, ROI at 10% (should not apply)
# TC8: Trailing stoploss - stoploss should be adjusted candle 2
# Test 8: trailing_stop should raise so candle 3 causes a stoploss.
# stop-loss: 10%, ROI: 10% (should not apply), stoploss adjusted in candle 2
tc8 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5050, 4950, 5000, 6172, 1, 0],
@@ -158,10 +151,8 @@ tc8 = BTContainer(data=[
)
# Test 9 - trailing_stop should raise - high and low in same candle.
# Candle Data for test 9
# Set stop-loss at 10%, ROI at 10% (should not apply)
# TC9: Trailing stoploss - stoploss should be adjusted candle 3
# Test 9: trailing_stop should raise - high and low in same candle.
# stop-loss: 10%, ROI: 10% (should not apply), stoploss adjusted in candle 3
tc9 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5050, 4950, 5000, 6172, 1, 0],
@@ -173,10 +164,9 @@ tc9 = BTContainer(data=[
trades=[BTrade(sell_reason=SellType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3)]
)
# Test 10 - trailing_stop should raise so candle 3 causes a stoploss
# Test 10: trailing_stop should raise so candle 3 causes a stoploss
# without applying trailing_stop_positive since stoploss_offset is at 10%.
# Set stop-loss at 10%, ROI at 10% (should not apply)
# TC10: Trailing stoploss - stoploss should be adjusted candle 2
# stop-loss: 10%, ROI: 10% (should not apply), stoploss adjusted candle 2
tc10 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5050, 4950, 5000, 6172, 1, 0],
@@ -190,10 +180,9 @@ tc10 = BTContainer(data=[
trades=[BTrade(sell_reason=SellType.STOP_LOSS, open_tick=1, close_tick=4)]
)
# Test 11 - trailing_stop should raise so candle 3 causes a stoploss
# Test 11: trailing_stop should raise so candle 3 causes a stoploss
# applying a positive trailing stop of 3% since stop_positive_offset is reached.
# Set stop-loss at 10%, ROI at 10% (should not apply)
# TC11: Trailing stoploss - stoploss should be adjusted candle 2,
# stop-loss: 10%, ROI: 10% (should not apply), stoploss adjusted candle 2
tc11 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5050, 4950, 5000, 6172, 1, 0],
@@ -207,10 +196,9 @@ tc11 = BTContainer(data=[
trades=[BTrade(sell_reason=SellType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3)]
)
# Test 12 - trailing_stop should raise in candle 2 and cause a stoploss in the same candle
# Test 12: trailing_stop should raise in candle 2 and cause a stoploss in the same candle
# applying a positive trailing stop of 3% since stop_positive_offset is reached.
# Set stop-loss at 10%, ROI at 10% (should not apply)
# TC12: Trailing stoploss - stoploss should be adjusted candle 2,
# stop-loss: 10%, ROI: 10% (should not apply), stoploss adjusted candle 2
tc12 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5050, 4950, 5000, 6172, 1, 0],
@@ -224,6 +212,47 @@ tc12 = BTContainer(data=[
trades=[BTrade(sell_reason=SellType.TRAILING_STOP_LOSS, open_tick=1, close_tick=2)]
)
# Test 13: Buy and sell ROI on same candle
# stop-loss: 10% (should not apply), ROI: 1%
tc13 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5050, 4950, 5000, 6172, 1, 0],
[1, 5000, 5100, 4950, 5100, 6172, 0, 0],
[2, 5100, 5251, 4850, 5100, 6172, 0, 0],
[3, 4850, 5050, 4850, 4750, 6172, 0, 0],
[4, 4750, 4950, 4850, 4750, 6172, 0, 0]],
stop_loss=-0.10, roi=0.01, profit_perc=0.01,
trades=[BTrade(sell_reason=SellType.ROI, open_tick=1, close_tick=1)]
)
# Test 14 - Buy and Stoploss on same candle
# stop-loss: 5%, ROI: 10% (should not apply)
tc14 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5050, 4950, 5000, 6172, 1, 0],
[1, 5000, 5100, 4600, 5100, 6172, 0, 0],
[2, 5100, 5251, 4850, 5100, 6172, 0, 0],
[3, 4850, 5050, 4850, 4750, 6172, 0, 0],
[4, 4750, 4950, 4350, 4750, 6172, 0, 0]],
stop_loss=-0.05, roi=0.10, profit_perc=-0.05,
trades=[BTrade(sell_reason=SellType.STOP_LOSS, open_tick=1, close_tick=1)]
)
# Test 15 - Buy and ROI on same candle, followed by buy and Stoploss on next candle
# stop-loss: 5%, ROI: 10% (should not apply)
tc15 = BTContainer(data=[
# D O H L C V B S
[0, 5000, 5050, 4950, 5000, 6172, 1, 0],
[1, 5000, 5100, 4900, 5100, 6172, 1, 0],
[2, 5100, 5251, 4650, 5100, 6172, 0, 0],
[3, 4850, 5050, 4850, 4750, 6172, 0, 0],
[4, 4750, 4950, 4350, 4750, 6172, 0, 0]],
stop_loss=-0.05, roi=0.01, profit_perc=-0.04,
trades=[BTrade(sell_reason=SellType.ROI, open_tick=1, close_tick=1),
BTrade(sell_reason=SellType.STOP_LOSS, open_tick=2, close_tick=2)]
)
TESTS = [
tc0,
tc1,
@@ -238,6 +267,9 @@ TESTS = [
tc10,
tc11,
tc12,
tc13,
tc14,
tc15,
]

View File

@@ -9,7 +9,7 @@ import pandas as pd
import pytest
from arrow import Arrow
from freqtrade import DependencyException, constants
from freqtrade import DependencyException, OperationalException, constants
from freqtrade.configuration import TimeRange
from freqtrade.data import history
from freqtrade.data.btanalysis import evaluate_result_multi
@@ -21,7 +21,8 @@ from freqtrade.optimize.backtesting import Backtesting
from freqtrade.state import RunMode
from freqtrade.strategy.default_strategy import DefaultStrategy
from freqtrade.strategy.interface import SellType
from freqtrade.tests.conftest import (get_args, log_has, log_has_re, patch_exchange,
from freqtrade.tests.conftest import (get_args, log_has, log_has_re,
patch_exchange,
patched_configuration_load_config_file)
@@ -345,6 +346,23 @@ def test_backtesting_init(mocker, default_conf, order_types) -> None:
assert not backtesting.strategy.order_types["stoploss_on_exchange"]
def test_backtesting_init_no_ticker_interval(mocker, default_conf, caplog) -> None:
"""
Check that stoploss_on_exchange is set to False while backtesting
since backtesting assumes a perfect stoploss anyway.
"""
patch_exchange(mocker)
del default_conf['ticker_interval']
default_conf['strategy_list'] = ['DefaultStrategy',
'TestStrategy']
mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.5))
with pytest.raises(OperationalException):
Backtesting(default_conf)
log_has("Ticker-interval needs to be set in either configuration "
"or as cli argument `--ticker-interval 5m`", caplog.record_tuples)
def test_tickerdata_to_dataframe_bt(default_conf, mocker) -> None:
patch_exchange(mocker)
timerange = TimeRange(None, 'line', 0, -100)
@@ -618,8 +636,9 @@ def test_processed(default_conf, mocker) -> None:
def test_backtest_pricecontours(default_conf, fee, mocker) -> None:
# TODO: Evaluate usefullness of this, the patterns and buy-signls are unrealistic
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
tests = [['raise', 19], ['lower', 0], ['sine', 18]]
tests = [['raise', 19], ['lower', 0], ['sine', 35]]
# We need to enable sell-signal - otherwise it sells on ROI!!
default_conf['experimental'] = {"use_sell_signal": True}

View File

@@ -15,6 +15,7 @@ from freqtrade.configuration import Arguments, Configuration
from freqtrade.configuration.check_exchange import check_exchange
from freqtrade.configuration.directory_operations import create_datadir, create_userdata_dir
from freqtrade.configuration.json_schema import validate_config_schema
from freqtrade.configuration.load_config import load_config_file
from freqtrade.constants import DEFAULT_DB_DRYRUN_URL, DEFAULT_DB_PROD_URL
from freqtrade.loggers import _set_loggers
from freqtrade.state import RunMode
@@ -26,8 +27,7 @@ from freqtrade.tests.conftest import (log_has, log_has_re,
def all_conf():
config_file = Path(__file__).parents[2] / "config_full.json.example"
print(config_file)
configuration = Configuration(Namespace())
conf = configuration._load_config_file(str(config_file))
conf = load_config_file(str(config_file))
return conf
@@ -54,12 +54,11 @@ def test_load_config_incorrect_stake_amount(default_conf) -> None:
def test_load_config_file(default_conf, mocker, caplog) -> None:
del default_conf['user_data_dir']
file_mock = mocker.patch('freqtrade.configuration.configuration.open', mocker.mock_open(
file_mock = mocker.patch('freqtrade.configuration.load_config.open', mocker.mock_open(
read_data=json.dumps(default_conf)
))
configuration = Configuration(Namespace())
validated_conf = configuration._load_config_file('somefile')
validated_conf = load_config_file('somefile')
assert file_mock.call_count == 1
assert validated_conf.items() >= default_conf.items()
@@ -115,7 +114,7 @@ def test_load_config_combine_dicts(default_conf, mocker, caplog) -> None:
configsmock = MagicMock(side_effect=config_files)
mocker.patch(
'freqtrade.configuration.configuration.Configuration._load_config_file',
'freqtrade.configuration.configuration.load_config_file',
configsmock
)
@@ -155,10 +154,9 @@ def test_load_config_file_exception(mocker) -> None:
'freqtrade.configuration.configuration.open',
MagicMock(side_effect=FileNotFoundError('File not found'))
)
configuration = Configuration(Namespace())
with pytest.raises(OperationalException, match=r'.*Config file "somefile" not found!*'):
configuration._load_config_file('somefile')
load_config_file('somefile')
def test_load_config(default_conf, mocker) -> None: