// 모의투자(Paper Trading) 도메인 타입 — Backend Application/Features/Api/Paper/*/Response.cs 대응 (camelCase 직렬화) // enum 은 Backend Response DTO 에서 .ToString() 으로 문자열화됨 (Stocks 컨벤션 통일 — enum.ToString() PascalCase). // 값은 Domain/Entities/Paper/ValueObject/* 의 enum 멤버명과 정확히 일치. // ── enum (문자열 값 = enum 멤버명, d4 §③ / Domain/Entities/Paper/ValueObject/*) ── export const PaperOrderSide = { Buy: 'Buy', Sell: 'Sell' } as const; export type PaperOrderSideValue = (typeof PaperOrderSide)[keyof typeof PaperOrderSide]; export const PaperFillRule = { Open: 'Open', Close: 'Close' } as const; export type PaperFillRuleValue = (typeof PaperFillRule)[keyof typeof PaperFillRule]; export const PaperOrderStatus = { Pending: 'Pending', Filled: 'Filled', Cancelled: 'Cancelled', Rejected: 'Rejected' } as const; export type PaperOrderStatusValue = (typeof PaperOrderStatus)[keyof typeof PaperOrderStatus]; export const PaperLedgerType = { Deposit: 'Deposit', Withdraw: 'Withdraw' } as const; export type PaperLedgerTypeValue = (typeof PaperLedgerType)[keyof typeof PaperLedgerType]; // ── 표시 라벨 ── export const PAPER_SIDE_LABEL: Record = { [PaperOrderSide.Buy]: '매수', [PaperOrderSide.Sell]: '매도' }; export const PAPER_FILL_RULE_LABEL: Record = { [PaperFillRule.Open]: '시가', [PaperFillRule.Close]: '종가' }; export const PAPER_ORDER_STATUS_LABEL: Record = { [PaperOrderStatus.Pending]: '접수', [PaperOrderStatus.Filled]: '체결', [PaperOrderStatus.Cancelled]: '취소', [PaperOrderStatus.Rejected]: '거부' }; export const PAPER_LEDGER_TYPE_LABEL: Record = { [PaperLedgerType.Deposit]: '입금', [PaperLedgerType.Withdraw]: '출금' }; // ── GET /api/paper/account ── export interface PaperAccountResponse { hasAccount: boolean; token: number; reservedToken: number; units: number; equity: number; cumReturnBp: number; positionsCount: number; } // ── POST /api/paper/account/deposit ── export interface PaperDepositResponse { token: number; units: number; unitsIssued: number; } // ── POST /api/paper/account/withdraw ── export interface PaperWithdrawResponse { token: number; units: number; unitsBurned: number; credited: number; burned: number; } // ── GET /api/paper/positions ── export interface PaperPositionRow { stockCode: string; stockName: string; quantity: number; reservedQuantity: number; avgPrice: number; latestClose: number|null; marketValue: number; unrealizedPnL: number; unrealizedPnLBp: number; } export interface PaperPositionsResponse { list: PaperPositionRow[]; } // ── POST /api/paper/orders ── export interface PaperPlaceOrderResponse { orderID: number; side: PaperOrderSideValue; fillRule: PaperFillRuleValue; targetDate: string; cancelableUntil: string; quantity: number; reservedAmount: number; } // ── GET /api/paper/orders ── export interface PaperFillInfo { price: number; quantity: number; fee: number; tax: number; amount: number; realizedPnL: number|null; priceDate: string; filledAt: string; } export interface PaperOrderRow { id: number; stockCode: string; stockName: string; side: PaperOrderSideValue; fillRule: PaperFillRuleValue; quantity: number; reservedAmount: number; targetDate: string; cancelableUntil: string; status: PaperOrderStatusValue; rejectReason: string|null; createdAt: string; fill: PaperFillInfo|null; } export interface PaperOrdersResponse { total: number; list: PaperOrderRow[]; } // ── GET /api/paper/ledger ── export interface PaperLedgerRow { id: number; type: PaperLedgerTypeValue; tokenAmount: number; unitsDelta: number; balanceAfter: number; createdAt: string; } export interface PaperLedgerResponse { total: number; list: PaperLedgerRow[]; } // ── GET /api/paper/leaderboard ── export type PaperLeaderboardSort = 'return'|'winrate'|'mdd'; export type PaperLeaderboardPeriod = 'week'|'month'|'all'; export interface PaperLeaderboardRow { rank: number; memberSID: string; nickname: string|null; thumb: string|null; returnBp: number; winRateBp: number; mddBp: number; fillCount: number; } export interface PaperLeaderboardResponse { sort: string; period: string; page: number; pageSize: number; rows: PaperLeaderboardRow[]; } // ── GET /api/paper/leaderboard/me ── export interface PaperMyRankResponse { sort: string; period: string; hasRank: boolean; rank: number; total: number; returnBp: number; winRateBp: number; mddBp: number; fillCount: number; } // ── GET /api/paper/members/{sid}/track-record ── export interface PaperTrackRecordResponse { hasAccount: boolean; cumReturnBp: number; mddBp: number; winRateBp: number; fillCount: number; latestTradeDate: string|null; }