gravy
Overview
Gravy consists of several microservices that operate over grpc:
- Data sources (e.g.
data/dailyprices
) - Supervisor (
supervisor
) - Algorithms (e.g.
algorithms/buyandhold
)
With all of these running, one can begin a backtest via cmd/begin_backtest/main.go
. Typically one will persist the data sources (which generally cache their outputs in memory) and make a "study" (studies/
), which is a shell script which configures the supervisor and algorithms to run against the persisting data sources.
Backtests currently output various debug logs (usually to a temp directory) and also a TimescaleDB output. Visualize the output with Grafana.
Technologies / dependencies
- gRPC
- proto3
- Golang
- Python 3
- PostGRES
- TimescaleDB
- Grafana
- Jupyter / colab
- Typical Python libraries (pandas, scipy, numpy, Tensorflow, keras, sklearn, matplotlib, etc)
Examples
To run gravy:
- Follow the instructions in
data/dailyprices
to get the basicdailyprices
andgravy_timescale_output
dbs - Run a persisting data source with
go run cmd/data/dailyprices/main.go
- Run a study, such as
sh ./studies/correlated_pairs.sh
- This should start populating a new table
timescaleout${TIMESTAMP}
in thegravy_timescale_output
db - Run grafana, e.g.
brew services start grafana
- Go to
localhost:3000
and bring the${TIMESTAMP}
to visualize the results - (there are also some files output in
/tmp/fizzybuzzy/
including a log of individual buy/sell orders)
To ask what are the five best days for GOOG stock.
echo "select date, open, close, (close-open)/open as perf from dailyprices
where ticker = 'GOOG'
order by perf desc limit 5
;" | psql gravy
To visualize prices data, use Colab:
pip3 install psycopg2
./jupyter-up.sh
- Go to
https://colab.research.google.com
and make a new Notebook. - On the upper right, use the "Connect" menu to "Connect to local runtime...".
- Run the following code.
import psycopg2, matplotlib.pyplot as plt, pandas as pd, pandas.io.sql as psql
conn = psycopg2.connect("host=localhost port=5432 dbname=gravy")
MSFTVSGOOGL = """
SELECT M.close AS msft, G.close AS googl, M.date AS date
FROM dailyprices M INNER JOIN dailyprices G ON M.date = G.date
WHERE M.ticker = 'MSFT' AND G.ticker = 'GOOGL' AND M.date > '2006-01-02'
ORDER BY date;"""
df = pd.read_sql(MSFTVSGOOGL, conn)
df["msft_norm"] = df["msft"] / df["msft"][0]
df["googl_norm"] = df["googl"] / df["googl"][0]
df.plot("date", ["msft_norm", "googl_norm"], figsize=(14, 7))
plt.show()