A monthly low-volatility stock selection backtest
A low-volatility stock strategy selects securities by a risk feature; it is not a promise of positive returns or a minimum-variance optimizer. Freeze the return window, data-freshness and liquidity gates, monthly ranking, equal stock allocations and actual order timing. Then reconcile the selected sleeve, cash reserve, costs and terminal treatment.
This guide implements a synthetic US-stock panel with twenty monthly slots and a USD account. CoTrading defensive-selection tools remain planned or unverified. No historical constituent provider, leverage, borrowing or live broker was tested. All reported account values are constructed mechanism checks.
Specify sixty-three returns, not sixty-three prices
At a scheduled completed close, require 64 compatible prices to construct 63 simple returns. Each return is current price divided by previous price minus one. Do not calculate standard deviation directly on price levels or treat 63 prices as 63 intervals. Save both endpoint dates with the score.
The fixture uses population standard deviation of those 63 returns. Python’s statistics documentation distinguishes this from sample standard deviation. The denominator is a declared convention, not a claim that one estimator is always best. No annualization is needed for this same-window relative ranking.
The raw-price toy period has no corporate actions. A real study must define distributions and adjustment treatment consistently. Identical-looking fields from different vendors may produce different returns, and a missing historical membership file cannot be repaired by a correct volatility function. Keep the market and currency uniform.
Exclude stale observations before rewarding low risk
Require all 64 price observations to be finite, positive and freshly observed under the supplied price_age contract. Require 63 positive finite volume observations with average at least 1,000 shares. This conservative eligibility rule is fixed before ranking; its threshold is an invented example, not a capacity estimate.
A forward-filled halted or unavailable price can create artificial zero returns. It must not win simply because its calculated standard deviation is small. Freshness information is therefore separate from numeric price validity. A finite repeated ten is not enough evidence that a tradable observation occurred.
Conversely, truly fresh flat prices with positive activity can have zero estimated volatility and still qualify under this contract. The example includes that counterfactual. Do not equate every zero score with a halt or discard a valid observation merely because it resembles the stale-price control numerically.
Build the synthetic cross section
There are 22 names. S01 through S20 have alternating positive and negative simple returns with increasing amplitudes from 0.001 to 0.020. S21 uses amplitude 0.0001 but lacks the first price. S22 has flat prices, zero volume and a stale age of one throughout its initial history.
At decision index 63, the valid lowest-risk twenty are S01 through S20 in that order. S21 is excluded for incomplete prices; S22 for stale prices. The ranking gate must not convert either into zero risk. Exact selected members and exclusion reasons are asserted, not merely the count of twenty.
The second monthly decision is index 84, twenty-one sessions later. Its 64-price window begins after S21’s missing first observation, so S21 now qualifies and ranks first. The new list is S21 followed by S01 through S19; S20 leaves. This is a history-completeness transition, not a retrospective filling of S21’s earlier missing value.
Freeze monthly holdings and sizing
Execute each decision at its next supplied open: indices 64 and 85. Hold the chosen names between monthly events; do not rerank daily and quietly change the strategy. The synthetic schedule is declared explicitly rather than fetched from an exchange calendar.
Each selected stock receives forty shares at the supplied transaction price ten. That gives equal 400-unit allocations across the twenty-name sleeve, 8,000 total stock notional from 10,000 initial capital. The remaining capital covers cash and fees. It is equal stock allocation within the sleeve, not a claim that the account is fully invested.
If fewer than twenty names satisfy the rules, this fixed-allocation design leaves unused slots in cash rather than leverages the remaining stocks. A different full-investment convention would need new quantities and cash checks. The ordinary fixture has exactly twenty eligible slots at both decisions.
Reconcile the first entry and daily marks
Twenty buys of forty shares at ten plus one fictional fee per order leave 1,980 cash and twenty holdings. Total entry fees are twenty. Every order is asserted with its security identifier, quantity, price, side and reason. The initial stock sleeve at execution prices is 8,000.
Daily equity uses the supplied close of each held stock, not a permanently carried entry price. At the first held close, the example’s marked equity is approximately 9,943.406948. It differs from the immediate open-price equity of 9,980 because closing marks differ; no extra cash transaction or fee is invented to explain that movement.
At the second rebalance, sell forty S20 at ten and pay one, then buy forty S21 at ten and pay one. Nineteen continuing holdings generate no replacement orders. Cash becomes 1,978, cumulative fees twenty-two and holdings remain twenty stocks. At that fixture’s supplied closing marks of ten, equity is 9,978.
Define terminal exit separately from monthly selection
The teaching run has a declared liquidation open at index 86, fixed in the configuration rather than inferred from the last input row. Sell all twenty positions at ten and pay one per sale. Final cash and equity are 9,958, total fees forty-two and quantity zero.
Flat transaction prices make the complete cash loss of forty-two equal to fees. Intermediate marks still fluctuate. This construction tests the difference between valuation and realized cash without claiming any historical low-volatility performance. A report ending before liquidation must use its marked equity rather than silently include terminal costs from another run.
The monthly exit of S20 at 85 and the final exits at 86 have different reasons. Preserve them in the ledger. A terminal accounting event is not evidence that the signal wanted to abandon every low-volatility stock, and the fixed terminal date must not move when testing an earlier data prefix.
Run the low-volatility acceptance pack
Download the complete example, save it as R587.py and run python R587.py with Python 3.12 or later. It uses only the standard library and synthetic inputs. The source is docs/growth/research/round-5/examples/R587.py.
Assertions require both exact lists, the two first-period exclusion reasons, all initial orders, the S20/S21 replacement, cash 1,980 and 1,978, terminal 9,958, fee totals and zero final holdings. The terminal order list is checked along with quantities and cash, so missing trade artifacts cannot pass solely on a summary value.
Additional tests make S22 fresh while leaving zero volume, requiring liquidity exclusion; making it fresh and liquid then allows its genuine flat-price score to qualify. Six invalid-price variants exclude S01. Prefix truncation after initial entry preserves earlier ledgers, and replacing future prices does not change the first selection.
The converse control supplies positive volume while keeping S22’s stale age. It must still be excluded. This separates freshness rejection from the zero-volume gate, so the stale-price claim is not supported merely by a stock that would already fail liquidity.
Interpret risk without a return guarantee
The Investor.gov order reference explains why an observed reference price is not assured execution. A real model needs spread, liquidity, corporate-action and market-rule evidence, not just a volatility ranking. The supplied ten-price opens are explicit assumptions.
Historical low measured volatility can coexist with concentration, gaps or losses. This strategy neither borrows to hit a risk target nor solves a covariance optimization problem. Save exposure, exclusions, turnover and cost assumptions beside genuine risk or return results if a historical study is later performed.
Archive window endpoints, estimator, freshness source, volume policy, monthly schedule, capacity, quantities and terminal convention. Recheck after any source or execution change. Completion means the selection and all account paths are reproducible, including stale-price rejection and actual exits; it does not certify defensive safety, minimum variance or future profitability.
FAQ
Can a stale flat series win because its volatility is zero?
Not here. Freshness and activity gates apply before ranking.
Is this minimum-variance optimization or leveraged risk targeting?
No. It is a fixed-window stock-selection rule with an unlevered cash reserve.