모의투자 관리 기능 추가

This commit is contained in:
Macbook
2026-05-31 03:47:07 +09:00
parent 9d7dddfa57
commit 16d0e2c226
78 changed files with 4688 additions and 972 deletions
@@ -0,0 +1,109 @@
-- V51: 모의투자 투자금 관리 (종목별 한도, 원장, 일별 스냅샷, reset 이력)
ALTER TABLE gc_paper_account
ADD COLUMN reserved_cash DECIMAL(20, 2) NOT NULL DEFAULT 0
COMMENT '미체결 예약 금액 합',
ADD COLUMN initial_capital_snapshot DECIMAL(20, 2) NULL
COMMENT '마지막 초기화 시점 기준 초기자본',
ADD COLUMN reset_count INT NOT NULL DEFAULT 0,
ADD COLUMN last_reset_at DATETIME NULL,
ADD COLUMN status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE'
COMMENT 'ACTIVE | FROZEN';
ALTER TABLE gc_paper_trade
ADD COLUMN realized_pnl_delta DECIMAL(20, 2) NULL COMMENT '매도 체결 실현손익',
ADD COLUMN position_qty_after DECIMAL(30, 12) NULL COMMENT '체결 후 잔량',
ADD COLUMN note VARCHAR(200) NULL;
CREATE INDEX idx_paper_trade_account_symbol_created
ON gc_paper_trade (account_id, symbol, created_at);
CREATE INDEX idx_paper_trade_account_created_desc
ON gc_paper_trade (account_id, created_at DESC);
CREATE TABLE gc_paper_symbol_allocation (
id BIGINT NOT NULL AUTO_INCREMENT,
account_id BIGINT NOT NULL,
symbol VARCHAR(50) NOT NULL,
korean_name VARCHAR(100) NULL,
max_invest_krw DECIMAL(20, 2) NOT NULL DEFAULT 0,
budget_pct DECIMAL(8, 4) NULL,
strategy_id BIGINT NULL,
is_active TINYINT(1) NOT NULL DEFAULT 1,
pinned TINYINT(1) NOT NULL DEFAULT 0,
sort_order INT NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY uk_paper_alloc_account_symbol (account_id, symbol),
INDEX idx_paper_alloc_account (account_id),
CONSTRAINT fk_paper_alloc_account FOREIGN KEY (account_id)
REFERENCES gc_paper_account(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='모의투자 종목별 투자 한도';
CREATE TABLE gc_paper_cash_ledger (
id BIGINT NOT NULL AUTO_INCREMENT,
account_id BIGINT NOT NULL,
entry_type VARCHAR(30) NOT NULL,
amount DECIMAL(20, 2) NOT NULL,
cash_before DECIMAL(20, 2) NOT NULL,
cash_after DECIMAL(20, 2) NOT NULL,
ref_trade_id BIGINT NULL,
symbol VARCHAR(50) NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
INDEX idx_paper_ledger_account_created (account_id, created_at DESC),
CONSTRAINT fk_paper_ledger_account FOREIGN KEY (account_id)
REFERENCES gc_paper_account(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='모의투자 자금 변동 원장';
CREATE TABLE gc_paper_daily_snapshot (
id BIGINT NOT NULL AUTO_INCREMENT,
account_id BIGINT NOT NULL,
snapshot_date DATE NOT NULL,
cash_balance DECIMAL(20, 2) NOT NULL,
stock_eval_amount DECIMAL(20, 2) NOT NULL,
total_asset DECIMAL(20, 2) NOT NULL,
daily_pnl DECIMAL(20, 2) NOT NULL DEFAULT 0,
daily_return_pct DECIMAL(10, 4) NOT NULL DEFAULT 0,
cumulative_return_pct DECIMAL(10, 4) NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY uk_paper_snapshot_account_date (account_id, snapshot_date),
CONSTRAINT fk_paper_snapshot_account FOREIGN KEY (account_id)
REFERENCES gc_paper_account(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='모의투자 일별 자산 스냅샷';
CREATE TABLE gc_paper_reset_log (
id BIGINT NOT NULL AUTO_INCREMENT,
account_id BIGINT NOT NULL,
reset_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
initial_capital DECIMAL(20, 2) NOT NULL,
cash_before DECIMAL(20, 2) NOT NULL,
positions_json JSON NULL,
reason VARCHAR(200) NULL,
PRIMARY KEY (id),
INDEX idx_paper_reset_account (account_id),
CONSTRAINT fk_paper_reset_account FOREIGN KEY (account_id)
REFERENCES gc_paper_account(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='모의투자 계좌 초기화 이력';
-- 기존 계좌: initial_capital_snapshot 백필 (device별 app_settings)
UPDATE gc_paper_account a
LEFT JOIN gc_app_settings s ON s.device_id = a.device_id
SET a.initial_capital_snapshot = COALESCE(s.paper_initial_capital, 10000000)
WHERE a.initial_capital_snapshot IS NULL;
-- 보유 종목 → allocation seed (max = 초기자본 스냅샷)
INSERT INTO gc_paper_symbol_allocation (account_id, symbol, korean_name, max_invest_krw, is_active, sort_order)
SELECT p.account_id, p.symbol, p.korean_name,
COALESCE(a.initial_capital_snapshot, 10000000),
1, 0
FROM gc_paper_position p
JOIN gc_paper_account a ON a.id = p.account_id
WHERE p.quantity > 0
ON DUPLICATE KEY UPDATE korean_name = COALESCE(VALUES(korean_name), gc_paper_symbol_allocation.korean_name);
@@ -0,0 +1,28 @@
-- V52: 모의투자 미체결 주문
CREATE TABLE gc_paper_order (
id BIGINT NOT NULL AUTO_INCREMENT,
account_id BIGINT NOT NULL,
symbol VARCHAR(50) NOT NULL,
side VARCHAR(10) NOT NULL COMMENT 'BUY | SELL',
order_type VARCHAR(20) NOT NULL DEFAULT 'LIMIT' COMMENT 'MARKET | LIMIT',
limit_price DECIMAL(20, 2) NULL,
quantity DECIMAL(30, 12) NOT NULL,
filled_quantity DECIMAL(30, 12) NOT NULL DEFAULT 0,
status VARCHAR(20) NOT NULL DEFAULT 'PENDING'
COMMENT 'PENDING | PARTIAL | FILLED | CANCELLED',
reserved_cash DECIMAL(20, 2) NOT NULL DEFAULT 0,
reserved_qty DECIMAL(30, 12) NOT NULL DEFAULT 0,
order_kind VARCHAR(20) NOT NULL DEFAULT 'limit',
source VARCHAR(20) NOT NULL DEFAULT 'MANUAL',
strategy_id BIGINT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
filled_at DATETIME NULL,
PRIMARY KEY (id),
INDEX idx_paper_order_account_status (account_id, status),
INDEX idx_paper_order_symbol_status (symbol, status),
CONSTRAINT fk_paper_order_account FOREIGN KEY (account_id)
REFERENCES gc_paper_account(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='모의투자 미체결 주문';
@@ -0,0 +1,6 @@
-- 설정 화면: 가상매매·실거래 카테고리 권한 (기존 settings_paper와 동일 허용)
INSERT INTO gc_role_menu_permission (role, menu_id, allowed)
SELECT role, 'settings_virtual', allowed FROM gc_role_menu_permission WHERE menu_id = 'settings_paper';
INSERT INTO gc_role_menu_permission (role, menu_id, allowed)
SELECT role, 'settings_live', allowed FROM gc_role_menu_permission WHERE menu_id = 'settings_paper';