Silars
Silars 是基于 Polars 的因子分析与回测工具库,提供数据预处理、组合权重、策略和回测入口。
安装
Silars 需要 Python 3.12 或更高版本;CI 持续验证 Python 3.12 和 3.13。
pip install silars
使用 uv:
uv add silars
最小示例
下面按每个 (date, time) 截面选择得分最高的两个资产,并生成等权组合:
from copy import deepcopy
import polars as pl
from silars.alphalens import top_k
scores = pl.DataFrame(
{
"date": ["2026-01-02"] * 3,
"time": ["09:31:00"] * 3,
"asset": ["A", "B", "C"],
"score": [0.2, 0.8, 0.5],
}
)
selector = deepcopy(top_k).set_params(num=2)
weights = selector.transform(scores)
print(weights.select("date", "time", "asset", "target_weight"))
主要入口
Preprocessor及预处理函数:因子清洗、标准化和中性化。top_k、qcut、MFEs/MFEConfig:组合权重生成。Strategy、FactorStrategy:策略编排。BacktestEngine、bt:回测。Zoo、zoo:因子数据工作区。
这些入口均从 silars.alphalens 导入。
MFEs 的行业、板块、个股和风格偏离均相对完整输入基准;Zoo.mfe 使用
挂载的风险基准。候选过滤和缺分只限制可买入资产,不重算基准。
启用基准约束时,基准总权重必须为正,基准成分必须有完整的对应风险暴露;
标量风格约束要求至少一列 *Barra。求解不可行、后验校验失败或建仓后
没有可选资产会抛错,不再沿用旧权重。约束验收针对目标权重,实际成交持仓
仍受涨跌停、停牌和回测执行规则影响。
研究期 tree shortlist
silars.feature_selection.select_features 用固定的单特征浅树,按独立验证期的每日
prediction RankIC 对已物化数值特征做粗筛:
from silars.feature_selection import select_features
ranking = select_features(
train,
valid,
feature_names,
"forward_return",
max_features=100,
)
它衡量的是 tree(feature) 对下游模型的排序潜力,不是原始特征 RankIC、独立 OOS、
显著性结论或可直接传给 MFEs 的 score。PIT、purge/embargo 和后续使用边界由
调用方保证。该入口也不同于
silars.alphalens.evaluate.select_features 的多重检验与相关性筛选。
同一模块也可以把一组显式特征通过一棵相同参数的浅树融合为 predict 区间的新特征:
from silars.feature_selection import fuse_features
fused = fuse_features(
train,
valid,
["feature_a", "feature_b", "feature_c"],
target="forward_return",
output_name="tree_fusion",
)
valid = valid.with_columns(fused["tree_fusion"])
该入口只返回 predict prediction,不返回模型或 train in-sample prediction。若输入 特征是利用同一 predict 区间的 target 选出的,结果仍有 post-selection bias,不是 独立 OOS;完整历史融合列应由调用方 walk-forward/cross-fit 生成。
若 valid 含 target,可用同一棵 train-only 树得到一行 holdout 摘要及可直接执行的 Polars 表达式:
from silars.feature_selection import evaluate_fusion
report = evaluate_fusion(
train,
valid,
["feature_a", "feature_b", "feature_c"],
target="forward_return",
output_name="tree_fusion",
)
expression = report.item(0, "expression")
valid = valid.with_columns(expression)
# 可持久化并交给另一个进程 / Dataset
lidb_expression = report.item(0, "lidb_expression")
返回列为 feature、source_features、model_rank_ic_mean、
model_rank_icir、expression、lidb_expression。expression 是当前进程可直接
执行的 pl.Expr;lidb_expression 是同一棵树生成的 LiDB/QDF 三元表达式字符串,
格式如 ((feature_a<=0.5)?(0.1):(0.2)) as tree_fusion,可持久化并由另一个进程
转成 Dataset。融合树的输入和输出统一量化为 6 位小数,表达式中的 threshold 与
leaf value 也最多保留 6 位小数。这里只能证明 train/valid 时间分离;PIT、label
实现时点、
purge/embargo、valid 前冻结特征集合且未重复使用 valid 选 winner 均由调用方保证。
holdout 审查只调用 evaluate_fusion,未来预测再选择 fuse_features 或冻结
expression,避免对同一区间重复 fit。
大量显式组合应一次交给批量入口,避免循环调用 evaluate_fusion 重复准备公共数据:
from itertools import product
import polars as pl
from silars.feature_selection import evaluate_fusions
groups = product(features_a, features_b)
ranking = evaluate_fusions(
train,
valid,
groups,
target="forward_return",
output_prefix="tree_fusion",
min_rank_ic=0.03,
n_jobs=7,
)
expressions = (
ranking.filter(pl.col("selected")).get_column("expression").to_list()
)
predict = predict.with_columns(expressions)
portable_ranking = ranking.drop("expression")
portable_ranking.write_parquet("fusion_ranking.parquet")
组合按输入顺序稳定命名为 tree_fusion_00000、tree_fusion_00001 等;组内特征名
排序,规范化后重复的组合会在首次 fit 前报错。公共 row-domain、target ranks、
sample weights 和特征值校验只准备一次,每组只保留自己的小型 Float32 矩阵。
只有通过 min_rank_ic 的行保存两种表达式,其余为 null。Object 列不能写
Parquet;持久化排名时只需移除 expression,lidb_expression 可直接保留。
另一个进程加载源 Dataset 后,可把筛选出的字符串直接交给 LiDB:
import lidb
import polars as pl
from lidb import dataset
selected = pl.read_parquet("fusion_ranking.parquet").filter(pl.col("selected"))
SOURCE_FEATURES = sorted(
{feature for group in selected["source_features"] for feature in group}
)
LIDB_EXPRESSIONS = tuple(
selected
.get_column("lidb_expression")
.drop_nulls()
)
@dataset(ds_feature_source)
def ds_tree_fusions(depend: pl.LazyFrame):
prepared = depend.with_columns(
pl.col(SOURCE_FEATURES).cast(pl.Float64).round(6).cast(pl.Float32)
)
return lidb.from_polars(prepared).sql(*LIDB_EXPRESSIONS)
源 Dataset 必须提供 source_features 中完全相同的列名;表达式版本变化时应同步
更新 Dataset 的稳定版本名,避免复用旧缓存。LiDB 不支持的列名或输出名不会被猜测
转义,对应 lidb_expression 返回 null,当前进程的 pl.Expr 仍然可用。源特征在
进入 LiDB 前必须使用相同的 round(6) -> Float32 预处理,否则不保证与评估结果
一致。
批量入口使用 ygo 的 threading backend 并行各组合,线程共享只读的
train/valid 和公共统计状态,不复制整张 DataFrame。n_jobs 必须为正整数,实际
worker 数不会超过组合数;外层已经并发或内存受限时传 n_jobs=1。
批量筛选会把 valid 变成 selection set;无论筛选多少行,它都不再是独立 OOS。
筛出的表达式必须在未参与组合筛选的后续 predict/test 区间验证。
基准对冲回测
对已加载的 Zoo,可复用原多头回测并得到 1:1 对冲收益。传入指数代码时读取对应
指数日收益:
from silars.alphalens import FactorStrategy, zoo
results = zoo.hedge(
["KMID"],
FactorStrategy(),
index_code="000300",
times=["09:31:00", "10:00:00"],
)
print(results["KMID"]["ret"])
print(results["KMID"]["metric"])
hedge() 会立即完成回测,并返回每个因子的 pos、ret、figure 和对冲组合
metric,不是延迟任务生成器;show=False 可跳过主动展示。
index_code="" 时不读取指数,直接从回测输入的 prev_close/open/close 构造等权市场
日收益,结果列为 mkt 和 long-mkt。指数路径运行时需要当前环境可导入
dc.data.base.ds_index_retC2C;period 仅控制原组合持仓周期,不缩放日度基准收益。
许可证
Silars 使用 MIT License。silars/empyrical 包含 Apache-2.0 许可的第三方代码,详见
THIRD_PARTY_NOTICES.md 和 LICENSES/Apache-2.0.txt。
Metadata
Release files for silars 2026.9.14.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| silars-2026.9.14.0.tar.gz | 244.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| silars-2026.9.14.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 395.4 kB
Release files / silars-2026.9.14.0.tar.gz
| Download URL | silars-2026.9.14.0.tar.gz |
|---|---|
| Size | 244.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1347d50a4efe796ea31589ca19583665638c3350fa35ff6deebfe86ff0893ff6
|
|
BLAKE2b-256 checksum How to use checksums |
dbce9b41001caa904d8ca560d1a239b7ce8f371718e57f971ea908b3e580a224
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / silars-2026.9.14.0-py3-none-any.whl
| Download URL | silars-2026.9.14.0-py3-none-any.whl |
|---|---|
| Size | 150.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
52cbb54983e2d6dca4d28ab6a16f7e0ee497c5d1f53e958a9405ad0b0b06d67b
|
|
BLAKE2b-256 checksum How to use checksums |
6a04468194b9d06657bfce0826274837bbd9c8ab5cefaa32aad340a26791f6e0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|