Add long/short support to backtesting

This commit is contained in:
Matthias 2021-11-18 20:34:59 +01:00
parent f40221dd9f
commit 0a50017c84
5 changed files with 19 additions and 2 deletions

View File

@ -30,7 +30,9 @@ BT_DATA_COLUMNS = ['pair', 'stake_amount', 'amount', 'open_date', 'close_date',
'fee_open', 'fee_close', 'trade_duration', 'fee_open', 'fee_close', 'trade_duration',
'profit_ratio', 'profit_abs', 'sell_reason', 'profit_ratio', 'profit_abs', 'sell_reason',
'initial_stop_loss_abs', 'initial_stop_loss_ratio', 'stop_loss_abs', 'initial_stop_loss_abs', 'initial_stop_loss_ratio', 'stop_loss_abs',
'stop_loss_ratio', 'min_rate', 'max_rate', 'is_open', 'buy_tag'] 'stop_loss_ratio', 'min_rate', 'max_rate', 'is_open', 'buy_tag',
'is_short'
]
# TODO-lev: usage of the above might need compatibility code (buy_tag, is_short?, ...?) # TODO-lev: usage of the above might need compatibility code (buy_tag, is_short?, ...?)

View File

@ -454,6 +454,8 @@ def generate_strategy_stats(btdata: Dict[str, DataFrame],
# 'days_breakdown_stats': days_breakdown_stats, # 'days_breakdown_stats': days_breakdown_stats,
'total_trades': len(results), 'total_trades': len(results),
'trade_count_long': len(results.loc[~results['is_short']]),
'trade_count_short': len(results.loc[results['is_short']]),
'total_volume': float(results['stake_amount'].sum()), 'total_volume': float(results['stake_amount'].sum()),
'avg_stake_amount': results['stake_amount'].mean() if len(results) > 0 else 0, 'avg_stake_amount': results['stake_amount'].mean() if len(results) > 0 else 0,
'profit_mean': results['profit_ratio'].mean() if len(results) > 0 else 0, 'profit_mean': results['profit_ratio'].mean() if len(results) > 0 else 0,
@ -719,6 +721,9 @@ def text_table_add_metrics(strat_results: Dict) -> str:
('', ''), # Empty line to improve readability ('', ''), # Empty line to improve readability
('Total/Daily Avg Trades', ('Total/Daily Avg Trades',
f"{strat_results['total_trades']} / {strat_results['trades_per_day']}"), f"{strat_results['total_trades']} / {strat_results['trades_per_day']}"),
('Long / Short',
f"{strat_results.get('trade_count_long', 'total_trades')} / "
f"{strat_results.get('trade_count_short', 0)}"),
('Starting balance', round_coin_value(strat_results['starting_balance'], ('Starting balance', round_coin_value(strat_results['starting_balance'],
strat_results['stake_currency'])), strat_results['stake_currency'])),
('Final balance', round_coin_value(strat_results['final_balance'], ('Final balance', round_coin_value(strat_results['final_balance'],

View File

@ -698,7 +698,8 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
'min_rate': [0.10370188, 0.10300000000000001], 'min_rate': [0.10370188, 0.10300000000000001],
'max_rate': [0.10501, 0.1038888], 'max_rate': [0.10501, 0.1038888],
'is_open': [False, False], 'is_open': [False, False],
'buy_tag': [None, None] 'buy_tag': [None, None],
"is_short": [False, False],
}) })
pd.testing.assert_frame_equal(results, expected) pd.testing.assert_frame_equal(results, expected)
data_pair = processed[pair] data_pair = processed[pair]
@ -1074,6 +1075,8 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat
'stake_amount': [0.01, 0.01], 'stake_amount': [0.01, 0.01],
'open_rate': [0.104445, 0.10302485], 'open_rate': [0.104445, 0.10302485],
'close_rate': [0.104969, 0.103541], 'close_rate': [0.104969, 0.103541],
"is_short": [False, False],
'sell_reason': [SellType.ROI, SellType.ROI] 'sell_reason': [SellType.ROI, SellType.ROI]
}) })
result2 = pd.DataFrame({'pair': ['XRP/BTC', 'LTC/BTC', 'ETH/BTC'], result2 = pd.DataFrame({'pair': ['XRP/BTC', 'LTC/BTC', 'ETH/BTC'],
@ -1091,6 +1094,7 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat
'stake_amount': [0.01, 0.01, 0.01], 'stake_amount': [0.01, 0.01, 0.01],
'open_rate': [0.104445, 0.10302485, 0.122541], 'open_rate': [0.104445, 0.10302485, 0.122541],
'close_rate': [0.104969, 0.103541, 0.123541], 'close_rate': [0.104969, 0.103541, 0.123541],
"is_short": [False, False, False],
'sell_reason': [SellType.ROI, SellType.ROI, SellType.STOP_LOSS] 'sell_reason': [SellType.ROI, SellType.ROI, SellType.STOP_LOSS]
}) })
backtestmock = MagicMock(side_effect=[ backtestmock = MagicMock(side_effect=[
@ -1180,6 +1184,7 @@ def test_backtest_start_multi_strat_nomock_detail(default_conf, mocker,
'2018-01-30 05:35:00', ], utc=True), '2018-01-30 05:35:00', ], utc=True),
'trade_duration': [235, 40], 'trade_duration': [235, 40],
'is_open': [False, False], 'is_open': [False, False],
'is_short': [False, False],
'stake_amount': [0.01, 0.01], 'stake_amount': [0.01, 0.01],
'open_rate': [0.104445, 0.10302485], 'open_rate': [0.104445, 0.10302485],
'close_rate': [0.104969, 0.103541], 'close_rate': [0.104969, 0.103541],
@ -1197,6 +1202,7 @@ def test_backtest_start_multi_strat_nomock_detail(default_conf, mocker,
'2018-01-30 08:30:00'], utc=True), '2018-01-30 08:30:00'], utc=True),
'trade_duration': [47, 40, 20], 'trade_duration': [47, 40, 20],
'is_open': [False, False, False], 'is_open': [False, False, False],
'is_short': [False, False, False],
'stake_amount': [0.01, 0.01, 0.01], 'stake_amount': [0.01, 0.01, 0.01],
'open_rate': [0.104445, 0.10302485, 0.122541], 'open_rate': [0.104445, 0.10302485, 0.122541],
'close_rate': [0.104969, 0.103541, 0.123541], 'close_rate': [0.104969, 0.103541, 0.123541],

View File

@ -344,6 +344,7 @@ def test_hyperopt_format_results(hyperopt):
"close_rate": [0.002546, 0.003014, 0.003103, 0.003217], "close_rate": [0.002546, 0.003014, 0.003103, 0.003217],
"trade_duration": [123, 34, 31, 14], "trade_duration": [123, 34, 31, 14],
"is_open": [False, False, False, True], "is_open": [False, False, False, True],
"is_short": [False, False, False, False],
"stake_amount": [0.01, 0.01, 0.01, 0.01], "stake_amount": [0.01, 0.01, 0.01, 0.01],
"sell_reason": [SellType.ROI, SellType.STOP_LOSS, "sell_reason": [SellType.ROI, SellType.STOP_LOSS,
SellType.ROI, SellType.FORCE_SELL] SellType.ROI, SellType.FORCE_SELL]
@ -412,6 +413,7 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None:
"close_rate": [0.002546, 0.003014, 0.003103, 0.003217], "close_rate": [0.002546, 0.003014, 0.003103, 0.003217],
"trade_duration": [123, 34, 31, 14], "trade_duration": [123, 34, 31, 14],
"is_open": [False, False, False, True], "is_open": [False, False, False, True],
"is_short": [False, False, False, False],
"stake_amount": [0.01, 0.01, 0.01, 0.01], "stake_amount": [0.01, 0.01, 0.01, 0.01],
"sell_reason": [SellType.ROI, SellType.STOP_LOSS, "sell_reason": [SellType.ROI, SellType.STOP_LOSS,
SellType.ROI, SellType.FORCE_SELL] SellType.ROI, SellType.FORCE_SELL]

View File

@ -76,6 +76,7 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir):
"close_rate": [0.002546, 0.003014, 0.003103, 0.003217], "close_rate": [0.002546, 0.003014, 0.003103, 0.003217],
"trade_duration": [123, 34, 31, 14], "trade_duration": [123, 34, 31, 14],
"is_open": [False, False, False, True], "is_open": [False, False, False, True],
"is_short": [False, False, False, False],
"stake_amount": [0.01, 0.01, 0.01, 0.01], "stake_amount": [0.01, 0.01, 0.01, 0.01],
"sell_reason": [SellType.ROI, SellType.STOP_LOSS, "sell_reason": [SellType.ROI, SellType.STOP_LOSS,
SellType.ROI, SellType.FORCE_SELL] SellType.ROI, SellType.FORCE_SELL]
@ -124,6 +125,7 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir):
"close_rate": [0.002546, 0.003014, 0.0032903, 0.003217], "close_rate": [0.002546, 0.003014, 0.0032903, 0.003217],
"trade_duration": [123, 34, 31, 14], "trade_duration": [123, 34, 31, 14],
"is_open": [False, False, False, True], "is_open": [False, False, False, True],
"is_short": [False, False, False, False],
"stake_amount": [0.01, 0.01, 0.01, 0.01], "stake_amount": [0.01, 0.01, 0.01, 0.01],
"sell_reason": [SellType.ROI, SellType.ROI, "sell_reason": [SellType.ROI, SellType.ROI,
SellType.STOP_LOSS, SellType.FORCE_SELL] SellType.STOP_LOSS, SellType.FORCE_SELL]