Switch from pair(str) to metadata(dict)

This commit is contained in:
Matthias
2018-07-29 20:36:03 +02:00
parent 941879dc19
commit 787d6042de
7 changed files with 64 additions and 57 deletions

View File

@@ -230,7 +230,7 @@ class Backtesting(object):
pair_data['buy'], pair_data['sell'] = 0, 0 # cleanup from previous run
ticker_data = self.advise_sell(
self.advise_buy(pair_data, pair), pair)[headers].copy()
self.advise_buy(pair_data, {'pair': pair}), {'pair': pair})[headers].copy()
# to avoid using data from future, we buy/sell with signal from previous candle
ticker_data.loc[:, 'buy'] = ticker_data['buy'].shift(1)

View File

@@ -75,7 +75,7 @@ class Hyperopt(Backtesting):
return arg_dict
@staticmethod
def populate_indicators(dataframe: DataFrame, pair: str) -> DataFrame:
def populate_indicators(dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['adx'] = ta.ADX(dataframe)
macd = ta.MACD(dataframe)
dataframe['macd'] = macd['macd']
@@ -228,7 +228,7 @@ class Hyperopt(Backtesting):
"""
Define the buy strategy parameters to be used by hyperopt
"""
def populate_buy_trend(dataframe: DataFrame, pair: str) -> DataFrame:
def populate_buy_trend(dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Buy strategy Hyperopt will build and use
"""

View File

@@ -28,7 +28,7 @@ class DefaultStrategy(IStrategy):
# Optimal ticker interval for the strategy
ticker_interval = '5m'
def populate_indicators(self, dataframe: DataFrame, pair: str) -> DataFrame:
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Adds several different TA indicators to the given DataFrame
@@ -36,7 +36,7 @@ class DefaultStrategy(IStrategy):
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.
:param dataframe: Raw data from the exchange and parsed by parse_ticker_dataframe()
:param pair: Pair currently analyzed
:param metadata: Additional information, like the currently traded pair
:return: a Dataframe with all mandatory indicators for the strategies
"""
@@ -199,11 +199,11 @@ class DefaultStrategy(IStrategy):
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, pair: str) -> DataFrame:
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on TA indicators, populates the buy signal for the given dataframe
:param dataframe: DataFrame
:param pair: Pair currently analyzed
:param metadata: Additional information, like the currently traded pair
:return: DataFrame with buy column
"""
dataframe.loc[
@@ -221,11 +221,11 @@ class DefaultStrategy(IStrategy):
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, pair: str) -> DataFrame:
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on TA indicators, populates the sell signal for the given dataframe
:param dataframe: DataFrame
:param pair: Pair currently analyzed
:param metadata: Additional information, like the currently traded pair
:return: DataFrame with buy column
"""
dataframe.loc[

View File

@@ -74,29 +74,29 @@ class IStrategy(ABC):
self.config = config
@abstractmethod
def populate_indicators(self, dataframe: DataFrame, pair: str) -> DataFrame:
def populate_indicators(self, 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()
:param pair: Pair currently analyzed
:param metadata: Additional information, like the currently traded pair
:return: a Dataframe with all mandatory indicators for the strategies
"""
@abstractmethod
def populate_buy_trend(self, dataframe: DataFrame, pair: str) -> DataFrame:
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on TA indicators, populates the buy signal for the given dataframe
:param dataframe: DataFrame
:param pair: Pair currently analyzed
:param metadata: Additional information, like the currently traded pair
:return: DataFrame with buy column
"""
@abstractmethod
def populate_sell_trend(self, dataframe: DataFrame, pair: str) -> DataFrame:
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on TA indicators, populates the sell signal for the given dataframe
:param dataframe: DataFrame
:param pair: Pair currently analyzed
:param metadata: Additional information, like the currently traded pair
:return: DataFrame with sell column
"""
@@ -106,16 +106,16 @@ class IStrategy(ABC):
"""
return self.__class__.__name__
def analyze_ticker(self, ticker_history: List[Dict], pair: str) -> DataFrame:
def analyze_ticker(self, ticker_history: List[Dict], metadata: dict) -> DataFrame:
"""
Parses the given ticker history and returns a populated DataFrame
add several TA indicators and buy signal to it
:return DataFrame with ticker data and indicator data
"""
dataframe = parse_ticker_dataframe(ticker_history)
dataframe = self.advise_indicators(dataframe, pair)
dataframe = self.advise_buy(dataframe, pair)
dataframe = self.advise_sell(dataframe, pair)
dataframe = self.advise_indicators(dataframe, metadata)
dataframe = self.advise_buy(dataframe, metadata)
dataframe = self.advise_sell(dataframe, metadata)
return dataframe
def get_signal(self, pair: str, interval: str, ticker_hist: List[Dict]) -> Tuple[bool, bool]:
@@ -130,7 +130,7 @@ class IStrategy(ABC):
return False, False
try:
dataframe = self.analyze_ticker(ticker_hist, pair)
dataframe = self.analyze_ticker(ticker_hist, {'pair': pair})
except ValueError as error:
logger.warning(
'Unable to analyze ticker for pair %s: %s',
@@ -275,15 +275,15 @@ class IStrategy(ABC):
"""
Creates a dataframe and populates indicators for given ticker data
"""
return {pair: self.advise_indicators(parse_ticker_dataframe(pair_data), pair)
return {pair: self.advise_indicators(parse_ticker_dataframe(pair_data), {'pair': pair})
for pair, pair_data in tickerdata.items()}
def advise_indicators(self, dataframe: DataFrame, pair: str) -> DataFrame:
def advise_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Populate indicators that will be used in the Buy and Sell strategy
This method should not be overridden.
:param dataframe: Raw data from the exchange and parsed by parse_ticker_dataframe()
:param pair: The currently traded pair
:param metadata: Additional information, like the currently traded pair
:return: a Dataframe with all mandatory indicators for the strategies
"""
if self._populate_fun_len == 2:
@@ -291,14 +291,14 @@ class IStrategy(ABC):
"the current function headers!", DeprecationWarning)
return self.populate_indicators(dataframe) # type: ignore
else:
return self.populate_indicators(dataframe, pair)
return self.populate_indicators(dataframe, metadata)
def advise_buy(self, dataframe: DataFrame, pair: str) -> DataFrame:
def advise_buy(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on TA indicators, populates the buy signal for the given dataframe
This method should not be overridden.
:param dataframe: DataFrame
:param pair: The currently traded pair
:param pair: Additional information, like the currently traded pair
:return: DataFrame with buy column
"""
if self._buy_fun_len == 2:
@@ -306,14 +306,14 @@ class IStrategy(ABC):
"the current function headers!", DeprecationWarning)
return self.populate_buy_trend(dataframe) # type: ignore
else:
return self.populate_buy_trend(dataframe, pair)
return self.populate_buy_trend(dataframe, metadata)
def advise_sell(self, dataframe: DataFrame, pair: str) -> DataFrame:
def advise_sell(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on TA indicators, populates the sell signal for the given dataframe
This method should not be overridden.
:param dataframe: DataFrame
:param pair: The currently traded pair
:param pair: Additional information, like the currently traded pair
:return: DataFrame with sell column
"""
if self._sell_fun_len == 2:
@@ -321,4 +321,4 @@ class IStrategy(ABC):
"the current function headers!", DeprecationWarning)
return self.populate_sell_trend(dataframe) # type: ignore
else:
return self.populate_sell_trend(dataframe, pair)
return self.populate_sell_trend(dataframe, metadata)

View File

@@ -60,10 +60,7 @@ def test_search_strategy():
def test_load_strategy(result):
resolver = StrategyResolver({'strategy': 'TestStrategy'})
pair = 'ETH/BTC'
assert len(resolver.strategy.populate_indicators.__annotations__) == 3
assert 'dataframe' in resolver.strategy.populate_indicators.__annotations__
assert 'pair' in resolver.strategy.populate_indicators.__annotations__
assert 'adx' in resolver.strategy.advise_indicators(result, pair=pair)
assert 'adx' in resolver.strategy.advise_indicators(result, metadata=pair)
def test_load_strategy_invalid_directory(result, caplog):
@@ -92,7 +89,7 @@ def test_strategy(result):
config = {'strategy': 'DefaultStrategy'}
resolver = StrategyResolver(config)
pair = 'ETH/BTC'
metadata = {'pair': 'ETH/BTC'}
assert resolver.strategy.minimal_roi[0] == 0.04
assert config["minimal_roi"]['0'] == 0.04
@@ -102,13 +99,13 @@ def test_strategy(result):
assert resolver.strategy.ticker_interval == '5m'
assert config['ticker_interval'] == '5m'
df_indicators = resolver.strategy.advise_indicators(result, pair=pair)
df_indicators = resolver.strategy.advise_indicators(result, metadata=metadata)
assert 'adx' in df_indicators
dataframe = resolver.strategy.advise_buy(df_indicators, pair=pair)
dataframe = resolver.strategy.advise_buy(df_indicators, metadata=metadata)
assert 'buy' in dataframe.columns
dataframe = resolver.strategy.advise_sell(df_indicators, pair='ETH/BTC')
dataframe = resolver.strategy.advise_sell(df_indicators, metadata=metadata)
assert 'sell' in dataframe.columns
@@ -196,21 +193,21 @@ def test_call_deprecated_function(result, monkeypatch):
default_location = path.join(path.dirname(path.realpath(__file__)))
resolver = StrategyResolver({'strategy': 'TestStrategyLegacy',
'strategy_path': default_location})
pair = 'ETH/BTC'
metadata = {'pair': 'ETH/BTC'}
# Make sure we are using a legacy function
assert resolver.strategy._populate_fun_len == 2
assert resolver.strategy._buy_fun_len == 2
assert resolver.strategy._sell_fun_len == 2
indicator_df = resolver.strategy.advise_indicators(result, pair=pair)
indicator_df = resolver.strategy.advise_indicators(result, metadata=metadata)
assert type(indicator_df) is DataFrame
assert 'adx' in indicator_df.columns
buydf = resolver.strategy.advise_buy(result, pair=pair)
buydf = resolver.strategy.advise_buy(result, metadata=metadata)
assert type(buydf) is DataFrame
assert 'buy' in buydf.columns
selldf = resolver.strategy.advise_sell(result, pair=pair)
selldf = resolver.strategy.advise_sell(result, metadata=metadata)
assert type(selldf) is DataFrame
assert 'sell' in selldf