Sander Korf
  • Portfolio
  • Resume

Sander Korf

Dutch Full Stack AI Engineer helping businesses cut costs through intelligent automation. 13+ years turning expensive manual processes into systems that work 24/7. Based in Amsterdam, available for freelance projects.

Navigation

  • Portfolio
  • Resume

Legal

  • Cookies
  • Privacy Policy
  • Terms and Conditions

Blog

Algolia

  • Algolia InstantSearch INP and object identity
  • Algolia merch by Sanity _type, not title
  • Algolia InstantSearch search key, not admin

Vercel

  • Next.js empty Suspense fallbacks wreck CLS P95
  • Vercel Workflows: skip closed eToro legs

eToro

  • eToro deploy vs rotate: idle cash not rotate
  • eToro search 404: query fields, not ticker
  • eToro v2 opens at-most-once, settlement
  • eToro LLM overlay ±10pp: critic cannot veto

Next.js

  • next-intl useTranslate skip links above fold
  • next-intl owns Klaviyo nl-NL email copy

Firebase & Expo

  • Staging deep links must not hijack production
  • Turn off Worklets Bundle Mode for EAS SHA-1
  • Reclaim Firebase orphan without password wipe

Centra & Klaviyo

  • Centra to Klaviyo tags need a plugin contract

About

  • Full Stack AI Engineer in Amsterdam

© 2026 Sander Korf. All rights reserved

94719489

  • Applied AI
  1. Home
  2. Blog
  3. eToro LLM overlay ±10pp: critic cannot veto

eToro LLM overlay ±10pp: critic cannot veto

Idle cash on a live book shows up immediately. I keep a deterministic core fully invested, cap model tilts, and never let a critic block deployment.

Sander KorfPublished August 12, 20264 min read
etorollmtypescript

This is an eToro book with an LLM overlay

TypeScript core. LLM tilt. Live eToro account. If the model owns the book, a reject or a sparse overlay is cash. The person watching the account sees a holiday, not a tilt.

What they would notice if it failed

Zero names. Zero invested. A critic that "said no" and parked the portfolio. Golden tests still green. The eToro book is the only review that mattered.

The LLM owned the eToro book

This TypeScript allocator feeds a live eToro book. I let an LLM write that book. Not a comment on it. The book. Regime labels, ticker picks, weights. When the model was fluent, the allocation looked sharp. When it was sparse, or when it rejected the prompt, the book went empty.

Empty is not a tilt. Empty is cash. A reject output froze the account at zero invested. A half-finished overlay did the same: missing names defaulted to nothing, and nothing plus nothing is a holiday, not a strategy.

Golden tests never caught it. They checked that a happy-path overlay blended. They never asserted a fully invested core. Zero names passed. The suite was green while the portfolio was parked.

Invert ownership

The deterministic layer now owns the eToro book. Always. A regime plus momentum core prints a 100% invested allocation before the model speaks.

Crisis: invested safe-haven. Not cash. The rule still puts you in the market. Normal: top momentum names plus a small crypto sleeve.

The LLM may only tilt each name ±10pp. Names it invents enter at most 10pp. Side and leverage still come from the model when it named the ticker. Weight does not.

Leftover after the clamp is not cash. I pour it back into the book via fillIndexLeftover. Fallback is the core. The overlay cannot delete the portfolio.

Clamp, then fill

applyLlmOverlay is TypeScript, not a prompt. It walks the union of core and overlay symbols. Each weight is clamped into [core − 10pp, core + 10pp], floored at zero. Dust gets pruned. Whatever is missing from 100% goes back into the book. That blended book is what I send to eToro.

Core vs overlay clamp

Solid bar is the blended book. Filled dot is core. Hollow dot is the raw overlay. Shaded band is the ±10pp leash. Leftover after clamp returns to the book, not cash.

Core is top momentum plus a 10% crypto sleeve and always sums to 100%.

  1. overlay 40% → book 40%
  2. overlay 30% → book 30%
  3. overlay 20% → book 20%
  4. overlay 10% → book 10%
  5. overlay 0% → book 0%
  6. overlay 0% → book 0%
  7. overlay 0% → book 0%
Raw overlay sum
100%
Blended book
100%
export const LLM_OVERLAY_MAX_DELTA = 0.1; // ±10pp
 
export function applyLlmOverlay(core: Allocation, overlay: Allocation): Allocation {
	const blended: Allocation = {};
	for (const symbol of new Set([...Object.keys(core), ...Object.keys(overlay)])) {
		const coreWeight = core[symbol] ?? 0;
		const lo = Math.max(0, coreWeight - LLM_OVERLAY_MAX_DELTA);
		const hi = coreWeight + LLM_OVERLAY_MAX_DELTA;
		const clamped = Math.min(hi, Math.max(lo, overlay[symbol] ?? 0));
		if (clamped > 0.0001) blended[symbol] = clamped;
	}
	return fillIndexLeftover(pruneDustWeights(blended), 1);
}

Drag the sliders. Zero the overlay. Invent a ticker. The sum stays one. Deterministic code prints the book. The model gets a leash.

Reject is not a veto on eToro cash

I also wired a risk-manager critic into the same eToro allocator. One job: look at a proposal and say accept, soften, or reject. On a book that is already invested, reject is the right call. Hold current. Do not churn for a model that got nervous.

On an empty eToro book, or a book sitting in cash, reject is a trap. The critic says no. The system keeps cash. The next run starts from cash. The critic says no again. Deadlock.

I tried to fix it in the prompt. "You cannot veto a cash deploy." The model ignored it on the next run, and the run after that. Prompt text is advice. The code path is the contract.

If shouldForceCashDeploy(current) is true and the critic says reject, ignore the overlay. Emit the deterministic core. Force shouldRebalance true. Cap conviction so the deploy is modest, not a swing.

if (critic.action === 'reject') {
	if (shouldForceCashDeploy(currentAllocation)) {
		return { allocation: coreAllocation, shouldRebalance: true };
	}
	return { allocation: currentAllocation, shouldRebalance: false };
}

Reject may hold current only when the book is already invested. Soften blends 60% overlay with 40% core, then re-clamps every sleeve to plus or minus ten percentage points. The critic can pull you. It cannot yank you off the rails.

Critic overlay vs the code path

Local demo. Same branch as production: reject cannot veto a cash deploy.
Current book
Critic verdict
shouldForceCashDeploy: trueshouldRebalance: trueconviction: 0.4

Current

  • cash
    100%
  • equity
    0%
  • bonds
    0%

Deterministic core

  • cash
    10%
  • equity
    55%
  • bonds
    35%

Critic overlay

  • cash
    5%
  • equity
    72%
  • bonds
    23%

Emitted allocation

  • cash
    10%
  • equity
    55%
  • bonds
    35%

Force cash deploy. Ignore the overlay. Emit the deterministic core.

Toggle an empty book versus an invested one. Hit reject. Cash-heavy: core ships, rebalance is forced. Invested: current holds.

Models do not keep promises they cannot see in the control flow. A sentence in a system prompt is a suggestion with a temperature. A branch in TypeScript is a gate. The overlay tilts. The critic comments. Neither one gets to park an eToro book in cash.


Happy coding!
Sander