Hemp was a great time for me to work with my hands, make products, and develop processes.   Yet, I really missed using the computational skill I built as a postdoc and, during this time, identified quantitative finance as a hobby to keep those neurons firing.  


My self-study started with both esoteric and basic concepts of finance, but quickly expanded to learning Python and building my own systematic trading strategies.  I have enjoyed some successes, learned from failures am excited to continue the work on my own (or even in a formal QF setting!).  At this stage, I'm beginning to incorporate machine learning models into my trading algorithms, expecting the experience will also feed back into my skill as a physical process modeler.


Before proceeding, please understand that I have no professional financial certifications, the following writeup should not be taken as advice, and that past performance is not necessarily indicative of future results.  With that said, below are milestones of my path through QF that I believe are worth sharing.  Enjoy!


The first book I read was Theory of Financial Risks by Bouchaud & Potters.  Quickly the material becomes pretty dense, especially for someone like myself whose mathematical experience centers more around physical applications of differential equations.  ‘Fat tails’ is the idea that motivated me to try my own hand at modeling equity returns.  As it turns out, Gaussian distributions typically falter at capturing exceptionally large returns and concepts such as Levy distributions, Pareto tails, power law tails, and Stable distributions are better suited to capture the impact of extreme events.  I thought incorporating this into my (eventual) trading algorithms could make the difference, so this is where I started!

Comparison between Gaussian & Stable distribution model fits to 20 years of historical S&P500 returns.  Distributions obtained as the PDFs complementary to the CDFs fit to sorted returns (see right panel).

Stable CDF fit to sorted returns made by optimizing α, β, γ, δ in (2).  Two parameter Gaussian CDF (erf) fit by least-squares minimization.

These figures were generated by a MATLAB code I wrote using data downloaded from Yahoo Finance with Python (1).  Shown are representations of the SPY ETF daily returns (that tracks the S&P500) for the past 20 years.  The panel on the left shows a histogram of (normalized) returns, evaluated from the downloaded price history, and both Gaussian and Stable distribution fits.  Gaussian distributions are limiting cases of Stable distributions, which can’t be written in neat closed forms, but nevertheless are computationally tractable and apparently useful:  In the (left) probability distribution representation, the Stable distribution better captures the low, but finite probabilities of extreme-valued returns than the Gaussian.  The discrepancy is much more dramatic on the right which presents both halves of the cumulative distribution function of returns and the associated model CDFs on log-log scale.


With codes for stable distribution fits up and running, I first backtested trading strategies that executed trades following low probability, large losses.    These strategies did not generate profound results, but nevertheless drove development of programming mechanics needed for backtesting strategies:  entering/exiting trades and evaluating strategy performance.  Soon, I extended these mechanics to new strategies that didn’t utilize stable distributions.  Although stable distributions perform better at modeling returns, they did not seem to significantly impact my entry-level systematic strategies.  Occasionally, I returned to the book by Bouchaud and Potters, finding myself increasingly able to follow concepts, such as extension of Black-Scholes option pricing/hedging from Gaussian to Stable returns.  I remain open to applying such concepts to strategies, but, for now, am content to apply the ‘simpler is better’ mantra, with which I have both achieved success and learned basic practical features of implementing backtested strategies.


The first strategy I found success with was based on so-called ‘Bollinger bands’ — which set trade entry & exit levels according to tunable distance (# of standard deviations) from a moving average of the price.  Thus there exist four parameters: the security of interest, the entry and exit band levels, and the moving average duration.  Normally, I would optimize performance (e.g. daily return, Sharpe ratio, maximum drawdown, etc.) by evaluating partial derivatives with respect to the parameters, selecting new parameter values accordingly, and repeating as needed.  However, because of discontinuities in the performance response, I resorted to some brute force and manual parameter adjustment.  In other words, I ran the strategy for lists of securities (e.g. S&P500, and R2000) with limited sets of parameters, selected best performers, and further optimized parameters by manual adjustment.

Performance of a Bollinger band strategy for the equity NABL.

Trade results for optimized strategy parameter values (50 day SMA, -2.1/-1.1 std.dev. entry/exit).

The above images show an example of strategy performance for the company ‘NABL’ where the 50 day simple moving average is tracked, and the ‘entry’ and ‘exit’ Bollinger bands are given by subtracting 2.1 and 1.1 standard deviation from the moving average, respectively.  Over the last two years, the strategy generated 8 trades for a total return of 63% with an average daily return of 1.55%.  Conceivably, a watch list of numerous comparably-performing strategies could generate profound results!  Yet, the details provide several reasons for caution.  First, observe that five of the 8 trade durations are only 2 to 3 days.  Implementation of the strategy—where the entries and exits are performed precisely at the daily close prices upon which the strategy is executed, is very challenging adds uncertainty to real strategy performance.  Furthermore, with a price history of only two years, small-cap stocks like NABL are more susceptible to regime change that totally negates past observed behaviors.  (Recognize too that, in trading, there is a constant battle between making decisions based on time-tested performance versus recent trends—I forget where I read this, but one could have made a fortune—for several centuries— investing in… alchemy!)


Despite these risks, this strategy guided me to make about 30 sales over the course of 6 months with a ‘win’ rate exceeding 80%, including a final, four week return of 20%  in May 2023.  Over this period, luck both helped and hurt me, but two major issues led to significant losses leading me to refine my approach.  First, I disregarded a ‘sell’ signal on an unrealized loss.  After several months of success I had became overconfident and averse to losses and the unrealized loss became even more substantial as I was sure I could wait for it to rebound.  Second, another position lost significant value that was entered, based on strategy performance over only the past couple years, and the company was particularly sensitive to the rising interest rate environment.  After holding these positions for too long, I took the losses and implemented an improved strategy intended to minimize these risks going forward.


The new strategy I developed combines three indicators—a short duration simple moving average, a long duration simple moving average, and relative strength index.  Entry/exit signals are generated when two conditions are met:  (1) difference between the two moving averages is negative/positive and (2) the RSI prints at a sufficiently low/hi percentile relative to the historical RSI distribution.  The four parameters for optimization, therefore, are the two moving average durations, the RSI lookback period, and the RSI oversold/overbought percentile.  In a ‘d’oh!’ moment, I also realized that I could significantly scale up the number of backtests, by testing the same downloaded price history for a security with different parameter sets, instead of repeatedly downloading the same price history.  Thus, I generated full factorial matrices defining over 700 sets of the four parameters, and then generated results for each company in the S&P500, totalling nearly 400000 10-year backtests (run in ~2 hrs on my 2021 MacBook Pro).  To filter the backtest results, I generated a watchlist of the 70 best-performing (daily return, total return) strategies that: (1) executed at least 10 trades over the past 10 years and (2) traded for at least 10 percent of the time (i.e. >365 days out of the 3650 day backtest).

Two-duration SMA & RSI Strategy for the equity PANW.

Trade results and optimized parameter values (16 day short SMA, 16+24=40 day long SMA, 24 day RSI lookback, 8% oversold (92% overbought) levels .

The figure above illustrates results of this new strategy having many attractive qualities.  First, the strategy executed 9 winning trades out of 10 total trades over the past ten years.  Second, the trades ranged from 14 to 200 days in duration suggesting the strategy is less sensitive to intraday entry-exit points than the example given earlier.  Third, performance exceeds the (already strong-performing) underlying asset, with nearly 550% total return while having cash locked up less than 30% of the time.  Having recently switched my positions according to signals generated by this approach, I’m optimistic about these features!  Nevertheless, I’m wary of two major risks:  (1) that companies regularly drop out of the S&P500 due to poor performance and (2) the backtest is mostly comprised of time during which interest rates were much less than what has been seen the last couple years.


To be continued!

Notes: