| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- using Infrastructure.StockData;
- namespace Application.Tests;
- [TestClass]
- public sealed class WorldIndexParserTests
- {
- [TestMethod]
- public void Parse_MapsFields_LowercasesSymbol()
- {
- // Stooq 라이트 배치(/q/l/?f=sd2t2ohlc&h&e=csv) 표준 응답 — 헤더 + 2행
- const string csv = """
- Symbol,Date,Time,Open,High,Low,Close
- ^SPX,2026-07-07,22:15:00,5100.50,5130.00,5090.10,5125.30
- ^NKX,2026-07-07,06:00:00,39000,39250,38900,39180.5
- """;
- var rows = WorldIndexCsvParser.Parse(csv);
- Assert.AreEqual(2, rows.Count);
- var spx = rows[0];
- Assert.AreEqual("^spx", spx.Symbol, "심볼은 소문자 정규화");
- Assert.AreEqual(new DateOnly(2026, 7, 7), spx.TradeDate);
- Assert.AreEqual(5100.50m, spx.Open);
- Assert.AreEqual(5130.00m, spx.High);
- Assert.AreEqual(5090.10m, spx.Low);
- Assert.AreEqual(5125.30m, spx.Close);
- var nkx = rows[1];
- Assert.AreEqual("^nkx", nkx.Symbol);
- Assert.AreEqual(39180.5m, nkx.Close);
- }
- [TestMethod]
- public void Parse_MissingClose_SkipsRow_MissingOhlc_FallsBackToClose()
- {
- // 첫 행: Close 가 N/D → 버림. 둘째 행: OHLC 가 N/D 지만 Close 유효 → OHLC 는 Close 로 보정.
- const string csv = """
- Symbol,Date,Time,Open,High,Low,Close
- ^BAD,N/D,N/D,N/D,N/D,N/D,N/D
- ^HSI,2026-07-07,10:00:00,N/D,N/D,N/D,24500.75
- """;
- var rows = WorldIndexCsvParser.Parse(csv);
- Assert.AreEqual(1, rows.Count, "Close 결측(N/D) 행은 제외");
- var hsi = rows[0];
- Assert.AreEqual("^hsi", hsi.Symbol);
- Assert.AreEqual(24500.75m, hsi.Close);
- Assert.AreEqual(24500.75m, hsi.Open, "OHLC 결측은 Close 로 보정");
- Assert.AreEqual(24500.75m, hsi.High);
- Assert.AreEqual(24500.75m, hsi.Low);
- }
- [TestMethod]
- public void Parse_EmptyOrHeaderOnly_ReturnsEmpty()
- {
- Assert.AreEqual(0, WorldIndexCsvParser.Parse("").Count);
- Assert.AreEqual(0, WorldIndexCsvParser.Parse(" ").Count);
- Assert.AreEqual(0, WorldIndexCsvParser.Parse("Symbol,Date,Time,Open,High,Low,Close").Count, "헤더만 있으면 0건");
- }
- }
|