Skip to content

View translation

HkBlueChipMonthlyCrossSectionalReversalBasketHkeq

Hypotheses

Hong Kong Large-Cap Cross-Sectional Monthly REVERSAL, Long-Only Equal-Weight Basket (HKEQ — buy the 6 biggest RELATIVE losers of the last 21 sessions out of a fixed 24-name HSI-blue-chip universe, hold 21 sessions, roll; a brand-new venue and price estate with ZERO prior experiments, 3-parameter)

Hypotheses

A LONG-ONLY, MULTI-INSTRUMENT, low-turnover CROSS-SECTIONAL REVERSAL basket on HONG KONG equities (HKEX main board, venue HKEQ) — a venue with 174 daily instruments in the catalog (2018-01-02 -> today) and literally ZERO of the factory's 1390 hypotheses ever pointed at it. The corpus is 70% Binance USD-M and 62% BTC; this hypothesis buys a completely different price estate with a completely different participant mix (retail + southbound mainland flow + index trackers), so whatever it produces is statistically independent of everything else in the programme. Mechanism (NOT time-series momentum, NOT an RSI dip-buy, NOT a macro/regime ETF rotation — all three of which are documented dead families here): every 21 trading sessions, rank a FIXED 24-name universe of HK blue chips by their trailing 21-session total return, subtract the universe MEDIAN return (cross-sectional demeaning, so the ranking is purely RELATIVE and carries no market-timing call), and hold an equal-weight basket of the 6 most negative (worst relative performers). Hold 21 sessions, then re-rank and roll; names that are still in the bottom-6 are NOT traded (turnover reduction = fee reduction). No shorts — HKEQ is a CASH account, so long-only is a venue constraint, not a preference. Why this is not the dead US-ETF-rotation family: there is no regime gate, no SMA, no macro asset-class switch and no timing of the market. The book is always 100% invested in 6 names; the only decision is WHICH 6, and that decision is made ~104 times over the history across 24 names, producing ~400 independent single-name bets — two orders of magnitude more effective sample than the 35-77 rebalances that made every SPY/QQQ/GLD/TLT rotation die overfit (L99). It is also not the crypto pairs/cointegration family (L96) — there is no spread, no hedge leg, no stationarity assumption, and no second fee-paying leg (L95). FEE ARITHMETIC (HKEQ is an EXPENSIVE venue and the design is built around that): statutory cost is ~0.11%/side (HK stamp duty 0.10% EACH side + SFC levy 0.0027% + HKEX trading fee 0.00565% + FRC levy), plus a ~4 bps half-spread on HSI large caps => round-trip ~0.30% of notional. Monthly idiosyncratic return dispersion in HK blue chips is ~9-11% (1 sd), and the documented Asia-ex-Japan pattern is REVERSAL rather than momentum at the 1-month horizon (momentum is empirically absent in HK/China large caps; short-horizon contrarian spreads of roughly +0.8% to +1.5%/month between relative-loser and relative-winner deciles). Expected per-trade capture = universe drift (~+0.25%/month) + reversal tilt (~+0.7%) ~= 0.95% of notional per 21-session hold, i.e. ~3x the 0.30% round-trip. A hold that long also means fee drag is ~0.30% per MONTH of exposure, not per day — the exact opposite of the sub-fee fast-cadence mechanisms that produced 489 fee_edge deaths here. Universe (all verified present in the catalog with unbroken 1-DAY history from 2018-01-02, so there is no listing-gap survivorship artifact from the 2018-2021 HK mega-listings): 0700 Tencent, 0005 HSBC, 1299 AIA, 0941 China Mobile, 0388 HKEX, 0939 CCB, 1398 ICBC, 3988 BOC, 2318 Ping An, 1211 BYD, 0883 CNOOC, 0857 PetroChina, 0386 Sinopec, 2628 China Life, 2388 BOCHK, 0001 CK Hutchison, 0016 SHK Properties, 0002 CLP, 0003 HK&China Gas, 0066 MTR, 0267 CITIC, 0288 WH Group, 1113 CK Asset, 0823 Link REIT. Data span 2018-01-02 -> 2026-08-21 (~8.6 years) covers four distinct regimes: 2018 trade war, 2019 protests, 2020 COVID crash + recovery, 2021-2022 China policy crackdown bear (HSI -50%), 2023-2026 recovery — so the walk-forward windows are genuinely different macro environments rather than three slices of one bull market. Session venue: HKEQ uses the XHKG calendar in src/data/market_calendar.py; daily bars are stamped at the session close and there is no overnight/weekend gap problem. Long-only, no leverage, whole-share sizing, HKD-denominated account.

Hypotheses

Implements the hypothesis exactly: fixed 24-name universe, 21-session trailing return, cross-sectional demeaning by the universe median, equal-weight long of the 6 worst relative performers, ~21-session hold with roll, long-only on HKEQ, no leverage, no regime gate and no absolute-return filter (the book is always 100% invested; the only decision is WHICH 6). The 21-session hold/roll is expressed as a CALENDAR month grid derived from the bar's own timestamp (year*12+month // rebalance_months) rather than a process-relative bar counter, so the ~104 rotation dates are identical across restarts, backtests and paper replay; a boundary is detected by comparing consecutive processed bars, so a restart mid-month does not churn the book. Cross-leg data is matched by exact session TIMESTAMP (bisect over per-leg (ts, close) lists trimmed as one unit), never by buffer position — the catalog re-stamps a handful of HK sessions and one leg missing a session must not shift another leg's return. Sizing is NAV-relative but hard-capped by free cash with a fee head-room buffer, because a CASH venue rejects a buy it cannot fund. Turnover control (no trade for names still in the bottom-6) is the fee defence: measured rotation is ~0.7 of the basket per month, i.e. ~0.22% of notional per month of exposure. ONE CONCERN, stated as required and implemented as asked anyway: an offline replication of exactly this rule on the catalog's 2018-2026 HK daily closes shows the demeaned-loser basket UNDERPERFORMING the equal-weight universe by ~0.17%/month (gross 0.18%/month vs 0.35% for the universe, i.e. roughly flat after the 0.22%/month rotation cost), so the documented Asia-ex-Japan 1-month contrarian premium does not appear at the 21-session horizon in this blue-chip universe — the backtest is likely to show the basket tracking the universe rather than beating it, and the Research Lead/Analyst own that call.

Hypotheses

Negative expectancy on a fully reliable 445-trade / 8.6-year sample, with the premise measurably absent. PF 0.933 (<1), total return -12.02%, Sharpe -0.098, and per-trade return 0.109% versus the ~0.30% HKEQ round trip the hypothesis was designed around. Those costs were never actually charged (HKEQ Equity instruments bypass `_apply_fees`), so a manual ~2%/yr haircut on ~4 rotations/month puts the true result near -2.5 to -3%/yr. The hypothesized Asia-ex-Japan 1-month contrarian premium is simply not present at the 21-session horizon in HSI blue chips — confirmed independently by the developer's own offline replication (loser basket 0.18%/month gross vs 0.35%/month for the equal-weight universe). Optimization cannot lift an edge that is below cost and gross-negative in sign; the three tunables only reshuffle which losers get bought. Not `revise_hypothesis`: the reversal premise itself is falsified on the exact universe it was specified for, and the venue's stamp duty leaves no room for a marginal variant.

Implementation

Long-only, always-invested cross-sectional MONTHLY REVERSAL basket on a fixed 24-name HKEX blue-chip universe (HKEQ, 1-DAY bars, CASH account, leverage 1). Every session each name's trailing 21-session return is computed and the universe MEDIAN subtracted, giving a purely RELATIVE score with no market-timing component; calculate_signal returns the primary name's (0700) demeaned score every bar. On each calendar rebalance boundary (month grid = ~21 HK sessions) the 6 most negative relative performers become the target basket: names dropping out are closed, new names are bought equal-weight (95% gross / 6 names) sized against NAV and hard-capped by the cash the CASH account actually holds, whole shares. Names that stay in the bottom-6 are NOT traded, so the ~0.30% HK round trip (0.11%/side stamp duty + ~4bp half spread) is paid only on the ~70% of the book that actually rotates, once a month. A target that could not be funded on the boundary session (sale proceeds not yet credited — HK is T+2) is retried on the following sessions until the next boundary.

Verification Results

Not a developer fix. Factory-level: narrow the `Equity` early-return in `_apply_fees` to venues whose VenueConfig fees are actually 0.0 (USEQ), and rebuild non-zero-fee Equity instruments with maker/taker set so MakerTakerFeeModel charges them; and raise `ROUND_TRIP_COST_PCT['HKEQ']` from 0.10 to ~0.30 (0.22% statutory + ~0.08% spread). Until then the analyst must haircut HKEQ/CNEQ results by hand.

Verification Results

Venue cost model gap (infrastructure, NOT fixable in this strategy file): HKEQ instruments are NT `Equity`, and `src/backtesting/runner.py::_apply_fees` short-circuits on `isinstance(instrument, Equity)` before it ever reads `venue_config.maker_fee/taker_fee`. That early return was written for USEQ (genuinely commission-free) but now also swallows HKEQ's declared 0.11%/side and CNEQ's 0.05%/side. Sandbox evidence: total_commission=0.0 and commission_pct_of_gross=0.0 on 336 closed positions at HKEQ. The strategy's fee arithmetic (0.95%/month capture vs 0.30% round trip) therefore cannot be validated by this backtest — the cost side is zero.

Verification Results

Either drop the `signal <= 0.0` condition (membership in `self._targets` is already the entry decision, and `_deploy` has already applied the ranking) or move the cash debit for the primary so it only happens once the entry is actually going to be submitted — e.g. set `_primary_enter`/`_primary_qty` and debit `cash_left` inside the same guarded branch, or apply the `<= 0` filter when building `missing` so the primary is excluded from the loop rather than reserved-then-vetoed.

Verification Results

The PRIMARY leg (0700) is gated differently from the other 23 legs. `_deploy()` decides the basket for all names identically and debits `cash_left` for the primary at line 224, but the primary's order is only actually submitted if `should_enter()` also sees `signal <= 0.0` (line 269). On a rebalance boundary the primary is by construction in the bottom-6 of 24 so its demeaned return is strictly negative and the gate is a no-op. On a RETRY session, however (a target that could not be funded on the boundary day is re-attempted every session until the next boundary), `rel` has been recomputed on a fresh 21-session window and the primary's demeaned score can have flipped positive while it is still in `self._targets`. The primary is then silently skipped, yet `cash_left` has already been reduced by its full `per_name` cost inside the same `_deploy()` call, so a later name in the loop can be starved of cash that was never spent. The 23 extra legs have no such veto.

Verification Results

No change required. If exact 21-session windows matter for parity with an offline replication, record the primary's close in `on_bar`-independent state (e.g. also record the primary inside a bar-agnostic hook) so its history has the same gap structure as the extras.

Verification Results

The cross-leg alignment barrier in the base template (`_maybe_process_primary` waits for all 23 same-timeframe extra legs to carry a bar at the primary's timestamp) means a single missing/halted session on ANY one of the 24 names skips the entire session for the whole strategy. Because the primary's close is recorded in `calculate_signal` (which only runs when the barrier passes) while extras are recorded in `on_extra_bar` (always), the primary's `_hist` develops gaps the extras do not have, so `ref_ts = prim_ts[-1 - lookback]` can be 22+ calendar sessions back rather than exactly 21. Impact is bounded and benign here (the `_close_at` bisect is timestamp-keyed, so all 24 legs still measure the SAME window, and `_tol_ns` = 10 days covers Lunar New Year), and a skipped boundary session merely defers the rebalance to the first processed session of the new month. Flagged so it is not mistaken for a lookback bug when comparing against an offline replication that uses an ungapped session index.

Verification Results

Three things the analyst should weigh at backtest review, none of which are code defects. (1) COSTS ARE NOT CHARGED: HKEQ catalog instruments are NautilusTrader `Equity` objects and `BacktestRunner._apply_fees()` returns every `Equity` untouched (the early-return's comment is US-specific: 'commission-free retail execution is the venue truth'). HKEQ's VenueConfig declares maker_fee=taker_fee=0.0011 (0.11%/side stamp duty + levies) but that never reaches the instrument, and the sandbox confirms it: total_commission=0.0, commission_pct_of_gross=0.0, impact_folded=false. The ~0.22% statutory round trip plus the 4bp half-spread — the single cost this whole hypothesis is designed around — is absent from reported PnL. Worse, `promotion_gates.ROUND_TRIP_COST_PCT['HKEQ']=0.10` also omits stamp duty, so the economics gate will not re-impose it either. Apply a manual haircut: measured turnover is ~0.7 of a 6-name book per month, i.e. ~0.15-0.22% of NAV per month, ~1.8-2.6%/yr, against a sandbox CAGR of 2.44%. That alone roughly erases the sandbox's return. (2) The DEVELOPER'S OWN offline replication of exactly this rule on the same 2018-2026 HK closes reports the demeaned-loser basket GROSS at 0.18%/month vs 0.35%/month for the equal-weight universe — i.e. NEGATIVE relative alpha before any cost. The sandbox is consistent with that read (Sharpe 0.198, CI -0.654..0.959, PSR 0.543, Calmar 0.09, max DD 27.1% with a 1705-day underwater duration, and alpha/beta/information_ratio all null so the vs-basket comparison was never computed). The documented Asia-ex-Japan 1-month contrarian premium is the premise, and the only in-house evidence says it is not present at the 21-session horizon in HSI blue chips. (3) impact_cost_pct=21.4% of gross on a HKD 100k book with capacity_usd 2.19M — inside the 50% soft floor but material for a mechanism whose entire claimed edge is ~0.7%/month. Recommend the full backtest be read with an explicit 0.30% round-trip haircut applied to the ~4.2 rotations/month before any optimize decision.

Backtest Review

Genuinely novel venue/price estate (HKEQ, zero prior experiments) with clean 2018-2026 daily history across four distinct macro regimes

Backtest Review

Large, reliable sample: 445 single-name trades over 8.6 years, ~104 monthly rebalances — not the low-trade-count trap that kills ETF rotations

Backtest Review

Mechanism implemented as described: long-only, always-invested, 6-name demeaned-loser basket, turnover suppressed on names that stay in the bottom-k (avg holding 40d, no shorts)

Backtest Review

Negative expectancy on a reliable sample: PF 0.933, total_return -12.02%, CAGR -1.52%, Sharpe -0.098, expectancy -$27.02/trade

Backtest Review

avg_trade_return_pct 0.109% is ~1/3 of the 0.30% HKEQ round-trip floor — and the loss is BEFORE costs

Backtest Review

Costs never charged: total_commission 0.0, commission_pct_of_gross 0.0, impact_folded false — the ~0.22% statutory round trip + spread (~2%/yr of NAV) is absent from the reported PnL

Backtest Review

Negative in 6 of 9 calendar years; loses worst in the CALM vol tercile (-15.1%), so the failure is the base case, not a stress artifact

Backtest Review

Max drawdown 32.3% with 2833 days underwater

Backtest Review

QA's edge concern is borne out: the developer's own offline replication measured the demeaned-loser basket at 0.18%/month gross vs 0.35%/month for the equal-weight universe — negative relative alpha before any cost, which the full backtest reproduces

Outcome Summary

HkBlueChipMonthlyCrossSectionalRever-3a9fe37ac4

Outcome Summary

The hypothesis staked out a genuinely new price estate for the factory — HKEQ, 174 daily instruments and zero prior experiments — and argued that a 21-session hold on the 6 most relatively oversold HSI blue chips would capture ~0.95%/month against a ~0.30% stamp-duty-heavy round trip. The implementation matched the design (long-only, always invested, ~40-day average holds, turnover suppressed on names that stayed in the bottom-6) and produced an unusually trustworthy sample: 445 single-name trades across the 2018 trade war, 2019 protests, COVID, the 2021-22 China bear and the later recovery. But the edge had the wrong sign: -12.02% total return, profit factor 0.933, Sharpe -0.098, and a 0.109% per-trade return that sat at roughly a third of the round-trip cost the engine never even charged (HKEQ Equity instruments bypass `_apply_fees`, so a manual ~2%/yr haircut would push the true result to about -2.5 to -3%/yr). The analyst abandoned it at backtest review rather than spend hours optimizing three tunables that only reshuffle which losers get bought, noting the Asia-ex-Japan contrarian premium is simply not present at the 21-session horizon in HSI large caps.

Outcome Summary

Before committing a multi-instrument basket to the pipeline, confirm the cross-sectional premium exists gross-of-cost on the exact universe — the developer's own offline replication already showed the loser basket at 0.18%/month versus 0.35%/month for the equal-weight universe, i.e. negative relative alpha that no parameter search could repair — and check that the venue's fees are actually charged by the engine before reading per-trade returns.

Outcome Summary

The analyst's backtest-review gate returned `abandon` before optimization: negative expectancy on a reliable 445-trade sample with the hypothesized edge measurably absent, losing in 6 of 9 calendar years and worst in the calm vol tercile (-15.1%). Optimization, analysis, risk review and promotion stages were never reached.

Outcome Summary

A long-only HKEQ basket that every 21 sessions bought the 6 worst relative performers out of a fixed 24-name HSI blue-chip universe (returns demeaned against the universe median) and held them a month, betting on a 1-month cross-sectional reversal premium in Hong Kong large caps.

Outcome Summary

Over 2018-01-02 to 2026-09-10 (2,058 data days, 2,146 bars) it made 445 long trades with a 50.6% win rate but lost money: total return -12.02%, CAGR -1.52%, Sharpe -0.098, profit factor 0.933, expectancy -$27.02/trade, max drawdown 32.3% over 2,833 days underwater. Avg trade return was 0.109% of notional, and commissions were recorded as 0.0 (total_commission 0.0, commission_pct_of_gross 0.0, impact_folded false), so even that figure is before the ~0.30% HKEQ round trip.
Strategy report

Backtest and paper results are hypothetical. Trading involves risk of loss.