Extract generate_text_table_strategy to seperate module

This commit is contained in:
Matthias 2020-01-02 07:32:12 +01:00
parent caec345c0b
commit 904e1647e1
3 changed files with 38 additions and 45 deletions

View File

@ -64,3 +64,32 @@ def generate_text_table_sell_reason(data: Dict[str, Dict], results: DataFrame) -
loss = len(results[(results['sell_reason'] == reason) & (results['profit_abs'] < 0)]) loss = len(results[(results['sell_reason'] == reason) & (results['profit_abs'] < 0)])
tabular_data.append([reason.value, count, profit, loss]) tabular_data.append([reason.value, count, profit, loss])
return tabulate(tabular_data, headers=headers, tablefmt="pipe") return tabulate(tabular_data, headers=headers, tablefmt="pipe")
def generate_text_table_strategy(stake_currency: str, max_open_trades: str,
all_results: Dict) -> str:
"""
Generate summary table per strategy
"""
floatfmt = ('s', 'd', '.2f', '.2f', '.8f', '.2f', 'd', '.1f', '.1f')
tabular_data = []
headers = ['Strategy', 'buy count', 'avg profit %', 'cum profit %',
f'tot profit {stake_currency}', 'tot profit %', 'avg duration',
'profit', 'loss']
for strategy, results in all_results.items():
tabular_data.append([
strategy,
len(results.index),
results.profit_percent.mean() * 100.0,
results.profit_percent.sum() * 100.0,
results.profit_abs.sum(),
results.profit_percent.sum() * 100.0 / max_open_trades,
str(timedelta(
minutes=round(results.trade_duration.mean()))) if not results.empty else '0:00',
len(results[results.profit_abs > 0]),
len(results[results.profit_abs < 0])
])
# Ignore type as floatfmt does allow tuples but mypy does not know that
return tabulate(tabular_data, headers=headers,
floatfmt=floatfmt, tablefmt="pipe") # type: ignore

View File

@ -10,7 +10,6 @@ from pathlib import Path
from typing import Any, Dict, List, NamedTuple, Optional from typing import Any, Dict, List, NamedTuple, Optional
from pandas import DataFrame from pandas import DataFrame
from tabulate import tabulate
from freqtrade.configuration import (TimeRange, remove_credentials, from freqtrade.configuration import (TimeRange, remove_credentials,
validate_config_consistency) validate_config_consistency)
@ -20,7 +19,8 @@ from freqtrade.exceptions import OperationalException
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds
from freqtrade.misc import file_dump_json from freqtrade.misc import file_dump_json
from freqtrade.optimize.backtest_reports import ( from freqtrade.optimize.backtest_reports import (
generate_text_table, generate_text_table_sell_reason) generate_text_table, generate_text_table_sell_reason,
generate_text_table_strategy)
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.resolvers import ExchangeResolver, StrategyResolver from freqtrade.resolvers import ExchangeResolver, StrategyResolver
from freqtrade.state import RunMode from freqtrade.state import RunMode
@ -131,37 +131,6 @@ class Backtesting:
return data, timerange return data, timerange
def _generate_text_table_strategy(self, all_results: dict) -> str:
"""
Generate summary table per strategy
"""
stake_currency = str(self.config.get('stake_currency'))
max_open_trades = self.config.get('max_open_trades')
floatfmt = ('s', 'd', '.2f', '.2f', '.8f', '.2f', 'd', '.1f', '.1f')
tabular_data = []
headers = ['Strategy', 'buy count', 'avg profit %', 'cum profit %',
'tot profit ' + stake_currency, 'tot profit %', 'avg duration',
'profit', 'loss']
for strategy, results in all_results.items():
tabular_data.append([
strategy,
len(results.index),
results.profit_percent.mean() * 100.0,
results.profit_percent.sum() * 100.0,
results.profit_abs.sum(),
results.profit_percent.sum() * 100.0 / max_open_trades,
str(timedelta(
minutes=round(results.trade_duration.mean()))) if not results.empty else '0:00',
len(results[results.profit_abs > 0]),
len(results[results.profit_abs < 0])
])
# Ignore type as floatfmt does allow tuples but mypy does not know that
return tabulate(tabular_data, headers=headers,
floatfmt=floatfmt, tablefmt="pipe") # type: ignore
def _store_backtest_result(self, recordfilename: Path, results: DataFrame, def _store_backtest_result(self, recordfilename: Path, results: DataFrame,
strategyname: Optional[str] = None) -> None: strategyname: Optional[str] = None) -> None:
@ -469,5 +438,7 @@ class Backtesting:
if len(all_results) > 1: if len(all_results) > 1:
# Print Strategy summary table # Print Strategy summary table
print(' Strategy Summary '.center(133, '=')) print(' Strategy Summary '.center(133, '='))
print(self._generate_text_table_strategy(all_results)) print(generate_text_table_strategy(self.config['stake_currency'],
self.config['max_open_trades'],
all_results=all_results))
print('\nFor more details, please look at the detail tables above') print('\nFor more details, please look at the detail tables above')

View File

@ -20,7 +20,8 @@ from freqtrade.data.history import get_timerange
from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.exceptions import DependencyException, OperationalException
from freqtrade.optimize import setup_configuration, start_backtesting from freqtrade.optimize import setup_configuration, start_backtesting
from freqtrade.optimize.backtest_reports import ( from freqtrade.optimize.backtest_reports import (
generate_text_table, generate_text_table_sell_reason) generate_text_table, generate_text_table_sell_reason,
generate_text_table_strategy)
from freqtrade.optimize.backtesting import Backtesting from freqtrade.optimize.backtesting import Backtesting
from freqtrade.state import RunMode from freqtrade.state import RunMode
from freqtrade.strategy.default_strategy import DefaultStrategy from freqtrade.strategy.default_strategy import DefaultStrategy
@ -361,7 +362,6 @@ def test_tickerdata_to_dataframe_bt(default_conf, mocker, testdatadir) -> None:
def test_generate_text_table(default_conf, mocker): def test_generate_text_table(default_conf, mocker):
patch_exchange(mocker)
results = pd.DataFrame( results = pd.DataFrame(
{ {
@ -390,7 +390,6 @@ def test_generate_text_table(default_conf, mocker):
def test_generate_text_table_sell_reason(default_conf, mocker): def test_generate_text_table_sell_reason(default_conf, mocker):
patch_exchange(mocker)
results = pd.DataFrame( results = pd.DataFrame(
{ {
@ -414,13 +413,7 @@ def test_generate_text_table_sell_reason(default_conf, mocker):
data={'ETH/BTC': {}}, results=results) == result_str data={'ETH/BTC': {}}, results=results) == result_str
def test_generate_text_table_strategyn(default_conf, mocker): def test_generate_text_table_strategy(default_conf, mocker):
"""
Test Backtesting.generate_text_table_sell_reason() method
"""
patch_exchange(mocker)
default_conf['max_open_trades'] = 2
backtesting = Backtesting(default_conf)
results = {} results = {}
results['ETH/BTC'] = pd.DataFrame( results['ETH/BTC'] = pd.DataFrame(
{ {
@ -455,7 +448,7 @@ def test_generate_text_table_strategyn(default_conf, mocker):
'| LTC/BTC | 3 | 30.00 | 90.00 ' '| LTC/BTC | 3 | 30.00 | 90.00 '
'| 1.30000000 | 45.00 | 0:20:00 | 3 | 0 |' '| 1.30000000 | 45.00 | 0:20:00 | 3 | 0 |'
) )
assert backtesting._generate_text_table_strategy(all_results=results) == result_str assert generate_text_table_strategy('BTC', 2, all_results=results) == result_str
def test_backtesting_start(default_conf, mocker, testdatadir, caplog) -> None: def test_backtesting_start(default_conf, mocker, testdatadir, caplog) -> None: