User

\"\"\" multi_tf_alignment_test.py (30-Aug-2026) ================================================================ MAKSAD: \"Established-Weekly-Breakout + Daily-Regime + Weekly-Stage\" combination genuinely-koi-Extra-Predictive-Value-deta-hai-ya-nahi — est

Asked by CNI Follower · 3 hrs ago · 08-09-2026

Script exactly does what you described: it audits whether “multi_tf_bullish_aligned” adds extra predictive value on top of the established weekly breakout logic, by comparing forward accuracy of two groups (Aligned vs Not-Aligned) over a 4‑week horizon, and now also saves proper per‑event raw CSV.

Below is a structured breakdown + a few important nuances to be aware of.

---

1. High‑level behaviour

- For each symbol’s daily history (from `backtest_data/.csv`), you:

- Convert to weekly OHLC via `sa.resample_timeframe(daily_df, "W")`.

- Walk forward week by week (rolling history).

- At each week:

- Use the established weekly breakout logic (via `get_direction_prediction(...)` → `detect_resistance_support_clusters` + `get_breakout_levels`) to get a bullish/bearish directional call.

- Map that weekly event date to daily data up to that date.

- Run `sa.get_full_regime_analysis(...)` to get `is_bullish_aligned`.

- Check the 4‑week forward outcome on weekly close and mark `is_correct`.

- Split events into:

- Group A: `is_aligned == True` (multi_tf_bullish_aligned = True).

- Group B: `is_aligned == False` (False or unavailable).

- Compute and print accuracy separately for both groups and write:

- A Markdown report: `backtest_data/multi_tf_alignment_test_report.md`

- Raw per‑event CSV: `backtest_data/multi_tf_alignment_raw_results.csv` (new fix).

Design intent (“REUSE baselines, sirf aligned vs not-aligned compare karo”) is correctly implemented.

---

2. Core logic details (and why they are sensible)

(a) Data loading

```python

filepath = os.path.join(BACKTEST_DATA_DIR, f"{symbol}.csv")

df = pd.read_csv(filepath, index_col=0, parse_dates=True)

if df.index.tz is not None:

df.index = df.index.tz_localize(None)

```

- Reads cached daily data; strips timezone to avoid misalignment.

- Returns empty `DataFrame()` if file missing → upstream loops correctly `continue`.

(b) Weekly direction prediction (pure reuse)

```python

cluster_info = sa.detect_resistance_support_clusters(weekly_slice_full_history)

breakout_info = sa.get_breakout_levels(weekly_slice_full_history, cluster_info=cluster_info)

...

if weekly_status in ("breakout_confirmed", "breakout_provisional"):

return "bullish"

elif weekly_status in ("breakdown_confirmed", "breakdown_provisional"):

return "bearish"

```

- This is a clean, exact reuse of your foundational breakout/breakdown logic.

- No new heuristics added; function only maps status → “bullish” / “bearish” / None.

(c) Walk‑forward protocol

- Skip symbols with <70 weekly bars:

```python

if len(weekly_df) < 70:

continue

```

- Ensures minimum 70 weeks of history available.

- Loop:

```python

for i in range(60, len(weekly_df) - FORWARD_HORIZON_WEEKS):

```

- First event at `i=60`: at least 60 weeks of back history before first signal (≈ 1.1–1.2 years), which is conservative and good.

- Forward horizon fixed at 4 weeks (`FORWARD_HORIZON_WEEKS = 4`), aligned with your baseline audit.

(d) Correct time alignment (weekly ↔ daily)

```python

breakout_week_end_date = weekly_slice.index[-1]

daily_slice_up_to = daily_df[daily_df.index <= breakout_week_end_date]

```

- Weekly event date = last index of `weekly_slice` (end of that week).

- Daily regime slice uses all daily bars up to and including that week‑end date → this is correctly causal (no look‑ahead into future daily bars).

(e) Regime alignment flag

```python

full_regime = sa.get_full_regime_analysis(daily_slice_up_to)

is_aligned = full_regime.get("is_bullish_aligned", False) if full_regime.get("available") else False

```

- If regime analysis not available or key missing → treated as Not‑Aligned (False).

- This matches your stated null‑hypothesis framing: “Alignment not proven / not available → default to baseline group.”

(f) Forward accuracy check

```python

entry_price = weekly_df["Close"].iloc[i]

future_price = weekly_df["Close"].iloc[i + FORWARD_HORIZON_WEEKS]

actual_direction = "bullish" if future_price > entry_price else "bearish"

is_correct = (direction == actual_direction)

```

- Entry = weekly close at event bar.

- Outcome = weekly close 4 weeks later.

- Direction correctness definition is simple and consistent with earlier audit:

- Any price increase over 4 weeks → bullish outcome; else bearish.

- Note: ties (future_price == entry_price) get classified as “bearish” by this logic. If you want “neutral” instead, you’d need an explicit third state; right now you’re intentionally keeping it binary, which is fine as long as you stay consistent across all audits.

---

3. Grouping, reporting, and CSV fix

(a) Grouping

```python

if is_aligned:

group_aligned.append(is_correct)

else:

group_not_aligned.append(is_correct)

```

- Both groups hold Booleans, so:

```python

accuracy = np.mean(results)

```

is literally % correct (True = 1, False = 0).

(b) Markdown report

- For each group with data:

- Prints `n` and accuracy to console.

- Also appends to `multi_tf_alignment_test_report.md`:

```markdown

## Aligned (multi_tf_bullish_aligned=True)

- n=...

- accuracy=...%

```

This is sufficient as a high‑level summary input for further analysis.

(c) Raw CSV (your recently fixed gap)

```python

all_events.append({

"symbol": symbol,

"event_date": breakout_week_end_date,

"direction": direction,

"is_aligned": is_aligned,

"is_correct": is_correct,

})

...

events_df = pd.DataFrame(all_events)

csv_path = os.path.join(BACKTEST_DATA_DIR, "multi_tf_alignment_raw_results.csv")

events_df.to_csv(csv_path, index=False)

```

- This now gives you an event‑level dataset perfect for:

- Null‑hypothesis testing.

- Stratified analysis (per symbol, per market regime, per direction, etc.).

- The structure is clean and minimal:

- `symbol`

- `event_date` (weekly Timestamp)

- `direction` (“bullish”/“bearish” from the breakout engine)

- `is_aligned` (bool)

- `is_correct` (bool)

Fix is correct and aligned with your comment: `null_hypothesis_framework.py-jaisi-scripts-genuinely-isko-load-kar-sakein`.

---

4. Important nuances / potential refinements

These aren’t bugs, but conscious design choices you may want to be aware of or refine:

1. Bullish vs Bearish events mixed together

- Right now, both bullish and bearish weekly signals go through the same alignment test and same `is_bullish_aligned` flag.

- That means:

- A bearish breakdown with bullish multi‑TF regime still counts as “Aligned=False” in Group‑B.

- If your conceptual question is specifically:

> “Kya ‘multi_tf_bullish_aligned’ sirf bullish breakouts ke liye extra edge deta hai?”

you may want an additional, more focused filter in your downstream analysis:

- e.g., only rows where `direction == "bullish"`.

2. No direction‑specific regime

- You currently only use `is_bullish_aligned`.

- For a symmetric framework, you could later add `is_bearish_aligned` and run a mirrored test for breakdowns. For now, your script remains faithful to the stated “bullish alignment” experiment; just keep this asymmetry in mind when interpreting results.

3. Forward horizon choice

- Using weekly close at t+4 weeks is consistent with your previous audit and global baseline.

- If you later want to test robustness, you can resample the same CSV with different horizons (2, 8, 12 weeks) without touching this engine’s internal logic—just change `FORWARD_HORIZON_WEEKS`.

4. Performance considerations

- As you already note, this is genuinely expensive:

- Per symbol, per week, you recompute clusters + breakout + full regime.

- This is logically correct but computationally heavy. If needed, you can cache intermediate regime calls or breakout results, but that’s an optimisation step, not a logical correction.

---

5. Summary judgment

- Design and implementation are logically consistent with your documented intent:

- Baseline weekly breakout logic is reused as‑is.

- Multi‑TF bullish alignment only acts as a tag to create two groups.

- Accuracy is measured in a clean, causal, walk‑forward manner on weekly closes over 4 weeks.

- The missing piece (per‑event raw CSV) is now correctly fixed.

You can safely use `multi_tf_alignment_raw_results.csv` as the input to your `null_hypothesis_framework` / statistical tests to see if the accuracy difference between the two groups is statistically significant or just noise.

If you have any further queries, please connect with us on 022-6290-10141 (Timings : 09.00 AM to 05.00 PM) or you can email us on info@cniinfoxchange.com