paper.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // 모의투자(Paper Trading) 도메인 타입 — Backend Application/Features/Api/Paper/*/Response.cs 대응 (camelCase 직렬화)
  2. // ⚠️ enum 은 Web.Api 에 JsonStringEnumConverter 미등록 → byte 값(숫자)으로 직렬화됨.
  3. // (Stocks 는 Response 에서 .ToString() 으로 문자열화했으나 Paper 는 raw enum 타입 그대로라 숫자 전송)
  4. // ── enum (byte 값, d4 §③ / Domain/Entities/Paper/ValueObject/*) ──
  5. export const PaperOrderSide = {
  6. Buy: 1,
  7. Sell: 2
  8. } as const;
  9. export type PaperOrderSideValue = (typeof PaperOrderSide)[keyof typeof PaperOrderSide];
  10. export const PaperFillRule = {
  11. Open: 1,
  12. Close: 2
  13. } as const;
  14. export type PaperFillRuleValue = (typeof PaperFillRule)[keyof typeof PaperFillRule];
  15. export const PaperOrderStatus = {
  16. Pending: 1,
  17. Filled: 2,
  18. Cancelled: 3,
  19. Rejected: 4
  20. } as const;
  21. export type PaperOrderStatusValue = (typeof PaperOrderStatus)[keyof typeof PaperOrderStatus];
  22. export const PaperLedgerType = {
  23. Deposit: 1,
  24. Withdraw: 2
  25. } as const;
  26. export type PaperLedgerTypeValue = (typeof PaperLedgerType)[keyof typeof PaperLedgerType];
  27. // ── 표시 라벨 ──
  28. export const PAPER_SIDE_LABEL: Record<PaperOrderSideValue, string> = {
  29. [PaperOrderSide.Buy]: '매수',
  30. [PaperOrderSide.Sell]: '매도'
  31. };
  32. export const PAPER_FILL_RULE_LABEL: Record<PaperFillRuleValue, string> = {
  33. [PaperFillRule.Open]: '시가',
  34. [PaperFillRule.Close]: '종가'
  35. };
  36. export const PAPER_ORDER_STATUS_LABEL: Record<PaperOrderStatusValue, string> = {
  37. [PaperOrderStatus.Pending]: '접수',
  38. [PaperOrderStatus.Filled]: '체결',
  39. [PaperOrderStatus.Cancelled]: '취소',
  40. [PaperOrderStatus.Rejected]: '거부'
  41. };
  42. export const PAPER_LEDGER_TYPE_LABEL: Record<PaperLedgerTypeValue, string> = {
  43. [PaperLedgerType.Deposit]: '입금',
  44. [PaperLedgerType.Withdraw]: '출금'
  45. };
  46. // ── GET /api/paper/account ──
  47. export interface PaperAccountResponse {
  48. hasAccount: boolean;
  49. token: number;
  50. reservedToken: number;
  51. units: number;
  52. equity: number;
  53. cumReturnBp: number;
  54. positionsCount: number;
  55. }
  56. // ── POST /api/paper/account/deposit ──
  57. export interface PaperDepositResponse {
  58. token: number;
  59. units: number;
  60. unitsIssued: number;
  61. }
  62. // ── POST /api/paper/account/withdraw ──
  63. export interface PaperWithdrawResponse {
  64. token: number;
  65. units: number;
  66. unitsBurned: number;
  67. credited: number;
  68. burned: number;
  69. }
  70. // ── GET /api/paper/positions ──
  71. export interface PaperPositionRow {
  72. stockCode: string;
  73. stockName: string;
  74. quantity: number;
  75. reservedQuantity: number;
  76. avgPrice: number;
  77. latestClose: number|null;
  78. marketValue: number;
  79. unrealizedPnL: number;
  80. unrealizedPnLBp: number;
  81. }
  82. export interface PaperPositionsResponse {
  83. list: PaperPositionRow[];
  84. }
  85. // ── POST /api/paper/orders ──
  86. export interface PaperPlaceOrderResponse {
  87. orderID: number;
  88. side: PaperOrderSideValue;
  89. fillRule: PaperFillRuleValue;
  90. targetDate: string;
  91. cancelableUntil: string;
  92. quantity: number;
  93. reservedAmount: number;
  94. }
  95. // ── GET /api/paper/orders ──
  96. export interface PaperFillInfo {
  97. price: number;
  98. quantity: number;
  99. fee: number;
  100. tax: number;
  101. amount: number;
  102. realizedPnL: number|null;
  103. priceDate: string;
  104. filledAt: string;
  105. }
  106. export interface PaperOrderRow {
  107. id: number;
  108. stockCode: string;
  109. stockName: string;
  110. side: PaperOrderSideValue;
  111. fillRule: PaperFillRuleValue;
  112. quantity: number;
  113. reservedAmount: number;
  114. targetDate: string;
  115. cancelableUntil: string;
  116. status: PaperOrderStatusValue;
  117. rejectReason: string|null;
  118. createdAt: string;
  119. fill: PaperFillInfo|null;
  120. }
  121. export interface PaperOrdersResponse {
  122. total: number;
  123. list: PaperOrderRow[];
  124. }
  125. // ── GET /api/paper/ledger ──
  126. export interface PaperLedgerRow {
  127. id: number;
  128. type: PaperLedgerTypeValue;
  129. tokenAmount: number;
  130. unitsDelta: number;
  131. balanceAfter: number;
  132. createdAt: string;
  133. }
  134. export interface PaperLedgerResponse {
  135. total: number;
  136. list: PaperLedgerRow[];
  137. }
  138. // ── GET /api/paper/leaderboard ──
  139. export type PaperLeaderboardSort = 'return'|'winrate'|'mdd';
  140. export type PaperLeaderboardPeriod = 'week'|'month'|'all';
  141. export interface PaperLeaderboardRow {
  142. rank: number;
  143. memberSID: string;
  144. nickname: string|null;
  145. thumb: string|null;
  146. returnBp: number;
  147. winRateBp: number;
  148. mddBp: number;
  149. fillCount: number;
  150. }
  151. export interface PaperLeaderboardResponse {
  152. sort: string;
  153. period: string;
  154. page: number;
  155. pageSize: number;
  156. rows: PaperLeaderboardRow[];
  157. }
  158. // ── GET /api/paper/leaderboard/me ──
  159. export interface PaperMyRankResponse {
  160. sort: string;
  161. period: string;
  162. hasRank: boolean;
  163. rank: number;
  164. total: number;
  165. returnBp: number;
  166. winRateBp: number;
  167. mddBp: number;
  168. fillCount: number;
  169. }
  170. // ── GET /api/paper/members/{sid}/track-record ──
  171. export interface PaperTrackRecordResponse {
  172. hasAccount: boolean;
  173. cumReturnBp: number;
  174. mddBp: number;
  175. winRateBp: number;
  176. fillCount: number;
  177. latestTradeDate: string|null;
  178. }