WarrantDailyTrade.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. using System.ComponentModel.DataAnnotations;
  2. using Domain.Entities.Stocks.ValueObject;
  3. namespace Domain.Entities.Stocks;
  4. /// <summary>
  5. /// 신주인수권증권/증서 일별매매 시세 (KRX OpenAPI sto 엔드포인트) — (WarrantType, Code, TradeDate) UNIQUE.
  6. /// 두 상품을 한 테이블에 담고 WarrantType 으로 구분한다. 공통 컬럼(가격/거래/시총) + 대상주식 정보 + 유형별 nullable 컬럼:
  7. /// - 증권(SubscriptionWarrant, sw_bydd_trd): ExercisePrice(행사가 EXER_PRC), ExerciseStartDate·ExerciseEndDate(행사기간 EXST_STRT_DD/EXST_END_DD)
  8. /// - 증서(SubscriptionRight, sr_bydd_trd): IssuePrice(발행가 ISU_PRC), DelistDate(상장폐지일 DELIST_DD — 증서는 단기 상장)
  9. /// 대상주식(공통): TargetStockCode(TARSTK_ISU_SRT_CD), TargetStockName(TARSTK_ISU_NM), TargetStockPrice(TARSTK_ISU_PRSNT_PRC).
  10. /// 등락률(ChangeRate)은 KrxStockParser 와 동일하게 소수 % 그대로 저장(Bp 아님).
  11. /// 가격은 decimal(18,2) — 증권/증서 가격은 정수지만 EtpDailyTrade 와 스케일 통일.
  12. /// 단축코드(ISU_CD)는 8자리 영숫자(예: 1099621D / 1013601E) — 6자리 종목코드가 아니다.
  13. /// </summary>
  14. public class WarrantDailyTrade
  15. {
  16. [Key]
  17. public long ID { get; private set; }
  18. /// <summary>신주인수권 구분 (1=증권 SubscriptionWarrant, 2=증서 SubscriptionRight)</summary>
  19. public WarrantType WarrantType { get; private set; }
  20. /// <summary>단축코드 (ISU_CD) — 8자리 영숫자(예: 1099621D)</summary>
  21. public string Code { get; private set; } = default!;
  22. /// <summary>종목명 (ISU_NM)</summary>
  23. public string Name { get; private set; } = default!;
  24. /// <summary>시장 구분 (1=KOSPI, 2=KOSDAQ, 3=KONEX) — 응답 MKT_NM 기준</summary>
  25. public StockMarket Market { get; private set; }
  26. /// <summary>거래일 (BAS_DD)</summary>
  27. public DateOnly TradeDate { get; private set; }
  28. /// <summary>종가 (TDD_CLSPRC)</summary>
  29. public decimal Close { get; private set; }
  30. /// <summary>시가 (TDD_OPNPRC)</summary>
  31. public decimal Open { get; private set; }
  32. /// <summary>고가 (TDD_HGPRC)</summary>
  33. public decimal High { get; private set; }
  34. /// <summary>저가 (TDD_LWPRC)</summary>
  35. public decimal Low { get; private set; }
  36. /// <summary>전일 대비 (CMPPREVDD_PRC)</summary>
  37. public decimal ChangeAmount { get; private set; }
  38. /// <summary>등락률 % (FLUC_RT)</summary>
  39. public decimal ChangeRate { get; private set; }
  40. /// <summary>거래량 (ACC_TRDVOL)</summary>
  41. public long Volume { get; private set; }
  42. /// <summary>거래대금 (ACC_TRDVAL, 원)</summary>
  43. public long TradeValue { get; private set; }
  44. /// <summary>시가총액 (MKTCAP, 원) — 미제공 시 null</summary>
  45. public long? MarketCap { get; private set; }
  46. /// <summary>상장증권수 (LIST_SHRS) — 미제공 시 null</summary>
  47. public long? ListedShares { get; private set; }
  48. /// <summary>대상주식 단축코드 (TARSTK_ISU_SRT_CD) — 미제공 시 null</summary>
  49. public string? TargetStockCode { get; private set; }
  50. /// <summary>대상주식명 (TARSTK_ISU_NM) — 미제공 시 null</summary>
  51. public string? TargetStockName { get; private set; }
  52. /// <summary>대상주식 현재가 (TARSTK_ISU_PRSNT_PRC) — 미제공 시 null</summary>
  53. public decimal? TargetStockPrice { get; private set; }
  54. /// <summary>행사가 (EXER_PRC) — 증권만. 증서는 null</summary>
  55. public decimal? ExercisePrice { get; private set; }
  56. /// <summary>행사 시작일 (EXST_STRT_DD) — 증권만. 증서는 null</summary>
  57. public DateOnly? ExerciseStartDate { get; private set; }
  58. /// <summary>행사 종료일 (EXST_END_DD) — 증권만. 증서는 null</summary>
  59. public DateOnly? ExerciseEndDate { get; private set; }
  60. /// <summary>발행가 (ISU_PRC) — 증서만. 증권은 null</summary>
  61. public decimal? IssuePrice { get; private set; }
  62. /// <summary>상장폐지일 (DELIST_DD) — 증서만(단기 상장). 증권은 null</summary>
  63. public DateOnly? DelistDate { get; private set; }
  64. public DateTime CreatedAt { get; private set; } = DateTime.UtcNow;
  65. private WarrantDailyTrade() { }
  66. public static WarrantDailyTrade Create(
  67. WarrantType warrantType,
  68. string code,
  69. string name,
  70. StockMarket market,
  71. DateOnly tradeDate,
  72. decimal close,
  73. decimal open,
  74. decimal high,
  75. decimal low,
  76. decimal changeAmount,
  77. decimal changeRate,
  78. long volume,
  79. long tradeValue,
  80. long? marketCap = null,
  81. long? listedShares = null,
  82. string? targetStockCode = null,
  83. string? targetStockName = null,
  84. decimal? targetStockPrice = null,
  85. decimal? exercisePrice = null,
  86. DateOnly? exerciseStartDate = null,
  87. DateOnly? exerciseEndDate = null,
  88. decimal? issuePrice = null,
  89. DateOnly? delistDate = null
  90. ) {
  91. if (!Enum.IsDefined(warrantType))
  92. {
  93. throw new ArgumentOutOfRangeException(nameof(warrantType));
  94. }
  95. if (string.IsNullOrWhiteSpace(code))
  96. {
  97. throw new ArgumentException("code required", nameof(code));
  98. }
  99. if (string.IsNullOrWhiteSpace(name))
  100. {
  101. throw new ArgumentException("name required", nameof(name));
  102. }
  103. return new WarrantDailyTrade
  104. {
  105. WarrantType = warrantType,
  106. Code = code.Trim(),
  107. Name = name.Trim(),
  108. Market = market,
  109. TradeDate = tradeDate,
  110. Close = close,
  111. Open = open,
  112. High = high,
  113. Low = low,
  114. ChangeAmount = changeAmount,
  115. ChangeRate = changeRate,
  116. Volume = volume,
  117. TradeValue = tradeValue,
  118. MarketCap = marketCap,
  119. ListedShares = listedShares,
  120. TargetStockCode = targetStockCode,
  121. TargetStockName = targetStockName,
  122. TargetStockPrice = targetStockPrice,
  123. ExercisePrice = exercisePrice,
  124. ExerciseStartDate = exerciseStartDate,
  125. ExerciseEndDate = exerciseEndDate,
  126. IssuePrice = issuePrice,
  127. DelistDate = delistDate
  128. };
  129. }
  130. /// <summary>동일 (WarrantType, Code, TradeDate) 재수집 시 값 갱신 (upsert)</summary>
  131. public void Update(
  132. string name,
  133. StockMarket market,
  134. decimal close,
  135. decimal open,
  136. decimal high,
  137. decimal low,
  138. decimal changeAmount,
  139. decimal changeRate,
  140. long volume,
  141. long tradeValue,
  142. long? marketCap = null,
  143. long? listedShares = null,
  144. string? targetStockCode = null,
  145. string? targetStockName = null,
  146. decimal? targetStockPrice = null,
  147. decimal? exercisePrice = null,
  148. DateOnly? exerciseStartDate = null,
  149. DateOnly? exerciseEndDate = null,
  150. decimal? issuePrice = null,
  151. DateOnly? delistDate = null
  152. ) {
  153. Name = name.Trim();
  154. Market = market;
  155. Close = close;
  156. Open = open;
  157. High = high;
  158. Low = low;
  159. ChangeAmount = changeAmount;
  160. ChangeRate = changeRate;
  161. Volume = volume;
  162. TradeValue = tradeValue;
  163. MarketCap = marketCap;
  164. ListedShares = listedShares;
  165. TargetStockCode = targetStockCode;
  166. TargetStockName = targetStockName;
  167. TargetStockPrice = targetStockPrice;
  168. ExercisePrice = exercisePrice;
  169. ExerciseStartDate = exerciseStartDate;
  170. ExerciseEndDate = exerciseEndDate;
  171. IssuePrice = issuePrice;
  172. DelistDate = delistDate;
  173. }
  174. }