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;
}
}