Methodology
How Argus reaches — and proves — a decision
Everything below is implemented in the open-source code. Where this page and the code disagree, the code wins and this page is a bug.
Step 1
Market snapshot
Each run starts by capturing one snapshot of the asset. Spot price comes from CoinGecko (CryptoCompare as fallback). Around 210 days of daily closes and volumes are used to compute RSI-14 (Wilder), MACD(12, 26, 9), EMA-20/50/200, 7/30/90-day returns, annualized 30-day realized volatility, drawdown from the 90-day high and a 7-vs-30-day volume trend. The Crypto Fear & Greed index provides sentiment.
If a data class is unavailable the snapshot records why, and analysts that require it abstain instead of guessing. Only spot price is mandatory. Snapshots are cached for 60 seconds, so two runs a few seconds apart see identical data.
Step 2
The analysts
Each analyst is a versioned prompt plus a declared set of data inputs. An analyst only receives the snapshot keys it declares, must respond with schema-valid JSON (vote, confidence 0–100, reasoning, cited data points), and is retried once with the validation error if it doesn't. Invalid output is never patched into a vote — it is recorded as a failure, along with the raw provider response.
| Analyst | Framework | Inputs |
|---|---|---|
| Value Hunter | Margin of safety · relative valuation | Market cap, 90-day drawdown, long-horizon returns |
| Momentum Trader | RSI · MACD · EMA trend · volume confirmation | Daily technicals computed from ~210 days of closes |
| Macro Analyst | Risk appetite · long-cycle regime | Fear & Greed index, 90-day trend, EMA-200 positioning |
| On-chain Sleuth | MVRV · SOPR · exchange netflows | On-chain metrics (abstains when no provider is connected) |
| Risk Guardian | Volatility-adjusted conviction · drawdown control | Realized volatility, drawdown, RSI extremes, sentiment |
Prompt texts are public at /api/prompts?ref=<agent>/<version>. Prompts are never edited in place; changes ship as a new version.
Step 3
Consensus
Votes are weighted by each analyst's confidence. For each direction d ∈ {BUY, SELL, HOLD}:
W_d = Σ confidence_i over analysts i that voted d
recommendation = argmax_d W_d
confidence = W_recommendation / Σ_d W_d × 100
split = (W_first − W_second) < 10% of Σ_d W_dA run needs at least 3 valid votes (quorum) to be sealable. Runs where an analyst failed are labelled degraded; abstentions due to missing data are not.
Step 4
Hashes & sealing
All hashes are SHA-256 over canonical JSON (object keys sorted recursively, no whitespace), so anyone in any language gets the same bytes.
dataSnapshotHash = sha256(canonical(snapshot.data))
promptHash_i = sha256(prompt file text, utf-8)
promptVersionHash = sha256(canonical({ v: 1, prompts: [{ agentId, promptVersion, promptHash }] sorted by agentId }))
reasoningHash = sha256(canonical({ v: 1, snapshotHash: dataSnapshotHash,
votes: [{ agentId, vote, confidence, reasoning, dataPointsCited }] sorted by agentId }))Sealing calls recordDecision on the registry contract, which emits DecisionRecorded(asset, decision, confidenceBps, dataSnapshotHash, promptVersionHash, timestamp, sender). The contract stores nothing and holds no funds. You can seal with your own wallet (you become the on-chain signer) or via the Argus relayer. Wallet-signed transactions are fetched from the chain and checked field-by-field before Argus marks them sealed.
Trust
Verify a decision yourself
Every decision page has a Verify independently button that runs these checks in your browser, reading the chain directly from a public RPC:
- Recompute
dataSnapshotHashfrom the published canonical snapshot bytes (stored verbatim, so no number is ever re-serialized). - Download each prompt version and check it hashes to the vote's
promptHash. - Recompute
promptVersionHashandreasoningHashfrom the votes. - Fetch the transaction receipt and decode the
DecisionRecordedevent.
To do it without our UI at all:
curl -s https://<argus-host>/api/decisions/<id> > decision.json
node -e '
const d = require("./decision.json"), c = require("crypto");
const canon = (v) => v === null || typeof v !== "object" ? v
: Array.isArray(v) ? v.map(canon)
: Object.fromEntries(Object.keys(v).sort().map((k) => [k, canon(v[k])]));
const bytes = d.snapshot.canonical; // the exact bytes that were hashed
const isCanonical = JSON.stringify(canon(JSON.parse(bytes))) === bytes;
const h = c.createHash("sha256").update(bytes).digest("hex");
console.log(isCanonical && h === d.dataSnapshotHash ? "snapshot OK" : "MISMATCH");'Track record
Outcome scoring
Sealed decisions are scored automatically once their horizon has passed (7 days by default) by comparing the asset's price at decision time with its price at the horizon. A move beyond ±2% counts as directional:
BUY is correct when return > +2%
SELL is correct when return < −2%
HOLD is correct when |return| ≤ 2%Each analyst's vote in a scored decision is graded the same way. The leaderboard reports hit rate and a confidence-weighted Brier score (lower is better), so an analyst that is confidently wrong is penalized more than one that hedged.
Honesty
Limitations
- Analysts are large language models. They can be wrong, inconsistent across runs and confidently mistaken.
- The On-chain Sleuth abstains until an on-chain metrics provider (MVRV, SOPR, netflows) is connected.
- Market data comes from free-tier public APIs and may be delayed or briefly unavailable.
- Sealing currently happens on Monad testnet.
- Nothing here is financial advice. See the risk disclaimer.