Merge branch 'develop' into pairlocks_direction

This commit is contained in:
Matthias
2022-05-01 14:59:04 +02:00
64 changed files with 637 additions and 547 deletions

View File

@@ -0,0 +1,30 @@
# type: ignore
from pandas import DataFrame
from freqtrade.strategy import IStrategy
# Dummy strategy - no longer loads but raises an exception.
class TestStrategyLegacyV1(IStrategy):
minimal_roi = {
"40": 0.0,
"30": 0.01,
"20": 0.02,
"0": 0.04
}
stoploss = -0.10
timeframe = '5m'
def populate_indicators(self, dataframe: DataFrame) -> DataFrame:
return dataframe
def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame:
return dataframe
def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame:
return dataframe

View File

@@ -1,85 +0,0 @@
# --- Do not remove these libs ---
# Add your lib to import here
import talib.abstract as ta
from pandas import DataFrame
from freqtrade.strategy import IStrategy
# --------------------------------
# This class is a sample. Feel free to customize it.
class TestStrategyLegacyV1(IStrategy):
"""
This is a test strategy using the legacy function headers, which will be
removed in a future update.
Please do not use this as a template, but refer to user_data/strategy/sample_strategy.py
for a uptodate version of this template.
"""
# Minimal ROI designed for the strategy.
# This attribute will be overridden if the config file contains "minimal_roi"
minimal_roi = {
"40": 0.0,
"30": 0.01,
"20": 0.02,
"0": 0.04
}
# Optimal stoploss designed for the strategy
# This attribute will be overridden if the config file contains "stoploss"
stoploss = -0.10
timeframe = '5m'
def populate_indicators(self, dataframe: DataFrame) -> DataFrame:
"""
Adds several different TA indicators to the given DataFrame
Performance Note: For the best performance be frugal on the number of indicators
you are using. Let uncomment only the indicator you are using in your strategies
or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
"""
# Momentum Indicator
# ------------------------------------
# ADX
dataframe['adx'] = ta.ADX(dataframe)
# TEMA - Triple Exponential Moving Average
dataframe['tema'] = ta.TEMA(dataframe, timeperiod=9)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame:
"""
Based on TA indicators, populates the buy signal for the given dataframe
:param dataframe: DataFrame
:return: DataFrame with buy column
"""
dataframe.loc[
(
(dataframe['adx'] > 30) &
(dataframe['tema'] > dataframe['tema'].shift(1)) &
(dataframe['volume'] > 0)
),
'buy'] = 1
return dataframe
def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame:
"""
Based on TA indicators, populates the sell signal for the given dataframe
:param dataframe: DataFrame
:return: DataFrame with buy column
"""
dataframe.loc[
(
(dataframe['adx'] > 70) &
(dataframe['tema'] < dataframe['tema'].shift(1)) &
(dataframe['volume'] > 0)
),
'sell'] = 1
return dataframe

View File

@@ -56,19 +56,6 @@ class StrategyTestV2(IStrategy):
# By default this strategy does not use Position Adjustments
position_adjustment_enable = False
def informative_pairs(self):
"""
Define additional, informative pair/interval combinations to be cached from the exchange.
These pair/interval combinations are non-tradeable, unless they are part
of the whitelist as well.
For more information, please consult the documentation
:return: List of tuples in the format (pair, interval)
Sample: return [("ETH/USDT", "5m"),
("BTC/USDT", "15m"),
]
"""
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Adds several different TA indicators to the given DataFrame

View File

@@ -82,6 +82,11 @@ class StrategyTestV3(IStrategy):
# })
# return prot
bot_started = False
def bot_start(self):
self.bot_started = True
def informative_pairs(self):
return []

View File

@@ -686,7 +686,7 @@ def test_is_pair_locked(default_conf):
def test_is_informative_pairs_callback(default_conf):
default_conf.update({'strategy': 'TestStrategyLegacyV1'})
default_conf.update({'strategy': 'StrategyTestV2'})
strategy = StrategyResolver.load_strategy(default_conf)
# Should return empty
# Uses fallback to base implementation

View File

@@ -1,6 +1,5 @@
# pragma pylint: disable=missing-docstring, protected-access, C0103
import logging
import warnings
from base64 import urlsafe_b64encode
from pathlib import Path
@@ -35,7 +34,7 @@ def test_search_all_strategies_no_failed():
directory = Path(__file__).parent / "strats"
strategies = StrategyResolver.search_all_objects(directory, enum_failed=False)
assert isinstance(strategies, list)
assert len(strategies) == 6
assert len(strategies) == 5
assert isinstance(strategies[0], dict)
@@ -43,10 +42,10 @@ def test_search_all_strategies_with_failed():
directory = Path(__file__).parent / "strats"
strategies = StrategyResolver.search_all_objects(directory, enum_failed=True)
assert isinstance(strategies, list)
assert len(strategies) == 7
assert len(strategies) == 6
# with enum_failed=True search_all_objects() shall find 2 good strategies
# and 1 which fails to load
assert len([x for x in strategies if x['class'] is not None]) == 6
assert len([x for x in strategies if x['class'] is not None]) == 5
assert len([x for x in strategies if x['class'] is None]) == 1
@@ -100,7 +99,7 @@ def test_load_strategy_noname(default_conf):
@pytest.mark.filterwarnings("ignore:deprecated")
@pytest.mark.parametrize('strategy_name', ['StrategyTestV2', 'TestStrategyLegacyV1'])
@pytest.mark.parametrize('strategy_name', ['StrategyTestV2'])
def test_strategy_pre_v3(result, default_conf, strategy_name):
default_conf.update({'strategy': strategy_name})
@@ -346,40 +345,6 @@ def test_strategy_override_use_exit_profit_only(caplog, default_conf):
assert log_has("Override strategy 'exit_profit_only' with value in config file: True.", caplog)
@pytest.mark.filterwarnings("ignore:deprecated")
def test_deprecate_populate_indicators(result, default_conf):
default_location = Path(__file__).parent / "strats"
default_conf.update({'strategy': 'TestStrategyLegacyV1',
'strategy_path': default_location})
strategy = StrategyResolver.load_strategy(default_conf)
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
indicators = strategy.advise_indicators(result, {'pair': 'ETH/BTC'})
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated - check out the Sample strategy to see the current function headers!" \
in str(w[-1].message)
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
strategy.advise_entry(indicators, {'pair': 'ETH/BTC'})
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated - check out the Sample strategy to see the current function headers!" \
in str(w[-1].message)
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
strategy.advise_exit(indicators, {'pair': 'ETH_BTC'})
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated - check out the Sample strategy to see the current function headers!" \
in str(w[-1].message)
@pytest.mark.filterwarnings("ignore:deprecated")
def test_missing_implements(default_conf, caplog):
@@ -438,33 +403,14 @@ def test_missing_implements(default_conf, caplog):
StrategyResolver.load_strategy(default_conf)
@pytest.mark.filterwarnings("ignore:deprecated")
def test_call_deprecated_function(result, default_conf, caplog):
default_location = Path(__file__).parent / "strats"
def test_call_deprecated_function(default_conf):
default_location = Path(__file__).parent / "strats/broken_strats/"
del default_conf['timeframe']
default_conf.update({'strategy': 'TestStrategyLegacyV1',
'strategy_path': default_location})
strategy = StrategyResolver.load_strategy(default_conf)
metadata = {'pair': 'ETH/BTC'}
# Make sure we are using a legacy function
assert strategy._populate_fun_len == 2
assert strategy._buy_fun_len == 2
assert strategy._sell_fun_len == 2
assert strategy.INTERFACE_VERSION == 1
assert strategy.timeframe == '5m'
indicator_df = strategy.advise_indicators(result, metadata=metadata)
assert isinstance(indicator_df, DataFrame)
assert 'adx' in indicator_df.columns
enterdf = strategy.advise_entry(result, metadata=metadata)
assert isinstance(enterdf, DataFrame)
assert 'enter_long' in enterdf.columns
exitdf = strategy.advise_exit(result, metadata=metadata)
assert isinstance(exitdf, DataFrame)
assert 'exit_long' in exitdf
with pytest.raises(OperationalException,
match=r"Strategy Interface v1 is no longer supported.*"):
StrategyResolver.load_strategy(default_conf)
def test_strategy_interface_versioning(result, default_conf):
@@ -472,10 +418,6 @@ def test_strategy_interface_versioning(result, default_conf):
strategy = StrategyResolver.load_strategy(default_conf)
metadata = {'pair': 'ETH/BTC'}
# Make sure we are using a legacy function
assert strategy._populate_fun_len == 3
assert strategy._buy_fun_len == 3
assert strategy._sell_fun_len == 3
assert strategy.INTERFACE_VERSION == 2
indicator_df = strategy.advise_indicators(result, metadata=metadata)