---
title: "Getting Started with NNS: Overview"
author: "Fred Viole"
output: html_vignette
vignette: >
  %\VignetteIndexEntry{Getting Started with NNS: Overview}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r}
#| label: setup
#| include: true
# Prereqs (uncomment if needed):
# install.packages("NNS")
# install.packages(c("data.table","xts","zoo","Rfast"))

suppressPackageStartupMessages({
  library(NNS)
  library(data.table)
})
set.seed(42)
```


```{r, include=FALSE, message=FALSE}
data.table::setDTthreads(2L)
options(mc.cores = 1)
Sys.setenv("OMP_THREAD_LIMIT" = 2)
```

# Orientation

**Goal.** A complete, hands‑on curriculum for Nonlinear Nonparametric Statistics (NNS) using **partial moments**. Each section blends narrative intuition, precise math, and executable code.

**Structure.** 1. Foundations — partial moments & variance decomposition 2. Descriptive & distributional tools 3. Dependence & nonlinear association 4. Hypothesis testing & ANOVA (LPM‑CDF) 5. Regression, boosting, stacking & causality 6. Time series & forecasting 7. Simulation (max‑entropy), Monte Carlo & risk‑neutral rescaling 8. Portfolio & stochastic dominance

**Notation.** For a random variable $X$ and threshold/target $t$, the population $n$‑th **partial moments** are defined as

$$
\operatorname{LPM}(n,t,X) 
= \int_{-\infty}^{t} (t-x)^{n} \, dF_X(x),
\qquad
\operatorname{UPM}(n,t,X) 
= \int_{t}^{\infty} (x-t)^{n} \, dF_X(x).
$$

The **empirical** estimators replace $F_X$ with the empirical CDF $\hat F_n$ (or, equivalently, use indicator functions):

$$
\widehat{\operatorname{LPM}}_n(t;X) = \frac{1}{n} \sum_{i=1}^n (t-x_i)^n \, \mathbf{1}_{\{x_i \le t\}},
\qquad
\widehat{\operatorname{UPM}}_n(t;X) = \frac{1}{n} \sum_{i=1}^n (x_i-t)^n \, \mathbf{1}_{\{x_i > t\}}.
$$

These correspond to integrals over the measurable subsets $\{X \le t\}$ and $\{X > t\}$ in a $\sigma$‑algebra; the empirical sums are discrete analogues of Lebesgue integrals.

------------------------------------------------------------------------

# 1. Foundations — Partial Moments & Variance Decomposition

## 1.1 Why partial moments

-   Classical variance treats upside and downside symmetrically. Partial moments separate them, allowing **asymmetric risk/reward** analysis around a chosen target $t$ (often the mean or a benchmark).
-   At $t=\mu_X$: 
$$
\operatorname{Var}(X) = \operatorname{UPM}(2,\mu_X,X) + \operatorname{LPM}(2,\mu_X,X)\quad\text{(exact empirical identity)}.
$$
This **is not** the same as splitting conditional variances around a threshold; partial moments use a *global* reference, preserving the between‑group contribution.

## 1.2 Core functions and headers

-   `LPM(degree, target, variable)`
-   `UPM(degree, target, variable)`
-   `LPM.ratio(degree = 0, target, variable)` (empirical CDF when `degree=0`)
-   `UPM.ratio(degree = 0, target, variable)`
-   `LPM.VaR(p, degree, variable)` (quantiles via partial‑moment CDFs)

## 1.3 Code: variance decomposition & CDF

```{r}
# Normal sample
y <- rnorm(3000)
mu <- mean(y)
L2 <- LPM(2, mu, y); U2 <- UPM(2, mu, y)
cat(sprintf("LPM2 + UPM2 = %.6f vs var(y)=%.6f\n", (L2+U2)*(length(y) / (length(y) - 1)), var(y)))

# Empirical CDF via LPM.ratio(0, t, x)
for (t in c(-1,0,1)) {
  cdf_lpm <- LPM.ratio(0, t, y)
  cat(sprintf("CDF at t=%+.1f : LPM.ratio=%.4f | empirical=%.4f\n", t, cdf_lpm, mean(y<=t)))
}

# Asymmetry on a skewed distribution
z <- rexp(3000)-1; mu_z <- mean(z)
cat(sprintf("Skewed z: LPM2=%.4f, UPM2=%.4f (expect imbalance)\n", LPM(2,mu_z,z), UPM(2,mu_z,z)))
```

**Interpretation.** The equality `LPM2 + UPM2 == var(x)` (Bessel adjustment used) holds because deviations are measured against the *global* mean. `LPM.ratio(0, t, x)` constructs an empirical CDF directly from partial‑moment counts.

------------------------------------------------------------------------

# 2. Descriptive & Distributional Tools

## 2.1 Higher moments from partial moments

Define asymmetric analogues of skewness/kurtosis using $\operatorname{UPM}_3$, $\operatorname{LPM}_3$ (and degree 4), yielding robust tail diagnostics without parametric assumptions.

**Header.** `NNS.moments(x)`

```{r}
M <- NNS.moments(y)
M
```

## 2.2 Mode estimation (no bin‑or‑bandwidth angst)

**Header.** `NNS.mode(x)`

```{r}
set.seed(23)
multimodal <- c(rnorm(1500,-2,.5), rnorm(1500,2,.5))
NNS.mode(multimodal,multi = TRUE)
```

## 2.3 CDF tables via LPM ratios

```{r}
qgrid <- quantile(z, probs = seq(0.05,0.95,by=0.1))
CDF_tbl <- data.table(threshold = as.numeric(qgrid), CDF = sapply(qgrid, function(q) LPM.ratio(0,q,z)))
CDF_tbl
```

------------------------------------------------------------------------

# 3. Dependence & Nonlinear Association

## 3.1 Why move beyond Pearson $r$

Pearson captures linear monotone relationships. Many structures (U‑shapes, saturation, asymmetric tails) produce near‑zero $r$ despite strong dependence. Partial‑moment dependence metrics respond to such structure.

**Headers.** - `Co.LPM(degree, target, x, y)` / `Co.UPM(...)` (co‑partial moments) - `PM.matrix(l_degree, u_degree, target=NULL, variable, pop_adj=TRUE)` - `NNS.dep(x, y)` (scalar dependence coefficient) - `NNS.copula(X, target=NULL, continuous=TRUE, plot=FALSE, independence.overlay=FALSE)`

## 3.2 Code: nonlinear dependence

```{r}
set.seed(1)
x <- runif(2000,-1,1)
y <- x^2 + rnorm(2000, sd=.05)
cat(sprintf("Pearson r = %.4f\n", cor(x,y)))
cat(sprintf("NNS.dep  = %.4f\n", NNS.dep(x,y)$Dependence))

X <- data.frame(a=x, b=y, c=x*y + rnorm(2000, sd=.05))
pm <- PM.matrix(1, 1, target = "means", variable=X, pop_adj=TRUE)
pm

cop <- NNS.copula(X, continuous=TRUE, plot=FALSE)
cop
```

## 3.3 Code: copula

```{r, eval=FALSE}
# Data
set.seed(123); x = rnorm(100); y = rnorm(100); z = expand.grid(x, y)

# Plot
rgl::plot3d(z[,1], z[,2], Co.LPM(0, z[,1], z[,2], z[,1], z[,2]), col = "red")

# Uniform values
u_x = LPM.ratio(0, x, x); u_y = LPM.ratio(0, y, y); z = expand.grid(u_x, u_y)

# Plot
rgl::plot3d(z[,1], z[,2], Co.LPM(0, z[,1], z[,2], z[,1], z[,2]), col = "blue")
```

**Interpretation.** `NNS.dep` remains high for curved relationships; `PM.matrix` collects co‑partial moments across variables; `NNS.copula` summarizes higher‑dimensional dependence using partial‑moment ratios. Copulas are returned and evaluated via `Co.LPM` functions.

------------------------------------------------------------------------

# 4. Hypothesis Testing & ANOVA (LPM‑CDF)

## 4.1 Concept

Instead of distributional assumptions, compare groups via **LPM‑based CDFs**. Output is a *degree of certainty* (not a p‑value) for equality of populations or means.

**Header.** `NNS.ANOVA(control, treatment, means.only=FALSE, medians=FALSE, confidence.interval=.95, tails=c("Both","left","right"), pairwise=FALSE, plot=TRUE, robust=FALSE)`

## 4.2 Code: two‑sample & multi‑group

```{r}
ctrl <- rnorm(200, 0, 1)
trt  <- rnorm(180, 0.35, 1.2)
NNS.ANOVA(control=ctrl, treatment=trt, means.only=FALSE, plot=FALSE)

A <- list(g1=rnorm(150,0.0,1.1), g2=rnorm(150,0.2,1.0), g3=rnorm(150,-0.1,0.9))
NNS.ANOVA(control=A, means.only=TRUE, plot=FALSE)
```

**Math sketch.** For each quantile/threshold $t$, compare CDFs built from `LPM.ratio(0, t, •)` (possibly with one‑sided tails). Aggregate across $t$ to a certainty score.

------------------------------------------------------------------------

# 5. Regression, Boosting, Stacking & Causality

## 5.1 Philosophy

`NNS.reg` learns **partitioned** relationships using partial‑moment weights — linear where appropriate, nonlinear where needed — avoiding fragile global parametric forms.

**Headers.** - `NNS.reg(x, y, order=NULL, smooth=TRUE, ncores=1, ...)` → `$Fitted.xy`, `$Point.est`, … - `NNS.boost(IVs.train, DV.train, IVs.test, epochs, learner.trials, status, balance, type, folds)` - `NNS.stack(IVs.train, DV.train, IVs.test, type, balance, ncores, folds)` - `NNS.caus(x, y)` (directional causality score via conditional dependence)

## 5.2 Code: classification via regression + ensembles

```{r, fig.width=7, fig.height=5, fig.align='center'}
# Example 1: Nonlinear regression
set.seed(123)
x_train <- runif(200, -2, 2)
y_train <- sin(pi * x_train) + rnorm(200, sd = 0.2)

x_test <- seq(-2, 2, length.out = 100)

NNS.reg(x = data.frame(x = x_train), y = y_train, order = NULL)
```


```{r, eval = FALSE}
# Simple train/test for boosting & stacking
test.set = 141:150
 
boost <- NNS.boost(IVs.train = iris[-test.set, 1:4], 
              DV.train = iris[-test.set, 5],
              IVs.test = iris[test.set, 1:4],
              epochs = 10, learner.trials = 10, 
              status = FALSE, balance = TRUE,
              type = "CLASS", folds = 1)


mean(boost$results == as.numeric(iris[test.set,5]))
[1] 1


boost$feature.weights; boost$feature.frequency

stacked <- NNS.stack(IVs.train = iris[-test.set, 1:4], 
                     DV.train = iris[-test.set, 5],
                     IVs.test = iris[test.set, 1:4],
                     type = "CLASS", balance = TRUE,
                     ncores = 1, folds = 1)
mean(stacked$stack == as.numeric(iris[test.set,5]))
[1] 1
```

## 5.3 Code: directional causality

```{r}
NNS.caus(mtcars$hp,  mtcars$mpg)  # hp -> mpg
NNS.caus(mtcars$mpg, mtcars$hp)   # mpg -> hp
```

**Interpretation.** Examine asymmetry in scores to infer direction. The method conditions partial‑moment dependence on candidate drivers.

------------------------------------------------------------------------

# 6. Time Series & Forecasting

**Headers.** `NNS.ARMA`, `NNS.ARMA.optim`, `NNS.seas`, `NNS.VAR`

```{r , fig.width=7, fig.align='center'}
# Univariate nonlinear ARMA
z <- as.numeric(scale(sin(1:480/8) + rnorm(480, sd=.35)))

# Seasonality detection (prints a summary)
NNS.seas(z, plot = FALSE)

# Validate seasonal periods
NNS.ARMA.optim(z, h=48, seasonal.factor = NNS.seas(z, plot = FALSE)$periods, plot = TRUE, ncores = 1)
```

**Notes.** NNS seasonality uses coefficient of variation instead of ACF/PACFs, and NNS ARMA blends multiple seasonal periods into the linear or nonlinear regression forecasts.

------------------------------------------------------------------------

# 7. Simulation, Bootstrap & Risk‑Neutral Rescaling

## 7.1 Maximum entropy bootstrap (shape‑preserving)

**Header.** `NNS.meboot(x, reps=999, rho=NULL, type="spearman", drift=TRUE, ...)`

```{r}
x_ts <- cumsum(rnorm(350, sd=.7))
mb <- NNS.meboot(x_ts, reps=5, rho = 1)
dim(mb["replicates", ]$replicates)
```

## 7.2 Monte Carlo over the full correlation space

**Header.** `NNS.MC(x, reps=30, lower_rho=-1, upper_rho=1, by=.01, exp=1, type="spearman", ...)`

```{r}
mc <- NNS.MC(x_ts, reps=5, lower_rho=-1, upper_rho=1, by=.5, exp=1)
length(mc$ensemble); head(names(mc$replicates),5)
```

## 7.3 Risk‑neutral rescale (pricing context)

**Header.** `NNS.rescale(x, a, b, method=c("minmax","riskneutral"), T=NULL, type=c("Terminal","Discounted"))`

```{r}
px <- 100 + cumsum(rnorm(260, sd = 1))
rn <- NNS.rescale(px, a=100, b=0.03, method="riskneutral", T=1, type="Terminal")
c( target = 100*exp(0.03*1), mean_rn = mean(rn) )
```

**Interpretation.** `riskneutral` shifts the mean to match $S_0 e^{rT}$ (Terminal) or $S_0$ (Discounted), preserving distributional shape.

------------------------------------------------------------------------

# 8. Portfolio & Stochastic Dominance

Stochastic dominance orders uncertain prospects for broad classes of risk‑averse utilities; partial moments supply practical, nonparametric estimators.

**Headers.** - `NNS.FSD.uni(x, y)`, `NNS.SSD.uni(x, y)`, `NNS.TSD.uni(x, y)` - `NNS.SD.cluster(R)`, `NNS.SD.efficient.set(R)`

```{r}
RA <- rnorm(240, 0.005, 0.03)
RB <- rnorm(240, 0.003, 0.02)
RC <- rnorm(240, 0.006, 0.04)

NNS.FSD.uni(RA, RB)
NNS.SSD.uni(RA, RB)
NNS.TSD.uni(RA, RB)

Rmat <- cbind(A=RA, B=RB, C=RC)
try(NNS.SD.cluster(Rmat, degree = 1))
try(NNS.SD.efficient.set(Rmat, degree = 1))
```

------------------------------------------------------------------------

# Appendix A — Measure‑theoretic sketch (why partial moments are rigorous)

Let $(\Omega, \mathcal{F}, \mathbb{P})$ be a probability space, $X: \Omega\to\mathbb{R}$ measurable. For any fixed $t\in\mathbb{R}$, the sets $\{X\le t\}$ and $\{X>t\}$ are in $\mathcal{F}$ because they are preimages of Borel sets. The **population** partial moments are

$$
\operatorname{LPM}(k,t,X) = \int_{-\infty}^{t} (t-x)^k\, dF_X(x),
\qquad
\operatorname{UPM}(k,t,X) = \int_{t}^{\infty} (x-t)^k\, dF_X(x).
$$

The **empirical** versions correspond to replacing $F_X$ with the empirical measure $\mathbb{P}_n$ (or CDF $\hat F_n$):

$$
\widehat{\operatorname{LPM}}_k(t;X) = \int_{(-\infty,t]} (t-x)^k\, d\mathbb{P}_n(x),
\qquad
\widehat{\operatorname{UPM}}_k(t;X) = \int_{(t,\infty)} (x-t)^k\, d\mathbb{P}_n(x).
$$

Centering at $t=\mu_X$ yields the variance decomposition identity in Section 1.

------------------------------------------------------------------------

# Appendix B — Quick Reference (Grouped by Topic)

## 1. Partial Moments & Ratios
- `LPM(degree, target, variable)` — lower partial moment of order `degree` at `target`.
- `UPM(degree, target, variable)` — upper partial moment of order `degree` at `target`.
- `LPM.ratio(degree, target, variable)`; `UPM.ratio(...)` — normalized shares; `degree=0` gives CDF.
- `LPM.VaR(p, degree, variable)` — partial-moment quantile at probability `p`.
- `Co.LPM(degree, target, x, y)` — co-lower partial moment between two variables.
- `Co.UPM(degree, target, x, y)` — co-upper partial moment between two variables.
- `D.LPM(degree, target, variable)` — divergent lower partial moment (away from `target`).
- `D.UPM(degree, target, variable)` — divergent upper partial moment (away from `target`).
- `NNS.CDF(x, target = NULL, points = NULL, plot = TRUE/FALSE)` — CDF from partial moments.
- `NNS.moments(x)` — mean/var/skew/kurtosis via partial moments.

## 2. Descriptive Statistics & Distributions
- `NNS.mode(x, multi=FALSE)` — nonparametric mode(s).
- `PM.matrix(l_degree, u_degree, target, variable, pop_adj)` — co-/divergent partial-moment matrices.
- `NNS.gravity(x, w = NULL)` — partial-moment weighted location (gravity center).
- `NNS.norm(x, method = "moment")` — normalization retaining target moments.

See NNS Vignette: [Getting Started with NNS: Partial Moments](https://CRAN.R-project.org/package=NNS/vignettes/NNSvignette_Partial_Moments.html)

## 3. Dependence & Association
- `NNS.dep(x, y)` — nonlinear dependence coefficient.
- `NNS.copula(X, target, continuous, plot, independence.overlay)` — dependence from co-partial moments.

See NNS Vignette: [Getting Started with NNS: Correlation and Dependence](https://CRAN.R-project.org/package=NNS/vignettes/NNSvignette_Correlation_and_Dependence.html)

## 4. Hypothesis Testing
- `NNS.ANOVA(control, treatment, ...)` — certainty of equality (distributions or means).

See NNS Vignette: [Getting Started with NNS: Comparing Distributions](https://CRAN.R-project.org/package=NNS/vignettes/NNSvignette_Comparing_Distributions.html)


## 5. Regression, Classification & Causality
- `NNS.part(x, y, ...)` — partition analysis for variable segmentation.
- `NNS.reg(x, y, ...)` — partition-based regression/classification (`$Fitted.xy`, `$Point.est`).
- `NNS.boost(IVs, DV, ...)`, `NNS.stack(IVs, DV, ...)` — ensembles using `NNS.reg` base learners.
- `NNS.caus(x, y)` — directional causality score.

See NNS Vignette: [Getting Started with NNS: Clustering and Regression](https://CRAN.R-project.org/package=NNS/vignettes/NNSvignette_Clustering_and_Regression.html)

\medskip

See NNS Vignette: [Getting Started with NNS: Classification](https://CRAN.R-project.org/package=NNS/vignettes/NNSvignette_Classification.html)

## 6. Differentiation & Slope Measures
- `dy.dx(x, y)` — numerical derivative of `y` with respect to `x` via partial moments.
- `dy.d_(x, Y, var)` — partial derivative of multivariate `Y` w.r.t. `var`.
- `NNS.diff(x, y)` — derivative via secant projections.

## 7. Time Series & Forecasting
- `NNS.ARMA(...)`, `NNS.ARMA.optim(...)` — nonlinear ARMA modeling.
- `NNS.seas(...)` — detect seasonality.
- `NNS.VAR(...)` — nonlinear VAR modeling.
- `NNS.nowcast(x, h, ...)` — near-term nonlinear forecast.

See NNS Vignette: [Getting Started with NNS: Forecasting](https://CRAN.R-project.org/package=NNS/vignettes/NNSvignette_Forecasting.html)

## 8. Simulation, Bootstrap & Rescaling
- `NNS.meboot(...)` — maximum entropy bootstrap.
- `NNS.MC(...)` — Monte Carlo over correlation space.
- `NNS.rescale(...)` — risk-neutral or min–max rescaling.

See NNS Vignette: [Getting Started with NNS: Sampling and Simulation](https://CRAN.R-project.org/package=NNS/vignettes/NNSvignette_Sampling.html)

## 9. Portfolio Analysis & Stochastic Dominance
- `NNS.FSD.uni(x, y)`, `NNS.SSD.uni(x, y)`, `NNS.TSD.uni(x, y)` — univariate stochastic dominance tests.
- `NNS.SD.cluster(R)`, `NNS.SD.efficient.set(R)` — dominance-based portfolio sets.


For complete references, please see the Vignettes linked above and their specific referenced materials.


```{r threads, echo = FALSE}
Sys.setenv("OMP_THREAD_LIMIT" = "")
```
