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