7.4 Limit and stop orders
- 7.5 Commission models
- 7.6 Slippage models
- 7.7 Why this component earns its keep
- Key Takeaways
- Action Steps
8. Performance Metrics: The Real Formulas
- 8.1 Metrics you can trust
- 8.2 Period returns and CAGR
src/metrics/performance.py
- 8.3 Sharpe ratio
- 8.4 Sortino ratio
- 8.5 Maximum drawdown
- 8.6 Win rate and profit factor
- 8.7 Turnover
Sum of absolute weight changes over the year.
- 8.8 Reporting a metric table
- Key Takeaways
- Action Steps
9. Walk-Forward Analysis
- 9.1 Why a single train/test split is not enough
- 9.2 The rolling window
src/validation/walk_forward.py
- 9.3 What you optimize
- 9.4 Reading the result
- 9.5 Avoiding leakage
- 9.6 When walk-forward is overkill
- Key Takeaways
- Action Steps
10. Look-Ahead and Survivorship Bias
- 10.1 The two biases that silently inflate backtests
- 10.2 Look-ahead bias
- 10.3 Target shift test
- 10.4 Survivorship bias
- 10.5 Point-in-time fundamentals
- 10.6 The honesty test
- Key Takeaways
- Action Steps
11. Parameter Sensitivity and the Plateau
- 11.1 A peak is not a robust edge
- 11.2 Sweeping a grid
src/validation/sensitivity.py
- 11.3 Reading the surface
- 11.4 Threshold of robustness
- 11.5 Number of parameters
- 11.6 Out-of-sample consistency
- Key Takeaways
- Action Steps
12. Monte Carlo and Stress Testing
- 12.1 Your equity curve is one path
- 12.2 Resampling trade order
src/validation/monte_carlo.py
- 12.3 Reading the distribution
- 12.4 Stress scenarios
- 12.5 Why this matters in deployment
- 12.6 Limitations
- Key Takeaways
- Action Steps
13. A Minimal Usable Engine, End to End
- 13.1 Putting it together
- 13.2 The full listing
src/minimal_engine.py
- 13.3 How to extend it
- 13.4 What it deliberately omits
- Key Takeaways
- Action Steps
14. The Trusted-Backtest Checklist
- 14.1 Run this before believing any result
- 14.2 Data
- 14.3 No look-ahead
- 14.4 Costs and fills
- 14.5 Validation
- 14.6 Risk
- 14.7 Reporting
- 14.8 The final question
- Key Takeaways
- Action Steps
15. From Backtest to Paper Trading
- 15.1 The backtest is not the strategy
- 15.2 Paper trading means
- 15.3 Logging everything
- 15.4 Comparing backtest to paper
- 15.5 What is normal
- 15.6 When to stop paper trading
- Key Takeaways
- Action Steps
16. Common Engine Bugs and How to Find Them
- 16.1 Bugs you will write
- 16.2 Order direction reversed
- 16.3 Position not updated
- 16.4 Double-shifted signal
- 16.5 Off-by-one in warm-up
- 16.6 Slippage applied only to buys
- 16.7 Commission on notional but not cash
- 16.8 Using adjusted prices for fills
- 16.9 Reconciliation test
- 16.10 The self-audit loop
- Key Takeaways
- Action Steps
17. Scaling and Optimizing Your Engine
- 17.1 When the loop gets slow
- 17.2 Profile first
- 17.3 Vectorize indicators inside the loop
- 17.4 Avoid per-bar DataFrame construction
- 17.5 When to move to a faster language
- 17.6 Parallelizing walk-forward
- 17.7 Keep the engine honest while fast
- Key Takeaways
- Action Steps
18. Closing: What a Credible Backtest Looks Like
- 18.1 You now have the pieces
- 18.2 The credible backtest has these traits
- 18.3 The next step
- 18.4 Final disclaimer
19. Designing Your Event Loop: Synchronous vs Asynchronous
- 19.1 The loop is the heart
- 19.2 Synchronous loop
- 19.3 Why not asynchronous
- 19.4 Bar-level vs tick-level
- 19.5 Order of operations within a bar
- 19.6 Multiple events per timestamp
- Key Takeaways
- Action Steps
20. Modeling Order Types Realistically
- 20.1 More than market orders
- 20.2 Market orders
- 20.3 Limit orders
- 20.4 Stop orders
- 20.5 Stop-limit orders
- 20.6 The intrabar path problem
- Key Takeaways
- Action Steps
21. Position Sizing and Risk Controls in the Engine
- 21.1 Sizing is a portfolio responsibility
- 21.2 Fixed fractional sizing
- 21.3 Volatility targeting
- 21.4 Maximum position size
- 21.5 Total heat limit
- 21.6 Drawdown circuit breaker
- Key Takeaways
- Action Steps
22. Multi-Instrument Portfolios in the Engine
- 22.1 Moving from one to many
- 22.2 Position storage
- 22.3 Order routing
- 22.4 Cash allocation
- 22.5 Correlation awareness
- 22.6 Rebalancing
- Key Takeaways
- Action Steps
23. Tax Lots and Cost Basis
- 23.1 Why tax lots matter
- 23.2 FIFO
- 23.3 Average cost
- 23.4 Which to use
- 23.5 Partial fills
- Key Takeaways
- Action Steps
24. Performance Attribution: Where Do Returns Come From?
- 24.1 A total return number hides the story
- 24.2 Market exposure (beta)
- 24.3 Timing versus selection
- 24.4 By regime
- 24.5 By trade type
- Key Takeaways
- Action Steps
25. Data Quality Monitoring in the Engine
- 25.1 Bad data quietly corrupts backtests
- 25.2 Pre-load validation
- 25.3 Gap detection
- 25.4 Outlier detection
- 25.5 In-loop checks
- 25.6 Versioning and provenance
- Key Takeaways
- Action Steps
26. Logging and Reproducibility
- 26.1 A backtest without a log is a guess
- 26.2 What to log
- 26.3 Determinism
- 26.4 Configuration files
- 26.5 A results database
- 26.6 Reproducibility checklist
- Key Takeaways
- Action Steps
27. Testing Your Engine with Synthetic Data
- 27.1 Unit tests before trust
- 27.2 Test cash math
- 27.3 Test no look-ahead
- 27.4 Test stop fills
- 27.5 Test drawdown
- 27.6 Test costs
- 27.7 Why synthetic tests matter
- Key Takeaways
- Action Steps
28. When to Use Vectorized vs Event-Driven in Practice
- 28.1 The practical decision
- 28.2 Use vectorized when
- 28.2 Use event-driven when
- 28.3 A hybrid workflow
- 28.4 The trap of premature optimization
- 28.5 The trap of vectorized false confidence
- Key Takeaways
- Action Steps
29. Common Backtesting Frameworks and When to Reach for Them
- 29.1 You do not need to write everything
- 29.2 What frameworks provide
- 29.3 When a framework helps
- 29.4 When to build your own
- 29.5 The danger of black-box frameworks
- 29.6 Recommended path
- Key Takeaways
- Action Steps
30. The Developer’s Discipline
- 30.1 Engineering is the edge
- 30.2 Version control
- 30.3 Code review
- 30.4 Modular design
- 30.5 Continuous testing
- 30.6 Document assumptions
- 30.7 The closing principle
- Key Takeaways
- Action Steps
31. Modeling Borrowing and Short Selling
- 31.1 The long-only assumption is a limitation
- 31.2 What a short position means
- 31.3 Borrow costs
- 31.4 Margin requirements
- 31.5 Short squeezes and risk
- 31.6 When to start with longs
- Key Takeaways
- Action Steps
32. Handling Corporate Actions in the Event Loop
- 32.1 Why corporate actions are events
- 32.2 A CorporateAction event
- 32.3 Processing a split
- 32.4 Processing a dividend
- 32.5 The ordering rule
- 32.6 Look-ahead risk
- Key Takeaways
- Action Steps
33. Benchmarks and Comparing Your Strategy
- 33.1 Without a benchmark, you have no scale
- 33.2 Choose the right benchmark
- 33.3 Excess returns
- 33.4 Relative drawdown
- 33.5 Benchmark timing
- 33.6 Reporting format
- Key Takeaways
- Action Steps
34. Volume and Liquidity Constraints
- 34.1 You cannot trade more than the market gives
- 34.2 Volume participation limit
- 34.3 Market impact
- 34.4 Illiquid instruments
- 34.5 Capacity
- Key Takeaways
- Action Steps
35. Intraday Data and Bar Resampling
- 35.1 Why daily bars are not always enough
- 35.2 Intraday data formats
- 35.3 Resampling
- 35.4 Time-of-day effects
- 35.5 Session and holiday handling
- 35.6 The cost of finer data
- Key Takeaways
- Action Steps
36. Stress Testing the Portfolio
- 36.1 Beyond historical averages
- 36.2 Historical stress scenarios
- 36.3 Synthetic stress scenarios
- 36.4 Reverse stress testing
- 36.5 Correlation breakdown
- 36.6 Action from stress tests
- Key Takeaways
- Action Steps
37. From Backtest to Live: The Bridge
- 37.1 The last mile
- 37.2 Data feeds
- 37.3 Order routing
- 37.4 Monitoring
- 37.5 Fail-safe defaults
- 37.6 The bridge principle
- Key Takeaways
- Action Steps
38. A Worked Example: Moving Average Crossover, Fully Modeled
- 38.1 The example
- 38.2 The setup
- 38.3 The code
Entry signal from previous bar’s close
Stop check on intrabar low
- 38.4 What to inspect
- 38.5 The lesson
- Key Takeaways
- Action Steps
39. Choosing a Broker for Programmatic Trading
- 39.1 The engine is only half the system
- 39.2 API access
- 39.3 Commission structure
- 39.4 Margin and short availability
- 39.5 Reliability
- 39.6 Data quality
- Key Takeaways
- Action Steps
40. Maintaining a Live Engine
- 40.1 The engine is a service
- 40.2 Daily checks
- 40.3 Weekly review
- 40.4 Quarterly review
- 40.5 Change management
- 40.6 When to retire
- Key Takeaways
- Action Steps
41. Walk-Forward Parameter Refinement
- 41.1 Refining, not optimizing
- 41.2 The rolling re-optimization
- 41.3 Stability of chosen parameters
- 41.4 The penalty for complexity
- 41.5 Out-of-sample aggregation
- Key Takeaways
- Action Steps
42. The Research Notebook
- 42.1 Treat research as a lab notebook
- 42.2 What to record per experiment
Each experiment is a markdown file
experiments/2026-01-15-ma-crossover.md
- 42.3 Why this matters
- 42.4 Linking to code
- 42.5 Review cadence
- Key Takeaways
- Action Steps
43. Psychological Pitfalls in Backtesting
- 43.1 The backtest is the easy part
- 43.2 Confirmation bias
- 43.3 Over-optimism from a single good run
- 43.4 Anchoring on a parameter
- 43.5 Hindsight bias
- 43.6 Sunk cost
- Key Takeaways
- Action Steps
44. Documentation for Your Engine
- 44.1 Code without documentation is a mystery
- 44.2 The README
- 44.3 Inline comments
- 44.4 The strategy brief
- 44.5 Change log
- Key Takeaways
- Action Steps
45. Comparing Your Engine to Reference Results
- 45.1 How do you know your engine is right?
- 45.2 Choose a reference
- 45.3 Reconcile differences
- 45.4 The sanity benchmark
- Key Takeaways
- Action Steps
46. Common Fill Model Errors
- 46.1 The fill model is where optimism hides
- 46.2 Filling at the close you signaled on
- 46.3 Ignoring slippage entirely
- 46.4 Limit orders always filling
- 46.5 Gap fills at the limit
- 46.6 Commission on one side
- 46.7 Volume-agnostic sizing
- Key Takeaways
- Action Steps
47. Trade Logging and Reconciliation
- 47.1 Every trade must be recorded
- 47.2 Log fields
- 47.3 Reconciliation
- 47.4 Why reconciliation matters
- Key Takeaways
- Action Steps
48. The Limits of Backtesting
- 48.1 Know what a backtest cannot tell you
- 48.1 Past is not future
- 48.2 Execution slippage is unknown
- 48.3 Your behavior is untested
- 48.4 Structural changes
- 48.5 The honest conclusion
- Key Takeaways
- Action Steps
49. A 30-Day Plan to Build Your Engine
- 49.1 From zero to a working backtest
- 49.2 Week one: skeleton
- 49.3 Week two: components
- 49.4 Week three: validation
- 49.5 Week four: robustness
- Key Takeaways
- Action Steps
50. Glossary of Engine Internals
- 50.1 A quick reference
- 50.2 Architecture terms
- 50.3 Fill terms
- 50.4 Validation terms
- 50.5 Risk terms
- Key Takeaways
- Action Steps
51. Integrating with a Vectorized Research Workflow
- 51.1 Best of both worlds
- 51.2 The screening stage
- 51.3 The validation stage
- 51.4 The deployment stage
- 51.5 Why not just use event-driven for everything?
- Key Takeaways
- Action Steps
52. Reporting Results to Stakeholders
- 52.1 If you cannot explain it, you do not understand it
- 52.2 The one-page summary
- 52.3 The equity curve
- 52.4 The trade table
- 52.5 The assumptions list
- 52.6 The caveats
- Key Takeaways
- Action Steps
53. The Honest Research Mindset
- 53.1 The most important tool is skepticism
- 53.2 Assume the backtest is wrong until proven otherwise
- 53.3 Prefer the boring conclusion
- 53.4 Kill your babies
- 53.5 Document what does not work
- 53.6 The closing principle
- Key Takeaways
- Action Steps
54. Handling Time Zones and Trading Sessions
- 54.1 The clock matters more than you think
- 54.2 Session calendars
- 54.3 Time zone alignment
- 54.4 Overnight gaps
- 54.5 After-hours data
- Key Takeaways
- Action Steps
55. Testing for Survivorship Bias in Your Data
- 55.1 The silent killer
- 55.2 Test 1: Are delisted symbols present?
Check if any symbol in your data has a delisting date
- 55.3 Test 2: Universe as of a past date
- 55.4 Test 3: Small-cap performance
- 55.5 What to do
- Key Takeaways
- Action Steps
56. The Research Pipeline as Code
- 56.1 Automate the tedious parts
- 56.2 The pipeline script
- 56.3 Reproducibility
- 56.4 Scheduling
- 56.5 Versioning results
- Key Takeaways
- Action Steps
57. Common Questions About Event-Driven Design
- 57.1 Why not just use a framework?
- 57.2 How fast does Python need to be?
- 57.3 How do I test my engine?
- 57.4 What data format should I use?
- 57.5 How do I handle multiple timeframes?
- 57.6 What if my strategy needs fundamental data?
- Key Takeaways
- Action Steps
58. Performance Attribution by Trade Type
- 58.1 Which trades make money
- 58.2 By entry reason
- 58.3 By exit reason
- 58.4 By holding period
- 58.5 The insight
- Key Takeaways
- Action Steps
59. Backtesting on a Budget
- 59.1 You do not need expensive data
- 59.1 Free data
- 59.2 Low-cost upgrades
- 59.3 Software
- 59.4 The real cost
- 59.5 When to upgrade
- Key Takeaways
- Action Steps
60. The Final Checklist: Are You Ready to Trade?
- 60.1 One last gate
- 60.2 Engine
- 60.3 Data
- 60.4 Strategy
- 60.5 Costs
- 60.6 Risk
- 60.7 Process
- Key Takeaways
- Action Steps
61. Handling Missing Data and Gaps
- 61.1 Gaps are normal, but they must be handled
- 61.2 Expected gaps
- 61.3 Unexpected gaps
- 61.4 Suspensions
- 61.5 Gaps and position marks
- Key Takeaways
- Action Steps
62. The Role of Luck in Backtest Results
- 62.1 Your best backtest might be luck
- 62.2 The number of tests
- 62.3 The sample size
- 62.4 Out-of-sample confirmation
- 62.5 The honest attitude
- Key Takeaways
- Action Steps
63. Comparing Two Backtests Fairly
- 63.1 Which strategy is better?
- 63.1 Compare on the same data
- 63.2 Compare risk-adjusted returns
- 63.3 Compare drawdowns
- 63.4 Compare turnover
- 63.5 Compare out-of-sample
- Key Takeaways
- Action Steps
64. The Ethics of Backtesting and Deployment
- 64.1 You are responsible for your claims
- 64.1 No misleading returns
- 64.2 Disclose assumptions
- 64.3 Do not sell signals
- 64.4 Respect your own risk
- 64.5 The closing thought
- Key Takeaways
- Action Steps
65. The Minimal Engine, Extended: A Worked Example
- 65.1 Putting it all together
- 65.2 The imports and events
- 65.3 The data handler
- 65.4 The portfolio
- 65.5 The loop
- Key Takeaways
- Action Steps
66. Scaling from One Symbol to a Portfolio
- 66.1 The engine must handle many instruments
- 66.1 The data alignment problem
- 66.2 The portfolio-level risk
- 66.3 The rebalance loop
- 66.4 The backtest speed
- Key Takeaways
- Action Steps
67. Reading Other People’s Backtests Critically
- 67.1 Most published backtests are not trustworthy
- 67.1 What data was used?
- 67.2 Were costs included?
- 67.3 Was there an out-of-sample period?
- 67.4 How many parameters?
- 67.5 The verdict
- Key Takeaways
- Action Steps
68. The Difference Between Simulation and Reality
- 68.1 The gap is the lesson
- 68.1 The timing gap
- 68.2 The liquidity gap
- 68.3 The data gap
- 68.4 The behavior gap
- 68.5 The lesson
- Key Takeaways
- Action Steps
69. Your Research Environment as a Product
- 69.1 Treat your tools as a product
- 69.1 Fast iteration
- 69.2 Clear logs
- 69.3 Reproducible configs
- 69.4 Version control
- Key Takeaways
- Action Steps
70. The Final Word: Build, Validate, Repeat
- 70.1 The loop never ends
- 70.1 Build
- 70.2 Validate
- 70.3 Deploy
- 70.4 Refine
- 70.5 The mindset
- Key Takeaways
- Action Steps
71. The Backtest Engineer’s Reading List
- 71.1 What to read next
- 71.1 Time series analysis
- 71.2 Risk management
- 71.3 Market microstructure
- 71.4 Machine learning for trading
- 71.5 The habit
- Key Takeaways
- Action Steps
72. Common Engine Bug Patterns
- 72.1 Bugs are where edges go to die
- 72.1 Off-by-one in signal shifting
- 72.2 Using adjusted data for unadjusted fills
- 72.3 Forgetting commission on one side
- 72.4 Position size from cash, not equity
- 72.5 Not handling multiple fills per bar
- 72.6 Survivorship in the universe
- Key Takeaways
- Action Steps
73. The Worked Example: A Complete Walk-Through
- 73.1 From idea to backtest
- 73.1 The idea
- 73.2 The mechanism
- 73.3 The rules
- 73.4 The backtest
- 73.5 The validation
- 73.6 The conclusion
- Key Takeaways
- Action Steps
74. The Research Journal: A Practical Template
- 74.1 A journal you will actually use
- 74.1 The entry format
- 74.2 Why this works
- 74.3 The monthly review
- 74.4 Link to code
- Key Takeaways
- Action Steps
75. The Backtest Engineer’s Mindset
- 75.1 The right attitude makes the engine better
- 75.1 Assume you are wrong
- 75.2 Prefer simple over complex
- 75.3 Measure twice
- 75.4 Kill quickly
- 75.5 Learn from failure
- Key Takeaways
- Action Steps
76. The Final Checklist, Expanded
- 76.1 A longer checklist for serious deployments
- 76.1 Data
- 76.2 Engine
- 76.3 Strategy
- 76.4 Costs
- 76.5 Risk
- Key Takeaways
- Action Steps
77. The Closing: Your Engine, Your Process
- 77.1 You now have everything you need
- 77.1 Build the engine
- 77.2 Validate rigorously
- 77.3 Deploy carefully
- 77.4 The reward
- 77.5 Final thought
- Key Takeaways
- Action Steps
78. The Backtest Engineer’s Toolkit
- 78.1 The tools you need
- 78.1 Core software
- 78.2 Data tools
- 78.3 Engine components
- 78.4 Reporting tools
- Key Takeaways
- Action Steps
79. The Backtest Engineer’s Daily Routine
- 79.1 What a disciplined routine looks like
- 79.1 Morning
- 79.2 Midday
- 79.3 Evening
- 79.4 Weekly
- 79.5 Monthly
- Key Takeaways
- Action Steps
80. The Final Word on Backtesting
- 80.1 This is the end of the book, not the end of the work
- 80.1 Build carefully
- 80.2 Validate honestly
- 80.3 Deploy slowly
- 80.4 The reward
- 80.5 Goodbye
- Key Takeaways
- Action Steps
81. Afterword
- 81.1 You have the tools
- 81.2 Start today
- 81.3 Stay honest
- 81.4 Good luck
- Key Takeaways
- Action Steps
82. Final Note
- 82.1 Thank you
- 82.2 The journey
- 82.3 Goodbye
- Key Takeaways
- Action Steps
Frequently Asked Questions
- Should I use an existing backtesting framework instead of building my own?
- What is the difference between vectorized and event-driven backtesting?
- Why does my backtest look great but paper trading is worse?
- How do I prevent look-ahead bias?
- What commission model should I use?
- How many parameters can I tune?
- What is a good Sharpe ratio?
- How do I handle dividends in an engine?
- What about splits?
- How much historical data do I need?
- Can I backtest options or futures with this engine?
- How do I know if my engine is correct?
- Should I trust a perfect-looking equity curve?
- What if walk-forward results are inconsistent?
- How do I calibrate slippage?
- Do I need a fast engine?
Glossary
About the Author
FREE RESOURCES
Disclaimer
How This Book Is Structured
1. Vectorized versus Event-Driven Backtesting
- 1.1 Two ways to replay history
- 1.2 Vectorized backtesting
A simplified vectorized backtest
- 1.3 The limits of vectorization
- 1.4 Event-driven backtesting
A tiny event loop skeleton
- 1.5 When to use which
- 1.6 What this book builds