namespace Infrastructure.StockData; /// /// SEIBro getBondOptionXrcInfo(채권 조기상환 정보) 응답 파서 — 순수 C#. 공용 SeibroXml envelope 입력. /// 자연키 (ISIN, ERLY_RED_DT) 중 하나라도 없으면 건너뛴다. 날짜(YYYYMMDD)→DateOnly, 콤마 포함 숫자→decimal. /// public static class SeibroBondOptionXrcParser { public sealed record Row( string Isin, string? KorSecnNm, DateOnly? XrcBeginDt, DateOnly? XrcExpryDt, DateOnly ErlyRedDt, string? OptionTpcd, decimal? ApliIrate, decimal? ErlyRedamtVal, decimal? IntPayAmt, decimal? IssuRema, decimal? XrcRatio ); public static IReadOnlyList Parse(SeibroXml.Envelope envelope) { var rows = new List(); foreach (var fields in envelope.Rows) { var isin = SeibroXml.GetOrNull(fields, "ISIN")?.Trim(); var erlyRedDt = SeibroFieldParse.Date(SeibroXml.GetOrNull(fields, "ERLY_RED_DT")); if (string.IsNullOrEmpty(isin) || erlyRedDt is null) { continue; } rows.Add(new Row( isin, SeibroXml.GetOrNull(fields, "KOR_SECN_NM")?.Trim(), SeibroFieldParse.Date(SeibroXml.GetOrNull(fields, "XRC_BEGIN_DT")), SeibroFieldParse.Date(SeibroXml.GetOrNull(fields, "XRC_EXPRY_DT")), erlyRedDt.Value, SeibroXml.GetOrNull(fields, "OPTION_TPCD")?.Trim(), SeibroFieldParse.Decimal(SeibroXml.GetOrNull(fields, "APLI_IRATE")), SeibroFieldParse.Decimal(SeibroXml.GetOrNull(fields, "ERLY_REDAMT_VAL")), SeibroFieldParse.Decimal(SeibroXml.GetOrNull(fields, "INT_PAY_AMT")), SeibroFieldParse.Decimal(SeibroXml.GetOrNull(fields, "ISSU_REMA")), SeibroFieldParse.Decimal(SeibroXml.GetOrNull(fields, "XRC_RATIO")) )); } return rows; } }