trader-memory-core
Track investment theses across their lifecycle — from screening idea to closed position with postmortem. Register theses from screener outputs, manage state transitions, attach position sizing, review due dates, and generate postmortem reports with P&L and MAE/MFE analysis. Trigger when user says "r
By tradermonty · 2,020 installs
npx skills add tradermonty/claude-trading-skills --skill trader-memory-core
Source repository · Upstream listing
Trader Memory Core
Overview
Persistent state layer that bundles screening → analysis → position sizing → portfolio management outputs into a single "thesis object" per investment idea. Tracks what you thought, what happened, and what you learned — across conversations.
Phase 1 supports single ticker theses: dividend income, growth momentum, mean reversion, earnings drift, pivot breakout.
When to Use
After a screener (kanchi, earnings trade analyzer, vcp, pead, canslim, edge candidate agent) produces candidates
When transitioning a thesis from IDEA → ENTRY READY → ACTIVE → CLOSED
When attaching position sizer output to a thesis
When checking which theses are due for review
When closing a position and generating a postmortem with lessons learned
Prerequisites
Python 3.10+
pyyaml (already in project dependencies)
jsonschema (already in pyproject.toml ; required by thesis store.py and every command that imports it, including thesis ingest.py and thesis review.py )
FMP API key (optional, only for MAE/MFE calculation in postmortem)
How to invoke the CLI
Use the stdlib only launcher trader memory cli.py for all CLI work. It transparently routes through uv run project <repo when uv is available, so the repo's pinned jsonschema is reachable even from a foreign cwd or from python3 with no global jsonschema (e.g. cron / Hermes profile runs):
Subcommands: store → thesis store.py , ingest → thesis ingest.py , review → thesis review.py . Everything after the subcommand is forwarded verbatim, so existing argument flags ( state dir , transition , open position , etc.) work unchanged.
If the launcher reports that jsonschema is not importable AND uv is not on PATH , the actionable fixes (in priority order) are:
1. Install uv (https://docs.astral.sh/uv/) and re run the launcher.
2. Install the project's dependencies into the current interpreter:
Do not treat the thesis store as unavailable and do not mutate state/theses/ .yaml by hand to work around a missing dependency — schema validation is part of thesis state integrity.
Workflow
1. Register — Ingest screener output as thesis
Read the screener's JSON output and convert to thesis using the appropriate adapter.
Supported sources: kanchi dividend sop , earnings trade analyzer , vcp screener , pead screener , canslim screener , edge candidate agent , manual .
Each thesis starts in IDEA status.
For kanchi dividend sop , registration is fail closed: each row must carry
one of CLEAN PASS , PASS CAUTION , or CONDITIONAL PASS in verdict .
Missing verdicts and HOLD REVIEW / STEP1 RECHECK / FAIL rows are skipped
and never written to thesis state.
Manual brokerage entry (fractional shares)
For trades that did not come from a screener — e.g. fractional share
brokers (IBKR, Robinhood, IBI Smart, Alpaca, eToro) or hand journaling — use
the manual source with a free form JSON file (a single object or an array):
Required: ticker , thesis statement , thesis type (one of
dividend income , growth momentum , mean reversion , earnings drift ,
pivot breakout ). stop price / stop loss and target price / take profit
map to exit.stop loss / exit.take profit ; entry price / entry date / shares
are kept in origin.raw provenance — the authoritative entry price/date and
share count are set when you open the position (below). shares may be
fractional (the schema accepts any positive number). Like every adapter,
manual ingest creates an IDEA thesis only — it never mutates status
directly.
To record an already open broker position , run the explicit lifecycle
sequence (the event date flags backdate the history so it stays
chronological):
2. Query — Search and list theses
Filter by ticker , status , or type .
3. Update — Transition, attach position, link reports
Each lifecycle operation is available both as a Python function and as a
thesis store.py CLI subcommand. event date / actual date accept a
plain YYYY MM DD (widened to midnight UTC) or a full ISO timestamp.
State transition (IDEA → ENTRY READY only):
event date backdates status history.at (use it when backfilling an
existing position so the later backdated open position stays chronological).
Python: thesis store.transition(state dir, thesis id, "ENTRY READY", reason, event date=...) .
Open position (ENTRY READY → ACTIVE — the only path to ACTIVE):
shares accepts fractional quantities. Python:
thesis store.open position(state dir, thesis id, actual price, actual date, shares=..., event date=...) .
shares (and shares remaining , when present) must be a finite, positive
number no greater than 10<sup 12</sup (a sanity bound, not an economic
constraint — fractional shares below the cap remain unrestricted). NaN,
±Infinity, and absurdly large values (e.g. a malformed position sizer
report) are rejected with a clean error at save time, on open position ,
attach position , and trim alike.
For a futures thesis, use contracts instead of shares (see
"Futures positions" below) — if attach futures position already populated
the position, omit contracts and only pass actual price / actual date .
Trim — partial close (ACTIVE/PARTIALLY CLOSED → PARTIALLY CLOSED, or →
CLOSED when the whole remainder is sold):
position.shares is the original opened quantity (immutable);
position.shares remaining tracks what is still open. Each trim appends a
status history ledger entry ( shares sold / price / proceeds /
realized pnl ). outcome.pnl dollars is the cumulative realized P&L
(Σ all trims + final close); outcome.pnl pct = pnl dollars / (entry price ×
original shares) × 100 . A trim that sells the entire remainder closes the
thesis (default exit reason: manual , overridable with exit reason ).
date is the ledger timestamp (override with event date ). Python:
thesis store.trim(state dir, thesis id, shares sold, price, date, ...) .
Status invariants: ACTIVE ⇒ shares remaining == shares ;
PARTIALLY CLOSED ⇒ 0 < shares remaining < shares ; CLOSED ⇒
shares remaining == 0 . Legacy theses (no shares remaining ) are treated as
fully open at runtime.
For a futures thesis, use contracts sold instead of shares sold —
close / terminate need no flag changes; they read position.asset type and
dispatch automatically (see "Futures positions" below).
Close or invalidate (→ CLOSED or INVALIDATED):
close accepts an ACTIVE or PARTIALLY CLOSED thesis; from
PARTIALLY CLOSED it adds the final leg and reports the cumulative outcome.
Python: thesis store.terminate(state dir, thesis id, terminal status, exit reason, actual price, actual date) . For CLOSED, delegates to close() which computes P&L (fractional share aware). For INVALIDATED, P&L is computed if entry/exit prices are available.
Record review (any non terminal):
Use thesis store.mark reviewed(state dir, thesis id, review date=..., outcome="OK" "WARN" "REVIEW") to advance next review date and record alerts.
Attach position sizer output:
Python: thesis store.attach position(state dir, thesis id, report path) to link position sizing data. Validates that the report mode is "shares" (not budget).
Futures positions (contracts / multiplier / direction)
A thesis whose position.asset type == "futures" (or quantity unit ==
"contracts" ) is a futures thesis. Futures theses use quantity /
quantity remaining (whole contracts — no fractional contracts) instead of
shares / shares remaining , carry a direction ( LONG or SHORT ) and a
multiplier , and every P&L computation ( close , terminate , trim ) applies
(exit price entry price) × multiplier × quantity × sign (sign = +1
LONG, −1 SHORT) instead of the equity per unit formula. close / terminate
/ trim / open position all dispatch on position.asset type automatically
— no separate futures subcommands for those four operations. USD denominated
contracts only — there is no FX conversion in the P&L path, so a non USD
contract spec.currency is rejected outright rather than computing P&L in
the wrong currency's magnitude.
Attach a futures position sizer SIZED report (step 6 of the Shapiro
contrarian pipeline — futures position sizer → trader memory core):
Rejects a NO TRADE report ( sizing status != "SIZED" ), an invalid
direction , a non positive/fractional contracts count, a non finite/non positive
contract spec.multiplier , or a non USD contract spec.currency .
Re attach status guard is IDEA / ENTRY READY only — stricter than
equity's attach position (which also allows ACTIVE ): re attaching a
futures position on ACTIVE would silently overwrite the entire position
dict including direction , flipping the sign of every subsequent P&L
computation. Correcting an already open futures position needs a fresh
thesis (or a future dedicated "amend" operation) — not a re attach.
Direct open, no attach (build the position from CLI flags instead of a
SIZED report — contract currency is required here since there is no
contract spec to read a currency from, and must be USD ):
Trim / close / terminate — same subcommands as equity, contracts sold
in place of shares sold :
Python: thesis store.attach futures position(state dir, thesis id, report path) ,
thesis store.open position(state dir, thesis id, actual price, actual date, contracts=..., multiplier=..., direction=...) .
Link related reports:
Use thesis store.link report(state dir, thesis id, skill, file, date) to cross reference analysis documents.
4. Review — Check due dates and monitoring status
List theses with next review date <= as of . Use with kanchi dividend review monitor triggers (T1 T5) for systematic review.
5. Postmortem — Close and reflect
Generate a structured postmortem in state/journal/ . If FMP API key is available, includes MAE/MFE (Maximum Adverse/Favorable Excursion) metrics.
Summary statistics:
Shows win rate, average P&L%, and per type breakdown across all closed theses.
Output Format
Thesis YAML (state/theses/)
Each thesis is a YAML file with:
Identity: thesis id, ticker, created at
Classification: thesis type, setup type, catalyst
Lifecycle: status, status history
Entry/Exit: target prices, actual prices, conditions
Position: shares (fractional supported), value, risk (from position sizer or open position shares ); or, for futures, quantity/multiplier/direction/contract spec (from futures position sizer or open position contracts )
Monitoring: review dates, triggers, alerts
Origin: source skill, screening grade, raw provenance
Outcome: P&L, holding days, MAE/MFE, lessons learned
Index (state/theses/ index.json)
Lightweight index for fast queries without loading full YAML files.
Journal (state/journal/)
Postmortem markdown reports: pm {thesis id}.md .
Key Principles
Forward only transitions : IDEA → ENTRY READY → ACTIVE → CLOSED (no backtracking)
Raw provenance : All original screener data preserved in origin.raw provenance
Atomic writes : All file operations use tempfile + os.replace
Git tracked state : state/ directory is committed, providing audit trail
Phase 1 scope : Single ticker theses only (pair trades and options in Phase 2)
Resources
references/thesis lifecycle.md — Status states and valid transitions
references/field mapping.md — Source skill → canonical field mapping
schemas/thesis.schema.json — JSON Schema for thesis validation
../../examples/workflows/trade memory loop/sample run full path/ — Worked end to end Plan → Trade → Record → Postmortem → Backtest → Journal example