using System.ComponentModel.DataAnnotations;
using Domain.Entities.Stocks.ValueObject;
namespace Domain.Entities.Stocks;
///
/// 지수(시장) 일별 마감 시세 (KRX OpenAPI idx 엔드포인트) — (Series, IndexName, TradeDate) UNIQUE.
/// 한 계열(KOSPI/KOSDAQ/KRX) 안에 여러 지수(코스피/코스피200/… )가 존재하므로 IndexName 까지 UQ 에 포함한다.
/// 등락률은 정수 보관을 위해 %×100 basis point(Bp)로 저장 (예: -0.70% → -70, 1.45% → 145).
///
public class IndexDailyPrice
{
[Key]
public long ID { get; private set; }
/// 계열 구분 (1=KOSPI, 2=KOSDAQ, 3=KRX)
public MarketIndexSeries Series { get; private set; }
/// 지수명 (IDX_NM, 예: "코스피", "코스닥", "KRX 100")
public string IndexName { get; private set; } = default!;
/// 거래일 (BAS_DD)
public DateOnly TradeDate { get; private set; }
/// 종가 (CLSPRC_IDX)
public decimal Close { get; private set; }
/// 전일 대비 (CMPPREVDD_IDX)
public decimal ChangeVal { get; private set; }
/// 등락률 basis point = %×100 (FLUC_RT)
public int FlucRateBp { get; private set; }
/// 시가 (OPNPRC_IDX)
public decimal Open { get; private set; }
/// 고가 (HGPRC_IDX)
public decimal High { get; private set; }
/// 저가 (LWPRC_IDX)
public decimal Low { get; private set; }
/// 거래량 (ACC_TRDVOL)
public long Volume { get; private set; }
/// 거래대금 (ACC_TRDVAL, 원)
public long Value { get; private set; }
/// 상장시가총액 (MKTCAP, 원) — 미제공 시 null
public long? MarketCap { get; private set; }
public DateTime CreatedAt { get; private set; } = DateTime.UtcNow;
private IndexDailyPrice() { }
public static IndexDailyPrice Create(
MarketIndexSeries series,
string indexName,
DateOnly tradeDate,
decimal close,
decimal changeVal,
int flucRateBp,
decimal open,
decimal high,
decimal low,
long volume,
long value,
long? marketCap = null
) {
if (!Enum.IsDefined(series))
{
throw new ArgumentOutOfRangeException(nameof(series));
}
if (string.IsNullOrWhiteSpace(indexName))
{
throw new ArgumentException("indexName required", nameof(indexName));
}
return new IndexDailyPrice
{
Series = series,
IndexName = indexName.Trim(),
TradeDate = tradeDate,
Close = close,
ChangeVal = changeVal,
FlucRateBp = flucRateBp,
Open = open,
High = high,
Low = low,
Volume = volume,
Value = value,
MarketCap = marketCap
};
}
/// 동일 (Series, IndexName, TradeDate) 재수집 시 값 갱신 (upsert)
public void Update(
decimal close,
decimal changeVal,
int flucRateBp,
decimal open,
decimal high,
decimal low,
long volume,
long value,
long? marketCap = null
) {
Close = close;
ChangeVal = changeVal;
FlucRateBp = flucRateBp;
Open = open;
High = high;
Low = low;
Volume = volume;
Value = value;
MarketCap = marketCap;
}
}