mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-11-10 10:21:59 +00:00
Fix calcs, rename ratio, add docs
This commit is contained in:
parent
79f7f82c59
commit
6ccc12f337
|
@ -287,12 +287,17 @@ Return a summary of your profit/loss and performance.
|
|||
> **Best Performing:** `PAY/BTC: 50.23%`
|
||||
> **Trading volume:** `0.5 BTC`
|
||||
> **Profit factor:** `1.04`
|
||||
> **Win / Loss:** `102 / 36`
|
||||
> **Winrate:** `73.91%`
|
||||
> **Expectancy (Ratio):** `4.87 (1.66)`
|
||||
> **Max Drawdown:** `9.23% (0.01255 BTC)`
|
||||
|
||||
The relative profit of `1.2%` is the average profit per trade.
|
||||
The relative profit of `15.2 Σ%` is be based on the starting capital - so in this case, the starting capital was `0.00485701 * 1.152 = 0.00738 BTC`.
|
||||
Starting capital is either taken from the `available_capital` setting, or calculated by using current wallet size - profits.
|
||||
Profit Factor is calculated as gross profits / gross losses - and should serve as an overall metric for the strategy.
|
||||
Expectancy corresponds to the average return per currency unit at risk, i.e. the winrate and the risk-reward ratio (the average gain of winning trades compared to the average loss of losing trades).
|
||||
Expectancy Ratio is expected profit or loss of a subsequent trade based on the performance of all past trades.
|
||||
Max drawdown corresponds to the backtesting metric `Absolute Drawdown (Account)` - calculated as `(Absolute Drawdown) / (DrawdownHigh + startingBalance)`.
|
||||
Bot started date will refer to the date the bot was first started. For older bots, this will default to the first trade's open date.
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ class Profit(BaseModel):
|
|||
profit_factor: float
|
||||
winrate: float
|
||||
expectancy: float
|
||||
expectancy_rate: float
|
||||
expectancy_ratio: float
|
||||
max_drawdown: float
|
||||
max_drawdown_abs: float
|
||||
trading_volume: Optional[float]
|
||||
|
|
|
@ -524,15 +524,15 @@ class RPC:
|
|||
profit_factor = winning_profit / abs(losing_profit) if losing_profit else float('inf')
|
||||
|
||||
mean_winning_profit = (winning_profit / winning_trades) if winning_trades > 0 else 0
|
||||
mean_losing_profit = (losing_profit / losing_trades) if losing_trades > 0 else 0
|
||||
mean_losing_profit = (abs(losing_profit) / losing_trades) if losing_trades > 0 else 0
|
||||
|
||||
winrate = (winning_trades / closed_trade_count) * 100 if closed_trade_count > 0 else 0
|
||||
loserate = (100 - winrate)
|
||||
|
||||
expectancy, expectancy_rate = self.__calc_expectancy(mean_winning_profit,
|
||||
mean_losing_profit,
|
||||
winrate,
|
||||
loserate)
|
||||
expectancy, expectancy_ratio = self.__calc_expectancy(mean_winning_profit,
|
||||
mean_losing_profit,
|
||||
winrate,
|
||||
loserate)
|
||||
|
||||
trades_df = DataFrame([{'close_date': trade.close_date.strftime(DATETIME_PRINT_FORMAT),
|
||||
'profit_abs': trade.close_profit_abs}
|
||||
|
@ -591,7 +591,7 @@ class RPC:
|
|||
'profit_factor': profit_factor,
|
||||
'winrate': winrate,
|
||||
'expectancy': expectancy,
|
||||
'expectancy_rate': expectancy_rate,
|
||||
'expectancy_ratio': expectancy_ratio,
|
||||
'max_drawdown': max_drawdown,
|
||||
'max_drawdown_abs': max_drawdown_abs,
|
||||
'trading_volume': trading_volume,
|
||||
|
@ -629,20 +629,18 @@ class RPC:
|
|||
self, mean_winning_profit: float, mean_losing_profit: float,
|
||||
winrate: float, loserate: float) -> Tuple[float, float]:
|
||||
|
||||
expectancy = 1.0
|
||||
if mean_winning_profit > 0 and abs(mean_losing_profit) > 0:
|
||||
expectancy = (
|
||||
(1 + (mean_winning_profit / abs(mean_losing_profit))) * (winrate / 100) - 1
|
||||
)
|
||||
elif mean_winning_profit == 0:
|
||||
expectancy = 0.0
|
||||
|
||||
expectancy_rate = (
|
||||
expectancy = (
|
||||
((winrate / 100) * mean_winning_profit) -
|
||||
((loserate / 100) * mean_losing_profit)
|
||||
)
|
||||
|
||||
return expectancy, expectancy_rate
|
||||
expectancy_ratio = float('inf')
|
||||
if mean_losing_profit > 0:
|
||||
expectancy_ratio = (
|
||||
((1 + (mean_winning_profit / mean_losing_profit)) * (winrate / 100)) - 1
|
||||
)
|
||||
|
||||
return expectancy, expectancy_ratio
|
||||
|
||||
def _rpc_balance(self, stake_currency: str, fiat_display_currency: str) -> Dict:
|
||||
""" Returns current account balance per crypto """
|
||||
|
|
|
@ -851,7 +851,7 @@ class Telegram(RPCHandler):
|
|||
best_pair_profit_ratio = stats['best_pair_profit_ratio']
|
||||
winrate = stats['winrate']
|
||||
expectancy = stats['expectancy']
|
||||
expectancy_rate = stats['expectancy_rate']
|
||||
expectancy_ratio = stats['expectancy_ratio']
|
||||
|
||||
if stats['trade_count'] == 0:
|
||||
markdown_msg = f"No trades yet.\n*Bot started:* `{stats['bot_start_date']}`"
|
||||
|
@ -879,7 +879,7 @@ class Telegram(RPCHandler):
|
|||
f"*Latest Trade opened:* `{latest_trade_date}`\n"
|
||||
f"*Win / Loss:* `{stats['winning_trades']} / {stats['losing_trades']}`\n"
|
||||
f"*Winrate:* `{winrate:.2f}%`\n"
|
||||
f"*Expectancy (Rate):* `{expectancy:.2f} ({expectancy_rate:.2f})`"
|
||||
f"*Expectancy (Ratio):* `{expectancy:.2f} ({expectancy_ratio:.2f})`"
|
||||
)
|
||||
if stats['closed_trade_count'] > 0:
|
||||
markdown_msg += (
|
||||
|
|
|
@ -403,7 +403,7 @@ def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None:
|
|||
assert res['latest_trade_date'] == ''
|
||||
assert res['latest_trade_timestamp'] == 0
|
||||
assert res['expectancy'] == 0
|
||||
assert res['expectancy_rate'] == 0
|
||||
assert res['expectancy_ratio'] == float('inf')
|
||||
|
||||
# Create some test data
|
||||
create_mock_trades_usdt(fee)
|
||||
|
@ -416,14 +416,14 @@ def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None:
|
|||
assert pytest.approx(stats['profit_all_percent_mean']) == -57.86
|
||||
assert pytest.approx(stats['profit_all_fiat']) == -85.205614098
|
||||
assert pytest.approx(stats['winrate']) == 66.666666667
|
||||
assert pytest.approx(stats['expectancy']) == 0.223308883
|
||||
assert pytest.approx(stats['expectancy']) == 0.9133333333333327
|
||||
assert stats['trade_count'] == 7
|
||||
assert stats['first_trade_humanized'] == '2 days ago'
|
||||
assert stats['latest_trade_humanized'] == '17 minutes ago'
|
||||
assert stats['avg_duration'] in ('0:17:40')
|
||||
assert stats['best_pair'] == 'XRP/USDT'
|
||||
assert stats['best_rate'] == 10.0
|
||||
assert stats['expectancy_rate'] == 3.64
|
||||
assert stats['expectancy_ratio'] == 0.22330888345558253
|
||||
|
||||
# Test non-available pair
|
||||
mocker.patch(f'{EXMS}.get_rate',
|
||||
|
|
|
@ -829,8 +829,8 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
|
|||
'profit_closed_percent_mean': -0.75, 'profit_closed_ratio_sum': -0.015,
|
||||
'profit_closed_percent_sum': -1.5, 'profit_closed_ratio': -6.739057628404269e-06,
|
||||
'profit_closed_percent': -0.0, 'winning_trades': 0, 'losing_trades': 2,
|
||||
'profit_factor': 0.0, 'winrate': 0.0, 'expectancy': 0.0, 'expectancy_rate': 0.0033695635,
|
||||
'trading_volume': 91.074,
|
||||
'profit_factor': 0.0, 'winrate': 0.0, 'expectancy': -0.0033695635,
|
||||
'expectancy_ratio': -1.0, 'trading_volume': 91.074,
|
||||
}
|
||||
),
|
||||
(
|
||||
|
@ -845,8 +845,8 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
|
|||
'profit_closed_percent_mean': 0.75, 'profit_closed_ratio_sum': 0.015,
|
||||
'profit_closed_percent_sum': 1.5, 'profit_closed_ratio': 7.391275897987988e-07,
|
||||
'profit_closed_percent': 0.0, 'winning_trades': 2, 'losing_trades': 0,
|
||||
'profit_factor': None, 'winrate': 100.0, 'expectancy': 1.0,
|
||||
'expectancy_rate': 0.0003695635, 'trading_volume': 91.074,
|
||||
'profit_factor': None, 'winrate': 100.0, 'expectancy': 0.0003695635,
|
||||
'expectancy_ratio': None, 'trading_volume': 91.074,
|
||||
}
|
||||
),
|
||||
(
|
||||
|
@ -861,8 +861,9 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
|
|||
'profit_closed_percent_mean': 0.25, 'profit_closed_ratio_sum': 0.005,
|
||||
'profit_closed_percent_sum': 0.5, 'profit_closed_ratio': -5.429078808526421e-06,
|
||||
'profit_closed_percent': -0.0, 'winning_trades': 1, 'losing_trades': 1,
|
||||
'profit_factor': 0.02775724835771106, 'winrate': 50.0, 'expectancy': -0.48612137582114445,
|
||||
'expectancy_rate': 0.0028695635, 'trading_volume': 91.074,
|
||||
'profit_factor': 0.02775724835771106, 'winrate': 50.0,
|
||||
'expectancy': -0.0027145635000000003, 'expectancy_ratio': -0.48612137582114445,
|
||||
'trading_volume': 91.074,
|
||||
}
|
||||
)
|
||||
])
|
||||
|
@ -921,7 +922,7 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, is_short, expected)
|
|||
'profit_factor': expected['profit_factor'],
|
||||
'winrate': expected['winrate'],
|
||||
'expectancy': expected['expectancy'],
|
||||
'expectancy_rate': expected['expectancy_rate'],
|
||||
'expectancy_ratio': expected['expectancy_ratio'],
|
||||
'max_drawdown': ANY,
|
||||
'max_drawdown_abs': ANY,
|
||||
'trading_volume': expected['trading_volume'],
|
||||
|
|
|
@ -800,7 +800,7 @@ async def test_telegram_profit_handle(
|
|||
assert '*Max Drawdown:*' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*Profit factor:*' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*Winrate:*' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*Expectancy (Rate):*' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*Expectancy (Ratio):*' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*Trading volume:* `126 USDT`' in msg_mock.call_args_list[-1][0][0]
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user