// This Pine Script® code is licensed under Apache-2.0
// SPDX-License-Identifier: Apache-2.0
// © PineForge contributors 2026
//
// PF probe 33 — matrix.new<float>() covariance + largest-eigenvalue extraction
// Purpose: parity test for `var matrix<float>` cell mutations (`m.set(i,j,v)`)
// driven by per-bar ta.sma covariance entries, then eigenvalue derivation.
//
//@version=6
strategy("Matrix Eigen PCA", overlay=false, initial_capital=1000000, process_orders_on_close=false, pyramiding=1, commission_type=strategy.commission.percent, commission_value=0, slippage=0, default_qty_type=strategy.fixed, default_qty_value=1)
length = input.int(14, "Length", minval=2)
v1 = close - open
v2 = high - low
// Covariance matrix simulation over `length`
v1_mean = ta.sma(v1, length)
v2_mean = ta.sma(v2, length)
cov11 = ta.sma((v1 - v1_mean) * (v1 - v1_mean), length)
cov12 = ta.sma((v1 - v1_mean) * (v2 - v2_mean), length)
cov21 = cov12
cov22 = ta.sma((v2 - v2_mean) * (v2 - v2_mean), length)
var m = matrix.new<float>(2, 2, 0.0)
m.set(0, 0, cov11)
m.set(0, 1, cov12)
m.set(1, 0, cov21)
m.set(1, 1, cov22)
covReady = not na(cov11) and not na(cov12) and not na(cov22)
// Largest eigenvalue = principal variance (always >= 0); compare to its SMA so crosses are meaningful
float lam = na
if covReady
lam := array.size(m.eigenvalues()) > 0 ? array.get(m.eigenvalues(), 0) : na
lamSma = ta.sma(lam, length)
if covReady and not na(lam) and not na(lamSma) and ta.crossover(lam, lamSma)
strategy.entry("Long", strategy.long)
if covReady and not na(lam) and not na(lamSma) and ta.crossunder(lam, lamSma)
strategy.entry("Short", strategy.short)