"""Convex-strategy fields: trailing stop, longer hold, manual window. These columns let the bot run trend-capture (asymmetric payoff) instead of mean-reversion scalping: - trailing_stop_pct : Trail distance once profit > activate threshold. None = use fixed take_profit_pct (legacy behaviour). - trailing_activate_at_pct: Profit % at which trailing kicks in. - max_hold_hours : Replaces the hardcoded 1-hour cap. Default 168 (7 days) so runners can run. - manual_window_until : One-shot "enable for N hours" override. When set and in the future, bot trades regardless of active_from / active_until schedule. NULL = use schedule. """ from typing import Sequence, Union import sqlalchemy as sa from alembic import op revision: str = "007" down_revision: Union[str, None] = "006" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: with op.batch_alter_table("subscriptions") as batch_op: batch_op.add_column(sa.Column("trailing_stop_pct", sa.Float(), nullable=True)) batch_op.add_column(sa.Column("trailing_activate_at_pct", sa.Float(), nullable=True)) batch_op.add_column(sa.Column("max_hold_hours", sa.Integer(), nullable=False, server_default="168")) batch_op.add_column(sa.Column("manual_window_until", sa.DateTime(), nullable=True)) def downgrade() -> None: with op.batch_alter_table("subscriptions") as batch_op: batch_op.drop_column("manual_window_until") batch_op.drop_column("max_hold_hours") batch_op.drop_column("trailing_activate_at_pct") batch_op.drop_column("trailing_stop_pct")