feat: add alphaview tool to show alpha weights alongside bar data

Joins the bar dataset with one or more alpha parquet files on (symbol, date)
for a given symbol and date range. Standalone tools/alphaview.py wired as
`cli.py alphaview`, plus README docs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Yuxuan Yan
2026-06-09 15:45:06 +08:00
parent f4b7ef3ae6
commit 0c524c6987
3 changed files with 86 additions and 0 deletions
+26
View File
@@ -179,6 +179,31 @@ ln -sf "$(pwd)/tools/pqcat.py" ~/.local/bin/pqcat # ~/.local/bin must be on PA
pqcat alphas/reversal_5d.pq --info pqcat alphas/reversal_5d.pq --info
``` ```
### `alphaview` — alpha weight(s) alongside bar data for one symbol
Join the bar dataset and one or more alpha parquet files on `(symbol, date)` and
print them side by side, so you can eyeball how a weight moves against price /
volume over a time range.
| Option | Default | Description |
| --- | --- | --- |
| `--data-path` | (required) | Bar dataset dir or parquet file |
| `--alpha-path` | (required) | Comma-separated alpha parquet path(s) — each `alpha_name` becomes a column |
| `--symbol` | (required) | Symbol id, e.g. `sh600000` |
| `--start-date` | — | `YYYY-MM-DD` (inclusive) |
| `--end-date` | — | `YYYY-MM-DD` (inclusive) |
| `-c, --columns` | `close,volume` | Comma-separated bar columns to show |
```bash
python3 cli.py alphaview \
--data-path data/daily_bars/csi500 \
--alpha-path alphas/reversal_5d.pq,alphas/momentum_5d.pq \
--symbol sh600000 --start-date 2024-01-01 --end-date 2024-03-31 \
-c close,volume,vwap
```
Also standalone like `pqcat``ln -sf "$(pwd)/tools/alphaview.py" ~/.local/bin/alphaview`.
## Alphas: the factory / plugin interface ## Alphas: the factory / plugin interface
An **alpha** is a class that maps a wide close matrix (date index × `symbol_id` An **alpha** is a class that maps a wide close matrix (date index × `symbol_id`
@@ -272,6 +297,7 @@ directory yields an extra `month` (`YYYY-MM`) partition column on top of
- `pipeline/common/schema.py` — parquet column contracts - `pipeline/common/schema.py` — parquet column contracts
- `data/downloader.py`, `data/universe.py` — baostock/akshare download + constituents - `data/downloader.py`, `data/universe.py` — baostock/akshare download + constituents
- `tools/pqcat.py` — standalone parquet inspector (`pqcat`), also wired as `cli.py pqcat` - `tools/pqcat.py` — standalone parquet inspector (`pqcat`), also wired as `cli.py pqcat`
- `tools/alphaview.py` — standalone alpha-vs-bar viewer (`alphaview`), also wired as `cli.py alphaview`
- `examples/alphas/` — example external alpha(s) - `examples/alphas/` — example external alpha(s)
## Roadmap (not yet implemented) ## Roadmap (not yet implemented)
+2
View File
@@ -15,6 +15,7 @@ from pipeline.data.cli import data
from pipeline.alpha.cli import alpha from pipeline.alpha.cli import alpha
from pipeline.combo.cli import combo from pipeline.combo.cli import combo
from tools.pqcat import pqcat from tools.pqcat import pqcat
from tools.alphaview import alphaview
@click.group() @click.group()
@@ -39,6 +40,7 @@ cli.add_command(data)
cli.add_command(alpha) cli.add_command(alpha)
cli.add_command(combo) cli.add_command(combo)
cli.add_command(pqcat) cli.add_command(pqcat)
cli.add_command(alphaview)
if __name__ == "__main__": if __name__ == "__main__":
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/env python3
"""Show alpha weight(s) alongside daily bar data for a single symbol.
Joins the bar dataset and one or more alpha parquet files on (symbol, date) so
you can eyeball how a weight moves against price/volume over a time range.
"""
import click
import pandas as pd
def _filter_dates(df, start_date, end_date):
if start_date:
df = df[df["date"] >= pd.Timestamp(start_date)]
if end_date:
df = df[df["date"] <= pd.Timestamp(end_date)]
return df
@click.command(name="alphaview")
@click.option("--data-path", required=True, type=click.Path(exists=True), help="Bar dataset dir or parquet file")
@click.option("--alpha-path", "alpha_paths", required=True, help="Comma-separated alpha parquet path(s)")
@click.option("--symbol", required=True, help="Symbol id, e.g. sh600000")
@click.option("--start-date", default=None, help="YYYY-MM-DD (inclusive)")
@click.option("--end-date", default=None, help="YYYY-MM-DD (inclusive)")
@click.option("-c", "--columns", default="close,volume", help="Comma-separated bar columns to show")
def alphaview(data_path, alpha_paths, symbol, start_date, end_date, columns):
"""Print bar columns + alpha weight(s) for SYMBOL over a date range."""
bar_cols = [c.strip() for c in columns.split(",") if c.strip()]
bars = pd.read_parquet(data_path)
bars = bars[bars["symbol_id"] == symbol]
if bars.empty:
raise click.ClickException(f"Symbol {symbol!r} not found in {data_path}")
missing = [c for c in bar_cols if c not in bars.columns]
if missing:
raise click.ClickException(f"Bar columns not found: {', '.join(missing)}")
bars = _filter_dates(bars, start_date, end_date)
out = bars[["date", *bar_cols]].set_index("date").sort_index()
for path in (p.strip() for p in alpha_paths.split(",") if p.strip()):
adf = pd.read_parquet(path)
adf = adf[adf["symbol_id"] == symbol]
adf = _filter_dates(adf, start_date, end_date)
# One alpha file may carry multiple alpha_name values; spread to columns.
wide = adf.pivot_table(index="date", columns="alpha_name", values="weight")
out = out.join(wide, how="left")
if out.empty:
raise click.ClickException("No rows in the requested date range")
with pd.option_context("display.max_rows", None, "display.max_columns", None, "display.width", None):
click.echo(f"symbol: {symbol} rows: {len(out):,}")
click.echo(out.to_string())
if __name__ == "__main__":
alphaview()