Programming for quants: make the result reproducible and the mistake detectable
A notebook prints a price. You change a helper function, rerun a later cell and obtain a different number. Which inputs and which version of the model produced the original result?
Reproducibility is part of the research record. It makes a result easier to inspect, compare and challenge. Testing adds a related safeguard: it gives selected mistakes a way to become visible before they influence a conclusion.
Neither practice proves that a trading model is economically valid. A reproducible backtest can implement the wrong experiment perfectly. The useful habit is to preserve the calculation and test the assumptions that connect it to its stated purpose.
Start with a small deterministic function
Consider a present-value function for a certain future payment at a flat annual effective rate. It takes a payment, rate and maturity; it returns a price. It does not download data, change global settings or silently choose a day-count convention.
def present_value(payment, rate, years):
if rate <= -1 or years < 0:
raise ValueError('Unsupported rate or maturity')
return payment / (1 + rate) ** years
print(round(present_value(100, 0.05, 1), 6))
# 95.238095This is a specified mathematical model. A production valuation interface would need richer conventions and validation. Keeping the teaching function small makes its contract easy to read and its output easy to check independently.
Separate data access, model calculation and reporting. A change in a chart label should not rerun an unrecorded data request. A change in a pricing method should be comparable on the same saved input fixture.
Use checks with an economic reason
At zero maturity, the present value should equal the payment. At zero rate, discounting should leave a fixed payment unchanged. For a positive payment and positive maturity, increasing the rate should reduce this model's price.
These are boundary and monotonicity checks. They can reveal incorrect signs or exponents without copying the implementation into a test. A second hand-worked value, such as 100/1.05, supplies an independent numerical reference.

A test asserting that a function equals the same expression rewritten in another file may reproduce the same mistake. Prefer checks tied to identities, limits, invariants and small independently calculable cases.
For numerical quantities, define tolerances appropriate to the scale and method. Exact equality between floating-point outputs can be too strict; a broad tolerance can hide a meaningful error. An absolute tolerance and a relative tolerance answer different questions near zero and at large scales.
Randomness needs a record
If a calculation uses simulation, specify the random-number generator, seed, number of trials and sampling model. A seed helps reproduce draws within a compatible implementation; it does not describe the probability model or eliminate Monte Carlo uncertainty.
Keep the trial count alongside the estimate and an uncertainty measure. Comparing two methods on shared random draws can reduce noise in their difference, but that dependence should be deliberate and documented.
Changing the implementation can change the order in which random numbers are consumed. The same seed then need not recreate the same path-level experiment. Record versions and preserve a small deterministic fixture when exact regression comparisons matter.
Save the experiment, not only the picture
A useful run record includes the input snapshot or its content hash, model version, parameters, timing conventions and output definition. If you report a Sharpe ratio, record the return series, sampling frequency and treatment of cash and costs that produced it.
Hashes identify bytes; they do not certify that a vendor's history is point-in-time accurate. Version numbers identify software; they do not validate its financial assumptions. These records make the relevant questions answerable rather than answering them automatically.
Keep generated results separate from source data. Use a clear command to regenerate the output from a clean process. A fresh run helps expose notebooks that depend on hidden state from cells executed out of order.
Build a compact first project
Package the present-value function, a deterministic input file, a script that produces the result and a few independent checks. Add a sensitivity calculation and compare it with exact repricing. Save the assumptions beside the output.
Then extend the same structure to a small time-series experiment. The earlier programming article's availability-time check should remain a separate safeguard from the numerical price checks. Different failure modes deserve different evidence.
Until then, peace.
Go deeper with lessons, derivations and worked exercises behind this article.