def test_strategy_override_use_sell_signal(caplog, default_conf): caplog.set_level(logging.INFO) default_conf.update({ 'strategy': 'DefaultStrategy', }) resolver = StrategyResolver(default_conf) assert resolver.strategy.use_sell_signal assert isinstance(resolver.strategy.use_sell_signal, bool) # must be inserted to configuration assert 'use_sell_signal' in default_conf['ask_strategy'] assert default_conf['ask_strategy']['use_sell_signal'] default_conf.update({ 'strategy': 'DefaultStrategy', 'ask_strategy': { 'use_sell_signal': False, }, }) resolver = StrategyResolver(default_conf) assert not resolver.strategy.use_sell_signal assert isinstance(resolver.strategy.use_sell_signal, bool) assert log_has( "Override strategy 'use_sell_signal' with value in config file: False.", caplog)
def test_strategy_override_use_sell_profit_only(caplog, default_conf): caplog.set_level(logging.INFO) default_conf.update({ 'strategy': 'DefaultStrategy', }) resolver = StrategyResolver(default_conf) assert not resolver.strategy.sell_profit_only assert isinstance(resolver.strategy.sell_profit_only, bool) # must be inserted to configuration assert 'sell_profit_only' in default_conf['experimental'] assert not default_conf['experimental']['sell_profit_only'] default_conf.update({ 'strategy': 'DefaultStrategy', 'experimental': { 'sell_profit_only': True, }, }) resolver = StrategyResolver(default_conf) assert resolver.strategy.sell_profit_only assert isinstance(resolver.strategy.sell_profit_only, bool) assert log_has( "Override strategy 'sell_profit_only' with value in config file: True.", caplog)
def __init__(self, config: Dict[str, Any]) -> None: self.config = config # Reset keys for backtesting self.config['exchange']['key'] = '' self.config['exchange']['secret'] = '' self.config['exchange']['password'] = '' self.config['exchange']['uid'] = '' self.config['dry_run'] = True self.strategylist: List[IStrategy] = [] exchange_name = self.config.get('exchange', {}).get('name', 'bittrex').title() self.exchange = ExchangeResolver(exchange_name, self.config).exchange self.fee = self.exchange.get_fee() 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): # Force one interval self.ticker_interval = str(self.config.get('ticker_interval')) self.ticker_interval_mins = timeframe_to_minutes( self.ticker_interval) for strat in list(self.config['strategy_list']): stratconf = deepcopy(self.config) stratconf['strategy'] = strat self.strategylist.append(StrategyResolver(stratconf).strategy) else: # only one strategy self.strategylist.append(StrategyResolver(self.config).strategy) # Load one strategy self._set_strategy(self.strategylist[0])
def __init__(self, config: Dict[str, Any]) -> None: self.config = config # Reset keys for backtesting self.config['exchange']['key'] = '' self.config['exchange']['secret'] = '' self.config['exchange']['password'] = '' self.config['exchange']['uid'] = '' self.config['dry_run'] = True self.strategylist: List[IStrategy] = [] self.exchange = ExchangeResolver(self.config['exchange']['name'], self.config).exchange self.fee = self.exchange.get_fee() 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(stratconf).strategy) else: # No strategy list specified, only one strategy self.strategylist.append(StrategyResolver(self.config).strategy) # Load one (first) strategy self._set_strategy(self.strategylist[0])
def test_strategy_override_use_sell_profit_only(caplog): caplog.set_level(logging.INFO) config = { 'strategy': 'DefaultStrategy', } resolver = StrategyResolver(config) assert not resolver.strategy.sell_profit_only assert isinstance(resolver.strategy.sell_profit_only, bool) # must be inserted to configuration assert 'sell_profit_only' in config['experimental'] assert not config['experimental']['sell_profit_only'] config = { 'strategy': 'DefaultStrategy', 'experimental': { 'sell_profit_only': True, }, } resolver = StrategyResolver(config) assert resolver.strategy.sell_profit_only assert isinstance(resolver.strategy.sell_profit_only, bool) assert ('freqtrade.resolvers.strategy_resolver', logging.INFO, "Override strategy 'sell_profit_only' with value in config file: True." ) in caplog.record_tuples
def test_strategy_override_order_types(caplog): caplog.set_level(logging.INFO) order_types = { 'buy': 'market', 'sell': 'limit', 'stoploss': 'limit', 'stoploss_on_exchange': True, } config = {'strategy': 'DefaultStrategy', 'order_types': order_types} resolver = StrategyResolver(config) assert resolver.strategy.order_types for method in ['buy', 'sell', 'stoploss', 'stoploss_on_exchange']: assert resolver.strategy.order_types[method] == order_types[method] assert ('freqtrade.resolvers.strategy_resolver', logging.INFO, "Override strategy 'order_types' with value in config file:" " {'buy': 'market', 'sell': 'limit', 'stoploss': 'limit'," " 'stoploss_on_exchange': True}.") in caplog.record_tuples config = {'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(config)
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 }) resolver = StrategyResolver(default_conf) assert resolver.strategy.order_types for method in ['buy', 'sell', 'stoploss', 'stoploss_on_exchange']: assert resolver.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(default_conf)
def __init__(self, config: Dict[str, Any]) -> None: self.config = config # Reset keys for backtesting self.config['exchange']['key'] = '' self.config['exchange']['secret'] = '' self.config['exchange']['password'] = '' self.config['exchange']['uid'] = '' self.config['dry_run'] = True self.strategylist: List[IStrategy] = [] if self.config.get('strategy_list', None): # Force one interval self.ticker_interval = str(self.config.get('ticker_interval')) self.ticker_interval_mins = constants.TICKER_INTERVAL_MINUTES[ self.ticker_interval] for strat in list(self.config['strategy_list']): stratconf = deepcopy(self.config) stratconf['strategy'] = strat self.strategylist.append(StrategyResolver(stratconf).strategy) else: # only one strategy self.strategylist.append(StrategyResolver(self.config).strategy) # Load one strategy self._set_strategy(self.strategylist[0]) self.exchange = Exchange(self.config) self.fee = self.exchange.get_fee()
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 }) resolver = StrategyResolver(default_conf) assert resolver.strategy.order_time_in_force for method in ['buy', 'sell']: assert resolver.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(default_conf)
def test_strategy_override_order_tif(caplog): caplog.set_level(logging.INFO) order_time_in_force = { 'buy': 'fok', 'sell': 'gtc', } config = { 'strategy': 'DefaultStrategy', 'order_time_in_force': order_time_in_force } resolver = StrategyResolver(config) assert resolver.strategy.order_time_in_force for method in ['buy', 'sell']: assert resolver.strategy.order_time_in_force[method] == order_time_in_force[method] assert ('freqtrade.resolvers.strategy_resolver', logging.INFO, "Override strategy 'order_time_in_force' with value in config file:" " {'buy': 'fok', 'sell': 'gtc'}." ) in caplog.record_tuples config = { '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(config)
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 __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 analyse_and_plot_pairs(config: Dict[str, Any]): plot_elements = init_plotscript(config) trades = plot_elements['trades'] strategy = StrategyResolver(config).strategy pair_counter = 0 plots = [] for pair, data in plot_elements["tickers"].items(): pair_counter += 1 logger.info("analyse pair %s", pair) tickers = {} tickers[pair] = data dataframe = strategy.analyze_ticker(tickers[pair], {'pair': pair}) trades_pair = trades.loc[trades['pair'] == pair] trades_pair = extract_trades_of_period(dataframe, trades_pair) plots.append( analyze_results(pair=pair, data=dataframe, trades=trades_pair, indicators1=parse_indicators( config['indicators1'] if 'indicators1' in config.keys() else None), indicators2=parse_indicators( config['indicators2'] if 'indicators2' in config.keys() else None))) logger.info('End of ploting process %s plots generated', pair_counter) return plots
def test_load_not_found_strategy(): strategy = StrategyResolver() 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={})
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_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(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(default_conf)
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_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 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_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_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_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)
def __init__(self, config: Dict[str, Any]) -> None: """ Init all variables and objects the bot needs to work :param config: configuration dict, you can use Configuration.get_config() to get the config dict. """ logger.info('Starting freqtrade %s', __version__) # Init bot state self.state = State.STOPPED # Init objects self.config = config self._heartbeat_msg = 0 self.heartbeat_interval = self.config.get('internals', {}).get( 'heartbeat_interval', 60) self.strategy: IStrategy = StrategyResolver(self.config).strategy # Check config consistency here since strategies can set certain options validate_config_consistency(config) self.exchange = ExchangeResolver(self.config['exchange']['name'], self.config).exchange self.wallets = Wallets(self.config, self.exchange) self.dataprovider = DataProvider(self.config, self.exchange) # Attach Dataprovider to Strategy baseclass IStrategy.dp = self.dataprovider # Attach Wallets to Strategy baseclass IStrategy.wallets = self.wallets self.pairlists = PairListManager(self.exchange, self.config) # 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 = self._refresh_whitelist() persistence.init(self.config.get('db_url', None), clean_open_orders=self.config.get('dry_run', False)) # Set initial bot state from config initial_state = self.config.get('initial_state') self.state = State[ initial_state.upper()] if initial_state else State.STOPPED # RPC runs in separate threads, can start handling external commands just after # initialization, even before Freqtradebot has a chance to start its throttling, # so anything in the Freqtradebot instance should be ready (initialized), including # the initial state of the bot. # Keep this at the end of this initialization method. self.rpc: RPCManager = RPCManager(self)
def test_strategy_override_stoploss(caplog, default_conf): caplog.set_level(logging.INFO) default_conf.update({'strategy': 'DefaultStrategy', 'stoploss': -0.5}) resolver = StrategyResolver(default_conf) assert resolver.strategy.stoploss == -0.5 assert log_has( "Override strategy 'stoploss' with value in config file: -0.5.", caplog)
def test_strategy_override_stoploss(caplog): caplog.set_level(logging.INFO) config = {'strategy': 'DefaultStrategy', 'stoploss': -0.5} resolver = StrategyResolver(config) assert resolver.strategy.stoploss == -0.5 assert ('freqtrade.resolvers.strategy_resolver', logging.INFO, "Override strategy 'stoploss' with value in config file: -0.5." ) in caplog.record_tuples
def test_load_strategy(default_conf, result): default_conf.update({ 'strategy': 'SampleStrategy', 'strategy_path': str(Path(__file__).parents[2] / 'freqtrade/templates') }) resolver = StrategyResolver(default_conf) assert 'rsi' in resolver.strategy.advise_indicators( result, {'pair': 'ETH/BTC'})
def test_strategy_override_minimal_roi(caplog): caplog.set_level(logging.INFO) config = {'strategy': 'DefaultStrategy', 'minimal_roi': {"0": 0.5}} resolver = StrategyResolver(config) assert resolver.strategy.minimal_roi[0] == 0.5 assert ( 'freqtrade.resolvers.strategy_resolver', logging.INFO, "Override strategy 'minimal_roi' with value in config file: {'0': 0.5}." ) in caplog.record_tuples
def test_strategy_override_trailing_stop(caplog, default_conf): caplog.set_level(logging.INFO) default_conf.update({'strategy': 'DefaultStrategy', 'trailing_stop': True}) resolver = StrategyResolver(default_conf) assert resolver.strategy.trailing_stop assert isinstance(resolver.strategy.trailing_stop, bool) assert log_has( "Override strategy 'trailing_stop' with value in config file: True.", caplog)
def test_load_strategy_base64(result, caplog, default_conf): with open("user_data/strategies/sample_strategy.py", "rb") as file: encoded_string = urlsafe_b64encode(file.read()).decode("utf-8") default_conf.update({'strategy': 'SampleStrategy:{}'.format(encoded_string)}) resolver = StrategyResolver(default_conf) assert 'rsi' in resolver.strategy.advise_indicators(result, {'pair': 'ETH/BTC'}) # Make sure strategy was loaded from base64 (using temp directory)!! assert log_has_re(r"Using resolved strategy SampleStrategy from '" r".*(/|\\).*(/|\\)SampleStrategy\.py'\.\.\.", caplog)