# autoresearch: evolve the stock-scoring function

You are a research agent. Your job is to improve `scores()` in
`autoresearch/train.py` so the METRIC goes DOWN, one experiment at a time,
in the style of karpathy/autoresearch.

## The metric

`METRIC` = **negative annualized Sharpe** of a monthly-rebalanced,
equal-weight, top-20 S&P 500 portfolio over the in-sample window (~4y).
Lower is better. The last 12 months are a **holdout**: its Sharpe is printed
every run — mention it in your commit notes, but NEVER tune to it.

## The loop

1. Read the current best METRIC from the latest commit message (`git log --oneline`).
2. Form ONE hypothesis and edit **only** `autoresearch/train.py`.
3. Run (must finish well under 5 minutes; the seed takes seconds):

   ```
   cd /var/www/html/finance-tool && .venv/bin/python autoresearch/train.py
   ```

4. If METRIC is lower than the best so far:
   `git commit -am "metric: <value> — <one-line description of the change>"`
   Otherwise: `git checkout -- autoresearch/train.py` and try something else.
5. Repeat.

## Rules

- Edit nothing except `autoresearch/train.py`. `prepare.py`, this file, and
  everything under `screener/` are frozen.
- Keep the `scores(close, volume) -> pd.Series` contract exactly as documented
  in train.py. pandas/numpy only; no new dependencies; no network, file I/O,
  or randomness inside `scores()` — output must be deterministic.
- Price/volume signals only. Free Yahoo fundamentals are current-only
  snapshots, so any fundamental signal would leak the future — out of scope.
- The panels you receive are pre-truncated to the rebalance date. Don't try
  to defeat that; using only data up to `close.index[-1]` is the whole game.

## Research directions

- Momentum variants: window lengths, skip-month size, volatility-scaled momentum.
- Mean-reversion horizons: 5d/10d/60d z-scores; rank vs raw z.
- Volume: dollar-volume liquidity filter, volume z-score / spikes.
- Cross-sectional rank normalization instead of fixed linear clip bounds.
- Reweight or drop the four seed signals; try interactions (momentum gated on
  low volatility, reversal only in liquid names).
- Low-volatility tilt; different top_n is NOT tunable (fixed in prepare.py).

## Accepted caveats (do not try to fix)

- Survivorship bias: today's S&P constituents backfilled 5 years.
- No transaction costs or slippage; close-to-close monthly fills.
- This is research tooling, not investment advice.
