From c7fc73180cacf0e297389903b773c1cac42ae6e8 Mon Sep 17 00:00:00 2001 From: zhaoli Date: Wed, 19 Aug 2026 22:05:08 +0000 Subject: [PATCH] start experiment 33 (exp/33-q01-m2-reproduction-add-spsharpe22-to-th) --- code/MANIFEST.txt | 26 ++++----- .../__pycache__/__init__.cpython-312.pyc | Bin 374 -> 374 bytes .../data/__pycache__/__init__.cpython-312.pyc | Bin 216 -> 216 bytes .../data/__pycache__/handler.cpython-312.pyc | Bin 11073 -> 11073 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 319 -> 319 bytes .../__pycache__/rank_ensemble.cpython-312.pyc | Bin 9461 -> 9461 bytes .../__pycache__/rank_gbdt.cpython-312.pyc | Bin 9838 -> 12288 bytes .../tac_qlib/contrib/model/rank_gbdt.py | 54 +++++++++++++++--- .../__pycache__/__init__.cpython-312.pyc | Bin 234 -> 234 bytes .../__pycache__/optimal_stop.cpython-312.pyc | Bin 10428 -> 10428 bytes .../data/__pycache__/__init__.cpython-312.pyc | Bin 522 -> 522 bytes .../data/__pycache__/config.cpython-312.pyc | Bin 11464 -> 11464 bytes .../__pycache__/providers.cpython-312.pyc | Bin 13340 -> 13340 bytes 13 files changed, 59 insertions(+), 21 deletions(-) diff --git a/code/MANIFEST.txt b/code/MANIFEST.txt index 440091e..3adbdb4 100644 --- a/code/MANIFEST.txt +++ b/code/MANIFEST.txt @@ -1,27 +1,27 @@ # TradeAC custom-qlib-code snapshot (auto-generated) -# parent repo HEAD : e660b4f2dd7c521615c54a142eec9266837f2e64 +# parent repo HEAD : 483a86e47f777e22f8f4be0326c05133b7dbb5a5 # tac-qlib/tac_qlib/contrib # tac-qlib/tac_qlib/data # per-file hashes (git hash-object): 1b6298c4a5652f2e863cbdc385a1014a570fcd59 tac-qlib/tac_qlib/contrib/__init__.py - b5e28b7c0a10ab553eaa6303013a880731742378 tac-qlib/tac_qlib/contrib/__pycache__/__init__.cpython-312.pyc + b419ee55ed455a1c45423d1c9025ca5cc0a98576 tac-qlib/tac_qlib/contrib/__pycache__/__init__.cpython-312.pyc c76a9f17f680e74eea766eff27f7624359749ed6 tac-qlib/tac_qlib/contrib/data/__init__.py - 715ab312125a446af751b928fe41cf41b99ffcd0 tac-qlib/tac_qlib/contrib/data/__pycache__/__init__.cpython-312.pyc - a82a6a236db93097d48748e541c2cf9caa4e48b5 tac-qlib/tac_qlib/contrib/data/__pycache__/handler.cpython-312.pyc + 2f6c67620aa2f9e6aaaef3369361d9b3eac3d6ca tac-qlib/tac_qlib/contrib/data/__pycache__/__init__.cpython-312.pyc + fdd5923a70a399e8680913593ff111641947898e tac-qlib/tac_qlib/contrib/data/__pycache__/handler.cpython-312.pyc 0dd25ef161c6e0f15eafc84886e7e1381deb38c3 tac-qlib/tac_qlib/contrib/data/handler.py b151d139a0dcde87d74b21e7c4b729176ba5c39b tac-qlib/tac_qlib/contrib/model/__init__.py - 483221cf1d5bad779d3cf9505269b7fb0b3f165d tac-qlib/tac_qlib/contrib/model/__pycache__/__init__.cpython-312.pyc - 1286dec07a861f25691b24f71ecc22d8eb3537df tac-qlib/tac_qlib/contrib/model/__pycache__/rank_ensemble.cpython-312.pyc - 5185764bd55dbc63d16582bfcb6adc11b7e6d342 tac-qlib/tac_qlib/contrib/model/__pycache__/rank_gbdt.cpython-312.pyc + 08dec87ccdf6bb5d2cf611ca3032a4280aaab8cf tac-qlib/tac_qlib/contrib/model/__pycache__/__init__.cpython-312.pyc + 6fb61946ea9a83dfb560de3717f5fbf482c4c00e tac-qlib/tac_qlib/contrib/model/__pycache__/rank_ensemble.cpython-312.pyc + 3e80f2e08b661ddd2f58ffe5a6196063fa41ae51 tac-qlib/tac_qlib/contrib/model/__pycache__/rank_gbdt.cpython-312.pyc d3f051f3a8650c42fedc7b367b966f7c74fb5789 tac-qlib/tac_qlib/contrib/model/rank_ensemble.py - ccfe7d554989aa7f3e5a2128ae663e51b2207149 tac-qlib/tac_qlib/contrib/model/rank_gbdt.py + d03e6611338918d4aac5eea4adf26f85a3763652 tac-qlib/tac_qlib/contrib/model/rank_gbdt.py 4afcf9058231111c412925f4c4b84e81d656db87 tac-qlib/tac_qlib/contrib/strategy/__init__.py - 13a8e4a41ce9afde97a55756d666d3ff5cbbec0e tac-qlib/tac_qlib/contrib/strategy/__pycache__/__init__.cpython-312.pyc - 0bb5804a79611c66bc25988226ca0f1cdbe1a7eb tac-qlib/tac_qlib/contrib/strategy/__pycache__/optimal_stop.cpython-312.pyc + 6ad10c2ebe37c16417e67c7aeb731ad1fcb6da2f tac-qlib/tac_qlib/contrib/strategy/__pycache__/__init__.cpython-312.pyc + 8d684b3216b040071d9ee4fa920a0e0c7486d278 tac-qlib/tac_qlib/contrib/strategy/__pycache__/optimal_stop.cpython-312.pyc 79aaad9e39fcc740a773f4f63c512ce1086cfde0 tac-qlib/tac_qlib/contrib/strategy/optimal_stop.py 92e6e90eb0cd0a25142034560f27adb6b705b1a8 tac-qlib/tac_qlib/data/__init__.py - 3cbc0686e6f863d306d93c589a607a5bdb7201f2 tac-qlib/tac_qlib/data/__pycache__/__init__.cpython-312.pyc - 46bcdbcc173ff3a6281fed33d10c1bcac96876b0 tac-qlib/tac_qlib/data/__pycache__/config.cpython-312.pyc - 6df4f88af22ab4c026c14ef1835f2e630cdf850c tac-qlib/tac_qlib/data/__pycache__/providers.cpython-312.pyc + 7c4e6c345fad1978efe8860c0d977d0c02d6f8d9 tac-qlib/tac_qlib/data/__pycache__/__init__.cpython-312.pyc + 99e602392d51663cb06d5c425000b1ed1e5a916b tac-qlib/tac_qlib/data/__pycache__/config.cpython-312.pyc + 020dcdcf288e4832c8cf2386351f78d5ceb4fe13 tac-qlib/tac_qlib/data/__pycache__/providers.cpython-312.pyc 53c9007a928841fd3c3b08450f9a6520ce1ac091 tac-qlib/tac_qlib/data/config.py 8d0644f6f0d1efb94798ed444cc73e63b643459b tac-qlib/tac_qlib/data/providers.py diff --git a/code/tac-qlib/tac_qlib/contrib/__pycache__/__init__.cpython-312.pyc b/code/tac-qlib/tac_qlib/contrib/__pycache__/__init__.cpython-312.pyc index b5e28b7c0a10ab553eaa6303013a880731742378..b419ee55ed455a1c45423d1c9025ca5cc0a98576 100644 GIT binary patch delta 20 acmeyy^o@!8G%qg~0}yo1Zr#Y8%?JQN0tLJP delta 20 acmeyy^o@!8G%qg~0}vc{Z`sJ5%?JQMw*{pD diff --git a/code/tac-qlib/tac_qlib/contrib/data/__pycache__/__init__.cpython-312.pyc b/code/tac-qlib/tac_qlib/contrib/data/__pycache__/__init__.cpython-312.pyc index 715ab312125a446af751b928fe41cf41b99ffcd0..2f6c67620aa2f9e6aaaef3369361d9b3eac3d6ca 100644 GIT binary patch delta 19 Zcmcb?c!QDqG%qg~0}yo1Zk@<|763Nx1-}3Q delta 19 Zcmcb?c!QDqG%qg~0}vc{Z<)w_763N71*iZ3 diff --git a/code/tac-qlib/tac_qlib/contrib/data/__pycache__/handler.cpython-312.pyc b/code/tac-qlib/tac_qlib/contrib/data/__pycache__/handler.cpython-312.pyc index a82a6a236db93097d48748e541c2cf9caa4e48b5..fdd5923a70a399e8680913593ff111641947898e 100644 GIT binary patch delta 20 acmX>Yb})?lG%qg~0}yo1Zr#XjrVRi@v<2?~ delta 20 acmX>Yb})?lG%qg~0}vc{Z`sIgrVRi@X$9B- diff --git a/code/tac-qlib/tac_qlib/contrib/model/__pycache__/__init__.cpython-312.pyc b/code/tac-qlib/tac_qlib/contrib/model/__pycache__/__init__.cpython-312.pyc index 483221cf1d5bad779d3cf9505269b7fb0b3f165d..08dec87ccdf6bb5d2cf611ca3032a4280aaab8cf 100644 GIT binary patch delta 20 acmdnbw4aIlG%qg~0}yo1Zr#Xj!UzC3Y6TYn delta 20 acmdnbw4aIlG%qg~0}vc{Z`sIg!UzC39|Zsa diff --git a/code/tac-qlib/tac_qlib/contrib/model/__pycache__/rank_ensemble.cpython-312.pyc b/code/tac-qlib/tac_qlib/contrib/model/__pycache__/rank_ensemble.cpython-312.pyc index 1286dec07a861f25691b24f71ecc22d8eb3537df..6fb61946ea9a83dfb560de3717f5fbf482c4c00e 100644 GIT binary patch delta 20 acmezB`PGyAG%qg~0}yo1Zr#ZJN(BH*`3C9$ delta 20 acmezB`PGyAG%qg~0}vc{Z`sKGN(BH*t_ITp diff --git a/code/tac-qlib/tac_qlib/contrib/model/__pycache__/rank_gbdt.cpython-312.pyc b/code/tac-qlib/tac_qlib/contrib/model/__pycache__/rank_gbdt.cpython-312.pyc index 5185764bd55dbc63d16582bfcb6adc11b7e6d342..3e80f2e08b661ddd2f58ffe5a6196063fa41ae51 100644 GIT binary patch delta 3868 zcmZ`+Yiu0V72etR%j;b~7RQfdoOpvbcAS_%35i3R1ZP7U48)kwglKoXGhR)6(~yP<%xr6p@k)EI%<1tH-mrg0Tj4N`wVRjH9GA+{T-?#M`0|G|$66)IH-wLRyq zH!+W1Y46;7&Uel|=ggh&-u=gkLMrs9h6cY4TJiOl&b=F32(>Y9FWf)3tC0`9=sX?e z!+a2)_wfxc+D^CGZ3!D6deO%Fgr@5bw6fVwZ<=++Bfq}g;EB0l3R33t5xdQH)uuBP z0G(mGzCNCJm~QXpCc|bh6ZX48r|vLcZQE?u?PlMW&bDRdIyk^K@6y+ovDwb~&A~{s z!%+i${~pM&8;s%H1aSP#K{mX74n~H{a1P;fT|4iFWhrjnQ(G{l2SHEUJ$Lh7-eGw8 znyH(2@$Pn;;pW}Er`3LN+MKB6$tgUUV`zQ&O%ib zSzuL8)7airN>&FXAwQ!jLa&(-LQ**Wdk;Twa z_-SECuweTlZ1V*#9epKGIJ6cFT|QnszUVGHO7qoVtT4RR7`Z%CoLOYvZhEKv&GtKu z{e@#|(YCANf>>sjn{KpUYrhkHa7Dj$?$0-=dtBZO*%Uc&Sm6q7j)}^PH zPA+X*Dd% zK&Wv1b1021eV4vq;)5UM$J-9`Z=Sd8@P&WX)*0PM7-&;#<|S{BdDI)v*QwB{N9sD{ zF~d=3U?9nR8sNGO8ncasexhfh5Zp2Ivd^%(eoGR#K+{i(0Z6)_rWqZn#? z;W%*{;d-%=n|XVEHs54K%&@;RN;>uCdesaNB2S;|GC%aSx7Jr31v?;YPi`3As9Ey= zIZs*R*}L4k4>@Tk&&{%)I~ue2xPqjk8=PLxc>c3)GtetXboJj0uko zFb7hslMiL(oUE}w8r(g@PH;el1PNZ=7%24w zV^vvAz_SerjZ!jYXj2V1^8`PIPbf{}2SCEm#TyBJ0;Cl>E09*?G?YY!AL&4e8!`o! zw;ZCZTW%u2%hCzHaLS05i;_3#M5t3cPjt(5VNxJ~=j2(-i8LE;wp@@iuUUDw#EnDf zmWwhh*@A91qp6*!@RKZuoXl7bEvaHBfybm;>s1^}07xs-mTQ_L0HF^Fjv+x-vN(g{ zSWdhTXt+Hw|F5?`mc((jND``)g!i1(*7qKH9OO^IPb*P+|E$ei2tJZW){7V8R}No& zeBtpo(&gCe=c+C7rH5_|T^stHquMuA^&co4S@U%*3gywIo~mybP&LdZ%IT#CtG?a9 z;Qq$T{l)$(xvIYlkl?Sc*jGxIAGqV+{vGo`!{zQ0gV%PfaJO2k-3Kcj2j6e528Iid zt@iG`;k)Kr4*c|?QcFo#==e*dyAtWHMz&Q0Js&xTZZ$(k`pkufPdl*UaTmce)$;J1 z&cUsTJOVSa&-{6)n>l~;R;bJ{W9ARTG3FUFAMRv~n{R|abofpqC;^?BYvDX(Cr-oW z$1U0WNC?J9<4yu>2V1vx`2c@H>jN=zAIkjC;>~cF5ZEPMC~(TW2%ATnE=K$b39No<;nKnTYl>`%E=@j49lF zFZweVlQR>YBYUVLx5^PNs}a0xSPoTD2~FZ{xpb|>3%3ZZshBPz;% zf?d)4s`D)K%bTaWF4~!s=GvBh9dzw0s6?3Mh7WB*oUxcGGG`95qfF)IOY8yW`I=vZ znb@HLRH=aDtI%1ltilTtSwgvgJt0(nhaH(g1x80`$f~({>u%<+=963J!H zfd3KmX;FkvZuMFv?l-Dk^SZMsNZBO4bh$&!)$ z96>y|wQG91t*L(BT^U90L1a7mjmgILbWsL|oq{)eB7?^AN_czDjAu#CRAa^i_|4Eg zMBreyk(1c6XP%ZK~OXr6BF;5b|EoNGUuN2 zopZi>&b?>m$QuuLd%knKOE~s?y<>cEHaO|2LKh|*MjJembKKHhDY?eEZoi4!!Ab6M zPIAcQGiHe9xbCW~MJT;-+ii0?n8{G|__~SIcs{W9b7L0WO&)vddbe>s-*Vg-ua_E0 zOytZtzIt($%%e;LYsSO`d&aCeE@w6TXki_*kJ)sz;APpinMGZ)46z)oncQ@QyiZXy zw1S~kfcouEVht3d6JpLXSV4}KR*)Y(CFD?9g-Q354sVU)2?06jeP$7KKFJ>pkT1M} zw#6DHqy8c{;!fPOa5)PO>NUkG^~E#dxWOR#snoZ$7+hSVoMeh}f_3yRdFcKAaF{(9 z*!znN51`8jKqHt85B7jwM$JiCp(aJ8&Ujjhi@L0^ms;bQl$J?RtElN&Ri@^IqEjA= zO215bEt!ZjNYf?eS5;Y&s6C#>IG&dKs7aORUTajw30b2SmN7*6zGPa|sU;HC4G@9Og zkw5qRoU361&6oP}uN)gWTRDx+RZq0AK&NM7`0e)m=HrnI5Ai`<7(}Pu6yB~EqB5#bK%y{_I zo%yb{}0^ zCP~9x;7Ef|NOye?$`)qpkDAb05)mQ+WA7|DA&gqt$o3^hC>p{sa!QDznZnP)MsyH1 z!WxJX5Rkx5P6j>41m#n31^6W3C5sJ#^MCSi4>+JYY?RzZax0rrfqcAj%xm;&=}o7T z0_tQNG?U1x4NfDB79q)i`6te`h)8yK!)vrPiqmJDPO+TRNxCg(*Z1{dL zJ`F(wObC2uC!S(TXQyDt%>dg#7?m2N|D`95jjh{Y;-2Y>KqwZKNo)k4LE+><* zn1FDEp&I;zUc>?&~49%!E$V{OcpC?zE zT5F6!V^hGgG-HCOJqZKb-q cUL6UPp_bq3c@+A+EQ3&E{(^b diff --git a/code/tac-qlib/tac_qlib/contrib/model/rank_gbdt.py b/code/tac-qlib/tac_qlib/contrib/model/rank_gbdt.py index ccfe7d5..d03e661 100644 --- a/code/tac-qlib/tac_qlib/contrib/model/rank_gbdt.py +++ b/code/tac-qlib/tac_qlib/contrib/model/rank_gbdt.py @@ -53,23 +53,61 @@ from qlib.workflow import R __all__ = ["RankICLGBModel", "rankic_feval"] +def _group_averaged_rank(values: np.ndarray, gid: np.ndarray, offs: np.ndarray) -> np.ndarray: + """Averaged (tie-corrected) rank of ``values`` within each group, vectorized. + + ``gid`` maps each row to its group id; ``offs`` holds the cumulative row + offsets so that group ``i`` occupies rows ``[offs[i], offs[i+1])``. Returns + the same result as ``pandas.Series.rank(method='average')`` applied per + group, but in one pass (``np.lexsort`` is the only non-linear step). + """ + n = len(values) + order = np.lexsort((values, gid)) + ord_rank = np.empty(n, dtype=np.float64) + ord_rank[order] = np.arange(n, dtype=np.float64) - offs[gid[order]] + 1.0 + sg = gid[order] + sv = values[order] + newblock = np.empty(n, dtype=bool) + newblock[0] = True + newblock[1:] = (sg[1:] != sg[:-1]) | (sv[1:] != sv[:-1]) + blockid = np.cumsum(newblock) - 1 + block_mean = np.bincount(blockid, weights=ord_rank[order]) / np.bincount(blockid) + out = np.empty(n) + out[order] = block_mean[blockid] + return out + + def _per_day_spearman(preds: np.ndarray, labels: np.ndarray, group: np.ndarray) -> float: """Mean per-day Spearman rank correlation of preds vs labels. ``group`` holds the number of rows of each trading day (query group), in order. Days with <3 valid rows or a constant pred/label are skipped. + + Vectorized: per-day Spearman == Pearson of the per-day rank transforms, + and the Pearson moments (``sum``, ``sum`` of products/squares) aggregate + over each day with ``np.bincount``. Runs ~10x faster than the per-day + ``pd.Series.rank()`` loop that preceded it — this feval is invoked on the + train and valid panels every boosting round, per seed. """ if group is None or len(group) == 0: return 0.0 offs = np.concatenate([[0], np.cumsum(group.astype(int))]) - vals = [] - for i in range(len(group)): - s = slice(offs[i], offs[i + 1]) - p, l = preds[s], labels[s] - if len(p) < 3 or np.std(p) == 0 or np.std(l) == 0: - continue - vals.append(np.corrcoef(pd.Series(p).rank(), pd.Series(l).rank())[0, 1]) - return float(np.mean(vals)) if vals else 0.0 + gid = np.repeat(np.arange(len(group)), group.astype(int)) + rp = _group_averaged_rank(preds, gid, offs) + rl = _group_averaged_rank(labels, gid, offs) + n_g = group.astype(float) + s_p = np.bincount(gid, weights=rp) + s_l = np.bincount(gid, weights=rl) + s_pl = np.bincount(gid, weights=rp * rl) + s_pp = np.bincount(gid, weights=rp * rp) + s_ll = np.bincount(gid, weights=rl * rl) + cov = n_g * s_pl - s_p * s_l + var_p = n_g * s_pp - s_p ** 2 + var_l = n_g * s_ll - s_l ** 2 + denom = np.sqrt(var_p * var_l) + valid = (n_g >= 3) & (denom > 0) + corr = np.where(valid, cov / np.where(denom == 0, 1, denom), 0.0) + return float(corr[valid].mean()) if valid.any() else 0.0 def rankic_feval(preds, dataset): diff --git a/code/tac-qlib/tac_qlib/contrib/strategy/__pycache__/__init__.cpython-312.pyc b/code/tac-qlib/tac_qlib/contrib/strategy/__pycache__/__init__.cpython-312.pyc index 13a8e4a41ce9afde97a55756d666d3ff5cbbec0e..6ad10c2ebe37c16417e67c7aeb731ad1fcb6da2f 100644 GIT binary patch delta 19 ZcmaFG_==JHG%qg~0}yo1Zk@<|9{@Rs1@!;` delta 19 ZcmaFG_==JHG%qg~0}vc{Z<)w_9{@R21>OJv diff --git a/code/tac-qlib/tac_qlib/contrib/strategy/__pycache__/optimal_stop.cpython-312.pyc b/code/tac-qlib/tac_qlib/contrib/strategy/__pycache__/optimal_stop.cpython-312.pyc index 0bb5804a79611c66bc25988226ca0f1cdbe1a7eb..8d684b3216b040071d9ee4fa920a0e0c7486d278 100644 GIT binary patch delta 20 acmdlJxF?YNG%qg~0}yo1Zr#YeQ3C)(H3m}v delta 20 acmdlJxF?YNG%qg~0}vc{Z`sJbQ3C)&>IOUj diff --git a/code/tac-qlib/tac_qlib/data/__pycache__/__init__.cpython-312.pyc b/code/tac-qlib/tac_qlib/data/__pycache__/__init__.cpython-312.pyc index 3cbc0686e6f863d306d93c589a607a5bdb7201f2..7c4e6c345fad1978efe8860c0d977d0c02d6f8d9 100644 GIT binary patch delta 20 acmeBT>0;qN&CAQh00f=0TQ_q5X9NH;Y6W}% delta 20 acmeBT>0;qN&CAQh00hU~TQ+k4X9NH;9|dIq diff --git a/code/tac-qlib/tac_qlib/data/__pycache__/config.cpython-312.pyc b/code/tac-qlib/tac_qlib/data/__pycache__/config.cpython-312.pyc index 46bcdbcc173ff3a6281fed33d10c1bcac96876b0..99e602392d51663cb06d5c425000b1ed1e5a916b 100644 GIT binary patch delta 20 acmX>Rc_NbgG%qg~0}yo1Zr#YeR|fz`IR=XW delta 20 acmX>Rc_NbgG%qg~0}vc{Z`sJbR|fz_?gn%K diff --git a/code/tac-qlib/tac_qlib/data/__pycache__/providers.cpython-312.pyc b/code/tac-qlib/tac_qlib/data/__pycache__/providers.cpython-312.pyc index 6df4f88af22ab4c026c14ef1835f2e630cdf850c..020dcdcf288e4832c8cf2386351f78d5ceb4fe13 100644 GIT binary patch delta 20 acmbP}F(-rjG%qg~0}yo1Zr#W&XaWF1eFd!m delta 20 acmbP}F(-rjG%qg~0}vc{Z`sH#XaWF1G6j|Z