feat: persist skipped ledger fills
Co-authored-by: genichin <4282227+genichin@users.noreply.github.com>
This commit is contained in:
co-authored by
genichin
parent
df0258bc36
commit
76cde2edd0
@@ -0,0 +1,98 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from uuid import UUID
|
||||
|
||||
from trex_core.application.alarm_emitter import AlarmEmitter
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class LedgerSkipRecord:
|
||||
skip_key: str
|
||||
instance_key: str
|
||||
slot_id: UUID
|
||||
portfolio_id: str | None
|
||||
symbol: str | None
|
||||
order_id: str | None
|
||||
execution_id: str | None
|
||||
side: str
|
||||
qty: float
|
||||
price: float
|
||||
executed_at: datetime
|
||||
order_venue: str
|
||||
execution_venue: str
|
||||
skip_reason: str
|
||||
status: str
|
||||
resolution_reason: str | None
|
||||
resolved_at: datetime | None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
def make_ledger_skip_key(
|
||||
*,
|
||||
instance_key: str,
|
||||
slot_id: UUID,
|
||||
side: str,
|
||||
order_id: str | None,
|
||||
execution_id: str | None,
|
||||
skip_reason: str,
|
||||
) -> str:
|
||||
return ":".join(
|
||||
[
|
||||
"ledger-skip",
|
||||
instance_key,
|
||||
str(slot_id),
|
||||
side,
|
||||
order_id or "-",
|
||||
execution_id or "-",
|
||||
skip_reason,
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def ledger_skip_alarm_fields(record: LedgerSkipRecord) -> dict[str, object]:
|
||||
return {
|
||||
"skip_key": record.skip_key,
|
||||
"instance_key": record.instance_key,
|
||||
"slot_id": str(record.slot_id),
|
||||
"portfolio_id": record.portfolio_id,
|
||||
"symbol": record.symbol,
|
||||
"order_id": record.order_id,
|
||||
"execution_id": record.execution_id,
|
||||
"side": record.side,
|
||||
"qty": record.qty,
|
||||
"price": record.price,
|
||||
"executed_at": record.executed_at.isoformat(),
|
||||
"order_venue": record.order_venue,
|
||||
"execution_venue": record.execution_venue,
|
||||
"skip_reason": record.skip_reason,
|
||||
"status": record.status,
|
||||
"resolution_reason": record.resolution_reason,
|
||||
"resolved_at": record.resolved_at.isoformat() if record.resolved_at else None,
|
||||
"created_at": record.created_at.isoformat(),
|
||||
"updated_at": record.updated_at.isoformat(),
|
||||
}
|
||||
|
||||
|
||||
def publish_ledger_skip_alarm(
|
||||
alarm_emitter: AlarmEmitter | None,
|
||||
record: LedgerSkipRecord,
|
||||
*,
|
||||
resolved: bool,
|
||||
) -> None:
|
||||
if alarm_emitter is None:
|
||||
return
|
||||
code = "ledger_skip_resolved" if resolved else "ledger_skip_unresolved"
|
||||
title = (
|
||||
f"원장 skip 해소: slot={record.slot_id} reason={record.resolution_reason or 'resolved'}"
|
||||
if resolved
|
||||
else f"원장 skip 발생: slot={record.slot_id} reason={record.skip_reason}"
|
||||
)
|
||||
alarm_emitter.publish_alarm(
|
||||
code,
|
||||
title,
|
||||
fields=ledger_skip_alarm_fields(record),
|
||||
severity="info" if resolved else "critical",
|
||||
)
|
||||
Reference in New Issue
Block a user