본문으로 건너뛰기

Audit log (broker_order_events)

broker_order_events 테이블은 모든 주문 시도와 broker 응답을 시간순으로 기록합니다. 트러블슈팅, 컴플라이언스, reconciliation의 source-of-truth입니다.

📸 broker_order_events 테이블 뷰 (추후 자동 캡처 예정)

이벤트 타입

event_type발생 시점
placedbroker가 주문 접수
rejectedrisk-rule 위반 또는 broker 거부
canceled사용자 취소
filled부분/전체 체결
expiredTIF 만료
live_request_confirm라이브 활성화 토큰 발급
live_enabled / live_disabled라이브 모드 토글

컬럼 구조

컬럼타입의미
idbigintPK
order_idtextclient_order_id 또는 합성 ID
user_idint소유자 (FK)
brokertextbinance / alpaca / kis / live_gating
event_typetext위 표 참고
payloadjsonb요청/응답 원본
correlation_idtext같은 주문 흐름 묶기
created_attimestamptz이벤트 발생 시각

UI 노출

현재 별도 Audit 페이지는 없습니다. 다음 위치에서 간접 활용됩니다.

위치역할
Trades 페이지filled 이벤트 → 거래 행 생성
Reconciliationbroker drift 추적
Equity 페이지 cancel 버튼canceled 이벤트 기록

전용 viewer는 후속 작업이며, 현재는 SQL 직접 조회를 권장합니다.

SQL 조회 예시

SELECT id, broker, event_type, created_at, payload->>'reason' AS reason
FROM broker_order_events
WHERE user_id = $1
AND created_at > now() - interval '1 day'
ORDER BY created_at DESC
LIMIT 100;

거부 이벤트 분석

event_type = 'rejected' 행의 payload.code로 거부 사유를 그룹화하면 자주 발생하는 문제를 파악할 수 있습니다.

code원인
RISK_RULE_VIOLATIONper-trade cap, daily loss 등 위반
MARKET_CLOSED정규장 외 주문
INSUFFICIENT_FUNDS매수 가능 한도 부족
BROKER_REJECTEDbroker 자체 거부 (호가 단위, 거래 정지 등)
BROKER_UNAVAILABLEbroker API 5xx / timeout

절대 룰

멀티사용자 격리

모든 SELECT는 반드시 user_id = current_user.id 필터를 포함해야 합니다. 라우터 레이어에서 강제하지만, 직접 SQL을 작성할 때도 동일하게 적용하세요.

자주 묻는 질문

Q. live 활성화 흐름도 여기 기록되나요?
A. 네. event_type='live_request_confirm' / 'live_enabled' / 'live_disabled'로 broker 컬럼은 live_gating이 됩니다.

Q. payload가 너무 커요. 인덱싱은?
A. (user_id, created_at) 복합 인덱스가 기본입니다. JSONB 키를 자주 검색하면 GIN 인덱스를 추가하세요.

Q. 데이터 보관 기간은?
A. 기본 무기한. 운영 정책에 따라 90일/365일 partition을 두는 것을 권장합니다.

관련 페이지