Add CAGR calculation to backtesting
This commit is contained in:
parent
7b02114ad2
commit
4143ebbeae
@ -299,6 +299,7 @@ A backtesting result will look like that:
|
|||||||
| Final balance | 0.01762792 BTC |
|
| Final balance | 0.01762792 BTC |
|
||||||
| Absolute profit | 0.00762792 BTC |
|
| Absolute profit | 0.00762792 BTC |
|
||||||
| Total profit % | 76.2% |
|
| Total profit % | 76.2% |
|
||||||
|
| CAGR % | 460.87% |
|
||||||
| Trades per day | 3.575 |
|
| Trades per day | 3.575 |
|
||||||
| Avg. stake amount | 0.001 BTC |
|
| Avg. stake amount | 0.001 BTC |
|
||||||
| Total trade volume | 0.429 BTC |
|
| Total trade volume | 0.429 BTC |
|
||||||
@ -388,6 +389,7 @@ It contains some useful key metrics about performance of your strategy on backte
|
|||||||
| Final balance | 0.01762792 BTC |
|
| Final balance | 0.01762792 BTC |
|
||||||
| Absolute profit | 0.00762792 BTC |
|
| Absolute profit | 0.00762792 BTC |
|
||||||
| Total profit % | 76.2% |
|
| Total profit % | 76.2% |
|
||||||
|
| CAGR % | 460.87% |
|
||||||
| Avg. stake amount | 0.001 BTC |
|
| Avg. stake amount | 0.001 BTC |
|
||||||
| Total trade volume | 0.429 BTC |
|
| Total trade volume | 0.429 BTC |
|
||||||
| | |
|
| | |
|
||||||
|
@ -553,3 +553,14 @@ def calculate_csum(trades: pd.DataFrame, starting_balance: float = 0) -> Tuple[f
|
|||||||
csum_max = csum_df['sum'].max() + starting_balance
|
csum_max = csum_df['sum'].max() + starting_balance
|
||||||
|
|
||||||
return csum_min, csum_max
|
return csum_min, csum_max
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_cagr(days_passed: int, starting_balance: float, final_balance: float) -> float:
|
||||||
|
"""
|
||||||
|
Calculate CAGR
|
||||||
|
:param days_passed: Days passed between start and ending balance
|
||||||
|
:param starting_balance: Starting balance
|
||||||
|
:param final_balance: Final balance to calculate CAGR against
|
||||||
|
:return: CAGR
|
||||||
|
"""
|
||||||
|
return (final_balance / starting_balance) ** (1 / (days_passed / 365)) - 1
|
||||||
|
@ -9,7 +9,7 @@ from pandas import DataFrame, to_datetime
|
|||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
|
|
||||||
from freqtrade.constants import DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN, UNLIMITED_STAKE_AMOUNT
|
from freqtrade.constants import DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN, UNLIMITED_STAKE_AMOUNT
|
||||||
from freqtrade.data.btanalysis import (calculate_csum, calculate_market_change,
|
from freqtrade.data.btanalysis import (calculate_cagr, calculate_csum, calculate_market_change,
|
||||||
calculate_max_drawdown)
|
calculate_max_drawdown)
|
||||||
from freqtrade.misc import (decimals_per_coin, file_dump_joblib, file_dump_json,
|
from freqtrade.misc import (decimals_per_coin, file_dump_joblib, file_dump_json,
|
||||||
get_backtest_metadata_filename, round_coin_value)
|
get_backtest_metadata_filename, round_coin_value)
|
||||||
@ -446,6 +446,7 @@ def generate_strategy_stats(pairlist: List[str],
|
|||||||
'profit_total_abs': results['profit_abs'].sum(),
|
'profit_total_abs': results['profit_abs'].sum(),
|
||||||
'profit_total_long_abs': results.loc[~results['is_short'], 'profit_abs'].sum(),
|
'profit_total_long_abs': results.loc[~results['is_short'], 'profit_abs'].sum(),
|
||||||
'profit_total_short_abs': results.loc[results['is_short'], 'profit_abs'].sum(),
|
'profit_total_short_abs': results.loc[results['is_short'], 'profit_abs'].sum(),
|
||||||
|
'cagr': calculate_cagr(backtest_days, start_balance, content['final_balance']),
|
||||||
'backtest_start': min_date.strftime(DATETIME_PRINT_FORMAT),
|
'backtest_start': min_date.strftime(DATETIME_PRINT_FORMAT),
|
||||||
'backtest_start_ts': int(min_date.timestamp() * 1000),
|
'backtest_start_ts': int(min_date.timestamp() * 1000),
|
||||||
'backtest_end': max_date.strftime(DATETIME_PRINT_FORMAT),
|
'backtest_end': max_date.strftime(DATETIME_PRINT_FORMAT),
|
||||||
@ -746,6 +747,7 @@ def text_table_add_metrics(strat_results: Dict) -> str:
|
|||||||
('Absolute profit ', round_coin_value(strat_results['profit_total_abs'],
|
('Absolute profit ', round_coin_value(strat_results['profit_total_abs'],
|
||||||
strat_results['stake_currency'])),
|
strat_results['stake_currency'])),
|
||||||
('Total profit %', f"{strat_results['profit_total']:.2%}"),
|
('Total profit %', f"{strat_results['profit_total']:.2%}"),
|
||||||
|
('CAGR %', f"{strat_results['cagr']:.2%}"),
|
||||||
('Trades per day', strat_results['trades_per_day']),
|
('Trades per day', strat_results['trades_per_day']),
|
||||||
('Avg. daily profit %',
|
('Avg. daily profit %',
|
||||||
f"{(strat_results['profit_total'] / strat_results['backtest_days']):.2%}"),
|
f"{(strat_results['profit_total'] / strat_results['backtest_days']):.2%}"),
|
||||||
|
@ -8,13 +8,13 @@ from pandas import DataFrame, DateOffset, Timestamp, to_datetime
|
|||||||
|
|
||||||
from freqtrade.configuration import TimeRange
|
from freqtrade.configuration import TimeRange
|
||||||
from freqtrade.constants import LAST_BT_RESULT_FN
|
from freqtrade.constants import LAST_BT_RESULT_FN
|
||||||
from freqtrade.data.btanalysis import (BT_DATA_COLUMNS, analyze_trade_parallelism, calculate_csum,
|
from freqtrade.data.btanalysis import (BT_DATA_COLUMNS, analyze_trade_parallelism, calculate_cagr,
|
||||||
calculate_market_change, calculate_max_drawdown,
|
calculate_csum, calculate_market_change,
|
||||||
calculate_underwater, combine_dataframes_with_mean,
|
calculate_max_drawdown, calculate_underwater,
|
||||||
create_cum_profit, extract_trades_of_period,
|
combine_dataframes_with_mean, create_cum_profit,
|
||||||
get_latest_backtest_filename, get_latest_hyperopt_file,
|
extract_trades_of_period, get_latest_backtest_filename,
|
||||||
load_backtest_data, load_backtest_metadata, load_trades,
|
get_latest_hyperopt_file, load_backtest_data,
|
||||||
load_trades_from_db)
|
load_backtest_metadata, load_trades, load_trades_from_db)
|
||||||
from freqtrade.data.history import load_data, load_pair_history
|
from freqtrade.data.history import load_data, load_pair_history
|
||||||
from freqtrade.exceptions import OperationalException
|
from freqtrade.exceptions import OperationalException
|
||||||
from tests.conftest import CURRENT_TEST_STRATEGY, create_mock_trades
|
from tests.conftest import CURRENT_TEST_STRATEGY, create_mock_trades
|
||||||
@ -336,6 +336,19 @@ def test_calculate_csum(testdatadir):
|
|||||||
csum_min, csum_max = calculate_csum(DataFrame())
|
csum_min, csum_max = calculate_csum(DataFrame())
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('start,end,days, expected', [
|
||||||
|
(64900, 176000, 3 * 365, 0.3945),
|
||||||
|
(64900, 176000, 365, 1.7119),
|
||||||
|
(1000, 1000, 365, 0.0),
|
||||||
|
(1000, 1500, 365, 0.5),
|
||||||
|
(1000, 1500, 100, 3.3927), # sub year
|
||||||
|
(0.01000000, 0.01762792, 120, 4.6087), # sub year BTC values
|
||||||
|
])
|
||||||
|
def test_calculate_cagr(start, end, days, expected):
|
||||||
|
|
||||||
|
assert round(calculate_cagr(days, start, end), 4) == expected
|
||||||
|
|
||||||
|
|
||||||
def test_calculate_max_drawdown2():
|
def test_calculate_max_drawdown2():
|
||||||
values = [0.011580, 0.010048, 0.011340, 0.012161, 0.010416, 0.010009, 0.020024,
|
values = [0.011580, 0.010048, 0.011340, 0.012161, 0.010416, 0.010009, 0.020024,
|
||||||
-0.024662, -0.022350, 0.020496, -0.029859, -0.030511, 0.010041, 0.010872,
|
-0.024662, -0.022350, 0.020496, -0.029859, -0.030511, 0.010041, 0.010872,
|
||||||
|
Loading…
Reference in New Issue
Block a user