| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- using System.ComponentModel.DataAnnotations;
- namespace Domain.Entities.Stocks;
- /// <summary>
- /// ESG 지수 일별시세 (KRX OpenAPI esg/esg_index_info) — (IndexName, TradeDate) UNIQUE.
- /// 응답 shape 이 시장/파생 지수(IndexDailyPrice)와 달라 재사용하지 않고 별도 테이블로 둔다 (채권지수 BondIndexDailyPrice 와 동일한 이유):
- /// - 종가(CLSPRC_IDX)만 제공하고 시가/고가/저가·시가총액이 없다. → IndexDailyPrice 재사용 시 OHLC 5컬럼이 0/null 로 낭비된다.
- /// - 대신 ESG 지수 고유의 구성종목수(TRD_ISU_CNT)를 제공한다. → IndexDailyPrice 에는 담을 곳이 없다.
- /// 등락률(UPDN_RATE)은 정수 보관을 위해 %×100 basis point(Bp)로 저장 (IndexDailyPrice.FlucRateBp 와 동일 규약).
- /// 거래량 단위는 천주, 거래대금 단위는 백만원(원문 그대로 보관 — 스케일 변환하지 않는다).
- /// </summary>
- public class EsgIndexDailyPrice
- {
- [Key]
- public long ID { get; private set; }
- /// <summary>지수명 (IDX_NM, 예: "KRX ESG Leaders 150")</summary>
- public string IndexName { get; private set; } = default!;
- /// <summary>거래일 (BAS_DD)</summary>
- public DateOnly TradeDate { get; private set; }
- /// <summary>현재가/종가 (CLSPRC_IDX)</summary>
- public decimal Close { get; private set; }
- /// <summary>전일비 (PRV_DD_CMPR)</summary>
- public decimal ChangeVal { get; private set; }
- /// <summary>등락률 basis point = %×100 (UPDN_RATE)</summary>
- public int FlucRateBp { get; private set; }
- /// <summary>구성종목수 (TRD_ISU_CNT)</summary>
- public int ConstituentCount { get; private set; }
- /// <summary>거래량 (ACC_TRDVOL, 천주)</summary>
- public long Volume { get; private set; }
- /// <summary>거래대금 (ACC_TRDVAL, 백만원)</summary>
- public long Value { get; private set; }
- public DateTime CreatedAt { get; private set; } = DateTime.UtcNow;
- private EsgIndexDailyPrice() { }
- public static EsgIndexDailyPrice Create(
- string indexName,
- DateOnly tradeDate,
- decimal close,
- decimal changeVal,
- int flucRateBp,
- int constituentCount,
- long volume,
- long value
- ) {
- if (string.IsNullOrWhiteSpace(indexName))
- {
- throw new ArgumentException("indexName required", nameof(indexName));
- }
- return new EsgIndexDailyPrice
- {
- IndexName = indexName.Trim(),
- TradeDate = tradeDate,
- Close = close,
- ChangeVal = changeVal,
- FlucRateBp = flucRateBp,
- ConstituentCount = constituentCount,
- Volume = volume,
- Value = value
- };
- }
- /// <summary>동일 (IndexName, TradeDate) 재수집 시 값 갱신 (upsert)</summary>
- public void Update(
- decimal close,
- decimal changeVal,
- int flucRateBp,
- int constituentCount,
- long volume,
- long value
- ) {
- Close = close;
- ChangeVal = changeVal;
- FlucRateBp = flucRateBp;
- ConstituentCount = constituentCount;
- Volume = volume;
- Value = value;
- }
- }
|