This is the exact math – every indicator, every score band, every threshold and weight, taken directly from the scoring engine. If you want the plain-language version instead, see the FAQ. This page exists so nothing here has to be taken on faith: you can check any reading on the homepage against the rule that produced it.
Every run (every 4 hours) does the same five steps, for BTC and then $DOG:
BTC has no on-chain data source available (see FAQ for why), so its weight is redistributed across the other four categories:
$DOG gets a fifth category, shaving weight off the rest to make room:
These weights are static constants in the scoring engine – they don't drift or self-tune. If a category has no usable data at all in a given run (every indicator inside it failed), that category is dropped from the weighted sum entirely and the remaining weights implicitly carry more of the composite for that one run – this is the coverage mechanism, also used in the confidence score below.
Distance of current price from the 200-day simple moving average, as a percentage: dist = (price − SMA200) / SMA200.
| Condition | Score |
|---|---|
| dist > 25% | +2 |
| dist > 5% | +1 |
| −5% ≤ dist ≤ 5% | 0 (hugging the mean, no edge) |
| dist < −5% | −1 |
| dist < −25% | −2 |
Requires at least 210 days of daily history to compute at all; otherwise the whole Trend block reports as a data limitation.
Base score: +1 for a golden cross (50-day SMA above 200-day), −1 for a death cross (below).
Freshness multiplier: if the cross happened ≤30 days ago, the score is doubled to ±2 – a cross that just happened carries more information than one that happened months ago and has already been priced in.
Rate of change of the weekly 21-period EMA over the last two weeks, expressed as a per-week percentage: slope = (EMA[t] − EMA[t−2]) / EMA[t−2] / 2.
| Condition | Score |
|---|---|
| slope > 2%/wk | +2 |
| slope > 0.5%/wk | +1 |
| slope < −0.5%/wk | −1 |
| slope < −2%/wk | −2 |
Needs at least 21 full weeks of history; otherwise reports as a data limitation rather than a guess.
| Weekly RSI | Score | Reasoning |
|---|---|---|
| ≥ 72 | −2 | Historically overheated |
| 55 – 72 | +1 | Bullish zone, not yet overheated |
| 42 – 55 | 0 | Mid-range, no swing edge |
| 28 – 42 | −1 | Weak zone |
| ≤ 28 | +2 | Washed out – favors accumulation |
Note this is not simple overbought/oversold: the 55–72 band scores positive (bullish continuation), and only ≥72 flips to contrarian negative. This reflects that momentum can stay strong for a while in a genuine trend before it becomes an overextension worth fading.
Unlike the weekly read, daily RSI only scores at the extremes, since day-to-day noise isn't reliable on a swing-trading timeframe: ≥80 → −1, ≤22 → +1, otherwise 0.
Scored on the sign of the histogram and whether it's expanding or contracting versus the previous reading:
| Histogram | Direction | Score |
|---|---|---|
| Positive | Rising | +1 |
| Positive | Falling | 0 |
| Negative | Falling | −1 |
| Negative | Rising | 0 |
| Funding rate | Score | Reasoning |
|---|---|---|
| > 0.03% | −2 | Longs heavily crowded, contrarian bearish |
| > 0.012% | −1 | Long side paying up |
| −0.02% to 0.012% | 0 | Normal band, no crowding |
| < −0.02% | +1 | Shorts crowded, contrarian bullish |
Compares 7-day open-interest change against 7-day price change – the goal is telling new demand apart from pure leverage:
| OI change | Price change (7d) | Score | Reasoning |
|---|---|---|---|
| > +3% | > +2% | +1 | Rising OI with rising price – real demand |
| > +5% | |change| < 2% | −1 | Leverage building without price follow-through |
| < −5% | > +2% | −1 | Price up on falling OI – weak short-covering rally |
Since no exchange publishes a ready-made OI history for the $DOG contract, this history is self-tracked from periodic Kraken snapshots stored in Cloudflare KV – it takes ~7 days after first deploy to fully populate, and shows as a data limitation until then.
> 2.5 → −1 (retail heavily long-tilted, contrarian caution) · < 0.7 → +1 (retail net short, contrarian support) · otherwise 0.
Contrarian, graded in two tiers. The ±1 bands anchor to alternative.me's own published "Extreme" labels (≥75 greed, ≤25 fear); the ±2 tail is reserved for readings the index only reaches a handful of times a year:
| Fear & Greed | Score | Reasoning |
|---|---|---|
| ≥ 90 | −2 | Deep Extreme Greed – rare distribution-zone reading |
| 78 – 89 | −1 | Extreme Greed, contrarian caution |
| 23 – 77 | 0 | No contrarian edge |
| 11 – 22 | +1 | Extreme Fear, contrarian support |
| ≤ 10 | +2 | Deep Extreme Fear – rare accumulation-zone reading |
The extreme-tier cutoffs (90 / 10) are a judgment call – chosen as "meaningfully deeper into the extreme than the standard label," calibrated to where the index actually spends its time, rather than round numbers that would fire too rarely to matter.
Two numbers per keyword: the current index level (0–100 scale) and percent vs. the 90-day average.
| Condition | Score | Reasoning |
|---|---|---|
| index ≥ 85 | −1 | Search interest near peak – retail euphoria, contrarian |
| vs-avg > +15% and index < 70 | +1 | Rising from a modest base – early interest, not euphoria |
| vs-avg < −15% | −1 if "buy-intent" query, else 0 | Only queries tagged buy-intent score fading interest as bearish; generic terms don't |
$DOG tracks the keyword "DOG bitcoin" (disambiguates the token from the animal); BTC tracks "bitcoin". Google's official Trends API remains limited alpha as of mid-2026, so this runs through Apify's scraper Actor on a ~24h refresh cycle rather than live per-run – see the FAQ for why that's an acceptable tradeoff at swing-trade timeframes.
Recent posts are pulled via GetXAPI and classified with a keyword lexicon – deliberately simple and auditable rather than a black-box model, so every score is traceable to the words that produced it. Two hard rules in the classifier, both added after a real false-positive:
Net ratio is computed as (bull − bear) / (bull + bear) among posts that expressed any direction at all:
| Condition | Score |
|---|---|
| Fewer than 5 directional posts in the sample | 0 – too few to score, shown not counted |
| Net ratio ≥ 50% bullish | −1 (euphoric, contrarian) |
| Net ratio > 15% bullish | +1 |
| −15% to +15% | 0 – balanced chatter |
| Net ratio > 15% bearish | −1 |
| Net ratio ≥ 50% bearish | +1 (capitulation, contrarian) |
CoinMarketCap shows a bullish/bearish community vote on each coin's page. We read it (without casting a vote) and track it, but score it differently from the other rows, for a specific reason: these are lifetime-cumulative tallies, not a fresh daily reading. $DOG sits around 91% bullish across 300k+ votes accumulated over its whole existence – nearly every coin skews permanently bullish because the people who vote are holders. So the absolute level is close to meaningless as a signal; a fixed "euphoria" cutoff would just mark the coin contrarian-bearish forever.
Instead, we score the 7-day momentum of the bullish share – how the crowd's conviction is changing, not where it sits. Since CMC exposes only a live cumulative number and no history, we build our own series in KV (one snapshot per run), the same way we do for futures open interest and holder count. Until ~7 days of snapshots exist, the row shows the current level for context but is not counted:
| 7-day change in bullish share | Score | Reasoning |
|---|---|---|
| ≥ +1.5 percentage points | −1 | Crowd turning more euphoric – contrarian caution |
| −1.5 to +1.5 pp | 0 | No directional shift |
| ≤ −1.5 pp | +1 | Crowd cooling – contrarian support |
This uses CMC's undocumented internal endpoint (the same call their own site makes). Being undocumented, it can change or start blocking without notice – the same fragility as our Google Trends source – so it degrades to a labeled "data limitation" row the moment it breaks, never a fabricated reading. The ±1.5pp threshold is a judgment call and may be recalibrated once real movement data accumulates.
Market value vs. realized value – roughly, current price divided by the aggregate cost basis of all holders. Same contrarian-at-extremes logic as Fear & Greed:
| MVRV | Score | Reasoning |
|---|---|---|
| < 0.4 | +2 | Deeply below fair value – strong accumulation zone historically |
| 0.4 – 0.8 | +1 | Below aggregate cost basis |
| 0.8 – 2.0 | 0 | Near fair value |
| 2.0 – 3.5 | −1 | Elevated above typical fair-value range |
| > 3.5 | −2 | Extreme unrealized gains – historically precedes distribution |
Sourced from dogdata.xyz's own Bitcoin Core + Ord full node – not a third-party estimate.
Percent of circulating supply currently above its cost basis: <15% → +1 (widespread capitulation, contrarian bullish) · >90% → −1 (broad euphoria, contrarian bearish) · otherwise 0.
>+1% → +1 (healthy accumulation/adoption) · <−1% → −1 (base shrinking) · otherwise 0. This is not contrarian – a growing holder base is read as a straightforwardly positive signal, unlike the other on-chain metrics.
Step 1 – category score. Each category's indicator scores are averaged, then mildly amplified by ×1.4 and clamped to [−2, +2], so a category where every indicator agrees can reach the full ±2 even though no single indicator did:
Step 2 – weighted composite. Category scores are combined using the weights from above, then normalized down to a [−1, +1] range:
Categories with zero usable indicators (every one failed) are dropped from both the numerator and denominator – they don't drag the score toward zero, they're excluded entirely, same principle as individual data-limitation rows.
This is hysteresis – the same principle a thermostat uses so it doesn't click on and off every time the temperature wobbles by half a degree. Two constants control it:
| ENTER = 0.60 | Composite must exceed this magnitude to enter BUY or SELL from HOLD |
| EXIT_BUFFER = 0.15 | Once in BUY/SELL, composite must fall back below ENTER − EXIT_BUFFER = 0.45 before dropping to HOLD |
So a stance change requires crossing ±0.60, and once changed, requires falling back past 0.45 (not just 0.60 again) to leave – the 0.15 gap is a deliberate dead zone that stops the signal from chattering back and forth around a single threshold. A hard reversal (BUY straight to SELL) is still allowed in one step if the composite swings from above +0.60 to below −0.60 in a single run.
$DOG is a Bitcoin Rune – it tends to move with BTC's broader trend, and Rune tokens historically get dragged down hard in BTC downtrends regardless of their own fundamentals. This check runs after $DOG's own composite is computed, using whichever BTC composite is already sitting in the data store from BTC's own run in the same cycle:
In plain terms: if $DOG's own evidence says bullish while BTC is clearly trending down, $DOG's score gets docked a flat 0.30 – sometimes enough on its own to pull a marginal BUY back down to HOLD, given the hysteresis thresholds above. It only fires in one direction (penalizing DOG-bullish-against-BTC-bearish) – there's currently no symmetric bonus for DOG-bearish-while-BTC-bullish or symmetric penalty the other way.
If BTC hasn't computed yet in the same cycle (a cold-start edge case, since BTC always runs first), this check is skipped entirely and logged as "no BTC signal in store yet" rather than blocking $DOG's run.
Worth knowing: the −0.30 penalty size and the −0.30 BTC trigger threshold are fixed constants chosen by judgment, not backtested or derived from a formula. If you want to press on why those particular numbers, that's the honest answer.
| Term | Meaning |
|---|---|
| agreement | Fraction of scored categories whose sign matches the composite's sign (a category scoring exactly 0 always counts as agreeing) |
| strength | min(|composite| / 1.2, 1) – how far the composite sits from zero, capped at 1 |
| coverage | Fraction of categories that had at least one usable indicator this run (vs. failing entirely) |
Agreement carries the most weight deliberately – a confident-looking composite built from categories pulling in different directions is treated as less trustworthy than a smaller composite where everything actually points the same way.