A lightweight Taiwan stock market backtesting system with a React web UI, supporting 6 technical strategies, parameter optimization via grid search, and 9 performance metrics.
Project Overview
LazyBacktest is a full-stack web application for backtesting Taiwan Stock Exchange (TWSE) trading strategies. The React frontend lets users select a ticker, date range, strategy, and parameters, then visualizes results as an equity curve, annual/monthly return heatmap, and 9 key metrics (CAGR, Max Drawdown, Sharpe, Sortino, etc.). The FastAPI backend fetches historical price data (local DB cache → yfinance → CSV fallback), runs backtests, and supports grid search parameter optimization ranked by Sharpe Ratio.
Technical Challenges & Solutions
Strategy Abstraction
Each strategy (SMA, RSI, MACD, KD, Bollinger Bands, Price Breakout) has different signal logic, but the backtesting engine needs a unified interface.
Solution: Designed a Strategy base class with abstract generate_signals() that each strategy implements. The backtesting engine calls generate_signals() and applies position sizing and capital management uniformly, making it trivial to add new strategies.
Grid Search Parameter Optimization
Finding the best parameter combination (e.g., SMA fast/slow period) via manual trial-and-error is tedious and unreliable.
Solution: Implemented a grid search engine that exhaustively tests all parameter combinations within user-defined ranges, runs a full backtest for each, and ranks results by Sharpe Ratio. The top N combinations are returned to the frontend for comparison.
Historical Data Reliability
yfinance API calls can fail or return incomplete data, especially for delisted TWSE tickers.
Solution: Implemented a three-tier data sourcing strategy: first query the local PostgreSQL cache, fall back to yfinance on cache miss, and finally fall back to local CSV files for tickers with known API issues. Results are written back to the cache to speed up future queries.
Architecture
Frontend: React 18 + TypeScript + Vite + TailwindCSS + Recharts, served via Docker + Nginx. Backend: Python 3.11+ + FastAPI + SQLAlchemy (ORM) + Alembic migrations + Pandas/NumPy for computation + yfinance for market data + PostgreSQL (prod) / SQLite (test) + Redis for caching. One-command start with docker-compose up --build.
Learnings
Building LazyBacktest deepened my quantitative finance knowledge and Python data-processing skills. Designing the strategy abstraction layer with decoupled entry/exit logic made adding new strategies straightforward. TDD with pytest and strict Mypy type checking caught edge cases early and made the financial calculation logic reliable.