M1 │ 스캐너 최소 거래량 100만→10만주 │ kosdaq_scanner.py │
├─────┼─────────────────────────────────────────────────────┼────────────────────────────────┤ │ M2 │ ADX 히스테리시스 18/22 (플리핑 방지) │ mean_reversion_strategy.py │ ├─────┼─────────────────────────────────────────────────────┼────────────────────────────────┤ │ M3 │ 분할매도 최소 수익 1.0%→0.5% │ mean_reversion_strategy.py │ ├─────┼─────────────────────────────────────────────────────┼────────────────────────────────┤ │ M4 │ ORB 갭 필터 4% + 레인지 폭 0.3% 최소 │ day_trading_strategy.py │ ├─────┼─────────────────────────────────────────────────────┼────────────────────────────────┤ │ M5 │ 쿨다운 스트릭 부분매도 시 미변경 │ daytrading/position_manager.py │ ├─────┼─────────────────────────────────────────────────────┼────────────────────────────────┤ │ M6 │ MDD 강제매도 loss_tracker 기록 제거 (허위 ban 방지) │ mdd_manager.py │ ├─────┼─────────────────────────────────────────────────────┼────────────────────────────────┤ │ M7 │ RSI Wilder 스무딩으로 통일 │ mean_reversion_strategy.py
This commit is contained in:
@@ -36,7 +36,7 @@ def upgrade() -> None:
|
||||
]:
|
||||
try:
|
||||
batch_op.add_column(sa.Column(col_name, col_type, nullable=True))
|
||||
except Exception:
|
||||
except (sa.exc.OperationalError, sa.exc.ProgrammingError):
|
||||
pass # 이미 존재하는 컬럼은 무시
|
||||
|
||||
# total_amount 백필
|
||||
|
||||
@@ -11,6 +11,7 @@ Create Date: 2026-03-10
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision: str = "0002"
|
||||
down_revision: Union[str, None] = "0001"
|
||||
@@ -18,63 +19,26 @@ branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def _safe_create_index(table, index_name, columns):
|
||||
"""인덱스가 이미 존재하면 스킵."""
|
||||
conn = op.get_bind()
|
||||
result = conn.execute(sa.text(
|
||||
"SELECT 1 FROM pg_indexes WHERE tablename=:t AND indexname=:i"
|
||||
), {"t": table, "i": index_name})
|
||||
if not result.fetchone():
|
||||
op.create_index(index_name, table, columns)
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ── trade_history 인덱스 ──────────────────────────────────────────────
|
||||
with op.batch_alter_table("trade_history", schema=None) as batch_op:
|
||||
batch_op.create_index(
|
||||
"ix_trade_history_status_created_at",
|
||||
["status", "created_at"],
|
||||
)
|
||||
batch_op.create_index(
|
||||
"ix_trade_history_stock_order_created",
|
||||
["stock_code", "order_type", "created_at"],
|
||||
)
|
||||
|
||||
# ── market_data 인덱스 ────────────────────────────────────────────────
|
||||
with op.batch_alter_table("market_data", schema=None) as batch_op:
|
||||
batch_op.create_index(
|
||||
"ix_market_data_stock_code_timestamp",
|
||||
["stock_code", "timestamp"],
|
||||
)
|
||||
|
||||
# ── stock_analysis 인덱스 ─────────────────────────────────────────────
|
||||
with op.batch_alter_table("stock_analysis", schema=None) as batch_op:
|
||||
batch_op.create_index(
|
||||
"ix_stock_analysis_stock_code_analysis_date",
|
||||
["stock_code", "analysis_date"],
|
||||
)
|
||||
|
||||
# ── portfolio 인덱스 ──────────────────────────────────────────────────
|
||||
with op.batch_alter_table("portfolio", schema=None) as batch_op:
|
||||
batch_op.create_index(
|
||||
"ix_portfolio_quantity",
|
||||
["quantity"],
|
||||
)
|
||||
|
||||
# ── active_trades 인덱스 ──────────────────────────────────────────────
|
||||
with op.batch_alter_table("active_trades", schema=None) as batch_op:
|
||||
batch_op.create_index(
|
||||
"ix_active_trades_stock_code_status",
|
||||
["stock_code", "status"],
|
||||
)
|
||||
batch_op.create_index(
|
||||
"ix_active_trades_status",
|
||||
["status"],
|
||||
)
|
||||
|
||||
# ── watchlist_stocks 인덱스 ───────────────────────────────────────────
|
||||
with op.batch_alter_table("watchlist_stocks", schema=None) as batch_op:
|
||||
batch_op.create_index(
|
||||
"ix_watchlist_stocks_is_active_stock_code",
|
||||
["is_active", "stock_code"],
|
||||
)
|
||||
|
||||
# ── claude_analysis_log 인덱스 ────────────────────────────────────────
|
||||
with op.batch_alter_table("claude_analysis_log", schema=None) as batch_op:
|
||||
batch_op.create_index(
|
||||
"ix_claude_analysis_log_stock_code_created_at",
|
||||
["stock_code", "created_at"],
|
||||
)
|
||||
_safe_create_index("trade_history", "ix_trade_history_status_created_at", ["status", "created_at"])
|
||||
_safe_create_index("trade_history", "ix_trade_history_stock_order_created", ["stock_code", "order_type", "created_at"])
|
||||
_safe_create_index("market_data", "ix_market_data_stock_code_timestamp", ["stock_code", "timestamp"])
|
||||
_safe_create_index("stock_analysis", "ix_stock_analysis_stock_code_analysis_date", ["stock_code", "analysis_date"])
|
||||
_safe_create_index("portfolio", "ix_portfolio_quantity", ["quantity"])
|
||||
_safe_create_index("active_trades", "ix_active_trades_stock_code_status", ["stock_code", "status"])
|
||||
_safe_create_index("active_trades", "ix_active_trades_status", ["status"])
|
||||
_safe_create_index("watchlist_stocks", "ix_watchlist_stocks_is_active_stock_code", ["is_active", "stock_code"])
|
||||
_safe_create_index("claude_analysis_log", "ix_claude_analysis_log_stock_code_created_at", ["stock_code", "created_at"])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
|
||||
@@ -5,6 +5,7 @@ Revises: 0004
|
||||
Create Date: 2026-03-20
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
# revision identifiers
|
||||
revision = "0005"
|
||||
@@ -14,8 +15,12 @@ depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ix_active_trades_status는 0002에서 이미 생성됨 → stock_code 인덱스만 추가
|
||||
op.create_index("ix_active_trades_stock_code", "active_trades", ["stock_code"])
|
||||
conn = op.get_bind()
|
||||
result = conn.execute(sa.text(
|
||||
"SELECT 1 FROM pg_indexes WHERE tablename='active_trades' AND indexname='ix_active_trades_stock_code'"
|
||||
))
|
||||
if not result.fetchone():
|
||||
op.create_index("ix_active_trades_stock_code", "active_trades", ["stock_code"])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
|
||||
@@ -16,10 +16,16 @@ depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column(
|
||||
"news",
|
||||
sa.Column("sentiment_score", sa.Numeric(5, 3), nullable=True),
|
||||
)
|
||||
conn = op.get_bind()
|
||||
result = conn.execute(sa.text(
|
||||
"SELECT 1 FROM information_schema.columns "
|
||||
"WHERE table_name='news' AND column_name='sentiment_score'"
|
||||
))
|
||||
if not result.fetchone():
|
||||
op.add_column(
|
||||
"news",
|
||||
sa.Column("sentiment_score", sa.Numeric(5, 3), nullable=True),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
|
||||
Reference in New Issue
Block a user