parent
cf044d166e
commit
5fce7f3b22
@ -168,6 +168,26 @@ def extract_trades_of_period(dataframe: pd.DataFrame, trades: pd.DataFrame,
|
|||||||
return trades
|
return trades
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_market_change(data: Dict[str, pd.DataFrame], column: str = "close") -> float:
|
||||||
|
"""
|
||||||
|
Calculate market change based on "column".
|
||||||
|
Calculation is done by taking the first non-null and the last non-null element of each column
|
||||||
|
and calculating the pctchange as "(last - first) / first".
|
||||||
|
Then the results per pair are combined as mean.
|
||||||
|
|
||||||
|
:param data: Dict of Dataframes, dict key should be pair.
|
||||||
|
:param column: Column in the original dataframes to use
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
tmp_means = []
|
||||||
|
for pair, df in data.items():
|
||||||
|
start = df[column].dropna().iloc[0]
|
||||||
|
end = df[column].dropna().iloc[-1]
|
||||||
|
tmp_means.append((end - start) / start)
|
||||||
|
|
||||||
|
return np.mean(tmp_means)
|
||||||
|
|
||||||
|
|
||||||
def combine_dataframes_with_mean(data: Dict[str, pd.DataFrame],
|
def combine_dataframes_with_mean(data: Dict[str, pd.DataFrame],
|
||||||
column: str = "close") -> pd.DataFrame:
|
column: str = "close") -> pd.DataFrame:
|
||||||
"""
|
"""
|
||||||
|
@ -8,7 +8,7 @@ from pandas import DataFrame
|
|||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
|
|
||||||
from freqtrade.constants import DATETIME_PRINT_FORMAT
|
from freqtrade.constants import DATETIME_PRINT_FORMAT
|
||||||
from freqtrade.data.btanalysis import calculate_max_drawdown
|
from freqtrade.data.btanalysis import calculate_max_drawdown, calculate_market_change
|
||||||
from freqtrade.misc import file_dump_json
|
from freqtrade.misc import file_dump_json
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -208,6 +208,8 @@ def generate_backtest_stats(config: Dict, btdata: Dict[str, DataFrame],
|
|||||||
stake_currency = config['stake_currency']
|
stake_currency = config['stake_currency']
|
||||||
max_open_trades = config['max_open_trades']
|
max_open_trades = config['max_open_trades']
|
||||||
result: Dict[str, Any] = {'strategy': {}}
|
result: Dict[str, Any] = {'strategy': {}}
|
||||||
|
market_change = calculate_market_change(btdata, 'close')
|
||||||
|
|
||||||
for strategy, results in all_results.items():
|
for strategy, results in all_results.items():
|
||||||
|
|
||||||
pair_results = generate_pair_metrics(btdata, stake_currency=stake_currency,
|
pair_results = generate_pair_metrics(btdata, stake_currency=stake_currency,
|
||||||
@ -232,7 +234,8 @@ def generate_backtest_stats(config: Dict, btdata: Dict[str, DataFrame],
|
|||||||
'backtest_end': max_date.datetime,
|
'backtest_end': max_date.datetime,
|
||||||
'backtest_end_ts': max_date.timestamp,
|
'backtest_end_ts': max_date.timestamp,
|
||||||
'backtest_days': backtest_days,
|
'backtest_days': backtest_days,
|
||||||
'trades_per_day': round(len(results) / backtest_days, 2) if backtest_days > 0 else None
|
'trades_per_day': round(len(results) / backtest_days, 2) if backtest_days > 0 else None,
|
||||||
|
'market_change': market_change,
|
||||||
}
|
}
|
||||||
result['strategy'][strategy] = strat_stats
|
result['strategy'][strategy] = strat_stats
|
||||||
|
|
||||||
@ -348,11 +351,12 @@ def text_table_add_metrics(strategy_results: Dict) -> str:
|
|||||||
('Max Drawdown', f"{round(strategy_results['max_drawdown'] * 100, 2)}%"),
|
('Max Drawdown', f"{round(strategy_results['max_drawdown'] * 100, 2)}%"),
|
||||||
('Drawdown Start', strategy_results['drawdown_start'].strftime(DATETIME_PRINT_FORMAT)),
|
('Drawdown Start', strategy_results['drawdown_start'].strftime(DATETIME_PRINT_FORMAT)),
|
||||||
('Drawdown End', strategy_results['drawdown_end'].strftime(DATETIME_PRINT_FORMAT)),
|
('Drawdown End', strategy_results['drawdown_end'].strftime(DATETIME_PRINT_FORMAT)),
|
||||||
|
('Market change', f"{round(strategy_results['market_change'] * 100, 2)}%"),
|
||||||
]
|
]
|
||||||
|
|
||||||
return tabulate(metrics, headers=["Metric", "Value"], tablefmt="orgtbl")
|
return tabulate(metrics, headers=["Metric", "Value"], tablefmt="orgtbl")
|
||||||
else:
|
else:
|
||||||
return
|
return ''
|
||||||
|
|
||||||
|
|
||||||
def show_backtest_results(config: Dict, backtest_stats: Dict):
|
def show_backtest_results(config: Dict, backtest_stats: Dict):
|
||||||
|
@ -8,6 +8,7 @@ from pandas import DataFrame, DateOffset, Timestamp, to_datetime
|
|||||||
from freqtrade.configuration import TimeRange
|
from freqtrade.configuration import TimeRange
|
||||||
from freqtrade.data.btanalysis import (BT_DATA_COLUMNS,
|
from freqtrade.data.btanalysis import (BT_DATA_COLUMNS,
|
||||||
analyze_trade_parallelism,
|
analyze_trade_parallelism,
|
||||||
|
calculate_market_change,
|
||||||
calculate_max_drawdown,
|
calculate_max_drawdown,
|
||||||
combine_dataframes_with_mean,
|
combine_dataframes_with_mean,
|
||||||
create_cum_profit,
|
create_cum_profit,
|
||||||
@ -135,6 +136,14 @@ def test_load_trades(default_conf, mocker):
|
|||||||
assert bt_mock.call_count == 0
|
assert bt_mock.call_count == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_calculate_market_change(testdatadir):
|
||||||
|
pairs = ["ETH/BTC", "ADA/BTC"]
|
||||||
|
data = load_data(datadir=testdatadir, pairs=pairs, timeframe='5m')
|
||||||
|
result = calculate_market_change(data)
|
||||||
|
assert isinstance(result, float)
|
||||||
|
assert pytest.approx(result) == 0.00955514
|
||||||
|
|
||||||
|
|
||||||
def test_combine_dataframes_with_mean(testdatadir):
|
def test_combine_dataframes_with_mean(testdatadir):
|
||||||
pairs = ["ETH/BTC", "ADA/BTC"]
|
pairs = ["ETH/BTC", "ADA/BTC"]
|
||||||
data = load_data(datadir=testdatadir, pairs=pairs, timeframe='5m')
|
data = load_data(datadir=testdatadir, pairs=pairs, timeframe='5m')
|
||||||
|
Loading…
Reference in New Issue
Block a user