Added more error checking to strategy interface and tested/validated
This commit is contained in:
parent
db5e038b0f
commit
9e92a641f5
@ -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']
|
|
||||||
|
|
||||||
# linear decay: f(t) = start - (rate * t)
|
if not dynamic_roi:
|
||||||
if dynamic_roi['dynamic_roi_type'] == 'linear':
|
return None, None
|
||||||
rate = (start - end) / dynamic_roi['dynamic_roi_time']
|
|
||||||
min_roi = max(end, start - (rate * trade_dur))
|
if 'dynamic_roi_type' in dynamic_roi and dynamic_roi['dynamic_roi_type'] \
|
||||||
# exponential decay: f(t) = start * e^(-rate*t)
|
in ['linear', 'exponential', 'connect']:
|
||||||
elif dynamic_roi['dynamic_roi_type'] == 'exponential':
|
roi_type = dynamic_roi['dynamic_roi_type']
|
||||||
min_roi = max(end, start * np.exp(-dynamic_roi['dynamic_roi_rate']*trade_dur))
|
# linear decay: f(t) = start - (rate * t)
|
||||||
elif dynamic_roi['dynamic_roi_type'] == 'connect':
|
if roi_type == 'linear':
|
||||||
# connect the points in the defined table with lines
|
if 'dynamic_roi_start' in dynamic_roi and 'dynamic_roi_end' in dynamic_roi and \
|
||||||
past_roi = list(filter(lambda x: x <= trade_dur, minimal_roi.keys()))
|
'dynamic_roi_time' in dynamic_roi:
|
||||||
next_roi = list(filter(lambda x: x > trade_dur, minimal_roi.keys()))
|
start = dynamic_roi['dynamic_roi_start']
|
||||||
if not past_roi:
|
end = dynamic_roi['dynamic_roi_end']
|
||||||
return None, None
|
time = dynamic_roi['dynamic_roi_time']
|
||||||
current_entry = max(past_roi)
|
rate = (start - end) / time
|
||||||
# if we are past the final point in the table, use that key/vaule pair
|
min_roi = max(end, start - (rate * trade_dur))
|
||||||
if not next_roi:
|
return trade_dur, min_roi
|
||||||
return current_entry, minimal_roi[current_entry]
|
else:
|
||||||
# use the slope-intercept formula between the two points in the roi table we are between
|
return None, None
|
||||||
else:
|
# exponential decay: f(t) = start * e^(-rate*t)
|
||||||
|
elif roi_type == 'exponential':
|
||||||
|
if 'dynamic_roi_start' in dynamic_roi and 'dynamic_roi_end' in dynamic_roi and \
|
||||||
|
'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)
|
||||||
|
Loading…
Reference in New Issue
Block a user