Merge pull request #2985 from Fredrik81/pretty-backtesting

Changed table style of backtesting and alignment of headers
This commit is contained in:
Matthias 2020-02-28 06:20:34 +01:00 committed by GitHub
commit ac7fa8252b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 45 deletions

View File

@ -423,28 +423,37 @@ class Backtesting:
strategy if len(self.strategylist) > 1 else None) strategy if len(self.strategylist) > 1 else None)
print(f"Result for strategy {strategy}") print(f"Result for strategy {strategy}")
print(' BACKTESTING REPORT '.center(133, '=')) table = generate_text_table(data, stake_currency=self.config['stake_currency'],
print(generate_text_table(data, max_open_trades=self.config['max_open_trades'],
stake_currency=self.config['stake_currency'], results=results)
max_open_trades=self.config['max_open_trades'], if isinstance(table, str):
results=results)) print(' BACKTESTING REPORT '.center(len(table.splitlines()[0]), '='))
print(table)
print(' SELL REASON STATS '.center(133, '=')) table = generate_text_table_sell_reason(data,
print(generate_text_table_sell_reason(data, stake_currency=self.config['stake_currency'],
stake_currency=self.config['stake_currency'], max_open_trades=self.config['max_open_trades'],
max_open_trades=self.config['max_open_trades'], results=results)
results=results)) if isinstance(table, str):
print(' SELL REASON STATS '.center(len(table.splitlines()[0]), '='))
print(table)
print(' LEFT OPEN TRADES REPORT '.center(133, '=')) table = generate_text_table(data,
print(generate_text_table(data, stake_currency=self.config['stake_currency'],
stake_currency=self.config['stake_currency'], max_open_trades=self.config['max_open_trades'],
max_open_trades=self.config['max_open_trades'], results=results.loc[results.open_at_end], skip_nan=True)
results=results.loc[results.open_at_end], skip_nan=True)) if isinstance(table, str):
print(' LEFT OPEN TRADES REPORT '.center(len(table.splitlines()[0]), '='))
print(table)
if isinstance(table, str):
print('=' * len(table.splitlines()[0]))
print() print()
if len(all_results) > 1: if len(all_results) > 1:
# Print Strategy summary table # Print Strategy summary table
print(' STRATEGY SUMMARY '.center(133, '=')) table = generate_text_table_strategy(self.config['stake_currency'],
print(generate_text_table_strategy(self.config['stake_currency'], self.config['max_open_trades'],
self.config['max_open_trades'], all_results=all_results)
all_results=all_results)) print(' STRATEGY SUMMARY '.center(len(table.splitlines()[0]), '='))
print(table)
print('=' * len(table.splitlines()[0]))
print('\nFor more details, please look at the detail tables above') print('\nFor more details, please look at the detail tables above')

View File

@ -66,7 +66,7 @@ def generate_text_table(data: Dict[str, Dict], stake_currency: str, max_open_tra
]) ])
# Ignore type as floatfmt does allow tuples but mypy does not know that # Ignore type as floatfmt does allow tuples but mypy does not know that
return tabulate(tabular_data, headers=headers, return tabulate(tabular_data, headers=headers,
floatfmt=floatfmt, tablefmt="pipe") # type: ignore floatfmt=floatfmt, tablefmt="orgtbl", stralign="right") # type: ignore
def generate_text_table_sell_reason( def generate_text_table_sell_reason(
@ -112,7 +112,7 @@ def generate_text_table_sell_reason(
profit_percent_tot, profit_percent_tot,
] ]
) )
return tabulate(tabular_data, headers=headers, tablefmt="pipe") return tabulate(tabular_data, headers=headers, tablefmt="orgtbl", stralign="right")
def generate_text_table_strategy(stake_currency: str, max_open_trades: str, def generate_text_table_strategy(stake_currency: str, max_open_trades: str,
@ -146,7 +146,7 @@ def generate_text_table_strategy(stake_currency: str, max_open_trades: str,
]) ])
# Ignore type as floatfmt does allow tuples but mypy does not know that # Ignore type as floatfmt does allow tuples but mypy does not know that
return tabulate(tabular_data, headers=headers, return tabulate(tabular_data, headers=headers,
floatfmt=floatfmt, tablefmt="pipe") # type: ignore floatfmt=floatfmt, tablefmt="orgtbl", stralign="right") # type: ignore
def generate_edge_table(results: dict) -> str: def generate_edge_table(results: dict) -> str:
@ -172,4 +172,4 @@ def generate_edge_table(results: dict) -> str:
# Ignore type as floatfmt does allow tuples but mypy does not know that # Ignore type as floatfmt does allow tuples but mypy does not know that
return tabulate(tabular_data, headers=headers, return tabulate(tabular_data, headers=headers,
floatfmt=floatfmt, tablefmt="pipe") # type: ignore floatfmt=floatfmt, tablefmt="orgtbl", stralign="right") # type: ignore

View File

@ -22,14 +22,14 @@ def test_generate_text_table(default_conf, mocker):
) )
result_str = ( result_str = (
'| Pair | Buys | Avg Profit % | Cum Profit % | Tot Profit BTC |' '| Pair | Buys | Avg Profit % | Cum Profit % | Tot Profit BTC |'
' Tot Profit % | Avg Duration | Wins | Draws | Losses |\n' ' Tot Profit % | Avg Duration | Wins | Draws | Losses |\n'
'|:--------|-------:|---------------:|---------------:|-----------------:|' '|---------+--------+----------------+----------------+------------------+'
'---------------:|:---------------|-------:|--------:|---------:|\n' '----------------+----------------+--------+---------+----------|\n'
'| ETH/BTC | 2 | 15.00 | 30.00 | 0.60000000 |' '| ETH/BTC | 2 | 15.00 | 30.00 | 0.60000000 |'
' 15.00 | 0:20:00 | 2 | 0 | 0 |\n' ' 15.00 | 0:20:00 | 2 | 0 | 0 |\n'
'| TOTAL | 2 | 15.00 | 30.00 | 0.60000000 |' '| TOTAL | 2 | 15.00 | 30.00 | 0.60000000 |'
' 15.00 | 0:20:00 | 2 | 0 | 0 |' ' 15.00 | 0:20:00 | 2 | 0 | 0 |'
) )
assert generate_text_table(data={'ETH/BTC': {}}, assert generate_text_table(data={'ETH/BTC': {}},
stake_currency='BTC', max_open_trades=2, stake_currency='BTC', max_open_trades=2,
@ -52,13 +52,13 @@ def test_generate_text_table_sell_reason(default_conf, mocker):
) )
result_str = ( result_str = (
'| Sell Reason | Sells | Wins | Draws | Losses |' '| Sell Reason | Sells | Wins | Draws | Losses |'
' Avg Profit % | Cum Profit % | Tot Profit BTC | Tot Profit % |\n' ' Avg Profit % | Cum Profit % | Tot Profit BTC | Tot Profit % |\n'
'|:--------------|--------:|-------:|--------:|---------:|' '|---------------+---------+--------+---------+----------+'
'---------------:|---------------:|-----------------:|---------------:|\n' '----------------+----------------+------------------+----------------|\n'
'| roi | 2 | 2 | 0 | 0 |' '| roi | 2 | 2 | 0 | 0 |'
' 15 | 30 | 0.6 | 15 |\n' ' 15 | 30 | 0.6 | 15 |\n'
'| stop_loss | 1 | 0 | 0 | 1 |' '| stop_loss | 1 | 0 | 0 | 1 |'
' -10 | -10 | -0.2 | -5 |' ' -10 | -10 | -0.2 | -5 |'
) )
assert generate_text_table_sell_reason( assert generate_text_table_sell_reason(
@ -95,14 +95,14 @@ def test_generate_text_table_strategy(default_conf, mocker):
) )
result_str = ( result_str = (
'| Strategy | Buys | Avg Profit % | Cum Profit % | Tot' '| Strategy | Buys | Avg Profit % | Cum Profit % | Tot'
' Profit BTC | Tot Profit % | Avg Duration | Wins | Draws | Losses |\n' ' Profit BTC | Tot Profit % | Avg Duration | Wins | Draws | Losses |\n'
'|:--------------|-------:|---------------:|---------------:|------' '|---------------+--------+----------------+----------------+------------------+'
'-----------:|---------------:|:---------------|-------:|--------:|---------:|\n' '----------------+----------------+--------+---------+----------|\n'
'| TestStrategy1 | 3 | 20.00 | 60.00 | ' '| TestStrategy1 | 3 | 20.00 | 60.00 | 1.10000000 |'
' 1.10000000 | 30.00 | 0:17:00 | 3 | 0 | 0 |\n' ' 30.00 | 0:17:00 | 3 | 0 | 0 |\n'
'| TestStrategy2 | 3 | 30.00 | 90.00 | ' '| TestStrategy2 | 3 | 30.00 | 90.00 | 1.30000000 |'
' 1.30000000 | 45.00 | 0:20:00 | 3 | 0 | 0 |' ' 45.00 | 0:20:00 | 3 | 0 | 0 |'
) )
assert generate_text_table_strategy('BTC', 2, all_results=results) == result_str assert generate_text_table_strategy('BTC', 2, all_results=results) == result_str
@ -111,8 +111,7 @@ def test_generate_edge_table(edge_conf, mocker):
results = {} results = {}
results['ETH/BTC'] = PairInfo(-0.01, 0.60, 2, 1, 3, 10, 60) results['ETH/BTC'] = PairInfo(-0.01, 0.60, 2, 1, 3, 10, 60)
assert generate_edge_table(results).count('+') == 7
assert generate_edge_table(results).count(':|') == 7
assert generate_edge_table(results).count('| ETH/BTC |') == 1 assert generate_edge_table(results).count('| ETH/BTC |') == 1
assert generate_edge_table(results).count( assert generate_edge_table(results).count(
'| Risk Reward Ratio | Required Risk Reward | Expectancy |') == 1 '| Risk Reward Ratio | Required Risk Reward | Expectancy |') == 1