Add win/loss metrics to archive stats with symbol filter sync.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-21 09:03:21 +08:00
parent 073a382d41
commit c05afbbedf
5 changed files with 174 additions and 36 deletions
+71
View File
@@ -11,12 +11,15 @@ from zoneinfo import ZoneInfo
from hub_symbol_archive_lib import (
CHART_DISPLAY_TZ,
_compute_period_stats,
_fill_missing_bars,
init_db,
list_daily_trades,
load_symbol_trades,
ms_to_wall_clock_str,
parse_wall_clock_ms,
resolve_archive_chart,
trading_day_bounds_ms,
upsert_bars_5m,
upsert_trade_overlay,
list_symbol_rows,
@@ -271,3 +274,71 @@ def test_upsert_forces_sync_exchange_key():
assert len(rows) == 1
assert rows[0]["exchange_key"] == "gate_bot"
assert "account_exchange_key" not in rows[0]
def test_compute_period_stats_win_loss_metrics():
rows = [
{"exchange_key": "binance", "pnl_amount": 10.0, "behavior_tag": ""},
{"exchange_key": "binance", "pnl_amount": 4.0, "behavior_tag": ""},
{"exchange_key": "okx", "pnl_amount": -3.0, "behavior_tag": "sick"},
{"exchange_key": "okx", "pnl_amount": -6.0, "behavior_tag": ""},
]
st = _compute_period_stats(rows)
assert st["open_count"] == 4
assert st["win_count"] == 2
assert st["loss_count"] == 2
assert st["avg_win"] == 7.0
assert st["avg_loss"] == -4.5
assert st["max_win"] == 10.0
assert st["max_loss"] == -6.0
assert st["sick_count"] == 1
assert st["pnl_total"] == 5.0
assert st["pnl_ex_sick"] == 8.0
assert st["by_exchange"]["binance"]["win_count"] == 2
def test_list_daily_trades_search_filters_stats():
with tempfile.TemporaryDirectory() as td:
db = Path(td) / "archive.db"
init_db(db)
day = "2023-11-15"
start_ms, _ = trading_day_bounds_ms(day)
btc_close = start_ms + 3_600_000
eth_close = start_ms + 7_200_000
upsert_trades_cache(
"gate",
[
{
"id": 1,
"symbol": "BTC/USDT",
"result": "止盈",
"pnl_amount": 5.0,
"opened_at_ms": start_ms,
"closed_at_ms": btc_close,
},
{
"id": 2,
"symbol": "ETH/USDT",
"result": "止损",
"pnl_amount": -2.0,
"opened_at_ms": btc_close,
"closed_at_ms": eth_close,
},
],
db_path=db,
)
payload = list_daily_trades(
period="range",
date_from=day,
date_to=day,
search="btc",
db_path=db,
)
assert len(payload["trades"]) == 1
assert payload["trades"][0]["symbol"] == "BTC/USDT"
st = payload["stats"]
assert st["open_count"] == 1
assert st["win_count"] == 1
assert st["loss_count"] == 0
assert st["max_win"] == 5.0
assert st["pnl_total"] == 5.0