| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- using Domain.Entities.Stocks.ValueObject;
- using Infrastructure.StockData;
- namespace Application.Tests;
- [TestClass]
- public sealed class IndexPriceParserTests
- {
- [TestMethod]
- public void ParseIndexPrices_MapsFields_CommasAndDash()
- {
- // KRX OpenAPI(kospi_dd_trd) 표준 응답 샘플 — 콤마 천단위 + "-"(결측) 혼재, 등락률 %→Bp 변환 검증
- const string json = """
- {"OutBlock_1":[
- {"BAS_DD":"20260703","IDX_CLSS":"KOSPI","IDX_NM":"코스피","CLSPRC_IDX":"3,150.25","CMPPREVDD_IDX":"-22.10","FLUC_RT":"-0.70","OPNPRC_IDX":"3,172.00","HGPRC_IDX":"3,180.55","LWPRC_IDX":"3,145.10","ACC_TRDVOL":"512,345,678","ACC_TRDVAL":"9,870,000,000,000","MKTCAP":"2,100,870,169,275,000"},
- {"BAS_DD":"20260703","IDX_CLSS":"KOSPI","IDX_NM":"코스피 200","CLSPRC_IDX":"420.15","CMPPREVDD_IDX":"6.05","FLUC_RT":"1.46","OPNPRC_IDX":"415.00","HGPRC_IDX":"421.00","LWPRC_IDX":"414.50","ACC_TRDVOL":"-","ACC_TRDVAL":"-","MKTCAP":"-"}
- ]}
- """;
- var rows = KrxIndexParser.ParseIndexPrices(json, MarketIndexSeries.KOSPI);
- Assert.AreEqual(2, rows.Count);
- var kospi = rows[0];
- Assert.AreEqual(MarketIndexSeries.KOSPI, kospi.Series);
- Assert.AreEqual("코스피", kospi.IndexName);
- Assert.AreEqual(new DateOnly(2026, 7, 3), kospi.TradeDate);
- Assert.AreEqual(3150.25m, kospi.Close, "콤마 천단위를 제거하고 소수 종가를 파싱해야 한다");
- Assert.AreEqual(-22.10m, kospi.ChangeVal);
- Assert.AreEqual(-70, kospi.FlucRateBp, "FLUC_RT -0.70% → -70 Bp");
- Assert.AreEqual(3172.00m, kospi.Open);
- Assert.AreEqual(3180.55m, kospi.High);
- Assert.AreEqual(3145.10m, kospi.Low);
- Assert.AreEqual(512345678L, kospi.Volume, "거래량 콤마 제거");
- Assert.AreEqual(9870000000000L, kospi.Value, "거래대금 콤마 제거");
- Assert.AreEqual(2100870169275000L, kospi.MarketCap);
- var kospi200 = rows[1];
- Assert.AreEqual("코스피 200", kospi200.IndexName);
- Assert.AreEqual(146, kospi200.FlucRateBp, "FLUC_RT 1.46% → 146 Bp");
- Assert.AreEqual(0L, kospi200.Volume, "\"-\" 거래량은 0 으로 흡수");
- Assert.AreEqual(0L, kospi200.Value, "\"-\" 거래대금은 0 으로 흡수");
- Assert.IsNull(kospi200.MarketCap, "\"-\" 시가총액은 null");
- }
- [TestMethod]
- public void ParseIndexPrices_EmptyOrMissingBlock_ReturnsEmpty()
- {
- // 결과 없음 — OutBlock_1 이 빈 배열
- var empty = KrxIndexParser.ParseIndexPrices("""{"OutBlock_1":[]}""", MarketIndexSeries.KOSDAQ);
- Assert.AreEqual(0, empty.Count);
- // OutBlock_1 노드 자체가 없는 응답도 안전하게 0건
- var missing = KrxIndexParser.ParseIndexPrices("""{"respMsg":"Unauthorized API Call","respCode":"401"}""", MarketIndexSeries.KRX);
- Assert.AreEqual(0, missing.Count);
- }
- [TestMethod]
- public void ParseIndexPrices_RoundsHalfAwayFromZero()
- {
- // 등락률 반올림 경계 — 0.005% → 1 Bp (AwayFromZero), -0.005% → -1 Bp
- const string json = """
- {"OutBlock_1":[
- {"BAS_DD":"20260703","IDX_NM":"경계+","CLSPRC_IDX":"100","CMPPREVDD_IDX":"0","FLUC_RT":"0.005","OPNPRC_IDX":"100","HGPRC_IDX":"100","LWPRC_IDX":"100","ACC_TRDVOL":"0","ACC_TRDVAL":"0","MKTCAP":"0"},
- {"BAS_DD":"20260703","IDX_NM":"경계-","CLSPRC_IDX":"100","CMPPREVDD_IDX":"0","FLUC_RT":"-0.005","OPNPRC_IDX":"100","HGPRC_IDX":"100","LWPRC_IDX":"100","ACC_TRDVOL":"0","ACC_TRDVAL":"0","MKTCAP":"0"}
- ]}
- """;
- var rows = KrxIndexParser.ParseIndexPrices(json, MarketIndexSeries.KRX);
- Assert.AreEqual(1, rows[0].FlucRateBp);
- Assert.AreEqual(-1, rows[1].FlucRateBp);
- }
- }
|