ElsUnredeemedScale.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. using System.ComponentModel.DataAnnotations;
  2. namespace Domain.Entities.Stocks;
  3. /// <summary>
  4. /// SEIBro 기초자산별 미상환규모 (getBassetUnredScale) — 주요 기초자산(13종)별 미상환종목수·미상환잔액 (Wave 5, ★P2).
  5. /// **ELS 지수 하락 리스크 지표** (개미 관심). 자연키 UNIQUE (StdDt, StndBassetCd, SecnTpcd).
  6. /// 일별 13기초자산 × SECN_TPCD{41ELS/43DLS} = 최대 26콜/일 스윕. 응답 필드는 BassetContent·UnredSecncnt·UnredRema 3종.
  7. /// ⚠️ 응답에 없는 StdDt·StndBassetCd·SecnTpcd 는 요청 파라미터를 배치가 스탬핑한다.
  8. /// ⚠️ StndBassetCd 는 입력 13종(KSD02*) 원문 — getAssetInfo 반환 코드체계(KSD31*)와 달라 매핑 흡수하지 않고 원문 저장.
  9. /// </summary>
  10. public class ElsUnredeemedScale
  11. {
  12. [Key]
  13. public int ID { get; private set; }
  14. /// <summary>기준일자 (STD_DT, 요청값 스탬핑)</summary>
  15. public DateOnly StdDt { get; private set; }
  16. /// <summary>표준기초자산코드 (STND_BASSET_CD, 요청값 스탬핑) — 입력 13종 KSD02* 원문</summary>
  17. public string StndBassetCd { get; private set; } = default!;
  18. /// <summary>종목구분코드 (SECN_TPCD, 요청값 스탬핑) — 41ELS 43DLS</summary>
  19. public string SecnTpcd { get; private set; } = default!;
  20. /// <summary>기초자산내용 (BASSET_CONTENT) — 예 EURO STOXX 50</summary>
  21. public string? BassetContent { get; private set; }
  22. /// <summary>미상환종목수 (UNRED_SECNCNT)</summary>
  23. public int? UnredSecncnt { get; private set; }
  24. /// <summary>미상환잔액 (UNRED_REMA) — 원화 환산 합계</summary>
  25. public decimal? UnredRema { get; private set; }
  26. public DateTime UpdatedAt { get; private set; } = DateTime.UtcNow;
  27. private ElsUnredeemedScale() { }
  28. public static ElsUnredeemedScale Create(DateOnly stdDt, string stndBassetCd, string secnTpcd, string? bassetContent, int? unredSecncnt, decimal? unredRema)
  29. {
  30. if (string.IsNullOrWhiteSpace(stndBassetCd))
  31. {
  32. throw new ArgumentException("stndBassetCd required", nameof(stndBassetCd));
  33. }
  34. return new ElsUnredeemedScale
  35. {
  36. StdDt = stdDt,
  37. StndBassetCd = stndBassetCd.Trim(),
  38. SecnTpcd = secnTpcd.Trim(),
  39. BassetContent = Trimmed(bassetContent),
  40. UnredSecncnt = unredSecncnt,
  41. UnredRema = unredRema
  42. };
  43. }
  44. /// <summary>재수집 반영 — 변경 필드가 있을 때만 UpdatedAt 갱신 (자연키 StdDt/StndBassetCd/SecnTpcd 은 불변)</summary>
  45. public void Update(string? bassetContent, int? unredSecncnt, decimal? unredRema)
  46. {
  47. var changed = false;
  48. changed |= Set(Trimmed(bassetContent), BassetContent, v => BassetContent = v);
  49. changed |= Set(unredSecncnt, UnredSecncnt, v => UnredSecncnt = v);
  50. changed |= Set(unredRema, UnredRema, v => UnredRema = v);
  51. if (changed)
  52. {
  53. UpdatedAt = DateTime.UtcNow;
  54. }
  55. }
  56. private static string? Trimmed(string? value)
  57. {
  58. return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
  59. }
  60. private static bool Set<T>(T incoming, T current, Action<T> assign)
  61. {
  62. if (EqualityComparer<T>.Default.Equals(incoming, current))
  63. {
  64. return false;
  65. }
  66. assign(incoming);
  67. return true;
  68. }
  69. }