The examples and architectures in this series are my personal educational, non-commercial experiments; they are not an offer of IT or consulting services.
Post #8 was about an alert that fired for no reason at all. This one is the opposite kind of blind spot: a real loss, sitting in plain view in the exchange rate the whole time, that nobody catches until someone closes the books thirty days later — by which point there's nothing left to do about it.
The invoice, the rates, and the numbers below are a composite illustration built from patterns I've seen repeat across different projects; they don't describe a specific company, currency pair, or transaction.
One invoice, one month, one blind spot
What the invoice looked like on day one — and on day thirty
A services company invoices a US client $95,000 for a project. The day the invoice goes out, the accounting system books it at that day's exchange rate — a formality nobody expects to think about again until the client pays.
| Rate | EUR value | |
|---|---|---|
| Day 1 — Invoice issued (EUR/USD 1.0750) | 1.0750 | €88,372 |
| Day 30 — Payment received (EUR/USD 1.1100) | 1.1100 | €85,586 |
| Difference — surfaced at month-end reconciliation | — | −€2,786 |
Nothing went wrong with the deal itself. The client paid in full, on time, exactly as invoiced. The dollar simply bought fewer euros on day thirty than it did on day one — and the gap between those two numbers only became visible when someone reconciled the bank receipt against the original invoice, four weeks after the rate had already moved.
Why it hides until close
An invoice gets booked once, at one rate, on one day. Nothing in a typical accounting workflow re-checks that rate while the invoice is still open — there's no daily comparison against today's market rate, no running total of what's drifting in the background. The variance only exists as a calculation, and nobody runs that calculation until the bank receipt lands and someone reconciles it against the invoice during close. By then the position is already settled. There's nothing left to manage, only something left to explain.
A currency loss doesn't announce itself. It just quietly changes the exchange rate on the one day nobody happens to be looking.
How often should you actually be watching exchange rates?
| Review frequency | What you catch | What you miss | Verdict |
|---|---|---|---|
| Monthly (month-end close) | Total realized FX gain or loss for the period | Any chance to react while the position was still open | High risk |
| Weekly | Which invoices are exposed and roughly by how much | Daily rate swings on positions still open | Acceptable |
| Daily | Today's rate against each open invoice's booked rate | Intraday volatility | Good |
| Real-time + threshold alerts | Every open position, flagged the moment it crosses a set band | Almost nothing — the drift is visible while the invoice is still open | Optimal |
What daily FX monitoring would actually have to do
None of this requires anything exotic. It needs a list of open positions and the rate each one was booked at, a daily feed of current rates, a calculation comparing the two, and a threshold that decides what's worth flagging versus what's just normal noise. That's the same shape of mechanism as the cash-flow and reporting checks earlier in this series — applied to a different number.
I put together a small script that does exactly this against sample data: it reads a CSV of open positions, compares the booked rate to a current rate, and flags anything past a set variance — nothing connected to a real account, no live trading, just the calculation itself. It sits in the same personal, non-commercial repository as the earlier demos in this series.
There's a small prototype for this
fx_monitor_agent.py reads a CSV of open FX positions and flags anything that has drifted past a set threshold since it was booked — the same logic described above, run against sample data.
Follow the series
Post #10 stays with money already in the business — cash sitting in the account, earning nothing, for reasons that have nothing to do with not knowing better.