IndexDailyPrice.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. using System.ComponentModel.DataAnnotations;
  2. using Domain.Entities.Stocks.ValueObject;
  3. namespace Domain.Entities.Stocks;
  4. /// <summary>
  5. /// 지수(시장) 일별 마감 시세 (KRX OpenAPI idx 엔드포인트) — (Series, IndexName, TradeDate) UNIQUE.
  6. /// 한 계열(KOSPI/KOSDAQ/KRX) 안에 여러 지수(코스피/코스피200/… )가 존재하므로 IndexName 까지 UQ 에 포함한다.
  7. /// 등락률은 정수 보관을 위해 %×100 basis point(Bp)로 저장 (예: -0.70% → -70, 1.45% → 145).
  8. /// </summary>
  9. public class IndexDailyPrice
  10. {
  11. [Key]
  12. public long ID { get; private set; }
  13. /// <summary>계열 구분 (1=KOSPI, 2=KOSDAQ, 3=KRX)</summary>
  14. public MarketIndexSeries Series { get; private set; }
  15. /// <summary>지수명 (IDX_NM, 예: "코스피", "코스닥", "KRX 100")</summary>
  16. public string IndexName { get; private set; } = default!;
  17. /// <summary>거래일 (BAS_DD)</summary>
  18. public DateOnly TradeDate { get; private set; }
  19. /// <summary>종가 (CLSPRC_IDX)</summary>
  20. public decimal Close { get; private set; }
  21. /// <summary>전일 대비 (CMPPREVDD_IDX)</summary>
  22. public decimal ChangeVal { get; private set; }
  23. /// <summary>등락률 basis point = %×100 (FLUC_RT)</summary>
  24. public int FlucRateBp { get; private set; }
  25. /// <summary>시가 (OPNPRC_IDX)</summary>
  26. public decimal Open { get; private set; }
  27. /// <summary>고가 (HGPRC_IDX)</summary>
  28. public decimal High { get; private set; }
  29. /// <summary>저가 (LWPRC_IDX)</summary>
  30. public decimal Low { get; private set; }
  31. /// <summary>거래량 (ACC_TRDVOL)</summary>
  32. public long Volume { get; private set; }
  33. /// <summary>거래대금 (ACC_TRDVAL, 원)</summary>
  34. public long Value { get; private set; }
  35. /// <summary>상장시가총액 (MKTCAP, 원) — 미제공 시 null</summary>
  36. public long? MarketCap { get; private set; }
  37. public DateTime CreatedAt { get; private set; } = DateTime.UtcNow;
  38. private IndexDailyPrice() { }
  39. public static IndexDailyPrice Create(
  40. MarketIndexSeries series,
  41. string indexName,
  42. DateOnly tradeDate,
  43. decimal close,
  44. decimal changeVal,
  45. int flucRateBp,
  46. decimal open,
  47. decimal high,
  48. decimal low,
  49. long volume,
  50. long value,
  51. long? marketCap = null
  52. ) {
  53. if (!Enum.IsDefined(series))
  54. {
  55. throw new ArgumentOutOfRangeException(nameof(series));
  56. }
  57. if (string.IsNullOrWhiteSpace(indexName))
  58. {
  59. throw new ArgumentException("indexName required", nameof(indexName));
  60. }
  61. return new IndexDailyPrice
  62. {
  63. Series = series,
  64. IndexName = indexName.Trim(),
  65. TradeDate = tradeDate,
  66. Close = close,
  67. ChangeVal = changeVal,
  68. FlucRateBp = flucRateBp,
  69. Open = open,
  70. High = high,
  71. Low = low,
  72. Volume = volume,
  73. Value = value,
  74. MarketCap = marketCap
  75. };
  76. }
  77. /// <summary>동일 (Series, IndexName, TradeDate) 재수집 시 값 갱신 (upsert)</summary>
  78. public void Update(
  79. decimal close,
  80. decimal changeVal,
  81. int flucRateBp,
  82. decimal open,
  83. decimal high,
  84. decimal low,
  85. long volume,
  86. long value,
  87. long? marketCap = null
  88. ) {
  89. Close = close;
  90. ChangeVal = changeVal;
  91. FlucRateBp = flucRateBp;
  92. Open = open;
  93. High = high;
  94. Low = low;
  95. Volume = volume;
  96. Value = value;
  97. MarketCap = marketCap;
  98. }
  99. }