Improve tests for backtest protections
This commit is contained in:
parent
5849d07497
commit
effc96e92b
@ -121,8 +121,8 @@ The base-class provides an instance of the exchange (`self._exchange`) the pairl
|
||||
self._pairlist_pos = pairlist_pos
|
||||
```
|
||||
|
||||
!!! Note
|
||||
You'll need to register your pairlist in `constants.py` under the variable `AVAILABLE_PAIRLISTS` - otherwise it will not be selectable.
|
||||
!!! Tip
|
||||
Don't forget to register your pairlist in `constants.py` under the variable `AVAILABLE_PAIRLISTS` - otherwise it will not be selectable.
|
||||
|
||||
Now, let's step through the methods which require actions:
|
||||
|
||||
@ -184,6 +184,7 @@ No protection should use datetime directly, but use the provided `date_now` vari
|
||||
|
||||
!!! Tip "Writing a new Protection"
|
||||
Best copy one of the existing Protections to have a good example.
|
||||
Don't forget to register your protection in `constants.py` under the variable `AVAILABLE_PROTECTIONS` - otherwise it will not be selectable.
|
||||
|
||||
#### Implementation of a new protection
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
## Protections
|
||||
|
||||
!!! Warning "Beta feature"
|
||||
This feature is still in it's testing phase. Should you notice something you think is wrong please let us know via Discord, Slack or via Issue.
|
||||
This feature is still in it's testing phase. Should you notice something you think is wrong please let us know via Discord, Slack or via Github Issue.
|
||||
|
||||
Protections will protect your strategy from unexpected events and market conditions by temporarily stop trading for either one pair, or for all pairs.
|
||||
All protection end times are rounded up to the next candle to avoid sudden, unexpected intra-candle buys.
|
||||
@ -13,7 +13,7 @@ All protection end times are rounded up to the next candle to avoid sudden, unex
|
||||
Each Protection can be configured multiple times with different parameters, to allow different levels of protection (short-term / long-term).
|
||||
|
||||
!!! Note "Backtesting"
|
||||
Protections are supported by backtesting and hyperopt, but must be enabled by using the `--enable-protections` flag.
|
||||
Protections are supported by backtesting and hyperopt, but must be explicitly enabled by using the `--enable-protections` flag.
|
||||
|
||||
### Available Protections
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
from typing import Callable
|
||||
from cachetools import TTLCache, cached
|
||||
|
||||
|
@ -1,2 +0,0 @@
|
||||
# flake8: noqa: F401
|
||||
# from freqtrade.plugins.protectionmanager import ProtectionManager
|
@ -3,8 +3,6 @@ import logging
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any, Dict
|
||||
|
||||
from sqlalchemy import and_, or_
|
||||
|
||||
from freqtrade.persistence import Trade
|
||||
from freqtrade.plugins.protections import IProtection, ProtectionReturn
|
||||
from freqtrade.strategy.interface import SellType
|
||||
|
@ -79,7 +79,7 @@ def load_data_test(what, testdatadir):
|
||||
fill_missing=True)}
|
||||
|
||||
|
||||
def simple_backtest(config, contour, num_results, mocker, testdatadir) -> None:
|
||||
def simple_backtest(config, contour, mocker, testdatadir) -> None:
|
||||
patch_exchange(mocker)
|
||||
config['timeframe'] = '1m'
|
||||
backtesting = Backtesting(config)
|
||||
@ -98,7 +98,7 @@ def simple_backtest(config, contour, num_results, mocker, testdatadir) -> None:
|
||||
enable_protections=config.get('enable_protections', False),
|
||||
)
|
||||
# results :: <class 'pandas.core.frame.DataFrame'>
|
||||
assert len(results) == num_results
|
||||
return results
|
||||
|
||||
|
||||
# FIX: fixturize this?
|
||||
@ -532,23 +532,9 @@ def test_processed(default_conf, mocker, testdatadir) -> None:
|
||||
assert col in cols
|
||||
|
||||
|
||||
def test_backtest_pricecontours(default_conf, fee, mocker, testdatadir) -> None:
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
tests = [
|
||||
['sine', 35],
|
||||
['raise', 19],
|
||||
['lower', 0],
|
||||
['sine', 35],
|
||||
['raise', 19]
|
||||
]
|
||||
# While buy-signals are unrealistic, running backtesting
|
||||
# over and over again should not cause different results
|
||||
for [contour, numres] in tests:
|
||||
simple_backtest(default_conf, contour, numres, mocker, testdatadir)
|
||||
|
||||
|
||||
def test_backtest_pricecontours_protections(default_conf, fee, mocker, testdatadir) -> None:
|
||||
# TODO: Evaluate usefullness of this, the patterns and buy-signls are unrealistic
|
||||
# While this test IS a copy of test_backtest_pricecontours, it's needed to ensure
|
||||
# results do not carry-over to the next run, which is not given by using parametrize.
|
||||
default_conf['protections'] = [
|
||||
{
|
||||
"method": "CooldownPeriod",
|
||||
@ -567,7 +553,31 @@ def test_backtest_pricecontours_protections(default_conf, fee, mocker, testdatad
|
||||
# While buy-signals are unrealistic, running backtesting
|
||||
# over and over again should not cause different results
|
||||
for [contour, numres] in tests:
|
||||
simple_backtest(default_conf, contour, numres, mocker, testdatadir)
|
||||
assert len(simple_backtest(default_conf, contour, mocker, testdatadir)) == numres
|
||||
|
||||
|
||||
@pytest.mark.parametrize('protections,contour,expected', [
|
||||
(None, 'sine', 35),
|
||||
(None, 'raise', 19),
|
||||
(None, 'lower', 0),
|
||||
(None, 'sine', 35),
|
||||
(None, 'raise', 19),
|
||||
([{"method": "CooldownPeriod", "stop_duration": 3}], 'sine', 9),
|
||||
([{"method": "CooldownPeriod", "stop_duration": 3}], 'raise', 10),
|
||||
([{"method": "CooldownPeriod", "stop_duration": 3}], 'lower', 0),
|
||||
([{"method": "CooldownPeriod", "stop_duration": 3}], 'sine', 9),
|
||||
([{"method": "CooldownPeriod", "stop_duration": 3}], 'raise', 10),
|
||||
])
|
||||
def test_backtest_pricecontours(default_conf, fee, mocker, testdatadir,
|
||||
protections, contour, expected) -> None:
|
||||
if protections:
|
||||
default_conf['protections'] = protections
|
||||
default_conf['enable_protections'] = True
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
# While buy-signals are unrealistic, running backtesting
|
||||
# over and over again should not cause different results
|
||||
assert len(simple_backtest(default_conf, contour, mocker, testdatadir)) == expected
|
||||
|
||||
|
||||
def test_backtest_clash_buy_sell(mocker, default_conf, testdatadir):
|
||||
|
@ -76,7 +76,8 @@ def test_generate_backtest_stats(default_conf, testdatadir):
|
||||
"sell_reason": [SellType.ROI, SellType.STOP_LOSS,
|
||||
SellType.ROI, SellType.FORCE_SELL]
|
||||
}),
|
||||
'config': default_conf}
|
||||
'config': default_conf,
|
||||
'locks': []}
|
||||
}
|
||||
timerange = TimeRange.parse_timerange('1510688220-1510700340')
|
||||
min_date = Arrow.fromtimestamp(1510688220)
|
||||
|
@ -1,5 +1,5 @@
|
||||
import random
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user