Extract edge reporting to optimize_reports
This commit is contained in:
parent
989ab646a9
commit
c475729c13
@ -18,7 +18,7 @@ from freqtrade.data.dataprovider import DataProvider
|
|||||||
from freqtrade.exceptions import OperationalException
|
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.optimize_reports import (
|
||||||
generate_text_table, generate_text_table_sell_reason,
|
generate_text_table, generate_text_table_sell_reason,
|
||||||
generate_text_table_strategy)
|
generate_text_table_strategy)
|
||||||
from freqtrade.persistence import Trade
|
from freqtrade.persistence import Trade
|
||||||
|
@ -6,13 +6,12 @@ This module contains the edge backtesting interface
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from tabulate import tabulate
|
|
||||||
|
|
||||||
from freqtrade import constants
|
from freqtrade import constants
|
||||||
from freqtrade.configuration import (TimeRange, remove_credentials,
|
from freqtrade.configuration import (TimeRange, remove_credentials,
|
||||||
validate_config_consistency)
|
validate_config_consistency)
|
||||||
from freqtrade.edge import Edge
|
from freqtrade.edge import Edge
|
||||||
from freqtrade.resolvers import StrategyResolver, ExchangeResolver
|
from freqtrade.optimize.optimize_reports import generate_edge_table
|
||||||
|
from freqtrade.resolvers import ExchangeResolver, StrategyResolver
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -44,33 +43,8 @@ class EdgeCli:
|
|||||||
self.edge._timerange = TimeRange.parse_timerange(None if self.config.get(
|
self.edge._timerange = TimeRange.parse_timerange(None if self.config.get(
|
||||||
'timerange') is None else str(self.config.get('timerange')))
|
'timerange') is None else str(self.config.get('timerange')))
|
||||||
|
|
||||||
def _generate_edge_table(self, results: dict) -> str:
|
|
||||||
|
|
||||||
floatfmt = ('s', '.10g', '.2f', '.2f', '.2f', '.2f', 'd', '.d')
|
|
||||||
tabular_data = []
|
|
||||||
headers = ['pair', 'stoploss', 'win rate', 'risk reward ratio',
|
|
||||||
'required risk reward', 'expectancy', 'total number of trades',
|
|
||||||
'average duration (min)']
|
|
||||||
|
|
||||||
for result in results.items():
|
|
||||||
if result[1].nb_trades > 0:
|
|
||||||
tabular_data.append([
|
|
||||||
result[0],
|
|
||||||
result[1].stoploss,
|
|
||||||
result[1].winrate,
|
|
||||||
result[1].risk_reward_ratio,
|
|
||||||
result[1].required_risk_reward,
|
|
||||||
result[1].expectancy,
|
|
||||||
result[1].nb_trades,
|
|
||||||
round(result[1].avg_trade_duration)
|
|
||||||
])
|
|
||||||
|
|
||||||
# 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 start(self) -> None:
|
def start(self) -> None:
|
||||||
result = self.edge.calculate()
|
result = self.edge.calculate()
|
||||||
if result:
|
if result:
|
||||||
print('') # blank line for readability
|
print('') # blank line for readability
|
||||||
print(self._generate_edge_table(self.edge._cached_pairs))
|
print(generate_edge_table(self.edge._cached_pairs))
|
||||||
|
@ -107,3 +107,29 @@ 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="pipe") # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
def generate_edge_table(results: dict) -> str:
|
||||||
|
|
||||||
|
floatfmt = ('s', '.10g', '.2f', '.2f', '.2f', '.2f', 'd', '.d')
|
||||||
|
tabular_data = []
|
||||||
|
headers = ['pair', 'stoploss', 'win rate', 'risk reward ratio',
|
||||||
|
'required risk reward', 'expectancy', 'total number of trades',
|
||||||
|
'average duration (min)']
|
||||||
|
|
||||||
|
for result in results.items():
|
||||||
|
if result[1].nb_trades > 0:
|
||||||
|
tabular_data.append([
|
||||||
|
result[0],
|
||||||
|
result[1].stoploss,
|
||||||
|
result[1].winrate,
|
||||||
|
result[1].risk_reward_ratio,
|
||||||
|
result[1].required_risk_reward,
|
||||||
|
result[1].expectancy,
|
||||||
|
result[1].nb_trades,
|
||||||
|
round(result[1].avg_trade_duration)
|
||||||
|
])
|
||||||
|
|
||||||
|
# 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
|
@ -1,7 +1,8 @@
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from freqtrade.optimize.backtest_reports import (
|
from freqtrade.edge import PairInfo
|
||||||
generate_text_table, generate_text_table_sell_reason,
|
from freqtrade.optimize.optimize_reports import (
|
||||||
|
generate_edge_table, generate_text_table, generate_text_table_sell_reason,
|
||||||
generate_text_table_strategy)
|
generate_text_table_strategy)
|
||||||
from freqtrade.strategy.interface import SellType
|
from freqtrade.strategy.interface import SellType
|
||||||
|
|
||||||
@ -94,3 +95,14 @@ def test_generate_text_table_strategy(default_conf, mocker):
|
|||||||
'| 1.30000000 | 45.00 | 0:20:00 | 3 | 0 |'
|
'| 1.30000000 | 45.00 | 0:20:00 | 3 | 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
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate_edge_table(edge_conf, mocker):
|
||||||
|
|
||||||
|
results = {}
|
||||||
|
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('| ETH/BTC |') == 1
|
||||||
|
assert generate_edge_table(results).count(
|
||||||
|
'| risk reward ratio | required risk reward | expectancy |') == 1
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
from freqtrade.edge import PairInfo
|
|
||||||
from freqtrade.optimize import setup_configuration, start_edge
|
from freqtrade.optimize import setup_configuration, start_edge
|
||||||
from freqtrade.optimize.edge_cli import EdgeCli
|
from freqtrade.optimize.edge_cli import EdgeCli
|
||||||
from freqtrade.state import RunMode
|
from freqtrade.state import RunMode
|
||||||
@ -106,16 +105,3 @@ def test_edge_init_fee(mocker, edge_conf) -> None:
|
|||||||
edge_cli = EdgeCli(edge_conf)
|
edge_cli = EdgeCli(edge_conf)
|
||||||
assert edge_cli.edge.fee == 0.1234
|
assert edge_cli.edge.fee == 0.1234
|
||||||
assert fee_mock.call_count == 0
|
assert fee_mock.call_count == 0
|
||||||
|
|
||||||
|
|
||||||
def test_generate_edge_table(edge_conf, mocker):
|
|
||||||
patch_exchange(mocker)
|
|
||||||
edge_cli = EdgeCli(edge_conf)
|
|
||||||
|
|
||||||
results = {}
|
|
||||||
results['ETH/BTC'] = PairInfo(-0.01, 0.60, 2, 1, 3, 10, 60)
|
|
||||||
|
|
||||||
assert edge_cli._generate_edge_table(results).count(':|') == 7
|
|
||||||
assert edge_cli._generate_edge_table(results).count('| ETH/BTC |') == 1
|
|
||||||
assert edge_cli._generate_edge_table(results).count(
|
|
||||||
'| risk reward ratio | required risk reward | expectancy |') == 1
|
|
||||||
|
Loading…
Reference in New Issue
Block a user