Fred v1.4
v1.0, but buy the first pullback to the pre-market high instead of the break.
Why it should work
v1.0 skips about half of its calm breaks because the ask is already more than 1% above the level. Many of those come back to test it. v1.4 rests a limit buy at the pre-market high for 15 minutes after the cross, which almost doubles the number of trades at a similar return per trade.
How it trades
Universebefore 04:00 ET
Nasdaq, NYSE and NYSE American common stocks whose previous close was under $5, with at least 20 sessions of history.
Volume filter04:00 to 09:30 ET
Pre-market volume reaches at least 90% of the stock's average daily volume over the previous 90 sessions. The names that pass at 09:30 are the day's roster.
Triggerfrom 09:30 ET
The first regular-session trade above the pre-market high. If the stock opens above it, Fred waits for a trade back below and then a new cross.
Calm-before-break gateat the cross
Volume over the 5 minutes before the cross, per minute, must be under 2x the average pre-market volume per minute. A spike into the level is skipped.
Entryat the cross
After the cross, a resting limit buy at the pre-market high for 15 minutes (v1.0: immediate-or-cancel at +1%). It fills only if a trade prints below the level, so it buys the first pullback instead of the break. Shadow replay only: the live trader does not place resting entries yet.
Exituntil 16:00 ET
Limit sell at +25% from the fill, stop at -10% from the fill, otherwise sold in the closing auction.
Sizeper trade
10% of the day's starting equity per trade (5% roughly halves the drawdown). The backtest also caps size at 10% of the entry minute's volume.
Parameters, read from the locked config
| Universe | Previous close under | $5.00 |
| Universe | Exchanges | NASDAQ, NYSE, AMEX |
| Universe | Minimum history | 20 sessions |
| Roster | Pre-market volume | ≥ 90% of the 90-session average daily volume |
| Roster | Roster fixed at | 09:30 ET |
| Entry | Limit (IOC) | pre-market high +0% |
| Entry | Calm before break | last 5 min volume/min < 2x pre-market volume/min |
| Entry | No entry after | 15:59 ET |
| Entry | Entries per stock per day | 1 |
| Exit | Take profit | +25% from the fill |
| Exit | Stop loss | -10% from the fill |
| Exit | End of day | closing auction (MOC) |
| Size | Per trade | 10% of the day's starting equity |
Full config (configs/versions/v1.4.yaml)
# Fred v1.4 (draft, child of v1.0): retest entry: after the cross, a resting limit buy at the PM high for 15 minutes (v1.0: IOC at +1%). Shadow only.
# Everything else is v1.0 unchanged. Rules in words: docs/versions/v1.4.yaml.
# fred shadow configs/versions nightly forward test next to v1.0
name: fred_v1_4
plan: paid # SIP real time (Algo Trader Plus). IEX misses ~99.8% of pre-market volume.
scanner:
prep_at: "03:50"
start: "04:00"
poll_seconds: 60
watchlist_at: "09:00"
roster_at: "09:30"
watchlist_min_progress: 0.5 # "on track" = at least 50% of the volume threshold by 09:00
max_lines: 15
baselines:
max_price: 5.0 # previous raw close under $5
exchanges: [NASDAQ, NYSE, AMEX]
avg_sessions: 90
min_history: 20
filters:
- {cls: fred.scanner.filters:PriceBand, params: {max_price: 5.0, field: prev_close}}
- {cls: fred.scanner.filters:PremarketVolumeVsAverage, params: {ratio: 0.9}}
trader:
broker: alpaca_paper # alpaca_paper | sim (dry run, no orders sent)
poll_seconds: 1 # how often the last trade is checked for the cross
last_entry: "15:59"
max_entries_per_symbol: 1
# first trade above the PM high from 09:30 (after a dip below if it opened above) -> limit IOC at PM high x 1.01
entry: {cls: fred.signals.pm_high_breakout:PmHighCross, params: {max_chase: 0.0, mode: retest, retest_seconds: 900}}
gates: # checked at the moment of the cross
- {cls: fred.live.gates:CalmBeforeBreak, params: {lookback: 5, max_ratio: 2.0}}
exit: {cls: fred.exits.target_stop:TargetStop, params: {take_profit: 0.25, stop_loss: 0.10}}
close_order: moc # anything still open sells in the closing auction
close_buffer_minutes: 15 # MOC sent at 15:45 (Alpaca cutoff 15:50); 12:45 on half days
sizer: {cls: fred.sizing.percent:PercentOfEquity, params: {pct: 0.10, skip_if_insufficient_cash: true}}
# The spec also caps size at 10% of the entry minute's volume. That volume is only known after the
# minute ends (the backtest used the full bar), so live runs without the cap; the trade log
# records the entry minute's volume to check afterwards whether it would have bound.
# To turn a live estimate on: add max_participation: 0.10 to the params above.
risk:
- {cls: fred.risk.guards:KillSwitch}
Results the version was chosen on
Replayed tick by tick (scripts/fred_v1x.py export). Buys at the ask 1 second after each trigger, stops sell at the bid 1 second later, targets fill at the limit, no entry and no target/stop from 15:45, still open sells at the official close. Fees: SEC and FINRA on sells. $25,000 start.
By year: 2025: +84.9% · 2026: +18.8%. Exits: 22% target · 42% stop · 37% close. 16 of 23 months positive.
How it is doing since the lock
Every weekday after the close, the day is replayed tick by tick from the delayed SIP tape exactly as this config would have traded it.
No forward-test days yet. The nightly replay adds one row per roster name after every US session.
Caveats
- Chosen in November 2026 out of about 60 variants tried on the same 22 months as v1.0, so some of its edge is likely luck. The forward test next to v1.0 is the real test.
- The backtest fills the limit whenever a trade prints below it. A real resting order joins the back of the queue and can miss fills on winners, so live results are likely worse.
- Weaker in 2026 (+0.57%) than 2025 (+1.98%).
- Backtest under the live rules (no entry or target/stop from 15:45, official close), stops at the real bid 1 s later. v1.0's own frozen backtest predates those rules; under them v1.0 makes +1.03% per trade on 373 trades.