SeibroStkIncdecParser.cs 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. namespace Infrastructure.StockData;
  2. /// <summary>
  3. /// SEIBro getStkIncdecDetails(주식증감내역) 응답 파서 — 순수 C#. 공용 SeibroXml envelope 입력.
  4. /// 자연키(ISIN, SECN_ISSU_NTIMES, ISSU_DT, SECN_ISSU_RACD) 중 하나라도 없거나 비형식인 행은 건너뛴다.
  5. /// ISSU_QTY 는 감소(소각) 시 음수 → Long 이 부호 보존. ISSUPRC 0 은 유효값(무상).
  6. /// </summary>
  7. public static class SeibroStkIncdecParser
  8. {
  9. public sealed record Row(
  10. int? IssucoCustno,
  11. string Isin,
  12. string? SecnKacd,
  13. int SecnIssuNtimes,
  14. DateOnly IssuDt,
  15. decimal? Issuprc,
  16. long? IssuQty,
  17. string SecnIssuRacd,
  18. string? SecnIssuNm,
  19. DateOnly? ListDt
  20. );
  21. public static IReadOnlyList<Row> Parse(SeibroXml.Envelope envelope)
  22. {
  23. var rows = new List<Row>();
  24. foreach (var fields in envelope.Rows)
  25. {
  26. var isin = SeibroXml.GetOrNull(fields, "ISIN")?.Trim();
  27. var ntimes = SeibroFieldParse.Int(SeibroXml.GetOrNull(fields, "SECN_ISSU_NTIMES"));
  28. var issuDt = SeibroFieldParse.Date(SeibroXml.GetOrNull(fields, "ISSU_DT"));
  29. var racd = SeibroXml.GetOrNull(fields, "SECN_ISSU_RACD")?.Trim();
  30. if (string.IsNullOrEmpty(isin) || ntimes is null || issuDt is null || string.IsNullOrEmpty(racd))
  31. {
  32. continue;
  33. }
  34. rows.Add(new Row(
  35. SeibroFieldParse.Int(SeibroXml.GetOrNull(fields, "ISSUCO_CUSTNO")),
  36. isin,
  37. SeibroXml.GetOrNull(fields, "SECN_KACD")?.Trim(),
  38. ntimes.Value,
  39. issuDt.Value,
  40. SeibroFieldParse.Decimal(SeibroXml.GetOrNull(fields, "ISSUPRC")),
  41. SeibroFieldParse.Long(SeibroXml.GetOrNull(fields, "ISSU_QTY")),
  42. racd,
  43. SeibroXml.GetOrNull(fields, "SECN_ISSU_NM")?.Trim(),
  44. SeibroFieldParse.Date(SeibroXml.GetOrNull(fields, "LIST_DT"))
  45. ));
  46. }
  47. return rows;
  48. }
  49. }