Task #5 Decision Log
This is the canonical decision log for Task #5 A-share leader strategy. It records what we tested, how we tested it, the result, and the decision. RayDario owns strategy rationale additions; JimSimons owns engineering method, scripts, outputs, and site links.
Current Locked Version
**v1.2 candidate** = v1.1 production + public-fund combined sponsorship bonus.
- Entry filter: RPS250 > 80 and RPS125 > 80.
- Sponsorship score: public-fund combined bonus using market-value and holding-count scores, release-date PIT merged. This is a small score bonus, not a hard filter.
- Risk controls: strict HS300 M-filter, Shenwan industry cap <= 30% NAV, 8% entry weight, max 12 holdings, 15% winner trim.
- Friction: 50 bp buy slippage + 50 bp sell slippage + 10 bp one-way trading cost.
- Metrics: FULL annualized 14.76%, vol 19.97%, Sharpe 0.739, max drawdown -22.34%, average exposure 28.47%.
- Candidate output: output/streaming_v0/v1_2_candidate/summary.md.
2026-05-26 ATR / Winner Trim Research Update
Status: documented for strategy-governance review. Production/P1/P2 are not changed by this log entry.
Canonical memo: docs/research/task5_v15_atr_trim_decision_memo.md.
Official sample: 2015-02-17 to 2026-05-15 true-extended v1.3 Y2. Baseline replay for ATR sensitivity matched cached v1.3 Y2 NAV with max absolute daily NAV difference around 8.9e-16.
Rejected Mechanical Fundamental Overlays
| Idea | Result | Decision |
|---|---|---|
| Sell after two consecutive EPS YoY deceleration observations | All tested variants materially underperformed v1.3 Y2. Best tested annualized return was about 12.59% vs baseline 16.21%. | Do not add automatic sell rule. Manual fundamental-risk review signal only. |
| Add strict_score bonus for consecutive EPS acceleration | All tested bonus variants underperformed baseline Sharpe/NAV. Best strict version was 15.98% annualized / 0.825 Sharpe / 4.979x NAV vs baseline 16.21% / 0.842 / 5.084x. | Do not add mechanical strict_score bonus. Manual quality label only. |
Artifacts:
- scripts/run_task5_eps_deceleration_sell_ab.py
- output/streaming_hist_2012/v1_5_eps_deceleration_sell_ab/
- scripts/run_task5_eps_acceleration_bonus_ab.py
- output/streaming_hist_2012/v1_5_eps_acceleration_bonus_ab/
ATR Initial Stop Sensitivity
Only the initial ATR stop multiplier changed. Entry rules, smart capacity, chain cap, winner trim, breakeven/MA stops, trend exits, and fundamental disproof exits stayed unchanged.
| ATR initial stop | Annualized | Sharpe | MDD | Final NAV | ATR stop sells | Read |
|---|---|---|---|---|---|---|
| 1.5x | 13.80% | 0.715 | -32.89% | 4.052x | 320 | Too tight; heavy whipsaw |
| 2.0x | 14.97% | 0.788 | -27.62% | 4.528x | 230 | Still too tight |
| 2.5x current | 16.21% | 0.842 | -29.25% | 5.084x | 186 | Baseline |
| 2.75x | 16.93% | 0.876 | -29.02% | 5.439x | 160 | Improves |
| 3.0x | 17.04% | 0.879 | -27.46% | 5.494x | 145 | Improves |
| 3.25x | 17.39% | 0.894 | -27.23% | 5.672x | 134 | Best core grid point |
| 3.5x | 17.20% | 0.887 | -27.91% | 5.573x | 130 | Strong |
| 5.0x | 17.26% | 0.891 | -26.53% | 5.606x | 100 | Strong but looser |
Interpretation: v1.3's 2.5x initial stop appears too tight for A-share leader volatility. A 3.0x-3.5x band improves the frontier; 3.25x is the most balanced single-parameter candidate.
Artifacts:
- scripts/run_task5_atr_stop_sensitivity.py
- output/streaming_hist_2012/v1_5_atr_stop_sensitivity/
Robustness and Interaction Checks
ATR 3.25x is not only a single-window result:
| Window | 3.25x return | 2.5x return | Delta | 3.25x MDD | 2.5x MDD | MDD delta |
|---|---|---|---|---|---|---|
| FULL | +467.21% | +408.43% | +58.78 pp | -27.23% | -29.25% | +2.02 pp |
| 2015-2017 | +59.99% | +59.66% | +0.34 pp | -26.70% | -24.92% | -1.78 pp |
| 2018-2023 | +74.68% | +61.98% | +12.70 pp | -25.63% | -26.84% | +1.21 pp |
| 2024-2026 | +102.08% | +96.04% | +6.04 pp | -17.65% | -17.68% | Flat |
| 2025 Q4 | -3.23% | -6.11% | +2.88 pp | -13.89% | -14.07% | +0.18 pp |
| 2026 YTD | +38.01% | +38.84% | -0.82 pp | -9.23% | -9.48% | +0.25 pp |
ATR 3.25x beats ATR 2.5x under each tested winner-trim threshold:
| ATR / trim | Annualized | Sharpe | MDD | Final NAV |
|---|---|---|---|---|
| 2.5x / 15% current | 16.21% | 0.842 | -29.25% | 5.084x |
| 3.25x / 15% | 17.39% | 0.894 | -27.23% | 5.672x |
| 2.5x / 12% | 16.41% | 0.870 | -29.24% | 5.179x |
| 3.25x / 12% | 17.85% | 0.935 | -27.22% | 5.916x |
| 2.5x / 20% | 16.05% | 0.833 | -29.26% | 5.009x |
| 3.25x / 20% | 17.59% | 0.903 | -27.23% | 5.779x |
Fresh gradual remains the default deployment policy. Under ATR 3.25x, copy-full and staged-copy still do not pass the robustness gate: 12-month median return delta versus fresh gradual was -0.80 pp for copy-full and -1.13 pp for staged4, with worse MDD.
Artifacts:
- scripts/run_task5_atr_stop_robustness.py
- output/streaming_hist_2012/v1_5_atr_stop_robustness/
ATR 3.25x + Winner Trim 12% Combo
Independent four-way comparison:
| Scenario | Annualized | Sharpe | MDD | Final NAV | Trades | ATR sells | Trim sells |
|---|---|---|---|---|---|---|---|
| Current 2.5x / 15% | 16.21% | 0.842 | -29.25% | 5.084x | 695 | 186 | 41 |
| ATR-only 3.25x / 15% | 17.39% | 0.894 | -27.23% | 5.672x | 643 | 134 | 39 |
| Trim-only 2.5x / 12% | 16.41% | 0.870 | -29.24% | 5.179x | 799 | 188 | 145 |
| Combo 3.25x / 12% | 17.85% | 0.935 | -27.22% | 5.916x | 746 | 136 | 142 |
The combo improves annualized return by +1.64 pp, Sharpe by +0.094, MDD by +2.03 pp, and final NAV by +0.832x versus current v1.3.
Segment attribution for combo:
| Window | Combo return | Current return | Delta | Combo MDD | Current MDD |
|---|---|---|---|---|---|
| 2015-2017 | +60.76% | +59.66% | +1.11 pp | -25.81% | -24.92% |
| 2018-2023 | +79.53% | +61.98% | +17.55 pp | -25.62% | -26.84% |
| 2024-2026 | +104.10% | +96.04% | +8.06 pp | -17.60% | -17.68% |
| 2025 Q4 | -2.68% | -6.11% | +3.43 pp | -13.41% | -14.07% |
| 2026 YTD | +37.89% | +38.84% | -0.94 pp | -9.28% | -9.48% |
Artifacts:
- scripts/run_task5_atr325_trim12_combo.py
- output/streaming_hist_2012/v1_5_atr325_trim12_combo/
Recommendation and Governance
Engineering recommendation:
1. Advance ATR initial stop 2.5x -> 3.25x as the primary low-complexity production-candidate change.
2. Keep winner trim at 15% if the next production step is intended to be a single-parameter v1.4 change.
3. Keep deployment policy as fresh gradual.
4. Keep ATR 3.25x + trim 12% as a stronger but higher-bar v-next candidate. It changes two sell-side parameters and should require one more anti-overfit check before production adoption.
RayDario CIO ruling on 2026-05-26: ship ATR 3.25x as the v1.4 single-parameter production change after Kaite green-light; do not ship the double-parameter combo yet. Combo is deferred to v1.5 candidate research.
Version Timeline
| Version | Test / Change | Result | Decision |
|---|---|---|---|
| v0 strict baseline | Weekly strict candidates + daily active-set tracking; no realistic slippage; no industry cap. | FULL annualized 18.00%, Sharpe 0.88, MDD -21.78%, avg exposure 29.64%. | Useful research baseline, but too optimistic for production. |
| v0+ sensitivity | M-filter variants, industry cap, 50 bp slippage. | Relaxed M-filters worsened drawdown; industry cap had near-zero alpha cost; slippage materially reduced Sharpe. | Keep strict M-filter, add industry cap, make 50 bp slippage default. |
| v1 production | strict M-filter + 30% industry cap + 50 bp slippage + 10 bp cost. | FULL annualized 13.69%, Sharpe 0.678, MDD -24.41%. | Production baseline before rule enhancements. |
| per-rule A/B | Test Kaite buy rules and O'Neil sell rules one by one on top of v1. | B3 improved Sharpe/MDD; other rules failed or did not pass drawdown criteria. | Adopt B3 only. |
| v1.1 production | v1 + B3 dual-window RPS. | FULL annualized 14.34%, Sharpe 0.716, MDD -23.42%. | Current locked candidate. |
| v1.2 candidate | v1.1 + public-fund combined sponsorship bonus. | FULL annualized 14.76%, Sharpe 0.739, MDD -22.34%; stress windows show 0 exposure / 0 MDD. | Accepted as Task #5 IC pack v1 candidate. |
Test Results
v0+ Sensitivity
Script: scripts/run_task5_v0plus_sensitivity.py.
Output: output/streaming_v0/v0plus_sensitivity/task5_v0plus_sensitivity_summary.md.
| Question | Method | Result | Decision | Why |
|---|---|---|---|---|
| Should M-filter be relaxed? | Compare strict HS300 close > MA50 and MA50 > MA200 against relaxed variants. | Relaxed variants worsened Sharpe and max drawdown. | Keep strict M-filter. | A-share leader strategy is beta-sensitive; bear-market stock picking does not compensate for market regime risk. |
| Should industry cap be added? | Add Shenwan L1 industry cap <= 30%. | Near-zero alpha cost, small governance improvement. | Add cap. | Avoid concentration without materially changing alpha. |
| Should slippage be default? | Add 50 bp buy/sell slippage and 10 bp one-way cost. | Sharpe fell from paper 0.88 to realistic 0.678. | Use realistic friction as default reporting line. | Prevent false comfort from paper alpha. |
Buy Rule A/B
Script: scripts/run_task5_per_rule_ab.py.
Output: output/streaming_v0/per_rule_ab/task5_per_rule_ab_summary.md.
Each rule was tested individually on top of v1 production. Lock rule: Sharpe > v1 baseline and max drawdown >= -25%.
| Rule | Result | Decision | Why |
|---|---|---|---|
| B1 EPS/revenue two-quarter persistence | Sharpe 0.507, MDD -27.87%. | Reject. | Too restrictive and worsens drawdown. |
| B2 RSI12 > 50 | Sharpe 0.527, MDD -24.52%. | Reject. | Does not improve frontier. |
| B3 RPS250 and RPS125 both > 80 | Sharpe 0.716, MDD -23.42%. | **Adopt.** | Confirms persistent relative strength across long and medium windows. |
| B4 volume ratio > 1.5 | Sharpe 0.523, MDD -20.39%. | Reject. | Cuts exposure too much; volume spike is not a reliable pre-entry filter here. |
| B5 turnover < 10% | Sharpe 0.690, MDD -26.48%. | Reject. | Slight Sharpe gain but violates drawdown threshold. |
B5 Real Turnover Retest
Script: scripts/build_task5_turnover_rate.py then scripts/run_task5_per_rule_ab.py.
Data: RQData get_turnover_rate(..., fields="today"), 2,057,280 rows for 832 active-universe stocks from 2015-01-05 to 2026-05-15.
Decision: B5 remains rejected. Earlier proxy was invalid; true turnover fixed the data issue, but the rule still failed the drawdown criterion.
O'Neil Sell Rule A/B
Script: scripts/run_task5_per_rule_ab.py.
Each sell overlay was added on top of existing v1 sell rules, not used standalone.
| Rule | Trigger Profile | Result | Decision | Diagnosis |
|---|---|---|---|---|
| S1 exhaustion gap | 0 extra triggers. | Same as baseline. | Reject. | Signal is absent under A-share microstructure. |
| S2 climax top | 1,304 extra trims; trades 458 -> 1,740. | Sharpe 0.512. | Reject. | Sells winners too early and too frequently. |
| S3 high-volume stall | 1 extra trigger. | Sharpe 0.676. | Reject. | Almost no signal. |
| S4 down-day proxy | 1,494 extra trims; avg exposure 13.4%. | Sharpe 0.421. | Reject. | Over-trims normal pullbacks and starves exposure. |
| S5 close > 1.7 * MA200 | 1,581 extra trims; median holding days 19 on overlay sells. | Sharpe 0.285. | Reject. | Cuts true leaders in their main advance. |
| S6 new-high fail | 245 extra exits. | Sharpe 0.338, MDD -28.26%. | Reject. | Treats normal A-share retracements as failure and worsens drawdown. |
LHB Sponsorship A/B
Scripts: scripts/build_task5_lhb_sponsorship.py, scripts/run_task5_sponsorship_ab.py.
Data: RQData dragon-tiger-list details, 159,002 raw detail rows, 14,607 stock-date rows. PIT merge uses 20-calendar-day backward lookback.
Output: output/streaming_v0/sponsorship_ab/task5_v0plus_sensitivity_summary.md.
| Variant | Result | Decision | Why |
|---|---|---|---|
| Institutional bonus | Sharpe 0.610, MDD -26.18%. | Reject. | Worse risk-return. |
| Northbound bonus | Sharpe 0.627, MDD -24.41%. | Reject. | Does not beat baseline. |
| Combined bonus | Sharpe 0.619, MDD -26.18%. | Reject. | Worse risk-return. |
| Positive filter | Sharpe 0.087, avg exposure 11.34%. | Reject. | Overfilters and starves the strategy. |
Public Fund Sponsorship A/B
Scripts: scripts/build_task5_fund_sponsorship.py, scripts/run_task5_fund_sponsorship_ab.py.
Data: RQData public-fund holdings. Each report date uses top 500 equity-like funds by latest size, A-share holdings only, aggregated by stock/report period. PIT merge uses the actual release_date, not the report period date.
Output: output/streaming_v0/fund_sponsorship_ab/task5_fund_sponsorship_ab_summary.md.
| Variant | Result | Decision | Why |
|---|---|---|---|
| Market-value bonus | Sharpe 0.738, MDD -25.17%. | Reject. | Improves Sharpe but breaches -25% drawdown line. |
| Holding-count bonus | Sharpe 0.723, MDD -22.36%. | Pass but not final choice. | Improves drawdown but weaker than combined. |
| Combined bonus | Sharpe 0.739, MDD -22.34%. | **Accept as v1.2 candidate.** | Best frontier improvement; uses durable sponsorship signal without hard-filtering universe. |
| Positive filter | Sharpe 0.696, MDD -23.42%. | Reject. | Hard filter does not improve frontier. |
Stress Tests
Script: scripts/build_task5_stress_report.py.
Output: output/streaming_v0/stress_tests/task5_stress_summary.md and stress_detail.md.
| Period | Result | Interpretation |
|---|---|---|
| 2015 crash | v1/v1.1/v1.2 stock-level exit logs unavailable because strict candidate backtest has no 2015 positions. HS300 -43.29%, CSI800 -44.13%. M-filter was off throughout the window. | Data coverage limits stock-level conclusion. Regime filter would have blocked entries. |
| 2018 bear | v1/v1.1/v1.2 return 0%, MDD 0%, exposure 0. HS300 -26.34%, CSI800 -28.37%. | No strict positions existed; M-filter turned off on 2018-02-07 and stayed off. Passes protection goal, but this is an out-of-market result rather than exit-timing proof. |
| 2024 small-cap crash | v1/v1.1/v1.2 return 0%, MDD 0%, exposure 0. HS300 -0.63%, CSI800 -1.76% in selected window. | M-filter was already off at the start; strategy avoided new entries and held no positions. |
Open Items
- Public fund sponsorship: feasible via fund.get_holdings, but full universe is very large. Needs a separate PIT data-engineering plan before A/B testing.
- IC pack v1: summarize v1.2 candidate and reference this decision log.
- Stress test limitation: current strict candidate simulation begins stock-level effective exposure in 2019-03. A true 2015 exit-timing test requires extending the candidate/fundamental data pipeline backward.
- IC pack v1 should reference this decision log instead of duplicating all intermediate test tables.
Strategy Rationale
Why CANSLIM + Minervini
The strategy combines CANSLIM and Minervini SEPA because the two frameworks cover different parts of the leader-stock problem.
- CANSLIM provides the fundamental and sponsorship universe: accelerating earnings, sales, leadership, institutional demand, and market regime.
- Minervini provides the technical timing discipline: Stage 2 trend, relative strength, volatility contraction, and strict risk control.
- Compared with a broad factor model, this is more explainable and better suited to a concentrated 10-15 stock portfolio.
- Compared with pure value, it better matches A-share leader-stock behavior, where policy themes, industry cycle acceleration, and capital flow often dominate cheapness.
- Compared with pure momentum, it avoids relying only on price action by requiring fundamental confirmation.
Why Strict M-filter Is Core
A-share leader-stock selection is strongly regime-dependent. In weak market regimes, individual-stock alpha is usually overwhelmed by market beta and liquidity contraction.
The sensitivity test confirmed this quantitatively: relaxed M-filters dramatically worsened drawdown, while strict M-filter kept 2024 H1 and other weak windows out of market. OOS-A 0% return is therefore a feature, not a bug: cash in a bear market is an active risk-control decision.
Why B3 Works
B3 requires both long-window and medium-window relative strength: RPS250 > 80 and RPS125 > 80.
This filters out two common false positives:
- long-term strong stocks that have recently lost momentum;
- short-term rebounds in stocks that remain weak on a long horizon.
That is why B3 improved both Sharpe and max drawdown, while B1/B2/B4 did not. B1 was too restrictive given noisy quarterly reports. B2 overlapped heavily with existing trend filters. B4 turned a volume confirmation concept into a pre-entry filter and starved exposure.
Why O'Neil Sell Overlays Failed
The O'Neil sell overlays failed because they are calibrated to US market microstructure and volatility, while A-share leaders have higher single-name volatility, daily price limits, and different pullback behavior.
The empirical pattern was clear:
- S1/S3 barely triggered, so they added no useful signal.
- S2/S4/S5/S6 triggered too early or too frequently, cutting winners and normal pullbacks before the baseline trend/ATR system had a chance to work.
The current three-axis exit already covers the intended risks in a more A-share-calibrated way: ATR stop for volatility-adjusted risk, MA/trend-template breaks for trend failure, and EPS yoy deterioration for fundamental disproof.
Why LHB Sponsorship Failed
Dragon-tiger-list sponsorship did not work as a quality signal in this backtest. The likely reason is that LHB activity is dominated by short-term trading and theme/squeeze behavior, not durable institutional sponsorship.
This differs from northbound-style sponsorship, which is slower-moving and closer to long-term capital allocation. LHB may still be useful for short-horizon trading diagnostics, but it is not accepted into the medium-term leader-stock production spec.