"TradingView is built for people who already speak the language of markets. Deriv Pulse is built for the moment before that."
Built for the Deriv API Grand Prix 2026 · April 6–17
| Name | Role |
|---|---|
| Ibrahim Abdulla | Product · Designer · Developer |
Submission date: April 6, 2026 Competition: Deriv API Grand Prix 2026 Category: Consumer · Open category
Deriv Pulse is a single-page, deployable web app that answers one question a non-trader actually asks:
Is right now a calm or crazy moment in global markets?
It is not a trading dashboard. It is not a chart tool. It is the emotional front door to understanding markets — designed for someone who has never traded before. The entire experience lives on one screen. No backend. No database. Just a live URL anyone can open.
The problem with every existing market tool — Bloomberg, TradingView, even Deriv's own platform — is that they assume the user already speaks the language of markets. Candlesticks, order books, bid/ask spreads: these are fluent-trader concepts. They exclude the 99% of people who haven't started yet.
Deriv Pulse is designed for the moment before someone becomes a trader. It takes real, live, institutional-grade market data from Deriv's public WebSocket API and translates it into a single human feeling: calm, steady, active, or wild.
The strategic argument:
- Every person who opens this screen and understands "markets are calm right now" is one step closer to becoming a Deriv client
- This is a user acquisition funnel disguised as a visualisation
- The flow is: Awareness → Curiosity → First experience → Signup — all on one screen
1. First-time user sees a 3-step walkthrough:
- Step 1: bottom sheet ("Markets, made human.") — explains the app in one sentence
- Step 2: spotlight on the orb ("This colour is the market's mood. Right now.")
- Step 3: spotlight on the first asset row ("Tap any asset to predict where it's heading.")
- "?" button in header replays the walkthrough at any time
2. Home screen: tagline "Feel the market. Before you trade it." above the breathing orb
3. Orb colour and speed reflect the current market mood in real time
4. Featured asset card shows the most-moving asset (driven by live tick delta)
5. User taps the orb (or featured card) — Pulse Read sheet slides up:
- Which asset is moving most / most stable right now
- AI-narrative momentum insight ("Bitcoin trending upward across last 4 ticks")
- Opinionated CTA: "Predict [Asset] now →"
6. User taps an asset row directly — prediction sheet slides up with:
- Last 80 ticks as a historical chart (from ticks_history API)
- Live price as entry point
- Real Deriv payout quotes on each direction button ("~87% if right")
- Momentum signal ("Bitcoin trending upward across last 4 ticks")
- Direction buttons labelled "With the flow ↑" / "Against it ↓"
7. User picks a duration (30s / 60s / 5 min) and direction (UP / DOWN)
8. Countdown begins — live mini chart, entry vs current price, progress bar; sheet stays open so the user can watch the countdown unfold; drag down or tap outside to minimise to the mini bar
SIMULATION MODE (default — no account needed):
- At zero: result compared against live price
- WIN → "You called it. Bitcoin moved your way."
- LOSE → "Markets had other plans. Bitcoin went the other way."
DEMO ACCOUNT MODE (optional — connect via + Demo button):
- On direction pick: real Deriv buy call fires with proposal ID
- Deriv contract executes on your demo balance ($1 stake)
- When Deriv settles the contract, result shows official P&L
- "Deriv settled this contract. +$0.87 · Demo account · Won"
9. Result screen shows: plain-English explanation, price moved %, win/loss record
10. "Predict [Asset] on Deriv →" deep-links to that asset on app.deriv.com
11. "Read the next pulse ↑" resets — loops back to the Pulse Read sheet
Below the headline area, a live panel explains why the market feels the way it does right now. It reads from the same real-time WebSocket data as the rest of the app and surfaces up to three plain-English signal bullets on every tick cycle.
| Signal | Source | Example |
|---|---|---|
| Vol 75 spike | Rolling 14-sample baseline vs current getVolatility('1HZ75V') |
"Volatility 75 is spiking faster than its recent average" |
| Multi-asset mover count | % change from tick −5 to tick 0 across all 10 symbols | "3 assets moved >0.07% in the last 5 ticks" |
| Vol 75 momentum | 4-of-4 consecutive same-direction tick changes on 1HZ75V |
"Momentum increasing over last 5 ticks" |
| Cross-asset alignment | All primary assets moving the same direction simultaneously | "All tracked assets rising together — broad upward pressure" |
| Vol index agreement | Both 1HZ75V and 1HZ100V above the active threshold |
"Vol 75 & 100 both elevated — synthetic indices heating up" |
The AI badge and top accent line recolour with --mood-color in real time. The panel throttles its DOM redraws to every 4 ticks and samples its baseline every 5 ticks to prevent flicker on fast synthetic index streams.
The central visual is a breathing orb that shifts colour, glow intensity, and animation speed based on live volatility data from Deriv's synthetic indices.
| State | Volatility Score | Colour | Animation | Headline |
|---|---|---|---|---|
| Calm | < 0.05% | Deep teal #0f9b8e |
Slow, 4s cycle | "Markets are breathing easy right now." |
| Steady | 0.05–0.15% | Warm amber #d4924a |
Rhythmic, 2.5s | "Markets are moving with purpose." |
| Active | 0.15–0.35% | Electric blue #4a8fd4 |
Quick, 1.5s | "Something is stirring out there." |
| Wild | > 0.35% | Coral red #d45a4a |
Rapid, 0.8s | "It's chaotic out there right now." |
Mood is calculated from Deriv's Volatility 75 and Volatility 100 synthetic indices — instruments specifically designed to simulate real market volatility conditions.
- One
.htmlfile — embedded CSS and JS, zero build step - Zero dependencies — no npm, no framework, no bundler
- Google Fonts — Inter (300/400/500/600/700/800), loaded via
<link> - Deriv WebSocket API V3 — 9 live tick subscriptions + up to 5 API calls per prediction
Live at https://deriv-pulse.vercel.app
wss://ws.derivws.com/websockets/v3?app_id=1089
| Call | Purpose |
|---|---|
ticks × 9 symbols |
Live price stream |
asset_index |
Tradeable dot per asset row |
authorize |
Demo account auth (if token stored) |
| Call | When | Purpose |
|---|---|---|
ticks_history |
Asset tapped | 80-tick history chart on choose sheet |
proposal × 2 |
Asset tapped | Payout % for CALL and PUT |
proposal × 2 |
Duration changed | Refresh payout quotes |
buy |
Direction chosen (demo mode) | Execute real Deriv contract |
proposal_open_contract |
After buy | Stream settlement in real time |
| Symbol | Name | Role |
|---|---|---|
cryBTCUSD |
Bitcoin | Asset display |
frxEURUSD |
Euro | Asset display |
frxXAUUSD |
Gold | Asset display |
cryETHUSD |
Ethereum | Asset display |
frxGBPUSD |
British Pound | Asset display |
1HZ10V |
Volatility 10 Index | Mood signal |
1HZ25V |
Volatility 25 Index | Mood signal |
1HZ75V |
Volatility 75 Index | Primary mood driver |
1HZ100V |
Volatility 100 Index | Primary mood driver |
function getVolatility(sym) {
const h = priceHistory[sym]; // last 20 ticks
return Math.abs((h[h.length - 1] - h[0]) / h[0] * 100);
}
function recalculateMood() {
const score = (getVolatility('1HZ75V') + getVolatility('1HZ100V')) / 2;
if (score < 0.05) return setMood('calm');
if (score < 0.15) return setMood('steady');
if (score < 0.35) return setMood('active');
return setMood('wild');
}When a user taps an asset, two proposal calls fire for CALL and PUT with a $1 stake. The response payout is used to show real Deriv contract rates on the direction buttons:
const pct = Math.round((proposal.payout / proposal.ask_price - 1) * 100);
// e.g. "~87% if right" on the Going UP button- User taps + Demo in the header → pastes an API token (Trading scope) — token created at developers.deriv.com/dashboard/tokens
- Token stored in
localStorage, sent only to Deriv's WebSocket { authorize: token }fires → balance and loginid confirmed- On direction choice →
{ buy: proposalId, price: askPrice }executes a $1 Deriv contract proposal_open_contractsubscription streams settlement- When
is_sold: 1: result screen shows Deriv's official P&L - Fallback: if Deriv hasn't settled within 8s, resolves from live price comparison
On connect, { asset_index: 1, landing_company: 'svg' } is sent. The response is parsed to check which of the 5 displayed assets have CALL/PUT contracts available. Each asset row shows a 5px dot:
- Green — confirmed available for trading
- Dim grey — view only
All mood-driven visuals flow through CSS variables on :root:
--mood-color /* primary accent colour */
--mood-glow /* same colour at ~20% opacity */
--anim-duration /* orb breathe cycle speed */When mood changes, colour, glow, orb speed, spark lines, predict pills, and time selector all update simultaneously via transition: 2s ease.
All WebSocket lifecycle logic lives in a single DerivWSManager class:
| Behaviour | Detail |
|---|---|
| Keep-alive ping | Every 25 s while connected |
| Exponential backoff | 1 s → 2 s → 4 s → 8 s → 16 s → 30 s (cap), resets on success |
| Heartbeat watchdog | Force-reconnects if no data arrives for 60 s while nominally connected |
| Tab visibility | visibilitychange listener reconnects immediately when the user returns to the tab |
| Reconnecting banner | Amber top banner slides in on disconnect, disappears on recovery |
| Live dot states | Amber pulse = reconnecting · Green flash = recovered |
| Row dimming | Asset rows dim to 45% opacity during disconnect; prices preserved in state — no blank rows |
| Recovery toast | "Reconnected ✓" shown after any reconnect |
| Re-subscription | All tick subscriptions re-sent on every onopen; old server-side subs die with the socket |
1. startPrediction(sym)
→ records entry price, fetches ticks_history + proposal quotes
2. chooseDirection('up' | 'down')
→ starts 250ms interval countdown
3. Every 250ms:
→ remaining time, live price vs entry, mini chart, progress bar
4. At t=0: resolvePrediction(exitPrice)
→ won = price moved in predicted direction
→ orb flashes green (win) or amber (loss) for 1.5s
→ streak updated in localStorage
1. chooseDirection fires → buy call with proposal ID
2. Deriv returns contract_id → subscribe to proposal_open_contract
3. Countdown runs in parallel
4. If Deriv settles first → countdown stops, result from Deriv data
5. If countdown ends first → "Settling..." spinner, 8s Deriv fallback
6. Result shows official P&L from Deriv
- 30 seconds — fast, for crypto
- 60 seconds — default
- 5 minutes — slower assets like Gold
Changing duration re-fires proposal calls to refresh payout quotes.
Choose sheet — 80-tick history from ticks_history API, rendered as SVG polyline. Shows price context before picking direction.
Countdown sheet — builds live from WebSocket ticks since prediction started. Entry price shown as dashed reference line. Only redraws on new ticks (throttled).
- Win →
#1D9E75(green) for 1.5s - Loss →
#BA7517(amber) for 1.5s
Achieved by scoped --mood-color inline style on #orb-wrapper, removed after 1.5s.
A compact dot strip in the header, next to the Day streak counter. Replaces the old scoreboard fraction.
- Dots — last 8 predictions; green filled = correct, outlined red = wrong
- Win animation — newest dot scales to 1.7× with a green glow ring on a correct prediction
- Early state label — under 5 predictions:
"first call"/"N calls", no percentage; accuracy % only appears at 5+ predictions when there is enough signal to be meaningful - Result screen — shows streak first ("3 correct in a row"), then accuracy if enough data, then a gentle nudge ("N predictions — keep going"); raw fraction removed
Tracked in localStorage as { wins, total }. Persists across sessions. Shown on result screen.
Calm luxury meets live data. Think Bloomberg meets the Calm app. Every pixel is intentional. Built for a C-suite presentation at a fintech company.
#0a0d12 — near-black with a subtle SVG noise texture overlay (4% opacity fractalNoise) and a directional gradient.
- Inter — entire app, single typeface with 6 weights:
- 800 — tagline, headlines, result screen, onboarding, auth titles
- 600 — sheet asset name, spotlight text, pulse narrative
- 400 — body text, asset names, supporting copy
- 300 — countdown number, subline, onboarding body (light, airy)
- Tagline:
clamp(1.2rem, 4.5vw, 1.7rem),letter-spacing: -0.03em— tight and confident - Countdown number: 72px Inter 300 — large light numerals feel more modern than serif
A layered SVG with:
- Ambient glow div — radial gradient, scales 1→1.3 on the breathe cycle
- Main orb body — radial gradient ellipse with depth falloff
- Inner highlight ellipse — offset from centre, creates a 3D light-source feel
- Specular highlight — small blurred white ellipse at top-left
- Ring — fades opacity only (no scale), stays perfectly geometric
The orb and ring animate independently:
- Ring: opacity fade only (
0.08 → 0.22) - Inner orb: pure scale breathe (
1.0 → 1.08) - Whole SVG: glow filter pulse only — no transform, no layout shift
Each row: name + mood dot | spark line | live price | status | Predict › pill
- Per-market mood dot — 7px circle, colour reflects the individual asset's volatility mood (teal=calm, amber=steady, blue=active, red=wild); seeded from
ticks_historyon boot; neutralvar(--border)before data arrives - Left border flashes to
--mood-coloron hover - Loading skeleton pulse on prices while waiting for first tick
- Status column (rising/falling/steady) shown at ≥460px viewport width
- Full-screen
#splashcovers the page immediately on load with a pulsing mini-orb and "DERIV PULSE" wordmark - Dismissed on the first WebSocket tick — fades out over 0.5s then removes itself from the DOM
- No blank white flash or layout shift while the WebSocket connects
<meta name="theme-color" content="#11141b">— Chrome/Android status bar matches the app backgroundapple-mobile-web-app-capable+black-translucentstatus bar — correct behaviour when added to iOS Home Screen
- Slides up from bottom with
cubic-bezier(0.16, 1, 0.3, 1)— the iOS spring curve - Wide drag zone: top 60px — covers the handle pill and first content line; any swipe near the top initiates the drag. Handle bar opacity bumped to 32% for better visibility as an affordance.
- Drag handle: pull down 80px+ to minimise
- During active countdown: minimises to a 56px bar showing asset, direction, timer, progress bar
- Tap the bar to re-expand
- Backdrop tap: minimises if prediction active, dismisses otherwise
Fixed to the bottom of the viewport at all times (z-index below bottom sheet). Glassmorphic background. Always visible regardless of scroll position.
3apr/
├── index.html ← the entire application (~2,500 lines, HTML + CSS + JS)
├── README.md ← this file
├── CHANGELOG.md ← version history
├── PROMPTS.md ← full development session log
└── LICENSE ← MIT
| Asset | Symbol | API call |
|---|---|---|
| Bitcoin | cryBTCUSD |
ticks (live) + ticks_history |
| Ethereum | cryETHUSD |
ticks (live) + ticks_history |
| Euro | frxEURUSD |
ticks (live) + ticks_history |
| British Pound | frxGBPUSD |
ticks (live) + ticks_history |
| Gold | frxXAUUSD |
ticks (live) + ticks_history |
| Market Mood | 1HZ75V · 1HZ100V |
ticks (live) |
| Payout quotes | all 5 assets | proposal (CALL + PUT) |
| Contract execution | all 5 assets | buy + proposal_open_contract |
| Tradeability | all 5 assets | asset_index |
Updates: real-time, every tick (~1s per symbol).
Three disclaimer placements:
-
Fixed compliance bar — always visible at the bottom of the viewport:
"Not financial advice · No real money involved · For informational purposes only"
-
Inside the prediction sheet (before direction choice):
"This is not financial advice. No real money is involved. Past market movements do not predict future results."
-
Result screen (after every prediction):
Same disclaimer as above.
Demo account mode is clearly labelled throughout as using virtual funds only.
Live URL: https://deriv-pulse.vercel.app
# Local dev
python3 -m http.server 3000
# then open http://localhost:3000
# Deploy
vercel --prodNo build step. No environment variables. No server. No database.
One liner:
"Deriv Pulse is the emotional entry point that sits before your existing product."
On the demo account feature:
"It's not a simulation pretending to be real. When you connect a demo account, the buy call actually fires on Deriv's infrastructure. You get a real contract ID, real settlement data, real P&L — on virtual money. That's a fundamentally different thing."
Built for the Deriv API Grand Prix 2026 · Powered by Deriv API V3 · Optional demo account · No backend · No database