A Predictive Stock Entry & Exit SystemBuilt on OVTLYR behavioral analytics
Sentiment data in; a regime call, an entry score, exit rules, a position size and a stop out. Everything below is measured on trades the rules never saw, and the places it breaks down have their own section.
Per-trade win rate
76.1%
639 completed trades on 500 unseen tickers, 2024-2026 (Slice C). Across random half-samples of those tickers, the 10th-90th percentile range is 74-78%.
Mean return per trade
+3.83%
Median +7.90%. Per-trade Sharpe 0.171. Average hold 55 days.
Portfolio return
16.1% a year
Backtest 2020-2026 on holdout tickers with the full rule set: next-open fills, 10 bp costs, 20 positions. SPY: 14.2%.
Worst drawdown
−15.4%
Same backtest. SPY held throughout fell 33.7% at its worst.
Table of contents
Per-trade metrics are measured on a permanently locked 500-ticker holdout across 2024–2026. Methodology: rolling look-ahead-free classifier, purged k-fold Cross-Validation (CV) with embargo, Benjamini-Hochberg False Discovery Rate (BH-FDR) multiple-testing correction, block-bootstrap confidence intervals. Data spans 2020–2026. Not financial advice. OVTLYR links are referral links.
Headline
The system identifies the current market regime (Crisis / Normal / Extended) from SPY breadth, scores each stock with a regime-aware composite, and exits each trade with five profit and deadline rules (T1/T2/T3/T3_EXT/CAP) plus two risk rules: a disaster stop and a dead-trade exit. Each position is sized so that hitting its stop costs 1% of the account, and half that on days with weak buying conditions. Idle cash sits in SPY while the Balancer strategy is long SPY, and in T-bills (SGOV) otherwise. Universe filters (average volume ≥ 1,000,000 and price ≥ $5) keep illiquid micro-caps and reverse-split-to-death stocks out of the candidate list.
Per-trade results — four validation slices
500 tickers were held out of all training and rule selection. Combined with a time split at 2024-01-01, this gives four test slices. Slice C (unseen tickers × unseen time) is the strictest test: tickers the rules were never tuned on, over a period the rules were never fitted to. Only completed trades are counted, and the $5 price screen uses the close on the entry day.
| Slice | n trades | Win rate | Mean ret | Median | Avg hold |
|---|---|---|---|---|---|
| Train (2,029 tickers, 2020-2023) | 5,093 | 82.74% | +4.68% | +7.84% | 45d |
| Slice A (unseen tickers, 2020-2023) | 1,168 | 82.62% | +5.15% | +7.73% | 46d |
| Slice B (train tickers, 2024-2026) | 2,551 | 77.58% | +3.35% | +8.05% | 54d |
| Slice C (500 unseen tickers × 2024-2026) | 639 | 76.06% | +3.83% | +7.90% | 55d |
Win rate stays between 76% and 83% on every slice. The two recent slices are lower: 2024-2026 has been a harder market for fear entries than 2020-2023, which held two bear markets.
How much of this depends on which tickers were held out? Split the holdout's tickers into four disjoint quarters and you get four separate reads of the same rules over the same period:
| quarter | tickers | trades | win rate | mean return |
|---|---|---|---|---|
| 1 | 57 | 163 | 77.3% | +3.69% |
| 2 | 57 | 164 | 78.7% | +5.79% |
| 3 | 57 | 156 | 80.1% | +4.01% |
| 4 | 57 | 156 | 67.9% | +1.73% |
Across 2,000 random half-samples the win rate has a 10th–90th percentile range of 74.0–78.2%, and the mean return runs from +1.03% to +6.76%. That's why the headline is a range, not a single number.
How trades end
With the live rules (the stop and the dead-trade exit included, every fill at the next open), on the holdout tickers, 2020-2026, 646 completed trades:
| Exit | % of trades | Win rate | Mean return | Median hold (trading days) |
|---|---|---|---|---|
| T1 (F&G normalization) | 5.6% | 100% | +7.8% | 15 |
| T2 (deep-fear recovery) | 12.2% | 98.7% | +11.1% | 42 |
| T3 (Crisis profit-take) | 29.9% | 100% | +11.5% | 15 |
| T3_EXT (non-Crisis, peak-aware) | 29.6% | 100% | +13.8% | 18 |
| Dead-trade exit | 11.1% | 5.6% | −11.3% | 58 |
| Disaster stop | 7.1% | 0% | −29.2% | 46 |
| CAP (120-day timeout) | 4.5% | 17.2% | −18.7% | 120 |
About three trades in four end at a profit exit. The profit exits fire only when the trade is in profit, so they win by construction; a few lose a little when the next open gaps below. The losing quarter mostly ends through the dead-trade exit, around day 60 at about −11%, and only 1 in 20 trades still reaches the 120-day cap. Each position is sized so a stop costs about 1% of the account, so a −29% stop exit costs the account about 1%.
The headline figures above are the entry and exit rules alone. Without the risk rules, 24.9% of trades on Slice C reach the cap, with an average loss of 23%.
Win rate by validation slice
What is OVTLYR?
OVTLYR (pronounced "outlier") is a behavioral analytics platform that quantifies investor sentiment for 3,300+ US-listed stocks. Its core output is the Fear & Greed oscillator — a 0–100 score per stock per day. Lower means more fear, higher means more greed.
The system on this page uses sentiment as the primary feature, with price-based signals (EMA deviations, sector breadth, order blocks) as confirmations.
Metrics are documented in the glossary.
Methodology
The pipeline
- Feature engineering. Extract Fear & Greed (F&G), EMA50 deviations, sector breadth and F&G rate of change across all 11 GICS sectors.
- Bottom identification. Find ~7,000 price bottoms using local-minima detection plus forward-return analysis.
- Stock classification. Label each ticker Mean-Reversion (MR), Momentum (MOM), or Mixed (MIX) from how it has responded to fear signals, using only data before each date.
- Cross-ticker pattern mining. Find features that predict profitable entries regardless of ticker.
- Model building. Build a scoring model for each regime.
- Backtesting. 2020–2023 in-sample (IS), 2024–2026 out-of-sample (OOS). After each trade, the next entry on that ticker can only come after the exit, so overlapping holds are never counted twice.
- Consolidation and CV. Cross-validate any candidate rule across year, regime and classification splits before shipping.
- Portfolio testing. Run the rules as a 20-position portfolio with real fills at the next open and trading costs, and judge changes on return, drawdown and Sharpe in both time halves.
Scale
- 3,300+ stocks in the OVTLYR universe. Universe filters: volume ≥ 1M + price ≥ $5.
- 500 tickers held out of all training and rule selection.
- 11 GICS sectors represented.
- 4,358 out-of-sample (OOS) trades across Slices A, B and C, plus 5,093 in-sample training trades.
- Training: Jan 2020 – Dec 2023. Time holdout: Jan 2024 onward.
- Rule discovery: ~1,000 candidate rules tested with BH-FDR multiple-testing correction (q=0.10).
The Three Regimes
The market is split into three modes — Crisis, Normal, and Extended — based on how broad the market's uptrend is. Each mode has its own buy criteria. The mode is detected from SPY breadth, the percentage of S&P 500 stocks currently in uptrends.
SPY breadth — the share of S&P 500 stocks in an uptrend
Crisis0–15%
Deep fear. Low F&G, sentiment still falling, price well under the 50-day average, weak sector.
~30 days a year · highest conviction
Normal15–50%
Stock-level fear starting to turn. Below-neutral F&G ticking up, price under the 50-day average.
Most of the year · the everyday playbook
Extended50–100%
No new entries. Over half the index is already in an uptrend, so this is late in the move — the weakest forward returns of any regime. Existing positions are held.
16% of days · no entries taken
| Mode | When it's active | What it buys | Frequency & conviction |
|---|---|---|---|
| CRISIS | SPY breadth < 15% | Stocks showing deep fear: low Fear & Greed score, sentiment dropping fast, price well below the 50-day average, weak sector. Stocks that historically bounce from extreme fear (MR) get the strongest preference. Full formula: Crisis score. | Rare (~30 days/year). Highest conviction — buy what everyone's panicking about. |
| NORMAL | SPY breadth 15–50% | Stocks with stock-level fear starting to recover: below-neutral Fear & Greed, price below the 50-day average, weak-to-neutral sector, sentiment ticking up. Full formula: Normal score. | Most of the year. Medium conviction — the everyday playbook. |
| EXTENDED | SPY breadth ≥ 50% | Nothing. More than half the index is already in an uptrend, so the move has largely happened. Existing positions are held; no new ones are opened. | 16.3% of days. The market's own forward 20-day return here is +0.51%, against +2.35% in Crisis. |
The strategy inverts across modes. In Crisis, panic-selling creates the best buying opportunities — everyone wants out, the stock is cheap, the recovery edge is largest. The mode is always checked first; everything downstream depends on it.
Why the third regime buys nothing
Extended means SPY breadth is at or above 50%: more than half the index is already trending up. That sounds like the best time to buy and measures the opposite — it is late in the move, and the market's own forward 20-day return is the weakest of the three regimes (+0.51%, against +2.35% in Crisis). Fear setups appear on 13.3% of stock-days here versus 43.6% in Crisis, so the setups this plan trades barely exist.
Nine entry variants were backtested for this regime — buying fear, buying momentum names at fear, and riding greed. Every one tied or lost to taking nothing, and the holdout trade count was the same either way: the slots refill with better Crisis and Normal trades.
Taking no entries is not sitting out. Positions opened earlier are held straight through — 11.6% to 19.1% of all position-days happen while the market is in Extended.
The n810 Trading Plan
The entry and exit side has three pieces: universe filters (volume ≥ 1M, price ≥ $5), the entry filter (F&G < 70 in every regime), and five exit rules. Two refinements: T1 is skipped while OVTLYR's trend overlay is up, and T3_EXT is skipped for MOM stocks so they can run past their first peak. See stock classification for the MR/MOM/MIX definition.
The F&G=70 cliff
Below F&G=70 (fear to neutral), few trades end in the 120-day timeout. At F&G ≥ 70 (greed), the share of trades that time out at a loss roughly doubles. Don't buy stocks that are already in greedy territory.
Universe filters (applied before any other rule)
| Filter | Trigger | Plain English |
|---|---|---|
| Liquidity | stkDetail.avgVolume < 1,000,000 → SKIP ticker | Don't consider tickers that trade fewer than 1M shares a day on average. Excludes the illiquid micro-caps that produce the worst losses. |
| Price | close < $5 → SKIP | Don't consider stocks under $5. OVTLYR's historical prices are forward-split-adjusted, so a reverse-split-to-death stock can look expensive in its history; the filter keeps these out. |
| F&G ceiling | osc >= 70 at entry → SKIP entry | Don't open a position when the stock is already in greedy territory. |
The system doesn't sell on OVTLYR's Sell flag alone.
OVTLYR publishes its own Buy / Sell flag for each stock. The profit exits ignore it: they read the underlying Fear & Greed number directly and exit when it crosses back into greed while the trade is in profit. Tested head-to-head, reading the raw number beat selling on the flag on both return and win rate. The flag is used in one place: the dead-trade exit below counts OVTLYR Sell signals on a losing position.
The five exit rules
Each day after entry, these rules are checked in order. The first one that matches sells the position at the next open. Four of them require the trade to be profitable; the fifth (CAP) is a hard 120-day deadline.
Each day a position is open, in this order
- T1Sentiment back in greed, trade up 5%+ — unless the trend is still confirmed→ sell
- T2Entered in deep fear, the bounce has faded, trade up 5%+→ sell
- T3Opened in Crisis, sentiment recovered to 40, trade up 5%+→ sell
- T3_EXTOpened outside Crisis, peaked at +10%, now fading — momentum names exempt→ sell
- CAPNone of the above fired within 120 trading days→ sell
No match — hold, and check the same five tomorrow.
| # | Name | What it's looking for | Technical trigger |
|---|---|---|---|
| T1 | Sentiment normalized | Fear & Greed has climbed back into greedy territory (≥60) and the trade is up at least 5% — unless OVTLYR's trend indicator says the stock is still in a confirmed uptrend, in which case we let it ride. | osc >= 60 AND P&L > +5% AND final_region != 1 |
| T2 | Deep-fear bounce is fading | Entered at deep fear (F&G < 50), F&G has recovered >60% of the way back to neutral and is now turning down, and the trade is up at least 5%. Lock in the bounce before it reverses. | entry F&G < 50 AND recovery > 60% AND F&G falling AND P&L > +5% |
| T3 | Crisis-entry profit-take | For trades opened in Crisis mode: sell when F&G recovers to 40 and the trade is up at least 5%. The threshold is 40 for every sector. | regime@entry == CRISIS AND osc >= 40 AND P&L > +5% |
| T3_EXT | Non-Crisis, peaked-then-faded | For trades opened outside Crisis: if the trade ever peaked at +10% or more and F&G has reached 40, lock in the remaining profit. Skipped for momentum stocks because those tend to keep running past the first peak. | regime@entry != CRISIS AND peak P&L >= +10% AND osc >= 40 AND P&L > 0 AND classification != MOMENTUM |
| CAP | 120-day deadline | If none of the above fired after 120 trading days, close the position regardless of P&L. | days held >= 120 |
T3_EXT usually sells at or near the trade's peak: the median give-back from the peak is zero. After the sale, on the train tickers, the stocks did no better than SPY over the next 60 days.
The 120-day cap is also a cooldown
Every profit exit needs P&L above 5%, so a trade whose peak never reaches +5% can only end at CAP or through the risk rules. On the holdout, about 65% of CAP trades never peak above +5%.
The cap also keeps the ticker out of the entry rules while it is held. Any rule that exits earlier hands the name back, and the entry rules often buy the same falling stock again. That is why simple early exits — stop-losses at −10% to −30%, trailing stops, day-count cuts — all lowered the return per trade. The risk rules below were chosen differently: they give up a little return in exchange for roughly halving the portfolio's worst drawdown.
How to Trade It
The complete rule set, as the daily picks publish it. Every rule is in one shared module that the picks, the position checker and the backtests all call.
Every morning (picks publish before the US open):
- Buy new picks at the open. Each pick carries a stop price and a size.
- Size each position so that hitting its stop loses 1% of the account: 1% ÷ the stop distance, capped at 8% of the account. A typical pick is about 3%; a volatile one is smaller, a calm one larger. Hold at most 20 positions. To risk 0.5% or 2% per position instead, scale every size by the same factor. On Weak buying-condition days, new picks get half that size. The picks show the halved size. Weak-day trades still make money on average, just less, so they are bought smaller, not skipped.
- Sell at the open when a position meets any exit:
- the profit exits T1, T2, T3, T3_EXT, or the 120-day CAP;
- Dead trade: held 45+ trading days, never closed 5%+ above the entry price, below the entry price today, and OVTLYR has printed 2+ Sell signals since you bought;
- Disaster stop: a close at or below the entry price − 8 × ATR20, where ATR20 is the stock's average daily range over the 20 days before you bought. That's about −33% for a typical pick. It catches disasters, not dips. An overnight gap can still open below it, which is why the size is set from it.
- Idle cash (anything not in positions) goes into SPY while the Balancer strategy is long SPY, and into SGOV (0–3 month T-bills) otherwise. The picks page shows which every morning. When it changes, act that day, at the open or the close. Sell SPY or SGOV as needed to fund new picks.
Performance
By year (Slice C: unseen tickers × 2024-2026)
| Year | n trades | WR | Mean ret | Median |
|---|---|---|---|---|
| 2024 (full year) | 329 | 78.42% | +4.55% | +7.90% |
| 2025 (full year) | 307 | 73.29% | +2.89% | +7.88% |
Trades opened in 2026 are mostly still open, and a trade only counts once it has closed, so 2026 is not shown.
Why sector breadth carries more weight at its low tail
The entry score reads sector breadth: the share of the stock's own sector on an OVTLYR Buy signal. The lower it is, the better the trade, all the way down to near zero, on all four slices. So the score grades the tail: +1.5 below 2%, +1.0 below 5%, +0.5 below 10%, on top of the standard breadth points. Inside a single regime the effect holds, and it survives a control for the stock's own Fear & Greed.
What breadth did not do
Six other readings of the same feed were tested and none survived: breadth direction, acceleration, its own EMA20/EMA50 trend, a sector's rank against the other ten, 20-day sector rotation, and price-versus-breadth divergence. Using breadth as an exit was worse still: it fires on a large share of trades at a poor win rate, cutting winners short. Only the raw low tail earned a place.
Market and sector conditions
Weaker sector and market conditions at entry go with better trades, in both regimes. For example, trades opened while the stock's sector ETF was below its 50-day average returned +5.3% on average, against +1.1% when it was above. Trade results are still about 90% stock-specific: the market explains roughly a fifth of a single stock's moves, and the sector adds a few points more.
Portfolio Results
The tables above are per trade. This is the full rule set run as a portfolio: 2020-01 to 2026-10, every fill at the next open, 10 bp trading costs, 20 positions, $100k start. Rule-set rows are the median of 20 orderings of same-day picks.
| train tickers: CAGR / max DD / Sharpe | holdout tickers | |
|---|---|---|
| Full rule set (1% risk sizing, half size on Weak days, stop, dead-trade exit, idle cash in SPY or SGOV) | 17.2% / −13.2% / 1.33 | 16.1% / −15.4% / 1.26 |
| Entry and exit rules alone, 5% per pick | 21.8% / −27.7% / 1.02 | 11.8% / −23.1% / 0.71 |
| SPY held throughout | 14.2% / −33.7% / 0.77 | same |
- Drawdown is about halved. The worst single position cost about 1.5–2% of the account, against about 4–5% with flat 5% sizing.
- The idle-cash rule matters. Holding SPY only while the Balancer strategy is long SPY, and T-bills otherwise, is what keeps the drawdown down; holding SPY all the time does not.
- It gives up return in strong markets. The edge over SPY came from 2020-2023, which held two bear markets. In 2024-2026 holding SPY (+19.5% a year) beat every active version.
What was tested and not adopted
- Ranking the day's picks. No ranking — setup score, liquidity, volatility, the stock's own record, Fear & Greed — chose better trades within a day out of sample, and filling the 20 slots highest-ranked first did no better than random order.
- Sector caps. Limiting open positions per sector (1 to 5) made the train portfolio worse.
- Leveraged ETFs for idle cash. 3× SPY instead of SPY added return but deepened the worst drawdown to about −23%.
- Different T3_EXT gates. 15–20% gates earned more per trade but didn't hold on both ticker sets; the gate stays at 10%.
- Bigger positions on Strong days. 1.5× size on Strong buying-condition days won on the train tickers but deepened the holdout drawdown from −15.0% to −17.6%.
- A faster dead-trade exit. Cutting dead trades after 20 or 30 days instead of 45, or after one Sell signal instead of two, lowered the train Sharpe from 1.33 to 1.27. The extra exits include trades that would have recovered.
The Daily Picks
The daily picks publish every weekday before the US open.
- A standing list. A name that meets the entry rule keeps meeting it, and is republished every session it does. Each pick shows whether it is new and how many sessions in a row it has qualified. Names that have been on the list a while did not do worse than fresh ones.
- Sorted by distance below the 50-day average. Deepest first. Picks flagged ⚠ PRICE GAP (a 40%+ one-day move in the last 60 sessions, usually a split, spin-off or data error) go last.
- Stop and size on every pick, from the rules in How to Trade It.
- Buying conditions. A day-level reading — Weak, Normal or Strong — from the average setup score of the day's new picks. The score separates days, not the picks within a day. On the holdout, trades opened on weak days averaged about +1.8%, on normal days +5.7% and on strong days +6.1%.
- Idle cash. Whether idle cash should be in SPY or SGOV that day.
Data Quality
The OVTLYR feed occasionally has bad-tick errors — a single-day price that's disconnected from the days around it and disagrees with other public sources. Without correction these produce fictional trades in the backtest. The pipeline scans every ticker at load time for spike-then-revert patterns, statistical outliers, and OHLC inconsistencies, and repairs high-confidence cases in memory. The effect on the headline numbers is under 0.1 points of win rate.
Caveats and known limitations
Caveat 1
Survivorship bias
Every ticker in the OVTLYR universe is one that still exists today. Delisted, bankrupt, or going-concern-failed stocks are absent from the dataset. The 76.1% holdout win rate is conditional on the stock surviving long enough to be in the universe. Trader weighting: for any stock with known bankruptcy risk, discount the signal accordingly.
Caveat 2
Short out-of-sample window
The holdout period starts in January 2024 and contains one Crisis stretch (the 2025 tariff shock and the 2026 Middle East crisis). One crisis is a thin sample. The training period (2020-2023) included COVID and the 2022 bear market, so the rules have seen several kinds of crisis, but results depend on the future looking somewhat like the past.
Caveat 3
Individual trades can lose far more than the stop
The disaster stop sits about 33% below a typical entry, and an overnight gap can open well below it. The worst holdout trade lost 76.5%. Sizing from the stop keeps any one loss to a small share of the account, but it doesn't cap the trade itself.
Caveat 4
The risk rules were chosen after the fact
The pre-declared risk test failed. The stop and the dead-trade exit were chosen after that, then checked once on the holdout tickers, where they held. Treat them as post hoc.
Caveat 5
Portfolio tests use a subset of tickers
The portfolio backtests run on the tickers with full daily data on hand: 300 train and 68 holdout tickers. With 68 tickers the holdout rarely fills all 20 slots, so it says little about how picks are chosen when there are more than 20.
Caveat 6
Split-adjusted historical prices
OVTLYR's historical price series is forward-split-adjusted. A stock that did a 1:100 reverse split shows its earlier closes 100 times higher than they were. Trader workflow: check reverse-split history for any candidate before opening a position; the ⚠ PRICE GAP flag catches most of these.
Caveat 7
Liquidity is a present-day figure
OVTLYR provides average volume as a single current number, not a daily series, so the volume filter uses today's liquidity to judge past trades.
Methodology
(1) 500 tickers were held out of all training and rule derivation. (2) The
stock classifier uses a strict as_of_date cutoff so it never reads future
records. (3) Rule thresholds are checked across the four-slice grid (train /
ticker holdout / time holdout / both). (4) Cross-validation is purged k-fold with
embargo. (5) ~1,000 candidate rules were tested with Benjamini-Hochberg
FDR correction at q=0.10. (6) Portfolio changes are
pre-declared, tested on train tickers, and must hold in both time halves before
the holdout is run once. (7) The live tools and the backtest make the same entry
and exit decision for any ticker and date.
Tools
The production scripts share the same entry and exit logic, universe filters, rolling classifier and risk rules. The live tools and the backtest make the same decision for any ticker and date.
daily.pyBuilds each day's picks: regime, entries, stop and size for each pick, buying conditions and the idle-cash reading. Published to this site every weekday before the open.
regime.pyFetches SPY data and prints the current market regime in one line: Crisis, Normal or Extended, and which playbook applies.
analyze.py TICKERTicker analysis. Buy / Wait / Avoid for new positions. For a held position
(--owned PRICE --entry-date DATE) it checks every exit — the profit exits, CAP,
the dead-trade exit and the disaster stop — and says Hold or Sell. It also lists
every earlier trade the plan would have taken on the ticker: dates, prices, days
held, F&G in and out, peak and trough, and exit reason.
portfolio.pyReads current holdings and runs the same checks on every position, with each ticker's earlier record under the plan.
scan.pyOpportunity scanner. Checks the regime first, then scores every cached ticker and prints the candidates with each one's earlier record under the plan.