diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md index b9d01a236..0c45fbbf1 100644 --- a/docs/telegram-usage.md +++ b/docs/telegram-usage.md @@ -171,7 +171,7 @@ official commands. You can ask at any moment for help with `/help`. | `/profit []` | Display a summary of your profit/loss from close trades and some stats about your performance, over the last n days (all trades by default) | `/forcesell ` | Instantly sells the given trade (Ignoring `minimum_roi`). | `/forcesell all` | Instantly sells all open trades (Ignoring `minimum_roi`). -| `/forcebuy [rate]` | Instantly buys the given pair. Rate is optional. (`forcebuy_enable` must be set to True) +| `/forcebuy [rate]` | Instantly buys the given pair. Rate is optional and only applies to limit orders. (`forcebuy_enable` must be set to True) | `/performance` | Show performance of each finished trade grouped by pair | `/balance` | Show account balance per currency | `/daily ` | Shows profit or loss per day, over the last n days (n defaults to 7) diff --git a/freqtrade/optimize/hyperopt_tools.py b/freqtrade/optimize/hyperopt_tools.py index cfbc2757e..0b2efa5c2 100755 --- a/freqtrade/optimize/hyperopt_tools.py +++ b/freqtrade/optimize/hyperopt_tools.py @@ -1,4 +1,3 @@ - import io import logging from copy import deepcopy @@ -64,10 +63,11 @@ class HyperoptTools(): 'export_time': datetime.now(timezone.utc), } logger.info(f"Dumping parameters to {filename}") - rapidjson.dump(final_params, filename.open('w'), indent=2, - default=hyperopt_serializer, - number_mode=rapidjson.NM_NATIVE | rapidjson.NM_NAN - ) + with filename.open('w') as f: + rapidjson.dump(final_params, f, indent=2, + default=hyperopt_serializer, + number_mode=rapidjson.NM_NATIVE | rapidjson.NM_NAN + ) @staticmethod def try_export_params(config: Dict[str, Any], strategy_name: str, params: Dict): diff --git a/freqtrade/optimize/space/decimalspace.py b/freqtrade/optimize/space/decimalspace.py index 643999cc1..220502e69 100644 --- a/freqtrade/optimize/space/decimalspace.py +++ b/freqtrade/optimize/space/decimalspace.py @@ -7,11 +7,15 @@ class SKDecimal(Integer): def __init__(self, low, high, decimals=3, prior="uniform", base=10, transform=None, name=None, dtype=np.int64): self.decimals = decimals - _low = int(low * pow(10, self.decimals)) - _high = int(high * pow(10, self.decimals)) + + self.pow_dot_one = pow(0.1, self.decimals) + self.pow_ten = pow(10, self.decimals) + + _low = int(low * self.pow_ten) + _high = int(high * self.pow_ten) # trunc to precision to avoid points out of space - self.low_orig = round(_low * pow(0.1, self.decimals), self.decimals) - self.high_orig = round(_high * pow(0.1, self.decimals), self.decimals) + self.low_orig = round(_low * self.pow_dot_one, self.decimals) + self.high_orig = round(_high * self.pow_dot_one, self.decimals) super().__init__(_low, _high, prior, base, transform, name, dtype) @@ -25,9 +29,9 @@ class SKDecimal(Integer): return self.low_orig <= point <= self.high_orig def transform(self, Xt): - aa = [int(x * pow(10, self.decimals)) for x in Xt] - return super().transform(aa) + return super().transform([int(v * self.pow_ten) for v in Xt]) def inverse_transform(self, Xt): res = super().inverse_transform(Xt) - return [round(x * pow(0.1, self.decimals), self.decimals) for x in res] + # equivalent to [round(x * pow(0.1, self.decimals), self.decimals) for x in res] + return [int(v) / self.pow_ten for v in res] diff --git a/freqtrade/resolvers/strategy_resolver.py b/freqtrade/resolvers/strategy_resolver.py index e7c077e84..a7b95a3c5 100644 --- a/freqtrade/resolvers/strategy_resolver.py +++ b/freqtrade/resolvers/strategy_resolver.py @@ -56,17 +56,21 @@ class StrategyResolver(IResolver): if strategy._ft_params_from_file: # Set parameters from Hyperopt results file params = strategy._ft_params_from_file - strategy.minimal_roi = params.get('roi', strategy.minimal_roi) + strategy.minimal_roi = params.get('roi', getattr(strategy, 'minimal_roi', {})) - strategy.stoploss = params.get('stoploss', {}).get('stoploss', strategy.stoploss) + strategy.stoploss = params.get('stoploss', {}).get( + 'stoploss', getattr(strategy, 'stoploss', -0.1)) trailing = params.get('trailing', {}) - strategy.trailing_stop = trailing.get('trailing_stop', strategy.trailing_stop) - strategy.trailing_stop_positive = trailing.get('trailing_stop_positive', - strategy.trailing_stop_positive) + strategy.trailing_stop = trailing.get( + 'trailing_stop', getattr(strategy, 'trailing_stop', False)) + strategy.trailing_stop_positive = trailing.get( + 'trailing_stop_positive', getattr(strategy, 'trailing_stop_positive', None)) strategy.trailing_stop_positive_offset = trailing.get( - 'trailing_stop_positive_offset', strategy.trailing_stop_positive_offset) + 'trailing_stop_positive_offset', + getattr(strategy, 'trailing_stop_positive_offset', 0)) strategy.trailing_only_offset_is_reached = trailing.get( - 'trailing_only_offset_is_reached', strategy.trailing_only_offset_is_reached) + 'trailing_only_offset_is_reached', + getattr(strategy, 'trailing_only_offset_is_reached', 0.0)) # Set attributes # Check if we need to override configuration diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 846747f40..073583940 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -1033,7 +1033,8 @@ class Telegram(RPCHandler): :return: None """ forcebuy_text = ("*/forcebuy []:* `Instantly buys the given pair. " - "Optionally takes a rate at which to buy.` \n") + "Optionally takes a rate at which to buy " + "(only applies to limit orders).` \n") message = ("*/start:* `Starts the trader`\n" "*/stop:* `Stops the trader`\n" "*/status |[table]:* `Lists all open trades`\n" diff --git a/freqtrade/strategy/hyper.py b/freqtrade/strategy/hyper.py index dad282d7e..eaf41263a 100644 --- a/freqtrade/strategy/hyper.py +++ b/freqtrade/strategy/hyper.py @@ -381,7 +381,8 @@ class HyperStrategyMixin(object): if filename.is_file(): logger.info(f"Loading parameters from file {filename}") try: - params = json_load(filename.open('r')) + with filename.open('r') as f: + params = json_load(f) if params.get('strategy_name') != self.__class__.__name__: raise OperationalException('Invalid parameter file provided.') return params diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 547d9313f..0bbfc8906 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -65,9 +65,9 @@ class IStrategy(ABC, HyperStrategyMixin): _populate_fun_len: int = 0 _buy_fun_len: int = 0 _sell_fun_len: int = 0 - _ft_params_from_file: Dict = {} + _ft_params_from_file: Dict # associated minimal roi - minimal_roi: Dict + minimal_roi: Dict = {} # associated stoploss stoploss: float diff --git a/requirements.txt b/requirements.txt index b10bbabf6..f242fb9b1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,18 +1,18 @@ -numpy==1.21.2 +numpy==1.21.3 pandas==1.3.4 pandas-ta==0.3.14b -ccxt==1.58.47 +ccxt==1.59.2 # Pin cryptography for now due to rust build errors with piwheels cryptography==35.0.0 aiohttp==3.7.4.post0 -SQLAlchemy==1.4.25 +SQLAlchemy==1.4.26 python-telegram-bot==13.7 -arrow==1.2.0 +arrow==1.2.1 cachetools==4.2.2 requests==2.26.0 urllib3==1.26.7 -jsonschema==4.1.0 +jsonschema==4.1.2 TA-Lib==0.4.21 technical==1.3.0 tabulate==0.8.9 @@ -41,4 +41,4 @@ psutil==5.8.0 colorama==0.4.4 # Building config files interactively questionary==1.10.0 -prompt-toolkit==3.0.20 +prompt-toolkit==3.0.21 diff --git a/tests/optimize/test_hyperopt_tools.py b/tests/optimize/test_hyperopt_tools.py index 9c2b2e8fc..d9a52db39 100644 --- a/tests/optimize/test_hyperopt_tools.py +++ b/tests/optimize/test_hyperopt_tools.py @@ -209,7 +209,8 @@ def test_export_params(tmpdir): assert filename.is_file() - content = rapidjson.load(filename.open('r')) + with filename.open('r') as f: + content = rapidjson.load(f) assert content['strategy_name'] == 'StrategyTestV2' assert 'params' in content assert "buy" in content["params"] diff --git a/tests/strategy/test_strategy_loading.py b/tests/strategy/test_strategy_loading.py index 3a30a824a..3590c3e01 100644 --- a/tests/strategy/test_strategy_loading.py +++ b/tests/strategy/test_strategy_loading.py @@ -62,8 +62,8 @@ def test_load_strategy(default_conf, result): def test_load_strategy_base64(result, caplog, default_conf): - with (Path(__file__).parents[2] / 'freqtrade/templates/sample_strategy.py').open("rb") as file: - encoded_string = urlsafe_b64encode(file.read()).decode("utf-8") + filepath = Path(__file__).parents[2] / 'freqtrade/templates/sample_strategy.py' + encoded_string = urlsafe_b64encode(filepath.read_bytes()).decode("utf-8") default_conf.update({'strategy': 'SampleStrategy:{}'.format(encoded_string)}) strategy = StrategyResolver.load_strategy(default_conf)