TradeFrame · US Live · India in Build

TradeFrame — System Guide

Your two-book portfolio system, end to end. US: IndMoney, human execution (internally "Trading OS v3" in n8n). India: Kite Connect algo, in build. Built 11 Aug 2026 · last updated 25 Aug 2026.

CURRENT · v3.0
5
Open positions
45
Symbol universe
~110/800
Daily API credits
8
Live workflows
39
Config rows
14
Open items

01What you actually do

1
Read

The 6 PM digest

One Telegram message before the US open, with an audio version underneath it. Actions are at the top, always. If there's nothing to do it says so explicitly.

2
Confirm

Tap to confirm

Every stop change arrives as a ✅ button. Tap it after you've made the change in IndMoney — that's what writes it into the system's state.

3
Optional

Ask, when you want to

Send ask … for a reasoned answer against your live positions. Send a portfolio screenshot to fix any table drift.

Since v2.7 there is a fourth thing to read shadow

The 5 PM run now also runs the FRM. It executes the deterministic pre-compute first, writes a mandatory FRM SHADOW block into the brief — regime score, tonight's cash target and the reason for it, its proposals, and each candidate declined with the exact criterion it failed — logs those proposals to the scoreboard under author frm-shadow, and arms tomorrow's price conditions for Market Watch to check. The 6 PM digest carries one 🤖 FRM SHADOW summary line off the back of it.

None of that is a step for you. While frm_enabled is 0 there are no FRM buttons, no FRM alerts and nothing armed for real — read the proposals the way you would read a second opinion. One thing is asked of you: going live on 31 Aug needs at least one DEPLOY proposal you reviewed and would have tapped, so say so when you see one. See the FRM card.

02The pipeline, livenew in v2.5

The whole thing in one line

Four layers. Three of them never sleep; one of them is you.

Reflexes · n8n

Everything deterministic — reading fills out of Gmail, stop math, alerts, digests, the nightly screen. Free and around the clock.

Judgment · Claude

Everything that needs research and reasoning, on a schedule.

Memory

n8n data tables, the Claude project, a private GitHub repo — nothing evaporates.

You · action

You place orders and tap done. The broker has no API, so your finger stays on the button by design.

The pipeline, live

A closed loop. Watch it once end to end and you have the whole system. How it works · not what you hold
Workflows run 0
Rows written 0
Symbols screened 0
Telegram messages 0
TwelveData credits12 / 800
Free tier · 8 calls a minute
continuous
Two inputs from outside

01 / 11
Layers Reflex · n8n Judgment · Claude Memory · tables You · action
Shapes Workflow Data table Outside the system The loop, clockwise What is moving

Nothing here is read from your account. This diagram explains the machinery — the counters are sample volumes chosen to show what moves where. Your actual positions, stop losses, targets and watchlist live in the n8n data tables, not in this document. The counters step as the walkthrough runs. Hover or tab to any box to pin its explanation; the walkthrough pauses while you read. Every stage is written out below, in order.

  1. continuousTwo inputs from outside IndMoney emails every fill, cancel and dividend into Gmail, and TwelveData supplies prices. Those two feeds are the system's only contact with the outside world.
  2. every 15 minFill Ingest writes the ledger n8n reads the new IndMoney mail, parses each order into a trade_ledger row and adjusts cash inside positions_state. Stop fills get a 🚨 Telegram alert straight away.
  3. 19:00–01:30 IST · every 30 minMarket Watch does the stop math Through the US session it pulls prices in batches of six, reads positions_state, and works out stop proximity, exact raise-stop instructions and take-profit touches — then sends the Telegram alert and its spoken version.
  4. 16:45 ISTThe Nightly Screen The screen pulls 260 daily bars for all 45 universe symbols and rewrites screen_results. No Telegram message: this exists purely to give the brain a terminal to read.
  5. 17:00 ISTMCP hands over live state The State Export bridge serialises positions_state, trade_ledger and the fresh screen into one payload. Without it the brain would be reasoning from a memory of yesterday.
  6. 17:00 ISTThe brain researches the world Claude reads that state, then goes out for news, earnings, sector and macro, checks re-entry candidates and cash deployment, and decides what — if anything — should change. Since v2.7 it runs the FRM pre-compute first and judges from those numbers, then writes its FRM SHADOW block — regime, cash target and reason, proposals, declines — every session, qualifying candidates or not.
  7. 17:00 ISTBrief Intake writes it down Everything the brain decided comes back through the Brief Intake bridge as structured rows: daily_brief and pending_action for tonight, plus a copy in recommendations so the call can be graded later. A second, separately gated call carries the FRM's own proposals into the same scoreboard under author frm-shadow.
  8. 18:00 ISTThe digest goes out n8n reads the brief and the pending actions and sends one Telegram message — actions first, each with a ✅ button — followed by an mp3 of the same thing. An hour before the US open.
  9. 18:00–19:00 ISTYou are the executor You place the order in IndMoney yourself, then tap ✅. That tap is what writes the new stop back into positions_state — the system never assumes you acted.
  10. on the next fillAnd the loop closes Your order fills, IndMoney emails the confirmation, and Fill Ingest picks it up within fifteen minutes. Nothing in this diagram has an end — that is the whole design.
  11. 02:15 ISTThe scorer keeps it honest A side branch off memory: every recommendation that has come due at 5, 20 or 60 days is graded against what actually happened, and the grade goes back into the same table.

03The day, hour by hour

The daily loop

All times IST · 12:00 noon → 12:00 next day

Since v2.4 the whole loop runs on India time: screen, brain and digest all land before the session they describe, not a session late. Post-close, the heartbeat and scorer close the loop before the next screen.

Reflex · n8n Judgment · Claude Market gate US session Watch poll · 30 min Fill ingest · hourly
18:00
Daily Digest

Actions, brain brief, portfolio and recent fills in one message — plus a spoken version.

Hover, tap or tab to any marker to read it here. Every event's full detail is listed below — nothing is hidden behind the chart.

Every event, in full

The rail above is the shape of the day. This is the substance.

16:45
Nightly Screen n8n no telegram

Market is shut, so it reads the last completed daily bar. Screens the 45-symbol universe, writes screen_results. No Telegram message — deliberately. It exists to feed the brain.

17:00
Daily Pre-Open Brain Claude decision-maker

Reads live state plus the fresh screen, researches news, earnings, sector and macro, checks re-entry candidates, evaluates cash deployment. Since v2.7 it executes the deterministic MCP — FRM Precompute first and reasons from those numbers instead of re-deriving them, then writes a mandatory FRM SHADOW block into the brief — regime score, tonight's cash target and the reason for it, the proposals, and every candidate declined with the exact criterion it failed. Writes the full brief to Daily_Briefs.md and pushes structured actions through MCP — Brief Intake, which also logs each one into recommendations for scoring later — FRM proposals among them, under author frm-shadow so they are scored separately. Last step: MCP — FRM Arm arms tomorrow's price conditions and sweeps yesterday's. See the FRM card.

18:00
Daily Digest n8n + audio

🎯 Actions with ✅ tap-to-confirm buttons, the 🧠 brain brief, portfolio, recent fills — then a spoken version as an mp3. Lands with an hour to spare before the open. Since v2.7 it also carries one 🤖 FRM SHADOW summary line — regime, cash target, what the FRM would have proposed. One line, no buttons: nothing in it is actionable while frm_enabled is 0.

19:00
US market opens

Market Watch starts polling.

19:00–01:30
Market Watch n8n + audio every 30 min

Every 30 minutes through the session: warns when a price is within 2% of its stop, tells you exactly when and where to raise one (RAISE STOP — AVGO: 333.50 → 342.40), flags take-profit touches, and sends advisory alerts on manual_override rows. Thresholds come from system_config, not hardcoded. Prices in batches of 6 spaced a minute apart, so the free TwelveData tier is never breached — the batch now covers held and armed symbols. Since v2.7 the same pass checks the conditions the brain armed last night and records the ones that come true; while frm_enabled is 0 it cannot send anything about them.

01:30
US market closes

The daily bar for the session completes.

01:35
Market Watch heartbeat n8n text only

A session summary sent every session regardless of activity, which says "no actions outstanding" in as many words when there are none. Silence during the session now means checked and quiet, not dead. Text only, on purpose.

02:15
Recommendation Scorer n8n

Grades every brief action that has come due at 5, 20 or 60 days. Only messages you when something was actually scored.

all day
Fill ingest n8n hourly

Gmail checked hourly through US market hours plus a sweep. Any IndMoney order email is parsed into the ledger, cash is adjusted, and you get a Telegram alert — 🚨 for stop fills. Can lag up to about an hour.

1st · 07:00
Monthly Counterfactual Report Claude read-only

Every exit scored saved-vs-whipsaw against holding, cash drag, performance vs SPY and QQQ, compliance stats, improvement proposals. Goes to the project, GitHub reports/, and a digest summary.

Mon · 09:00
Weekly Review Claude read-only

The drift auditor. Writes to Notion only — never an action, never a trade. See Decision authority.

04Telegram cheat sheet

Commands — the alerts bot

Send these to US Stocks — Alerts. Nothing is case-sensitive; the leading slash is optional.

done
Tap-picker: a button for every pending stop change. No typing. Typed done AVGO 342.40 still works if you prefer.
status
All positions — price, stop, % distance to stop, pending actions.
ask <question>
+ audioClaude answers in about 20 seconds against your live positions and recent trades, then sends a spoken version. No web access — anything needing fresh news belongs in a project chat.
cash · cash set 260.67
Show or reconcile the cash balance.
chatid
Echoes your chat id. Diagnostic only.
📷 screenshot
+ audioClaude vision reads your holdings, diffs them against the system's tables, and proposes unit and cash fixes with Apply / Ignore buttons. Stops are never changed from a screenshot.
Anything else falls through to the help text — the ask prefix is required on purpose, so a stray message never burns a model call.
There is no FRM command and no FRM button. In shadow the FRM writes into the brief and nowhere else, so there is nothing here to tap and nothing armed for real. Its kill switch is a system_config row deliberately — no command, no button, no UI. See the FRM card.

The two bots

BotCarriesYou send it
US Stocks — AlertsTrade alerts, digests, brain briefs, audio notes, command repliesEverything above
Monitoring — Trading OS⚠️ Failure alerts when any n8n workflow breaks, across every project — not just tradingNothing. Read-only.
Raise-stop alerts and the digest carry the same ✅ Done / ⏰ Later buttons. Tapping ✅ means "I have made this change in IndMoney" — it writes the new stop into positions_state. Since v2.6 the tap writes the row's own current guarded level rather than whatever level the button was minted with, and tells you when the two disagree — so a button surfacing from old scrollback can never lower a stop.

05Voice notesnew in v2.5

What speaks, and what doesn't

Anything the model writes now arrives twice — as text first, then as an mp3 you can play with the phone in your pocket. Deterministic one-liners stay text-only, because reading "Stop updated for NVDA ✅" is faster than listening to it.

MessageAudioWhy
Daily Digest, 6 PMyesThe original. A composed spoken briefing, not the document read aloud.
The 🤖 FRM SHADOW line inside itunverifiedIt rides in the digest text, but the spoken script is composed separately in Build Spoken Text, which the FRM work did not change. Whether the line survives into the mp3 has not been checked against a delivered message — so this row says what is known and no more.
Market Watch alertsyesArrives mid-session when you may not be at a screen. Prices and stop levels are dictated slowly.
ask answersyesReasoning is long-form; listening beats scrolling.
Screenshot reconcile reportyesModel-generated, and worth hearing before you tap Apply.
done / status / cash / help / menusnoOne-liners. Audio would be slower than reading.
Session heartbeat, 1:35 AMnoIt fires whether or not anything happened. Nightly audio you'd never play is noise.
Nightly Screenn/aSends no Telegram message at all — it's a data source for the brain.
If the audio ever fails — an OpenAI outage, a timeout — the text still arrives. Every speech node is set to continue on error, so the voice layer can never swallow the message underneath it.

06Open items

Outstanding

14 OPEN · AS OF 24 AUG 2026
1
Refresh portfolio_meta.cash_usd

Manually maintained, goes stale silently. cash set <amount> in Telegram is the fastest fix.

2
Delete the test row in recommendations

Left over from wiring validation. It will otherwise be scored as if real.

3
OUST stop is 1.13 low

True 20-day high is 49.50, so the 15% trail should be 42.08. Currently 40.95.

4
First screen-driven brain run: Monday 18 August

The universe trend buckets decision is what unblocks it.

5
The scoreboard needs ~30 scored recommendations

Before then, any read on stop widths or entry quality is noise. Too early to conclude anything.

6
Cash at 16.4%, Layer 2 effectively empty since 10 July

Now governed by the cash-ladder and Layer 2 floor rules in system_config. Watch that they actually close the gap over the coming ladder sessions. Since v2.7 the FRM also states a target cash % and its reason every night in shadow — that is the number to read, while the ladder is still the thing that binds.

7
Disable the old desktop scheduled task

The ~6:38 PM SL/TP task in the desktop app. Fully replaced, and it only ever ran when the laptop was awake.

8
GitHub workflow backup is disabled

Repair by enabling the instance's public API on PikaPods — N8N_PUBLIC_API_DISABLED=false.

9
Alpaca parked

Revisit if annual turnover nears ₹10L, positions become whole-share, or Alpaca's GIFT City entity goes live.

10
Next frontier: an India / Zerodha system

Where trades can actually execute automatically. See the project doc India_Algo_Trading_Kickoff.md.

11
Retire the transitional prose fallback in psLevel

The guarded reader still falls back to an anchored regex for rows written before pending_stop_level existed. Delete it once the column has populated across the book — a regex cannot see negation, so "do NOT raise stop to 46" still yields 46. The guards bound the damage; the column is the real answer.

12
A staleness monitor on positions_state.last_updated

The failure monitor only ever sees a workflow that runs and fails. A trigger that stops firing at all is structurally invisible to it — the same blind spot that produced a false "Market Watch is dead" call on 18 Aug. Watch the timestamp the data carries, not the execution list.

13
A symbol absent from positions_state escapes the guards

Expand Recommendations has no row to check it against, so an unguarded level still lands in recommendations — and Apply Pending Action then silently no-ops on the write. Scoreboard noise rather than a money path, but it fails quietly, which is the pattern worth catching.

14
FRM go-live review — 31 Aug 2026

Seven shadow sessions end that Monday. The evening review is the only thing that can move frm_enabled from 0 to 1, and it is decided against the four exit criteria, not on impression. Until it happens the FRM proposes into the brief and nothing else. See the FRM card.

✓
Market Hours Gate was hardcoded to the EDT window Resolved 2026-08-21

Raised on 19 Aug as a dated deadline — correct through summer, wrong by an hour from 1 Nov 2026. Fixed two days later: the gate resolves the session in America/New_York instead, shipped with Market Watch private and checked over a 37-case boundary matrix plus a 7,200-minute old-vs-new regression with zero mismatches.

07When something looks wrong

Symptom on the left, what it actually means on the right.

No alerts all session
That is now distinguishable from a dead system — the 1:35 AM heartbeat fires either way. If the heartbeat arrived, silence was correct.
A workflow broke
Check the Monitoring — Trading OS chat first. Every workflow is wired to the global failure handler, so a break announces itself. Then the n8n executions tab.
Tables drifted from reality
Send a portfolio screenshot. Vision diff → Apply. That is always the fastest path back to truth.
Digest says "actions: none" but the brief describes an action
The reconciliation pass works — Build Digest cross-reads the brief text against the resting stops and surfaces the mismatch. But it was finding the level by matching the brain's prose, and on 18 Aug a differently-phrased action walked straight past it, so the claim that this was "structurally impossible" was too strong. The level now comes from pending_stop_level, not from wording. See the original post-mortem and the one that falsified it.
Audio arrived flat or mispronounced
The spoken script is composed separately from the text, in Build Spoken Text / Build Reply Voice / Build Alert Voice. Ticker names and shorthand expansions live there.
A number in a message looks stale
last_price comes from the last Market Watch poll — 30-minute cadence, and frozen outside US market hours.
The brief has no FRM block
The pre-compute did not answer. The run is flagged FRM_PRECOMPUTE_UNAVAILABLE and the brain carries on without it: the primary brief is unaffected, and arming is skipped entirely rather than run on stale numbers. Check MCP — FRM Precompute in the n8n executions tab.
The FRM says the calendar is clear
Check that it isn't empty. An empty macro_calendar silently yields event_clear=true in FRM Compute — indistinguishable from a genuinely quiet week, and it hands the regime score that point either way. A macro_empty flag is the fix and is not built yet.