SPB Git

spb/wp40_uqo

Public MIT
8.8 KB · 131 lines cpp
1// raid — command-line tool: devices | validate | estimate | data | benchmark (Phase 1: devices, validate, estimate on CSV/Parquet).2#include <cstdio>3#include <cstring>4#include <iostream>5#include <fstream>6#include <string>7#include <vector>8#include <map>9#include <nlohmann/json.hpp>10#include "raid/core/types.hpp"11#include "raid/core/error.hpp"12#include "raid/core/manifest.hpp"13#include "raid/core/hash.hpp"14#include "raid/backend/backend.hpp"15#include "raid/data/io.hpp"16#include "raid/data/calendar.hpp"17#include "raid/data/returns.hpp"18#include "raid/estimators/realized.hpp"19#include "raid/estimators/ols.hpp"20#include "raid/models/garch.hpp"21#include "raid/estimators/har.hpp"22#ifdef RAID_WITH_FINDATA23#include "raid/data/findata.hpp"24#endif2526using namespace raid;27using json = nlohmann::json;2829namespace {30void usage() {31  std::fprintf(stderr,32    "raid %s — Research Architecture for Intraday Data (UQO WP 40)\n"33    "  raid devices                                   list backends/devices (JSON)\n"34    "  raid validate <bars.csv|.parquet> [--session regular|extended]   quality report per symbol (JSON)\n"35    "  raid estimate realized <bars> [--backend auto|cpu|metal] [--bpv-no-fs]   per-session realized measures\n"36    "  raid estimate garch <bars> [--model garch|gjr|egarch] [--dist gaussian|student_t] [--horizon H] [--returns daily|intraday]\n"37    "  raid estimate ols <csv y,x1,x2...> [--cov classical|hc0..hc3|hac|cluster] [--lags L]\n"38    "  raid estimate har <bars> [--horizon h] [--log] [--harq] [--window W --step S]   daily RV from 1m bars → HAR fit (+ rolling forecasts)\n"39    "  raid data ...                                  FinData access (Phase 2)\n"40    "  raid benchmark ...                             benchmark harness (Phase 3+)\n", RAID_VERSION);41}42std::string arg(const std::vector<std::string>& a, const std::string& key, const std::string& def = "") { for (usize i = 0; i + 1 < a.size(); ++i) if (a[i] == key) return a[i + 1]; return def; }43bool flag(const std::vector<std::string>& a, const std::string& key) { for (auto& s : a) if (s == key) return true; return false; }4445std::map<std::string, BarSeries> load_bars(const std::string& path) {46  if (path.size() > 4 && path.substr(path.size() - 4) == ".csv") return data::read_bars_csv(path);47#ifdef RAID_WITH_ARROW48  if (path.size() > 8 && path.substr(path.size() - 8) == ".parquet") return data::read_bars_parquet(path).series;49  if (path.size() > 6 && path.substr(path.size() - 6) == ".arrow") return data::read_bars_arrow_ipc(path).series;50#endif51  throw RaidError(ErrorCode::io, "unsupported input format (csv" 52#ifdef RAID_WITH_ARROW53  ", parquet, arrow"54#endif55  "): " + path);56}5758int cmd_devices() {59  json out = json::array(); for (auto& d : backend::list_devices()) out.push_back(d.to_json());60  json j = {{"devices", out}, {"host", host_info()}}; std::cout << j.dump(1) << "\n"; return 0;61}6263int cmd_validate(const std::vector<std::string>& a) {64  if (a.empty()) { usage(); return 2; }65  auto bars = load_bars(a[0]); MarketCalendar cal;66  const auto policy = arg(a, "--session", "regular") == "extended" ? SessionPolicy::extended : SessionPolicy::regular;67  json out = json::array();68  for (auto& [sym, b] : bars) { auto bb = b; auto st = bb.normalize(); auto q = bb.validate(cal, policy); q.duplicates = st.duplicates_removed; q.unsorted = st.reordered; out.push_back(q.to_json()); }69  std::cout << json({{"file", a[0]}, {"sha256", Sha256::of_file(a[0])}, {"reports", out}}).dump(1) << "\n"; return 0;70}7172int cmd_estimate(const std::vector<std::string>& a) {73  if (a.size() < 2) { usage(); return 2; }74  const std::string what = a[0], path = a[1];75  ExecutionPlan plan; plan.backend = backend_from_string(arg(a, "--backend", "auto"));76  if (what == "realized") {77    auto bars = load_bars(path); MarketCalendar cal; json out = json::object();78    est::RealizedOptions ro; ro.plan = plan; ro.bpv_finite_sample = !flag(a, "--bpv-no-fs");79    for (auto& [sym, b0] : bars) { auto b = b0; b.normalize(); auto reg = b.filter_session(cal, SessionPolicy::regular); auto ir = data::intraday_returns(reg); auto m = est::realized_measures(ir, ro);80      json rows = json::array(); for (usize k = 0; k < m.sessions.size(); ++k) rows.push_back({{"session", m.sessions[k].iso()}, {"n", m.n_returns[k]}, {"rv", m.rv[k]}, {"bpv", m.bpv[k]}, {"rsv_neg", m.rsv_neg[k]}, {"rsv_pos", m.rsv_pos[k]}, {"rq", m.rq[k]}, {"jump", m.jump[k]}, {"tripv", m.tripv[k]}, {"ret", m.daily_return[k]}});81      out[sym] = {{"measures", rows}, {"backend", std::string(to_string(m.stats.backend))}, {"precision", std::string(to_string(m.stats.precision))}, {"wall_seconds", m.stats.wall_seconds}, {"note", m.stats.note}, {"warnings", m.warnings}}; }82    std::cout << out.dump(1) << "\n"; return 0;83  }84  if (what == "garch") {85    auto bars = load_bars(path); MarketCalendar cal; json out = json::object();86    models::GarchFitOptions go; const std::string mdl = arg(a, "--model", "garch"); go.model = mdl == "gjr" ? models::GarchModel::gjr : (mdl == "egarch" ? models::GarchModel::egarch : models::GarchModel::garch);87    go.dist = arg(a, "--dist", "gaussian") == "student_t" ? models::GarchDist::student_t : models::GarchDist::gaussian; go.forecast_horizon = std::stoi(arg(a, "--horizon", "0")); go.plan = plan;88    const bool intraday = arg(a, "--returns", "daily") == "intraday";89    for (auto& [sym, b0] : bars) { auto b = b0; b.normalize(); auto reg = b.filter_session(cal, SessionPolicy::regular); auto ir = data::intraday_returns(reg);90      std::vector<f64> r; if (intraday) r = ir.r; else for (f64 v : ir.close_to_close) if (std::isfinite(v)) r.push_back(v);91      try { auto e = models::garch_fit(r, go); out[sym] = e.to_json(); } catch (const RaidError& ex) { out[sym] = {{"error", ex.what()}}; } }92    std::cout << out.dump(1) << "\n"; return 0;93  }94  if (what == "har") {95    auto bars = load_bars(path); MarketCalendar cal; json out = json::object(); est::HarSpec s; s.horizon = std::stoi(arg(a, "--horizon", "1")); s.log = flag(a, "--log"); s.harq = flag(a, "--harq");96    for (auto& [sym, b0] : bars) { auto b = b0; b.normalize(); auto reg = b.filter_session(cal, SessionPolicy::regular); auto ir = data::intraday_returns(reg); est::RealizedOptions ro; ro.plan = plan; auto m = est::realized_measures(ir, ro);97      try { auto e = est::har_fit(m.rv, s, m.rq); json j = e.to_json(); j["forecast_next"] = est::har_forecast(e, m.rv, s, m.rq); j["n_sessions"] = m.rv.size();98        if (!arg(a, "--window").empty()) { auto r = est::har_rolling(m.rv, s, static_cast<usize>(std::stoul(arg(a, "--window"))), static_cast<usize>(std::stoul(arg(a, "--step", "1"))), m.rq); auto l = est::forecast_loss(r.actual, r.forecast); j["rolling"] = {{"n_fits", r.n_fits}, {"mse", l.mse}, {"qlike", l.qlike}, {"seconds", r.seconds}}; }99        out[sym] = j; } catch (const RaidError& ex) { out[sym] = {{"error", ex.what()}}; } }100    std::cout << out.dump(1) << "\n"; return 0;101  }102  if (what == "ols") {103    std::ifstream f(path); RAID_REQUIRE(f.good(), io, "cannot open " + path); std::string line; std::getline(f, line);104    std::vector<std::string> names; { usize s = 0; for (usize i = 0; i <= line.size(); ++i) if (i == line.size() || line[i] == ',') { names.push_back(line.substr(s, i - s)); s = i + 1; } }105    std::vector<std::vector<f64>> rows; while (std::getline(f, line)) { if (line.empty()) continue; std::vector<f64> r; usize s = 0; for (usize i = 0; i <= line.size(); ++i) if (i == line.size() || line[i] == ',') { r.push_back(std::stod(line.substr(s, i - s))); s = i + 1; } rows.push_back(r); }106    const usize n = rows.size(), k = names.size() - 1; Eigen::MatrixXd X(n, k + 1); Eigen::VectorXd y(n);107    for (usize i = 0; i < n; ++i) { y[static_cast<Eigen::Index>(i)] = rows[i][0]; X(static_cast<Eigen::Index>(i), 0) = 1.0; for (usize j = 0; j < k; ++j) X(static_cast<Eigen::Index>(i), static_cast<Eigen::Index>(j + 1)) = rows[i][j + 1]; }108    est::OlsOptions oo; oo.cov.type = stats::covtype_from_string(arg(a, "--cov", "classical")); oo.cov.hac_lags = std::stoi(arg(a, "--lags", "-1")); oo.names = {"const"}; for (usize j = 1; j < names.size(); ++j) oo.names.push_back(names[j]);109    std::cout << est::ols(X, y, oo).estimate.to_json().dump(1) << "\n"; return 0;110  }111  usage(); return 2;112}113}  // namespace114115int main(int argc, char** argv) {116  std::vector<std::string> a(argv + 1, argv + argc);117  if (a.empty()) { usage(); return 2; }118  try {119    const std::string cmd = a[0]; a.erase(a.begin());120    if (cmd == "devices") return cmd_devices();121    if (cmd == "validate") return cmd_validate(a);122    if (cmd == "estimate") return cmd_estimate(a);123#ifdef RAID_WITH_FINDATA124    if (cmd == "data") return raid::findata::cli_main(a);125#endif126    if (cmd == "benchmark") { std::fprintf(stderr, "benchmark: use the bench_* executables (Phase 3+)\n"); return 2; }127    usage(); return 2;128  } catch (const RaidError& e) { std::fprintf(stderr, "raid error: %s\n", e.what()); return 1; }129  catch (const std::exception& e) { std::fprintf(stderr, "error: %s\n", e.what()); return 1; }130}131
Files · edf90b664f59d98f1489651599148df98a2fb1d1
Menu

Theme