07ed6ad917
reversal_rank weights the 5-day reversal signal by bounded cross-sectional rank instead of z-score, so a few extreme A-share pct_change outliers (newly listed / post-suspension / limit-up names) can no longer dominate the book. compute_alpha gains an optional per-date investable-universe mask (tradable, non-ST, seasoned, top-liquidity) applied to the signal before weighting, exposed via --liquid-universe/--universe-top-n. combo combine now accepts a single alpha as an identity passthrough so a one-alpha pipeline run needs no synthetic second input. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
48 lines
1.4 KiB
Python
48 lines
1.4 KiB
Python
"""CLI for alpha combination."""
|
|
|
|
import os
|
|
import click
|
|
|
|
from pipeline.combo.combine import combine_alphas, COMBO_METHODS
|
|
|
|
|
|
@click.group(name="combo")
|
|
def combo():
|
|
"""Combine multiple alphas into a single combined weight."""
|
|
|
|
|
|
@combo.command("combine")
|
|
@click.option(
|
|
"--alpha-paths", required=True,
|
|
help="Comma-separated paths to alpha parquet files",
|
|
)
|
|
@click.option("--combo-name", required=True, help="Name for this combo")
|
|
@click.option(
|
|
"--method", default="equal_weight",
|
|
type=click.Choice(list(COMBO_METHODS.keys())),
|
|
help="Combination method",
|
|
)
|
|
@click.option("--output-dir", default="combos", help="Directory to save combo parquet")
|
|
def combine(alpha_paths, combo_name, method, output_dir):
|
|
"""Combine multiple alphas and save as parquet."""
|
|
paths = [p.strip() for p in alpha_paths.split(",") if p.strip()]
|
|
if len(paths) < 1:
|
|
click.echo("Error: --alpha-paths requires at least 1 path", err=True)
|
|
return
|
|
|
|
result = combine_alphas(
|
|
alpha_paths=paths,
|
|
combo_name=combo_name,
|
|
method=method,
|
|
)
|
|
|
|
os.makedirs(output_dir, exist_ok=True)
|
|
out_path = f"{output_dir}/{combo_name}.pq"
|
|
result.to_parquet(out_path, index=False)
|
|
click.echo(f"Saved combo: {out_path} ({len(result):,} rows)")
|
|
click.echo(
|
|
f"Weight stats — min: {result['weight'].min():.4f}, "
|
|
f"max: {result['weight'].max():.4f}, "
|
|
f"mean: {result['weight'].mean():.4f}"
|
|
)
|