Honesty doctrine. Every candidate anomaly is an artifact until proven otherwise; in-sample results are never findings; past statistical regularity does not imply future returns. This is research on statistical properties of market data — not investment advice, not a trading system.

Code / tools/new_experiment.py

tools/new_experiment.py 164 lines
#!/usr/bin/env python3
# =============================================================================
#  Project   : anomaly-atlas
#  File      : tools/new_experiment.py
#  Purpose   : Scaffold a header-compliant experiment directory (CLAUDE.md §3, §10)
#  Author    : Simon-Pierre Boucher
#  Contact   : contact@spboucher.ai
#  Data src  : hfmarketdata.io (sole data source)
#  Created   : 2026-08-12
#  Modified  : 2026-08-12
#  Platform  : macOS / Apple Silicon (arm64)
#  License   : All rights reserved (research code)
# =============================================================================
"""Scaffold a new experiment directory with the mandatory structure.

Creates: README.md, hypothesis.md (seven-field scientific block, incl. the
artifact null), benchmark.py, implementation/, results/, analysis.md — all
with conforming author headers.

Usage:
    python3 tools/new_experiment.py experiments/micro/expX_name "One-line purpose"
    python3 tools/new_experiment.py experiments/candidate_04 "Candidate: ..."
"""

from __future__ import annotations

import sys
from datetime import date
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parent.parent
TODAY = date.today().isoformat()

PY_HEADER = """\
# =============================================================================
#  Project   : anomaly-atlas
#  File      : {rel}
#  Purpose   : {purpose}
#  Author    : Simon-Pierre Boucher
#  Contact   : contact@spboucher.ai
#  Data src  : hfmarketdata.io (sole data source)
#  Created   : {today}
#  Modified  : {today}
#  Platform  : macOS / Apple Silicon (arm64)
#  License   : All rights reserved (research code)
# =============================================================================
"""

MD_HEADER = """\
---
project: anomaly-atlas
document: {doc}
author: Simon-Pierre Boucher
contact: contact@spboucher.ai
data_source: hfmarketdata.io
created: {today}
status: draft
---
"""

HYPOTHESIS_BODY = """
# Hypothesis — {name}

```text
Hypothesis
  <what we believe and why — pre-specified BEFORE looking at results>

Falsification criterion
  <the concrete measurable outcome that would prove this wrong>

Artifact null(s)
  <the fake-signal baseline(s) this must beat: bounce / staleness /
   non-synchronous timestamps / permuted calendar / random walk>

Method
  <exact procedure, universe, split (train/validation/holdout), seeds,
   number of hypotheses tested, correction applied>

Result
  <filled after the run: effect size, bootstrap CIs, corrected p-values,
   OOS status, cost-adjusted effect, credits used>

Interpretation
  <what the numbers mean, WITH confidence level (0-3); alternative
   explanations considered — artifact first>

Next experiment
  <the most informative follow-up given this result>
```
"""

BENCHMARK_BODY = '''
"""Benchmark entry point for {name}.

Must embed the hardware manifest in all result output
(see benchmarks/hardware_manifest.py) and write results to
results/{name}/<timestamp>/. Uses hfmarketdata.io data ONLY, exclusively
through src/anomaly_atlas/data/hf_client.py.
"""

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[{depth}] / "benchmarks"))
from hardware_manifest import collect_manifest  # noqa: E402


def main() -> None:
    collect_manifest()  # embedded in results once implemented
    raise NotImplementedError("experiment not yet implemented")


if __name__ == "__main__":
    main()
'''


def scaffold(exp_dir: Path, purpose: str) -> None:
    if exp_dir.exists() and any(exp_dir.iterdir()):
        sys.exit(f"error: {exp_dir} already exists and is not empty")
    name = exp_dir.name
    rel = exp_dir.relative_to(REPO_ROOT)
    (exp_dir / "implementation").mkdir(parents=True, exist_ok=True)
    (exp_dir / "results").mkdir(exist_ok=True)

    def md(doc: str) -> str:
        return MD_HEADER.format(doc=doc, today=TODAY)

    (exp_dir / "README.md").write_text(
        md(f"{name}/README")
        + f"\n# {name}\n\n{purpose}\n\nStatus: scaffolded {TODAY}, not yet run.\n"
    )
    (exp_dir / "hypothesis.md").write_text(
        md(f"{name}/hypothesis") + HYPOTHESIS_BODY.format(name=name)
    )
    (exp_dir / "analysis.md").write_text(
        md(f"{name}/analysis") + f"\n# Analysis — {name}\n\n*To be written after results exist. "
        "Must include the seven-field block and the evidence standard of CLAUDE.md §10 "
        "(never report an in-sample number as a finding).*\n"
    )
    depth = len(rel.parts)  # parents[] index up to repo root
    (exp_dir / "benchmark.py").write_text(
        PY_HEADER.format(
            rel=rel / "benchmark.py",
            purpose=f"Benchmark runner: {purpose}"[:82],
            today=TODAY,
        )
        + BENCHMARK_BODY.format(name=name, depth=depth)
    )
    print(f"scaffolded {rel} ({purpose})")


def main() -> None:
    if len(sys.argv) < 3:
        sys.exit(__doc__)
    exp_dir = (REPO_ROOT / sys.argv[1]).resolve()
    if REPO_ROOT not in exp_dir.parents:
        sys.exit("error: experiment directory must live inside the repository")
    scaffold(exp_dir, sys.argv[2])


if __name__ == "__main__":
    main()