Every automated system that still has a human with override permissions is not an automated system. It is a hybrid, and the human half never gets profiled.I spent years shipping trading rules I described as systematic. Entry conditions in code, stop distance in code, position size in code. And then, most days, I would do something slightly different from what the code said, because I was watching, and watching produces opinions. Skip the setup that looks weak. Flatten before the news. Take the profit early because giving it back would feel worse than never having it.None of that shows up in a trade log. A trade log records what happened. It does not record what would have happened, so the gap between the two is invisible by construction. That gap is the thing I wanted a number for.It turns out you can get one with about eighty lines of pandas against a broker CSV export. Below are three audits I run monthly, the code for each, and what they returned on a sample log. Every figure in this article comes from a synthetic 214-trade dataset built for the walkthrough, not from anyone's live account, so treat the numbers as a worked example rather than a claim about markets.The SetupYou need two things joined on a trade ID: what you did, and what the rules said to do. Most brokers export the first. The second you have to reconstruct, either from your strategy's own signal log or by replaying the rules over the same bars.The sample log has 214 trades over roughly six months. The underlying system risks a fixed dollar amount per trade, stops out at -1R, targets +2R, and produces +0.29R per trade on a 44% win rate when left alone. The human layer on top skips roughly one signal in ten, cuts winners early about a third of the time, moves the stop to breakeven once a trade is comfortably green, and occasionally sizes up after a loss.Those four behaviors are the entire difference between the two curves below, and my prior going in was that they would all be expensive. That prior was wrong in a way I found more useful than being right.Audit 1: The Intervention TaxThe headline number is a subtraction. Same signals, same bars, one curve where the rules ran untouched and one where I was in the loop.import pandas as pddf = pd.read_csv("trade_log.csv") # trade_id, sys_pnl, act_pnl, behaviourtax = df.act_pnl.sum() - df.sys_pnl.sum()print(f"system: ${df.sys_pnl.sum():,.0f}")print(f"actual: ${df.act_pnl.sum():,.0f}")print(f"tax: ${tax:,.0f} ({tax / df.sys_pnl.sum():.0%} of gross)")# same subtraction, split by what I didby_habit = (df.assign(delta=df.act_pnl - df.sys_pnl) .groupby("behaviour")["delta"] .agg(["count", "sum"]) .sort_values("sum"))print(by_habit)On the sample log, the system produced $12,337, and the executed version produced $10,939. The tax is $1,398, about 11% of gross.Eleven percent is not a catastrophe, which is exactly why nobody catches it. It does not read as a leak. It reads as a slightly disappointing six months, and the natural response to a slightly disappointing six months is to go looking for a better strategy.The breakdown is where it gets useful:habittradesdeltacut winners early26-$2,161skipped signals24-$423moved stop to breakeven38-$22sized up after a loss49+$662One habit accounts for more than the entire tax. Cutting winners early cost more than the net gap, and the other three partly offset it. Of the 26 trades I cut at +0.8R, 19 went on to hit the +2R target under the rules. The others would have come back and stopped out, which is the memory that makes the habit feel justified.The breakeven column is the one that surprised me. It is the single most argued-about habit in retail trading, and in this sample, it was worth negative twenty-two dollars across 38 trades. Not good, not bad, noise. I had assumed for years it was either saving me or killing me, and it turned out to be neither, which meant every hour I had spent thinking about it was an hour not spent on the exit rule that was actually bleeding.Sizing up after a loss made $662, and this is the trap the audit is designed to catch rather than endorse. That habit does not have positive expected value. It multiplies the size of whatever comes next, and across 49 trades the coin landed favorably. Judging a variance-increasing habit by its realised P&L over 49 samples is exactly the reasoning error the script exists to replace. The right column to look at there is not the sum; it is the worst drawdown with and without.Audit 2: Stop distance against your own MAE.The second audit asks whether a parameter you set once, probably with a round number, matches the data you have since collected.Maximum adverse excursion is how far a trade went against you before it did whatever it did next. Most platforms export it. If yours does not, join entry and exit timestamps to 1-minute bars and take the extreme in that window. Slightly overstates heat on long holds, close enough to size from.w = df[df.sys_R > 0]l = df[df.sys_R < 0]print(f"winners: median MAE {w.mae_R.median():.2f}R, " f"25th pct {w.mae_R.quantile(.25):.2f}R, " f"share past -0.70R {(w.mae_R