diff --git a/docs/configuration.md b/docs/configuration.md index d4ccedf84..ff5ce118c 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -197,6 +197,33 @@ you run it in production mode. ``` If you have not your Bittrex API key yet, [see our tutorial](https://github.com/freqtrade/freqtrade/blob/develop/docs/pre-requisite.md). + +### Embedding Strategies + +FreqTrade provides you with with an easy way to embed the strategy into your configuration file. +This is done by utilizing BASE64 encoding and providing this string at the strategy configuration field, +in your chosen config file. + +##### Encoding a string as BASE64 + +This is a quick example, how to generate the BASE64 string in python + +```python +from base64 import urlsafe_b64encode + +with open(file, 'r') as f: + content = f.read() +content = urlsafe_b64encode(content.encode('utf-8')) +``` + +The variable 'content', will contain the strategy file in a BASE64 encoded form. Which can now be set in your configurations file as following + +```json +"strategy": "NameOfStrategy:BASE64String" +``` + +Please ensure that 'NameOfStrategy' is identical to the strategy name! + ## Next step Now you have configured your config.json, the next step is to [start your bot](https://github.com/freqtrade/freqtrade/blob/develop/docs/bot-usage.md). diff --git a/freqtrade/strategy/resolver.py b/freqtrade/strategy/resolver.py index ea887e43e..7aeec300e 100644 --- a/freqtrade/strategy/resolver.py +++ b/freqtrade/strategy/resolver.py @@ -7,7 +7,10 @@ import importlib.util import inspect import logging import os +import tempfile +from base64 import urlsafe_b64decode from collections import OrderedDict +from pathlib import Path from typing import Dict, Optional, Type from freqtrade import constants @@ -87,6 +90,22 @@ class StrategyResolver(object): # Add extra strategy directory on top of search paths abs_paths.insert(0, extra_dir) + if ":" in strategy_name: + logger.info("loading base64 endocded strategy") + strat = strategy_name.split(":") + + if len(strat) == 2: + temp = Path(tempfile.mkdtemp("freq", "strategy")) + name = strat[0] + ".py" + + temp.joinpath(name).write_text(urlsafe_b64decode(strat[1]).decode('utf-8')) + temp.joinpath("__init__.py").touch() + + strategy_name = os.path.splitext(name)[0] + + # register temp path with the bot + abs_paths.insert(0, str(temp.resolve())) + for path in abs_paths: try: strategy = self._search_strategy(path, strategy_name=strategy_name, config=config) diff --git a/freqtrade/tests/strategy/test_strategy.py b/freqtrade/tests/strategy/test_strategy.py index 6bb17fc28..0cbd9f22c 100644 --- a/freqtrade/tests/strategy/test_strategy.py +++ b/freqtrade/tests/strategy/test_strategy.py @@ -1,5 +1,6 @@ # pragma pylint: disable=missing-docstring, protected-access, C0103 import logging +from base64 import urlsafe_b64encode from os import path import warnings @@ -63,6 +64,13 @@ def test_load_strategy(result): assert 'adx' in resolver.strategy.advise_indicators(result, metadata=metadata) +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_invalid_directory(result, caplog): resolver = StrategyResolver() extra_dir = path.join('some', 'path')