| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- using System.ComponentModel.DataAnnotations;
- namespace Domain.Entities.Stocks;
- /// <summary>
- /// SEIBro 채권 종목 정보 (getBondStatInfo) — 만기·표면이자율·옵션·보증·순위·신용등급 (Wave 4, ★P2). PK Isin.
- /// **신용등급 4사(KIS/NICE/SCI/KR) 유일 소스.** 신용등급 코드는 코드표가 커서 원문 문자열로 저장(채권.md 공통표 참조).
- /// rolling per-ISIN 대상 = BondIssuance.Isin ∪ 기존 KRX BondDailyTrade.Code(ISIN). GetBondDetail 의 주 조인 대상.
- /// 발행당시 등급이라 재수집 시 스냅샷 갱신(변경 시 UpdatedAt). 소수 precision 은 넉넉히(채권.md NUMBER(13~14,10)).
- /// </summary>
- public class BondMaster
- {
- /// <summary>종목코드 (ISIN) — PK</summary>
- [Key]
- [MaxLength(12)]
- public string Isin { get; private set; } = default!;
- /// <summary>발행사 번호 (ISSUCO_CUSTNO)</summary>
- public int? IssucoCustno { get; private set; }
- /// <summary>한글종목명 (KOR_SECN_NM)</summary>
- public string? KorSecnNm { get; private set; }
- /// <summary>종목종류코드 (SECN_KACD) — 1108일반회사채 등</summary>
- public string? SecnKacd { get; private set; }
- /// <summary>발행일자 (ISSU_DT)</summary>
- public DateOnly? IssuDt { get; private set; }
- /// <summary>만기일자 (XPIR_DT)</summary>
- public DateOnly? XpirDt { get; private set; }
- /// <summary>발행통화코드 (ISSU_CUR_CD) — KRW</summary>
- public string? IssuCurCd { get; private set; }
- /// <summary>최초발행금액 (FIRST_ISSU_AMT)</summary>
- public decimal? FirstIssuAmt { get; private set; }
- /// <summary>발행잔액 (ISSU_REMA)</summary>
- public decimal? IssuRema { get; private set; }
- /// <summary>납입금액 (PAYIN_AMT)</summary>
- public decimal? PayinAmt { get; private set; }
- /// <summary>표면이자율 (COUPON_RATE)</summary>
- public decimal? CouponRate { get; private set; }
- /// <summary>만기상환율 (XPIRED_RATE)</summary>
- public decimal? XpiredRate { get; private set; }
- /// <summary>모집방법코드 (RECU_WHCD) — 11공모 12사모 13일반 14CBO기초사모 21매출</summary>
- public string? RecuWhcd { get; private set; }
- /// <summary>발행방법코드 (ISSU_WHCD) — 1실물 2전액등록 …</summary>
- public string? IssuWhcd { get; private set; }
- /// <summary>특이채권종류구분코드 (PARTICUL_BOND_KIND_TPCD) — 1전환 2교환 3신주인수권 4분리형신주인수권 6이익참가 9해당없음</summary>
- public string? ParticulBondKindTpcd { get; private set; }
- /// <summary>옵션구분코드 (OPTION_TPCD) — 9401CALL 9402PUT 9403CALL+PUT 9404NOTE 0000해당없음</summary>
- public string? OptionTpcd { get; private set; }
- /// <summary>강제조기상환여부 (FORC_ERLY_RED_YN, Y/N)</summary>
- public bool? ForcErlyRedYn { get; private set; }
- /// <summary>금리변동구분코드 (MR_CHG_TPCD) — 1고정 2변동 3고정+변동</summary>
- public string? MrChgTpcd { get; private set; }
- /// <summary>등록기관구분코드 (REGI_ORG_TPCD) — 1:KSD</summary>
- public string? RegiOrgTpcd { get; private set; }
- /// <summary>보증구분코드 (GRTY_TPCD) — 1보증 2무보증 3담보부 4일반</summary>
- public string? GrtyTpcd { get; private set; }
- /// <summary>기명구분코드 (SIGNA_TPCD) — 1기명 2무기명 3기명+무기명</summary>
- public string? SignaTpcd { get; private set; }
- /// <summary>순위구분코드 (RANK_TPCD) — 1선순위 2후순위 3중순위 9해당없음</summary>
- public string? RankTpcd { get; private set; }
- /// <summary>이자지급방법구분코드 (INT_PAY_WAY_TPCD) — 1이표 2할인 3복리 4단리</summary>
- public string? IntPayWayTpcd { get; private set; }
- /// <summary>단리복리구분코드 (SINT_CINT_TPCD) — 1단리 2복리 3단리+복리</summary>
- public string? SintCintTpcd { get; private set; }
- /// <summary>이자율변동구분코드 (IRATE_CHG_TPCD) — 1이율동일 2이율상이 3비정형</summary>
- public string? IrateChgTpcd { get; private set; }
- /// <summary>만기보장수익율 (XPIR_GUAR_PRATE)</summary>
- public decimal? XpirGuarPrate { get; private set; }
- /// <summary>만기보장수익율구분코드 (XPIR_GUAR_PRATE_TPCD) — 01연복리 02 3개월복리 …</summary>
- public string? XpirGuarPrateTpcd { get; private set; }
- /// <summary>원금상환방법코드 (PRCP_RED_WHCD) — 11만기 21중도 31조기 …</summary>
- public string? PrcpRedWhcd { get; private set; }
- /// <summary>상장일 (APLI_DT)</summary>
- public DateOnly? ApliDt { get; private set; }
- /// <summary>상장폐지일자 (DLIST_DT)</summary>
- public DateOnly? DlistDt { get; private set; }
- /// <summary>KIS평가등급코드 (KIS_VALAT_GRD_CD, 발행당시) — 신용등급코드표 원문</summary>
- public string? KisValatGrdCd { get; private set; }
- /// <summary>NICE평가등급코드 (NICE_VALAT_GRD_CD) — 신용등급코드표 원문</summary>
- public string? NiceValatGrdCd { get; private set; }
- /// <summary>서울신용평가등급코드 (SCI_VALAT_GRD_CD) — 신용등급코드표 원문</summary>
- public string? SciValatGrdCd { get; private set; }
- /// <summary>한국기업평가등급코드 (KR_VALAT_GRD_CD) — 신용등급코드표 원문</summary>
- public string? KrValatGrdCd { get; private set; }
- /// <summary>전자증권여부 (ELTSC_YN) — Y전자 N예탁</summary>
- public bool? EltscYn { get; private set; }
- /// <summary>권리행사주체 (EXER_MBODY_TPCD) — 1KSD 2자체</summary>
- public string? ExerMbodyTpcd { get; private set; }
- /// <summary>이자산정방식 (INT_ESTM_MANN_TPCD) — 1정형 2비정형 3해당없음</summary>
- public string? IntEstmMannTpcd { get; private set; }
- public DateTime UpdatedAt { get; private set; } = DateTime.UtcNow;
- private BondMaster() { }
- public static BondMaster Create(string isin, BondMasterFields f)
- {
- if (string.IsNullOrWhiteSpace(isin))
- {
- throw new ArgumentException("isin required", nameof(isin));
- }
- var entity = new BondMaster { Isin = isin.Trim() };
- entity.Apply(f);
- return entity;
- }
- /// <summary>재수집 반영 (PK Isin 은 불변) — 스냅샷 갱신, 변경 시에만 UpdatedAt</summary>
- public void Update(BondMasterFields f)
- {
- Apply(f);
- }
- private void Apply(BondMasterFields f)
- {
- var changed = false;
- changed |= Set(f.IssucoCustno, IssucoCustno, v => IssucoCustno = v);
- changed |= Set(Trimmed(f.KorSecnNm), KorSecnNm, v => KorSecnNm = v);
- changed |= Set(Trimmed(f.SecnKacd), SecnKacd, v => SecnKacd = v);
- changed |= Set(f.IssuDt, IssuDt, v => IssuDt = v);
- changed |= Set(f.XpirDt, XpirDt, v => XpirDt = v);
- changed |= Set(Trimmed(f.IssuCurCd), IssuCurCd, v => IssuCurCd = v);
- changed |= Set(f.FirstIssuAmt, FirstIssuAmt, v => FirstIssuAmt = v);
- changed |= Set(f.IssuRema, IssuRema, v => IssuRema = v);
- changed |= Set(f.PayinAmt, PayinAmt, v => PayinAmt = v);
- changed |= Set(f.CouponRate, CouponRate, v => CouponRate = v);
- changed |= Set(f.XpiredRate, XpiredRate, v => XpiredRate = v);
- changed |= Set(Trimmed(f.RecuWhcd), RecuWhcd, v => RecuWhcd = v);
- changed |= Set(Trimmed(f.IssuWhcd), IssuWhcd, v => IssuWhcd = v);
- changed |= Set(Trimmed(f.ParticulBondKindTpcd), ParticulBondKindTpcd, v => ParticulBondKindTpcd = v);
- changed |= Set(Trimmed(f.OptionTpcd), OptionTpcd, v => OptionTpcd = v);
- changed |= Set(f.ForcErlyRedYn, ForcErlyRedYn, v => ForcErlyRedYn = v);
- changed |= Set(Trimmed(f.MrChgTpcd), MrChgTpcd, v => MrChgTpcd = v);
- changed |= Set(Trimmed(f.RegiOrgTpcd), RegiOrgTpcd, v => RegiOrgTpcd = v);
- changed |= Set(Trimmed(f.GrtyTpcd), GrtyTpcd, v => GrtyTpcd = v);
- changed |= Set(Trimmed(f.SignaTpcd), SignaTpcd, v => SignaTpcd = v);
- changed |= Set(Trimmed(f.RankTpcd), RankTpcd, v => RankTpcd = v);
- changed |= Set(Trimmed(f.IntPayWayTpcd), IntPayWayTpcd, v => IntPayWayTpcd = v);
- changed |= Set(Trimmed(f.SintCintTpcd), SintCintTpcd, v => SintCintTpcd = v);
- changed |= Set(Trimmed(f.IrateChgTpcd), IrateChgTpcd, v => IrateChgTpcd = v);
- changed |= Set(f.XpirGuarPrate, XpirGuarPrate, v => XpirGuarPrate = v);
- changed |= Set(Trimmed(f.XpirGuarPrateTpcd), XpirGuarPrateTpcd, v => XpirGuarPrateTpcd = v);
- changed |= Set(Trimmed(f.PrcpRedWhcd), PrcpRedWhcd, v => PrcpRedWhcd = v);
- changed |= Set(f.ApliDt, ApliDt, v => ApliDt = v);
- changed |= Set(f.DlistDt, DlistDt, v => DlistDt = v);
- changed |= Set(Trimmed(f.KisValatGrdCd), KisValatGrdCd, v => KisValatGrdCd = v);
- changed |= Set(Trimmed(f.NiceValatGrdCd), NiceValatGrdCd, v => NiceValatGrdCd = v);
- changed |= Set(Trimmed(f.SciValatGrdCd), SciValatGrdCd, v => SciValatGrdCd = v);
- changed |= Set(Trimmed(f.KrValatGrdCd), KrValatGrdCd, v => KrValatGrdCd = v);
- changed |= Set(f.EltscYn, EltscYn, v => EltscYn = v);
- changed |= Set(Trimmed(f.ExerMbodyTpcd), ExerMbodyTpcd, v => ExerMbodyTpcd = v);
- changed |= Set(Trimmed(f.IntEstmMannTpcd), IntEstmMannTpcd, v => IntEstmMannTpcd = v);
- if (changed)
- {
- UpdatedAt = DateTime.UtcNow;
- }
- }
- private static string? Trimmed(string? value)
- {
- return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
- }
- private static bool Set<T>(T incoming, T current, Action<T> assign)
- {
- if (EqualityComparer<T>.Default.Equals(incoming, current))
- {
- return false;
- }
- assign(incoming);
- return true;
- }
- }
- /// <summary>BondMaster 필드 묶음 (getBondStatInfo 필드 다수 — 생성/갱신 인자 축약)</summary>
- public sealed record BondMasterFields(
- int? IssucoCustno,
- string? KorSecnNm,
- string? SecnKacd,
- DateOnly? IssuDt,
- DateOnly? XpirDt,
- string? IssuCurCd,
- decimal? FirstIssuAmt,
- decimal? IssuRema,
- decimal? PayinAmt,
- decimal? CouponRate,
- decimal? XpiredRate,
- string? RecuWhcd,
- string? IssuWhcd,
- string? ParticulBondKindTpcd,
- string? OptionTpcd,
- bool? ForcErlyRedYn,
- string? MrChgTpcd,
- string? RegiOrgTpcd,
- string? GrtyTpcd,
- string? SignaTpcd,
- string? RankTpcd,
- string? IntPayWayTpcd,
- string? SintCintTpcd,
- string? IrateChgTpcd,
- decimal? XpirGuarPrate,
- string? XpirGuarPrateTpcd,
- string? PrcpRedWhcd,
- DateOnly? ApliDt,
- DateOnly? DlistDt,
- string? KisValatGrdCd,
- string? NiceValatGrdCd,
- string? SciValatGrdCd,
- string? KrValatGrdCd,
- bool? EltscYn,
- string? ExerMbodyTpcd,
- string? IntEstmMannTpcd
- );
|