Skip to content

release: v0.2.0#1

Merged
quantbai merged 21 commits into
mainfrom
dev
Mar 23, 2026
Merged

release: v0.2.0#1
quantbai merged 21 commits into
mainfrom
dev

Conversation

@quantbai
Copy link
Copy Markdown
Owner

Summary

Production audit: 8 bug fixes (4 numerical), project scaffolding, CI/CD automation.

Change Type

  • Bug fix
  • New feature
  • Numerical change [BREAKING]

Numerical Impact

  • ts_product: negative inputs now return correct product (was null)
  • ts_covariance: ddof changed from 0 to 1 (values change)
  • divide/inverse: zero divisor now returns null (was Inf->null implicitly)

Testing

  • 141 tests pass
  • Lint passes

quantbai and others added 21 commits March 19, 2026 17:17
- Switch license from MIT to Apache 2.0
- Remove legacy setup.py, keep only pyproject.toml
- Fix package discovery to exclude assets directory
- Change default sort order to [timestamp, symbol] for cross-sectional workflows
- Update README license badge

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
清除 WQ-style, phandas 等引用

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
測試預期行為:跳過 null,rank 用 method=average

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 所有截面運算子從 has_null→kill_all 改為 per-row null check
- rank: method=min → method=average(ties 取平均排名)
- zscore: ddof=1 → ddof=0(母體標準差)
- quantile: 重寫為 rank→shift→inverse CDF,保留 [DEV]

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ts_std_dev, ts_covariance, ts_zscore, ts_cv: ddof=0
- ts_corr, ts_autocorr: 保留 ddof=1(相關係數不受 ddof 影響)
- 全面 min_periods→min_samples 消除 deprecation warning

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
原 ts_quantile 改名 ts_percentile(rolling 百分位數)
新 ts_quantile 匹配 spec:rank → inverse CDF transform

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
filter=True: add/subtract 把 null 視為 0,multiply 把 null 視為 1

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ts_skewness: 手算公式完全算錯(符號和數值都不對),改用 rolling_skew(bias=True)
ts_decay_linear: 6 行 shift 邏輯改為 1 行 rolling_mean(weights=[1,2,...,n])
兩者均經 verify_against_polars.py 驗證與原生 Polars 完美匹配

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
一行呼叫顯示:維度、覆蓋率、null/NaN/inf 計數、分布統計、rank turnover
統計量排除 null/NaN/inf 後計算,避免污染

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
統計量先 per-timestamp 截面計算,再顯示 mean +/- std over time
cs_mean, cs_std, cs_skew 各自顯示時序穩定性

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New operators:
- ts: ts_step, ts_decay_exp_window, days_from_last_change, kth_element,
  last_diff_value, inst_tvr, ts_delta_limit, ts_regression (10 rettypes),
  trade_when
- cs: winsorize, truncate, left_tail, right_tail, quantile (exported)
- base: densify, bucket
- group: group_mean (weighted), group_median, group_backfill

Fixes:
- ts_quantile gaussian driver: zscore -> rank+ppf (Acklam approximation)
- winsorize/truncate: null-safe clip via max/min_horizontal
- bucket range_params: fix float accumulation drift
- normalize: add use_std, limit params
- scale: add longscale, shortscale params
- log type annotation: float -> Optional[float]

Removals:
- ln() redundant with log()
- Factor.describe() moved to analytics layer
- __all__ deduplication: ops/__init__.py is single source of truth

Tests: consolidated 11 files -> 5+conftest (1:1 module mapping), 131 tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CLAUDE.md: complete development standards (git workflow, coding standards,
  commit convention, code review rules, versioning, known limitations)
- CI: GitHub Actions workflow for pytest on Python 3.10-3.13 + ruff lint
- Pre-commit: ruff lint/format + pytest hooks
- PR template: change type checklist with numerical impact section
- CHANGELOG.md: structured change log with [NUMERICAL] tags
- pyproject.toml: dev dependencies (pytest, ruff, pre-commit), tool configs
- _validation.py: input validation helpers for operator parameters
- .gitignore: exclude .claude/ local settings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…anup

[NUMERICAL] Three changes that affect computation results:

1. ts_product: silently returned null for negative inputs due to log-sum-exp
   trick. Replaced with sign-magnitude decomposition (count negatives for
   sign, exp(sum(log(abs(x)))) for magnitude, zero detection).

2. ts_covariance: used ddof=0 (population) inconsistent with ts_corr (ddof=1).
   Aligned to ddof=1 (sample covariance). This changes output values.

3. ts_count_nans: used min_samples=1 unlike all other ts_* operators.
   Aligned to min_samples=window for consistency.

4. ts_regression rettype=7 (MSE): added explicit zero guard for window=2
   (n-2=0). Previously relied on implicit Inf-to-null conversion.

Also moved DEV operators (hump, ts_arg_max, ts_arg_min) to _dev.py,
removed from public API. These use Python callbacks and are not
production-grade.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[NUMERICAL] divide() and inverse() previously produced Inf when dividing
by zero, relying on Factor constructor's implicit Inf-to-null conversion.
Now explicitly returns null where abs(denominator) < 1e-10, matching the
zero-guard pattern used by all other division operations in the library.

Added tests for divide() (basic, zero denominator, scalar, scalar zero)
and reverse() (negate, null preservation) -- both previously had zero
test coverage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_balance() previously hardcoded interval="1d", which would silently
drop all intraday data when loading hourly or minutely datasets.
The skeleton was built with daily timestamps only, and the left join
discarded any rows not matching midnight timestamps.

load() now accepts an interval parameter (default "1d") that propagates
to _balance(). Supports any Polars duration string (e.g., "1h", "5m").

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Factor constructor now validates required columns [timestamp, symbol,
  factor] and raises ValueError with clear message if missing
- Added __hash__ = None to Factor class (explicit, since __eq__ returns
  Factor not bool -- matches pandas semantics, documented in docstring)
- Applied ruff auto-formatting across all modules (import sorting,
  Union -> X | Y syntax for Python 3.10+)
- No behavioral changes beyond the new constructor validation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- publish.yml: triggered by v* tags, builds and publishes to PyPI
  via Trusted Publisher (no API tokens stored in repo)
- CLAUDE.md: added complete release process (7 steps), versioning
  table with examples, one-time GitHub setup instructions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- publish.yml: now runs full test suite before publishing, creates
  GitHub Release with auto-generated notes and build artifacts
- CLAUDE.md: comprehensive rewrite with 12 numbered sections covering
  all development practices from daily workflow to release process.
  This is the single source of truth for any developer or LLM.

Sections: project overview, architecture, git workflow, coding standards,
testing, commit convention, code review, versioning, release process,
one-time setup, commands reference, known limitations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Version 0.2.0 includes production audit fixes with multiple numerical
corrections. See CHANGELOG.md for full details.

Key numerical changes:
- ts_product: now handles negative values correctly
- ts_covariance: aligned to ddof=1 (sample) matching ts_corr
- divide/inverse: explicit zero-division guards
@quantbai quantbai merged commit 3f9d349 into main Mar 23, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant