pinkfish
A lightweight backtester and spreadsheet library for stocks and ETFs.
Pinkfish is built for a specific niche: backtesting stocks, ETFs, portfolios, and swing-trading strategies using free daily data. It started as a way to test simple, rule-based strategies from authors like Larry Connors, Cesar Alvarez, Andreas Clenow, and Gary Antonacci — short-term mean reversion, momentum rotation, and allocation ideas that read cleanly in a few lines of Python. It is simple, pandas-native, and stays out of your way while you test ideas.
Start with the buy-and-hold example
- Single stock or ETF strategies — Connors-style mean reversion (see
examples/strategies/double-7s), golden cross, sell-in-May, and similar swing-trading ideas - Stock and ETF portfolios — asset allocation, sector rotation, and momentum across a fixed basket of symbols (see
examples/portfolios/asset-allocation-portfolio,examples/portfolios/momentum-gem-portfolio,examples/portfolios/double-7s-portfolio) - Open and close execution with daily bars — pinkfish's distinguishing feature (see below)
- Short selling and margin — included in the trade log API
- Parameter optimization — run a strategy with different settings and compare performance metrics side by side
- Jupyter spreadsheets — build formatted trading spreadsheets in a notebook: add indicators, highlight buy/sell conditions, and review signals you can execute manually
Many backtesters use an order model (market, limit, stop, etc.), not "close only." Pinkfish is different in a simpler way: you choose the fill price when you call buy() / sell() — row.open, row.close, or whatever fits the rule. No order matching; you decide the price in your loop. On one daily bar you can buy at the open and sell at the close, or act on a signal at the close and fill at that close on the same day — practical for swing rules on free daily OHLC data.
Pinkfish is not aimed at large, changing stock universes — for example, screening the S&P 500 each month and holding a different set of individual stocks as constituents enter and leave the index. That workflow needs point-in-time membership data, corporate actions across many symbols, and heavier infrastructure. Pinkfish keeps a fixed, small set of symbols and focuses on getting trade timing right.
If you need a general-purpose event-driven engine, a live-trading framework, or a stock-picking screener with a rotating universe, look elsewhere. Pinkfish does one thing well: test trading ideas on daily OHLC data with realistic open/close fills.
I specifically wanted to backtest simple strategies from Larry Connors and others — the kind of quantified swing rules in books like Short Term Trading Strategies That Work (Connors and Alvarez) and Trading Evolved (Clenow), or dual-momentum ETF models like Antonacci's GEM approach. Even straightforward rules — buy on the close the same day a new 20-day high is set, or buy at the open and sell at the close — were awkward in the backtesters I tried. I wanted something lightweight and to the point.
- pandas DataFrames for spreadsheet-style trading signal sheets in Jupyter
- Common technical indicators included; optional integration with TA-Lib or pandas-ta
- matplotlib for equity curves and charts
- Free daily data from Yahoo Finance (cached locally)
- Simple Python API — loop over rows, call
tlog.buy()/tlog.sell()at the price you choose
I recommend using pinkfish on Linux or in a Linux VM. It should also work on Windows and macOS.
# Recommended: create a new Python virtual environment first.
git clone https://github.com/fja05680/pinkfish.git
cd pinkfish
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install setuptools
python setup.py install # or: python setup.py developThis is how I got pinkfish working on Xubuntu 22.04:
# Make sure your system is up to date
sudo apt update
sudo apt upgrade
# Install some preliminary requirements
sudo apt install build-essential
sudo apt install git
sudo apt install python3-pip
# Clone pinkfish repo from GitHub
git clone https://github.com/fja05680/pinkfish.git
cd pinkfish
# Create virtual Python environment
python -m venv venv
source venv/bin/activate
# Install pinkfish
python setup.py develop
# Install TA-Lib (optional)
cd ~/Downloads
sudo wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz
tar -xzvf ta-lib-0.4.0-src.tar.gz
cd ta-lib
./configure --prefix=/usr
make
sudo make install
pip install TA-Lib
# Create shared data cache directory (optional)
mkdir $HOME/symbol-cache
echo [global] > $HOME/.pinkfish
echo base_dir = $HOME >> $HOME/.pinkfishMost examples are notebooks. GitHub renders .ipynb files in the browser, so you can read any example without installing Jupyter. To run notebook cells locally, start a notebook server after you install pinkfish and activate your virtual environment:
cd pinkfish
source venv/bin/activate # Windows: venv\Scripts\activate
jupyter nbclassicYour browser should open the Jupyter file browser. From there:
- Open the
examplesfolder. - Open a notebook — start with basics/buy-and-hold/strategy.ipynb.
- Run the cells from top to bottom (
Shift+Enterin each cell).
To open a specific example directly:
jupyter nbclassic examples/basics/buy-and-hold/strategy.ipynbIf you prefer jupyter notebook or JupyterLab, install the extra packages first: pip install notebook or pip install jupyterlab.
Pinkfish does not require Jupyter. You can run strategies as plain Python scripts. In double-7s, strategy.py holds the shared Strategy class (used by the notebook and signals.py), but it also has a main function; run python strategy.py to backtest or python signals.py for daily signals.
Examples live under [examples/](examples/) in five namespaces: basics, tutorials, strategies, portfolios, and patterns. See examples/README.md for the full curriculum and learning path.
Quick links:
- buy-and-hold — minimal strategy
- buy-open-sell-close — buy at the open, sell at the close on the same day
- double-7s — Connors/Alvarez mean-reversion strategy on ETFs; includes a daily signals script with optional Pushover and email notifications
- golden-cross — classic moving-average crossover
- asset-allocation-portfolio — multi-ETF portfolio with monthly rebalance
- spreadsheet — trading signal sheet in Jupyter
The double-7s example includes signals.py for end-of-day action after you backtest in the notebook. Shared helpers live in pinkfish.signals; optional Pushover and Resend delivery is in pinkfish.signals.notify.
Actions are BUY, SELL, HOLD (stay long), or PASS (stay flat). Without notification credentials the script prints to the terminal and writes signals.html.
See examples/strategies/double-7s/README.md for Pushover and email setup.
API reference: https://fja05680.github.io/pinkfish/html/pinkfish/index.html
Docs are generated with pdoc into [docs/html/](docs/html/) and published with GitHub Pages from the [docs/](docs/) folder on main.
Regenerate and commit after API changes:
cd docs
./generate-docs.sh
git add html/ index.html
git commit -m "Update API documentation"
git pushTo view locally:
xdg-open docs/html/pinkfish/index.html # Linux
# open docs/html/pinkfish/index.html # macOS
# start docs/html/pinkfish/index.html # WindowsSource modules with docstrings are in [pinkfish/](pinkfish/).