Switch from pair(str) to metadata(dict)
This commit is contained in:
@@ -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)
|
||||
|
@@ -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
|
||||
"""
|
||||
|
@@ -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[
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user