IdxMax and IdxMin return the position of NaN instead of the extreme value
メンテナーはふだん 3 日以内に返信
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 78/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
調査の方向性
まず qlib/data/ops で IdxMax と IdxMin を見つけ、実際のオペレーターに対して提供された再現スクリプトを実行します。次に、qlib/contrib/data/loader.py の関連する IMAX、IMIN、IMXD 式を確認し、ウィンドウに NaN 値が含まれる場合にインデックス付きの結果が Max および Min と一致することを検証します。
索引モデルが issue の本文から書いたものです。
説明
🐛 Bug Description
IdxMax and IdxMin return the position of the extreme value inside the
rolling window. Both use ndarray.argmax / ndarray.argmin, which do not skip
NaN: as soon as the window holds a NaN, they return its position instead.
Max and Min go through pandas.rolling.max/min and do skip NaN, so the two
contradict each other on the same series. Mad and Rank in the same file
filter NaN explicitly (x[~np.isnan(x)]); IdxMax and IdxMin do not.
This reaches Alpha158. qlib/contrib/data/loader.py builds three field
families on these two operators:
| field | expression | meaning per the comment in the loader |
|---|---|---|
IMAX{d} |
IdxMax($high, d)/d |
days since the last high (Aroon) |
IMIN{d} |
IdxMin($low, d)/d |
days since the last low (Aroon) |
IMXD{d} |
(IdxMax($high,d)-IdxMin($low,d))/d |
distance between the two |
$high and $low are NaN while an instrument is suspended.
To Reproduce
- Run the script below on a clean checkout. It only replaces the data access
of a leaf feature; the operators under test run their real code.
import numpy as np
import pandas as pd
from qlib.data.base import Feature
from qlib.data.ops import IdxMax, Max
class SeriesFeature(Feature):
def __init__(self, name, values):
super().__init__(name)
self._values = values
def _load_internal(self, instrument, start_index, end_index, freq):
return pd.Series(self._values, dtype="float64")
values = [1.0, 5.0, np.nan, 2.0, 3.0]
window = 3
idx = IdxMax(SeriesFeature("a", values), window).load("x", 0, len(values) - 1, "day")
mx = Max(SeriesFeature("b", values), window).load("x", 0, len(values) - 1, "day")
for i in range(len(values)):
w = values[max(0, i - window + 1) : i + 1]
print(f"{w} Max={mx.iloc[i]} IdxMax={idx.iloc[i]} points at {w[int(idx.iloc[i]) - 1]}")
- Output on
be725493:
[1.0] Max=1.0 IdxMax=1.0 points at 1.0
[1.0, 5.0] Max=5.0 IdxMax=2.0 points at 5.0
[1.0, 5.0, nan] Max=5.0 IdxMax=3.0 points at nan
[5.0, nan, 2.0] Max=5.0 IdxMax=2.0 points at nan
[nan, 2.0, 3.0] Max=3.0 IdxMax=1.0 points at nan
Every window holding a NaN is wrong.
Expected Behavior
IdxMax points at the value Max reports for the same window, and IdxMin at
the value Min reports.
Environment
- Qlib version: 0.9.8.dev34 (editable install)
- Python version: 3.12.13
- OS: MacOS 26.6.2, arm64
- Commit number: be725493eb1a6bbb42bf11b37aa7669f59610ff1
- numpy 2.5.3, pandas 2.3.3
Additional Notes
Scale on real data. csi300, 30 instruments, 2019, qlib_data_simple:
| measurement | value |
|---|---|
| rows | 7320 |
NaN in $high |
76 (1.04 %) |
| instruments holding at least one NaN | 30 of 30 |
IMAX5 differing between argmax and nanargmax |
224 of 7314 (3.06 %) |
One NaN spoils the window for N days, so the effect is wider than the share of
NaN itself.
- 主要言語
- Python
- スター
- 49.5k
- フォーク
- 7.8k
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
- Dockerfile または Docker Compose ファイルあり
- プルリクエストのテンプレートあり
- コントリビューションガイドなし
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
microsoft/qlib のほかの issue
-
StructuredCovEstimator crashes for one factor and uses inconsistent residual variance対応中かも @Divyansh151005 が 6 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
microsoft/qlib#2377 · コメント 1 件 ·
メンテナーはふだん 3 日以内に返信
-
collect_info.py does not start: pkg_resources is gone from setuptools 82対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
microsoft/qlib#2354 · コメント 1 件 ·
メンテナーはふだん 3 日以内に返信
-
Bug: Rsquare(N=0) expanding path leaks inf/garbage on near-constant windows (rolling path is guarded)対応中かも @DogInfantry が 106 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
microsoft/qlib#2297 · コメント 4 件 ·
メンテナーはふだん 3 日以内に返信
-
TopkDropoutStrategy ignores get_risk_degree() for position sizing対応中かも @zhaow-de が 124 日前に担当しました。 オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
microsoft/qlib#2276 · コメント 2 件 ·
メンテナーはふだん 3 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 78/100
microsoft/qlib#2198 · コメント 1 件 ·
メンテナーはふだん 3 日以内に返信
似ている issue
-
難易度 1/5 1〜3時間 初心者へのやさしさ 85/100
WLAN-Pi/wlanpi-profiler#341 ·
メンテナーはふだん 1 日以内に返信
-
Memory leak: the shared `validation_aborted_error` keeps every traceback it is raised through対応中かも @Fire162 が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
graphql-python/graphql-core#287 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
roman-corgi/ctc-dip#160 ·
メンテナーはふだん 1 日以内に返信
-
type-bug
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
render_findings.py reads and writes in the host's default encoding, so findings.html breaks on a cp1252 Windows host対応中かも @Aaqibhafeezkhan が今日担当しました。 オープンbug good first issue mentored python size: XS up-for-grabs
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
dheerajjha/mcp-migrate#366 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信