SSM-JTK – Methodology — short walkthrough (6)

Goal. Show, on one page, how we go from a small, public strip of daily angles to a locked, ephemeris-independent kernel you can reproduce anywhere.


6.1 Inputs (fixed choices)

  • Time & frame. One sample per civil day at 05:30 IST, geocentric, sidereal (Lahiri/Chitrapaksha).
  • Angle domain. Degrees in [0,360); display with wrap360(x).
  • Series. A past-decade daily CSV from a public ephemeris (observation-only) or your own internally constructed tables.

6.2 Train/Test windows and midpoint anchor

  • Train. Contiguous span (e.g., 2020-01-01..2024-12-31, daily).
  • Test. Disjoint past span (e.g., 2015-01-01..2019-12-31, daily).
  • Midpoint anchor. t0 = midpoint(train_start, train_stop); use t = days_since(date, t0).

Why mid-anchor? It de-couples intercept and phases, reducing edge bias and long-span phase creep.


6.3 Unwrap once, then fit by linear least squares

Unwrap the sidereal angle so the series is continuous (carry +-360 to minimize day-to-day jumps).

Families and OLS targets

  • Fixed-n (Moon, Jupiter, Saturn, Uranus, Neptune, Pluto): lock mean motion to physics
    n = 360 / P_sid
    y(t) = L_actual_unwrapped(t) - n*t
    X(t) = [ 1, sin(w1*t), cos(w1*t), ..., sin(wm*t), cos(wm*t) ]
    beta = [ a0, c*, d* ] (degrees)
  • Free-n (Sun, Mercury, Venus, Mars): learn slope once
    y(t) = L_actual_unwrapped(t)
    X(t) = [ 1, t, sin(w1*t), cos(w1*t), ..., sin(wm*t), cos(wm*t) ]
    beta = [ a0, b1, c*, d* ] (where b1 approximates slope during fit)

Export rule. Fold the learned slope into n_deg_per_day = b1 in the manifest; do not export b1 itself.

Tiny candidate frequency sets (declare, then gate)

  • Outer (Jupiter/Saturn/Uranus/Neptune):
    BASE = { w1 = 2*pi/P_syn, 2*w1, wS = 2*pi/P_sid }
    EXTRAS = { nE = 2*pi/365.2564, 3*w1 }
  • Moon (fast):
    BASE_MOON = { wS = 2*pi/P_sid, wA = 2*pi/P_anom }
    EXTRAS = { wD = 2*pi/P_drac, nE }
  • Sun/Inner (free-n; small set):
    BASE_INNER = { w_syn, 2*w_syn }
    EXTRAS = { 3*w_syn, |w_syn - nE|, nE }

Solve OLS for beta for each candidate set.


6.4 Select with a strict, two-part gate (parsimony first)

For each candidate:
BIC = k*log(N) + N*log( max(RSS/N, 1e-16) ) (down is better; guards tiny variances)

Parameter count:
k = 1 + 2*m (fixed-n: intercept + 2 per harmonic)
k = 2 + 2*m (free-n: plus a slope term during fit)

Event-aware loss on TRAIN:
loss = 1.0*MAE_deg_train + 0.3*cusp_MAE_train + 0.4*MAE_speed

Admit an extra only if BOTH hold:
BIC_extra <= BIC_base - 6.0 AND loss_extra < loss_base

Selection rule. Pick the admissible candidate with smallest (loss, then BIC); else use BASE.

Why this gate? Keeps kernels tiny and portable while honoring crossings and stations.


6.5 Lock and export a manifest (portable kernel)

Save a per-body manifest with:
planet, t0, P_sid (or null), n_deg_per_day, selected_model, omegas{...}, beta{...}, notes

Runtime evaluator (identical for all bodies):
t = days_since(D, t0)
y = b0 + n_deg_per_day*t
for each omega_k in omegas: y += c_k*sin(omega_k*t) + d_k*cos(omega_k*t)
L_hat_deg = wrap360(y)

Nodes. Store a manifest for Rahu; evaluate Ketu = wrap360(L_rahu + 180).

Event-day normalization (parity at sign boundaries). After comparing event lists, apply year-boundary normalization -> prev-day convention -> bounded snap where needed:

  • Prev-day convention. Record ingresses on the previous day after year-boundary normalization.
  • Bounded snap. Allow at most +-1 day to resolve a clear neighbor mismatch.

No runtime ephemeris calls are required.


6.6 Score on TEST (report event metrics)

Compute on the TEST window:

  • Degrees. MAE_deg, P90_deg (or P95 for Moon), MAX_deg
  • Rasi. misclass_rate at 30 deg bins
  • Edges and timing. cusp_dist_MAE_deg, rasi_cross_MAE_days, station_date_MAE_days

Publish (conceptual, local).

  • A single-row scorecard and a per-day audit for your records.
  • The locked manifest you used to evaluate.

Acceptance bands (reader-friendly defaults).

  • Sun and inner (Mercury, Venus, Mars): phase_MAE_deg <= 1.5 and rasi_cross_MAE_days <= 2.0
  • Outer slow bodies (Jupiter, Saturn, Uranus, Neptune, Nodes): prioritize phase/timing; e.g., target MAE_deg <= 2.0, P90_deg <= 4.0; also track rasi_cross_MAE_days and station_date_MAE_days (looser because |n| is small).
  • Moon (fast body): cusp_dist_MAE_deg <= 1.5; rasi_cross_MAE_days <= 1.0 (many cases will be hours).
    For the Moon, cusp and crossing timing are primary; degree MAE is secondary for a ~13 deg/day body.

Navigation
Back: SSM-JTK – CSV-only Scorecard How-To (5)
Next: SSM-JTK – Conclusion (7)


Directory of Pages
SSM-JTK – Series index & links


Disclaimer
The contents in the Shunyaya Symbolic Mathematics Jyotish Transit Kernel (SSM-JTK) materials are research/observation material. They are not astrological advice, not a scientific ephemeris, and not operational guidance. Do not use for safety-critical, medical, legal, or financial decisions. Use at your own discretion; no warranties are provided; results depend on correct implementation and inputs.


Explore Further
https://github.com/OMPSHUNYAYA/Symbolic-Mathematics-Jyotish-Transit-Kernel