A self-serve FOSS cryptocurrency price alert and portfolio tracking system.
With this tool you can keep track of cryptocurrency price changes and your crypto portfolio, without having to share your private information with third parties. This project uses an AGPL licence to ensure that it will always be available for those who need it. No frontend frameworks are employed to complicate matters, and Go is used as the backend to ensure timely and reliable delivery of content.
You can install this application with the following steps.
- Install Go 1.18
- Create a
.envfile in the project - Run
scripts/build.sh - Create a ClickHouse database and user
- Apply
sql/schema.sqlin ClickHouse
You may wish to set up a ClickHouse database and user for development like so:
clickhouse-client --multiquery <<'SQL'
CREATE DATABASE some_database;
CREATE USER some_user IDENTIFIED WITH sha256_password BY 'some_password';
GRANT ALL ON some_database.* TO some_user;
SQL
Your .env file should look like so:
DEBUG=true
ADDRESS=:8000
DB_USERNAME=some_user
DB_PASSWORD=some_password
DB_HOST=localhost
DB_PORT=9000
DB_NAME=some_database
SMTP_USERNAME=email_username
SMTP_PASSWORD=email_password
SMTP_FROM=email_username@email.host
SMTP_HOST=email.host
SMTP_PORT=465
SESSION_SECRET=some_32_char_secret_cookie_value
The DEBUG flag enables serving files from /static, and other debugging
information. This should be set to false in production.
Run bin/ingest to load cryptocurrency price data into the database. This
should be run periodically to get the latest prices for cryptocurrencies.
It is recommended to run this program before bin/notify.
You can generate ClickHouse-ready CSV files from Binance historical data and load them into your database with these scripts:
scripts/backfill-binance-daily.sh 2026-01-28 2026-02-21 ./data/backfill
scripts/load-binance-backfill-csv.sh \
./data/backfill/crypto_currency_prices_2026-01-28_to_2026-02-21.csv \
./data/backfill/crypto_currencies_2026-01-28_to_2026-02-21.csvThe loader can also be run with only the prices CSV; missing currencies will be derived from price rows:
scripts/load-binance-backfill-csv.sh \
./data/backfill/crypto_currency_prices_2026-01-28_to_2026-02-21.csvThe backfill script pulls 1d spot klines directly from Binance
api/v3/klines, prints HTTP/curl errors to stderr, computes a daily average
as (open + high + low + close) / 4, normalizes USDT quotes to USD to
match ingest behavior, and writes CSV files with headers for direct
ClickHouse import.
For a quick test run, set SYMBOL_LIMIT:
SYMBOL_LIMIT=20 scripts/backfill-binance-daily.sh 2026-01-28 2026-02-21 ./data/backfillTo slow request rate, set REQUEST_DELAY_SECONDS (default 0.05):
REQUEST_DELAY_SECONDS=0.1 scripts/backfill-binance-daily.sh 2026-01-28 2026-02-21 ./data/backfillStoring this price data can take up lots of space. You can condense the price
data into daily average prices by running scripts/condense-prices.sh.
To inspect ClickHouse storage usage, query system.parts for the table sizes
and consider adding TTL rules if you want to expire older price data.
Run bin/notify to send price alert emails using the SMTP credentials set in
the .env file. You should create test alerts to ensure emails will be delivered.
Popular mail hosts can reject mail for all kinds of reasons.
One easy way to ensure your mail will be delivered is to send with GMail as the SMTP provider to a GMail address, or similar for other popular email providers.
Run bin/adduser EMAIL PASSWORD to add a user with a given email address and
password. You should be able to log in to the site after the program completes
successfully.
This section will describe running the server with nginx.
Copy at least the contents of bin and static to a directory on a webserver,
and set up nginx to serve your static content and work as a reverse proxy.
server {
# ...
location /static {
include expires_headers;
root /your/dir;
}
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_redirect off;
# Use the port you're running the server with here.
proxy_pass http://localhost:8000/;
}
}You can set cron rules to start the server up on boot, and to periodically load price data and send email alerts.
# Start pricewarp at server start
@reboot cd /your/dir && bin/pricewarp &> server.log
# Ingest new prices every 10 minutes from minute 1.
1-59/10 * * * * cd /your/dir && bin/ingest
# Ingest new prices every 10 minutes from minute 2.
2-59/10 * * * * cd /your/dir && bin/notify
# Condence prices during the middle of the night.
0 3 * * * cd ~/pricewarp && scripts/condense-prices.shYou could start your server right away with nohup.
nohup bin/pricewarp &> server.log &

