Skip to content
➜DEPLOYED
➜cd products/tradestats
cd ../products
➜SYSTEM_BRIEFING--target=tradestats
DEPLOYED·tradestats.online

tradestats// position sizing, journal, analytics

one account cannot read another's trades. enforced in postgres. live at tradestats.online.

  • ➜
OPEN_JOURNALhow_isolation_works// free, no subscription
➜STRUCTURAL_SIGNALS--shape=stable
➜SYSTEM_SIGNALS
  • PRODUCT
    8

    Capability surfaces

    calculator · journal · analytics · strategies · expenses · patterns · settings · market pulse

  • DATA
    14

    Tables under RLS

    every one scoped to the account that wrote the row

  • BACKEND
    15

    Analytics functions

    switched to security invoker so policies apply to aggregates too

  • INVARIANT
    UTC

    Stored, then rendered local

    one instant, many clocks. calendar dates never converted.

➜TRY_THE_CORE--interactive

// this is the product, not a screenshot The sizing math below is the same calculation the app runs before every trade. Change the account, the risk percentage, or the stop, and watch the lot size move.

➜POSITION_SIZER
LONG

// lots = (balance × risk%) ÷ (stop distance × contract size)

Lot size

1.04

104,167 units

Risk
$250.00
Reward at target
$697.92
Reward : risk
2.79R
Stop distance
0.00240
Risk per lot
$240.00
1R risked2.79R sought

// illustrative. verify contract specs against your broker before risking capital.

➜SNAPSHOT--format=summary

What it is

A trading journal that starts before the trade. Size the position, take it, log what happened, then read the record by session, instrument, and hour of day. Strategies get their own track record. Funded-account fees and payouts sit next to realised P&L so the cost of trading is visible. Built for my own trading first, then opened to anyone with a Google account.

What stays private

These pages cover architecture, capability surface, and the isolation model. They do not expose schemas, policy bodies, endpoint shapes, or anything from the internal market-analysis surfaces, which are gated to a single role and are not part of what general accounts see. Nobody's trades appear here, mine included.

➜CAPABILITY_SURFACES--count=8 --preview

// preview · full breakdown on the modules route Eight surfaces ship today. Market Pulse is internal only and does not appear for general accounts. Full detail at /modules.

➜STACK_TOPOLOGY--tiers=4 --serverless
policy enforced below the client

Tier_01 // edge

// static bundle, no server of my own

Browser

React 19 SPA on Vercel. Marketing page public, everything else gated.

Tier_02 // application

// the client holds a session, never a secret

Vite // React 19

Router, calculator, journal, analytics. Bundle carries the anon key only.

Google OAuth

Supabase is the OAuth client. No password ever reaches the app.

Realtime channel

Postgres changes streamed to the dashboard for live level updates.

Tier_03 // policy

// the only place authorisation is decided

Row-level security

Every table filtered by user_id = auth.uid(). Reads and writes both.

Analytics RPCs

Security invoker, so aggregates obey the same policies as the rows.

Tier_04 // data plane

// one instant, stored once

Postgres

Trades, strategies, expenses, patterns. Every timestamp TIMESTAMPTZ.

Object storage

Chart screenshots and receipts under a per-account path prefix.

➜ invariant: user_id = auth.uid() on every row[the client is never the authority]
➜PRODUCT_PRINCIPLES--count=4
  • [01]

    The database decides

    Authorisation is a row-level security policy, not a filter in a React component. A client holding the anon key and a valid session still cannot read a row it does not own, because the check happens below the query.

  • [02]

    Size before you click

    The calculator runs first, not the journal. Risk percentage, stop distance, and contract specs produce a lot size, and that number is the whole point of the tool.

  • [03]

    One instant, many clocks

    Every timestamp is stored as UTC and rendered in the timezone on the profile. Calendar dates are never passed through a timezone, because a date the user picked is not an instant.

  • [04]

    Outcomes in R

    A trade closed at plus two hundred dollars means nothing on its own. The same trade at 2.8R against a 1R risk compares to every other trade in the record.

➜DEEP_DIVES--routes=3

// three focused routes Pick the one closest to what you actually want to know. Each is self-contained and links back to the hub.

➜enter_the_product

The product lives at tradestats.online

These pages cover how it is built. The product is deployed, free, and takes a Google account to enter. No card, no trial clock, no broker connection.