CoolFace
Apppublic

thinkingEverytime/QuantOracle

sourceHugging Faceupdated 6mo agoView on Hugging Face
1likes
build_features.py81 linesDownload Raw Back to scripts
1#!/usr/bin/env python32"""Build a feature table from local OHLCV store.3 4Writes: data/features.parquet5"""6 7# ruff: noqa: E402  (sys.path bootstrap must run before local imports)8 9from __future__ import annotations10 11import argparse12from pathlib import Path13 14import pandas as pd15 16import sys17 18from pathlib import Path as _Path19 20# Scripts are executed with `scripts/` as sys.path[0]. Add repo root + frontend for imports.21_ROOT = str(_Path(__file__).resolve().parents[1])22if _ROOT not in sys.path:23    sys.path.insert(0, _ROOT)24_FRONTEND = str(_Path(__file__).resolve().parents[1] / "frontend")25if _FRONTEND not in sys.path:26    sys.path.insert(0, _FRONTEND)27 28from services.store import data_dir, read_ohlcv29 30from quant.features import build_features, build_targets31 32try:33    import duckdb  # type: ignore34except Exception:  # pragma: no cover35    duckdb = None36 37 38def main():39    ap = argparse.ArgumentParser()40    ap.add_argument("--horizon", type=int, default=5)41    ap.add_argument("--out", default="", help="Output parquet path (default: data/features.parquet)")42    args = ap.parse_args()43 44    root = data_dir()45    ohlcv_dir = root / "ohlcv"46    if not ohlcv_dir.exists():47        raise SystemExit(f"Missing {ohlcv_dir} (run scripts/ingest_eod.py first)")48 49    rows = []50    for p in sorted(ohlcv_dir.glob("*.parquet")):51        sym = p.stem52        h = read_ohlcv(sym)53        if h.empty or "Close" not in h:54            continue55        feats = build_features(h)56        if feats.empty:57            continue58        y = build_targets(h["Close"], horizon=args.horizon).reindex(feats.index)59        feats = feats.assign(symbol=sym, target=y)60        rows.append(feats.reset_index().rename(columns={"index": "Date"}))61 62    if not rows:63        raise SystemExit("No features produced")64 65    out = pd.concat(rows, ignore_index=True).dropna()66    out["Date"] = pd.to_datetime(out["Date"])67    out_path = Path(args.out) if args.out else (root / "features.parquet")68    out_path.parent.mkdir(parents=True, exist_ok=True)69    if duckdb is None:70        raise SystemExit("duckdb is required to write Parquet (install: `pip install duckdb`).")71    con = duckdb.connect(database=":memory:")72    con.register("df", out)73    path = str(out_path).replace("'", "''")74    con.execute(f"COPY df TO '{path}' (FORMAT PARQUET)")75    con.close()76    print(f"Wrote {len(out):,} rows -> {out_path}")77 78 79if __name__ == "__main__":80    main()81