| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- using Domain.Entities.Stocks.ValueObject;
- using Infrastructure.StockData;
- namespace Application.Tests;
- [TestClass]
- public sealed class KrxCommodityParserTests
- {
- [TestMethod]
- public void ParseDaily_Gold_MapsIsuCodeOhlcChangeAndRate()
- {
- // KRX OpenAPI(gold_bydd_trd) 실검증 샘플 — ISU_CD/ISU_NM + 주식형 OHLC(TDD_*) + 전일대비(CMPPREVDD_PRC)·등락률(FLUC_RT). 협의가격은 금 미제공 → null
- const string json = """
- {"OutBlock_1":[
- {"BAS_DD":"20250102","ISU_CD":"04020000","ISU_NM":"금 99.99_1Kg","TDD_CLSPRC":"128790","CMPPREVDD_PRC":"940","FLUC_RT":"0.74","TDD_OPNPRC":"128600","TDD_HGPRC":"129060","TDD_LWPRC":"128000","ACC_TRDVOL":"219723","ACC_TRDVAL":"28313945030"}
- ]}
- """;
- var rows = KrxCommodityParser.ParseDaily(json, CommodityMarket.Gold);
- Assert.AreEqual(1, rows.Count);
- var c = rows[0];
- Assert.AreEqual(CommodityMarket.Gold, c.CommodityMarket, "시장은 호출 인자로 결정");
- Assert.AreEqual("04020000", c.Code, "ISU_CD");
- Assert.AreEqual("금 99.99_1Kg", c.Name);
- Assert.AreEqual(new DateOnly(2025, 1, 2), c.TradeDate);
- Assert.AreEqual(128790m, c.Close, "TDD_CLSPRC");
- Assert.AreEqual(128600m, c.Open, "TDD_OPNPRC");
- Assert.AreEqual(129060m, c.High, "TDD_HGPRC");
- Assert.AreEqual(128000m, c.Low, "TDD_LWPRC");
- Assert.AreEqual(940m, c.ChangeAmount, "CMPPREVDD_PRC");
- Assert.AreEqual(0.74m, c.ChangeRate, "FLUC_RT");
- Assert.IsNull(c.WeightedDiscussionPrice, "협의가격은 금 미제공 → null");
- Assert.AreEqual(219723L, c.Volume);
- Assert.AreEqual(28313945030L, c.TradeValue);
- }
- [TestMethod]
- public void ParseDaily_Emission_MapsFields_WithNegativeChangeAndThousandsCommas()
- {
- // KRX OpenAPI(ets_bydd_trd) 실검증 샘플 — 배출권(KAU/KCU/KOC). 음수 전일대비/등락률 + 천단위 콤마 방어
- const string json = """
- {"OutBlock_1":[
- {"BAS_DD":"20250102","ISU_CD":"05003240","ISU_NM":"KAU24","TDD_CLSPRC":"9,280","CMPPREVDD_PRC":"-210","FLUC_RT":"-2.21","TDD_OPNPRC":"9,300","TDD_HGPRC":"9,500","TDD_LWPRC":"9,280","ACC_TRDVOL":"859,512","ACC_TRDVAL":"8,011,657,000"}
- ]}
- """;
- var rows = KrxCommodityParser.ParseDaily(json, CommodityMarket.Emission);
- Assert.AreEqual(1, rows.Count);
- var c = rows[0];
- Assert.AreEqual(CommodityMarket.Emission, c.CommodityMarket);
- Assert.AreEqual("05003240", c.Code);
- Assert.AreEqual("KAU24", c.Name);
- Assert.AreEqual(9280m, c.Close, "종가 콤마 제거");
- Assert.AreEqual(9300m, c.Open);
- Assert.AreEqual(9500m, c.High);
- Assert.AreEqual(9280m, c.Low);
- Assert.AreEqual(-210m, c.ChangeAmount, "음수 전일대비");
- Assert.AreEqual(-2.21m, c.ChangeRate, "음수 등락률");
- Assert.IsNull(c.WeightedDiscussionPrice);
- Assert.AreEqual(859512L, c.Volume, "거래량 콤마 제거");
- Assert.AreEqual(8011657000L, c.TradeValue, "거래대금 콤마 제거");
- }
- [TestMethod]
- public void ParseDaily_Oil_UsesOilNameAsCode_WeightedPrices_NoOhlcNoChange()
- {
- // KRX OpenAPI(oil_bydd_trd) 실검증 샘플 — ISU_CD 없음, OIL_NM(유종구분)을 Code·Name 으로. 가중평균가격 경쟁→Close / 협의→WeightedDiscussionPrice. OHLC 0, 등락 null
- const string json = """
- {"OutBlock_1":[
- {"BAS_DD":"20250102","OIL_NM":"휘발유","WT_AVG_PRC":"1595.88","WT_DIS_AVG_PRC":"1549.24","ACC_TRDVOL":"3365180","ACC_TRDVAL":"5292762275"}
- ]}
- """;
- var rows = KrxCommodityParser.ParseDaily(json, CommodityMarket.Oil);
- Assert.AreEqual(1, rows.Count);
- var c = rows[0];
- Assert.AreEqual(CommodityMarket.Oil, c.CommodityMarket);
- Assert.AreEqual("휘발유", c.Code, "석유는 OIL_NM 을 코드로 사용");
- Assert.AreEqual("휘발유", c.Name);
- Assert.AreEqual(new DateOnly(2025, 1, 2), c.TradeDate);
- Assert.AreEqual(1595.88m, c.Close, "가중평균가격_경쟁(WT_AVG_PRC) → Close");
- Assert.AreEqual(1549.24m, c.WeightedDiscussionPrice, "가중평균가격_협의(WT_DIS_AVG_PRC)");
- Assert.AreEqual(0m, c.Open, "석유 OHLC 미제공 → 0");
- Assert.AreEqual(0m, c.High);
- Assert.AreEqual(0m, c.Low);
- Assert.IsNull(c.ChangeAmount, "석유 전일대비 미제공 → null");
- Assert.IsNull(c.ChangeRate, "석유 등락률 미제공 → null");
- Assert.AreEqual(3365180L, c.Volume);
- Assert.AreEqual(5292762275L, c.TradeValue);
- }
- [TestMethod]
- public void ParseDaily_NullOrDashValues_AreHandled()
- {
- // 미반영 행 — 금/배출권의 전일대비/등락률이 ""/"-" → null (0 과 구분), 가격은 "-" → 0.
- const string goldJson = """
- {"OutBlock_1":[
- {"BAS_DD":"20250102","ISU_CD":"04020100","ISU_NM":"미니금 99.99_100g","TDD_CLSPRC":"-","CMPPREVDD_PRC":"","FLUC_RT":"-","TDD_OPNPRC":"-","TDD_HGPRC":"-","TDD_LWPRC":"-","ACC_TRDVOL":"0","ACC_TRDVAL":"0"}
- ]}
- """;
- var goldRows = KrxCommodityParser.ParseDaily(goldJson, CommodityMarket.Gold);
- Assert.AreEqual(1, goldRows.Count);
- Assert.AreEqual(0m, goldRows[0].Close, "\"-\" 가격은 0");
- Assert.IsNull(goldRows[0].ChangeAmount, "\"\" 전일대비는 null");
- Assert.IsNull(goldRows[0].ChangeRate, "\"-\" 등락률은 null");
- // 석유 — 협의가격 미체결("") → null
- const string oilJson = """
- {"OutBlock_1":[
- {"BAS_DD":"20250102","OIL_NM":"등유","WT_AVG_PRC":"1000.00","WT_DIS_AVG_PRC":"","ACC_TRDVOL":"3963954","ACC_TRDVAL":"3973954000"}
- ]}
- """;
- var oilRows = KrxCommodityParser.ParseDaily(oilJson, CommodityMarket.Oil);
- Assert.AreEqual(1, oilRows.Count);
- Assert.AreEqual(1000.00m, oilRows[0].Close);
- Assert.IsNull(oilRows[0].WeightedDiscussionPrice, "\"\" 협의가격은 null");
- }
- [TestMethod]
- public void ParseDaily_EmptyOrMissingBlock_ReturnsEmpty()
- {
- // basDd 미반영 — OutBlock_1 이 빈 배열
- Assert.AreEqual(0, KrxCommodityParser.ParseDaily("""{"OutBlock_1":[]}""", CommodityMarket.Gold).Count);
- // 인증 실패 등 OutBlock_1 노드 자체가 없는 응답도 안전하게 0건
- Assert.AreEqual(0, KrxCommodityParser.ParseDaily("""{"respMsg":"Unauthorized API Call","respCode":"401"}""", CommodityMarket.Oil).Count);
- }
- }
|