feat: Add performance metrics dashboard and metrics calculator
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import UTC, datetime, timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
from arbitrade.config.settings import Settings
|
||||
from arbitrade.metrics import MetricsCalculator
|
||||
from arbitrade.storage.db import DuckDBStore
|
||||
|
||||
|
||||
def test_metrics_calculator_summarizes_execution_data(tmp_path) -> None:
|
||||
settings = Settings(_env_file=None, DUCKDB_PATH=tmp_path / "metrics.duckdb")
|
||||
store = DuckDBStore(settings)
|
||||
store.migrate()
|
||||
|
||||
started = datetime.now(UTC)
|
||||
finished = started + timedelta(seconds=30)
|
||||
started_two = started + timedelta(minutes=1)
|
||||
finished_two = started_two + timedelta(seconds=90)
|
||||
|
||||
with store.connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO trades (
|
||||
trade_ref,
|
||||
started_at,
|
||||
finished_at,
|
||||
status,
|
||||
realized_pnl,
|
||||
estimated_pnl,
|
||||
capital_used,
|
||||
cycle,
|
||||
leg_count
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
[
|
||||
"trade-1",
|
||||
started,
|
||||
finished,
|
||||
"filled",
|
||||
12.5,
|
||||
10.0,
|
||||
100.0,
|
||||
"USD->BTC->ETH->USD",
|
||||
3,
|
||||
"trade-2",
|
||||
started_two,
|
||||
finished_two,
|
||||
"filled",
|
||||
-4.5,
|
||||
-2.0,
|
||||
200.0,
|
||||
"USD->ETH->BTC->USD",
|
||||
3,
|
||||
],
|
||||
)
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO opportunities (
|
||||
detected_at,
|
||||
cycle,
|
||||
gross_pct,
|
||||
net_pct,
|
||||
est_profit,
|
||||
executed
|
||||
) VALUES (?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
[
|
||||
started,
|
||||
"USD->BTC->ETH->USD",
|
||||
4.0,
|
||||
3.0,
|
||||
0.03,
|
||||
True,
|
||||
started_two,
|
||||
"USD->ETH->BTC->USD",
|
||||
2.0,
|
||||
1.0,
|
||||
0.01,
|
||||
False,
|
||||
started_two + timedelta(seconds=30),
|
||||
"USD->BTC->ETH->USD",
|
||||
5.0,
|
||||
4.0,
|
||||
0.04,
|
||||
True,
|
||||
],
|
||||
)
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO orders (
|
||||
trade_ref,
|
||||
order_ref,
|
||||
leg_index,
|
||||
pair,
|
||||
side,
|
||||
volume,
|
||||
user_ref,
|
||||
status,
|
||||
filled_volume,
|
||||
avg_price,
|
||||
raw_response,
|
||||
recorded_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
[
|
||||
"trade-1",
|
||||
"order-1",
|
||||
0,
|
||||
"BTC/USD",
|
||||
"buy",
|
||||
2.0,
|
||||
101,
|
||||
"closed",
|
||||
2.0,
|
||||
100.0,
|
||||
"{}",
|
||||
started,
|
||||
"trade-2",
|
||||
"order-2",
|
||||
0,
|
||||
"ETH/USD",
|
||||
"sell",
|
||||
4.0,
|
||||
202,
|
||||
"closed",
|
||||
3.0,
|
||||
200.0,
|
||||
"{}",
|
||||
started_two,
|
||||
],
|
||||
)
|
||||
|
||||
metrics = MetricsCalculator(store).compute()
|
||||
|
||||
assert metrics.realized_pnl_usd == 8.0
|
||||
assert metrics.win_rate == 0.5
|
||||
assert metrics.avg_trade_duration_seconds == 60.0
|
||||
assert metrics.opportunities_per_minute == 2.0
|
||||
assert metrics.fill_rate == 0.875
|
||||
assert metrics.latency_p50_seconds == 60.0
|
||||
assert metrics.latency_p95_seconds == 87.0
|
||||
assert metrics.latency_p99_seconds == pytest.approx(89.4)
|
||||
Reference in New Issue
Block a user