Merge pull request #6964 from freqtrade/rpc_rel_daily
Telegram / api daily relative profit
This commit is contained in:
commit
2e1ed132f7
@ -328,11 +328,11 @@ Per default `/daily` will return the 7 last days. The example below if for `/dai
|
|||||||
|
|
||||||
> **Daily Profit over the last 3 days:**
|
> **Daily Profit over the last 3 days:**
|
||||||
```
|
```
|
||||||
Day Profit BTC Profit USD
|
Day (count) USDT USD Profit %
|
||||||
---------- -------------- ------------
|
-------------- ------------ ---------- ----------
|
||||||
2018-01-03 0.00224175 BTC 29,142 USD
|
2022-06-11 (1) -0.746 USDT -0.75 USD -0.08%
|
||||||
2018-01-02 0.00033131 BTC 4,307 USD
|
2022-06-10 (0) 0 USDT 0.00 USD 0.00%
|
||||||
2018-01-01 0.00269130 BTC 34.986 USD
|
2022-06-09 (5) 20 USDT 20.10 USD 5.00%
|
||||||
```
|
```
|
||||||
|
|
||||||
### /weekly <n>
|
### /weekly <n>
|
||||||
@ -342,11 +342,11 @@ from Monday. The example below if for `/weekly 3`:
|
|||||||
|
|
||||||
> **Weekly Profit over the last 3 weeks (starting from Monday):**
|
> **Weekly Profit over the last 3 weeks (starting from Monday):**
|
||||||
```
|
```
|
||||||
Monday Profit BTC Profit USD
|
Monday (count) Profit BTC Profit USD Profit %
|
||||||
---------- -------------- ------------
|
------------- -------------- ------------ ----------
|
||||||
2018-01-03 0.00224175 BTC 29,142 USD
|
2018-01-03 (5) 0.00224175 BTC 29,142 USD 4.98%
|
||||||
2017-12-27 0.00033131 BTC 4,307 USD
|
2017-12-27 (1) 0.00033131 BTC 4,307 USD 0.00%
|
||||||
2017-12-20 0.00269130 BTC 34.986 USD
|
2017-12-20 (4) 0.00269130 BTC 34.986 USD 5.12%
|
||||||
```
|
```
|
||||||
|
|
||||||
### /monthly <n>
|
### /monthly <n>
|
||||||
@ -356,11 +356,11 @@ if for `/monthly 3`:
|
|||||||
|
|
||||||
> **Monthly Profit over the last 3 months:**
|
> **Monthly Profit over the last 3 months:**
|
||||||
```
|
```
|
||||||
Month Profit BTC Profit USD
|
Month (count) Profit BTC Profit USD Profit %
|
||||||
---------- -------------- ------------
|
------------- -------------- ------------ ----------
|
||||||
2018-01 0.00224175 BTC 29,142 USD
|
2018-01 (20) 0.00224175 BTC 29,142 USD 4.98%
|
||||||
2017-12 0.00033131 BTC 4,307 USD
|
2017-12 (5) 0.00033131 BTC 4,307 USD 0.00%
|
||||||
2017-11 0.00269130 BTC 34.986 USD
|
2017-11 (10) 0.00269130 BTC 34.986 USD 5.10%
|
||||||
```
|
```
|
||||||
|
|
||||||
### /whitelist
|
### /whitelist
|
||||||
|
@ -120,6 +120,8 @@ class Stats(BaseModel):
|
|||||||
class DailyRecord(BaseModel):
|
class DailyRecord(BaseModel):
|
||||||
date: date
|
date: date
|
||||||
abs_profit: float
|
abs_profit: float
|
||||||
|
rel_profit: float
|
||||||
|
starting_balance: float
|
||||||
fiat_value: float
|
fiat_value: float
|
||||||
trade_count: int
|
trade_count: int
|
||||||
|
|
||||||
|
@ -36,7 +36,8 @@ logger = logging.getLogger(__name__)
|
|||||||
# versions 2.xx -> futures/short branch
|
# versions 2.xx -> futures/short branch
|
||||||
# 2.14: Add entry/exit orders to trade response
|
# 2.14: Add entry/exit orders to trade response
|
||||||
# 2.15: Add backtest history endpoints
|
# 2.15: Add backtest history endpoints
|
||||||
API_VERSION = 2.15
|
# 2.16: Additional daily metrics
|
||||||
|
API_VERSION = 2.16
|
||||||
|
|
||||||
# Public API, requires no auth.
|
# Public API, requires no auth.
|
||||||
router_public = APIRouter()
|
router_public = APIRouter()
|
||||||
|
@ -302,11 +302,12 @@ class RPC:
|
|||||||
return relativedelta(months=step)
|
return relativedelta(months=step)
|
||||||
return timedelta(**{timeunit: step})
|
return timedelta(**{timeunit: step})
|
||||||
|
|
||||||
profit_units: Dict[date, Dict] = {}
|
|
||||||
|
|
||||||
if not (isinstance(timescale, int) and timescale > 0):
|
if not (isinstance(timescale, int) and timescale > 0):
|
||||||
raise RPCException('timescale must be an integer greater than 0')
|
raise RPCException('timescale must be an integer greater than 0')
|
||||||
|
|
||||||
|
profit_units: Dict[date, Dict] = {}
|
||||||
|
daily_stake = self._freqtrade.wallets.get_total_stake_amount()
|
||||||
|
|
||||||
for day in range(0, timescale):
|
for day in range(0, timescale):
|
||||||
profitday = start_date - time_offset(day)
|
profitday = start_date - time_offset(day)
|
||||||
# Only query for necessary columns for performance reasons.
|
# Only query for necessary columns for performance reasons.
|
||||||
@ -318,8 +319,12 @@ class RPC:
|
|||||||
|
|
||||||
curdayprofit = sum(
|
curdayprofit = sum(
|
||||||
trade.close_profit_abs for trade in trades if trade.close_profit_abs is not None)
|
trade.close_profit_abs for trade in trades if trade.close_profit_abs is not None)
|
||||||
|
# Calculate this periods starting balance
|
||||||
|
daily_stake = daily_stake - curdayprofit
|
||||||
profit_units[profitday] = {
|
profit_units[profitday] = {
|
||||||
'amount': curdayprofit,
|
'amount': curdayprofit,
|
||||||
|
'daily_stake': daily_stake,
|
||||||
|
'rel_profit': round(curdayprofit / daily_stake, 8) if daily_stake > 0 else 0,
|
||||||
'trades': len(trades),
|
'trades': len(trades),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,6 +332,8 @@ class RPC:
|
|||||||
{
|
{
|
||||||
'date': f"{key.year}-{key.month:02d}" if timeunit == 'months' else key,
|
'date': f"{key.year}-{key.month:02d}" if timeunit == 'months' else key,
|
||||||
'abs_profit': value["amount"],
|
'abs_profit': value["amount"],
|
||||||
|
'starting_balance': value["daily_stake"],
|
||||||
|
'rel_profit': value["rel_profit"],
|
||||||
'fiat_value': self._fiat_converter.convert_amount(
|
'fiat_value': self._fiat_converter.convert_amount(
|
||||||
value['amount'],
|
value['amount'],
|
||||||
stake_currency,
|
stake_currency,
|
||||||
|
@ -605,14 +605,16 @@ class Telegram(RPCHandler):
|
|||||||
unit
|
unit
|
||||||
)
|
)
|
||||||
stats_tab = tabulate(
|
stats_tab = tabulate(
|
||||||
[[period['date'],
|
[[f"{period['date']} ({period['trade_count']})",
|
||||||
f"{round_coin_value(period['abs_profit'], stats['stake_currency'])}",
|
f"{round_coin_value(period['abs_profit'], stats['stake_currency'])}",
|
||||||
f"{period['fiat_value']:.2f} {stats['fiat_display_currency']}",
|
f"{period['fiat_value']:.2f} {stats['fiat_display_currency']}",
|
||||||
f"{period['trade_count']} trades"] for period in stats['data']],
|
f"{period['rel_profit']:.2%}",
|
||||||
|
] for period in stats['data']],
|
||||||
headers=[
|
headers=[
|
||||||
val.header,
|
f"{val.header} (count)",
|
||||||
f'Profit {stake_cur}',
|
f'{stake_cur}',
|
||||||
f'Profit {fiat_disp_cur}',
|
f'{fiat_disp_cur}',
|
||||||
|
'Profit %',
|
||||||
'Trades',
|
'Trades',
|
||||||
],
|
],
|
||||||
tablefmt='simple')
|
tablefmt='simple')
|
||||||
|
@ -311,10 +311,12 @@ def test__rpc_timeunit_profit(default_conf_usdt, ticker, fee,
|
|||||||
assert days['fiat_display_currency'] == default_conf_usdt['fiat_display_currency']
|
assert days['fiat_display_currency'] == default_conf_usdt['fiat_display_currency']
|
||||||
for day in days['data']:
|
for day in days['data']:
|
||||||
# {'date': datetime.date(2022, 6, 11), 'abs_profit': 13.8299999,
|
# {'date': datetime.date(2022, 6, 11), 'abs_profit': 13.8299999,
|
||||||
|
# 'starting_balance': 1055.37, 'rel_profit': 0.0131044,
|
||||||
# 'fiat_value': 0.0, 'trade_count': 2}
|
# 'fiat_value': 0.0, 'trade_count': 2}
|
||||||
assert day['abs_profit'] in (0.0, pytest.approx(13.8299999), pytest.approx(-4.0))
|
assert day['abs_profit'] in (0.0, pytest.approx(13.8299999), pytest.approx(-4.0))
|
||||||
|
assert day['rel_profit'] in (0.0, pytest.approx(0.01310441), pytest.approx(-0.00377583))
|
||||||
assert day['trade_count'] in (0, 1, 2)
|
assert day['trade_count'] in (0, 1, 2)
|
||||||
|
assert day['starting_balance'] in (pytest.approx(1059.37), pytest.approx(1055.37))
|
||||||
assert day['fiat_value'] in (0.0, )
|
assert day['fiat_value'] in (0.0, )
|
||||||
# ensure first day is current date
|
# ensure first day is current date
|
||||||
assert str(days['data'][0]['date']) == str(datetime.utcnow().date())
|
assert str(days['data'][0]['date']) == str(datetime.utcnow().date())
|
||||||
|
@ -432,9 +432,9 @@ def test_daily_handle(default_conf_usdt, update, ticker, fee, mocker) -> None:
|
|||||||
assert str(datetime.utcnow().date()) in msg_mock.call_args_list[0][0][0]
|
assert str(datetime.utcnow().date()) in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 13.83 USDT' in msg_mock.call_args_list[0][0][0]
|
assert ' 13.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 15.21 USD' in msg_mock.call_args_list[0][0][0]
|
assert ' 15.21 USD' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 2 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(2)' in msg_mock.call_args_list[0][0][0]
|
||||||
assert '13.83 USDT 15.21 USD 2 trades' in msg_mock.call_args_list[0][0][0]
|
assert '(2) 13.83 USDT 15.21 USD 1.31%' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 0 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(0)' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
# Reset msg_mock
|
# Reset msg_mock
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
@ -446,9 +446,9 @@ def test_daily_handle(default_conf_usdt, update, ticker, fee, mocker) -> None:
|
|||||||
assert str((datetime.utcnow() - timedelta(days=5)).date()) in msg_mock.call_args_list[0][0][0]
|
assert str((datetime.utcnow() - timedelta(days=5)).date()) in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 13.83 USDT' in msg_mock.call_args_list[0][0][0]
|
assert ' 13.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 15.21 USD' in msg_mock.call_args_list[0][0][0]
|
assert ' 15.21 USD' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 2 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(2)' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 1 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(1)' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 0 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(0)' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
# Reset msg_mock
|
# Reset msg_mock
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
@ -459,7 +459,7 @@ def test_daily_handle(default_conf_usdt, update, ticker, fee, mocker) -> None:
|
|||||||
telegram._daily(update=update, context=context)
|
telegram._daily(update=update, context=context)
|
||||||
assert ' 13.83 USDT' in msg_mock.call_args_list[0][0][0]
|
assert ' 13.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 15.21 USD' in msg_mock.call_args_list[0][0][0]
|
assert ' 15.21 USD' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 2 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(2)' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
|
|
||||||
def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None:
|
def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None:
|
||||||
@ -521,8 +521,8 @@ def test_weekly_handle(default_conf_usdt, update, ticker, fee, mocker) -> None:
|
|||||||
assert str(first_iso_day_of_current_week) in msg_mock.call_args_list[0][0][0]
|
assert str(first_iso_day_of_current_week) in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 3 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(3)' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 0 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(0)' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
# Reset msg_mock
|
# Reset msg_mock
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
@ -534,8 +534,8 @@ def test_weekly_handle(default_conf_usdt, update, ticker, fee, mocker) -> None:
|
|||||||
assert 'Weekly' in msg_mock.call_args_list[0][0][0]
|
assert 'Weekly' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 3 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(3)' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 0 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(0)' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
# Try invalid data
|
# Try invalid data
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
@ -589,8 +589,8 @@ def test_monthly_handle(default_conf_usdt, update, ticker, fee, mocker) -> None:
|
|||||||
assert current_month in msg_mock.call_args_list[0][0][0]
|
assert current_month in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 3 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(3)' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 0 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(0)' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
# Reset msg_mock
|
# Reset msg_mock
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
@ -603,8 +603,8 @@ def test_monthly_handle(default_conf_usdt, update, ticker, fee, mocker) -> None:
|
|||||||
assert current_month in msg_mock.call_args_list[0][0][0]
|
assert current_month in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 3 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(3)' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 0 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(0)' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
# Reset msg_mock
|
# Reset msg_mock
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
@ -617,7 +617,7 @@ def test_monthly_handle(default_conf_usdt, update, ticker, fee, mocker) -> None:
|
|||||||
assert 'Monthly Profit over the last 12 months</b>:' in msg_mock.call_args_list[0][0][0]
|
assert 'Monthly Profit over the last 12 months</b>:' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
assert ' 9.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
assert ' 10.81 USD' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 3 trade' in msg_mock.call_args_list[0][0][0]
|
assert '(3)' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
# The one-digit months should contain a zero, Eg: September 2021 = "2021-09"
|
# The one-digit months should contain a zero, Eg: September 2021 = "2021-09"
|
||||||
# Since we loaded the last 12 months, any month should appear
|
# Since we loaded the last 12 months, any month should appear
|
||||||
|
Loading…
Reference in New Issue
Block a user