Fred v1.3
v1.1 and v1.2 together: 3x pre-market volume and a +30% target.
Why it should work
Heavy-volume names (v1.1) are the ones that run, so they are also the ones where a higher target (v1.2) pays. Combined, the backtest is the best of the shortlist per trade, on the fewest trades.
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 3x the stock's average daily volume over the previous 90 sessions (v1.0: 0.9x). 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
Marketable limit order, immediate-or-cancel, at the pre-market high +1%. If the ask is already higher, there is no trade. One entry per stock per day, none after 15:59.
Exituntil 16:00 ET
Limit sell at +30% from the fill (v1.0: +25%), stop at -10% from the fill, otherwise sold in the closing auction. No new entry and no target/stop from 15:45.
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 | ≥ 300% of the 90-session average daily volume |
| Roster | Roster fixed at | 09:30 ET |
| Entry | Limit (IOC) | pre-market high +1% |
| 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 | +30% 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.3.yaml)
# Fred v1.3 (draft, child of v1.0): v1.1 + v1.2: pre-market volume >= 3x and take profit at +30%.
# Everything else is v1.0 unchanged. Rules in words: docs/versions/v1.3.yaml.
# fred shadow configs/versions nightly forward test next to v1.0
name: fred_v1_3
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: 3.0}}
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.01}}
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.30, 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: +29.9% · 2026: +38.4%. Exits: 26% target · 47% stop · 27% close. 15 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.
- Two choices stacked on the same data: the most exposed to overfitting of the four.
- 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.