EqualWeight

The baseline sizer: equal USD notional per signal

EqualWeight allocates equal USD notional to every signal, capped by max_positions. Hard to beat in backtests: always use it as your null hypothesis.

Import

python
from horizon.portfolio import EqualWeight

Signature

python
EqualWeight(
    max_positions: int = 20,
    gross_fraction_of_equity: float = 1.0,
)
max_positionsint
Maximum number of concurrent positions. Signals are ranked by confidence; the top N are selected.
gross_fraction_of_equityfloat
Total gross exposure as a fraction of equity. `1.0` = full equity; `0.5` = 50% gross.

The math

gross_budget = max_gross_notional_usd  (from constraints, or equity × gross_fraction_of_equity)
per_slot     = gross_budget / min(len(selected), max_positions)

Each signal gets per_slot × direction.sign as its target notional.

Use it

python
import horizon as hz
from horizon.portfolio import EqualWeight

result = hz.run(
    portfolio=EqualWeight(max_positions=10, gross_fraction_of_equity=0.8),
    ...
)

Why it’s the baseline

EqualWeight makes zero assumptions about edge estimates, vol, or correlation. If your fancy sizer doesn’t beat EqualWeight, your strategy doesn’t have real edge: the complexity is just overfitting.

Always compare your chosen sizer against EqualWeight:

python
r_complex = hz.run(portfolio=KellyOptimizer(...), ...)
r_baseline = hz.run(portfolio=EqualWeight(), ...)

if r_complex.sharpe < r_baseline.sharpe:
    print("Your complex sizer is not worth it")

When to use

Null hypothesis Your first backtest should use EqualWeight to establish a baseline.
When you don't trust your edge estimates If `expected_edge_bps` is noisy, Kelly will size positions weirdly. EqualWeight ignores the noise.
Very small portfolios With 2-3 positions, sophisticated optimization doesn't help much. EqualWeight is fine.

Pitfalls

Next