Full reference for the Quark signal feed. Endpoint list, response schemas, rate limits, and — most importantly — how to translate the regime score / crash probability / defensive blend into trades in your own portfolio.
| Base URL | https://api.quarkresearch.cc |
|---|---|
| Auth header | x-api-key: qk_... |
| Auth query | ?api_key=qk_... (for cURL convenience; prefer header) |
| Rate limit | 60 requests / minute / key |
| Content-Type | application/json (CSV endpoint returns text/csv) |
| Signal refresh | Daily post-close; intraday if regime flips or crash-prob crosses threshold |
| TLS | Required. HTTP requests are rejected. |
GET/api/signals/current
Top-level regime + tail risk + allocation summary. The most common call.
GET/api/signals/current/full
Unabridged signal — adds risk_params (τ_decoh, quantum_halflife, grassmann_distance) and rotation state. Use this when you want to replicate the full decision layer.
GET/api/signals/history?days=N
Historical signal observations, JSON. Max days=730.
GET/api/signals/history.csv?days=N
Same data, CSV. Columns: timestamp_utc, regime, regime_score, crash_prob_1d, crash_prob_5d, crash_prob_21d, equity_pct, defensive_pct, snr. Stable — safe to pipe into pandas/R.
GET/api/signals/usage
Your account info: tier, key last-4, webhook URL, rate limit, list of endpoints available to your tier.
GET/api/alpha/attribution
Per-signal decomposition of the library's α over the attribution window. 18 tracked signals; returns contribution in dollars, percent, and normalized share.
POST/api/webhook/register
Body: {"url": "https://your-server/webhook"}. One webhook per key. Replaces any existing registration.
POST/api/webhook/test
Fires a synthetic payload to your registered URL. Useful for verifying your receiver signature check before a real regime change lands.
POST/api/webhook/unregister
Removes webhook registration.
POST/api/billing/portal
Returns Stripe customer portal URL for self-service subscription management.
Every numeric field is a float in [0, 1] unless otherwise noted. All
fields carry a fallback: bool flag — when true,
the section is showing a classical/default estimate because the quantum
pipeline failed to produce a non-fallback value this cycle.
regime section| Field | Type | Range | Meaning |
|---|---|---|---|
regime_score | float | 0.0 – 1.0 | Continuous. 0 = RISK_ON, 0.5 = NEUTRAL, 1.0 = CRISIS. |
regime_label | string | — | Discrete label: RISK_ON, NEUTRAL, RISK_OFF, CRISIS. |
landscape_position | float | 0.0 – 1.0 | Where in the potential landscape the market sits. 0 = normal attractor, 1 = crisis attractor. |
barrier_depletion | float | 0.0 – 1.0 | Fraction of regime-defense barrier already consumed. Values above 0.7 mean a regime transition is imminent. |
decoherence_stress | float | 0.0 – 1.0 | Factor-correlation instability. 0 = factor structure stable; 1 = correlations reorganizing. |
tda_stress | float | 0.0 – 1.0 | Topological crash signature from persistent homology of correlation trajectories. |
past_saddle | bool | — | true when the system has already crossed the saddle point between regimes — a transition is locked in. |
crash_prob_1d | float | 0.0 – 1.0 | 1-day crash probability from this section (duplicate of tail_risk.crash_prob_1d). |
tail_risk section| Field | Type | Range | Meaning |
|---|---|---|---|
crash_prob_1d | float | 0.0 – 1.0 | Probability of a ≥3σ drawdown in the next trading day. |
crash_prob_5d | float | 0.0 – 1.0 | Same, 5-day horizon. |
crash_prob_21d | float | 0.0 – 1.0 | Same, 21-day (~1 month) horizon. The workhorse tail-risk number. |
instanton_var_10d | float | 0.0+ | Non-perturbative 10-day VaR as a decimal fraction of portfolio NAV (e.g. 0.0695 = 6.95%). |
instanton_action | float | 0.0+ | Barrier action integral — the "height" of the crash barrier. Higher = further from a crash. |
signal_quality section| Field | Type | Range | Meaning |
|---|---|---|---|
avg_snr | float | 0.0+ | Mean |trend velocity| / realized vol across the universe. High = trends are clean; low = noise. |
momentum_weight | float | 0.0 – 1.0 | Recommended weight on momentum factor given current SNR. |
quality_weight | float | 0.0 – 1.0 | Recommended weight on quality factor. |
volume_weight | float | 0.0 – 1.0 | Recommended weight on volume/liquidity factor. |
cyclicality_weight | float | 0.0 – 1.0 | Recommended weight on cyclicality factor. (Weights sum to 1.0.) |
n_assets | int | — | Number of assets with a valid SNR this cycle. |
allocation section| Field | Type | Range | Meaning |
|---|---|---|---|
per_asset_caps | {ticker: float} | 0.0 – 1.0 | Max weight we would hold in each ticker given the current landscape. Use as an upper clamp on your own weights. |
uniform_cap | float | 0.0 – 1.0 | Fallback per-asset cap when a ticker isn't in per_asset_caps. |
defensive_blend | float | 0.0 – 1.0 | Suggested shift toward defensive posture. 0 = no shift (all-equity), 1 = fully defensive (bonds / gold / cash). |
barrier_normalized | float | 0.0 – 1.0 | Barrier height / full action. 1 = fresh barrier, 0 = depleted. |
risk_params section (full endpoint only)| Field | Type | Range | Meaning |
|---|---|---|---|
quantum_halflife | float | days | How fast your covariance/signal estimates should adapt. Short = fast adaptation needed; long = regime stable. |
tau_decoh | float | days | Decoherence timescale — days until factor structure is expected to shift. |
grassmann_distance | float | 0.0 – π/2 | Angular distance between today's principal subspace and τ days ago. Large = factors rotating. |
quantum_shrinkage_boost | float | ≥ 1.0 | Covariance shrinkage multiplier recommended given Grassmannian distance. |
rotation section (full endpoint only)| Field | Type | Meaning |
|---|---|---|
grassmannian_distance | float | Factor-rotation magnitude. Same number as in risk_params. |
should_invalidate_cache | bool | true when cached signals / weights should be recomputed — eigenspace has rotated enough to invalidate them. |
force_short_halflife | bool | true when you should temporarily halve your signal smoothing window. |
fund_summary section| Field | Type | Meaning |
|---|---|---|
return_pct | float | Our live ensemble portfolio's cumulative return (%), for benchmarking. |
regime | string | Regime label we're currently trading under. |
health | string | GREEN / AMBER / RED — operational health of the live system. |
The signal is deliberately decoupled from any specific trade list — it's a set of continuous knobs you translate into your own allocation logic. Below are the three patterns we see licensees use successfully. Pick one that matches your existing workflow.
Simplest. You already have a strategic allocation (e.g. 60/40). Use defensive_blend to scale up/down your equity weight when the signal says conditions are deteriorating.
target_equity_pct = base_equity_pct × (1 − signal.allocation.defensive_blend) target_bond_pct = 1 − target_equity_pct # Example: # base 60/40, defensive_blend = 0.25 → # target_equity = 0.60 × 0.75 = 45% # target_bond = 55%
defensive_blend exceeds 0.10, or when rotation.should_invalidate_cache is true. Prevents thrash.For strategies that size positions as Kelly fractions or vol-targeted. Scale each position's size by the complement of the 21-day crash probability, so sizes shrink as crash risk rises.
crash_21 = signal.tail_risk.crash_prob_21d
sizing_multiplier = 1 − min(2 × crash_21, 0.80) # cap de-risking at 80%
for asset in portfolio:
target_size[asset] = base_size[asset] × sizing_multiplier
The 2× factor is a convention — we use it internally. It means a 21d crash probability of 0.40 drives sizing to 20% of baseline; anything higher clamps at 20%.
For licensees running their own quant book. Use the /full endpoint and consume the per-asset caps, factor weights, and Grassmannian state directly.
from scipy.optimize import minimize
def step(signal):
caps = signal.allocation.per_asset_caps # ticker → max weight
# Halflife → covariance EWMA decay
lam = 0.5 ** (1 / signal.risk_params.quantum_halflife)
cov = ewma_covariance(returns, lam) × signal.risk_params.quantum_shrinkage_boost
# Factor tilt from Nelson weights
factor_tilt = {
'momentum': signal.signal_quality.momentum_weight,
'quality': signal.signal_quality.quality_weight,
'volume': signal.signal_quality.volume_weight,
'cyclicality': signal.signal_quality.cyclicality_weight,
}
# Solve mean-variance with caps as upper bound on each w_i
weights = mean_variance_with_caps(
expected_returns=alpha_from_factors(factor_tilt),
covariance=cov,
upper_bounds=caps,
defensive_blend=signal.allocation.defensive_blend,
)
return weights
# Only re-solve on a regime change or rotation flag
if signal.rotation.should_invalidate_cache or regime_changed:
weights = step(signal)
| Field | Heuristic |
|---|---|
regime_score | Blend your risk-on / risk-off target allocation with this as the mixing weight. Score 0.0 = full risk-on book; 1.0 = full crisis book. |
crash_prob_21d > 0.15 | Hedge threshold. Start buying puts or reducing beta. Our own system buys hedges when this crosses 0.15 upward. |
barrier_depletion > 0.70 | Regime transition imminent. Expect the regime label to flip within days. Do not add risk. |
past_saddle == true | Transition is already locked in. Stop trying to fade the move. |
avg_snr < 0.10 | Market is in chop. Reduce turnover, widen rebalance bands. |
avg_snr > 0.30 | Trends are clean. Lengthen holding periods; don't over-trade. |
grassmann_distance > 0.30 | Factors are rotating. Invalidate any cached factor-based signals and recompute. |
defensive_blend == 1.0 | System is recommending a fully defensive posture. Match your policy — typically bonds + gold + cash. |
tda_stress > 0.50 | Correlation topology is stressed — diversification is breaking. Consider dollar-neutral pairs instead of long-only. |
fallback == true on any section | Treat that section as a classical fallback; don't stake conviction on it that cycle. |
import requests, json
KEY = 'qk_live_...'
BASE = 'https://api.quarkresearch.cc'
def daily_allocation(base_equity=0.60):
sig = requests.get(f'{BASE}/api/signals/current',
headers={'x-api-key': KEY}, timeout=10).json()
defensive = sig['allocation']['defensive_blend']
crash_21 = sig['tail_risk']['crash_prob_21d']
eq_pct = base_equity * (1 - defensive)
# Extra de-risk if crash probability elevated
if crash_21 > 0.15:
eq_pct *= 0.75
if crash_21 > 0.30:
eq_pct *= 0.50
bond_pct = 1 - eq_pct
return {'equity': eq_pct, 'bonds': bond_pct, 'signal': sig}
alloc = daily_allocation()
print(f"Target equity: {alloc['equity']:.1%}, bonds: {alloc['bonds']:.1%}")
# Register webhook (one-time)
curl -X POST -H "x-api-key: $KEY" \
-H "content-type: application/json" \
-d '{"url":"https://script.google.com/macros/s/YOUR_DEPLOY/exec"}' \
https://api.quarkresearch.cc/api/webhook/register
# Test delivery
curl -X POST -H "x-api-key: $KEY" \
https://api.quarkresearch.cc/api/webhook/test
Your Apps Script receives the same JSON as /api/signals/current. Write it into a sheet, pivot against your broker's positions, done.
def momentum_sleeve_sizing(base_gross_exposure=1.50):
sig = requests.get(f'{BASE}/api/signals/current',
headers={'x-api-key': KEY}).json()
# Sizing multiplier from crash probability
crash_21 = sig['tail_risk']['crash_prob_21d']
mult = 1 - min(2 * crash_21, 0.80)
# Adjust momentum weight based on SNR
mom_w = sig['signal_quality']['momentum_weight']
target_gross = base_gross_exposure * mult * (mom_w / 0.25) # 0.25 = long-run avg
return target_gross
Register a URL to receive push notifications when the regime changes, crash probability crosses 15%, or rotation.should_invalidate_cache fires.
Identical to /api/signals/current response, with one extra field at the top:
{
"event": "regime_change" | "crash_threshold_crossed" | "rotation_invalidate" | "test",
"regime": {...},
"tail_risk": {...},
...
}
Every webhook request carries an X-Quark-Signature header with an HMAC-SHA256 of the raw body, keyed on your API key. Verify in your receiver:
import hmac, hashlib
def verify(raw_body: bytes, signature: str, api_key: str) -> bool:
expected = hmac.new(
api_key.encode('utf-8'),
raw_body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, signature)
Webhooks that return a non-2xx status or time out after 5 seconds will be retried with exponential backoff: 30s, 2m, 10m, 1h, 6h, 24h. After that the delivery is dropped; the signal itself is still available via GET on /api/signals/current.
| Code | Meaning | What to do |
|---|---|---|
401 | Missing or invalid API key | Check header name is exactly x-api-key. Key starts with qk_. |
403 | Tier doesn't include this endpoint | Upgrade, or check endpoint-available list at /api/signals/usage. |
404 | Unknown endpoint | Confirm base URL is api.quarkresearch.cc, not quarkresearch.cc. |
429 | Rate limit exceeded | Back off; default limit is 60 req/min/key. Retry after Retry-After seconds. |
500 | Server error on our side | Retry with exponential backoff. If persistent, email hello@quarkresearch.cc. |
503 | Signal pipeline temporarily down | Retry after 60s. Fall back to previous cached signal. |
fallback: true semanticsWhen any section returns fallback: true, that section's values are from a classical/default estimator rather than the quantum pipeline. Two options:
| Date | Change |
|---|---|
| 2026-04-20 | Added /api/signals/current/full; added test-ping button on dashboard; signal log dedupe (no more duplicate CSV rows). |
| 2026-04-19 | Dashboard UI redesigned; tier labels rendered as "Automated Plus" instead of raw IDs; Manage button wired to Stripe portal. |
| 2026-04-18 | Alpha attribution endpoint live (/api/alpha/attribution). |
| 2026-04-15 | Endpoints moved behind api.quarkresearch.cc Cloudflare tunnel. |