| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- using System.ComponentModel.DataAnnotations;
- using System.ComponentModel.DataAnnotations.Schema;
- namespace Domain.Entities.Paper;
- /// <summary>
- /// 계좌 일별 스냅샷 — (AccountID, TradeDate) UNIQUE. 좌수 NAV·수익률·MDD 를 배치(M2)가 산출/upsert 한다 (d4 §③).
- /// 리더보드 기간 수익률은 스냅샷 nav 로 조회한다.
- /// </summary>
- public class PaperDailySnapshot
- {
- [ForeignKey(nameof(AccountID))]
- public virtual PaperAccount Account { get; private set; } = null!;
- [Key]
- public int ID { get; private set; }
- public int AccountID { get; private set; }
- /// <summary>거래일</summary>
- public DateOnly TradeDate { get; private set; }
- /// <summary>자유 + 예약 토큰</summary>
- public decimal Token { get; private set; }
- /// <summary>포지션 평가액</summary>
- public decimal PositionsValue { get; private set; }
- /// <summary>순자산 = Token + PositionsValue</summary>
- public decimal Equity { get; private set; }
- /// <summary>좌당 순자산 (18,8) = Equity / Units</summary>
- public decimal UnitNav { get; private set; }
- /// <summary>일간 수익률 Bp</summary>
- public int DailyReturnBp { get; private set; }
- /// <summary>누적 수익률 Bp = (nav - 1) × 10000</summary>
- public int CumReturnBp { get; private set; }
- /// <summary>최고 순자산 (MDD 산출용)</summary>
- public decimal PeakEquity { get; private set; }
- /// <summary>최대 낙폭 Bp</summary>
- public int MddBp { get; private set; }
- /// <summary>누적 체결 수 (리더보드 등재 요건)</summary>
- public int FillCountCum { get; private set; }
- public DateTime CreatedAt { get; private set; } = DateTime.UtcNow;
- private PaperDailySnapshot() { }
- public static PaperDailySnapshot Create(
- int accountID,
- DateOnly tradeDate,
- decimal token,
- decimal positionsValue,
- decimal equity,
- decimal unitNav,
- int dailyReturnBp,
- int cumReturnBp,
- decimal peakEquity,
- int mddBp,
- int fillCountCum
- ) {
- if (accountID <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(accountID));
- }
- return new PaperDailySnapshot
- {
- AccountID = accountID,
- TradeDate = tradeDate,
- Token = token,
- PositionsValue = positionsValue,
- Equity = equity,
- UnitNav = unitNav,
- DailyReturnBp = dailyReturnBp,
- CumReturnBp = cumReturnBp,
- PeakEquity = peakEquity,
- MddBp = mddBp,
- FillCountCum = fillCountCum
- };
- }
- /// <summary>동일 (AccountID, TradeDate) 재실행 시 값 갱신 (upsert, 배치 멱등).</summary>
- public void Update(
- decimal token,
- decimal positionsValue,
- decimal equity,
- decimal unitNav,
- int dailyReturnBp,
- int cumReturnBp,
- decimal peakEquity,
- int mddBp,
- int fillCountCum
- ) {
- Token = token;
- PositionsValue = positionsValue;
- Equity = equity;
- UnitNav = unitNav;
- DailyReturnBp = dailyReturnBp;
- CumReturnBp = cumReturnBp;
- PeakEquity = peakEquity;
- MddBp = mddBp;
- FillCountCum = fillCountCum;
- }
- }
|