Metadata-Version: 2.5
Name: soloresearch
Version: 0.1.1
Summary: Autonomous single-track forecasting research: data-quality gating plus an agent-driven model search.
Project-URL: Homepage, https://github.com/shantiswarup2/soloresearch
Project-URL: Repository, https://github.com/shantiswarup2/soloresearch
Author-email: Shanti Swarup Nayak <shantiswarup.nayak@sigmoidanalytics.com>
License: MIT
License-File: LICENSE
Requires-Python: >=3.9
Requires-Dist: numpy>=1.23
Requires-Dist: openpyxl>=3.1
Requires-Dist: pandas>=1.5
Requires-Dist: pyarrow>=10.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: ruptures>=1.1.7
Requires-Dist: scipy>=1.9
Requires-Dist: statsmodels>=0.14
Description-Content-Type: text/markdown

# soloresearch

Autonomous single-track forecasting research. Point it at a table of historical
values and it does two things: checks whether the data can be forecast at all,
then lets a coding agent iteratively discover a forecasting model that drives
validation error down, with every attempt scored against a leakage-safe judge
and logged.

It is the packaged version of a research loop that, on the M5 competition data,
took a seasonal-naive baseline from WRMSSE 0.807 to 0.542 with no human in the
loop. The package ships the *method* (the data-quality gate, the scoring judge,
and the agent-driven search); the numbers you get depend on your data.

---

## Install

```
pip install soloresearch
```

Python 3.9+. All dependencies (pandas, numpy, scipy, statsmodels, ruptures,
openpyxl, pyarrow, pyyaml) install automatically.

For stage 2 you also need a coding-agent CLI, either the Gemini CLI or Claude
Code. The package works with whichever you have.

---

## Quickstart

```
soloresearch init myproject          # 1. scaffold a project
# 2. put your data file in myproject/data/ and fill in myproject/forecast.yaml
soloresearch run myproject           # 3. data-quality checks + stage the panel
cd myproject/autoresearch
gemini                               # 4. or `claude`
```

Then give the agent this prompt:

> Read GEMINI.md and begin the autonomous forecasting research loop.
> Iterate on solution.py until RMSSE plateaus.

That is the whole flow. Stage 1 (`run`) is automatic. Stage 2 is an agent
working in the project, exactly as the original research loop did.

---

## How it works

### Stage 1 - data quality (automatic)

`soloresearch run` reads your `forecast.yaml`, loads the data, and runs a
two-part assessment on every series:

- **Structural** - parses timestamps, sorts, de-duplicates, fills calendar gaps,
  and infers the target profile from the actual values. Verdict: Clean /
  Acceptable / Deficient.
- **Forecastability** - gates on the three things no model can fix: too little
  history, a constant/flat series, or pure white noise. Verdict: Forecastable /
  Not Forecastable.

It also characterises each series (trend, seasonality, demand class) and detects
four kinds of regime change (level, trend, variance, seasonality). The headline
is **Forecast-Ready %**: the share of series that are both non-Deficient and
Forecastable.

Reports are written to `myproject/outputs/` as Excel (detailed), HTML (summary),
and JSON (machine-readable). A cleaned panel is staged for stage 2.

If too little of the data is forecastable, it stops here and tells you why.

### Stage 2 - agent-driven model search

The clean panel becomes a research problem. A coding agent, following the
`GEMINI.md` / `CLAUDE.md` instructions in the project, repeatedly:

1. reads the current best score,
2. edits `solution.py` (one hypothesis at a time),
3. runs `python run.py` to score it against a leakage-safe RMSSE judge that
   holds out the last `horizon` periods of each series,
4. keeps the change if the score improved, reverts it otherwise,
5. repeats until the score plateaus.

Every attempt is snapshotted and logged to `autoresearch/runs/`, so the whole
search is auditable. The judge only ever shows `predict()` the training history;
the holdout is hidden, and anti-leakage rules are enforced in the instructions.

---

## forecast.yaml

```yaml
file: sales.parquet    # data file inside data/  (.parquet or .csv)
time: date             # timestamp column
target: target         # column to forecast
entity: series_id      # column identifying each series (omit if single series)
partitions: []         # extra grouping columns (optional)
horizon: 6             # periods ahead to forecast and hold out for validation
timestep: M            # Y / Q / M / W / D / H
metric: smape          # reporting metric
```

Only `file`, `time`, and `target` are strictly required; the rest are inferred
when omitted, but declaring them is more reliable.

---

## What a project looks like

```
myproject/
  data/              your input file
  forecast.yaml      your config
  outputs/           DQ reports (Excel / HTML / JSON) + staged panel
  autoresearch/      the research harness the agent drives
    solution.py        the model file the agent evolves
    run.py             scores the current solution
    GEMINI.md          agent instructions
    runs/              every attempt, snapshotted and scored
```

---

## Scope and honest notes

- This ships a **method**, not a guaranteed number. The M5 result (0.807 to
  0.542) is a documented demonstration of the loop; your dataset, metric, and
  agent will produce their own result.
- Stage 2 is **agent-driven** by design: an external coding agent operates the
  harness by following the prompt, which is what makes the search auditable and
  reproducible as a process. It is not a black-box API call.
- The search is **single-track** (one solution improved along one path). A
  population-based version with an explicit trust layer is a separate project.

---

## License

MIT