Skip to content
Anurag Raina
Back to projects

Case study

OctaK Edge

Evidence-based stock verdicts for Indian equities, where AI explains but never scores.

Role
Architecture and implementation, two-person team
Year
2026
Status
In development
OctaK Edge landing page - a search box to analyse any NSE or BSE stock, under the headline 'Invest beyond noise. Decide with evidence.'

At a glance

stock universe
~300
holding timeframes
5
component scores
7
deployed apps
3

Overview

OctaK Edge turns an Indian stock into a structured verdict: component scores blended per holding timeframe, a trade plan with entry, stop and targets, and a position view that adapts to a real entry price and quantity.

One rule governs the system: numbers come from code, words come from AI. Every score, band and target is computed deterministically in TypeScript; the model only explains a verdict it did not produce, and proposes chart shapes from a closed list at capped confidence.

The product concept and the scoring model are my collaborator's. I built the platform around them - data layer, pipeline, database, access model, scheduled jobs, and the three-app architecture. Two people, pre-launch.

Why I Built It

Retail equity tools either publish a number with no derivation, or let a language model improvise a recommendation. Both are unfalsifiable; one of them sounds certain while being so.

OctaK Edge takes the harder position: every number traces to a deterministic module, and the model may only explain values it did not compute. Writing that sentence is easy. Keeping it true across free data sources, a serverless budget, five timeframes and a second app on the same database is the engineering.

The Approach

My scope was everything between the scoring model and a running product. It shipped as a single Next.js app - one deploy, no service boundary to maintain while the surface still moved. Once it stabilized, I reviewed it end to end, wrote up twelve ADRs, and ran the split into three apps as a phased program rather than a rewrite.

Scope choices, recorded rather than rediscovered:

  • No monorepo, and no separate repo for the schema or the shared package.
  • No ORM - a typed client and per-table modules suit a dozen tables.
  • No HTTP between apps, so no service mesh and no cross-app coupling.
  • No API versioning with one first-party client - the seam is kept, not built.

Architecture

OctaK Edge architecture: the determinism boundaryData flows from fail-safe adapters over free public sources into a deterministic engine that computes every number in TypeScript on the server. A trust boundary separates that engine from the AI layer: the model reads the computed values read-only, explains the verdict with a deterministic fallback and proposes chart shapes from a closed capped list, but never writes a score, band or target. The response combines the computed numbers and the narration. Below, three independently deployed apps - a credential-free Landing site, the App that holds the product and engine, and an operator Admin behind MFA - share a single Supabase Postgres database as their only runtime surface, with no app-to-app HTTP.Browser requestData adapters · fail-safefree public sources: Yahoo · NSE/BSE · RSSa blocked source becomes a visible gapDeterministic coreDeterministic engine · TypeScriptcomputes every number:indicators · scoring · trade plan · projectionnumbers ← code  ·  words ← AIthe model never writes a numberAI layer · narration onlyAI narrationexplains the verdict (deterministic fallback)proposes chart shapes from a closed list, cappedResponseverdict · trade plan · narrative+ sources[] / unavailable[]deployment · 3 apps, 1 databaseLandingpublic · no keysAppproduct + engineAdminoperator · MFASupabase · Postgres · RLSone shared database — no app-to-app HTTP
Numbers come from code, words come from AI - across three apps over one database.

One Next.js app, no separate backend. A single per-symbol pipeline is the spine: parallel fetch across independent sources, indicators, pattern detection, then a deterministic chain - component scores, timeframe-weighted blend, confluence, recommendation, trade setup, projection. Both the analysis and position routes call it, so the two surfaces cannot diverge.

Every data adapter is wrapped in a fail-safe cache. A thrown error becomes a typed "unavailable" for that field, and the response lists what was missing. No adapter ever substitutes a default.

Screening ~300 names per request is too heavy, so a cron precomputes a universe snapshot and requests only read it; its timestamp anchors determinism. Picks are written to an append-only forward log before the market resolves them, each stamped with the engine version and a hash of the exact scoring code.

Today it runs as three apps over one Supabase project - a credential-free landing site, the product, and an operator console - sharing only the schema and one published package.

Decisions & Tradeoffs

Enforce the determinism boundary structurally, not with a system prompt

Tradeoff accepted

Every new signal must be modelled by hand, and the product cannot answer what the engine cannot compute. In return the model has no code path that writes a number - it explains computed values, and its pattern guesses are validated against a closed list at capped confidence.

Alternatives considered (3)
  • Instruct the model not to invent numbers and trust it
  • Let the model adjust a computed score when it is confident
  • Generate the verdict with the model and compute a score afterwards to justify it

One shared database is the only contract between apps; no app-to-app HTTP

Tradeoff accepted

The schema becomes a coupling point two apps can break, so migrations are expand-contract, forward-only, and owned by one repo with a CI drift check. What it buys is zero runtime coupling - no internal auth, no availability dependency between apps.

Alternatives considered (3)
  • The product exposes internal endpoints the console calls
  • A second Supabase project for the console, with replication
  • A shared service layer in front of both

Three repos, one published package; duplicate everything else on purpose

Tradeoff accepted

Contract changes are two-step and some code is maintained twice. The rule that makes it bearable: promote to the shared package only when drift would be a security or billing bug - everything else is duplicated on purpose, with a comment naming its sibling.

Alternatives considered (3)
  • A monorepo with shared workspaces
  • A fourth repo for the schema, or for the shared package
  • Git submodules for shared code

Precompute the screening universe on a schedule; requests only read it

Tradeoff accepted

Results are only as fresh as the last snapshot, so every response carries its timestamp and a flagged live-fallback path. The worker tier stays designed-for, not built - the cut line is documented with its trigger conditions.

Alternatives considered (3)
  • Scan the universe on request
  • A job queue with workers
  • A long-lived worker outside the serverless runtime

Build the whole data layer on free, non-key-gated sources

Tradeoff accepted

Sources can block or change without notice, so the adapter layer contains the blast radius and a blocked source degrades to a visible gap. The licensing question is commercial, carried as a business gate before the product charges anyone.

Alternatives considered (2)
  • A paid market-data vendor from the start
  • Official exchange feeds

Engineering Challenges

Fitting a ~300-name universe scan into a serverless request budget.

How it was solved

A cron builds the feature vector for the whole universe and caches it; a request reads that snapshot, filters by per-timeframe eligibility, and runs full analysis only on a handful of finalists, batched ten at a time. The snapshot timestamp anchors determinism so two requests in the same window agree.

Degrading honestly when free sources fail without warning.

How it was solved

A component with no inputs is dropped from the blend, not scored zero, so weights renormalize and confidence reflects real coverage. The trade-setup generator refuses with a reason when the setup is weak, and the one value that could be faked - historical accuracy - is hardcoded null and flagged as the highest fabrication risk in the file.

Splitting one app into three without building a distributed monolith.

How it was solved

The schema got an owner (the repo with write-gravity), a single writer per table, expand-contract forward-only migrations, and a CI drift check. Rolling back app code is always safe against the newest schema, so schema rollback stops existing as a concept.

Features

  • Deterministic Edge Score: seven component scores reweighted across five holding timeframes
  • Trade plan with entry, stop, targets and reward-to-risk - or an explicit refusal when the setup is weak
  • My Position: the same analysis adapted to a real entry price and quantity
  • Edge Insight of the Day: a timeframe-specific screen over ~300 names, precomputed on a cron
  • Append-only forward log: every pick recorded before the market resolves it

Tech Stack

  • Next.js 16 (App Router)
  • React 19
  • TypeScript
  • Tailwind CSS 4
  • shadcn/ui
  • Supabase (Postgres, Auth, RLS)
  • Vercel + Vercel Cron
  • Upstash Redis
  • Zod
  • TradingView Lightweight Charts
  • yahoo-finance2
  • technicalindicators
  • Gemini / Anthropic / OpenAI (pluggable)
  • Vitest
  • Sentry

Lessons Learned

  • A constraint that lives in a prompt is a suggestion. The determinism boundary held because the model was never given a code path that could write a number.
  • Honest degradation costs less and is worth more than it looks. "Unavailable" beats a plausible default and deletes a class of bug nobody can reproduce.
  • Deferring debt with an explicit revisit trigger turns rot into a decision.

Screenshots

How OctaK Edge works - technical, fundamental and sentiment data feed a deterministic engine that computes an Edge Score the AI only explains.
A stock verdict for HDFCBANK - a Strong Buy Edge Score with supporting factors, risk factors and a structure-defined trade setup.
Edge Insight of the Day - the day's strongest setups screened across liquid NSE names, each with an Edge Score, confidence and expected move.

Contact

If you need an engineer who can own it end to end, from the interface to the infrastructure, let's talk.

Email me