Trading journal — spreadsheet, statistics and performance review

A complete guide to building a journal spreadsheet in around 20 minutes (an indicative time for someone familiar with spreadsheet basics; the first import and data checks may take longer): 26 columns with technical names consistent with article 15.9, row formulas and a dashboard of nine metrics in two variants (Polish and English Excel; cloud spreadsheet settings are covered below), plus a starter CSV file generated in your browser. You can download the ready-made XLSX or build the spreadsheet yourself using the full instructions below. Learning the formulas helps you understand the calculations and fix them yourself; thanks to the shared column names, a CSV export from this journal, with the correct delimiter, encoding and date format selected, works with the ready-made S1–S3 script from add-on I and the script from prompt P5; audits P6–P7 require two additional columns (below).

Trading journal spreadsheet with automatic statistics — planned and actual execution columns, win rate, profit factor and expectancy formulas, and a metrics dashboard on screen
The essentials in 60 seconds
  • 26 columns in five groups: identification, context, plan vs execution, costs and results, process — with formulas only where figures are derived from other fields (slippage, r_net, execution_drag)
  • A dashboard of nine formulas: trade count, win rate, profit factor, expectancy, total R, maximum drawdown in R, average MAE/MFE, clean execution rate — performance metrics calculated from r_net and process metrics from separate columns; the scope of MAE/MFE is explained below
  • Two formula variants: Excel PL (ŚREDNIA, LICZ.JEŻELI, semicolons) and Excel EN (AVERAGE, COUNTIF, commas) — a switch and copy buttons for each block
  • Metrics describe the sample from the first entry: around 50 trades is an example review point used in the course, not a universal minimum or proof of an edge. Conclusions depend on dispersion, dependence between results and the test plan. Limit breaches or data errors require an immediate response; changing strategy rules requires a separate hypothesis and validation

Ready-made XLSX journal

Download the trading journal — XLSX EN

The file has three sheets: Statistics, Journal and Instructions, 999 prepared rows, and formulas for net P&L, R, slippage and drawdown. Columns A–Z retain the format described below; the file also includes AA–AC (self-assessment from 15.9), AD (notes), AE–AF (equity curve and drawdown) and AG (clean execution) — CSV exports for the scripts cover A:Z. Yellow cells accept data; do not overwrite calculated columns with a broker export. If swap or commission is genuinely zero, enter 0 — missing data remains missing.

The examples in this guide do not feed into the file’s statistics. Drawdown includes the starting point of 0 R: an initial loss of −1 R produces a drawdown of 1 R. Arrange trades chronologically by closing time; keep a consistent order when closing times are identical. Do not sort column C alone — the fields of each record must stay together. After reordering rows, check that AE/AF still accumulate from row 2. The additional helper column coded_clean does not treat a blank error code as clean execution.

The spreadsheet shows average MAE and MFE for all entered measurements (including zeros), while additional variants for analysing winners and losers remain below. The file calculates profit factor in R, rather than in the account currency. Fill in planned P&L in column T only for the same type of exit: compare a planned SL with an executed SL, and TP with TP. Leave it blank for an exit with no equivalent.

The PL version uses PLN in its *_pln fields. The English version has the same column order and neutral monetary field names without the _pln suffix; you specify the account currency in its instructions. When transferring CSV files between languages, map the headers and check the currency. Changing the currency label alone does not convert any values.

Ready-made spreadsheet or build your own

  • Two routes to the same journal: the ready-made XLSX contains visible formulas, and the full guide lets you recreate the spreadsheet yourself. The file has no macros or broker connection. The starter CSV is still generated locally in your browser. You will find the file version on the Instructions sheet (currently 1.2, dated 21 September 2026; the article has a separate version number).
  • You know a spreadsheet you build yourself inside out: when a formula returns an error years later (a new pair, a different export format), it is easier to identify the cause because you know what it calculates. A “magic” template breaks silently — and a journal that lies is worse than no journal.
  • Column names are shared throughout the course: the headers come from the mini CSV specification in 15.9 (the spreadsheet covers around 20 of the 29 numbered logical fields in 15.9 — missing fields are listed under Sources), and the same names are expected by the ready-made S1–S3 script from add-on I and the script from prompt P5; audits P6–P7 in the AI workshop also need a plan-compliance status and a state note — add these: status = “plan” for error_code 0, “breach” for codes 1–9, and either omit rows with code 10 (infrastructure) from the P6 export or label their status “infrastructure” and explain this in the prompt; derive the state note from the self-assessment fields (AA–AC). One format, minimal data translation between tools.
  • The cloud is convenient, but these are account data: position sizes, results, process errors. Make a deliberate choice between cloud and local storage — use the same criteria as when pasting data into AI models (the data hygiene section in add-on H).
Anatomy of a journal row: identification, context, plan versus execution, costs and results, process — the result in R is calculated from net P&L and planned risk 1. IdentificationID · times · pair direction 2. Contextsetup · class · session 3. Plan vs executionplanned/actual entry/SL/TP slippage 4. Costs and resultsswap · commission PnL · r_net 5. Processerror_code state · quality r_net = net P&L / planned risk one column feeds the entire dashboard — that is why it uses NET P&L

Structure: 26 columns in 5 groups

The column letters (A–Z) match the layout used by the formulas below — if you change the order, update the references. Keep the technical headers in English: this allows the CSV export to work with the P5 script without mapping. You can add three self-assessment fields (mental_state, sleep_hours, decision_quality from 15.9) as optional columns AA–AC (already included in the file) — the formulas do not require them.

Col.HeaderGroup 1: identificationExample
Atrade_idsequential number or platform ID2026-041
Bopen_time_utcopening date and time in UTC — MT4/MT5 exports use the broker’s server time (e.g. GMT+2/+3 — check the broker’s specification); convert from the server time zone (15.9); format YYYY-MM-DD HH:MM2026-07-08 07:42
Cclose_time_utcclosing date and time in UTC (as in B); an actual date/time value in the spreadsheet, not text. Blank = open trade, excluded from the metrics; an invalid date or a close earlier than the entered opening time produces no R2026-07-08 13:15
Dpairinstrument — 6 characters without a separator or broker suffix (EURUSD, not EUR/USD or EURUSD.m); the pip formula applies only to FX pairs (a pip is 0.0001, or 0.01 for JPY pairs — identified by the ending); for other instruments, enter the pip size from the specification and change the multiplierEURUSD
Edirectionlong / short (lowercase — the slippage formula compares text)long
Col.HeaderGroup 2: contextExample
Fsetupsetup name from the playbook (add-on E)asia-london-breakout
Gsetup_classA+ / A / B / C — playbook class at entry; the list in the file follows 15.9. Do not assign a class based on the subsequent outcomeA+
Hsessionentry session (Asia / London / NY / overlap)London
Col.HeaderGroup 3: plan vs executionExample
Iplanned_entryplanned entry (recorded BEFORE placing the order)1.0850
Jactual_entryactual fill from the platform1.0852
Kplanned_slplanned stop-loss1.0820
Lplanned_tpplanned take-profit1.0910
Mactual_exitactual closing price1.0907
Nspread_pipsspread at entry0.7
Oslippage_entry_pipsformula — entry slippage in pips, positive = worse fill2.0
Col.HeaderGroup 4: costs and resultsExample
Pswapsigned swap amount in the account currency (a cost is negative)−3.20
Qcommissioncommission as a non-negative cost; 0 if there is no commission. Convert a negative cost in the broker’s export to a positive value so the formula does not add it to profit7.00
Rbroker_gross_pnlgross P&L from the platform: after spread and price execution, before swap and commission201.67
Sbroker_net_pnlformula (or enter manually if the broker reports net P&L)191.47
Tplanned_gross_pnlplanned P&L for the same type of exit (amount): planned TP for a TP exit, planned SL for a stop exit; leave blank for a manual or time-based exit — the file then leaves W blank, while 15.9 calculates drag as the sum of entry slippage, commission and swap in R: (O × pip value + Q − P) / U, where swap P retains its sign (negative = cost) — calculated manually, outside the formula220.00
Uplanned_riskplanned risk in the account currency (USD in the examples; distance from planned entry → planned SL in pips × pip value for the planned volume). This is the fixed R denominator for the trade, with no subsequent adjustment to match the loss. It is not a guaranteed maximum loss: gaps, slippage and costs can increase it110.00
Vr_netformula — net P&L in R; the column feeding the performance metrics1.74
Wexecution_drag_Rformula — the difference between planned gross P&L and actual net P&L in R; it can be negative when the result is better than planned0.26
Col.HeaderGroup 5: processExample
Xmae_rmaximum adverse price excursion during the life of the position, in R (definition: 15.9, section 7)0.35
Ymfe_rmaximum favourable price excursion during the life of the position, in R2.10
Zerror_code0 = clean execution; 1–9 = decision error codes; 10 = infrastructure error (catalogue: 15.9)0

Row formulas — calculated columns

Formula variant:

Settings: the PL variant uses Polish function names and semicolons; EN uses English names and commas. The delimiter depends on regional settings; in Google Sheets, the function language is set separately. On import, set B/C to date and time, then check =CZY.LICZBA(C2) (EN: =ISNUMBER(C2)): the correct result is PRAWDA/TRUE. Changing the cell’s appearance alone is not enough.

Enter the formulas in row 2 and fill down (or copy them to a range). The ranges extend to row 1000 — for a longer journal, extend the row formulas, validation and every dashboard range, including the completeness checks.

O2 · slippage_entry_pips positive = a worse fill than planned; JPY pairs use a multiplier of 100
=JEŻELI(ORAZ(CZY.LICZBA(I2);CZY.LICZBA(J2);DŁ(D2)=6;LUB(E2="long";E2="short"));JEŻELI(E2="long";J2-I2;I2-J2)*JEŻELI(PRAWY(D2;3)="JPY";100;10000);"")
=IF(AND(ISNUMBER(I2),ISNUMBER(J2),LEN(D2)=6,OR(E2="long",E2="short")),IF(E2="long",J2-I2,I2-J2)*IF(RIGHT(D2,3)="JPY",100,10000),"")
S2 · broker_net_pnl if the broker reports net P&L, enter it manually and omit the formula
=JEŻELI(ORAZ(ILE.LICZB(P2:R2)=3;Q2>=0);R2+P2-Q2;"")
=IF(AND(COUNT(P2:R2)=3,Q2>=0),R2+P2-Q2,"")
V2 · r_net net P&L in R — blank until there is a closing date (C), net P&L (S) and risk (U); an open trade does not count towards the metrics
=JEŻELI(ORAZ(CZY.LICZBA(C2);CZY.LICZBA(S2);CZY.LICZBA(U2));JEŻELI(ORAZ(C2>=1;C2<2958466;U2>0;LUB(B2="";ORAZ(CZY.LICZBA(B2);B2>=1;B2<=C2)));S2/U2;"");"")
=IF(AND(ISNUMBER(C2),ISNUMBER(S2),ISNUMBER(U2)),IF(AND(C2>=1,C2<2958466,U2>0,OR(B2="",AND(ISNUMBER(B2),B2>=1,B2<=C2))),S2/U2,""),"")
W2 · execution_drag_R comparison with the planned result for the same type of exit (T) — leave T and W blank for a manual or time-based exit (15.9: in that case, drag = (O × pip value + Q − P) / U, calculated manually)
=JEŻELI(ORAZ(CZY.LICZBA(V2);CZY.LICZBA(T2));(T2-S2)/U2;"")
=IF(AND(ISNUMBER(V2),ISNUMBER(T2)),(T2-S2)/U2,"")

Dashboard: 9 metrics and how to interpret them

Paste the metrics on a separate sheet (as in the file: prefix each range with the sheet name, e.g. 'Journal'!V2:V1000) or above the table — in that case, the headers move from row 1 and you need to adjust the references. Copying a block gives you several formulas on separate lines; place each in the appropriate cell. AE2, AF2 and AG2 belong on the Journal sheet, not the Statistics sheet.

An empty journal gives N = 0, total R = 0 and maximum drawdown = 0; WR, PF, expectancy and averages without measurements remain blank. PF is also blank when there are no losses, because the ratio then has no finite value. Results in R require net P&L in S, positive U and a numeric date/time in C within Excel’s date range. If B is filled in, it must be a recognised date no later than C. Excel stores dates as numbers; cell formatting neither converts text into a date nor checks whether the time was actually entered in UTC.

File version 1.2 uses Stop-style validation for dates, direction, class, commission cost, risk, MAE/MFE and code. Pasting data can bypass validation — this is why V rejects text dates and non-positive risk, S rejects negative commission costs, and AG accepts only integer codes 0–10. Checks in rows 16–19 of Statistics show entered closes without R, trades with R but no valid code, and invalid MAE and MFE measurements. A date formula returning empty text is treated as a missing close, not an invalid closed trade. Any count above zero needs to be explained before assessing the full sample.

Performance metrics use V. Average MAE/MFE across all entered measurements use a separate sample: they include non-negative numbers, including zero, even when V is still blank. A negative number, text (including “0.5” stored as text), a space or a Boolean value in a measurement column blocks its average until resolved, instead of silently distorting the result. You will find the invalid-cell count in Statistics B18 for MAE and B19 for MFE; an error in one column does not block a valid average in the other. Do not automatically compare their sample sizes with the number of closed trades. Enter non-negative measurements for the same defined period of a position’s life; leave missing measurements blank. The winner/loser variants below select a subset based on V.

Metrics 1–5 trade count · win rate · profit factor · expectancy · total R
Trade count:  =ILE.LICZB(V2:V1000)
Win rate:           =JEŻELI(ILE.LICZB(V2:V1000)=0;"";LICZ.JEŻELI(V2:V1000;">0")/ILE.LICZB(V2:V1000))
Profit factor:      =JEŻELI(LICZ.JEŻELI(V2:V1000;"<0")=0;"";SUMA.JEŻELI(V2:V1000;">0")/-SUMA.JEŻELI(V2:V1000;"<0"))
Expectancy (R):     =JEŻELI(ILE.LICZB(V2:V1000)=0;"";ŚREDNIA(V2:V1000))
Total R:             =SUMA(V2:V1000)
Trade count:  =COUNT(V2:V1000)
Win rate:           =IF(COUNT(V2:V1000)=0,"",COUNTIF(V2:V1000,">0")/COUNT(V2:V1000))
Profit factor:      =IF(COUNTIF(V2:V1000,"<0")=0,"",SUMIF(V2:V1000,">0")/-SUMIF(V2:V1000,"<0"))
Expectancy (R):     =IF(COUNT(V2:V1000)=0,"",AVERAGE(V2:V1000))
Total R:             =SUM(V2:V1000)
Metric 6 · maximum drawdown in R helper columns AE (equity curve) and AF (current drawdown) — fill both down
AE2 (curve):       =JEŻELI(CZY.LICZBA(V2);SUMA($V$2:V2);"")
AF2 (drawdown):   =JEŻELI(CZY.LICZBA(AE2);MAX(0;$AE$2:AE2)-AE2;"")
Max drawdown (R): =MAX(AF2:AF1000)
AE2 (curve):       =IF(ISNUMBER(V2),SUM($V$2:V2),"")
AF2 (drawdown):   =IF(ISNUMBER(AE2),MAX(0,$AE$2:AE2)-AE2,"")
Max drawdown (R): =MAX(AF2:AF1000)
Metrics 7–9 · MAE/MFE and clean execution (+ average drag) audit stops, exits and process
Avg. MAE (all):  =JEŻELI(WIERSZE(X2:X1000)-LICZ.PUSTE(X2:X1000)-ILE.LICZB(X2:X1000)+LICZ.JEŻELI(X2:X1000;"<0")>0;"";JEŻELI(ILE.LICZB(X2:X1000)=0;"";ŚREDNIA(X2:X1000)))   (as in the file, B11)
Avg. MFE (all):  =JEŻELI(WIERSZE(Y2:Y1000)-LICZ.PUSTE(Y2:Y1000)-ILE.LICZB(Y2:Y1000)+LICZ.JEŻELI(Y2:Y1000;"<0")>0;"";JEŻELI(ILE.LICZB(Y2:Y1000)=0;"";ŚREDNIA(Y2:Y1000)))   (as in the file, B12)
Avg. MAE of winners:    =JEŻELI(WIERSZE(X2:X1000)-LICZ.PUSTE(X2:X1000)-ILE.LICZB(X2:X1000)+LICZ.JEŻELI(X2:X1000;"<0")>0;"";JEŻELI.BŁĄD(ŚREDNIA.JEŻELI(V2:V1000;">0";X2:X1000);""))
Avg. MFE of losers:  =JEŻELI(WIERSZE(Y2:Y1000)-LICZ.PUSTE(Y2:Y1000)-ILE.LICZB(Y2:Y1000)+LICZ.JEŻELI(Y2:Y1000;"<0")>0;"";JEŻELI.BŁĄD(ŚREDNIA.JEŻELI(V2:V1000;"<0";Y2:Y1000);""))
AG2 (coded_clean):    =JEŻELI(ORAZ(CZY.LICZBA(V2);CZY.LICZBA(Z2));JEŻELI(ORAZ(Z2>=0;Z2<=10;Z2=LICZBA.CAŁK(Z2));JEŻELI(Z2=0;1;0);"");"")
Clean execution:     =JEŻELI(ILE.LICZB(AG2:AG1000)=0;"";ŚREDNIA(AG2:AG1000))
Avg. execution drag:   =JEŻELI(ILE.LICZB(W2:W1000)=0;"";ŚREDNIA(W2:W1000))   (optional, not in the file)
Avg. MAE (all):  =IF(ROWS(X2:X1000)-COUNTBLANK(X2:X1000)-COUNT(X2:X1000)+COUNTIF(X2:X1000,"<0")>0,"",IF(COUNT(X2:X1000)=0,"",AVERAGE(X2:X1000)))   (as in the file, B11)
Avg. MFE (all):  =IF(ROWS(Y2:Y1000)-COUNTBLANK(Y2:Y1000)-COUNT(Y2:Y1000)+COUNTIF(Y2:Y1000,"<0")>0,"",IF(COUNT(Y2:Y1000)=0,"",AVERAGE(Y2:Y1000)))   (as in the file, B12)
Avg. MAE of winners:    =IF(ROWS(X2:X1000)-COUNTBLANK(X2:X1000)-COUNT(X2:X1000)+COUNTIF(X2:X1000,"<0")>0,"",IFERROR(AVERAGEIF(V2:V1000,">0",X2:X1000),""))
Avg. MFE of losers:  =IF(ROWS(Y2:Y1000)-COUNTBLANK(Y2:Y1000)-COUNT(Y2:Y1000)+COUNTIF(Y2:Y1000,"<0")>0,"",IFERROR(AVERAGEIF(V2:V1000,"<0",Y2:Y1000),""))
AG2 (coded_clean):    =IF(AND(ISNUMBER(V2),ISNUMBER(Z2)),IF(AND(Z2>=0,Z2<=10,Z2=INT(Z2)),IF(Z2=0,1,0),""),"")
Clean execution:     =IF(COUNT(AG2:AG1000)=0,"",AVERAGE(AG2:AG1000))
Avg. execution drag:   =IF(COUNT(W2:W1000)=0,"",AVERAGE(W2:W1000))   (optional, not in the file)
Completeness checks — as in Statistics B16:B19 a count above zero means entries need checking
Close without R: =WIERSZE(C2:C1000)-LICZ.PUSTE(C2:C1000)-ILE.LICZB(V2:V1000)
R without a code:       =ILE.LICZB(V2:V1000)-ILE.LICZB(AG2:AG1000)
Invalid MAE:       =WIERSZE(X2:X1000)-LICZ.PUSTE(X2:X1000)-ILE.LICZB(X2:X1000)+LICZ.JEŻELI(X2:X1000;"<0")
Invalid MFE:       =WIERSZE(Y2:Y1000)-LICZ.PUSTE(Y2:Y1000)-ILE.LICZB(Y2:Y1000)+LICZ.JEŻELI(Y2:Y1000;"<0")
Close without R: =ROWS(C2:C1000)-COUNTBLANK(C2:C1000)-COUNT(V2:V1000)
R without a code:       =COUNT(V2:V1000)-COUNT(AG2:AG1000)
Invalid MAE:       =ROWS(X2:X1000)-COUNTBLANK(X2:X1000)-COUNT(X2:X1000)+COUNTIF(X2:X1000,"<0")
Invalid MFE:       =ROWS(Y2:Y1000)-COUNTBLANK(Y2:Y1000)-COUNT(Y2:Y1000)+COUNTIF(Y2:Y1000,"<0")
Two units of R — a check example. A trade with risk U = USD 50 and net P&L of −USD 50 has a result of −1R; another with U = USD 200 and net P&L of +USD 200 has +1R. Total r_net is 0R, but the account has gained USD 150. If the plan’s base 1R was USD 100 during that period, the result measured against its limit is +1.5 base R. PF also differs: 1 in trade R, 4 in USD. These are different measures, not a contradiction. Select the period using the time zone and week boundaries specified in the plan; the journal’s source timestamps remain in UTC. The sum of closed-position results does not replace monitoring current equity or losses on open positions. If base R changes, follow the plan’s documented rule instead of dividing the entire period by an arbitrary amount from its end.
MetricHow to read the results and their limitations
Win rateOn its own, it says nothing about an edge — see the chart below. It is blank when there are no closed trades; 0% means a sample with no winners. Use it to compare results with the playbook’s assumptions, not to judge “am I good at this?”
Profit factorBelow 1.0 = a negative result in R for the sample under review; it is meaningful only alongside trade count and drawdown. No losses in the sample means division by zero, not an “infinite edge”
Expectancy (R)The journal’s most important number: average net result per trade. A positive value after costs describes this sample but does not, by itself, prove an edge. Assess dispersion, dependence between results, stability of conditions and validation results according to the testing protocol (N). The figure of 50 is an example review point, and a decision to scale up also requires compliance with the risk plan
Max drawdown (R)A measure of the full history: AF calculates drawdown from the curve’s highest peak, so it is not the week’s loss. The plan’s weekly limit (add-on E) is expressed in the plan’s base R or as a percentage of capital. Do not compare it directly with total r_net if trades had different U values. With a constant base R in the account currency, the period’s result in the plan’s unit is the sum of net P&L in S for that period divided by the base R amount. For a percentage limit, use the capital base specified in the plan. AF describes the path of cumulative trade R, not drawdown in account balance or equity. Unusual drawdown calls for a check of the data, conditions and test assumptions
Avg. MAE of winnersLow (e.g. < 0.4R) = a hypothesis that the stop is wider than necessary — to be tested on a new sample, not tightened immediately (15.9); close to 1R = winners experienced an adverse move close to the full amount of risk — check entries and stop placement before concluding that this is an execution problem
Avg. MFE of losersHigh = trades moved in your favour and then reversed — audit exit and partial profit-taking rules
Execution drag (avg.)An optional formula (above), calculated only from trades with T filled in. A persistently high value indicates a gap between planned gross P&L and actual net P&L for comparable exits: it includes costs and differences in execution prices. Manual/early exits without an equivalent do not enter this average. Do not combine it with the simplified cost estimate for those exits
Clean executionThe percentage of closed trades with error_code = 0 (column AG counts only trades with valid R and an integer code from 0 to 10; a missing code does not count as clean execution). Around 90% may be a working threshold in a particular plan, not a quality standard. Check the number of assessed trades and missing codes: 100% from one code 0 and many blank codes does not describe the entire journal. A critical breach requires action regardless of the percentage. Metrics from trades that break the rules are not a clean test of those rules
Comparison of two systems: a higher win rate of 60 percent produces negative expectancy with a poor profit-to-loss ratio, while a 40 percent win rate with 2R winners produces positive expectancy Win rate A: 60% B: 40% avg. win 0.5R · avg. loss 1R avg. win 2R · avg. loss 1R Expectancy per trade A: −0.10R B: +0.20R that is why the dashboard starts with expectancy, and you read win rate only alongside the distribution of R

Starter CSV and import

The button creates the CSV file entirely in your browser, without sending data or making a separate network request: 26 headers plus two example rows — a winner and a loser — so the formulas have data to demonstrate how they work. The PL variant uses semicolons and a decimal comma (select the delimiter explicitly when importing; double-click behaviour depends on system settings), while EN uses commas and a decimal point. After importing, replace the calculated columns (O, S, V, W) in the example rows with the formulas from the section above, and delete the examples before making your first entry (or keep them in a separate file). A CSV export may save the precision displayed by the program; in XLSX 1.2, columns V and W use six decimal places. The starter CSV also uses six decimal places, calculated from the amounts in each row. With this rounding, the error in an individual R value does not exceed 0.0000005 R; PF can be more sensitive when the sum of losses is very small. A result with an absolute value below 0.0000005 R may round to zero, changing its win/loss classification and the win rate; for such data, increase precision before exporting. For analysis that requires greater precision, increase it before export, not just later in the script.

Starter journal file generated locally, using the variant selected by the formula switch
Export to add-ons H and I, step by step: copy the headers and used rows in A:Z from the Journal sheet to a new file using “Paste values”. Set B/C to yyyy-mm-dd hh:mm (a Polish interface may display rrrr-mm-dd gg:mm), and V/W to at least six decimal places, with no thousands separator. Save as CSV UTF-8. Before combining files, check that trade_id values are unique: script S1 does not remove duplicates. Aggregate partial fills of one position according to your chosen trade unit (including costs), retaining its original U; do not count the same trade both as several fills and as a single summary. Open a copy in a text editor: check for 26 fields per record, the delimiter, UTC dates and numbers. CSV contains values, not formulas or the other sheets — keep the original XLSX. For S1, set PL: CSV_SEP=";", DECIMAL=","; EN: CSV_SEP=",", DECIMAL=".". UTF-8 with a BOM can be read as utf-8-sig.

Checking the two examples: net P&L of USD 191.47 with risk of USD 110 gives 1.740636 R; net P&L of −USD 113.10 with risk of USD 105 gives −1.077143 R. From these six-decimal values, the script should produce N = 2, WR = 50%, total 0.663493 R, expectancy 0.3317465 R, PF of approximately 1.615974852 and max DD of 1.077143 R. S2 prints rounded figures: WR 0.5; PF 1.62; expectancy 0.332 R; total 0.66 R; max DD 1.08 R. The full XLSX formulas calculate from unrounded ratios, so the last digits may differ. S1 stops the analysis on an invalid closed trade; P5 instructs the script to exclude and report that record. Compare metrics only after reconciling the sample. P5 is an instruction to generate a script, not a ready-made file with a guaranteed result.

Build it step by step

  1. Create a blank spreadsheet in Excel or LibreOffice Calc; a cloud spreadsheet will also work — but these are account data, so make a deliberate choice.
  2. Import the starter CSV (or copy the headers from the structure tables). Check that numbers have been imported as numbers — if “1.0850” appears as text, the delimiter variant does not match your system settings.
  3. Paste the row formulas into O2, S2, V2 and W2, and fill down through a reserve of rows.
  4. Paste the dashboard (metrics 1–9) above the table or on a separate sheet; fill helper columns AE, AF and AG down in the same way as the row formulas, to the last prepared row.
  5. Set a routine: make an entry after each closed trade (the EOD checklist in add-on J includes this), read the metrics at your weekly review, and make playbook decisions quarterly (add-on E).
Trading journal dashboard in a spreadsheet — cells showing win rate, profit factor, expectancy and maximum drawdown in R above the entries table, with the equity curve from a helper column alongside
Trading journal dashboard in a spreadsheet — cells showing win rate, profit factor, expectancy and maximum drawdown in R above the entries table, with the equity curve from a helper column alongside

FAQ

Excel, LibreOffice or a cloud spreadsheet?

The formulas use basic functions available in Excel, LibreOffice Calc and Google Sheets. However, the choice of function names and delimiters depends on the program and file settings: the PL variant shows Polish names and semicolons, while EN shows English names and commas. A cloud spreadsheet may require English names with semicolons. We do not claim to have tested every version of these programs. The real distinction is elsewhere: the journal contains position sizes, results and a catalogue of your errors — in the cloud, these data are subject to the provider’s policies and stored outside your own drive. This section’s rule is to keep account data local by default; use the cloud deliberately and export a backup. It is the same decision that the data hygiene section of add-on H asks you to make before pasting a journal into a chat.

How many trades do you need before the metrics mean anything?

Metrics describe the sample from the first trade; around fifty is an example working point for the first system review, not a significance threshold — earlier on, expectancy and win rate change markedly after each run and say more about that recent run than about the system; dispersion and dependence between results also matter (which is why the same number appears in add-on E’s playbook as an A+ class threshold). This does not mean the journal is useless before then: process metrics work from the first entry — clean execution rate and completeness of entries — and they determine whether the system’s figures will ever be reliable. The order is always the same: process first, then the sample, and finally system assessment.

Why have an error_code column when the result is already visible?

Because outcome and decision quality are separate dimensions: there are profitable trades that break the plan (the most dangerous case — a rewarded breach becomes reinforced) and exemplary execution that ends in a loss. Error_code 0–10 lets you calculate expectancy SEPARATELY for clean execution: if the system makes money after breaches are filtered out, that suggests the problem lies in execution rather than the rules — a difference between subgroups does not yet prove the cause; it only shows where to look. Keep code 10 (infrastructure error) separate from decision errors; procedures for these cases are in add-on K, while the catalogue of codes 1–9 is in 15.9.

My Excel will not accept the formulas — what should I check?

It is almost always one of three things. First, the variant: function language and argument delimiter are separate settings. The switch provides two common combinations (PL: Polish names + semicolons; EN: English names + commas), but check your regional settings. In Google Sheets, also check the option to use English function names. Second, the decimal separator: a system using a decimal comma will read “1.0850” as text — hence the two CSV variants. Third, quotation marks: copying through messaging apps can replace straight quotes with typographic ones — copy using the button on this page, without an intermediary. If something still will not calculate, prompt P3 from add-on H can review formulas just as readily as code.

Illustrative scenario: a “profitable” system, until the journal accounted for costs. The journal was maintained carefully, but the P&L column was copied from the platform GROSS — without commission or swaps. After a quarter, expectancy was +0.12R, leading to a decision to increase frequency: more trades = more profit. After adding cost columns and recalculating r_net from net P&L, the result was −0.04R — the system was not making money, merely turning it over, and increasing frequency deepened the loss by exactly the cost of each additional trade. Hence the firm order of columns in group 4: costs separately, net P&L separately, and r_net calculated exclusively from net P&L.
Model scenario: MAE reveals a stop too tight for the market. A trader whose win rate was clearly below what the backtest suggested suspected the broker of stop hunting. A journal with mae_r and mfe_r columns revealed a less exciting truth: on losing trades, MAE regularly ended just beyond 1.0R, while MFE for the same entries had earlier reached 1.5R+ — positions moved in the right direction, reversed, and only then hit the stop. MAE/MFE measure only the life of the position, so price action after the stop required a separate measurement over a defined window — and that measurement showed a return to the intended direction. This led to a hypothesis that the SL sat within normal price fluctuations and that the exit rules were failing to capture part of the move. ATR describes the scale of volatility but does not, by itself, establish optimal stop placement. In this model scenario, moving the stop beyond market structure and reducing volume to keep the risk amount unchanged was tested on a separate sample; only that sample’s result justified further assessment of the change. Without MAE/MFE columns, this hypothesis never emerges — all that remains is a conspiracy theory about the broker.
  • 15.9 Journal and metrics — the full field catalogue (including error codes 0–10), MAE/MFE definitions and advanced metrics (SQN, Sortino)
  • 15.10 Strategy audit — what can be inferred from metrics, and from what sample
  • Add-on I — code kit — a ready-made, tested S1–S3 script: reads this spreadsheet’s CSV export (A–Z), calculates metrics and plots the equity curve
  • Add-on H, prompts P5–P7 — a script to calculate metrics from this spreadsheet’s CSV export, plus pattern audits (P6–P7: add plan-compliance status and a state note; P7 expects weekly metrics — copy rows closed during that week to a separate sheet and calculate the same formulas there; an auto-filter alone does not change COUNT/SUM/AVERAGE results)
  • Add-on E — plan template — a playbook calibrated quarterly using figures from this journal
  • Add-on J — checklists — the EOD/EOW routine that keeps the journal in use
Disclaimer: this page is educational and is not investment advice. The formulas and structure are for measuring your own results, not predicting them; example rows and values illustrate the data format, not expected outcomes. Metrics calculated from a small sample or gross results lead to poor decisions — this is why r_net is calculated from net P&L, and system assessment requires a test plan and attention to uncertainty and dependence between results — merely exceeding 50 trades confirms nothing.

Sources

  1. Van K. Tharp, Trade Your Way to Financial Freedom, 2nd ed., McGraw-Hill 2007 — the concepts of R-multiples and expectancy as core system metrics, on which the r_net column and dashboard are based.
  2. Internal: 15.9 Journal and metrics (field structure, error codes, MAE/MFE) and 15.10 Strategy audit (disciplined inference from a sample) — 26 columns A–Z plus 3 self-assessment fields give 29 columns in the file, but the spreadsheet covers around 20 of the 29 numbered logical fields in 15.9; missing fields are regime, actual_tp, slippage_exit_pips and four that 15.9 itself asks you to add (“the spreadsheet predates this section”): lots, pip_value_at_open, strategy_version, evidence_link — if you use the script from 15.9, add these as optional columns from AH onwards to avoid overwriting existing columns AA–AG; for scripts expecting A:Z, continue to export only that range.
  3. Documentation: Microsoft — argument delimiter and CSV, Microsoft — importing and exporting CSV, Google Sheets — locale and function language. Checked on 21 September 2026; these are configuration rules, not a claim that every application has been tested.
  4. NIST — uncertainty of the mean: dependence on sample size and dispersion; this does not justify a universal threshold of 50 trades. Checked on 21 September 2026.

Map a signed broker charge before calculating R

This fresh worksheet case uses PLN in both languages so changing a label never stands in for a currency conversion. All amounts are invented. The original spreadsheet and download controls remain above; the case does not populate them.

Distinguish the export sign from the destination convention

Decision J21 has price P&L+60 PLN, a signed broker commission −4 PLN and signed financing −1 PLN. Its initial recorded risk is 50 PLN. Decision J22 has price P&L−30 PLN, commission −3 PLN, financing +1 PLN and initial risk 40 PLN. The source signs describe cash effects. The destination journal uses a positive commission-cost field and signed financing. Map those conventions before copying columns; do not subtract a negative source commission and turn a charge into income.

Reconcile each complete decision once

For J21, net cash is 60−4−1=55 PLN and R=55/50=1.1. For J22, net cash is −30−3+1=−32 PLN and R=−32/40=−0.8. Enter positive commission costs 4 and 3 in the corresponding destination field. The signed financing values remain −1 and +1. Spread already reflected in the supplied price results is not deducted again. These are complete invented decisions, not separate partial exits counted as extra trades.

Keep a missing denominator unresolved

A third closed decision, J23, has net cash −8 PLN, but its initial risk is missing. Its R cannot be reconstructed from that number alone. Do not enter zero, invent a convenient risk or quietly omit the closed decision while labelling the rest the complete sample. The two valid R values sum to 0.3R and average 0.15R; these describe only that labelled subset. Complete cash across all three decisions is 55−32−8=15 PLN. Different coverage must remain visible.

Check the import before interpreting a dashboard

Retain the original export, mapping, units and explanation of unresolved rows. Use the spreadsheet’s completeness checks and verify the relevant date, numeric and risk fields. Import formatting does not establish that a text value became the intended number or that a risk amount came from a pre-entry record. After resolving J23, recalculate the complete distribution. Until then, distinguish the known cash reconciliation from the incomplete R analysis; neither is a forecast of future performance.

Three exercises with explanations

1. What are J21’s net amount and R?

Price +60 PLN; signed commission −4; financing −1; risk 50 PLN.

  1. A. 65 PLN and 1.3R
  2. B. 60 PLN and 1.2R
  3. C. 55 PLN and 1.1R
  4. D. 55 PLN and 55R
Show the answer and explanation

C. Map source signs to the journal’s field convention before calculating.

  • A. That turns the charges into gains.
  • B. That omits separate charges.
  • C. 60−4−1=55 PLN; 55/50=1.1R.
  • D. The net amount is not already a risk multiple.

2. What R can be assigned to the third decision?

Net −8 PLN; original planned risk missing.

  1. A. Zero automatically
  2. B. −8R
  3. C. Whichever improves the average
  4. D. Unresolved until a valid risk reference is obtained
Show the answer and explanation

D. Preserve the closed cash event and the missing-data flag.

  • A. Missing evidence is not zero risk or zero outcome.
  • B. A cash value is not an R value.
  • C. The desired result is not evidence.
  • D. The required denominator is missing.

3. Which statement preserves the supplied coverage?

J21 net 55 PLN; J22−32; third −8 without risk.

  1. A. All-three cash 15 PLN; R analysis remains incomplete
  2. B. The two-row mean describes all three
  3. C. The third decision never happened
  4. D. Changing PLN to USD converts the figures
Show the answer and explanation

A. Report both scope and units beside a metric.

  • A. 55−32−8=15 PLN; the missing risk still blocks a complete R distribution.
  • B. The subset excludes a closed decision.
  • C. Missing risk does not erase its cash effect.
  • D. A label change performs no conversion.

Return to the tool

Jarosław Wasiński

Editor-in-chief, ForexMechanics.com • Macro & FX analyst

Independent analyst and practitioner with over 20 years of experience in financial markets. Actively involved in Forex since 2007, with a focus on fundamental analysis, OTC market structure, and disciplined capital risk management.

  • Creator and editor-in-chief of MyBank.pl, providing reliable financial education since 2004.
  • Author of hundreds of in-depth market commentaries, structural analyses, and educational materials for traders and investors.
  • Advocate for market transparency, promoting education grounded in hard data and institutional reports (BIS, ESMA, CFTC).

All content is educational and informational only – it does not constitute investment advice or a recommendation. Remember: leveraged trading (Forex/CFD) carries a high risk of rapid capital loss.