20260705035218_AddPaperTrading.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. using System;
  2. using Microsoft.EntityFrameworkCore.Migrations;
  3. #nullable disable
  4. namespace Infrastructure.Migrations.AppDb
  5. {
  6. /// <inheritdoc />
  7. public partial class AddPaperTrading : Migration
  8. {
  9. /// <inheritdoc />
  10. protected override void Up(MigrationBuilder migrationBuilder)
  11. {
  12. migrationBuilder.AddColumn<bool>(
  13. name: "Paper_Enabled",
  14. table: "Config",
  15. type: "bit",
  16. nullable: false,
  17. defaultValue: false,
  18. comment: "모의투자 활성화");
  19. migrationBuilder.AddColumn<int>(
  20. name: "Paper_FeeRateBp",
  21. table: "Config",
  22. type: "int",
  23. nullable: false,
  24. defaultValue: 0,
  25. comment: "매매 수수료 Bp");
  26. migrationBuilder.AddColumn<int>(
  27. name: "Paper_MaxHolding",
  28. table: "Config",
  29. type: "int",
  30. nullable: false,
  31. defaultValue: 0,
  32. comment: "계좌 최대 보유 토큰 (0=무제한)");
  33. migrationBuilder.AddColumn<int>(
  34. name: "Paper_MinDeposit",
  35. table: "Config",
  36. type: "int",
  37. nullable: false,
  38. defaultValue: 0,
  39. comment: "최소 입금 토큰");
  40. migrationBuilder.AddColumn<int>(
  41. name: "Paper_MinFillsForRank",
  42. table: "Config",
  43. type: "int",
  44. nullable: false,
  45. defaultValue: 0,
  46. comment: "리더보드 등재 최소 체결 수");
  47. migrationBuilder.AddColumn<int>(
  48. name: "Paper_OrderMaxPctBp",
  49. table: "Config",
  50. type: "int",
  51. nullable: false,
  52. defaultValue: 0,
  53. comment: "1주문 상한 Bp");
  54. migrationBuilder.AddColumn<int>(
  55. name: "Paper_TaxRateBp",
  56. table: "Config",
  57. type: "int",
  58. nullable: false,
  59. defaultValue: 0,
  60. comment: "매도 거래세 Bp");
  61. migrationBuilder.AddColumn<int>(
  62. name: "Paper_WithdrawProfitBurnBp",
  63. table: "Config",
  64. type: "int",
  65. nullable: false,
  66. defaultValue: 0,
  67. comment: "출금 수익분 소각 Bp");
  68. migrationBuilder.CreateTable(
  69. name: "PaperAccount",
  70. columns: table => new
  71. {
  72. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  73. .Annotation("SqlServer:Identity", "1, 1"),
  74. MemberID = table.Column<int>(type: "int", nullable: false, comment: "회원 ID"),
  75. Token = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "자유 현금 토큰"),
  76. ReservedToken = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "매수 예약 토큰"),
  77. Units = table.Column<decimal>(type: "decimal(18,8)", precision: 18, scale: 8, nullable: false, comment: "좌수"),
  78. TotalDeposited = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "누적 입금"),
  79. TotalWithdrawn = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "누적 출금"),
  80. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
  81. RowVersion = table.Column<byte[]>(type: "rowversion", rowVersion: true, nullable: false)
  82. },
  83. constraints: table =>
  84. {
  85. table.PrimaryKey("PK_PaperAccount", x => x.ID);
  86. table.ForeignKey(
  87. name: "FK_PaperAccount_Member_MemberID",
  88. column: x => x.MemberID,
  89. principalTable: "Member",
  90. principalColumn: "ID",
  91. onDelete: ReferentialAction.Cascade);
  92. },
  93. comment: "모의투자 계좌 (회원당 1개)");
  94. migrationBuilder.CreateTable(
  95. name: "PaperDailySnapshot",
  96. columns: table => new
  97. {
  98. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  99. .Annotation("SqlServer:Identity", "1, 1"),
  100. AccountID = table.Column<int>(type: "int", nullable: false, comment: "계좌 ID"),
  101. TradeDate = table.Column<DateOnly>(type: "date", nullable: false, comment: "거래일"),
  102. Token = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "자유+예약 토큰"),
  103. PositionsValue = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "포지션 평가액"),
  104. Equity = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "순자산"),
  105. UnitNav = table.Column<decimal>(type: "decimal(18,8)", precision: 18, scale: 8, nullable: false, comment: "좌당 순자산"),
  106. DailyReturnBp = table.Column<int>(type: "int", nullable: false, comment: "일간 수익률 Bp"),
  107. CumReturnBp = table.Column<int>(type: "int", nullable: false, comment: "누적 수익률 Bp"),
  108. PeakEquity = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "최고 순자산"),
  109. MddBp = table.Column<int>(type: "int", nullable: false, comment: "최대 낙폭 Bp"),
  110. FillCountCum = table.Column<int>(type: "int", nullable: false, comment: "누적 체결 수"),
  111. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false)
  112. },
  113. constraints: table =>
  114. {
  115. table.PrimaryKey("PK_PaperDailySnapshot", x => x.ID);
  116. table.ForeignKey(
  117. name: "FK_PaperDailySnapshot_PaperAccount_AccountID",
  118. column: x => x.AccountID,
  119. principalTable: "PaperAccount",
  120. principalColumn: "ID",
  121. onDelete: ReferentialAction.Cascade);
  122. },
  123. comment: "모의투자 계좌 일별 스냅샷 (좌수 NAV·수익률·MDD)");
  124. migrationBuilder.CreateTable(
  125. name: "PaperLedger",
  126. columns: table => new
  127. {
  128. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  129. .Annotation("SqlServer:Identity", "1, 1"),
  130. AccountID = table.Column<int>(type: "int", nullable: false, comment: "계좌 ID"),
  131. Type = table.Column<byte>(type: "tinyint", nullable: false, comment: "유형 (1=입금, 2=출금)"),
  132. TokenAmount = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "이동 토큰"),
  133. UnitsDelta = table.Column<decimal>(type: "decimal(18,8)", precision: 18, scale: 8, nullable: false, comment: "좌수 변화"),
  134. WalletTxRefID = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true, comment: "연결 지갑 거래 RefID"),
  135. BalanceAfter = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "이동 후 자유 토큰 잔액"),
  136. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false)
  137. },
  138. constraints: table =>
  139. {
  140. table.PrimaryKey("PK_PaperLedger", x => x.ID);
  141. table.ForeignKey(
  142. name: "FK_PaperLedger_PaperAccount_AccountID",
  143. column: x => x.AccountID,
  144. principalTable: "PaperAccount",
  145. principalColumn: "ID",
  146. onDelete: ReferentialAction.Cascade);
  147. },
  148. comment: "모의투자 입출금 감사 원장");
  149. migrationBuilder.CreateTable(
  150. name: "PaperOrder",
  151. columns: table => new
  152. {
  153. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  154. .Annotation("SqlServer:Identity", "1, 1"),
  155. AccountID = table.Column<int>(type: "int", nullable: false, comment: "계좌 ID"),
  156. StockCode = table.Column<string>(type: "nchar(6)", fixedLength: true, maxLength: 6, nullable: false, comment: "단축코드"),
  157. Side = table.Column<byte>(type: "tinyint", nullable: false, comment: "방향 (1=매수, 2=매도)"),
  158. FillRule = table.Column<byte>(type: "tinyint", nullable: false, comment: "체결 규칙 (1=시가, 2=종가)"),
  159. Quantity = table.Column<int>(type: "int", nullable: false, comment: "수량"),
  160. ReservedAmount = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "매수 예약금"),
  161. TargetDate = table.Column<DateOnly>(type: "date", nullable: false, comment: "체결 기준일"),
  162. CancelableUntil = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "취소 가능 시한"),
  163. Status = table.Column<byte>(type: "tinyint", nullable: false, comment: "상태 (1=대기, 2=체결, 3=취소, 4=거부)"),
  164. RejectReason = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true, comment: "거부 사유"),
  165. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false)
  166. },
  167. constraints: table =>
  168. {
  169. table.PrimaryKey("PK_PaperOrder", x => x.ID);
  170. table.ForeignKey(
  171. name: "FK_PaperOrder_PaperAccount_AccountID",
  172. column: x => x.AccountID,
  173. principalTable: "PaperAccount",
  174. principalColumn: "ID",
  175. onDelete: ReferentialAction.Cascade);
  176. },
  177. comment: "모의투자 주문");
  178. migrationBuilder.CreateTable(
  179. name: "PaperPosition",
  180. columns: table => new
  181. {
  182. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  183. .Annotation("SqlServer:Identity", "1, 1"),
  184. AccountID = table.Column<int>(type: "int", nullable: false, comment: "계좌 ID"),
  185. StockCode = table.Column<string>(type: "nchar(6)", fixedLength: true, maxLength: 6, nullable: false, comment: "단축코드"),
  186. Quantity = table.Column<int>(type: "int", nullable: false, comment: "보유 수량"),
  187. ReservedQuantity = table.Column<int>(type: "int", nullable: false, comment: "매도 예약 수량"),
  188. AvgPrice = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: false, comment: "평균 단가"),
  189. UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
  190. RowVersion = table.Column<byte[]>(type: "rowversion", rowVersion: true, nullable: false)
  191. },
  192. constraints: table =>
  193. {
  194. table.PrimaryKey("PK_PaperPosition", x => x.ID);
  195. table.ForeignKey(
  196. name: "FK_PaperPosition_PaperAccount_AccountID",
  197. column: x => x.AccountID,
  198. principalTable: "PaperAccount",
  199. principalColumn: "ID",
  200. onDelete: ReferentialAction.Cascade);
  201. },
  202. comment: "모의투자 보유 포지션");
  203. migrationBuilder.CreateTable(
  204. name: "PaperFill",
  205. columns: table => new
  206. {
  207. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  208. .Annotation("SqlServer:Identity", "1, 1"),
  209. OrderID = table.Column<int>(type: "int", nullable: false, comment: "주문 ID"),
  210. Price = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "체결가"),
  211. Quantity = table.Column<int>(type: "int", nullable: false, comment: "수량"),
  212. Fee = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "수수료"),
  213. Tax = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "거래세"),
  214. Amount = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: false, comment: "체결 총액"),
  215. RealizedPnL = table.Column<decimal>(type: "decimal(18,0)", precision: 18, scale: 0, nullable: true, comment: "매도 확정 손익"),
  216. PriceDate = table.Column<DateOnly>(type: "date", nullable: false, comment: "체결가 기준일"),
  217. FilledAt = table.Column<DateTime>(type: "datetime2", nullable: false)
  218. },
  219. constraints: table =>
  220. {
  221. table.PrimaryKey("PK_PaperFill", x => x.ID);
  222. table.ForeignKey(
  223. name: "FK_PaperFill_PaperOrder_OrderID",
  224. column: x => x.OrderID,
  225. principalTable: "PaperOrder",
  226. principalColumn: "ID",
  227. onDelete: ReferentialAction.Cascade);
  228. },
  229. comment: "모의투자 체결 결과 (주문당 1건, 멱등)");
  230. migrationBuilder.CreateIndex(
  231. name: "IX_PaperAccount_MemberID",
  232. table: "PaperAccount",
  233. column: "MemberID",
  234. unique: true);
  235. migrationBuilder.CreateIndex(
  236. name: "IX_PaperDailySnapshot_AccountID_TradeDate",
  237. table: "PaperDailySnapshot",
  238. columns: new[] { "AccountID", "TradeDate" },
  239. unique: true);
  240. migrationBuilder.CreateIndex(
  241. name: "IX_PaperDailySnapshot_TradeDate_CumReturnBp",
  242. table: "PaperDailySnapshot",
  243. columns: new[] { "TradeDate", "CumReturnBp" },
  244. descending: new[] { false, true });
  245. migrationBuilder.CreateIndex(
  246. name: "IX_PaperFill_OrderID",
  247. table: "PaperFill",
  248. column: "OrderID",
  249. unique: true);
  250. migrationBuilder.CreateIndex(
  251. name: "IX_PaperLedger_AccountID_CreatedAt",
  252. table: "PaperLedger",
  253. columns: new[] { "AccountID", "CreatedAt" },
  254. descending: new[] { false, true });
  255. migrationBuilder.CreateIndex(
  256. name: "IX_PaperOrder_AccountID_CreatedAt",
  257. table: "PaperOrder",
  258. columns: new[] { "AccountID", "CreatedAt" },
  259. descending: new[] { false, true });
  260. migrationBuilder.CreateIndex(
  261. name: "IX_PaperOrder_Status_TargetDate",
  262. table: "PaperOrder",
  263. columns: new[] { "Status", "TargetDate" });
  264. migrationBuilder.CreateIndex(
  265. name: "IX_PaperPosition_AccountID_StockCode",
  266. table: "PaperPosition",
  267. columns: new[] { "AccountID", "StockCode" },
  268. unique: true);
  269. }
  270. /// <inheritdoc />
  271. protected override void Down(MigrationBuilder migrationBuilder)
  272. {
  273. migrationBuilder.DropTable(
  274. name: "PaperDailySnapshot");
  275. migrationBuilder.DropTable(
  276. name: "PaperFill");
  277. migrationBuilder.DropTable(
  278. name: "PaperLedger");
  279. migrationBuilder.DropTable(
  280. name: "PaperPosition");
  281. migrationBuilder.DropTable(
  282. name: "PaperOrder");
  283. migrationBuilder.DropTable(
  284. name: "PaperAccount");
  285. migrationBuilder.DropColumn(
  286. name: "Paper_Enabled",
  287. table: "Config");
  288. migrationBuilder.DropColumn(
  289. name: "Paper_FeeRateBp",
  290. table: "Config");
  291. migrationBuilder.DropColumn(
  292. name: "Paper_MaxHolding",
  293. table: "Config");
  294. migrationBuilder.DropColumn(
  295. name: "Paper_MinDeposit",
  296. table: "Config");
  297. migrationBuilder.DropColumn(
  298. name: "Paper_MinFillsForRank",
  299. table: "Config");
  300. migrationBuilder.DropColumn(
  301. name: "Paper_OrderMaxPctBp",
  302. table: "Config");
  303. migrationBuilder.DropColumn(
  304. name: "Paper_TaxRateBp",
  305. table: "Config");
  306. migrationBuilder.DropColumn(
  307. name: "Paper_WithdrawProfitBurnBp",
  308. table: "Config");
  309. }
  310. }
  311. }