0. How to use these notes
- Treat this as a chapter you can print and annotate.
- Anything marked REMEMBER or CORE SENTENCE is interview material.
- If you can explain every section calmly, you cover ~80% of the “engineering workflow” angle for this role.
1. Why engineering workflow matters for a pricing library
This role is not “one clever notebook”. It is about a production library used by trading, risk, and IT every day.
Key expectations:
- Changes must be reviewed, tested, and traceable.
- The system must survive schema evolution, new products, and new desks.
- When something breaks, logs and metrics must tell you where and why.
CORE SENTENCE: “A pricing library is critical infrastructure. We treat it like a product, not like research code.”
The engineering workflow is how you:
- keep quality as the codebase grows,
- avoid regressions,
- support auditors and model risk,
- and keep the team sane.
2. Git workflow: PRs, code review, protected main
2.1 Basic branching model
You should be able to describe a simple but credible model:
main(ormaster) is protected:- no direct pushes,
- only merged PRs.
- Feature branches:
feature/new-pricer-heston,bugfix/fix-delta-sign,infra/add-ci-cache.
REMEMBER: “All changes flow through pull requests into a protected main branch.”
2.2 Pull requests and code review
What you want to say:
- Every change:
- goes through a PR,
- is reviewed by at least one other quant/dev.
- Review checks:
- correctness,
- tests,
- style,
- potential performance issues,
- consistency with architecture (no new shortcuts or global state).
You can mention:
- small PRs are easier to review and revert.
- reviewers rotate but some senior people “own” critical modules.
CORE SENTENCE: “We keep PRs small, require reviews, and use protected branches so nothing lands in main without eyes and tests.”
3. CI: tests on every PR; fail fast
3.1 Minimum CI pipeline
You should be able to describe something like:
- On every PR:
- run
pytesttest suite; - run linters (e.g.
ruff/flake8), maybe formatting check (black); - run type checks (e.g.
mypy) for critical modules.
- run
- Pipeline fails fast:
- if tests or linters fail, PR cannot be merged.
You can name-drop:
- GitHub Actions CI (fits with what you already do).
- Separate jobs:
unit-tests,linting,type-check,- maybe
integration-testson main or nightly.
REMEMBER: “Every PR triggers CI with pytest and linters. The default is: red build, no merge.”
3.2 Test strategy
You do not need an academic treatise, but be specific:
- Unit tests:
- check small, deterministic pieces:
- pricing of simple instruments under simple markets,
- validation of inputs,
- utility functions (dates, calendars).
- check small, deterministic pieces:
- Integration tests:
- end-to-end pricing flows:
- load market snapshot,
- build model,
- run pricer,
- check price/Greeks against reference values.
- end-to-end pricing flows:
- Regression tests:
- keep a set of reference trades and reference snapshots.
- freeze expected results (within numerical tolerances).
- Any change that moves those must be intentional and reviewed.
CORE SENTENCE: “We treat reference trades and snapshots as regression tests. If a change moves those numbers, it must be an intentional model decision, not an accident.”
4. Database schema and migrations (Alembic)
In this role, you will have:
- trade tables,
- market snapshot metadata,
- model calibration artefacts,
- run logs,
- maybe risk and scenario tables.
Schema will evolve. You must show you think about safe evolution.
4.1 Alembic migrations
You can say:
- We use Alembic (for Postgres / Supabase) to manage schema migrations.
- Every schema change:
- has an Alembic revision with:
- upgrade and downgrade scripts,
- clear description of purpose.
- has an Alembic revision with:
- Migrations are:
- committed to Git,
- run via CI on test DB,
- run via deployment pipeline on staging/production.
REMEMBER: “Schema changes go through Alembic migrations, not manual SQL in production.”
4.2 Backward compatibility
Deep-technical question: “How do you design migration strategy and backward compatibility?”
You can talk about:
- Additive changes first:
- add new columns as nullable,
- backfill data,
- switch application code to use new fields,
- then later make columns non-null or drop old fields.
- Rolling deployments:
- app code must work against old and new versions during rollout window.
- Data migrations:
- heavy data transformations run as background jobs, not inside the migration itself.
CORE SENTENCE: “I prefer additive, backward-compatible changes with staged rollouts: add new columns, backfill, switch code, then clean up.”
4.3 Migration safety checks
You can mention:
- Migrations tested on staging with realistic data.
- CI step that:
- runs migrations on a clean DB,
- runs tests against migrated schema.
- Rollback plan:
- ability to restore from backup for catastrophic failures.
5. Packaging and versioning
The library is not a script. It is a versioned package.
5.1 Library packaging
You can say:
- We package the library as a Python package (e.g. using
pyproject.tomlwithsetuptoolsorpoetry). - Internal apps (risk engines, services) depend on a specific version:
- pinned in
requirements.txtor similar.
- pinned in
Key idea:
- We do releases, not constant pushes to “whatever is on main”.
REMEMBER: “The pricing library is a versioned package. Risk and trading systems depend on labelled releases, not on moving Git SHA guesses.”
5.2 Versioning scheme and changelog
Semantic-ish versioning is enough:
MAJOR.MINOR.PATCH:MAJOR– breaking changes to public APIs.MINOR– new features, backward-compatible.PATCH– bug fixes, no API changes.
You want to mention:
- changelog:
- for each release:
- new features,
- bug fixes,
- known issues.
- for each release:
- Tag releases in Git:
v1.3.0, etc.
CORE SENTENCE: “We keep a changelog and tagged releases. That lets us reproduce any result by tying runs to a library version and market/model snapshots.”
6. Observability: logs, metrics, errors
You will be asked: how do you know when things break, and how do you debug?
6.1 Structured logging
Plain print is not enough.
What you should say:
- We use structured logs (JSON or key–value) with consistent fields:
run_id,trade_id,portfolio_id,market_snapshot_id,model_id,pricer_name,tenant(if multi-tenant),severity(INFO/WARN/ERROR).
- Logs go to:
- a central log system (e.g. ELK/Supabase log, etc.).
REMEMBER: “Errors should be actionable: every log line has enough context to trace which run, trade, and snapshot were involved.”
6.2 Metrics and health checks
Metrics:
- performance:
- pricing latency per trade,
- throughput of batch runs.
- failure rates:
- error counts per run,
- timeouts,
- retries.
Health:
- FastAPI health endpoints:
/healthreturning status of DB connection and essential services,- maybe
/readyvs/liveendpoints for deployment checks.
6.3 Scheduled jobs and workers
You can mention:
- scheduled jobs / workers for:
- pulling market data,
- rebuilding curves and snapshots,
- calibrating models,
- running overnight risk.
- Workers:
- separate process (e.g. Celery / RQ / custom queue) consuming jobs,
- logging run IDs and status.
CORE SENTENCE: “We treat recurring tasks as scheduled jobs with their own logs, metrics, and run IDs, not as ad-hoc scripts.”
7. Your credible proof points
You want to connect concrete tools to the ideas above. The point is: these are things you really use.
You can calmly say you have experience with:
- pytest test suites
- for both unit and integration tests.
- GitHub Actions CI
- running tests and linters on every PR.
- FastAPI REST services
- as the interface for trading/risk/IT consumers.
- Postgres / Supabase
- as the main database for trades, snapshots, and results.
- Alembic migrations
- for schema evolution with versioned scripts.
- scheduled jobs / workers
- for nightly risk, data harvesting, calibration.
REMEMBER: “These are not marketing words. They are specific tools that show I can take a model from notebook to production.”
In the interview, you can give one small example tying them together:
“For example, in my current project we expose pricing via FastAPI, backed by Postgres with Alembic migrations. Every change to the pricing logic goes through a PR with pytest in GitHub Actions, and we track run IDs and snapshot IDs in structured logs.”
8. Typical interview questions and how to answer
8.1 “How do you maintain quality as the library grows?”
Answer structure:
- Process
- PRs, code review, protected main.
- CI on every PR.
- Tests
- Unit tests for small pieces.
- Integration tests for end-to-end pricing flows.
- Regression suites with reference trades.
- Versioning & releases
- Versioned packages, changelog, tagged releases.
- Observability & feedback loop
- Logs and metrics to spot regressions in production.
- Bug reports feed back into new tests.
Sample answer (compress for speaking):
“We keep main protected behind reviewed PRs and CI. Every change runs pytest and linters. We maintain a small set of reference portfolios as regression tests, and we release the library as versioned packages with a changelog. When something breaks in production, structured logs with run IDs and snapshot IDs let us reproduce and then add new tests so the issue never returns.”
8.2 “How do you enforce coding guidelines?”
Key points:
- Automated checks:
- formatters and linters in CI (e.g.
black,ruff). - reject code that fails style or type checks.
- formatters and linters in CI (e.g.
- Code review culture:
- reviewers comment on design, not just style.
- shared guidelines documented (short, concrete).
- Examples and templates:
- show “good examples” for new pricers, new instruments, new endpoints.
Sample answer:
“We encode guidelines in tools: formatters and linters run in CI, so inconsistencies do not merge. On top of that, code review is mandatory and reviewers look at design decisions, not only syntax. For common patterns like adding a new pricer or endpoint, we keep small templates so people do not reinvent structure.”
8.3 “How do you design migration strategy and backward compatibility?”
We already touched this in §4, but compress it:
- Additive first:
- new columns/tables added in a backward-compatible way.
- Dual-read / dual-write if needed:
- temporarily support both old and new structures.
- Staged rollout:
- migrate schema, deploy code that works with both, backfill, then clean up.
- Data migration as separate jobs:
- heavy transformations done via workers, not blocking deployment.
Sample answer:
“I try to keep migrations additive and backward-compatible. For example, we add new columns as nullable, deploy code that can read and write both old and new fields, then backfill in a background job. Once everything is stable, we remove the old fields. That way, rolling deployments never hit a state where the code and schema are inconsistent.”
8.4 “How do you handle performance bottlenecks?”
Structure your answer like this:
- Measure first
- use profiling and metrics:
- per-trade latency,
- per-batch runtime,
- hotspots in code.
- use profiling and metrics:
- Basic optimisations
- vectorise computations (NumPy) instead of Python loops.
- cache reusable artefacts:
- curve interpolations,
- Cholesky decompositions,
- common MC paths.
- Architecture-level moves
- move heavy work to workers;
- use batch APIs (price many trades at once);
- pre-compute and store results where appropriate.
- Maintain correctness
- keep tests and regression checks while optimising.
- do not introduce randomised shortcuts without controls.
Sample answer:
“I start by measuring: logging per-trade and per-batch runtimes and profiling hot paths. Often the biggest wins come from vectorising inner loops and caching reusable structures like curve interpolations or Cholesky factors. At the architecture level we batch valuations and run heavy jobs on workers rather than synchronous APIs. Throughout, we keep regression tests to ensure optimisations do not change numerical results beyond acceptable tolerances.”
9. Interview cheat sheet (sentences to memorise)
If you want a 30-second recall list, these are the key lines:
Git & PRs
“Main is protected. All changes flow through reviewed PRs with CI.”
Tests & CI
“Every PR runs pytest and linters. Reference portfolios act as regression tests.”
Migrations
“Schema evolves via Alembic migrations. I prefer additive, backward-compatible changes with staged rollout.”
Packaging
“The pricing library is a versioned package with tagged releases and a changelog.”
Observability
“We use structured logs with run IDs, trade IDs, and snapshot IDs so errors are instantly traceable.”
Workers & jobs
“Recurring tasks like calibration and overnight risk run as scheduled jobs or workers with their own metrics.”
Proof stack
“I have hands-on experience with pytest, GitHub Actions, FastAPI, Postgres/Supabase, and Alembic migrations.”