Files
ForexBot2/backtest/research/feed_divergence_2026-08-14.md
T
Harwinder Sekhon 1cebebf79a chore: keep only what the system needs — drop research tooling, study scripts, diagram, plan
Owner directive 2026-09-06: Dukascopy and similar research material is irrelevant to
the running system; keep only code and files with a role in system functioning.

Deleted (all in git history before this commit):
- backtest/research/ tooling and data: book_report, book_diff, burst_map,
  burst_precursors, burst_indicator_map, open_trade_bursts, calendar_impact,
  watch_rule_eval, sizing_model, commit_ladder, llm_news_eval + llm_news_golden.csv,
  ff_calendar_scraper, duka_spread + duka_spread_by_hour.csv (the Dukascopy spread
  study), feed_divergence_oanda_vs_tiingo.csv, the panel dry-test JSONL, __init__.py
- scripts/feed_divergence_study.py, scripts/signal_parity_study.py (completed studies;
  their reports keep the results)
- docs/architecture.png + architecture_diagram.py (developer illustration)
- docs/data_source_change_test_plan.md (Phase 4 shadow scan stays noted in CLAUDE.md)

Kept: the campaign .md reports in backtest/research/ as the decision ledger CLAUDE.md
cites (rule 1 evidence); scripts/shadow_scan.py (pending operational step);
backtest/diagnose_filters.py (test-locked backtester diagnostic).

Local, untracked material removed on this box: .superpowers/, walkforward/, baseline/,
the commit-ladder and LLM-eval result folders, the Dukascopy boundary CSV; the
sizing_2026-09 folder is pruned to the four 3-year baseline books CLAUDE.md names.

.gitignore no longer lists the removed research outputs; the backtest instructions
and CLAUDE.md no longer point at deleted tools.

Suite: 461 passed, 0 failed (nothing imported the removed files).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0156YhogLytzj9P2iH1skGbL
2026-09-06 17:35:41 -04:00

5.4 KiB
Raw Blame History

Feed Divergence Study — Oanda vs Tiingo vs Twelve Data (Phase 1)

Date: 2026-08-14 Test plan: docs/data_source_change_test_plan.md (removed 2026-09-06, in git history; the pending Phase 4 shadow scan is noted in CLAUDE.md) Tool: scripts/feed_divergence_study.py (script removed 2026-09-06, in git history) (fetch_range over 365d, parquet-cached) Window: 2025-08-14 → 2026-08-14 (12 months); Oanda-vs-TD truncated at TD cache head (2026-07-23)

Headline

Three mid-price feeds for the same XAU/USD instrument are not interchangeable:

Pair mean |ΔClose| p95 |ΔClose| direction agree (M5/M15/H1) bias extra bars
Oanda vs Tiingo ~$0.13 ~$0.29 97.7% / 98.3% / 98.5% ~0 Tiingo +3–5% (weekend)
Oanda vs Twelve Data ~$3.0 ~$11.9 81.0% / 88.7% / 92.7% −$1.06 (TD high) —
  • Oanda ↔ Tiingo are near-identical on shared bars (~1–2% of ATR on close), but Tiingo emits ~22 hours of Sunday bars/week that Oanda omits.
  • Oanda ↔ Twelve Data diverge massively — ~$3 mean close gap (≈30% of M5 ATR, ~30% of M15 ATR), a systematic ~$1 bias (TD quoted ~$1 high), and 19% of M5 bars even disagree on bar direction. This is the documented "Oanda/TD divergence" that motivated re-pinning the books on Oanda bars.

Oanda vs Tiingo — detailed

Both feeds: same bar grid, same head/tail timestamps. Tiingo simply has more bars (Sunday bars).

Coverage (12 months)

TF Oanda bars Tiingo bars shared Oanda-only Tiingo-only
M5 70,901 73,241 70,807 (96.6%) 94 (0.13%) 2,434 (3.32%)
M15 23,640 24,922 23,615 (94.7%) 25 (0.11%) 1,307 (5.24%)
H1 5,912 6,246 5,909 (94.6%) 3 (0.05%) 337 (5.40%)
H4 1,597 1,657 1,597 (96.4%) 0 60 (3.62%)
  • Tiingo-only bars cluster exclusively on Sundays (e.g. M15: 88/Sunday; H1: 22/Sunday; H4: 5/Sunday). Tiingo's FX endpoint resamples continuously and does not apply the FX weekend calendar — it emits ~22h of flat/stale Sunday bars that Oanda omits.
  • Oanda-only bars cluster on holidays (2025-11-27 Thanksgiving, 2025-12-10, 2026-06-25) — a handful of bars, negligible.

Per-bar OHLC diffs (Oanda − Tiingo, $)

TF Close mean Close p95 Close max |ΔClose| / ATR14 (mean / p95)
M5 $0.123 $0.285 $26.10 2.1% / 5.0%
M15 $0.128 $0.290 $26.10 1.3% / 2.9%
H1 $0.145 $0.335 $26.10 0.7% / 1.6%
H4 $0.168 $0.340 $17.53 0.4% / 0.8%
  • Bias is ~zero on every TF (no systematic one-feed-high).
  • Tail outliers (p99/max up to $26–88) occur during fast moves — the two feeds' bar extremes disagree on the exact tick, as expected.
  • Direction agreement is 97.7–98.4%, return correlation 0.995–0.9997.
  • Divergence is concentrated at the Friday-close / Sunday-reopen boundary (UTC hours 20–22; mean |ΔClose| ~2–4× the 08–19h baseline).

Phase 1 pass/fail vs plan thresholds

Criterion Plan threshold Result Verdict
timestamp overlap ≥ 99.5% 94.6–96.6% FAIL (Tiingo weekend bars)
Close p95 |Δ| ≤ 0.01% of price ~0.0067% PASS
no systematic bias mean Δ ≈ 0 ~0 PASS

The overlap "failure" is a coverage difference, not a data-quality one: the shared bars agree tightly, but Tiingo's extra Sunday bars mean the feeds have a different bar count. The signal pipeline's own _is_forex_weekend filter (NY-anchored) gates those Sunday bars, so live impact depends on whether any code trusts the feed's raw bar set directly.

Oanda vs Twelve Data — detailed (M5/M15/H1, cached TD parquets)

TF common mean |ΔClose| median |ΔClose| p95 max bias (TD−Oanda) dir agree
M5 66,246 $2.999 $1.118 $11.934 $101.85 +1.05 80.96%
M15 22,090 $2.951 $1.051 $11.848 $101.85 +1.08 88.71%
H1 5,526 $2.902 $0.985 $11.908 $70.94 +1.06 92.67%
  • The ~$3 mean / ~$1 median / ~$12 p95 gap is ~23× larger than the Oanda–Tiingo gap, and the ~$1 bias is systematic (Twelve Data quotes gold ~$1 high vs Oanda's true mid).
  • M5 direction agreement of 81% means one bar in five disagrees on direction — M5 signals on TD bars are effectively a different instrument than on Oanda bars.
  • This matches the prior Oanda/TD M15 study of 2026-07-24 (oanda_td_divergence.py, removed 2026-09-06 as superseded by this report; mean |ΔClose| ~$3.3) and confirms the standing rule: pinned Twelve-Data books are not comparable to Oanda live signals without a re-pin.

Conclusions for the data-source switch

  1. Oanda → Tiingo (or back) is signal-safe in magnitude (price diffs ~1–2% of ATR, 98% direction agreement), provided the weekend-bar coverage difference is handled — Tiingo's Sunday bars must be gated by the aggregator's NY-anchored weekend filter, not by raw bar count.
  2. Oanda → Twelve Data is a recalibration, not a formality. Phase 2/3 must quantify the actual signal/book delta; the $3/$1 bias alone guarantees a large fraction of marginal bars flip.
  3. Re-pinning the books on Oanda bars (Phase 3) remains mandatory before any TD-pinned baseline is treated as a live expectation.

Next steps

  • Phase 2: signal-level replay parity (analyze_from_dataframes on both feeds) to turn price-diff stats into flip rates.
  • Phase 3: backtest re-pin on Oanda bars at $0.30 and $0.65.