46963a4498
Co-authored-by: Cursor <cursoragent@cursor.com>
116 lines
4.4 KiB
Python
116 lines
4.4 KiB
Python
"""档案交易:复盘字段优先(开仓类型、持仓时长、开平仓时间)。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import tempfile
|
|
import unittest
|
|
from datetime import datetime, timedelta
|
|
from pathlib import Path
|
|
|
|
from hub_symbol_archive_lib import init_db, load_symbol_trades, upsert_trades_cache
|
|
from hub_trades_lib import (
|
|
_normalize_archive_trade_row,
|
|
display_entry_type_label,
|
|
effective_entry_type,
|
|
effective_hold_minutes,
|
|
)
|
|
|
|
|
|
class TestHubTradesReviewFields(unittest.TestCase):
|
|
def test_display_entry_type_for_manual_monitor_review(self):
|
|
d = {
|
|
"monitor_type": "下单监控",
|
|
"entry_reason": "",
|
|
"reviewed_entry_reason": "突破回踩",
|
|
"reviewed_at": "2026-06-08 10:00:00",
|
|
}
|
|
self.assertEqual(display_entry_type_label(d), "突破回踩")
|
|
|
|
def test_effective_entry_type_prefers_reviewed(self):
|
|
d = {
|
|
"entry_reason": "突破回踩",
|
|
"reviewed_entry_reason": "趋势回调",
|
|
"monitor_type": "下单监控",
|
|
}
|
|
self.assertEqual(effective_entry_type(d), "趋势回调")
|
|
|
|
def test_effective_hold_minutes_prefers_reviewed(self):
|
|
d = {
|
|
"hold_minutes": 30,
|
|
"reviewed_hold_minutes": 95,
|
|
"opened_at_ms": 1_700_000_000_000,
|
|
"closed_at_ms": 1_700_001_800_000,
|
|
}
|
|
self.assertEqual(effective_hold_minutes(d), 95)
|
|
|
|
def test_normalize_archive_trade_row_review_fields(self):
|
|
closed = (datetime.now() - timedelta(days=2)).strftime("%Y-%m-%d %H:%M:%S")
|
|
opened = (datetime.now() - timedelta(days=2, hours=2)).strftime("%Y-%m-%d %H:%M:%S")
|
|
row = _normalize_archive_trade_row(
|
|
{
|
|
"id": 9,
|
|
"symbol": "ONDO/USDT",
|
|
"direction": "short",
|
|
"result": "止损",
|
|
"reviewed_result": "手动平仓",
|
|
"pnl_amount": -2.5,
|
|
"reviewed_pnl_amount": -2.58,
|
|
"opened_at": opened,
|
|
"reviewed_opened_at": "2026-06-07 14:30:00",
|
|
"closed_at": closed,
|
|
"reviewed_closed_at": "2026-06-08 08:44:21",
|
|
"opened_at_ms": 1_700_000_000_000,
|
|
"closed_at_ms": 1_700_007_200_000,
|
|
"entry_reason": "突破回踩",
|
|
"reviewed_entry_reason": "趋势回调",
|
|
"hold_minutes": 30,
|
|
"reviewed_hold_minutes": 1080,
|
|
"monitor_type": "趋势回调",
|
|
"reviewed_at": closed,
|
|
},
|
|
exchange_key="gate",
|
|
)
|
|
self.assertIsNotNone(row)
|
|
assert row is not None
|
|
self.assertEqual(row["entry_type"], "趋势回调")
|
|
self.assertEqual(row["hold_minutes"], 1080)
|
|
self.assertEqual(row["opened_at"], "2026-06-07 14:30:00")
|
|
self.assertEqual(row["closed_at"], "2026-06-08 08:44:21")
|
|
self.assertTrue(row["reviewed"])
|
|
|
|
def test_archive_cache_enriches_review_display_fields(self):
|
|
with tempfile.TemporaryDirectory() as td:
|
|
db = Path(td) / "archive.db"
|
|
init_db(db)
|
|
upsert_trades_cache(
|
|
"gate",
|
|
[
|
|
{
|
|
"id": 3,
|
|
"symbol": "ONDO/USDT",
|
|
"direction": "short",
|
|
"result": "手动平仓",
|
|
"pnl_amount": -2.58,
|
|
"opened_at": "2026-06-07 14:30:00",
|
|
"closed_at": "2026-06-08 08:44:21",
|
|
"opened_at_ms": 1_781_000_000_000,
|
|
"closed_at_ms": 1_781_065_000_000,
|
|
"entry_type": "趋势回调",
|
|
"hold_minutes": 1080,
|
|
"hold_minutes_text": "18小时0分钟",
|
|
"reviewed": True,
|
|
}
|
|
],
|
|
db_path=db,
|
|
)
|
|
rows = load_symbol_trades("gate", "ONDO/USDT", db_path=db)
|
|
self.assertEqual(len(rows), 1)
|
|
self.assertEqual(rows[0]["entry_type"], "趋势回调")
|
|
self.assertEqual(rows[0]["hold_minutes"], 1080)
|
|
self.assertTrue(rows[0]["opened_at"].startswith("2026-06-07"))
|
|
self.assertTrue(rows[0]["closed_at"].startswith("2026-06-08"))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|