using System; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable namespace Infrastructure.Migrations.AppDb { /// public partial class AddPaperTrading : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.AddColumn( name: "Paper_Enabled", table: "Config", type: "bit", nullable: false, defaultValue: false, comment: "모의투자 활성화"); migrationBuilder.AddColumn( name: "Paper_FeeRateBp", table: "Config", type: "int", nullable: false, defaultValue: 0, comment: "매매 수수료 Bp"); migrationBuilder.AddColumn( name: "Paper_MaxHolding", table: "Config", type: "int", nullable: false, defaultValue: 0, comment: "계좌 최대 보유 토큰 (0=무제한)"); migrationBuilder.AddColumn( name: "Paper_MinDeposit", table: "Config", type: "int", nullable: false, defaultValue: 0, comment: "최소 입금 토큰"); migrationBuilder.AddColumn( name: "Paper_MinFillsForRank", table: "Config", type: "int", nullable: false, defaultValue: 0, comment: "리더보드 등재 최소 체결 수"); migrationBuilder.AddColumn( name: "Paper_OrderMaxPctBp", table: "Config", type: "int", nullable: false, defaultValue: 0, comment: "1주문 상한 Bp"); migrationBuilder.AddColumn( name: "Paper_TaxRateBp", table: "Config", type: "int", nullable: false, defaultValue: 0, comment: "매도 거래세 Bp"); migrationBuilder.AddColumn( name: "Paper_WithdrawProfitBurnBp", table: "Config", type: "int", nullable: false, defaultValue: 0, comment: "출금 수익분 소각 Bp"); migrationBuilder.CreateTable( name: "PaperAccount", columns: table => new { ID = table.Column(type: "int", nullable: false, comment: "PK") .Annotation("SqlServer:Identity", "1, 1"), MemberID = table.Column(type: "int", nullable: false, comment: "회원 ID"), Token = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "자유 현금 토큰"), ReservedToken = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "매수 예약 토큰"), Units = table.Column(type: "decimal(18,8)", precision: 18, scale: 8, nullable: false, comment: "좌수"), TotalDeposited = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "누적 입금"), TotalWithdrawn = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "누적 출금"), CreatedAt = table.Column(type: "datetime2", nullable: false), RowVersion = table.Column(type: "rowversion", rowVersion: true, nullable: false) }, constraints: table => { table.PrimaryKey("PK_PaperAccount", x => x.ID); table.ForeignKey( name: "FK_PaperAccount_Member_MemberID", column: x => x.MemberID, principalTable: "Member", principalColumn: "ID", onDelete: ReferentialAction.Cascade); }, comment: "모의투자 계좌 (회원당 1개)"); migrationBuilder.CreateTable( name: "PaperDailySnapshot", columns: table => new { ID = table.Column(type: "int", nullable: false, comment: "PK") .Annotation("SqlServer:Identity", "1, 1"), AccountID = table.Column(type: "int", nullable: false, comment: "계좌 ID"), TradeDate = table.Column(type: "date", nullable: false, comment: "거래일"), Token = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "자유+예약 토큰"), PositionsValue = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "포지션 평가액"), Equity = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "순자산"), UnitNav = table.Column(type: "decimal(18,8)", precision: 18, scale: 8, nullable: false, comment: "좌당 순자산"), DailyReturnBp = table.Column(type: "int", nullable: false, comment: "일간 수익률 Bp"), CumReturnBp = table.Column(type: "int", nullable: false, comment: "누적 수익률 Bp"), PeakEquity = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "최고 순자산"), MddBp = table.Column(type: "int", nullable: false, comment: "최대 낙폭 Bp"), FillCountCum = table.Column(type: "int", nullable: false, comment: "누적 체결 수"), CreatedAt = table.Column(type: "datetime2", nullable: false) }, constraints: table => { table.PrimaryKey("PK_PaperDailySnapshot", x => x.ID); table.ForeignKey( name: "FK_PaperDailySnapshot_PaperAccount_AccountID", column: x => x.AccountID, principalTable: "PaperAccount", principalColumn: "ID", onDelete: ReferentialAction.Cascade); }, comment: "모의투자 계좌 일별 스냅샷 (좌수 NAV·수익률·MDD)"); migrationBuilder.CreateTable( name: "PaperLedger", columns: table => new { ID = table.Column(type: "int", nullable: false, comment: "PK") .Annotation("SqlServer:Identity", "1, 1"), AccountID = table.Column(type: "int", nullable: false, comment: "계좌 ID"), Type = table.Column(type: "tinyint", nullable: false, comment: "유형 (1=입금, 2=출금)"), TokenAmount = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "이동 토큰"), UnitsDelta = table.Column(type: "decimal(18,8)", precision: 18, scale: 8, nullable: false, comment: "좌수 변화"), WalletTxRefID = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true, comment: "연결 지갑 거래 RefID"), BalanceAfter = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "이동 후 자유 토큰 잔액"), CreatedAt = table.Column(type: "datetime2", nullable: false) }, constraints: table => { table.PrimaryKey("PK_PaperLedger", x => x.ID); table.ForeignKey( name: "FK_PaperLedger_PaperAccount_AccountID", column: x => x.AccountID, principalTable: "PaperAccount", principalColumn: "ID", onDelete: ReferentialAction.Cascade); }, comment: "모의투자 입출금 감사 원장"); migrationBuilder.CreateTable( name: "PaperOrder", columns: table => new { ID = table.Column(type: "int", nullable: false, comment: "PK") .Annotation("SqlServer:Identity", "1, 1"), AccountID = table.Column(type: "int", nullable: false, comment: "계좌 ID"), StockCode = table.Column(type: "nchar(6)", fixedLength: true, maxLength: 6, nullable: false, comment: "단축코드"), Side = table.Column(type: "tinyint", nullable: false, comment: "방향 (1=매수, 2=매도)"), FillRule = table.Column(type: "tinyint", nullable: false, comment: "체결 규칙 (1=시가, 2=종가)"), Quantity = table.Column(type: "int", nullable: false, comment: "수량"), ReservedAmount = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "매수 예약금"), TargetDate = table.Column(type: "date", nullable: false, comment: "체결 기준일"), CancelableUntil = table.Column(type: "datetime2", nullable: false, comment: "취소 가능 시한"), Status = table.Column(type: "tinyint", nullable: false, comment: "상태 (1=대기, 2=체결, 3=취소, 4=거부)"), RejectReason = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true, comment: "거부 사유"), CreatedAt = table.Column(type: "datetime2", nullable: false) }, constraints: table => { table.PrimaryKey("PK_PaperOrder", x => x.ID); table.ForeignKey( name: "FK_PaperOrder_PaperAccount_AccountID", column: x => x.AccountID, principalTable: "PaperAccount", principalColumn: "ID", onDelete: ReferentialAction.Cascade); }, comment: "모의투자 주문"); migrationBuilder.CreateTable( name: "PaperPosition", columns: table => new { ID = table.Column(type: "int", nullable: false, comment: "PK") .Annotation("SqlServer:Identity", "1, 1"), AccountID = table.Column(type: "int", nullable: false, comment: "계좌 ID"), StockCode = table.Column(type: "nchar(6)", fixedLength: true, maxLength: 6, nullable: false, comment: "단축코드"), Quantity = table.Column(type: "int", nullable: false, comment: "보유 수량"), ReservedQuantity = table.Column(type: "int", nullable: false, comment: "매도 예약 수량"), AvgPrice = table.Column(type: "decimal(18,4)", precision: 18, scale: 4, nullable: false, comment: "평균 단가"), UpdatedAt = table.Column(type: "datetime2", nullable: false), RowVersion = table.Column(type: "rowversion", rowVersion: true, nullable: false) }, constraints: table => { table.PrimaryKey("PK_PaperPosition", x => x.ID); table.ForeignKey( name: "FK_PaperPosition_PaperAccount_AccountID", column: x => x.AccountID, principalTable: "PaperAccount", principalColumn: "ID", onDelete: ReferentialAction.Cascade); }, comment: "모의투자 보유 포지션"); migrationBuilder.CreateTable( name: "PaperFill", columns: table => new { ID = table.Column(type: "int", nullable: false, comment: "PK") .Annotation("SqlServer:Identity", "1, 1"), OrderID = table.Column(type: "int", nullable: false, comment: "주문 ID"), Price = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "체결가"), Quantity = table.Column(type: "int", nullable: false, comment: "수량"), Fee = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "수수료"), Tax = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "거래세"), Amount = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "체결 총액"), RealizedPnL = table.Column(type: "decimal(18,0)", precision: 18, scale: 0, nullable: true, comment: "매도 확정 손익"), PriceDate = table.Column(type: "date", nullable: false, comment: "체결가 기준일"), FilledAt = table.Column(type: "datetime2", nullable: false) }, constraints: table => { table.PrimaryKey("PK_PaperFill", x => x.ID); table.ForeignKey( name: "FK_PaperFill_PaperOrder_OrderID", column: x => x.OrderID, principalTable: "PaperOrder", principalColumn: "ID", onDelete: ReferentialAction.Cascade); }, comment: "모의투자 체결 결과 (주문당 1건, 멱등)"); migrationBuilder.CreateIndex( name: "IX_PaperAccount_MemberID", table: "PaperAccount", column: "MemberID", unique: true); migrationBuilder.CreateIndex( name: "IX_PaperDailySnapshot_AccountID_TradeDate", table: "PaperDailySnapshot", columns: new[] { "AccountID", "TradeDate" }, unique: true); migrationBuilder.CreateIndex( name: "IX_PaperDailySnapshot_TradeDate_CumReturnBp", table: "PaperDailySnapshot", columns: new[] { "TradeDate", "CumReturnBp" }, descending: new[] { false, true }); migrationBuilder.CreateIndex( name: "IX_PaperFill_OrderID", table: "PaperFill", column: "OrderID", unique: true); migrationBuilder.CreateIndex( name: "IX_PaperLedger_AccountID_CreatedAt", table: "PaperLedger", columns: new[] { "AccountID", "CreatedAt" }, descending: new[] { false, true }); migrationBuilder.CreateIndex( name: "IX_PaperOrder_AccountID_CreatedAt", table: "PaperOrder", columns: new[] { "AccountID", "CreatedAt" }, descending: new[] { false, true }); migrationBuilder.CreateIndex( name: "IX_PaperOrder_Status_TargetDate", table: "PaperOrder", columns: new[] { "Status", "TargetDate" }); migrationBuilder.CreateIndex( name: "IX_PaperPosition_AccountID_StockCode", table: "PaperPosition", columns: new[] { "AccountID", "StockCode" }, unique: true); } /// protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( name: "PaperDailySnapshot"); migrationBuilder.DropTable( name: "PaperFill"); migrationBuilder.DropTable( name: "PaperLedger"); migrationBuilder.DropTable( name: "PaperPosition"); migrationBuilder.DropTable( name: "PaperOrder"); migrationBuilder.DropTable( name: "PaperAccount"); migrationBuilder.DropColumn( name: "Paper_Enabled", table: "Config"); migrationBuilder.DropColumn( name: "Paper_FeeRateBp", table: "Config"); migrationBuilder.DropColumn( name: "Paper_MaxHolding", table: "Config"); migrationBuilder.DropColumn( name: "Paper_MinDeposit", table: "Config"); migrationBuilder.DropColumn( name: "Paper_MinFillsForRank", table: "Config"); migrationBuilder.DropColumn( name: "Paper_OrderMaxPctBp", table: "Config"); migrationBuilder.DropColumn( name: "Paper_TaxRateBp", table: "Config"); migrationBuilder.DropColumn( name: "Paper_WithdrawProfitBurnBp", table: "Config"); } } }