The Model in One Sentence

Each strategy is modelled as a $10,000 equal-weight portfolio that rebalances at every snapshot date — selling stocks that left the screen and buying stocks that entered it, with all positions sized equally.

Step-by-Step: What Happens at Each Snapshot

1
Record the screen output

At each snapshot date, the list of stocks passing the strategy's filter criteria is recorded with their closing prices. This is the raw input.

2
Classify each position

Each stock from the previous snapshot falls into one of three categories: Retained — still in the screen, Exited — dropped off the screen, or New — just entered the screen.

3
Calculate period returns

Retained stocks use actual snapshot-to-snapshot price change. Exited stocks are assumed to have had 0% price change since they were last in the screen — the sell fee is the only cost. New entrants are added at the current snapshot price and start earning returns from the next period onward.

4
Apply equal weights

The portfolio value at the start of each period is divided equally across all positions in that period's starting screen. Every stock gets the same dollar allocation.

5
Compound across periods

The ending portfolio value from one period becomes the starting value for the next. Returns compound.

Position Sizing Formula

position_size = portfolio_value ÷ n_stocks
period_return = Σ (position_size × (1 + stock_return)) − portfolio_value
# stock_return = (exit_price − entry_price) / entry_price for retained
# stock_return = −FEE_PCT for exited
# stock_return = not counted until next period for new entrants

Transaction Fee

A one-way sell fee is applied whenever a stock exits the screen. In the Python script this is controlled by a single constant:

TRANSACTION_FEE_PCT = 0.001 # 0.1% — set to 0.0 to disable

The fee simulates the friction of closing a position: broker commissions, bid-ask spread, and minor market impact. With fee enabled, an exited stock earns −0.1% rather than exactly 0%.

On low-turnover screens (90%+ retention) the impact is negligible. On high-turnover screens like Piotroski F-Score — which replaced 75% of its portfolio in Period 1 — the drag compounds meaningfully over time.

Example impact: Piotroski had 3 of 4 stocks exit in Period 1. Fee on those 3 exits = 3 × (0.1% × $2,500 each) = −$7.50 on a $10,000 portfolio = −0.075% drag that period, on top of any price losses. Over 12 periods, a consistently high-turnover strategy accumulates significantly more friction cost than a stable one.

Benchmarks

Two benchmarks are tracked alongside the strategies: the S&P 500 (^GSPC) and the NASDAQ Composite (^IXIC). Both are modelled the same way — $10,000 starting value, compounded using the actual index closing prices at each snapshot date. No dividends are included.

Benchmark prices are hardcoded in the script from the actual closing values on each snapshot date. This makes the analysis fully reproducible with no dependency on live data feeds.

Known Limitations

Exit price assumption. Exited stocks are assumed to have had 0% price movement since the last snapshot. In reality, they may have risen or fallen significantly before being sold. This is a conservative assumption — over many periods it tends to average out, but for any single period it adds noise.

Execution timing. The model assumes you can buy and sell exactly at the snapshot closing price. In practice, trades execute during the day with slippage. The fee partially compensates for this, but precise execution is not modelled.

New entrant lag. Stocks that enter the screen only start earning returns from the next snapshot onward. If a new entrant moves strongly in the period it joined, that return is not captured. This means strategies with high turnover slightly understate potential performance on the entry side.

Equal weight vs optimal weight. Allocating equally across all positions ignores differences in conviction, liquidity, and volatility. A more sophisticated model might size positions based on market cap, volatility, or signal strength. Equal weight is chosen for its simplicity and reproducibility.


Worked Example: S2 · Schloss Dividend, Period 1

The following example walks through the full calculation for the Schloss Dividend screen from the March 10 → April 22, 2026 period. This is real data from the journal.

Starting Value

$10,000

Positions

11

Size Each

$909.09

Period

43 days

The Mar 10 screen contained 11 stocks. Position size: $10,000 ÷ 11 = $909.09 each. By April 22, 8 stocks were retained, 3 had exited the screen, and 2 new entrants joined.

Ticker Status Entry (Mar 10) Exit (Apr 22) Return End Value
GGB Retained $3.58 $4.30 +20.11% $1,091.82
TX Retained $39.55 $42.77 +8.14% $982.73
VSNT Retained $36.54 $39.65 +8.51% $986.36
CHRD Retained $123.22 $131.13 +6.42% $967.27
DAC Retained $112.25 $115.02 +2.47% $931.82
MTH Retained $68.03 $69.49 +2.15% $928.18
ATHM Retained $19.61 $18.70 −4.64% $867.27
MOS Retained $26.92 $24.20 −10.10% $817.18
REXR Exited $35.66 — sold −0.1%* $908.18
ESNT Exited $59.29 — sold −0.1%* $908.18
RDN Exited $33.53 — sold −0.1%* $908.18
Portfolio Total +2.97% $10,297.17

* Exited stocks: no price change assumed; −0.1% sell fee applied.  |  New entrants THO and JOYY joined at the Apr 22 snapshot and are included in Period 2 calculations only.

The Calculation in Full

position_size = $10,000 ÷ 11 = $909.09

# retained stocks — actual price change
GGB contribution = $909.09 × (1 + 0.2011) = $1,091.55
MOS contribution = $909.09 × (1 − 0.1011) = $817.18
# ... (same for all 8 retained stocks)

# exited stocks — sell fee only
REXR contribution = $909.09 × (1 − 0.0010) = $908.18
# ... (same for ESNT, RDN)

portfolio_end = sum of all 11 contributions = $10,296.72
period_return = ($10,296.72 − $10,000) / $10,000 = +2.97%

The $10,296.72 then becomes the starting value for Period 2, where it is divided equally across the 10 stocks in the Apr 22 screen (8 retained + 2 new entrants: THO, JOYY).