AI argues. Code settles. The losses stay on the page.
A real Hong Kong + US brokerage account, run day after day by agents that
debate every call before it happens, then settled by code the model never
touches. Every result gets published, wins and losses both. Install the same
decision workflow into your own agent, in any harness: OpenClaw, Claude Code,
Codex, DeepSeek Harness, or one you write yourself.
Live dashboard · Daily briefs · Evidence · 简体中文
“The market doesn't care how confident the model was.”
Real positions, real P&L, graded in the open. Previews refresh weekly; the live dashboard updates through the trading day.
What this is
This started as one account, not a package. A multi-agent desk debates the
evidence on a real brokerage account with separate Hong Kong and US books and
proposes trades; the account owner still places the orders. What comes out of
that is the record: real positions, a growing decision history, and a public
scorecard the model has no say in — not a get-rich bot, and not a
copy-trading service.
clawock is the part of that desk we pulled out and made reusable: an
agent-native, harness-agnostic investment decision-workflow plugin with a
verifiable harness. OpenClaw, Claude Code, Codex, DeepSeek Harness, or
another external runtime keeps the model call, the conversation, memory,
planning, tools, permissions and credentials. clawock installs the workflow on
top of that: it certifies evidence, forces an opposing case, checks the money
and FX arithmetic, links outcomes back to the decision that caused them, and
keeps every improvement proposal reviewable and reversible. Swap harnesses and
the decision contract stays put — it's just files and a CLI. Seeexamples/ for the
same run done from a pure CLI, an OpenClaw skill, a Claude Code instruction, a Codex AGENTS.md,
and a DeepSeek Harness agent.
Install it with pip install clawock, or
run it on your own book without this repository at
all. The model proposes; Python owns the prices, the risk limits, the ledger,
the settlement, and the grading.
What makes it different
- A workflow plugin, not another agent — and not another harness. The external runtime keeps its model, chat, memory, skills engine, tool loop, and permissions; clawock makes the investment-decision contract portable across runtimes and across harnesses. The harness debate (OpenClaw vs Codex vs DeepSeek Harness) is a debate clawock does not participate in.
- The loop continues after the answer. Evidence, the opposing case, thesis,
decision, execution, and observed outcome share one lineage. Measured results
can propose bounded parameter changes, but never silently rewrite strategy. - Real money, graded in public. One live Hong Kong + US brokerage account, with a public scorecard that keeps every eligible result — the losses included, and the fact that the active calls haven't beaten buy-and-hold.
- The model can't grade itself. LLMs propose trades; Python settles them and computes the scorecard.
- One thesis, one episode. Repeated opinions on the same thesis count once. Each episode is settled from canonical vendor bars, with declared gap-fill rules when a session is missing.
- The ledger has to reconcile. A money-conservation check runs before every push; if cash, positions, and P&L don't balance, nothing is published.
- Built to keep running. Scheduled Hong Kong and US sessions produce bilingual briefs and refresh the live dashboard through the trading day.
How it works
The product boundary is simple: the external agent reads and reasons; clawock
owns the portable decision workflow and the deterministic truth around it.
The KCNyu deployment then applies that product boundary to one live portfolio.
This second diagram is the deployed KCNyu desk, not the reusable package boundary.
Every trading day the system pulls fresh prices, FX, volatility, earnings and macro context plus news and social sentiment; hands that normalized context to a multi-agent debate; applies deterministic risk, schema, and ledger gates in Python; delivers a brief to WeChat; and updates the public dashboard.
The information layer
Reading the market is most of what the LLM does, so the widest part of the system is data collection. The repository catalogs 41 fetch and compute modules across 8 layers, with bilingual Hong Kong + US coverage — live quotes, SEC + Eastmoney filings, capital flow, earnings calendars, macro (VIX / DXY / 10Y), Reddit and news sentiment, and market-moving social feeds. Each brief consumes the subset relevant to that market and session. Collection stays broad; the decision layer stays constrained.
All 8 layers, row by row — modules and primary sources
| Layer | Modules | Primary sources |
|---|---|---|
| 1 · Market | 7 | Tencent · Yahoo · Eastmoney · Polygon |
| 2 · Fundamentals & filings | 3 | SEC EDGAR · Eastmoney datacenter · HKEX |
| 3 · Capital flow | 1 | Eastmoney push2his |
| 4 · News & catalysts (bilingual) | 5 | Eastmoney · Finnhub · Google News · exchange filings |
| 5 · Macro & sentiment | 3 | Yahoo · Reddit · CNN · social feeds |
| 6 · Quant & risk | 9 | deterministic math over price history |
| 7 · Book & FX integrity | 6 | Frankfurter · the reconciliation ledger · local invariants |
| 8 · Backtest & calibration | 7 | local snapshots + canonical bars |
The fetch layer degrades gracefully: every live Eastmoney call routes through one throttled gateway, critical paths (quotes, FX) use multi-source fallback, and an empty fetch keeps the prior value instead of overwriting a good series with a blank. Public sources include Tencent, stooq, yfinance, Frankfurter, SEC EDGAR, Finnhub, Nasdaq, Eastmoney, Polygon, Alpha Vantage, Reddit, and Google News — full command and provider catalog in the command reference, whose inventory is generated from the same registries this table is checked against. Which module sits in which layer is itself an artifact — config/information-layers.json, where every packaged command is either in a layer or listed with the reason it is not collection — and CI checks the table above against it, so a module that moves cannot leave its count standing.
What each run actually receives
Collection is broad, but no run gets everything. Each scheduled job's preflight assembles only the blocks that job can act on, writes them to a context file, and the model reads that file rather than fetching for itself.
sources
──► preflight (Python, deterministic)
──► context.json
──► LLM prose
──► postflight (Python)
──► publish
Pre-open gets the most: full position truth, risk, signals, the evidence
graph, research state, and it writes the day's plan. The open/midday/close
runs travel light — a fresh quote, risk only when signals demand it. Intraday
check-ins (every 30 minutes a market is open) sit in between: more signal
detail, but no research production and no evidence-graph rebuild, because that
is a daily artifact and would be stale by construction.
The full block breakdown — row by row, by cadence
| Pre-open brief | Open / midday / afternoon / close | Intraday check-in | |
|---|---|---|---|
| When | 08:00 HKT, weekdays | HK 09:30 · 12:00 · 13:30 · 16:00 · US open and close | every 30 min while a market is open |
| Blocks | 37 | 16 | 29 |
| Position truth | holdings, book totals, concentration, leverage look-through | fresh quote block | fresh quote block |
| Risk | guardrail, discipline ledger, β/vol/drawdown, breakeven math | risk section only when signals demand it | signal counts and detail |
| Signals | quant factors and their hit-rate review, cross-sectional factor, peer residual, T+0 setups | peer/sector scan | peer/sector scan, T+0 setups, anomaly flags, entry setups and early-trend candidates re-run on the open bar, price-surface opportunity radar |
| News and events | evidence graph, Chinese-language company news, catalyst calendar, macro, Reddit and social feeds | catalyst probe on flagged names | catalyst probe on flagged names |
| Research state | thesis registry, research work queue (reviews due, overdue promises, ungated positions) | thesis and red lines for flagged names | thesis and red lines for flagged names |
| History | retrospective, decision metrics, reflections, data-integrity report | — | heartbeat slot state |
| Today's plan | writes it | the morning's still-open decisions for this leg | the morning's still-open decisions for this leg |
The catalyst probe is the narrow, time-sensitive one: it fires only for names that already moved, reads exchange and regulator filings first (SEC acceptance timestamps, HKEX announcements), classifies each item as interrupt, context or noise, and states no_recent_filing explicitly rather than letting an empty block read as "nothing happened".
Influencer radar
The system scans Trump (Truth Social, first-party) and Musk (news
aggregation) one to two times a day on the HK/US session clock, then an LLM
filters the noise and links what's left to actual holdings and sectors: stance
(endorse / oppose), relevance, and a plain-language summary. Who said what,
and whether it touches your book, is already sitting in the pre-open brief —
nobody has to go scroll social media for it.
A concrete example: on 2026-08-13 Trump announced a de minimis tariff-loophole
ruling; the radar matched it to retail/e-commerce and linked it to the Hang
Seng Tech position, and the summary landed in the next day's brief. The scan
the day before (2026-08-14) found 3 posts and zero holding hits — an empty
result is published as an empty result, not skipped. What's shown above is one
hit; misses go in the brief exactly as often as they happen.
How it decides
Analysis resolves into explicit, gated strategy decisions — and one stock can carry several at once.
- Several strategies, graded separately.
core_position,risk_rebalance,intraday_t,event_trade, andtactical_entrycan coexist on the same name, because a long-term thesis and an intraday trade can legitimately disagree. Each is graded in its own episode. - Attribution-first. Every decision is tagged by its dominant driver, and that driver's edge is measured dynamically from the record — no hit rate is hard-coded into the logic.
Low-frequency add campaigns
Adding to a position needs two independent signals to agree: a price/peer
signal (factor rank plus curated-peer residual) and a separate, point-in-time
news signal (reliable positive surprise or accelerating attention) — not one
moving average mistaken for alpha. Negative information or peer-laggard
evidence blocks it outright, sizing stays capped and tranche-based (a warming
policy earns a small exploration slice, not validated authority), and a small
rank wobble can't churn permission off and on.
- Falsify, don't confirm. In a risk-on tape the default is HOLD. A bullish story doesn't trigger a buy until it clears a disconfirming check and an "is this already priced in?" test on the last few days' move.
- Regime over timing. Leverage isn't timed; a 200-day-trend × volatility dial sets the cap. The backtested lesson: the edge was in de-leveraging in the wrong regime, not in calling tops.
The debate
The daily deep brief runs a structured multi-agent debate, adapted from TradingAgents for separate Hong Kong and US books. More agents isn't the point: the protocol demands an opposing case, and the Judge attributes each resolution to a named strategy frame.
- Analyst lenses. Fundamental, technical, sentiment, and sector-rotation agents read the same context and merge into one table. Every claim must cite numeric context.
- Bull vs Bear. Two researchers build opposing cases, each citing concrete analyst data points. The protocol asks them to genuinely disagree on at least one position and to record it, so unanimous agreement reads as a flag rather than evidence.
- Risk voices + a Judge. Aggressive, Conservative, and Neutral each argue their corner. A Judge weighs them, names the strategy frame driving each decision, and resolves the argument into
plan.json— which enters the next session's grading pipeline.
The public scorecard
Every call is settled mechanically and published — wins, losses, and the cases that can't be graded. Nothing is hand-tuned after the fact.
- Record — the model submits a versioned decision with its strategy, condition, regime, size, and confidence. The authoritative ledger is
memory/decisions.jsonl. - Trigger — Python evaluates it against canonical unadjusted daily bars, counted on each market's own calendar. An unfinished session grades nothing, and a gap straight through a trigger fills at the open — never at a price that was never available.
- Group — repeated calls of the same strategy collapse into one episode, so holding a position for five mornings does not manufacture five samples.
- Grade & publish — code settles the outcome, scores it against a plain directional baseline, and renders it. Shut sessions, calls that need human evidence, and instruments that didn't trade are published as ungradeable — out of the win-rate denominator, but kept visible in the coverage count instead of silently dropped.
The model submits decisions; it can never write or amend its own evaluation. That isolation stops the desk from grading itself — it does not make the market data or the metric definitions correct. Treat the record as a diagnostic, not as proof of return.

Cumulative episode win rate against a 50% directional-hit line — how often the direction was right, not what it earned. The buy-and-hold comparison is the Shadow Portfolio under Holdings; this is a different question. Refreshed weekly by GitHub Actions; live figures are on the Holdings tab.
How the grading handles the hard cases
- Incomplete sessions & missing bars. Triggers and marks come from
memory/bars/— unadjusted daily bars from a single canonical vendor feed, not an exchange feed. An unfinished session never grades anything. - Reaffirmations. Consecutive restatements of the same strategy/action are one episode. Re-anchoring a trigger to where the stock has since moved is still a reaffirmation, not a new call.
- Episode aggregation. An episode scores as the mean of its own settled calls, not an elected member — letting the first or last call speak for the group can swing the active win rate across the 50% line on nothing but that choice.
- Confidence calibration. Stated confidence remains an audit field. A strictly prequential beta-binomial hierarchy estimates action × driver × condition × regime probabilities from earlier dates only, shrinks sparse groups toward broader priors, and abstains from signal sizing when evidence or the posterior lower bound is insufficient.
- Timing, priced separately. A single-event diagnostic asks how much better or worse the trigger fill was than that session's close, strictly paired by ticker/date/direction/shares. It deliberately never draws a cumulative money curve.
- Shadow portfolio (simulated · not live). Two cash + inventory books replay the same timeline: one follows every triggered active call, the other buys and holds. Their cumulative difference is reported as simulated timing alpha. It keeps USD and HKD separate, exposes how few calls were ever actually executed, and discloses the unadjusted-bar bias. Source:
assets/data/shadow_portfolio.json. It is a policy simulation, not a claim about what the live account earned.
What we tested, and what failed
The scorecard reports what happened. This reports what was checked — and what did not survive the check.
A layer has to clear a stated bar before it is allowed to influence a decision, and the bar is set before the result is known:
- Factor edges must have a two-way clustered bootstrap interval that does not straddle 50%. An interval that straddles it means the sample is too small, which is a different statement from "the factor does not work" — both keep it out of decisions, and the distinction is published.
- The cross-sectional layer is pre-registered. Only snapshots recorded after registration count toward activation, so a retrospective result can never switch it on.
- The leverage dial is scored out of sample: thresholds are calibrated on a leading window and graded on the next one, and its timing is tested against a null that circularly shifts the same exposure path against returns — preserving its shape and time-in-market while destroying only the alignment.
Results are published whether or not they flatter the system. The dial's permutation test is the current example: on the sample available, its timing cannot be distinguished from chance, and that is stated on the page rather than left out of it. A failure to reject is not a refutation, and the page says which one it is.
Two properties keep this from decaying into copy. The page is generated from the artifacts, so it cannot quietly drift from them. And any backtest figure quoted in the repository has to cite a run card that still contains it — a stale citation points at real evidence that no longer says what the claim says, which reads as credible and is wrong. CI fails on both.
What the code enforces
The model writes opinions. The arithmetic that could corrupt the record runs in Python and is unit-tested.
That path is covered by a large unit-test suite — it's what keeps the system stable. Currencies never sum (HKD and USD are shown separately, rate and timestamp stamped), risk caps are checked every brief (single name ≤35%, Top-2 ≤70%, portfolio β ≤3.0, stop at −18%), and a thesis moves only on new evidence, never on a price move alone.
All twelve rules, what the code actually does for each
| Rule | What the code does |
|---|---|
| Currencies never sum | HKD and USD are shown in both views with the rate + timestamp stamped; adding them naively is a meaningless number. |
| Risk caps, checked every brief | Single name ≤35%, Top-2 ≤70%, leverage-ETF sleeve ≤50%, portfolio β ≤3.0, stop at −18%. Each breach has a durable age, acknowledgement, expiring override and execution-evidence record; same-risk adds freeze until compliance. Execution stays human. |
| Concentration per leg | HHI = Σ wᵢ² per book: <0.15 ✅ · 0.15–0.25 🟡 · 0.25–0.40 🟠 · >0.40 🔴. Never blended across currencies. |
| Leverage judged by regime | A 200-day-trend × volatility dial caps the leverage-ETF sleeve (×1 / ×0.5 / ×0); daily-reset 2×/3× products skip fundamentals entirely. |
| Return on peak principal | Return % uses peak net deposits from the cash-flow ledger, not cost − realized — a realized win must not fake a higher return. |
| News needs an evidence graph | Filings, issuer/exchange news, calendars, and headlines are deduplicated into expiring event IDs. A reliable, novel, negative event with price/volume or validated peer confirmation may drive defensive action. Positive surprise or accelerating attention can only join price-relative evidence in a capped add exploration; it cannot trade alone. |
| Unproven signals get an exploration boundary | A quant factor cannot claim validated authority until it clears prospective activation. While warming up, a pre-registered interaction can collect one capped tranche per ticker/policy; the ledger |

