Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/telegram-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ Return the performance of each crypto-currency the bot has sold.
> 5. `STORJ/BTC 0.0009 BTC (27.24%) (1)`
> ...

The relative performance is calculated against the total investment in the currency, aggregating all filled entries for the currency.

### /balance

Return the balance of all crypto-currency your have on the exchange.
Expand Down
39 changes: 36 additions & 3 deletions freqtrade/persistence/trade_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
Select,
String,
UniqueConstraint,
case,
desc,
func,
select,
Expand Down Expand Up @@ -1934,17 +1935,49 @@ def get_overall_performance(minutes=None) -> list[dict[str, Any]]:
start_date = datetime.now(timezone.utc) - timedelta(minutes=minutes)
filters.append(Trade.close_date >= start_date)

pair_rates = Trade.session.execute(
pair_costs = (
select(
Trade.pair,
func.sum(
(
func.coalesce(Order.filled, Order.amount)
* func.coalesce(Order.average, Order.price, Order.ft_price)
)
/ func.coalesce(Trade.leverage, 1)
).label("cost_per_pair"),
)
.join(Order, Trade.id == Order.ft_trade_id)
.filter(
*filters,
Order.ft_order_side == case((Trade.is_short.is_(True), "sell"), else_="buy"),
)
# Order.filled.gt > 0
.group_by(Trade.pair)
.cte("pair_costs")
)
trades_grouped = (
select(
Trade.pair,
func.sum(Trade.close_profit).label("profit_sum"),
func.sum(Trade.close_profit_abs).label("profit_sum_abs"),
func.count(Trade.pair).label("count"),
)
.filter(*filters)
.group_by(Trade.pair)
.cte("trades_grouped")
)
q = (
select(
trades_grouped.c.pair,
(trades_grouped.c.profit_sum_abs / pair_costs.c.cost_per_pair).label(
"profit_ratio"
),
trades_grouped.c.profit_sum_abs,
trades_grouped.c.count,
)
.join(pair_costs, trades_grouped.c.pair == pair_costs.c.pair)
.order_by(desc("profit_sum_abs"))
).all()
)
pair_rates = Trade.session.execute(q).all()

return [
{
Expand Down
2 changes: 1 addition & 1 deletion tests/rpc/test_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@ def test_performance_handle(default_conf_usdt, ticker, fee, mocker) -> None:
assert res[0]["pair"] == "NEO/USDT"
assert res[0]["count"] == 1
assert res[0]["profit_abs"] == 3.9875
assert res[0]["profit_pct"] == 5.0
assert res[0]["profit_pct"] == 1.99


def test_enter_tag_performance_handle(default_conf, ticker, fee, mocker) -> None:
Expand Down
18 changes: 9 additions & 9 deletions tests/rpc/test_rpc_apiserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -1166,26 +1166,26 @@ def test_api_performance(botclient, fee):
{
"count": 1,
"pair": "NEO/USDT",
"profit": 5.0,
"profit_pct": 5,
"profit_ratio": 0.05,
"profit": 1.99,
"profit_pct": 1.99,
"profit_ratio": 0.0199375,
"profit_abs": 3.9875,
},
{
"count": 1,
"pair": "XRP/USDT",
"profit": 10.0,
"profit": 9.47,
"profit_abs": 2.8425,
"profit_pct": 10.0,
"profit_ratio": 0.1,
"profit_pct": 9.47,
"profit_ratio": pytest.approx(0.094749999),
},
{
"count": 1,
"pair": "LTC/USDT",
"profit": -20.0,
"profit": -20.45,
"profit_abs": -4.09,
"profit_pct": -20.0,
"profit_ratio": -0.2,
"profit_pct": -20.45,
"profit_ratio": -0.2045,
},
]

Expand Down
2 changes: 1 addition & 1 deletion tests/rpc/test_rpc_telegram.py
Original file line number Diff line number Diff line change
Expand Up @@ -1591,7 +1591,7 @@ async def test_telegram_performance_handle(default_conf_usdt, update, ticker, fe
await telegram._performance(update=update, context=MagicMock())
assert msg_mock.call_count == 1
assert "Performance" in msg_mock.call_args_list[0][0][0]
assert "<code>XRP/USDT\t2.842 USDT (10.00%) (1)</code>" in msg_mock.call_args_list[0][0][0]
assert "<code>XRP/USDT\t2.842 USDT (9.47%) (1)</code>" in msg_mock.call_args_list[0][0][0]


async def test_telegram_entry_tag_performance_handle(
Expand Down
Loading