System Case Study · Fintech · Shariah-Compliant Data · Kenya

SIBK NSE Market Data Feed

Client

Salaam Investment Bank Kenya (SIBK)

Role

Plugin Architecture, Backend Engineering & Security

Stack

WordPress Plugin: PHP, MySQL, WP REST API, WP-Cron

Status

Live, daily production ingestion

Contents

Problem Statement

SIBK wanted live Nairobi Securities Exchange pricing on their site, but not the whole exchange. They're a Shariah-compliant investment bank, so only Shariah-certified counters can ever reach a customer-facing screen. Anything else isn't a display bug, it's a compliance breach. I knew that ruling-out had to be structural rather than editorial, because any workflow where a person could forget to filter a page before publishing it would eventually fail.

The data itself also had to be trustworthy before it could look trustworthy. NSE end-of-day figures arrive either by vendor API or by manual file drop depending on the day, and either path can hand over malformed rows, stale dates, or an implausible price spike. I couldn't let any of that reach the public site, and I couldn't let it quietly corrupt the historical record either.

Solution Overview

I built a WordPress plugin that treats market data ingestion as a compliance and security problem first, and a display problem second. Two adapters, a vendor REST API and a manual file drop, feed one pipeline: validate, filter against a bank-maintained Shariah allowlist, then store. Nothing reaches the public site, the ticker widget, or the market table until it has cleared every gate.

How I Approached It

  • I made the allowlist a compliance boundary, not a display filter. Non-approved tickers are excluded before storage rather than hidden in the template, so the disallowed data never touches the database at all.
  • I trust nothing from either adapter. Vendor API responses and dropped files go through identical validation and filtering, with no shortcut for either source.
  • I made it fail loud. Every ingest run is logged with counts at each stage (in, valid, filtered, saved), and repeated failures trigger an email alert instead of a quietly stale ticker.
  • I put the most scrutiny on file handling. Manual file drop is the riskier of the two inputs, so it gets path-traversal, MIME, symlink, and embedded-code checks before a single byte is parsed.

Ingestion Pipeline

Follow a single price from the exchange to the screen. The spine below is the path every row takes. Press Play the flow to watch it move, or tap any stage to read what happens there. Underneath are the pieces that make it run, grouped by job; tap any one for the plain-English version.

The path of a price
Tap any stage above to see what it does and when it runs.

Note: this shows the real pipeline architecture and stage names from the plugin I shipped. I've left out vendor endpoint details, credentials, and the live allowlist contents, since those are confidential to SIBK.

Feature Set

Dual-Adapter Ingestion

I wrote a REST adapter that pulls end-of-day data from a vendor API on a daily cron, with HTTPS enforced, the API key sent via header, and response size capped before parsing. I paired it with a File Drop adapter that watches a protected upload directory every 15 minutes during the post-market window, for the days data arrives manually instead. Both implement the same interface and feed the identical downstream pipeline, so neither source gets a lower-scrutiny path.

Shariah Allowlist Filtering

I made a versioned list of SCO-certified NSE tickers the compliance gate that every record has to clear before it's stored. The version string gets stamped onto every saved price row and logged on every ingest run, so you can always audit which allowlist revision was in effect for any given day's data.

Multi-Stage Data Validation

CheckRule
Required fieldsTicker, price, and trade date must all be present
Ticker format2–10 uppercase letters, matched against a strict pattern
Price boundsKES 0.01–10,000; anything outside is rejected, not clamped
Change sanitySingle-day change beyond 30% is dropped as implausible
Trade dateRejected if in the future or more than 7 days stale
High/low consistencyHigh below close, or low above close, is nulled as a data error
Batch sanityPayloads over 500 records, or >20% invalid rows, halt the whole batch

Public Read-Only API

I kept the REST surface minimal: /wp-json/sibk/v1/prices and /status serve Shariah-certified closing prices to the frontend. I exposed no public write endpoints, sanitise output before it leaves the server, and rate-limit per IP with cached responses so the endpoint stays cheap under load.

Admin Dashboard & Manual Controls

I built an admin screen that shows feed health at a glance: status, last successful run, live vs. approved ticker counts, and allowlist version, with a staleness warning if 26+ hours pass without a successful ingest, which means a missed trading day. There's also a full ingest log and one-click manual ingest buttons for both adapters, so the team can troubleshoot without touching a server.

Theme Integration

I wrote a bridge class that feeds live prices into the site's ticker and market-table widgets through a WordPress filter. It falls back to the theme's built-in sample data on its own until the first successful ingest has run.

Security & Reliability

This plugin sits closer to a bank's compliance boundary than a typical content feature, so I built it with the file-handling and credential-storage discipline that implies.

  • Hardened file drop: I check every dropped file for path traversal (via realpath() containment), size limit, extension whitelist, actual MIME type rather than just the extension, symlinks, and embedded PHP or script tags, all before a single byte is parsed.
  • Locked-down upload directory: I create the drop folder with a .htaccess deny-all and a dummy index.php, so nothing in it is ever directly reachable or executable over HTTP.
  • Parameterised queries only: every database read and write goes through $wpdb->prepare(). There's no raw SQL interpolation anywhere in the storage layer.
  • Encrypted credential storage: I store the vendor API key AES-256-CBC encrypted in the database, keyed off a constant defined in wp-config.php rather than in the codebase, with autoloading disabled.
  • TLS enforced end-to-end: the REST adapter refuses to run against a non-HTTPS endpoint, and I never disable SSL verification.
  • No silent failure: I track consecutive ingest failures per adapter and trigger an admin email alert, so the feed can't quietly go stale.

Outcomes & Impact

BeforeAfter
Market data display depended on manual, ad hoc filteringShariah compliance enforced structurally: non-approved tickers never reach storage
No standard path for vendor outages or bad data daysTwo independent adapters (API + file drop) with identical validation, so one path can cover for the other
No audit trail for what data was shown, or whenEvery ingest logged with per-stage counts and the allowlist version in effect
Failures would surface only if someone happened to checkAutomatic email alert after repeated consecutive failures

It's running in production now, ingesting NSE end-of-day data daily and serving Shariah-certified pricing to SIBK's ticker, market table, and public API. The compliance and data-quality checks are built into the pipeline itself rather than bolted on afterwards.

If this is you

If you depend on data that has to be accurate and on time, I build you the pipeline that delivers it and stays out of your way.

Back to

All Systems

Need software
built right?

Whatever you need built, I design and ship it end to end, from an internal tool to a full-stack product. Tell me what should already exist.

Talk to Me