Skip to content

Repository files navigation

qvac-finance-agent

Local-first financial intelligence agent. A multi-agent pipeline that pulls live Hyperliquid market data, reasons over it with a fully on-device LLM via @qvac/sdk, and grounds its output with local RAGzero cloud inference.

Built for the QVAC Hackathon I — Unleash Edge AI (General Purpose track). MIT licensed. Everything runs on the host machine.

▶ Demo video (2:31): https://youtu.be/7NrfnMkW6PM


Why this is edge AI

  • No cloud, no API keys for inference. Every token is generated locally through @qvac/sdk (llama.cpp under the hood). The only network calls are to Hyperliquid's free, public, no-auth market data endpoint.
  • Runs on a constrained laptop. Developed and benchmarked on a Surface Pro 7 (Intel i7-1065G7, 16 GB RAM, integrated Iris graphics, Windows 11) — well inside the ≤32 GB General Purpose track.
  • Evidence-first. Every inference call and data fetch is logged with timestamp, model name, token count, and tokens/sec to logs/run-<date>.jsonl for the hackathon evidence bundle.

Architecture

Hyperliquid public API  ──►  tools/hyperliquid.js  ──►  tools/market.js (tool calling)
                                                            │
   data/ (knowledge base) ──► agents/rag.js  ──────────────┤
                                                            ▼
                          agents/analyst.js  ──►  agents/signal.js
                          (factual summary)       (structured signal)
                                   └──── all inference via lib/qvac.js → @qvac/sdk ───┘
                                                            │
                                                   logs/run-*.jsonl (evidence)

(Above: the default pipeline mode. The orchestrator, scanner, and psy agents run as their own modes — see the table and CLI below.)

Agent Role
analyst Fetches live data for a coin, produces a factual market summary. Open-interest/price deltas come from a persisted prior snapshot (lib/state.js) — never invented.
rag On-device vector retrieval (EmbeddingGemma-300M → ragIngest/ragSearch) over the local data/ knowledge base, with a keyword fallback.
signal Emits a structured, hedged signal as GBNF-constrained JSON (responseFormat: json_schema) so the object is always valid.
orchestrator Tool-calling agent: the LLM picks Hyperliquid tools to answer free-form questions (see Tool calling below).
scanner Sweeps the whole perp universe, flags anomalies (extreme funding, big 24h moves, OI surges) with a deterministic score, and has the LLM summarize the watchlist.
psy Behavioral-risk / discipline reviewer running on MedGemma-4B (QVAC's medical model) — critiques a signal for FOMO, over-leverage, chasing. Demonstrates "right model for the job" + the Psy-model bonus.
journal On-device vector RAG over your private trade journal (journal/, gitignored) — feeds your own notes/rules into the signal & psy agents. Never leaves the device.
trader Turns a signal into a risk-sized order ticket and (opt-in) signs + places it on Hyperliquid testnet locally. Keys stay on-device; only the signed order is transmitted. See TRADING.md.

Requirements

  • Node.js ≥ 22.17 (QVAC requires ≥18; quickstart targets ≥22.17). npm ≥ 10.9.
  • ~5 GB free disk for model artifacts; 16 GB RAM is comfortable for ≤8B Q4 models.
  • Supported hosts: win32-x64, darwin-arm64/x64, linux-arm64/x64.

Windows note: use a real Node 22 (e.g. via nvm-windows: nvm install 22.17.0 && nvm use 22.17.0). nvm use needs an elevated shell to switch the global symlink; alternatively call the versioned binary directly. Native QVAC binaries ship prebuilt for win32-x64, so no C++ toolchain is needed.

Quickstart (reproducible)

git clone <this-repo> && cd qvac-finance-agent
npm install                 # pulls @qvac/sdk + native runtimes

# 1. Prove on-device inference works (downloads a ~0.8 GB model on first run):
npm run quickstart

# 2. Run the vertical slice — live BTC data -> local LLM commentary:
npm run slice               # or: node src/index.js --slice ETH

# 3. Run the full multi-agent pipeline (analyst -> vector-RAG -> signal):
npm start                   # or: node src/index.js SOL

# 4. Ask the tool-calling agent a free-form question:
node src/index.js --agent "What is the price and funding of ETH?"

# 5. Scan the whole market for anomalies (extreme funding / moves / OI surges):
node src/index.js --scan 6

# 6. Behavioral-risk review of a signal using MedGemma-4B (downloads ~2.6 GB once):
node src/index.js --psy ETH

# 7. Plan a risk-sized order from the signal (DRY-RUN — sends nothing):
node src/index.js --trade BTC
#    ...and place it on Hyperliquid TESTNET (opt-in, needs both flags + setup):
node src/index.js --trade BTC --execute --confirm   # see TRADING.md

First run downloads the model from the QVAC distributed registry; subsequent runs are offline-capable.

Install as a CLI

The package exposes a qvac-finance-agent binary (alias qvac-fin), so you can run it as a command from any directory instead of node src/index.js:

npm install -g .            # from the repo (or: npm link for development)

qvac-finance-agent --help
qvac-finance-agent ETH                         # full pipeline
qvac-finance-agent --slice SOL                 # vertical slice
qvac-finance-agent --scan 8                    # market anomaly scan
qvac-finance-agent --agent "funding on BTC?"   # tool-calling agent
qvac-finance-agent --psy ETH                   # MedGemma behavioral review
qvac-finance-agent --trade BTC                 # plan a risk-sized order (dry-run)
qvac-finance-agent --version

Data and logs resolve relative to the install location, so the command works from any working directory. The CLI runs on Node ≥ 22.17 (it uses whichever node is on your PATH); inference still runs fully on-device via @qvac/sdk, with models cached in ~/.qvac after the first download.

Tool calling

The orchestrator agent lets the local LLM choose which Hyperliquid tool to call. Native tool-call token emission was tested across LLAMA_TOOL_CALLING_1B, QWEN3_4B, and every toolDialect — sub-8B models on this SDK build / hardware did not reliably emit parseable tool-call frames. So the agent uses GBNF-constrained tool selection instead: the model outputs its decision as JSON constrained by a responseFormat: json_schema, which is deterministic even on a 1B model. Each step is {action:"call_tool",tool,arguments} or {action:"final",answer}; we execute the chosen tool against the live API, feed the result back, and loop. Tool specs live in src/tools/market.js.

Verified on-device (1B): --agent "price and funding of ETH"get_coin_snapshot({coin:"ETH"})"ETH ~$1573.9, funding ~7.95% annualized."

Models

Configure via the QVAC_MODEL env var. Accepts a FEATURED alias (src/lib/qvac.js) or any raw @qvac/sdk constant. Default: LLAMA_3_2_1B_INST_Q4_0.

Alias SDK constant Params Notes
LLAMA_1B LLAMA_3_2_1B_INST_Q4_0 1B Default; fastest, used for the slice.
LLAMA_TOOL_1B LLAMA_TOOL_CALLING_1B_INST_Q4_K 1B Tuned for tool calling (multi-agent).
QWEN3_4B QWEN3_4B_INST_Q4_K_M 4B Strong small reasoner (optional upgrade via QVAC_MODEL).
QWEN3_8B QWEN3_8B_INST_Q4_K_M 8B ~5 GB — practical ceiling on 16 GB RAM.
MEDGEMMA_4B MEDGEMMA_4B_IT_Q4_1 4B On-device medical reasoner (closest available to QVAC "Psy").
EMBED EMBEDDINGGEMMA_300M_Q4_0 0.3B Embeddings for on-device RAG.

Note on the "Psy" bonus: @qvac/sdk v0.12.2 does not export a MEDPSY constant — the available medical model is MedGemma-4B. If QVAC MedPsy is published to the distributed registry it can be loaded by name via the registry API; this is tracked as an open item.

On 16 GB RAM with integrated Iris graphics (no discrete GPU), ≤8B Q4 is the ceiling and inference is CPU-bound and slow — see Performance below.

Performance (measured on the dev machine)

Surface Pro 7 · i7-1065G7 (4c/8t) · 16 GB · Intel Iris Plus (integrated) · Win 11 · Node 22.17.

Stage Model Result
First load (cold, incl. ~0.8 GB download) LLAMA_1B ~113 s
Warm load (cached) LLAMA_1B ~5 s
Generation (warm) LLAMA_1B ~4.1 tok/s (116 tok / 28 s)
Generation (cold) LLAMA_1B ~1.2 tok/s
Generation MEDGEMMA_4B ~1.7 tok/s (340 tok / 203 s)
Embedding query EMBEDDINGGEMMA_300M ~58 ms

Inference runs on CPU (no GPU offload observed), so throughput is low. Practical implications: keep prompts/outputs short, prefer the 1B for interactive modes and the 4B for the psy review, and treat 8B as "works but slow." All timings are logged to logs/run-*.jsonl.

Context window: the Llama-3.2-1B build here exposes a 1024-token window, so the agents cap what they feed the model — RAG context is truncated (MAX_RAG_CHARS in signal.js) and tool results are capped in the orchestrator. This is a deliberate edge-AI constraint, not a bug.

Data source — Hyperliquid (free, no auth)

POST https://api.hyperliquid.xyz/info with a JSON body. We use metaAndAssetCtxs (mid/mark/oracle price, funding, open interest, 24h volume), l2Book, and candleSnapshot. No API key, no rate-limit tier required.

Project layout

src/
  index.js               entry/dispatch: --slice | --agent | --scan | --psy | --trade | default pipeline
  agents/
    analyst.js           factual market summary (honest cross-run deltas)
    signal.js            schema-constrained JSON trade signal
    rag.js               on-device vector retrieval (+ keyword fallback)
    orchestrator.js      tool-calling agent (GBNF tool selection)
    scanner.js           market-wide anomaly watchlist
    psy.js               MedGemma-4B behavioral-risk review
    journal.js           on-device RAG over the private trade journal
    trader.js            risk sizing, journal-rule enforcement, execution guards
  tools/{market,hyperliquid}.js   tool specs + Hyperliquid client (retry)
  tools/exchange.js      local order signing + Hyperliquid testnet placement
  lib/{qvac,logger,state}.js      SDK wrapper + evidence log + snapshot store
scripts/
  quickstart.js          QVAC inference smoke test
data/                    local RAG knowledge base (4 docs)
journal/                 private trade journal (gitignored; README + EXAMPLE committed)
logs/                    JSONL evidence logs (hardware + inference timings)
.env.example             runtime env vars (model + testnet trading key)
TRADING.md               trading agent: safety model + testnet setup

Disclaimer

Educational demonstration of on-device AI. Not financial advice. Analysis modes read public market data only. The optional trading agent is testnet-only by default, dry-run unless you pass both --execute and --confirm, and gated by the safety model in TRADING.md. Use at your own risk.

License

MIT — see LICENSE.

About

8-agent crypto intelligence + testnet trading — 100% on-device inference via @qvac/sdk. Live Hyperliquid data · local RAG · MedGemma psy review · signed orders. No cloud.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages