ConvertibleBondTarget.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. using System.ComponentModel.DataAnnotations;
  2. namespace Domain.Entities.Stocks;
  3. /// <summary>
  4. /// SEIBro 주식관련사채 행사대상 주식정보 (getXrcStkStatInfo) — CB/BW/EB 행사대상·행사가·행사비율 (Wave 3).
  5. /// 자연키 UNIQUE (BondIsin, XrcStkIsin) — 한 채권·행사주식 조합당 1행.
  6. /// rolling per-채권ISIN — 발견 소스는 ConvertibleExercise(getXrcStkOptionXrcInfo) 가 반환한 DISTINCT BOND_ISIN.
  7. /// ⚠️ getXrcStkStatInfo 실샘플이 result="0"(0행) 이라 필드 매핑은 주식.md 스펙 기준 — 운영 첫 수집 시 로그로 확인 필요.
  8. /// </summary>
  9. public class ConvertibleBondTarget
  10. {
  11. [Key]
  12. public int ID { get; private set; }
  13. /// <summary>채권 종목번호 (BOND_ISIN) — EB/BW/CB</summary>
  14. public string BondIsin { get; private set; } = default!;
  15. /// <summary>채권 종목명 (BOND_SECN_NM)</summary>
  16. public string? BondSecnNm { get; private set; }
  17. /// <summary>채권종류코드 (BOND_KIND_NM) — EB/CB/분리형BW/비분리형BW</summary>
  18. public string? BondKindNm { get; private set; }
  19. /// <summary>행사주식종목번호 (XRC_STK_ISIN)</summary>
  20. public string XrcStkIsin { get; private set; } = default!;
  21. /// <summary>주식 종목명 (STK_SECN_NM)</summary>
  22. public string? StkSecnNm { get; private set; }
  23. /// <summary>신주인수권증권종목번호 (WRTB_ISIN)</summary>
  24. public string? WrtbIsin { get; private set; }
  25. /// <summary>신주인수권증권명 (WRTB_SECN_NM)</summary>
  26. public string? WrtbSecnNm { get; private set; }
  27. /// <summary>행사비율 (XRC_RATIO)</summary>
  28. public decimal? XrcRatio { get; private set; }
  29. /// <summary>행사가격 (XRC_PRICE)</summary>
  30. public decimal? XrcPrice { get; private set; }
  31. /// <summary>결산기말제한일수 (SETACC_ENDTERM_LIMIT_DAYS)</summary>
  32. public int? SetaccEndtermLimitDays { get; private set; }
  33. /// <summary>신주배정일전제한일수 (NEWSTK_ALOC_DD_BF_LIMIT_DAYS)</summary>
  34. public int? NewstkAllocDdBfLimitDays { get; private set; }
  35. /// <summary>청구제한사유내용 (DMAN_LIMIT_RSN_CONTENT)</summary>
  36. public string? DmanLimitRsnContent { get; private set; }
  37. public DateTime UpdatedAt { get; private set; } = DateTime.UtcNow;
  38. private ConvertibleBondTarget() { }
  39. public static ConvertibleBondTarget Create(
  40. string bondIsin,
  41. string? bondSecnNm,
  42. string? bondKindNm,
  43. string xrcStkIsin,
  44. string? stkSecnNm,
  45. string? wrtbIsin,
  46. string? wrtbSecnNm,
  47. decimal? xrcRatio,
  48. decimal? xrcPrice,
  49. int? setaccEndtermLimitDays,
  50. int? newstkAllocDdBfLimitDays,
  51. string? dmanLimitRsnContent)
  52. {
  53. if (string.IsNullOrWhiteSpace(bondIsin))
  54. {
  55. throw new ArgumentException("bondIsin required", nameof(bondIsin));
  56. }
  57. if (string.IsNullOrWhiteSpace(xrcStkIsin))
  58. {
  59. throw new ArgumentException("xrcStkIsin required", nameof(xrcStkIsin));
  60. }
  61. return new ConvertibleBondTarget
  62. {
  63. BondIsin = bondIsin.Trim(),
  64. BondSecnNm = Trimmed(bondSecnNm),
  65. BondKindNm = Trimmed(bondKindNm),
  66. XrcStkIsin = xrcStkIsin.Trim(),
  67. StkSecnNm = Trimmed(stkSecnNm),
  68. WrtbIsin = Trimmed(wrtbIsin),
  69. WrtbSecnNm = Trimmed(wrtbSecnNm),
  70. XrcRatio = xrcRatio,
  71. XrcPrice = xrcPrice,
  72. SetaccEndtermLimitDays = setaccEndtermLimitDays,
  73. NewstkAllocDdBfLimitDays = newstkAllocDdBfLimitDays,
  74. DmanLimitRsnContent = Trimmed(dmanLimitRsnContent)
  75. };
  76. }
  77. /// <summary>재수집 반영 — 변경 필드가 있을 때만 UpdatedAt 갱신 (자연키는 불변)</summary>
  78. public void Update(
  79. string? bondSecnNm,
  80. string? bondKindNm,
  81. string? stkSecnNm,
  82. string? wrtbIsin,
  83. string? wrtbSecnNm,
  84. decimal? xrcRatio,
  85. decimal? xrcPrice,
  86. int? setaccEndtermLimitDays,
  87. int? newstkAllocDdBfLimitDays,
  88. string? dmanLimitRsnContent)
  89. {
  90. var changed = false;
  91. changed |= Set(Trimmed(bondSecnNm), BondSecnNm, v => BondSecnNm = v);
  92. changed |= Set(Trimmed(bondKindNm), BondKindNm, v => BondKindNm = v);
  93. changed |= Set(Trimmed(stkSecnNm), StkSecnNm, v => StkSecnNm = v);
  94. changed |= Set(Trimmed(wrtbIsin), WrtbIsin, v => WrtbIsin = v);
  95. changed |= Set(Trimmed(wrtbSecnNm), WrtbSecnNm, v => WrtbSecnNm = v);
  96. changed |= Set(xrcRatio, XrcRatio, v => XrcRatio = v);
  97. changed |= Set(xrcPrice, XrcPrice, v => XrcPrice = v);
  98. changed |= Set(setaccEndtermLimitDays, SetaccEndtermLimitDays, v => SetaccEndtermLimitDays = v);
  99. changed |= Set(newstkAllocDdBfLimitDays, NewstkAllocDdBfLimitDays, v => NewstkAllocDdBfLimitDays = v);
  100. changed |= Set(Trimmed(dmanLimitRsnContent), DmanLimitRsnContent, v => DmanLimitRsnContent = v);
  101. if (changed)
  102. {
  103. UpdatedAt = DateTime.UtcNow;
  104. }
  105. }
  106. private static string? Trimmed(string? value)
  107. {
  108. return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
  109. }
  110. private static bool Set<T>(T incoming, T current, Action<T> assign)
  111. {
  112. if (EqualityComparer<T>.Default.Equals(incoming, current))
  113. {
  114. return false;
  115. }
  116. assign(incoming);
  117. return true;
  118. }
  119. }