def test_strategy_override_order_tif(caplog, default_conf): caplog.set_level(logging.INFO) order_time_in_force = { 'buy': 'fok', 'sell': 'gtc', } default_conf.update({ 'strategy': 'DefaultStrategy', 'order_time_in_force': order_time_in_force }) strategy = StrategyResolver.load_strategy(default_conf) assert strategy.order_time_in_force for method in ['buy', 'sell']: assert strategy.order_time_in_force[method] == order_time_in_force[ method] assert log_has( "Override strategy 'order_time_in_force' with value in config file:" " {'buy': 'fok', 'sell': 'gtc'}.", caplog) default_conf.update({ 'strategy': 'DefaultStrategy', 'order_time_in_force': { 'buy': 'fok' } }) # Raise error for invalid configuration with pytest.raises(ImportError, match=r"Impossible to load Strategy 'DefaultStrategy'. " r"Order-time-in-force mapping is incomplete."): StrategyResolver.load_strategy(default_conf)
def test_load_strategy_noname(default_conf): default_conf['strategy'] = '' with pytest.raises( OperationalException, match="No strategy set. Please use `--strategy` to specify " "the strategy class to use."): StrategyResolver.load_strategy(default_conf)
def test_load_not_found_strategy(default_conf): default_conf['strategy'] = 'NotFoundStrategy' with pytest.raises( OperationalException, match=r"Impossible to load Strategy 'NotFoundStrategy'. " r"This class does not exist or contains Python code errors."): StrategyResolver.load_strategy(default_conf)
def test_strategy_override_order_types(caplog, default_conf): caplog.set_level(logging.INFO) order_types = { 'buy': 'market', 'sell': 'limit', 'stoploss': 'limit', 'stoploss_on_exchange': True, } default_conf.update({ 'strategy': 'DefaultStrategy', 'order_types': order_types }) strategy = StrategyResolver.load_strategy(default_conf) assert strategy.order_types for method in ['buy', 'sell', 'stoploss', 'stoploss_on_exchange']: assert strategy.order_types[method] == order_types[method] assert log_has( "Override strategy 'order_types' with value in config file:" " {'buy': 'market', 'sell': 'limit', 'stoploss': 'limit'," " 'stoploss_on_exchange': True}.", caplog) default_conf.update({ 'strategy': 'DefaultStrategy', 'order_types': { 'buy': 'market' } }) # Raise error for invalid configuration with pytest.raises(ImportError, match=r"Impossible to load Strategy 'DefaultStrategy'. " r"Order-types mapping is incomplete."): StrategyResolver.load_strategy(default_conf)
def test_load_not_found_strategy(default_conf): strategy = StrategyResolver(default_conf) with pytest.raises( OperationalException, match=r"Impossible to load Strategy 'NotFoundStrategy'. " r"This class does not exist or contains Python code errors."): strategy._load_strategy(strategy_name='NotFoundStrategy', config=default_conf)
def test_load_strategy_invalid_directory(result, caplog, default_conf): resolver = StrategyResolver(default_conf) extra_dir = Path.cwd() / 'some/path' resolver._load_strategy('SampleStrategy', config=default_conf, extra_dir=extra_dir) assert log_has_re(r'Path .*' + r'some.*path.*' + r'.* does not exist', caplog) assert 'adx' in resolver.strategy.advise_indicators(result, {'pair': 'ETH/BTC'})
def test_load_strategy_invalid_directory(result, caplog, default_conf): default_conf['strategy'] = 'DefaultStrategy' extra_dir = Path.cwd() / 'some/path' with pytest.raises(OperationalException): StrategyResolver._load_strategy('DefaultStrategy', config=default_conf, extra_dir=extra_dir) assert log_has_re(r'Path .*' + r'some.*path.*' + r'.* does not exist', caplog)
def test_search_strategy(): default_location = Path(__file__).parent / 'strats' s, _ = StrategyResolver._search_object(directory=default_location, object_name='DefaultStrategy') assert issubclass(s, IStrategy) s, _ = StrategyResolver._search_object(directory=default_location, object_name='NotFoundStrategy') assert s is None
def __init__(self, config: Dict[str, Any]) -> None: self.config = config # Reset keys for backtesting remove_credentials(self.config) self.strategylist: List[IStrategy] = [] self.exchange = ExchangeResolver.load_exchange( self.config['exchange']['name'], self.config) self.pairlists = PairListManager(self.exchange, self.config) if 'VolumePairList' in self.pairlists.name_list: raise OperationalException( "VolumePairList not allowed for backtesting.") self.pairlists.refresh_pairlist() if len(self.pairlists.whitelist) == 0: raise OperationalException("No pair in whitelist.") if config.get('fee'): self.fee = config['fee'] else: self.fee = self.exchange.get_fee( symbol=self.pairlists.whitelist[0]) if self.config.get('runmode') != RunMode.HYPEROPT: self.dataprovider = DataProvider(self.config, self.exchange) IStrategy.dp = self.dataprovider if self.config.get('strategy_list', None): for strat in list(self.config['strategy_list']): stratconf = deepcopy(self.config) stratconf['strategy'] = strat self.strategylist.append( StrategyResolver.load_strategy(stratconf)) validate_config_consistency(stratconf) else: # No strategy list specified, only one strategy self.strategylist.append( StrategyResolver.load_strategy(self.config)) validate_config_consistency(self.config) if "ticker_interval" not in self.config: raise OperationalException( "Timeframe (ticker interval) needs to be set in either " "configuration or as cli argument `--ticker-interval 5m`") self.timeframe = str(self.config.get('ticker_interval')) self.timeframe_min = timeframe_to_minutes(self.timeframe) # Get maximum required startup period self.required_startup = max( [strat.startup_candle_count for strat in self.strategylist]) # Load one (first) strategy self._set_strategy(self.strategylist[0])
def test_load_strategy_invalid_directory(result, caplog): resolver = StrategyResolver() extra_dir = path.join('some', 'path') resolver._load_strategy('TestStrategy', config={}, extra_dir=extra_dir) assert ( 'freqtrade.resolvers.strategy_resolver', logging.WARNING, 'Path "{}" does not exist'.format(extra_dir), ) in caplog.record_tuples assert 'adx' in resolver.strategy.advise_indicators(result, {'pair': 'ETH/BTC'})
def test_auto_hyperopt_interface_loadparams(default_conf, mocker, caplog): default_conf.update({'strategy': 'HyperoptableStrategy'}) del default_conf['stoploss'] del default_conf['minimal_roi'] mocker.patch.object(Path, 'is_file', MagicMock(return_value=True)) mocker.patch.object(Path, 'open') expected_result = { "strategy_name": "HyperoptableStrategy", "params": { "stoploss": { "stoploss": -0.05, }, "roi": { "0": 0.2, "1200": 0.01 } } } mocker.patch('freqtrade.strategy.hyper.json_load', return_value=expected_result) PairLocks.timeframe = default_conf['timeframe'] strategy = StrategyResolver.load_strategy(default_conf) assert strategy.stoploss == -0.05 assert strategy.minimal_roi == {0: 0.2, 1200: 0.01} expected_result = { "strategy_name": "HyperoptableStrategy_No", "params": { "stoploss": { "stoploss": -0.05, }, "roi": { "0": 0.2, "1200": 0.01 } } } mocker.patch('freqtrade.strategy.hyper.json_load', return_value=expected_result) with pytest.raises(OperationalException, match="Invalid parameter file provided."): StrategyResolver.load_strategy(default_conf) mocker.patch('freqtrade.strategy.hyper.json_load', MagicMock(side_effect=ValueError())) StrategyResolver.load_strategy(default_conf) assert log_has("Invalid parameter file format.", caplog)
def test_search_strategy(): default_config = {} default_location = Path(__file__).parent.parent.joinpath( 'strategy').resolve() assert isinstance( StrategyResolver._search_object(directory=default_location, object_type=IStrategy, kwargs={'config': default_config}, object_name='DefaultStrategy'), IStrategy) assert StrategyResolver._search_object( directory=default_location, object_type=IStrategy, kwargs={'config': default_config}, object_name='NotFoundStrategy') is None
def __init__(self, config: Dict[str, Any]) -> None: """ Init all variables and object the bot need to work :param config: configuration dict, you can use the Configuration.get_config() method to get the config dict. """ logger.info( 'Starting freqtrade %s', __version__, ) # Init bot states self.state = State.STOPPED # Init objects self.config = config self.strategy: IStrategy = StrategyResolver(self.config).strategy self.rpc: RPCManager = RPCManager(self) self.persistence = None self.exchange = Exchange(self.config) self.wallets = Wallets(self.exchange) pairlistname = self.config.get('pairlist', {}).get('method', 'StaticPairList') self.pairlists = PairListResolver(pairlistname, self, self.config).pairlist # Initializing Edge only if enabled self.edge = Edge(self.config, self.exchange, self.strategy) if \ self.config.get('edge', {}).get('enabled', False) else None self.active_pair_whitelist: List[str] = self.config['exchange'][ 'pair_whitelist'] self._init_modules()
def start_list_strategies(args: Dict[str, Any]) -> None: """ Print files with Strategy custom classes available in the directory """ config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) directory = Path( config.get('strategy_path', config['user_data_dir'] / USERPATH_STRATEGIES)) strategy_objs = StrategyResolver.search_all_objects( directory, not args['print_one_column'], config.get('recursive_strategy_search', False)) # Sort alphabetically strategy_objs = sorted(strategy_objs, key=lambda x: x['name']) for obj in strategy_objs: if obj['class']: obj['hyperoptable'] = obj['class'].detect_all_parameters() else: obj['hyperoptable'] = {'count': 0} if args['print_one_column']: print('\n'.join([s['name'] for s in strategy_objs])) else: _print_objs_tabular(strategy_objs, config.get('print_colorized', False), directory)
def get_trading_env(args: Namespace): """ Initalize freqtrade Exchange and Strategy, split pairs recieved in parameter :return: Strategy """ global _CONF # Load the configuration _CONF.update(setup_configuration(args)) print(_CONF) pairs = args.pairs.split(',') if pairs is None: logger.critical('Parameter --pairs mandatory;. E.g --pairs ETH/BTC,XRP/BTC') exit() # Load the strategy try: strategy = StrategyResolver(_CONF).strategy exchange = Exchange(_CONF) except AttributeError: logger.critical( 'Impossible to load the strategy. Please check the file "user_data/strategies/%s.py"', args.strategy ) exit() return [strategy, exchange, pairs]
def test_auto_hyperopt_interface(default_conf): default_conf.update({'strategy': 'HyperoptableStrategy'}) PairLocks.timeframe = default_conf['timeframe'] strategy = StrategyResolver.load_strategy(default_conf) with pytest.raises(OperationalException): next(strategy.enumerate_parameters('deadBeef')) assert strategy.buy_rsi.value == strategy.buy_params['buy_rsi'] # PlusDI is NOT in the buy-params, so default should be used assert strategy.buy_plusdi.value == 0.5 assert strategy.sell_rsi.value == strategy.sell_params['sell_rsi'] assert repr(strategy.sell_rsi) == 'IntParameter(74)' # Parameter is disabled - so value from sell_param dict will NOT be used. assert strategy.sell_minusdi.value == 0.5 all_params = strategy.detect_all_parameters() assert isinstance(all_params, dict) assert len(all_params['buy']) == 2 assert len(all_params['sell']) == 2 # Number of Hyperoptable parameters assert all_params['count'] == 6 strategy.__class__.sell_rsi = IntParameter([0, 10], default=5, space='buy') with pytest.raises(OperationalException, match=r"Inconclusive parameter.*"): [x for x in strategy.detect_parameters('sell')]
def test_is_pair_locked(default_conf): default_conf.update({'strategy': 'DefaultStrategy'}) strategy = StrategyResolver.load_strategy(default_conf) # dict should be empty assert not strategy._pair_locked_until pair = 'ETH/BTC' assert not strategy.is_pair_locked(pair) strategy.lock_pair(pair, arrow.utcnow().shift(minutes=4).datetime) # ETH/BTC locked for 4 minutes assert strategy.is_pair_locked(pair) # Test lock does not change lock = strategy._pair_locked_until[pair] strategy.lock_pair(pair, arrow.utcnow().shift(minutes=2).datetime) assert lock == strategy._pair_locked_until[pair] # XRP/BTC should not be locked now pair = 'XRP/BTC' assert not strategy.is_pair_locked(pair) # Unlocking a pair that's not locked should not raise an error strategy.unlock_pair(pair) # Unlock original pair pair = 'ETH/BTC' strategy.unlock_pair(pair) assert not strategy.is_pair_locked(pair)
def test_load_strategy_byte64(result): with open("freqtrade/tests/strategy/test_strategy.py", "r") as file: encoded_string = urlsafe_b64encode( file.read().encode("utf-8")).decode("utf-8") resolver = StrategyResolver( {'strategy': 'TestStrategy:{}'.format(encoded_string)}) assert 'adx' in resolver.strategy.advise_indicators(result, 'ETH/BTC')
def test_min_roi_reached2(default_conf, fee) -> None: # test with ROI raising after last interval min_roi_list = [ { 20: 0.07, 30: 0.05, 55: 0.30, 0: 0.1 }, { 0: 0.1, 20: 0.07, 30: 0.05, 55: 0.30 }, ] for roi in min_roi_list: default_conf.update({'strategy': 'DefaultStrategy'}) strategy = StrategyResolver.load_strategy(default_conf) strategy.minimal_roi = roi trade = Trade( pair='ETH/BTC', stake_amount=0.001, amount=5, open_date=arrow.utcnow().shift(hours=-1).datetime, fee_open=fee.return_value, fee_close=fee.return_value, exchange='bittrex', open_rate=1, ) assert not strategy.min_roi_reached( trade, 0.02, arrow.utcnow().shift(minutes=-56).datetime) assert strategy.min_roi_reached( trade, 0.12, arrow.utcnow().shift(minutes=-56).datetime) assert not strategy.min_roi_reached( trade, 0.04, arrow.utcnow().shift(minutes=-39).datetime) assert strategy.min_roi_reached( trade, 0.071, arrow.utcnow().shift(minutes=-39).datetime) assert not strategy.min_roi_reached( trade, 0.04, arrow.utcnow().shift(minutes=-26).datetime) assert strategy.min_roi_reached( trade, 0.06, arrow.utcnow().shift(minutes=-26).datetime) # Should not trigger with 20% profit since after 55 minutes only 30% is active. assert not strategy.min_roi_reached( trade, 0.20, arrow.utcnow().shift(minutes=-2).datetime) assert strategy.min_roi_reached( trade, 0.31, arrow.utcnow().shift(minutes=-2).datetime)
def test_call_deprecated_function(result, monkeypatch, default_conf): default_location = path.join(path.dirname(path.realpath(__file__))) default_conf.update({ 'strategy': 'TestStrategyLegacy', 'strategy_path': default_location }) resolver = StrategyResolver(default_conf) 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 assert resolver.strategy.INTERFACE_VERSION == 1 indicator_df = resolver.strategy.advise_indicators(result, metadata=metadata) assert isinstance(indicator_df, DataFrame) assert 'adx' in indicator_df.columns buydf = resolver.strategy.advise_buy(result, metadata=metadata) assert isinstance(buydf, DataFrame) assert 'buy' in buydf.columns selldf = resolver.strategy.advise_sell(result, metadata=metadata) assert isinstance(selldf, DataFrame) assert 'sell' in selldf
def test_min_roi_reached3(default_conf, fee) -> None: # test for issue #1948 min_roi = {20: 0.07, 30: 0.05, 55: 0.30, } default_conf.update({'strategy': 'DefaultStrategy'}) strategy = StrategyResolver.load_strategy(default_conf) strategy.minimal_roi = min_roi trade = Trade( pair='ETH/BTC', stake_amount=0.001, amount=5, open_date=arrow.utcnow().shift(hours=-1).datetime, fee_open=fee.return_value, fee_close=fee.return_value, exchange='binance', open_rate=1, ) assert not strategy.min_roi_reached(trade, 0.02, arrow.utcnow().shift(minutes=-56).datetime) assert not strategy.min_roi_reached(trade, 0.12, arrow.utcnow().shift(minutes=-56).datetime) assert not strategy.min_roi_reached(trade, 0.04, arrow.utcnow().shift(minutes=-39).datetime) assert strategy.min_roi_reached(trade, 0.071, arrow.utcnow().shift(minutes=-39).datetime) assert not strategy.min_roi_reached(trade, 0.04, arrow.utcnow().shift(minutes=-26).datetime) assert strategy.min_roi_reached(trade, 0.06, arrow.utcnow().shift(minutes=-26).datetime) # Should not trigger with 20% profit since after 55 minutes only 30% is active. assert not strategy.min_roi_reached(trade, 0.20, arrow.utcnow().shift(minutes=-2).datetime) assert strategy.min_roi_reached(trade, 0.31, arrow.utcnow().shift(minutes=-2).datetime)
def test_deprecate_populate_indicators(result, default_conf): default_location = path.join(path.dirname(path.realpath(__file__))) default_conf.update({ 'strategy': 'TestStrategyLegacy', 'strategy_path': default_location }) resolver = StrategyResolver(default_conf) with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") indicators = resolver.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") resolver.strategy.advise_buy(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") resolver.strategy.advise_sell(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)
def test_add_indicators(default_conf, testdatadir, caplog): pair = "UNITTEST/BTC" timerange = TimeRange(None, 'line', 0, -1000) data = history.load_pair_history(pair=pair, timeframe='1m', datadir=testdatadir, timerange=timerange) indicators1 = {"ema10": {}} indicators2 = {"macd": {"color": "red"}} strategy = StrategyResolver.load_strategy(default_conf) # Generate buy/sell signals and indicators data = strategy.analyze_ticker(data, {'pair': pair}) fig = generate_empty_figure() # Row 1 fig1 = add_indicators(fig=deepcopy(fig), row=1, indicators=indicators1, data=data) figure = fig1.layout.figure ema10 = find_trace_in_fig_data(figure.data, "ema10") assert isinstance(ema10, go.Scatter) assert ema10.yaxis == "y" fig2 = add_indicators(fig=deepcopy(fig), row=3, indicators=indicators2, data=data) figure = fig2.layout.figure macd = find_trace_in_fig_data(figure.data, "macd") assert isinstance(macd, go.Scatter) assert macd.yaxis == "y3" assert macd.line.color == "red" # No indicator found fig3 = add_indicators(fig=deepcopy(fig), row=3, indicators={'no_indicator': {}}, data=data) assert fig == fig3 assert log_has_re(r'Indicator "no_indicator" ignored\..*', caplog)
def test_min_roi_reached(default_conf, fee) -> None: # Use list to confirm sequence does not matter min_roi_list = [{20: 0.05, 55: 0.01, 0: 0.1}, {0: 0.1, 20: 0.05, 55: 0.01}] for roi in min_roi_list: default_conf.update({'strategy': 'DefaultStrategy'}) strategy = StrategyResolver.load_strategy(default_conf) strategy.minimal_roi = roi trade = Trade( pair='ETH/BTC', stake_amount=0.001, amount=5, open_date=arrow.utcnow().shift(hours=-1).datetime, fee_open=fee.return_value, fee_close=fee.return_value, exchange='binance', open_rate=1, ) assert not strategy.min_roi_reached(trade, 0.02, arrow.utcnow().shift(minutes=-56).datetime) assert strategy.min_roi_reached(trade, 0.12, arrow.utcnow().shift(minutes=-56).datetime) assert not strategy.min_roi_reached(trade, 0.04, arrow.utcnow().shift(minutes=-39).datetime) assert strategy.min_roi_reached(trade, 0.06, arrow.utcnow().shift(minutes=-39).datetime) assert not strategy.min_roi_reached(trade, -0.01, arrow.utcnow().shift(minutes=-1).datetime) assert strategy.min_roi_reached(trade, 0.02, arrow.utcnow().shift(minutes=-1).datetime)
def test_call_deprecated_function(result, monkeypatch, default_conf, caplog): default_location = Path(__file__).parent / "strats" del default_conf['timeframe'] default_conf.update({ 'strategy': 'TestStrategyLegacy', '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' assert strategy.ticker_interval == '5m' indicator_df = strategy.advise_indicators(result, metadata=metadata) assert isinstance(indicator_df, DataFrame) assert 'adx' in indicator_df.columns buydf = strategy.advise_buy(result, metadata=metadata) assert isinstance(buydf, DataFrame) assert 'buy' in buydf.columns selldf = strategy.advise_sell(result, metadata=metadata) assert isinstance(selldf, DataFrame) assert 'sell' in selldf assert log_has( "DEPRECATED: Please migrate to using 'timeframe' instead of 'ticker_interval'.", caplog)
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) == 2 assert isinstance(strategies[0], dict)
def analyse_and_plot_pairs(config: Dict[str, Any]): """ From arguments provided in cli: -Initialise backtest env -Get tickers data -Generate Dafaframes populated with indicators and signals -Load trades excecuted on same periods -Generate Plotly plot objects -Generate plot files :return: None """ exchange = ExchangeResolver(config.get('exchange', {}).get('name'), config).exchange strategy = StrategyResolver(config).strategy if "pairs" in config: pairs = config["pairs"].split(',') else: pairs = config["exchange"]["pair_whitelist"] # Set timerange to use timerange = Arguments.parse_timerange(config["timerange"]) ticker_interval = strategy.ticker_interval tickers = history.load_data( datadir=Path(str(config.get("datadir"))), pairs=pairs, ticker_interval=config['ticker_interval'], refresh_pairs=config.get('refresh_pairs', False), timerange=timerange, exchange=exchange, live=config.get("live", False), ) pair_counter = 0 for pair, data in tickers.items(): pair_counter += 1 logger.info("analyse pair %s", pair) tickers = {} tickers[pair] = data dataframe = generate_dataframe(strategy, tickers, pair) if config["trade_source"] == "DB": trades = load_trades_from_db(config["db_url"]) elif config["trade_source"] == "file": trades = load_backtest_data(Path(config["exportfilename"])) trades = trades.loc[trades['pair'] == pair] trades = extract_trades_of_period(dataframe, trades) fig = generate_graph( pair=pair, data=dataframe, trades=trades, indicators1=config["indicators1"].split(","), indicators2=config["indicators2"].split(",") ) generate_plot_file(fig, pair, ticker_interval) logger.info('End of ploting process %s plots generated', pair_counter)
def test_add_areas(default_conf, testdatadir, caplog): pair = "UNITTEST/BTC" timerange = TimeRange(None, 'line', 0, -1000) data = history.load_pair_history(pair=pair, timeframe='1m', datadir=testdatadir, timerange=timerange) indicators = { "macd": { "color": "red", "fill_color": "black", "fill_to": "macdhist", "fill_label": "MACD Fill" } } ind_no_label = {"macd": {"fill_color": "red", "fill_to": "macdhist"}} ind_plain = {"macd": {"fill_to": "macdhist"}} default_conf.update({'strategy': 'DefaultStrategy'}) strategy = StrategyResolver.load_strategy(default_conf) # Generate buy/sell signals and indicators data = strategy.analyze_ticker(data, {'pair': pair}) fig = generate_empty_figure() # indicator mentioned in fill_to does not exist fig1 = add_areas(fig, 1, data, {'ema10': {'fill_to': 'no_fill_indicator'}}) assert fig == fig1 assert log_has_re(r'fill_to: "no_fill_indicator" ignored\..*', caplog) # indicator does not exist fig2 = add_areas(fig, 1, data, {'no_indicator': {'fill_to': 'ema10'}}) assert fig == fig2 assert log_has_re(r'Indicator "no_indicator" ignored\..*', caplog) # everythin given in plot config, row 3 fig3 = add_areas(fig, 3, data, indicators) figure = fig3.layout.figure fill_macd = find_trace_in_fig_data(figure.data, "MACD Fill") assert isinstance(fill_macd, go.Scatter) assert fill_macd.yaxis == "y3" assert fill_macd.fillcolor == "black" # label missing, row 1 fig4 = add_areas(fig, 1, data, ind_no_label) figure = fig4.layout.figure fill_macd = find_trace_in_fig_data(figure.data, "macd<>macdhist") assert isinstance(fill_macd, go.Scatter) assert fill_macd.yaxis == "y" assert fill_macd.fillcolor == "red" # fit_to only fig5 = add_areas(fig, 1, data, ind_plain) figure = fig5.layout.figure fill_macd = find_trace_in_fig_data(figure.data, "macd<>macdhist") assert isinstance(fill_macd, go.Scatter) assert fill_macd.yaxis == "y"
def test_loss_calculation_prefer_correct_trade_count(hyperopt) -> None: StrategyResolver({'strategy': 'DefaultStrategy'}) correct = hyperopt.calculate_loss(1, hyperopt.target_trades, 20) over = hyperopt.calculate_loss(1, hyperopt.target_trades + 100, 20) under = hyperopt.calculate_loss(1, hyperopt.target_trades - 100, 20) assert over > correct assert under > correct
def test_load_staticmethod_importerror(mocker, caplog): mocker.patch("freqtrade.resolvers.strategy_resolver.import_strategy", Mock( side_effect=TypeError("can't pickle staticmethod objects"))) with pytest.raises(ImportError, match=r"Impossible to load Strategy 'DefaultStrategy'." r" This class does not exist or contains Python code errors"): StrategyResolver() assert log_has_re(r".*Error: can't pickle staticmethod objects", caplog.record_tuples)