SeibroStkStatParser.cs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. using System.Globalization;
  2. namespace Infrastructure.StockData;
  3. /// <summary>
  4. /// SEIBro getStkStatInfo(주식 종목 정보) 응답 파서 — 순수 C#. "SEIBro 종목 보강" (Wave 0, Stock.EnrichFromSeibro 입력).
  5. /// 행 필드(사용분): ISSUCO_CUSTNO / ISIN / SHOTN_ISIN / PVAL(액면가) / VOTRNO(1주당 의결권수) /
  6. /// TOTAL_STK_CNT(총발행주식수) / ELTSC_YN([Y]전자 [N]예탁 → bool, 그 외 null).
  7. /// 숫자 필드는 생략/빈 값/비숫자 시 null (0 과 구분). TOTAL_STK_CNT 는 스펙상 NUMBER(15,4) 라 decimal 로 읽어 long 절사.
  8. /// </summary>
  9. public static class SeibroStkStatParser
  10. {
  11. /// <summary>주식 종목 정보 1행 — 전 필드 nullable (SEIBro 는 필드 생략 가능)</summary>
  12. public sealed record Row(
  13. int? IssucoCustno,
  14. string? Isin,
  15. string? ShortCode,
  16. decimal? FaceValue,
  17. decimal? VotingRights,
  18. long? TotalIssuedShares,
  19. bool? IsElectronicSecurity
  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. rows.Add(new Row(
  27. ParseNullableInt(SeibroXml.GetOrNull(fields, "ISSUCO_CUSTNO")),
  28. SeibroXml.GetOrNull(fields, "ISIN")?.Trim(),
  29. SeibroXml.GetOrNull(fields, "SHOTN_ISIN")?.Trim(),
  30. ParseNullableDecimal(SeibroXml.GetOrNull(fields, "PVAL")),
  31. ParseNullableDecimal(SeibroXml.GetOrNull(fields, "VOTRNO")),
  32. ParseNullableLong(SeibroXml.GetOrNull(fields, "TOTAL_STK_CNT")),
  33. ParseYn(SeibroXml.GetOrNull(fields, "ELTSC_YN"))
  34. ));
  35. }
  36. return rows;
  37. }
  38. private static int? ParseNullableInt(string? raw)
  39. {
  40. return int.TryParse(raw, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value) ? value : null;
  41. }
  42. private static decimal? ParseNullableDecimal(string? raw)
  43. {
  44. return decimal.TryParse(raw, NumberStyles.Float, CultureInfo.InvariantCulture, out var value) ? value : null;
  45. }
  46. /// <summary>총발행주식수 — 스펙 NUMBER(15,4) 대비 decimal 로 읽고 정수 절사</summary>
  47. private static long? ParseNullableLong(string? raw)
  48. {
  49. return decimal.TryParse(raw, NumberStyles.Float, CultureInfo.InvariantCulture, out var value) ? (long)value : null;
  50. }
  51. private static bool? ParseYn(string? raw)
  52. {
  53. return raw?.Trim().ToUpperInvariant() switch
  54. {
  55. "Y" => true,
  56. "N" => false,
  57. _ => null
  58. };
  59. }
  60. }