Quant Trading for Programmers 29: Generate Target Weights From A Candidate List
· 12 min read · Views --
Last updated on

Quant Trading for Programmers 29: Generate Target Weights From A Candidate List

Author: Alex Xiang


Quant Trading for Programmers 29: Generate Target Weights From A Candidate List

Article 19 could already convert target weights into a rebalance plan. But the target weights themselves were still handwritten.

Article 29 adds a plain first policy: generate equal-weight targets from a candidate stock list while controlling gross exposure and the maximum number of symbols.

A ZiCode engineer planning target weights

Why Start With Equal Weight

Equal weight is not the optimal strategy, but it has one advantage: it is easy to explain.

In the early paper-trading stage, the weighting policy should not be more complex than the system itself. First make the chain run end to end with equal weight, then discuss factor weighting, risk budgeting, or industry constraints.

Equal weight is not the only common way to generate weights. Other approaches include weighting by factor scores, inverse volatility, market-cap or turnover constraints, and industry-neutral constraints. They are closer to real strategies, but they also make it easier to hide mistakes inside complicated parameters. Equal weight is a good first baseline because anomalies are easier to locate.

Policy Parameters

Chapter 29 adds app/target_weight_policy.py.

@dataclass(frozen=True)
class TargetWeightPolicy:
    max_symbols: int = 5
    gross_exposure: float = 0.8
    min_weight: float = 0.01

These three fields control the maximum number of stocks, the gross exposure cap, and the minimum single-stock weight.

Generate Equal-Weight Targets

targets = build_equal_weight_targets(
    ["000001.SZ", "600000.SH"],
    TargetWeightPolicy(max_symbols=2, gross_exposure=0.6),
)

The result is 30% per stock. The function deduplicates symbols, filters empty symbols, and truncates the list by the maximum symbol count.

Normalize Weights

Another common input is an external strategy that already produced weights, but whose total exceeds the allowed cap.

normalize_target_weights() drops invalid weights and compresses the total weight into max_total.

Current Integrated Run

In article 29, the paper-notify command uses the policy to convert candidate stocks into target weights:

uv run python -m scripts.chapter_examples paper-notify

Target-weight policy run result generated by the paper-notify command

The example candidate list contains a duplicated 000001.SZ. The policy deduplicates first, then generates two stocks at 30% each with gross_exposure=60%. Finally, max_total=55% compresses the total exposure to 55%, giving each stock 27.5%.

Chapter Update And Repository

This chapter adds:

  • app/target_weight_policy.py.
  • An equal-weight target-weight policy.
  • Constraints for maximum symbols, gross exposure, and minimum weight.
  • Target-weight normalization.
  • An integrated paper-notify example showing candidate deduplication, equal-weight generation, and gross-exposure normalization.
  • Background on equal weighting, factor weighting, volatility weighting, and other common weighting policies.
  • tests/test_target_weight_policy.py, covering deduplication, truncation, tiny weights, and normalization.

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-29
uv sync --extra dev
uv run pytest tests/test_target_weight_policy.py

Chapter 29 is commit f71baeb, tagged as chapter-29.

Summary

The target-weight policy should stay simple at first.

Article 29 converts a candidate list into explainable equal-weight targets, giving the rebalance plan a more stable input. The next article summarizes prices, production checks, and notification receipts into a run health report.