From 8bbee4038b874c766a3739e234f098db3f5464be Mon Sep 17 00:00:00 2001 From: Gert Wohlgemuth Date: Thu, 5 Jul 2018 14:30:24 -0700 Subject: [PATCH 1/7] integrated BASE64 encoded strategy loading --- freqtrade/strategy/resolver.py | 22 ++++++++++++++++++++-- freqtrade/tests/strategy/test_strategy.py | 9 +++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/freqtrade/strategy/resolver.py b/freqtrade/strategy/resolver.py index 0dcd3fc6a..46f70ccc9 100644 --- a/freqtrade/strategy/resolver.py +++ b/freqtrade/strategy/resolver.py @@ -6,14 +6,16 @@ This module load custom strategies import importlib.util import inspect import logging -import os +from base64 import urlsafe_b64decode from collections import OrderedDict from typing import Optional, Dict, Type from freqtrade import constants from freqtrade.strategy import import_strategy from freqtrade.strategy.interface import IStrategy - +import tempfile +import os +from pathlib import Path logger = logging.getLogger(__name__) @@ -80,6 +82,22 @@ class StrategyResolver(object): # Add extra strategy directory on top of search paths abs_paths.insert(0, extra_dir) + if ":" in strategy_name and "http" not in strategy_name: + print("loading none http based strategy: {}".format(strategy_name)) + 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, temp.absolute()) + for path in abs_paths: try: strategy = self._search_strategy(path, strategy_name) diff --git a/freqtrade/tests/strategy/test_strategy.py b/freqtrade/tests/strategy/test_strategy.py index 1e082c380..72125a244 100644 --- a/freqtrade/tests/strategy/test_strategy.py +++ b/freqtrade/tests/strategy/test_strategy.py @@ -1,6 +1,7 @@ # pragma pylint: disable=missing-docstring, protected-access, C0103 import logging import os +from base64 import urlsafe_b64encode import pytest @@ -50,6 +51,14 @@ def test_load_strategy(result): assert 'adx' in resolver.strategy.populate_indicators(result) +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 hasattr(resolver.strategy, 'populate_indicators') + assert 'adx' in resolver.strategy.populate_indicators(result) + + def test_load_strategy_invalid_directory(result, caplog): resolver = StrategyResolver() extra_dir = os.path.join('some', 'path') From e1f5745f59400f9be4e68b026166ad9c3dbb4ea6 Mon Sep 17 00:00:00 2001 From: Gert Wohlgemuth Date: Thu, 5 Jul 2018 14:50:23 -0700 Subject: [PATCH 2/7] Update resolver.py --- freqtrade/strategy/resolver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/strategy/resolver.py b/freqtrade/strategy/resolver.py index 25eb81888..d9531ed90 100644 --- a/freqtrade/strategy/resolver.py +++ b/freqtrade/strategy/resolver.py @@ -84,7 +84,7 @@ class StrategyResolver(object): abs_paths.insert(0, extra_dir) if ":" in strategy_name: - logger.debug(("loading base64 endocded strategy".) + logger.debug(("loading base64 endocded strategy") strat = strategy_name.split(":") if len(strat) == 2: From 58879ff0125077bfaa6a3ba45cd7e3c3b2278eb4 Mon Sep 17 00:00:00 2001 From: Gert Wohlgemuth Date: Thu, 5 Jul 2018 15:01:53 -0700 Subject: [PATCH 3/7] fixed braket --- freqtrade/strategy/resolver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/strategy/resolver.py b/freqtrade/strategy/resolver.py index d9531ed90..3ea2bf412 100644 --- a/freqtrade/strategy/resolver.py +++ b/freqtrade/strategy/resolver.py @@ -84,7 +84,7 @@ class StrategyResolver(object): abs_paths.insert(0, extra_dir) if ":" in strategy_name: - logger.debug(("loading base64 endocded strategy") + logger.debug("loading base64 endocded strategy") strat = strategy_name.split(":") if len(strat) == 2: From 1897a1cb6a97e529bf325238b8a2a5fe4ee1245c Mon Sep 17 00:00:00 2001 From: Gert Wohlgemuth Date: Thu, 5 Jul 2018 16:10:38 -0700 Subject: [PATCH 4/7] fixed mypy issues, seriosuly... --- freqtrade/strategy/resolver.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/freqtrade/strategy/resolver.py b/freqtrade/strategy/resolver.py index 3ea2bf412..6ae779669 100644 --- a/freqtrade/strategy/resolver.py +++ b/freqtrade/strategy/resolver.py @@ -17,7 +17,6 @@ import tempfile import os from pathlib import Path - logger = logging.getLogger(__name__) @@ -97,7 +96,7 @@ class StrategyResolver(object): strategy_name = os.path.splitext(name)[0] # register temp path with the bot - abs_paths.insert(0, temp.absolute()) + abs_paths.insert(0, str(temp.resolve())) for path in abs_paths: try: From b3df1b1ba70d476d7558bf43c82ffdc86cd2aaf3 Mon Sep 17 00:00:00 2001 From: Gert Date: Sat, 28 Jul 2018 21:31:20 -0700 Subject: [PATCH 5/7] added documentation: --- docs/configuration.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/configuration.md b/docs/configuration.md index dd16ef6b5..57c7a0bec 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -191,6 +191,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). From b83487cc36fb2d7c5440fbe3a89dabdad794e881 Mon Sep 17 00:00:00 2001 From: Gert Date: Mon, 30 Jul 2018 13:00:08 -0700 Subject: [PATCH 6/7] added required changes --- freqtrade/strategy/resolver.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/freqtrade/strategy/resolver.py b/freqtrade/strategy/resolver.py index 6ae779669..ea4f5c5e3 100644 --- a/freqtrade/strategy/resolver.py +++ b/freqtrade/strategy/resolver.py @@ -6,16 +6,16 @@ This module load custom strategies 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 from freqtrade.strategy import import_strategy from freqtrade.strategy.interface import IStrategy -import tempfile -import os -from pathlib import Path logger = logging.getLogger(__name__) @@ -83,7 +83,7 @@ class StrategyResolver(object): abs_paths.insert(0, extra_dir) if ":" in strategy_name: - logger.debug("loading base64 endocded strategy") + logger.info("loading base64 endocded strategy") strat = strategy_name.split(":") if len(strat) == 2: From 5b8ee214f9e4287aa36366af0eff48c4da6c0782 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 1 Aug 2018 07:28:12 +0200 Subject: [PATCH 7/7] Adapt to pair_to_strat methology --- freqtrade/tests/strategy/test_strategy.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/freqtrade/tests/strategy/test_strategy.py b/freqtrade/tests/strategy/test_strategy.py index 8135995a7..0cbd9f22c 100644 --- a/freqtrade/tests/strategy/test_strategy.py +++ b/freqtrade/tests/strategy/test_strategy.py @@ -67,9 +67,8 @@ def test_load_strategy(result): 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 hasattr(resolver.strategy, 'populate_indicators') - assert 'adx' in resolver.strategy.populate_indicators(result) + 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):