On and off, I continue to develop two interconnected projects built on a shared codebase. The first is a weekly automated dashboard tracking economic and financial market indicators across India and the world. The second, RBI Sentinel, tracks (& analyses) the tone of the Reserve Bank of India's monetary policy communications. Trust me when I say this, I personally use these platforms quite regularly, whether I'm researching a topic or simply trying to make sense of what's happening in the economy. They're as much tools for my own work as they are projects I enjoy building and improving.

Selected Charts


Part I · Automated Macro Dashboard

A scheduled pipeline that pulls live market and macro data, draws it through one shared chart style, and publishes the result. No step is manual, and nothing is ever a placeholder: a missing API key or an unreachable source fails the run rather than filling a gap.

Launch Live Dashboard ↗

What it publishes

Four sections, each with its own link and its own generator.

Section What it covers Charts
Weekly Markets Equities, rates, credit, FX, commodities, emerging markets and crypto — the week’s moves set against twelve-month trends 36
World Central bank rates and calendars, a six-economy scoreboard, US valuations (Shiller CAPE, implied equity risk premium), country risk 12
India Growth, inflation, monetary conditions, external balances, portfolio flows, central government fiscal accounts 15
RBI Sentinel Policy tone — Part II below 6

The Weekly page also carries The Week in Headlines: the week’s most-covered stories in world and Indian economics, collected every four hours from fifteen feeds across nine outlets and ranked by how many outlets carried a story and how many days it stayed in the news. Headlines are never written by the system — an unreadable feed is dropped, not invented.

How it is built

Two ingestion streams feed one charting engine:

  • Market data — a YFinanceFetcher pulls equity indices, FX pairs, commodities and volatility measures.
  • Macro fundamentals — a FredFetcher pulls the full US Treasury curve, credit spreads and inflation breakevens from FRED.

Every series carries a maximum age. A source that quietly stops updating fails the run instead of publishing a stale number — the failure mode that matters most on a dashboard nobody is watching.

Both streams are standardised into pandas DataFrames and drawn through a shared EconStyle module holding every visual constant in the project: colours, sizes, DPI, the rule above each title, the source line beneath it. No chart sets its own.

GitHub Actions runs the generators on a schedule — Weekly Markets and India on Saturday morning, World mid-morning, RBI Sentinel on weekday evenings and through the day of a policy decision. Each run commits its images. Streamlit Cloud serves them straight from the repository, and a loader finds the newest dated folder by natural sort rather than a hard-coded file list, so adding a chart needs no change to the app.

  1. Macro fundamentals FRED API
    Market data Yahoo Finance
  2. ETL and charting engine pandas processing, EconStyle rendering
  3. Scheduled runs GitHub Actions
    Local runs on demand
  4. Streamlit dashboard four sections, four links

Part II · RBI Sentinel

Central banks move markets twice: once when they change the policy rate, and again in how they describe the decision. The rate is a number anyone can read. The description is prose, and reading it consistently across a decade of meetings is the part nobody does by hand.

RBI Sentinel scores every Monetary Policy Committee document the Reserve Bank has published since October 2016 on a single hawkish–dovish scale, then asks a deliberately unkind question of the result: does the tone tell you anything the rate decision and the RBI’s own stated stance do not?

Open RBI Sentinel ↗

The corpus

   
Period October 2016 – August 2026
Policy cycles 61
Documents collected 285
Document types MPC Resolution (143), Governor’s Statement (81), Minutes (61)
Rate outcome by cycle 40 hold · 13 cut · 8 hike

Documents are discovered directly from rbi.org.in, not a redistributed dataset. Only press releases are scored; the Monthly Bulletin reprints the same text weeks later and is excluded, because scoring it would count a meeting twice.

That outcome distribution deserves a pause. Two thirds of cycles were holds, and only 21 of 61 produced a move at all. Any claim that a text signal “predicts the decision” has to beat a rule as crude as always say hold, which is right 66% of the time.

How a document is scored

A hybrid: 10% rule-based lexicon, 90% large language model.

  • Lexicon — a hand-built list of RBI-specific hawkish and dovish phrasing, counted with a five-word negation window and density-adjusted through a tanh transform, so a long document is not mechanically more hawkish than a short one.
  • Model — Claude Opus 5 reads the full document and returns a score from −1 (very dovish) to +1 (very hawkish), with five sub-dimensions: inflation concern, growth assessment, liquidity stance, rate guidance and external (rupee) stance.

The 10/90 split is measured, not assumed. Across the corpus the lexicon’s standard deviation is 0.263 against the model’s 0.587 — the keyword counter is 2.2× narrower, because the tanh normalisation compresses it toward zero. An earlier 25% weighting dragged every confident reading toward the middle: a document the model read at −0.95 could not be matched by a lexicon whose range stops near −0.64. At 10% the lexicon survives as an independent cross-check without flattening the signal.

A meeting’s composite weights Minutes 50%, Resolution 35%, Governor’s Statement 15% — the Minutes most heavily because they record individual members’ reasoning, which is where disagreement shows.

Facts are extracted without the model: The rate decision, the stated stance, the RBI’s CPI and GDP projections and the next meeting date are read from the Resolution by regular expression, and verified against all 61 cycles. Anything a regex can read reliably should not be handed to a language model: it costs money, and it introduces a failure mode where the number on the dashboard is a plausible invention. Only the tone judgement goes to the model.

  1. Discovery and cache rbi.org.in
  2. Extraction HTML parsing, text normalisation
  3. Lexicon scorer RBI-specific terms, negation window
    Model scorer Claude Opus 5
  4. Fusion and divergence check 0.10 lexicon + 0.90 model
  5. SQLite rbi_sentinel.db
  6. Chart generation
  7. Streamlit dashboard

What it found

Tone does not predict the rate decision: The composite tracks the policy cycle closely, but once the RBI’s own stated stance is in the model, tone adds nothing. This is a negative result and it is reported as one. It is also unsurprising in hindsight: the stance is the committee’s compressed summary of its own tone, published deliberately.

No reliable relationship with equities, the rupee or volatility: Tested against Nifty, Bank Nifty, USD/INR, gold and India VIX, nothing survived. Given how many pairs were tested, a couple of suggestive correlations would have been the expected result of chance alone; there were none worth reporting.

Tone does line up with the bond market’s reaction on decision day: The change in Resolution tone from one cycle to the next corresponds to the move in the 10-year government security yield that day — roughly 5 basis points for a typical shift in tone. This is the one relationship that held, and also the one most plausible in advance: the bond market prices the path of policy, and the Resolution’s language is the clearest public statement about that path.

The problem with that result

Every meeting in this sample happened before the scoring model was trained: A model that has read financial journalism up to its training cutoff has, in principle, encountered commentary about these very meetings, including what the bond market did afterwards. Nothing in a backtest can rule out the possibility that the model is recalling the outcome rather than reading the document.

This is the central methodological risk in applying language models to historical text, and holding out a test set does not solve it, because the contamination is in the model’s weights, not the analyst’s data split.

From October 2026, for every new Resolution:

  1. The tone score is computed and committed to the repository before the 17:00 IST government securities close, with a timestamp.
  2. The 10-year yield close is entered separately, afterwards, by hand — the RBI publishes no free machine-readable close, and rather than substitute a proxy the pipeline opens an issue and waits for the real number.
  3. Both are appended to a log that is never retroactively edited.

Each meeting is therefore a genuine out-of-sample observation, recorded before the outcome exists. The sample grows by about six observations a year, which is slow — and that is what honest evidence costs in a field with six data points a year.

Until that log has a meaningful number of entries, the decision-day result should be read as a hypothesis with supporting historical evidence, not an established finding.

Engineering constraints

  • Model spend is capped structurally: A document reaches the model only if it is new, belongs to an MPC cycle and clears a minimum length. A scheduled run scores at most four documents; a larger backlog scores nothing and fails the run, so a discovery bug cannot quietly spend money. Normal cost is about $0.15 per meeting.
  • Scheduling follows the calendar, not the clock: The pipeline reads the next meeting date out of the latest Resolution and only runs intraday checks on decision day. Every other day the gate exits in seconds.
  • Every score carries the version of the method that produced it: Changing the method means bumping that version; old scores are kept rather than overwritten, so a published number can always be traced to how it was calculated.
  • Charts are fingerprinted against the data that drew them, and a test fails if the database has moved since. A stale chart is a wrong chart.

Limitations

  • Sixty-one policy cycles is a small sample, and 21 rate moves is smaller still. Every historical result here is provisional.
  • The scoring model is closed and versioned by its vendor. Reproducing a score years from now requires the same model version — which is why scores are stored with their method version rather than recomputed.
  • The decision-day result is a same-day association, not a demonstrated trading edge. Nothing here has been tested after transaction costs, and the dashboard makes no recommendation.
  • The tone scale is one-dimensional by construction. The five sub-dimensions exist because a single hawkish–dovish number discards genuine disagreement — a committee worried about inflation and growth at once, for instance.