Add long/short support to backtesting
This commit is contained in:
parent
f40221dd9f
commit
0a50017c84
@ -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?, ...?)
|
||||||
|
|
||||||
|
|
||||||
|
@ -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'],
|
||||||
|
@ -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],
|
||||||
|
@ -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]
|
||||||
|
@ -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]
|
||||||
|
Loading…
Reference in New Issue
Block a user