Quant Trading for Programmers 15: Strategy Promotion Needs A Gate
Quant Trading for Programmers 15: Strategy Promotion Needs A Gate
Article 14 can now save strategy experiment records. The next question is more important: which candidates are allowed to enter the next stage?
Article 15 implements a strategy promotion gate. It does not decide whether a strategy can make money. It only decides whether a candidate has enough minimum evidence to enter paper-trading observation.

Why A Gate Is Necessary
Without a gate, strategy research becomes “whichever equity curve looks better gets promoted”.
That is dangerous. A candidate should answer at least:
- Does total return meet the minimum requirement?
- Is max drawdown not too deep?
- Is trade count not zero?
- Has it cleared the baseline strategy?
Here, “promotion” does not mean live trading. It means entering paper-trading observation. It is still only the next stage, not final approval. A stricter process would continue with out-of-sample validation, performance under different market regimes, capacity checks, cost and slippage stress tests, and human review.
Promotion Rules
Chapter 15 adds app/promotion_gate.py.
@dataclass(frozen=True)
class PromotionRule:
min_total_return: float = 0.02
max_drawdown_floor: float = -0.2
min_trade_count: int = 1
require_baseline_passed: bool = True
These thresholds are not final production standards. They are only the first minimum gate. Before real deployment, out-of-sample testing, longer history, multiple market regimes, and human review are still required.
Decision Object
The gate outputs PromotionDecision:
@dataclass(frozen=True)
class PromotionDecision:
accepted: bool
status: str
reasons: tuple[str, ...]
evidence: dict[str, Any]
reasons is important. Rejection should not be a vague “no”. It should explain what failed: return too low, drawdown too deep, too few trades, or baseline not cleared.
Collect All Rejection Reasons
The decision function does not return after the first problem. It collects all reasons:
if total_return < rule.min_total_return:
reasons.append("total_return_below_minimum")
if max_drawdown < rule.max_drawdown_floor:
reasons.append("max_drawdown_too_deep")
if trade_count < rule.min_trade_count:
reasons.append("trade_count_too_low")
if rule.require_baseline_passed and not baseline_passed:
reasons.append("baseline_not_cleared")
This lets a future UI or report tell researchers everything that needs to be fixed at once.
Current Mainline Integrated Run
Article 15 continues to use the same command and sends the experiment record from article 14 into the promotion gate:
uv run python -m scripts.chapter_examples strategy-promotion --source sample
The real output is:

The sample decision is accepted_for_paper_observation. The evidence shows total_return of 0.119814, max_drawdown of -0.025908, trade_count of 1, and baseline_passed=True. These are only minimum conditions. They do not mean the strategy is reliable. They only mean this candidate is qualified for later paper-trading observation.
Chapter Update And Repository
This chapter adds:
app/promotion_gate.py.- Promotion rules, promotion decisions, payload output, and batch-candidate summaries.
tests/test_promotion_gate.py, covering acceptance, rejection, disabling baseline requirements, and reason statistics.- A real current-mainline screenshot for strategy promotion.
- Background notes on paper-trading observation, out-of-sample validation, trading capacity, and stress tests.
- A stage review for articles 11-15.
Repository:
https://github.com/ax2/zi-quant-platform
Code for this chapter:
git clone https://github.com/ax2/zi-quant-platform.git
cd zi-quant-platform
git checkout chapter-15
uv sync --extra dev
uv run pytest tests/test_promotion_gate.py
The full chapter 15 test suite passes with 187 passed, still with only the existing FastAPI deprecation warning.
Stage Review For Articles 11-15
The third group of five articles completes the loop from portfolio backtesting to strategy admission.
Article 11 extends single-symbol backtesting into multi-symbol portfolio backtesting, adding equal-weight capital allocation, equity aggregation, and trade summaries.
Article 12 adds backtest metrics, so strategy comparison no longer depends only on final return.
Article 13 implements parameter grid search and produces rankable strategy candidates.
Article 14 saves candidate and baseline comparisons as experiment records, so research results do not only exist in terminal output.
Article 15 adds a strategy promotion gate. Only candidates that satisfy minimum return, drawdown, trade-count, and baseline-comparison requirements can enter paper-trading observation.
This group of articles does not introduce an LLM and does not yet execute paper trading. The reason is simple: if strategy candidates do not have serious backtest metrics and promotion rules, adding more automation later only amplifies noise.
Summary
Strategy promotion is not “higher return means pass”.
A candidate needs experiment records, baseline comparison, minimum return, acceptable drawdown, and enough trades. Article 15 writes these requirements as testable code. The next group enters paper trading and puts promoted candidates into observable portfolio state.
Follow ZiCode on WeChat
If this post was useful, you can follow later updates on WeChat as well.
X / Twitter
Follow @ax2_zicode
Faster technical notes, short thoughts, and new-post alerts are posted on X.
More in this column
- Quant Trading for Programmers 19: Generate Rebalance Plans From Target Weights
- Quant Trading for Programmers 18: Paper Trading Needs Risk Checks Too
- Quant Trading for Programmers 17: Generate Paper-Trading Account Snapshots
- Quant Trading for Programmers 16: Start With A Clear Paper-Trading Ledger
- Quant Trading for Programmers 14: Save Strategy Candidates As Experiment Records
- Quant Trading for Programmers 13: Add A First Grid Search For Strategy Parameters
- Quant Trading for Programmers 12: Final Return Is Not Enough
- Quant Trading for Programmers 11: From One Stock To A Portfolio Backtest