Added more error checking to strategy interface and tested/validated

This commit is contained in:
werkkrew 2021-03-13 13:26:29 -05:00
parent db5e038b0f
commit 9e92a641f5

View File

@ -10,6 +10,7 @@ from enum import Enum
from typing import Dict, List, NamedTuple, Optional, Tuple from typing import Dict, List, NamedTuple, Optional, Tuple
import arrow import arrow
import numpy as np
from pandas import DataFrame from pandas import DataFrame
from freqtrade.constants import ListPairsWithTimeframes from freqtrade.constants import ListPairsWithTimeframes
@ -636,39 +637,61 @@ class IStrategy(ABC):
""" """
dynamic_roi = self.dynamic_roi dynamic_roi = self.dynamic_roi
minimal_roi = self.minimal_roi minimal_roi = self.minimal_roi
start, end = dynamic_roi['dynamic_roi_start'], dynamic_roi['dynamic_roi_end']
if not dynamic_roi:
return None, None
# linear decay: f(t) = start - (rate * t) if 'dynamic_roi_type' in dynamic_roi and dynamic_roi['dynamic_roi_type'] \
if dynamic_roi['dynamic_roi_type'] == 'linear': in ['linear', 'exponential', 'connect']:
rate = (start - end) / dynamic_roi['dynamic_roi_time'] roi_type = dynamic_roi['dynamic_roi_type']
min_roi = max(end, start - (rate * trade_dur)) # linear decay: f(t) = start - (rate * t)
# exponential decay: f(t) = start * e^(-rate*t) if roi_type == 'linear':
elif dynamic_roi['dynamic_roi_type'] == 'exponential': if 'dynamic_roi_start' in dynamic_roi and 'dynamic_roi_end' in dynamic_roi and \
min_roi = max(end, start * np.exp(-dynamic_roi['dynamic_roi_rate']*trade_dur)) 'dynamic_roi_time' in dynamic_roi:
elif dynamic_roi['dynamic_roi_type'] == 'connect': start = dynamic_roi['dynamic_roi_start']
# connect the points in the defined table with lines end = dynamic_roi['dynamic_roi_end']
past_roi = list(filter(lambda x: x <= trade_dur, minimal_roi.keys())) time = dynamic_roi['dynamic_roi_time']
next_roi = list(filter(lambda x: x > trade_dur, minimal_roi.keys())) rate = (start - end) / time
if not past_roi: min_roi = max(end, start - (rate * trade_dur))
return None, None return trade_dur, min_roi
current_entry = max(past_roi) else:
# if we are past the final point in the table, use that key/vaule pair return None, None
if not next_roi: # exponential decay: f(t) = start * e^(-rate*t)
return current_entry, minimal_roi[current_entry] elif roi_type == 'exponential':
# use the slope-intercept formula between the two points in the roi table we are between if 'dynamic_roi_start' in dynamic_roi and 'dynamic_roi_end' in dynamic_roi and \
else: 'dynamic_roi_rate' in dynamic_roi:
start = dynamic_roi['dynamic_roi_start']
end = dynamic_roi['dynamic_roi_end']
rate = dynamic_roi['dynamic_roi_rate']
min_roi = max(end, start * np.exp(-rate*trade_dur))
return trade_dur, min_roi
else:
return None, None
# "connect the dots" between the points on the minima_roi table
elif roi_type == 'connect':
if not minimal_roi:
return None, None
# figure out where we are in the defined roi table
past_roi = list(filter(lambda x: x <= trade_dur, minimal_roi.keys()))
next_roi = list(filter(lambda x: x > trade_dur, minimal_roi.keys()))
# if we are past the final point in the table, use that key/vaule pair
if not past_roi:
return None, None
current_entry = max(past_roi)
if not next_roi:
return current_entry, minimal_roi[current_entry]
next_entry = min(next_roi) next_entry = min(next_roi)
# use the slope-intercept formula between the two points
# y = mx + b # y = mx + b
x1, y1 = current_entry, minimal_roi[current_entry] x1, y1 = current_entry, minimal_roi[current_entry]
x2, y2 = next_entry, minimal_roi[next_entry] x2, y2 = next_entry, minimal_roi[next_entry]
m = (y1-y2)/(x1-x2) m = (y1-y2)/(x1-x2)
b = (x1*y2 - x2*y1)/(x1-x2) b = (x1*y2 - x2*y1)/(x1-x2)
min_roi = (m * trade_dur) + b min_roi = (m * trade_dur) + b
return trade_dur, min_roi
else: else:
return None, None return None, None
return trade_dur, min_roi
def min_roi_reached_entry(self, trade_dur: int) -> Tuple[Optional[int], Optional[float]]: def min_roi_reached_entry(self, trade_dur: int) -> Tuple[Optional[int], Optional[float]]:
""" """
Based on trade duration defines the ROI entry that may have been reached. Based on trade duration defines the ROI entry that may have been reached.
@ -691,7 +714,9 @@ class IStrategy(ABC):
""" """
# Check if time matches and current rate is above threshold # Check if time matches and current rate is above threshold
trade_dur = int((current_time.timestamp() - trade.open_date_utc.timestamp()) // 60) trade_dur = int((current_time.timestamp() - trade.open_date_utc.timestamp()) // 60)
if self.dynamic_roi and self.dynamic_roi['dynamic_roi_enabled']:
if self.dynamic_roi and 'dynamic_roi_enabled' in self.dynamic_roi \
and self.dynamic_roi['dynamic_roi_enabled']:
_, roi = self.min_roi_reached_dynamic(trade_dur) _, roi = self.min_roi_reached_dynamic(trade_dur)
else: else:
_, roi = self.min_roi_reached_entry(trade_dur) _, roi = self.min_roi_reached_entry(trade_dur)