cedc8d79ee
Renumbers the four 2026-08-07 slices (ApprovalWorkflow, AuditTrail, TradeExecution, PortfolioReconciliation) to previously-unused VS-26..29, leaving WBS_MASTER.csv's original VS-03/04/12/14 definitions (IngestMarketDataPIT, ApplyCorporateActions, RankBuyCandidates, GenerateDailyRecommendations) untouched, per docs/DECISIONS/ADR-WBS-001-slice-renumbering.md. While investigating, found two things not yet resolved by this commit: - DEBT-017 (duplicate ApprovalWorkflow implementation): the tested backend (ApprovalWorkflow/) is [DontRegister]'d dead code; the live one (Features/ApprovalWorkflow/, wired in Program.cs) has no dedicated tests. AEG-VS-26-01 downgraded from COMPLETED to BLOCKED in the tracker pending an architect decision on which implementation is canonical. - Features/MarketData and Features/Portfolio (VS-03/04/05/08 Market Data Ingestion Dashboard, Portfolio Rebalance, Risk Metrics, Dashboard) are a third, already-implemented-and-tested body of work entirely absent from WBS_PROGRESS_TRACKER.csv. Flagged in CURRENT_ROADMAP.md as a follow-up. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
225 lines
5.4 KiB
Markdown
225 lines
5.4 KiB
Markdown
# VS-28: Trade Execution System (KIS Integration)
|
|
|
|
**Vertical Slice:** VS-28 (Trade Execution)
|
|
**Version:** 1.0 COMPLETE
|
|
**Date:** 2026-08-07
|
|
**Owner:** Backend Lead + Trading Ops
|
|
**Status:** ✅ READY FOR IMPLEMENTATION
|
|
**Depends On:** VS-10 (sell decisions), VS-26 (approval), VS-27 (audit)
|
|
|
|
---
|
|
|
|
## 📋 User Story
|
|
|
|
**As a** trading operations officer
|
|
**I want to** execute approved sell decisions through KIS API
|
|
**So that** portfolios are rebalanced automatically with full audit trail
|
|
|
|
**Acceptance Criteria:**
|
|
- ✅ Execute trade only after VS-26 approval
|
|
- ✅ Submit order to KIS, track order status
|
|
- ✅ Handle partial fills and slippage
|
|
- ✅ Confirm settlement and update cost basis
|
|
- ✅ Classify errors (transient/permanent/liquidity)
|
|
- ✅ All state changes logged (VS-27 audit)
|
|
|
|
---
|
|
|
|
## 🎯 Non-Goals
|
|
|
|
- ❌ Real-time market feeds (separate slice)
|
|
- ❌ Algorithm execution (beyond KIS API)
|
|
- ❌ Manual order override (compliance requirement)
|
|
- ❌ Cross-exchange routing (KIS only)
|
|
|
|
---
|
|
|
|
## 🔄 State Machine
|
|
|
|
```
|
|
PENDING (created from sell decision)
|
|
↓
|
|
SUBMITTED (sent to KIS)
|
|
↓
|
|
ACCEPTED (KIS confirmed receipt)
|
|
↓
|
|
PARTIAL_FILLED / FULLY_FILLED (execution progress)
|
|
↓
|
|
CONFIRMED (settlement confirmed)
|
|
↓
|
|
RECONCILED (cost basis updated by VS-29)
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Data Schema
|
|
|
|
```sql
|
|
CREATE TABLE trades (
|
|
id UUID PRIMARY KEY,
|
|
sell_decision_id UUID NOT NULL REFERENCES sell_decisions(id),
|
|
kis_order_id VARCHAR(50), -- KIS-assigned order ID
|
|
status VARCHAR(50) NOT NULL, -- PENDING, SUBMITTED, ACCEPTED, FILLED, CONFIRMED, RECONCILED
|
|
quantity INT NOT NULL,
|
|
executed_quantity INT,
|
|
unit_price DECIMAL(15,2),
|
|
total_amount DECIMAL(18,2),
|
|
commission DECIMAL(15,2),
|
|
net_proceeds DECIMAL(18,2),
|
|
error_message TEXT,
|
|
kis_response JSONB, -- Full KIS API response (order details, fills, errors)
|
|
execution_timestamp TIMESTAMPTZ,
|
|
settlement_timestamp TIMESTAMPTZ,
|
|
published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
correlation_id UUID NOT NULL,
|
|
revision INT NOT NULL DEFAULT 1
|
|
);
|
|
|
|
CREATE INDEX idx_trades_decision_id ON trades(sell_decision_id);
|
|
CREATE INDEX idx_trades_status ON trades(status);
|
|
CREATE INDEX idx_trades_kis_order_id ON trades(kis_order_id);
|
|
CREATE INDEX idx_trades_correlation_id ON trades(correlation_id);
|
|
```
|
|
|
|
---
|
|
|
|
## 🔐 API Contract
|
|
|
|
### POST /trades (Create Trade)
|
|
|
|
**Role:** System (after VS-26 approval)
|
|
**Request:**
|
|
```json
|
|
{
|
|
"sellDecisionId": "uuid",
|
|
"quantity": 1000,
|
|
"limitPrice": 50.00
|
|
}
|
|
```
|
|
**Response (202 Accepted):**
|
|
```json
|
|
{
|
|
"id": "trade-uuid",
|
|
"status": "PENDING",
|
|
"sellDecisionId": "uuid",
|
|
"quantity": 1000
|
|
}
|
|
```
|
|
|
|
### GET /trades (List)
|
|
|
|
**Query:** `status=FILLED&sellDecisionId=uuid`
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"items": [
|
|
{
|
|
"id": "trade-uuid",
|
|
"status": "CONFIRMED",
|
|
"quantity": 1000,
|
|
"executedQuantity": 1000,
|
|
"unitPrice": 49.95,
|
|
"totalAmount": 49950,
|
|
"commission": 50,
|
|
"netProceeds": 49900
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🔄 KIS API Integration
|
|
|
|
**Service:** `KisTradeExecutionService`
|
|
|
|
```csharp
|
|
ExecuteTradeAsync(tradeId, quantity, limitPrice, correlationId)
|
|
GetOrderStatusAsync(kisOrderId, correlationId)
|
|
CancelOrderAsync(kisOrderId, reason, correlationId)
|
|
ConfirmSettlementAsync(kisOrderId, correlationId)
|
|
```
|
|
|
|
**Error Classification:**
|
|
- **Transient:** Network timeout, rate limit → Retry with backoff
|
|
- **Permanent:** Invalid order, insufficient funds → Log & alert
|
|
- **Liquidity:** Partial fill, slippage > threshold → Manual review queue
|
|
|
|
---
|
|
|
|
## 🔧 Handlers & Jobs
|
|
|
|
### SubmitTradeHandler
|
|
- Create trade record (status=PENDING)
|
|
- Submit to KIS
|
|
- Update status=SUBMITTED on success
|
|
- Classify error if failure
|
|
|
|
### PollTradeStatusJob (Hangfire q-evaluation)
|
|
- Poll KIS every 1 minute (configurable)
|
|
- Update trade status (ACCEPTED, FILLED)
|
|
- Trigger ConfirmSettlementHandler when FILLED
|
|
|
|
### ConfirmSettlementHandler
|
|
- Wait 1 business day after FILLED
|
|
- Confirm settlement with KIS
|
|
- Update status=CONFIRMED
|
|
- Emit event to VS-29 (reconciliation)
|
|
|
|
### ReconcileTradeHandler
|
|
- Receive settlement event
|
|
- Update status=RECONCILED
|
|
- Mark ready for VS-29 processing
|
|
|
|
---
|
|
|
|
## ✅ Governance Gates
|
|
|
|
### Pre-Merge Gates
|
|
- [x] SLICE_SPEC complete
|
|
- [x] API contract finalized
|
|
- [x] KIS error classification designed
|
|
- [x] Idempotency key strategy (kis_order_id dedup)
|
|
|
|
### Post-Merge Validation
|
|
- [ ] Unit tests: 12/12 PASS
|
|
- [ ] Integration tests: 8/8 PASS
|
|
- [ ] Failure scenario tests: 3/3 PASS
|
|
- [ ] No SELECT *, schema-qualified SQL
|
|
- [ ] Immutable trades (INSERT-only)
|
|
- [ ] Correlation_id traceability
|
|
|
|
---
|
|
|
|
## 🛡️ Security & Compliance
|
|
|
|
**Immutability Guarantees:**
|
|
- INSERT-only trade records (no UPDATE)
|
|
- Timestamp immutable after insertion
|
|
- kis_response JSONB for full audit trail
|
|
|
|
**Error Classification:**
|
|
- Transient: Network issues, retryable
|
|
- Permanent: Invalid input, authorization
|
|
- Liquidity: Partial fills, slippage
|
|
|
|
**RBAC:**
|
|
- System role: Submit trades (via VS-26 approval)
|
|
- Operations: View & monitor execution
|
|
- Audit: Query immutable trail
|
|
|
|
---
|
|
|
|
## 📋 Related Specifications
|
|
|
|
- **VS-10:** Sell Decision (generates trades)
|
|
- **VS-26:** Approval Workflow (prerequisite)
|
|
- **VS-27:** Audit Trail (logs all state changes)
|
|
- **VS-29:** Portfolio Reconciliation (consumes trade settlement)
|
|
|
|
---
|
|
|
|
**Co-Authored-By:** Claude Haiku 4.5 <noreply@anthropic.com>
|
|
**Status:** ✅ READY FOR IMPLEMENTATION
|
|
**Next:** Database migration, KIS service implementation
|