This commit is contained in:
incrementby1 2021-10-27 15:52:10 +02:00
commit a50bde10de
10 changed files with 44 additions and 33 deletions

View File

@ -171,7 +171,7 @@ official commands. You can ask at any moment for help with `/help`.
| `/profit [<n>]` | 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) | `/profit [<n>]` | 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 <trade_id>` | Instantly sells the given trade (Ignoring `minimum_roi`). | `/forcesell <trade_id>` | Instantly sells the given trade (Ignoring `minimum_roi`).
| `/forcesell all` | Instantly sells all open trades (Ignoring `minimum_roi`). | `/forcesell all` | Instantly sells all open trades (Ignoring `minimum_roi`).
| `/forcebuy <pair> [rate]` | Instantly buys the given pair. Rate is optional. (`forcebuy_enable` must be set to True) | `/forcebuy <pair> [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 | `/performance` | Show performance of each finished trade grouped by pair
| `/balance` | Show account balance per currency | `/balance` | Show account balance per currency
| `/daily <n>` | Shows profit or loss per day, over the last n days (n defaults to 7) | `/daily <n>` | Shows profit or loss per day, over the last n days (n defaults to 7)

View File

@ -1,4 +1,3 @@
import io import io
import logging import logging
from copy import deepcopy from copy import deepcopy
@ -64,10 +63,11 @@ class HyperoptTools():
'export_time': datetime.now(timezone.utc), 'export_time': datetime.now(timezone.utc),
} }
logger.info(f"Dumping parameters to {filename}") logger.info(f"Dumping parameters to {filename}")
rapidjson.dump(final_params, filename.open('w'), indent=2, with filename.open('w') as f:
default=hyperopt_serializer, rapidjson.dump(final_params, f, indent=2,
number_mode=rapidjson.NM_NATIVE | rapidjson.NM_NAN default=hyperopt_serializer,
) number_mode=rapidjson.NM_NATIVE | rapidjson.NM_NAN
)
@staticmethod @staticmethod
def try_export_params(config: Dict[str, Any], strategy_name: str, params: Dict): def try_export_params(config: Dict[str, Any], strategy_name: str, params: Dict):

View File

@ -7,11 +7,15 @@ class SKDecimal(Integer):
def __init__(self, low, high, decimals=3, prior="uniform", base=10, transform=None, def __init__(self, low, high, decimals=3, prior="uniform", base=10, transform=None,
name=None, dtype=np.int64): name=None, dtype=np.int64):
self.decimals = decimals 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 # trunc to precision to avoid points out of space
self.low_orig = round(_low * pow(0.1, self.decimals), self.decimals) self.low_orig = round(_low * self.pow_dot_one, self.decimals)
self.high_orig = round(_high * pow(0.1, self.decimals), self.decimals) self.high_orig = round(_high * self.pow_dot_one, self.decimals)
super().__init__(_low, _high, prior, base, transform, name, dtype) super().__init__(_low, _high, prior, base, transform, name, dtype)
@ -25,9 +29,9 @@ class SKDecimal(Integer):
return self.low_orig <= point <= self.high_orig return self.low_orig <= point <= self.high_orig
def transform(self, Xt): def transform(self, Xt):
aa = [int(x * pow(10, self.decimals)) for x in Xt] return super().transform([int(v * self.pow_ten) for v in Xt])
return super().transform(aa)
def inverse_transform(self, Xt): def inverse_transform(self, Xt):
res = super().inverse_transform(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]

View File

@ -56,17 +56,21 @@ class StrategyResolver(IResolver):
if strategy._ft_params_from_file: if strategy._ft_params_from_file:
# Set parameters from Hyperopt results file # Set parameters from Hyperopt results file
params = strategy._ft_params_from_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', {}) trailing = params.get('trailing', {})
strategy.trailing_stop = trailing.get('trailing_stop', strategy.trailing_stop) strategy.trailing_stop = trailing.get(
strategy.trailing_stop_positive = trailing.get('trailing_stop_positive', 'trailing_stop', getattr(strategy, 'trailing_stop', False))
strategy.trailing_stop_positive) strategy.trailing_stop_positive = trailing.get(
'trailing_stop_positive', getattr(strategy, 'trailing_stop_positive', None))
strategy.trailing_stop_positive_offset = trailing.get( 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( 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 # Set attributes
# Check if we need to override configuration # Check if we need to override configuration

View File

@ -1033,7 +1033,8 @@ class Telegram(RPCHandler):
:return: None :return: None
""" """
forcebuy_text = ("*/forcebuy <pair> [<rate>]:* `Instantly buys the given pair. " forcebuy_text = ("*/forcebuy <pair> [<rate>]:* `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" message = ("*/start:* `Starts the trader`\n"
"*/stop:* `Stops the trader`\n" "*/stop:* `Stops the trader`\n"
"*/status <trade_id>|[table]:* `Lists all open trades`\n" "*/status <trade_id>|[table]:* `Lists all open trades`\n"

View File

@ -381,7 +381,8 @@ class HyperStrategyMixin(object):
if filename.is_file(): if filename.is_file():
logger.info(f"Loading parameters from file {filename}") logger.info(f"Loading parameters from file {filename}")
try: 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__: if params.get('strategy_name') != self.__class__.__name__:
raise OperationalException('Invalid parameter file provided.') raise OperationalException('Invalid parameter file provided.')
return params return params

View File

@ -65,9 +65,9 @@ class IStrategy(ABC, HyperStrategyMixin):
_populate_fun_len: int = 0 _populate_fun_len: int = 0
_buy_fun_len: int = 0 _buy_fun_len: int = 0
_sell_fun_len: int = 0 _sell_fun_len: int = 0
_ft_params_from_file: Dict = {} _ft_params_from_file: Dict
# associated minimal roi # associated minimal roi
minimal_roi: Dict minimal_roi: Dict = {}
# associated stoploss # associated stoploss
stoploss: float stoploss: float

View File

@ -1,18 +1,18 @@
numpy==1.21.2 numpy==1.21.3
pandas==1.3.4 pandas==1.3.4
pandas-ta==0.3.14b pandas-ta==0.3.14b
ccxt==1.58.47 ccxt==1.59.2
# Pin cryptography for now due to rust build errors with piwheels # Pin cryptography for now due to rust build errors with piwheels
cryptography==35.0.0 cryptography==35.0.0
aiohttp==3.7.4.post0 aiohttp==3.7.4.post0
SQLAlchemy==1.4.25 SQLAlchemy==1.4.26
python-telegram-bot==13.7 python-telegram-bot==13.7
arrow==1.2.0 arrow==1.2.1
cachetools==4.2.2 cachetools==4.2.2
requests==2.26.0 requests==2.26.0
urllib3==1.26.7 urllib3==1.26.7
jsonschema==4.1.0 jsonschema==4.1.2
TA-Lib==0.4.21 TA-Lib==0.4.21
technical==1.3.0 technical==1.3.0
tabulate==0.8.9 tabulate==0.8.9
@ -41,4 +41,4 @@ psutil==5.8.0
colorama==0.4.4 colorama==0.4.4
# Building config files interactively # Building config files interactively
questionary==1.10.0 questionary==1.10.0
prompt-toolkit==3.0.20 prompt-toolkit==3.0.21

View File

@ -209,7 +209,8 @@ def test_export_params(tmpdir):
assert filename.is_file() 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 content['strategy_name'] == 'StrategyTestV2'
assert 'params' in content assert 'params' in content
assert "buy" in content["params"] assert "buy" in content["params"]

View File

@ -62,8 +62,8 @@ def test_load_strategy(default_conf, result):
def test_load_strategy_base64(result, caplog, default_conf): def test_load_strategy_base64(result, caplog, default_conf):
with (Path(__file__).parents[2] / 'freqtrade/templates/sample_strategy.py').open("rb") as file: filepath = Path(__file__).parents[2] / 'freqtrade/templates/sample_strategy.py'
encoded_string = urlsafe_b64encode(file.read()).decode("utf-8") encoded_string = urlsafe_b64encode(filepath.read_bytes()).decode("utf-8")
default_conf.update({'strategy': 'SampleStrategy:{}'.format(encoded_string)}) default_conf.update({'strategy': 'SampleStrategy:{}'.format(encoded_string)})
strategy = StrategyResolver.load_strategy(default_conf) strategy = StrategyResolver.load_strategy(default_conf)