Merge pull request #332 from gcarq/hyperopt_stoploss

Add stoploss to the hyperopt parameters
This commit is contained in:
Janne Sinivirta 2018-01-08 08:03:09 +02:00 committed by GitHub
commit fa97a82568
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 13 deletions

View File

@ -31,6 +31,10 @@ TOTAL_TRIES = None
_CURRENT_TRIES = 0 _CURRENT_TRIES = 0
CURRENT_BEST_LOSS = 100 CURRENT_BEST_LOSS = 100
# max average trade duration in minutes
# if eval ends with higher value, we consider it a failed eval
MAX_ACCEPTED_TRADE_DURATION = 240
# this is expexted avg profit * expected trade count # this is expexted avg profit * expected trade count
# for example 3.5%, 1100 trades, EXPECTED_MAX_PROFIT = 3.85 # for example 3.5%, 1100 trades, EXPECTED_MAX_PROFIT = 3.85
EXPECTED_MAX_PROFIT = 3.85 EXPECTED_MAX_PROFIT = 3.85
@ -91,6 +95,7 @@ SPACE = {
{'type': 'stochf_cross'}, {'type': 'stochf_cross'},
{'type': 'ht_sine'}, {'type': 'ht_sine'},
]), ]),
'stoploss': hp.quniform('stoploss', -30, -2, 1),
} }
@ -109,11 +114,12 @@ def log_results(results):
sys.stdout.flush() sys.stdout.flush()
def calculate_loss(total_profit: float, trade_count: int): def calculate_loss(total_profit: float, trade_count: int, trade_duration: float):
""" objective function, returns smaller number for more optimal results """ """ objective function, returns smaller number for more optimal results """
trade_loss = 1 - 0.35 * exp(-(trade_count - TARGET_TRADES) ** 2 / 10 ** 5.2) trade_loss = 1 - 0.35 * exp(-(trade_count - TARGET_TRADES) ** 2 / 10 ** 5.2)
profit_loss = max(0, 1 - total_profit / EXPECTED_MAX_PROFIT) profit_loss = max(0, 1 - total_profit / EXPECTED_MAX_PROFIT)
return trade_loss + profit_loss duration_loss = min(trade_duration / MAX_ACCEPTED_TRADE_DURATION, 1)
return trade_loss + profit_loss + duration_loss
def optimizer(params): def optimizer(params):
@ -122,20 +128,21 @@ def optimizer(params):
from freqtrade.optimize import backtesting from freqtrade.optimize import backtesting
backtesting.populate_buy_trend = buy_strategy_generator(params) backtesting.populate_buy_trend = buy_strategy_generator(params)
results = backtest(OPTIMIZE_CONFIG['stake_amount'], PROCESSED) results = backtest(OPTIMIZE_CONFIG['stake_amount'], PROCESSED, stoploss=params['stoploss'])
result_explanation = format_results(results) result_explanation = format_results(results)
total_profit = results.profit_percent.sum() total_profit = results.profit_percent.sum()
trade_count = len(results.index) trade_count = len(results.index)
trade_duration = results.duration.mean() * 5
if trade_count == 0: if trade_count == 0 or trade_duration > MAX_ACCEPTED_TRADE_DURATION:
print('.', end='') print('.', end='')
return { return {
'status': STATUS_FAIL, 'status': STATUS_FAIL,
'loss': float('inf') 'loss': float('inf')
} }
loss = calculate_loss(total_profit, trade_count) loss = calculate_loss(total_profit, trade_count, trade_duration)
_CURRENT_TRIES += 1 _CURRENT_TRIES += 1

View File

@ -5,17 +5,23 @@ from freqtrade.optimize.hyperopt import calculate_loss, TARGET_TRADES, EXPECTED_
def test_loss_calculation_prefer_correct_trade_count(): def test_loss_calculation_prefer_correct_trade_count():
correct = calculate_loss(1, TARGET_TRADES) correct = calculate_loss(1, TARGET_TRADES, 20)
over = calculate_loss(1, TARGET_TRADES + 100) over = calculate_loss(1, TARGET_TRADES + 100, 20)
under = calculate_loss(1, TARGET_TRADES - 100) under = calculate_loss(1, TARGET_TRADES - 100, 20)
assert over > correct assert over > correct
assert under > correct assert under > correct
def test_loss_calculation_prefer_shorter_trades():
shorter = calculate_loss(1, 100, 20)
longer = calculate_loss(1, 100, 30)
assert shorter < longer
def test_loss_calculation_has_limited_profit(): def test_loss_calculation_has_limited_profit():
correct = calculate_loss(EXPECTED_MAX_PROFIT, TARGET_TRADES) correct = calculate_loss(EXPECTED_MAX_PROFIT, TARGET_TRADES, 20)
over = calculate_loss(EXPECTED_MAX_PROFIT * 2, TARGET_TRADES) over = calculate_loss(EXPECTED_MAX_PROFIT * 2, TARGET_TRADES, 20)
under = calculate_loss(EXPECTED_MAX_PROFIT / 2, TARGET_TRADES) under = calculate_loss(EXPECTED_MAX_PROFIT / 2, TARGET_TRADES, 20)
assert over == correct assert over == correct
assert under > correct assert under > correct
@ -93,7 +99,8 @@ def test_fmin_best_results(mocker, caplog):
"trigger": 2, "trigger": 2,
"uptrend_long_ema": 1, "uptrend_long_ema": 1,
"uptrend_short_ema": 0, "uptrend_short_ema": 0,
"uptrend_sma": 0 "uptrend_sma": 0,
"stoploss": -10,
} }
mocker.patch('freqtrade.optimize.hyperopt.MongoTrials', return_value=create_trials(mocker)) mocker.patch('freqtrade.optimize.hyperopt.MongoTrials', return_value=create_trials(mocker))
@ -109,7 +116,8 @@ def test_fmin_best_results(mocker, caplog):
'"adx": {\n "enabled": true,\n "value": 15.0\n },', '"adx": {\n "enabled": true,\n "value": 15.0\n },',
'"green_candle": {\n "enabled": true\n },', '"green_candle": {\n "enabled": true\n },',
'"mfi": {\n "enabled": false\n },', '"mfi": {\n "enabled": false\n },',
'"trigger": {\n "type": "ao_cross_zero"\n },' '"trigger": {\n "type": "ao_cross_zero"\n },',
'"stoploss": -10.0',
] ]
for line in exists: for line in exists: