using System.ComponentModel.DataAnnotations; namespace Domain.Entities.Stocks; /// /// ESG 증권상품 일별시세 (KRX OpenAPI esg/esg_etp_info) — (Name, TradeDate) UNIQUE. /// ESG 관련 ETF/ETN 등 증권상품의 일별 종가·등락 정보로, EtpDailyTrade(etp)와 응답 shape 이 다르다: /// - 단축코드(ISU_CD)가 없고 종목명(ISU_ABBRV)만 제공 → 코드 대신 종목명을 UQ 키로 사용한다. /// - OHLC 중 종가(TDD_CLSPRC)만 제공(시가/고가/저가 없음). NAV·순자산총액·기초지수도 미제공. /// - 상장주식수는 상장좌수(LIST_SHRS)로 제공된다. /// 등락률(FLUC_RT)은 소수 % 그대로 저장한다 (EtpDailyTrade.ChangeRate 와 동일 스케일, Bp 아님). 가격은 decimal(18,2). /// public class EsgSecurity { [Key] public long ID { get; private set; } /// 종목명 (ISU_ABBRV) — ISU_CD 미제공이라 이 값이 UQ 키의 일부 public string Name { get; private set; } = default!; /// 거래일 (BAS_DD) public DateOnly TradeDate { get; private set; } /// 현재가/종가 (TDD_CLSPRC) public decimal Close { get; private set; } /// 전일비 (CMPPREVDD_PRC) public decimal ChangeAmount { get; private set; } /// 등락률 % (FLUC_RT) — 소수 % 그대로 (Bp 아님) public decimal ChangeRate { get; private set; } /// 상장좌수 (LIST_SHRS) public long ListedShares { get; private set; } /// 거래량(좌) (ACC_TRDVOL) public long Volume { get; private set; } /// 거래대금(원) (ACC_TRDVAL) public long TradeValue { get; private set; } public DateTime CreatedAt { get; private set; } = DateTime.UtcNow; private EsgSecurity() { } public static EsgSecurity Create( string name, DateOnly tradeDate, decimal close, decimal changeAmount, decimal changeRate, long listedShares, long volume, long tradeValue ) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("name required", nameof(name)); } return new EsgSecurity { Name = name.Trim(), TradeDate = tradeDate, Close = close, ChangeAmount = changeAmount, ChangeRate = changeRate, ListedShares = listedShares, Volume = volume, TradeValue = tradeValue }; } /// 동일 (Name, TradeDate) 재수집 시 값 갱신 (upsert) public void Update( decimal close, decimal changeAmount, decimal changeRate, long listedShares, long volume, long tradeValue ) { Close = close; ChangeAmount = changeAmount; ChangeRate = changeRate; ListedShares = listedShares; Volume = volume; TradeValue = tradeValue; } }