BondEarlyRedemption.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using System.ComponentModel.DataAnnotations;
  2. namespace Domain.Entities.Stocks;
  3. /// <summary>
  4. /// SEIBro 채권 조기상환 정보 (getBondOptionXrcInfo) — Call/Put 옵션 행사 조기상환 (Wave 4). 자연키 UNIQUE (Isin, ErlyRedDt).
  5. /// 조기상환일(ERLY_RED_DT) 날짜 스윕으로 수집한다. 한 채권이 여러 조기상환일을 가질 수 있어 (Isin, ErlyRedDt) 로 구분.
  6. /// </summary>
  7. public class BondEarlyRedemption
  8. {
  9. [Key]
  10. public int ID { get; private set; }
  11. /// <summary>종목코드 (ISIN)</summary>
  12. public string Isin { get; private set; } = default!;
  13. /// <summary>한글종목명 (KOR_SECN_NM)</summary>
  14. public string? KorSecnNm { get; private set; }
  15. /// <summary>행사시작일 (XRC_BEGIN_DT)</summary>
  16. public DateOnly? XrcBeginDt { get; private set; }
  17. /// <summary>행사종료일 (XRC_EXPRY_DT)</summary>
  18. public DateOnly? XrcExpryDt { get; private set; }
  19. /// <summary>조기상환일 (ERLY_RED_DT)</summary>
  20. public DateOnly ErlyRedDt { get; private set; }
  21. /// <summary>옵션구분코드 (OPTION_TPCD) — 9401CALL 9402PUT 9403CALL+PUT</summary>
  22. public string? OptionTpcd { get; private set; }
  23. /// <summary>적용이자율 (APLI_IRATE)</summary>
  24. public decimal? ApliIrate { get; private set; }
  25. /// <summary>조기상환금액 (ERLY_REDAMT_VAL)</summary>
  26. public decimal? ErlyRedamtVal { get; private set; }
  27. /// <summary>이자지급금액 (INT_PAY_AMT)</summary>
  28. public decimal? IntPayAmt { get; private set; }
  29. /// <summary>최근발행잔액 (ISSU_REMA)</summary>
  30. public decimal? IssuRema { get; private set; }
  31. /// <summary>행사비율 (XRC_RATIO)</summary>
  32. public decimal? XrcRatio { get; private set; }
  33. public DateTime UpdatedAt { get; private set; } = DateTime.UtcNow;
  34. private BondEarlyRedemption() { }
  35. public static BondEarlyRedemption Create(
  36. string isin,
  37. string? korSecnNm,
  38. DateOnly? xrcBeginDt,
  39. DateOnly? xrcExpryDt,
  40. DateOnly erlyRedDt,
  41. string? optionTpcd,
  42. decimal? apliIrate,
  43. decimal? erlyRedamtVal,
  44. decimal? intPayAmt,
  45. decimal? issuRema,
  46. decimal? xrcRatio)
  47. {
  48. if (string.IsNullOrWhiteSpace(isin))
  49. {
  50. throw new ArgumentException("isin required", nameof(isin));
  51. }
  52. return new BondEarlyRedemption
  53. {
  54. Isin = isin.Trim(),
  55. KorSecnNm = Trimmed(korSecnNm),
  56. XrcBeginDt = xrcBeginDt,
  57. XrcExpryDt = xrcExpryDt,
  58. ErlyRedDt = erlyRedDt,
  59. OptionTpcd = Trimmed(optionTpcd),
  60. ApliIrate = apliIrate,
  61. ErlyRedamtVal = erlyRedamtVal,
  62. IntPayAmt = intPayAmt,
  63. IssuRema = issuRema,
  64. XrcRatio = xrcRatio
  65. };
  66. }
  67. /// <summary>재수집 반영 — 변경 필드가 있을 때만 UpdatedAt 갱신 (자연키 Isin/ErlyRedDt 는 불변)</summary>
  68. public void Update(
  69. string? korSecnNm,
  70. DateOnly? xrcBeginDt,
  71. DateOnly? xrcExpryDt,
  72. string? optionTpcd,
  73. decimal? apliIrate,
  74. decimal? erlyRedamtVal,
  75. decimal? intPayAmt,
  76. decimal? issuRema,
  77. decimal? xrcRatio)
  78. {
  79. var changed = false;
  80. changed |= Set(Trimmed(korSecnNm), KorSecnNm, v => KorSecnNm = v);
  81. changed |= Set(xrcBeginDt, XrcBeginDt, v => XrcBeginDt = v);
  82. changed |= Set(xrcExpryDt, XrcExpryDt, v => XrcExpryDt = v);
  83. changed |= Set(Trimmed(optionTpcd), OptionTpcd, v => OptionTpcd = v);
  84. changed |= Set(apliIrate, ApliIrate, v => ApliIrate = v);
  85. changed |= Set(erlyRedamtVal, ErlyRedamtVal, v => ErlyRedamtVal = v);
  86. changed |= Set(intPayAmt, IntPayAmt, v => IntPayAmt = v);
  87. changed |= Set(issuRema, IssuRema, v => IssuRema = v);
  88. changed |= Set(xrcRatio, XrcRatio, v => XrcRatio = v);
  89. if (changed)
  90. {
  91. UpdatedAt = DateTime.UtcNow;
  92. }
  93. }
  94. private static string? Trimmed(string? value)
  95. {
  96. return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
  97. }
  98. private static bool Set<T>(T incoming, T current, Action<T> assign)
  99. {
  100. if (EqualityComparer<T>.Default.Equals(incoming, current))
  101. {
  102. return false;
  103. }
  104. assign(incoming);
  105. return true;
  106. }
  107. }