Skip to content

rcalfredson/turtle

Repository files navigation

turtle

A modernized web app for experimenting with the vanilla Richard Dennis turtle trading strategy.

This version uses server-side historical EOD data lookup, a simplified strategy engine, and a lightweight browser UI for ticker selection and backtesting.

Research status and warning

This repository is a research artifact, not a live trading system.

After a series of realism checks, benchmark comparisons, broader universe tests, relative-strength filters, and hybrid SPY-core experiments, the current conclusion is that these Turtle-inspired long-only equity variants are not compelling enough to use as a replacement for passive index investing.

The project found some interesting behavior, especially around relative-strength filters and passive-core/active-sleeve hybrids, but the remaining edge was small, regime-dependent, and likely not large enough to overcome taxes, slippage, operational burden, overfitting risk, and ordinary benchmark alternatives such as SPY and QQQ.

If you found this repo while looking for a trading strategy to run with real money, start with the closing note:

The short version:

Backtests can be useful, but a strategy that only barely beats a simple benchmark in selected tests has not earned live-capital confidence.

Quick start

  1. Install dependencies:
npm install
  1. Run the app:
npm start
  1. Open http://localhost:3000

Requires Node.js 24 or newer.

Market data cache

Yahoo historical chart responses are cached on disk in .cache/market-data for 24 hours by default. You can tune this with:

MARKET_DATA_CACHE=false
MARKET_DATA_CACHE_DIR=.cache/market-data
MARKET_DATA_CACHE_TTL_HOURS=24

Matrix runner

Run ticker/date-range batches from the command line and write results to CSV:

npm run matrix

By default this runs the built-in 18-symbol by 4-date-range matrix and writes to reports/matrix-results-*.csv. Useful smaller runs:

npm run matrix -- --dry-run
npm run matrix -- --limit=3
npm run matrix -- --symbols=AAPL,SPY --ranges=2020-01-01:2024-12-31

Universe files

Portfolio and benchmark runners can load symbols from a text file with --symbolsFile. Files may use commas, spaces, or newlines, and # starts a comment:

npm run portfolio -- --symbolsFile=universes/sector-etfs.txt --gapAwareFills=true --maxUnits=1 --slippageBps=5
npm run benchmarks -- --symbolsFile=universes/sector-etfs.txt --benchmarkSymbols=SPY,QQQ,IWM,DIA

Portfolio runs can also sweep same-day entry ordering with --entryRank. Supported values are alphabetical, momentum63, and momentum126:

npm run portfolio -- --symbolsFile=universes/sp500-top100-established.txt --gapAwareFills=true --maxUnits=1 --slippageBps=5 --entryRank=alphabetical,momentum63,momentum126

Risk sizing can be swept with comma-separated --riskPercent values:

npm run portfolio -- --symbolsFile=universes/sp500-top100-established.txt --gapAwareFills=true --maxUnits=1 --slippageBps=5 --entryRank=momentum126 --riskPercent=0.25,0.5,1

Concurrent position limits can be swept with comma-separated --maxOpenPositions values:

npm run portfolio -- --symbolsFile=universes/sp500-top100-established.txt --gapAwareFills=true --maxUnits=1 --slippageBps=5 --entryRank=momentum126 --riskPercent=0.25 --maxOpenPositions=10,20,30

Market regime filters can gate new entries and add-ons with a broad-market moving average. Use --marketRegimeMa=0,200 to compare the unfiltered strategy with a prior-close SPY 200-day SMA filter:

npm run portfolio -- --symbolsFile=universes/sp500-top100-established.txt --gapAwareFills=true --slippageBps=5 --entryRank=momentum126 --riskPercent=0.25 --entryPeriod=55 --exitPeriod=50 --maxUnits=1,2,4 --marketRegimeSymbol=SPY --marketRegimeMa=0,200

Relative-strength filters can require breakout candidates to outperform a benchmark over a prior return lookback. Use --relativeStrengthLookback=0,126 to compare unfiltered entries with entries that have beaten SPY over the prior 126 trading days:

npm run portfolio -- --symbolsFile=universes/sp500-top100-established.txt --gapAwareFills=true --slippageBps=5 --entryRank=momentum126 --riskPercent=0.25 --entryPeriod=55 --exitPeriod=50 --maxUnits=1,2,4 --relativeStrengthSymbol=SPY --relativeStrengthLookback=0,126

Hybrid runs combine a passive buy-and-hold core with an active trend-following sleeve. Use --activeAllocationPct to sweep the active sleeve size; the remaining allocation goes to --coreSymbol. Use --rebalance=none,annual,quarterly to compare initial-allocation-only hybrids with periodic target-weight rebalancing:

npm run hybrid -- --symbolsFile=universes/sp500-top100-established.txt --coreSymbol=SPY --activeAllocationPct=20,30 --rebalance=none,annual,quarterly --gapAwareFills=true --slippageBps=5 --entryRank=momentum126 --riskPercent=0.25 --entryPeriod=55 --exitPeriod=50 --maxUnits=1 --maxOpenPositions=10 --relativeStrengthSymbol=SPY --relativeStrengthLookback=63,84

About

A web app to implement some of the basic decision metrics and algorithms used in the "turtle trading" strategy created by Richard Dennis.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages