SPB Git

spb/wp40_uqo

Public MIT
7.6 KB · 121 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#ifdef RAID_WITH_FINDATA22#include "raid/data/findata.hpp"23#endif2425using namespace raid;26using json = nlohmann::json;2728namespace {29void usage() {30  std::fprintf(stderr,31    "raid %s — Research Architecture for Intraday Data (UQO WP 40)\n"32    "  raid devices                                   list backends/devices (JSON)\n"33    "  raid validate <bars.csv|.parquet> [--session regular|extended]   quality report per symbol (JSON)\n"34    "  raid estimate realized <bars> [--backend auto|cpu|metal] [--bpv-no-fs]   per-session realized measures\n"35    "  raid estimate garch <bars> [--model garch|gjr|egarch] [--dist gaussian|student_t] [--horizon H] [--returns daily|intraday]\n"36    "  raid estimate ols <csv y,x1,x2...> [--cov classical|hc0..hc3|hac|cluster] [--lags L]\n"37    "  raid data ...                                  FinData access (Phase 2)\n"38    "  raid benchmark ...                             benchmark harness (Phase 3+)\n", RAID_VERSION);39}40std::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; }41bool flag(const std::vector<std::string>& a, const std::string& key) { for (auto& s : a) if (s == key) return true; return false; }4243std::map<std::string, BarSeries> load_bars(const std::string& path) {44  if (path.size() > 4 && path.substr(path.size() - 4) == ".csv") return data::read_bars_csv(path);45#ifdef RAID_WITH_ARROW46  if (path.size() > 8 && path.substr(path.size() - 8) == ".parquet") return data::read_bars_parquet(path).series;47  if (path.size() > 6 && path.substr(path.size() - 6) == ".arrow") return data::read_bars_arrow_ipc(path).series;48#endif49  throw RaidError(ErrorCode::io, "unsupported input format (csv" 50#ifdef RAID_WITH_ARROW51  ", parquet, arrow"52#endif53  "): " + path);54}5556int cmd_devices() {57  json out = json::array(); for (auto& d : backend::list_devices()) out.push_back(d.to_json());58  json j = {{"devices", out}, {"host", host_info()}}; std::cout << j.dump(1) << "\n"; return 0;59}6061int cmd_validate(const std::vector<std::string>& a) {62  if (a.empty()) { usage(); return 2; }63  auto bars = load_bars(a[0]); MarketCalendar cal;64  const auto policy = arg(a, "--session", "regular") == "extended" ? SessionPolicy::extended : SessionPolicy::regular;65  json out = json::array();66  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()); }67  std::cout << json({{"file", a[0]}, {"sha256", Sha256::of_file(a[0])}, {"reports", out}}).dump(1) << "\n"; return 0;68}6970int cmd_estimate(const std::vector<std::string>& a) {71  if (a.size() < 2) { usage(); return 2; }72  const std::string what = a[0], path = a[1];73  ExecutionPlan plan; plan.backend = backend_from_string(arg(a, "--backend", "auto"));74  if (what == "realized") {75    auto bars = load_bars(path); MarketCalendar cal; json out = json::object();76    est::RealizedOptions ro; ro.plan = plan; ro.bpv_finite_sample = !flag(a, "--bpv-no-fs");77    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);78      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]}});79      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}}; }80    std::cout << out.dump(1) << "\n"; return 0;81  }82  if (what == "garch") {83    auto bars = load_bars(path); MarketCalendar cal; json out = json::object();84    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);85    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;86    const bool intraday = arg(a, "--returns", "daily") == "intraday";87    for (auto& [sym, b0] : bars) { auto b = b0; b.normalize(); auto reg = b.filter_session(cal, SessionPolicy::regular); auto ir = data::intraday_returns(reg);88      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);89      try { auto e = models::garch_fit(r, go); out[sym] = e.to_json(); } catch (const RaidError& ex) { out[sym] = {{"error", ex.what()}}; } }90    std::cout << out.dump(1) << "\n"; return 0;91  }92  if (what == "ols") {93    std::ifstream f(path); RAID_REQUIRE(f.good(), io, "cannot open " + path); std::string line; std::getline(f, line);94    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; } }95    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); }96    const usize n = rows.size(), k = names.size() - 1; Eigen::MatrixXd X(n, k + 1); Eigen::VectorXd y(n);97    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]; }98    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]);99    std::cout << est::ols(X, y, oo).estimate.to_json().dump(1) << "\n"; return 0;100  }101  usage(); return 2;102}103}  // namespace104105int main(int argc, char** argv) {106  std::vector<std::string> a(argv + 1, argv + argc);107  if (a.empty()) { usage(); return 2; }108  try {109    const std::string cmd = a[0]; a.erase(a.begin());110    if (cmd == "devices") return cmd_devices();111    if (cmd == "validate") return cmd_validate(a);112    if (cmd == "estimate") return cmd_estimate(a);113#ifdef RAID_WITH_FINDATA114    if (cmd == "data") return raid::findata::cli_main(a);115#endif116    if (cmd == "benchmark") { std::fprintf(stderr, "benchmark: use the bench_* executables (Phase 3+)\n"); return 2; }117    usage(); return 2;118  } catch (const RaidError& e) { std::fprintf(stderr, "raid error: %s\n", e.what()); return 1; }119  catch (const std::exception& e) { std::fprintf(stderr, "error: %s\n", e.what()); return 1; }120}121
Files · 516afa5dba80de9542c7fd89bf2a5e143516ff00
Menu

Theme