The test a journal has to pass
A journal is useful if, and only if, it can answer this question: which of the things I do loses money, and how much. Everything in the schema below exists to make that query computable. Everything not in the schema is there because it felt like work.
That framing kills a lot of popular journal features immediately. Screenshots cannot be aggregated. Emotional narration cannot be ranked. A field you fill in but never group by is a field you should delete. The bar for including anything is that you can name the sentence it will let you write at the end of the quarter.
The full field schema
Fourteen fields, of which six are computed rather than typed. The type column matters more than it looks — anything stored as free text is a field you cannot sort, filter, or average, which means it is a field that will never change your behaviour.
| Field | Type | Entered or computed | Why it exists |
| Trade ID | Integer | Auto | Stable key for linking scale-ins, partial exits, and screenshots to one trade. |
| Date opened / closed | Date | Entered | Lets you group by regime, by month, and by day of week. Also the only way to measure holding period. |
| Symbol | Text | Entered | Cheap, and it is what lets you find the correlated-cluster problem later. |
| Direction | Enum: long / short | Entered | Short expectancy is usually worse than long expectancy and almost nobody separates them. |
| Setup tag | Enum, fixed list | Entered | The single most important field. Expectancy per setup is the whole point; expectancy per account tells you nothing actionable. |
| Planned entry | Decimal | Entered | Distinguishes the trade you intended from the trade you took. The gap between the two is a mistake tag. |
| Actual entry | Decimal | Entered | Feeds R and, differenced against planned entry, measures slippage and chasing. |
| Initial stop | Decimal | Entered before entry | Defines 1R. Entered before the fill or it is fiction. |
| Exit | Decimal | Entered | Weighted average if you scaled out. |
| Shares / contracts | Integer | Entered | Turns R into dollars and lets you check size against your own rule. |
| 1R per share | Decimal | Computed | entry − stop. The unit everything else is denominated in. |
| R-multiple result | Decimal | Computed | The output the whole system exists to produce. |
| MAE / MFE in R | Decimal ×2 | Entered or fed | Maximum adverse and favourable excursion. Diagnoses stops and exits separately. |
| Mistake tag | Enum, fixed list | Entered | One value from a short controlled list, including an explicit 'none'. |
Two optional fields earn their place once you have a few hundred trades: planned risk percentage at entry, which lets you audit whether you actually followed your own position sizing rule, and market regime as a coarse enum, which lets you check whether a setup only works in one environment.
A completed row, worked
One real-shaped trade, filled out end to end, with every computed field shown as arithmetic rather than as a result:
Symbol NVDA Direction long
Setup AVWAP reclaim (earnings anchor)
Planned in 48.00 Actual in 48.00
Initial stop 45.60 Exit 53.28
Shares 125
Computed:
1R per share = 48.00 − 45.60 = 2.40
Dollar risk = 125 × 2.40 = 300.00
Gain/share = 53.28 − 48.00 = 5.28
R-multiple = 5.28 ÷ 2.40 = +2.20R
Dollar P/L = 125 × 5.28 = +660.00
Check = 2.20R × 300.00 = +660.00 OK
MAE −0.55R (dipped to 46.68 before working)
MFE +2.45R (tagged 53.88 before the exit)
Mistake tag none
Note the check line. R × dollar risk must equal the dollar P/L, and if it does not, one of your inputs is wrong — usually the stop was moved and never re-recorded. Build that assertion into whatever tool you use. It catches the most common data-quality failure in a trading journal, which is a stop that quietly changed after entry.
Why R, not dollars
Dollars mix two different questions — was the idea good, and was the size right — into one number. R separates them. A +2R trade is a +2R trade whether you risked $50 or $500, so setups become comparable across account sizes, across instruments, and across time as the account grows.
R-multiple = (exit − entry) ÷ (entry − stop) long
R-multiple = (entry − exit) ÷ (stop − entry) short
Expectancy = Σ R ÷ number of trades
= (win rate × avg win R) − (loss rate × avg loss R)
The arithmetic behind sizing, expectancy, and break-even win rates is in the R-multiple guide, and it is worth reading before you design the schema, because R is what makes the schema aggregatable at all.
Per-setup expectancy, computed from a sample
Here is why the setup tag is non-negotiable. Take 120 closed trades across three setups. The figures below are an illustrative worked example, not a record of any account:
| Setup | Trades | Wins | Avg win | Losses | Avg loss | Total R | Expectancy |
| AVWAP reclaim | 46 | 20 | +1.90R | 26 | −0.85R | +15.90R | +0.346R |
| Breakout continuation | 44 | 15 | +2.40R | 29 | −0.95R | +8.45R | +0.192R |
| Mean reversion | 30 | 21 | +0.55R | 9 | −1.40R | −1.05R | −0.035R |
| All trades | 120 | 56 | — | 64 | — | +23.30R | +0.194R |
AVWAP: (20 × 1.90) + (26 × −0.85) = 38.00 − 22.10 = +15.90R
15.90 ÷ 46 = +0.346R per trade
Breakout: (15 × 2.40) + (29 × −0.95) = 36.00 − 27.55 = +8.45R
8.45 ÷ 44 = +0.192R per trade
Mean rev: (21 × 0.55) + (9 × −1.40) = 11.55 − 12.60 = −1.05R
−1.05 ÷ 30 = −0.035R per trade
Whole account: 23.30 ÷ 120 = +0.194R per trade
Drop mean reversion:
24.35 ÷ 90 = +0.271R per trade (+39% on the survivors)
The account-level number, +0.194R, is fine. It is also useless, because it is an average of a good setup, a mediocre one, and a losing one. The mean-reversion setup has the highest win rate in the book at 70% and is the only one losing money — exactly the trap a win-rate-headline journal walks into. Retiring it lifts expectancy on the remaining trades by 39% without learning a single new thing about the market.
Sample size, with the arithmetic
Before acting on any of those numbers, check whether they are real. Expectancy is a sample mean, so it carries a standard error of σ_R ÷ √N, where σ_R is the standard deviation of your R column. For a typical swing book σ_R lands around 1.2R. Applying that to the +0.346R AVWAP figure:
| Closed trades | Standard error | 95% CI on +0.346R | What you may conclude |
| 10 | 0.380 | −0.399 to +1.089 | Nothing at all. |
| 30 | 0.219 | −0.084 to +0.774 | Still cannot rule out zero. |
| 50 | 0.170 | +0.012 to +0.678 | Barely positive. Do not resize on this. |
| 100 | 0.120 | +0.110 to +0.580 | Probably a real edge, magnitude unknown. |
| 200 | 0.085 | +0.179 to +0.511 | Usable for sizing decisions. |
| 400 | 0.060 | +0.227 to +0.463 | Tight enough to act on confidently. |
Turn it around and the guidance gets sharper. The number of trades needed to distinguish an edge of size E from zero at 95% confidence is N = (1.96 × σ_R ÷ E)²:
σ_R = 1.2
E = +0.35R → N = (1.96 × 1.2 ÷ 0.35)² = 46 trades
E = +0.20R → N = (1.96 × 1.2 ÷ 0.20)² = 139 trades
E = +0.10R → N = (1.96 × 1.2 ÷ 0.10)² = 554 trades
E = +0.05R → N = (1.96 × 1.2 ÷ 0.05)² = 2213 trades
Small edges need enormous samples. This is not an abstraction — it is why the only setup that survived my own walk-forward testing needed 4,933 trades across a 129-symbol, 10-year universe to produce a defensible interval, and why the honest read on that result is still that it is not a validated edge. A discretionary trader taking three trades a week reaches 139 trades in about eleven months. Plan your review cadence around that arithmetic, not around the calendar.
Mistake tags: a taxonomy that stays countable
The rule is that the list is closed. Adding a new tag mid-quarter breaks every historical comparison, so define them once, define them tightly enough that you would tag the same trade the same way twice, and include an explicit none so that leaving the field blank is always a data error rather than a judgement.
| Tag | Definition (the test you apply) | Typical cause |
| chased entry | Actual entry worse than planned entry by more than 0.2R. | Fear of missing the move; no limit order. |
| moved stop | Stop widened after entry, in any amount, for any reason. | Refusing to take the planned loss. |
| oversized | Dollar risk exceeded the planned risk percentage by more than 25%. | Conviction override; arithmetic done in your head. |
| no setup | The entry does not satisfy the written criteria of any tag in your setup list. | Boredom; screen time without candidates. |
| early exit | Exited above the stop and below the planned target with no rule triggering it. | Discomfort with open profit. |
| late exit | Held past a rule-defined exit signal by more than one bar. | Hoping for a round number. |
| revenge trade | Entered within 30 minutes of a loss, in the same or a correlated name. | Trying to get it back. |
| none | The trade followed the plan. Losses tagged 'none' are the good kind. | — |
Then rank by R lost, not by frequency. Over the same 120-trade sample, the frequency ranking and the cost ranking disagree completely:
| Tag | Occurrences | Total R lost | R lost per occurrence | Share of tagged loss |
| Moved stop | 9 | −14.6R | −1.62R | 31.7% |
| Chased entry | 14 | −11.2R | −0.80R | 24.3% |
| Oversized | 3 | −6.9R | −2.30R | 15.0% |
| No setup | 7 | −5.1R | −0.73R | 11.1% |
| Early exit | 12 | −4.8R | −0.40R | 10.4% |
| Revenge trade | 2 | −3.4R | −1.70R | 7.4% |
| Total | 47 | −46.0R | — | 100% |
Chasing is the most frequent mistake and the third most expensive. Oversizing happened three times in 120 trades and cost 15% of all tagged losses, because a sizing error scales the entire outcome rather than shifting it. If you only reviewed frequency you would spend a quarter fixing your entries and never notice that three trades did most of the damage. That is also the strongest practical argument for treating the Kelly fraction as a hard ceiling rather than a target.
What MAE and MFE actually tell you
Maximum adverse excursion is the worst unrealised loss during the trade; maximum favourable excursion is the best unrealised gain. Recorded in R and grouped by outcome, they separate an entry problem from an exit problem, which is the distinction most traders never manage to make.
| Pattern | What it means | Action |
| High MAE on winners (past −0.7R routinely) | Stops sit inside normal noise; you are being shaken out of trades that work. | Widen the stop using structure or an ATR multiple, then cut share count to hold risk constant. |
| Low MFE on losers (under +0.3R) | The idea never worked at all. This is an entry problem, not an exit problem. | Tighten setup criteria or drop the setup. Do not touch the stop. |
| High MFE on losers (over +1.5R) | Trades that were working gave it all back. | Add a trailing or break-even rule. This is where scaling out genuinely helps. |
| High MFE, low realised R on winners | You are exiting early and leaving the edge behind. | Set exits by rule before entry and log deviations as 'early exit'. |
| MAE clustered just past 1R | Your stop is parked in a common reversal zone others are also using. | Re-anchor the stop off structure, not off a round percentage. |
| MAE near zero on most winners | Entries are unusually clean, or your sample is too small. | Check N before believing it. Under 30 trades this is noise. |
Where the stop should sit in the first place is a separate problem with its own logic, covered in the stop loss placement guide. MAE data tells you whether the answer you chose is working; it does not tell you what the answer should be.
The weekly review
Twenty minutes, same slot every week, with the numbers already computed before you sit down. If you are computing during the review, the review becomes a data-entry session and you will stop doing it.
- Data quality first. Every closed trade has a mistake tag, and every R × dollar-risk check reconciles. Fix that before reading a single number.
- Rank mistake tags by R lost for the trailing 20 trades. One line, no commentary.
- Compare planned versus actual risk percentage. Any trade over the rule gets named, regardless of outcome.
- Note the sample size of each setup and write 'insufficient' next to any under 30. That word is doing real work.
- Pick exactly one process change for the next 20 trades. One. Two changes at once makes the result uninterpretable.
- Write one sentence, not one page. What changes next week and how you will know it worked.
The monthly review
The monthly pass is the one that touches strategy, and it looks at things that are meaningless at weekly cadence.
- Recompute expectancy per setup tag with the standard error attached. Not the point estimate on its own — ever.
- Split long versus short expectancy. They usually differ, and most journals silently average them.
- Compare this month's per-setup expectancy against the trailing figure. A setup decaying over three consecutive months is a real signal.
- Check MAE and MFE distributions for drift. Widening MAE on winners often means the volatility regime moved, not that you got worse.
- Audit realised risk against planned risk across the whole month, and compute total open risk at the worst point.
- Retire or halve exactly one setup if the evidence supports it, and write the reason down so you cannot silently reinstate it.
When two setups disagree
Sooner or later a candidate satisfies two setup tags at once, or one setup says long while another says short on a correlated name. This is a schema problem before it is a trading problem, and the wrong fix is a new hybrid tag, which destroys the comparability of both histories.
- Define a precedence order in advance and write it into the setup list. The trade gets exactly one tag, decided by rule, not by outcome.
- Never create a combined tag retroactively. A tag that only exists after you saw the result is a curve fit with a filing system.
- If two setups fire in opposite directions on correlated names, take neither. The disagreement is information: your criteria are not as independent as you believed.
- If the overlap happens often, the two setups are one setup. Merge them and re-tag the history, once, with a note recording the date you did it.
- Log the road not taken. A 'skipped, conflicting signals' row costs nothing and tells you within a quarter whether the precedence rule is helping or costing you.
Export and portability
Whatever you use, the data must be yours in a format that outlives the tool. That means a flat CSV with one row per closed trade, ISO-8601 dates, and no formatting inside the values.
trade_id,date_open,date_close,symbol,direction,setup,
planned_entry,actual_entry,stop,exit,qty,r_per_share,
r_multiple,mae_r,mfe_r,mistake,notes
1,2026-03-04,2026-03-11,NVDA,long,avwap_reclaim,
48.00,48.00,45.60,53.28,125,2.40,
2.20,-0.55,2.45,none,earnings anchor 02-26
- One row per closed trade. Scale-ins and partial exits get their own table keyed on trade_id, not extra columns.
- Store the initial stop, never the current stop. Overwriting it destroys the R denominator and hides the 'moved stop' tag.
- Enums lowercase with underscores. 'AVWAP Reclaim' and 'avwap_reclaim' will become two setups the moment you group by that column.
- No currency symbols, no thousands separators, no percent signs. Every one of them turns a number into a string.
- Export monthly and keep the file. Broker statements reconcile to it; a hosted journal that shuts down does not.
Your broker's own export is the reconciliation source, not the journal — it has fills and fees but no planned stop, no setup tag, and no intent, which is where all the diagnostic value lives. The broker comparison in the Alpaca vs Interactive Brokers vs Robinhood guide covers which ones give you usable programmatic history.
What to ignore
Screenshots of every chart, hour-by-hour emotional narration, indicator settings you never vary, and win rate as a headline number. Win rate without reward-to-risk is decoration: 70% at +0.3R against 30% at −1R works out to (0.70 × 0.3) − (0.30 × 1.0) = −0.09R per trade. That is a losing system, and a journal that celebrates the 70% is actively harmful.
Also skip: daily profit-and-loss as a tracked metric, which encourages you to judge process by a one-day sample; equity-curve screenshots, which are decoration; and any field whose only consumer is your own sense of diligence. Consistency beats completeness. A six-field journal you fill in for 300 consecutive trades beats a twenty-field one you abandon in week five, because the entire value is in the aggregate, and an aggregate with gaps in it is not an aggregate.
I built TradeLog for exactly this shape: log the trade, get expectancy per setup with the sample size attached, no account, no server, data stays in your browser and exports to CSV. The risk toolkit takes the same numbers and turns them into a position size and a risk-of-ruin figure, and the transition problem — journalling paper trades before any of it touches real money — is covered in going from paper to live.
Educational content, not financial advice. No live profit-and-loss figures are claimed anywhere on this site; backtest and walk-forward results are always labelled as such. Full terms: /terms.html
Tools referenced in this guide