Skip to content

Commit f79d632

Browse files
author
OVVO-Financial
committed
NNS 11.3 Beta
1 parent e6e7d7b commit f79d632

12 files changed

+148
-80
lines changed

DESCRIPTION

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
Package: NNS
22
Type: Package
33
Title: Nonlinear Nonparametric Statistics
4-
Version: 11.2
5-
Date: 2025-03-23
4+
Version: 11.3
5+
Date: 2025-03-28
66
Authors@R: c(
77
person("Fred", "Viole", role=c("aut","cre"), email="[email protected]"),
88
person("Roberto", "Spadim", role=c("ctb"))

NNS_11.2.tar.gz

-1.18 MB
Binary file not shown.

NNS_11.2.zip

-863 KB
Binary file not shown.

NNS_11.3.tar.gz

1.15 MB
Binary file not shown.

NNS_11.3.zip

866 KB
Binary file not shown.

R/Central_tendencies.R

+4-4
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,10 @@ NNS.gravity <- function (x, discrete = FALSE)
139139
#' - For \code{method = "riskneutral"}: the risk-free rate \( r \) (e.g., 0.05), used with \( T \) to adjust the mean.
140140
#' @param method character; scaling method: \code{"minmax"} (default) for min-max scaling, or \code{"riskneutral"} for risk-neutral adjustment.
141141
#' @param T numeric; time to maturity in years (required for \code{method = "riskneutral"}, ignored otherwise; e.g., 1). Default is NULL.
142-
#' @param type character; for \code{method = "riskneutral"}: \code{"Terminal"} (default, mean = \( S_0 e^{r T} \)) or \code{"Discounted"} (mean = \( S_0 \)).
142+
#' @param type character; for \code{method = "riskneutral"}: \code{"Terminal"} (default) or \code{"Discounted"} (mean = \( S_0 \)).
143143
#' @return Returns a rescaled distribution:
144144
#' - For \code{"minmax"}: values scaled linearly to the range \code{[a, b]}.
145-
#' - For \code{"riskneutral"}: values scaled multiplicatively to a risk-neutral mean (\( S_0 e^{r T} \) if \code{type = "Terminal"}, or \( S_0 \) if \code{type = "Discounted"}).
145+
#' - For \code{"riskneutral"}: values scaled multiplicatively to a risk-neutral mean (\( S_0 e^(rT) \) if \code{type = "Terminal"}, or \( S_0 \) if \code{type = "Discounted"}).
146146
#' @author Fred Viole, OVVO Financial Systems
147147
#' @examples
148148
#' \dontrun{
@@ -151,11 +151,11 @@ NNS.gravity <- function (x, discrete = FALSE)
151151
#' x <- rnorm(100)
152152
#' NNS.rescale(x, a = 5, b = 10, method = "minmax") # Scales to [5, 10]
153153
#'
154-
#' # Risk-neutral scaling (Terminal): a = S_0, b = r # Mean 105.13
154+
#' # Risk-neutral scaling (Terminal): a = S_0, b = r # Mean approx 105.13
155155
#' prices <- 100 * exp(cumsum(rnorm(100, 0.001, 0.02)))
156156
#' NNS.rescale(prices, a = 100, b = 0.05, method = "riskneutral", T = 1, type = "Terminal")
157157
#'
158-
#' # Risk-neutral scaling (Discounted): a = S_0, b = r # Mean 100
158+
#' # Risk-neutral scaling (Discounted): a = S_0, b = r # Mean approx 100
159159
#' NNS.rescale(prices, a = 100, b = 0.05, method = "riskneutral", T = 1, type = "Discounted")
160160
#' }
161161
#' @export

R/Partial_Moments.R

+135-67
Original file line numberDiff line numberDiff line change
@@ -42,41 +42,38 @@
4242

4343

4444
NNS.CDF <- function(variable, degree = 0, target = NULL, type = "CDF", plot = TRUE){
45-
46-
if(any(class(variable)%in%c("tbl","data.table")) && dim(variable)[2]==1){
45+
if(any(class(variable) %in% c("tbl", "data.table")) && dim(variable)[2] == 1){
4746
variable <- as.vector(unlist(variable))
4847
}
49-
if(any(class(variable)%in%c("tbl","data.table"))){
48+
if(any(class(variable) %in% c("tbl", "data.table"))){
5049
variable <- as.data.frame(variable)
5150
}
5251

5352
if(!is.null(target)){
54-
if(is.null(dim(variable)) || dim(variable)[2]==1){
55-
if(target<min(variable) || target>max(variable)){
53+
if(is.null(dim(variable)) || dim(variable)[2] == 1){
54+
if(target < min(variable) || target > max(variable)){
5655
stop("Please make sure target is within the observed values of variable.")
5756
}
5857
} else {
59-
if(target[1]<min(variable[,1]) || target[1]>max(variable[,1])){
58+
if(target[1] < min(variable[,1]) || target[1] > max(variable[,1])){
6059
stop("Please make sure target 1 is within the observed values of variable 1.")
6160
}
62-
if(target[2]<min(variable[,2]) || target[2]>max(variable[,2])){
61+
if(target[2] < min(variable[,2]) || target[2] > max(variable[,2])){
6362
stop("Please make sure target 2 is within the observed values of variable 2.")
6463
}
6564
}
6665
}
66+
6767
type <- tolower(type)
68-
if(!(type%in%c("cdf","survival", "hazard", "cumulative hazard"))){
68+
if(!(type %in% c("cdf", "survival", "hazard", "cumulative hazard"))){
6969
stop(paste("Please select a type from: ", "`CDF`, ", "`survival`, ", "`hazard`, ", "`cumulative hazard`"))
7070
}
71+
72+
# Univariate Case
7173
if(is.null(dim(variable)) || dim(variable)[2] == 1){
7274
overall_target <- sort(variable)
7375
x <- overall_target
74-
if(degree > 0){
75-
CDF <- LPM.ratio(degree, overall_target, variable)
76-
} else {
77-
cdf_fun <- ecdf(x)
78-
CDF <- cdf_fun(overall_target)
79-
}
76+
CDF <- LPM.ratio(degree, overall_target, variable)
8077
values <- cbind.data.frame(sort(variable), CDF)
8178
colnames(values) <- c(deparse(substitute(variable)), "CDF")
8279
if(!is.null(target)){
@@ -88,106 +85,177 @@ NNS.CDF <- function(variable, degree = 0, target = NULL, type = "CDF", plot = TR
8885
if(type == "survival"){
8986
CDF <- 1 - CDF
9087
P <- 1 - P
91-
}else if(type == "hazard"){
92-
CDF <- exp(log(density(x, n = length(x))$y)-log(1-CDF))
88+
ylabel <- "S(x)"
89+
} else if(type == "hazard"){
90+
n <- length(x)
91+
window <- min(10, n-1)
92+
f_proxy <- numeric(n)
93+
for(i in 1:n){
94+
start <- max(1, i - window %/% 2)
95+
end <- min(n, i + window %/% 2)
96+
dx <- x[end] - x[start]
97+
f_proxy[i] <- (CDF[end] - CDF[start]) / dx
98+
}
99+
f_proxy <- pmax(f_proxy, 1e-10)
100+
reg_fit <- NNS.reg(x, f_proxy, order = NULL, n.best = 1, point.est = if(!is.null(target)) target else NULL, plot = FALSE)
101+
dens <- pmax(reg_fit$Fitted$y.hat, 1e-10)
102+
S <- pmax(1e-10, 1 - CDF)
103+
CDF <- dens / S
104+
CDF <- pmin(CDF, 1e6)
105+
CDF <- pmax(0, CDF)
93106
ylabel <- "h(x)"
94-
P <- NNS.reg(x[-length(x)], CDF[-length(x)], order = "max", point.est = c(x[length(x)], target), plot = FALSE)$Point.est
95-
CDF[is.infinite(CDF)] <- P[1]
96-
P <- P[-1]
97-
}else if(type == "cumulative hazard"){
98-
CDF <- -log((1 - CDF))
107+
if(!is.null(target)){
108+
P <- reg_fit$Point.est / S[which.min(abs(x - target))]
109+
P <- min(P, 1e6)
110+
P <- max(0, P)
111+
CDF[is.infinite(CDF)] <- P
112+
}
113+
} else if(type == "cumulative hazard"){
114+
S <- pmax(1e-10, 1 - CDF)
115+
CDF <- -log(S)
116+
CDF <- pmax(0, CDF)
117+
if(!is.null(target)){
118+
reg_fit <- NNS.reg(x, CDF, order = NULL, n.best = 1, point.est = target, plot = FALSE)
119+
P <- reg_fit$Point.est
120+
}
99121
ylabel <- "H(x)"
100-
P <- NNS.reg(x[-length(x)], CDF[-length(x)], order = "max", point.est = c(x[length(x)], target), plot = FALSE)$Point.est
101-
CDF[is.infinite(CDF)] <- P[1]
102-
P <- P[-1]
103122
}
104123
if(plot){
105124
plot(x, CDF, pch = 19, col = 'steelblue', xlab = deparse(substitute(variable)), ylab = ylabel, main = toupper(type), type = "s", lwd = 2)
106125
points(x, CDF, pch = 19, col = 'steelblue')
107-
lines(x, CDF, lty=2, col = 'steelblue')
126+
lines(x, CDF, lty = 2, col = 'steelblue')
108127
if(!is.null(target)){
109-
segments(target,0,target,P, col = "red", lwd = 2, lty = 2)
128+
segments(target, 0, target, P, col = "red", lwd = 2, lty = 2)
110129
segments(min(variable), P, target, P, col = "red", lwd = 2, lty = 2)
111130
points(target, P, col = "green", pch = 19)
112-
mtext(text = round(P,4), col = "red", side = 2, at = P, las = 2)
113-
mtext(text = round(target,4), col = "red", side = 1, at = target, las = 1)
131+
mtext(text = round(P, 4), col = "red", side = 2, at = P, las = 2)
132+
mtext(text = round(target, 4), col = "red", side = 1, at = target, las = 1)
114133
}
115134
}
116135
values <- data.table::data.table(cbind.data.frame(x, CDF))
117136
colnames(values) <- c(deparse(substitute(variable)), ylabel)
118137
return(
119138
list(
120-
"Function" = values ,
139+
"Function" = values,
121140
"target.value" = P
122141
)
123142
)
124-
} else {
125-
overall_target_1 <- (variable[,1])
126-
overall_target_2 <- (variable[,2])
127-
CDF <- (
128-
Co.LPM(degree, sort(variable[,1]), sort(variable[,2]), overall_target_1, overall_target_2) /
129-
(
130-
Co.LPM(degree, sort(variable[,1]), sort(variable[,2]), overall_target_1, overall_target_2) +
131-
Co.UPM(degree, sort(variable[,1]), sort(variable[,2]), overall_target_1, overall_target_2) +
132-
D.UPM(degree,degree, sort(variable[,1]), sort(variable[,2]), overall_target_1, overall_target_2) +
133-
D.LPM(degree,degree, sort(variable[,1]), sort(variable[,2]), overall_target_1, overall_target_2)
134-
)
143+
}
144+
# Bivariate Case
145+
else {
146+
overall_target_1 <- variable[,1]
147+
overall_target_2 <- variable[,2]
148+
149+
sorted_indices <- order(variable[,1], variable[,2])
150+
sorted_x <- variable[sorted_indices, 1]
151+
sorted_y <- variable[sorted_indices, 2]
152+
153+
joint_cdf <- (
154+
Co.LPM(degree, overall_target_1, overall_target_2, overall_target_1, overall_target_2) /
155+
(
156+
Co.LPM(degree, overall_target_1, overall_target_2, overall_target_1, overall_target_2) +
157+
Co.UPM(degree, overall_target_1, overall_target_2, overall_target_1, overall_target_2) +
158+
D.UPM(degree, degree, overall_target_1, overall_target_2, overall_target_1, overall_target_2) +
159+
D.LPM(degree, degree, overall_target_1, overall_target_2, overall_target_1, overall_target_2)
160+
)
135161
)
162+
CDF <- joint_cdf[sorted_indices]
163+
164+
marginal_X <- LPM.ratio(degree, sorted_x, overall_target_1)
165+
marginal_Y <- LPM.ratio(degree, sorted_y, overall_target_2)
166+
167+
ylabel <- "Probability"
136168
if(type == "survival"){
137-
CDF <- 1 - CDF
169+
CDF <- 1 - marginal_X - marginal_Y + CDF
170+
CDF <- pmax(0, pmin(1, CDF))
171+
ylabel <- "S(x, y)"
138172
} else if(type == "hazard"){
139-
CDF <- sort(variable) / (1 - CDF)
173+
data_points <- data.frame(x = sorted_x, y = sorted_y)
174+
dens_proxy <- pmax(joint_cdf[sorted_indices], 1e-10)
175+
reg_fit <- NNS.reg(data_points, dens_proxy, order = "max",
176+
point.est = if(!is.null(target)) data.frame(x = target[1], y = target[2]) else NULL,
177+
plot = FALSE)
178+
dens <- pmax(reg_fit$Fitted$y.hat, 1e-10)
179+
S_xy <- pmax(1e-10, 1 - marginal_X - marginal_Y + CDF)
180+
CDF <- dens / S_xy
181+
CDF <- pmax(0, CDF)
182+
ylabel <- "h(x, y)"
140183
} else if(type == "cumulative hazard"){
141-
CDF <- -log((1 - CDF))
184+
S_xy <- pmax(1e-10, 1 - marginal_X - marginal_Y + CDF)
185+
CDF <- -log(S_xy)
186+
CDF <- pmax(0, CDF)
187+
ylabel <- "H(x, y)"
142188
}
189+
143190
if(!is.null(target)){
144191
P <- (
145-
Co.LPM(degree, variable[,1], variable[,2], target[1], target[2]) /
146-
(
147-
Co.LPM(degree, variable[,1], variable[,2], target[1], target[2]) +
148-
Co.UPM(degree, variable[,1], variable[,2], target[1], target[2]) +
149-
D.LPM(degree,degree, variable[,1], variable[,2], target[1], target[2]) +
150-
D.UPM(degree,degree, variable[,1], variable[,2], target[1], target[2])
151-
)
192+
Co.LPM(degree, overall_target_1, overall_target_2, target[1], target[2]) /
193+
(
194+
Co.LPM(degree, overall_target_1, overall_target_2, target[1], target[2]) +
195+
Co.UPM(degree, overall_target_1, overall_target_2, target[1], target[2]) +
196+
D.LPM(degree, degree, overall_target_1, overall_target_2, target[1], target[2]) +
197+
D.UPM(degree, degree, overall_target_1, overall_target_2, target[1], target[2])
198+
)
152199
)
200+
P_marginal_X <- LPM.ratio(degree, target[1], overall_target_1)
201+
P_marginal_Y <- LPM.ratio(degree, target[2], overall_target_2)
202+
if(type == "survival"){
203+
P <- 1 - P_marginal_X - P_marginal_Y + P
204+
P <- max(0, min(1, P))
205+
} else if(type == "hazard"){
206+
P_dens <- pmax(reg_fit$Point.est, 1e-10)
207+
S_target <- max(1e-10, 1 - P_marginal_X - P_marginal_Y + P)
208+
P <- P_dens / S_target
209+
P <- min(P, 1e6)
210+
P <- max(0, P)
211+
} else if(type == "cumulative hazard"){
212+
S_target <- max(1e-10, 1 - P_marginal_X - P_marginal_Y + P)
213+
P <- -log(S_target)
214+
P <- max(0, P)
215+
}
153216
} else {
154217
P <- NULL
155218
}
219+
156220
if(plot){
157221
plot3d(
158-
variable[,1], variable[,2], CDF, col = "steelblue",
222+
variable[sorted_indices, 1], variable[sorted_indices, 2], CDF, col = "steelblue",
159223
xlab = deparse(substitute(variable[,1])), ylab = deparse(substitute(variable[,2])),
160-
zlab = "Probability", box = FALSE, pch = 19
224+
zlab = ylabel, box = FALSE, pch = 19
161225
)
162-
if(!is.null(target)){
226+
if(!is.null(target) && !is.na(P)){
163227
points3d(target[1], target[2], P, col = "green", pch = 19)
164228
points3d(target[1], target[2], 0, col = "red", pch = 15, cex = 2)
165229
lines3d(
166-
x= c(target[1], max(variable[,1])),
167-
y= c(target[2], max(variable[,2])),
168-
z= c(P, P),
169-
col = "red", lwd = 2, lty=3
230+
x = c(target[1], max(variable[,1])),
231+
y = c(target[2], max(variable[,2])),
232+
z = c(P, P),
233+
col = "red", lwd = 2, lty = 3
170234
)
171235
lines3d(
172-
x= c(target[1], target[1]),
173-
y= c(target[2], target[2]),
174-
z= c(0, P),
175-
col = "red", lwd = 1, lty=3
236+
x = c(target[1], target[1]),
237+
y = c(target[2], target[2]),
238+
z = c(0, P),
239+
col = "red", lwd = 1, lty = 3
176240
)
177241
text3d(
178-
max(variable[,1]), max(variable[,2]), P, texts = paste0("P = ", round(P,4)), pos = 4, col = "red"
242+
max(variable[,1]), max(variable[,2]), P, texts = paste0("P = ", round(P, 4)), pos = 4, col = "red"
179243
)
180244
}
181-
182245
}
183246

247+
return(list(
248+
"Function" = data.table::data.table(cbind(
249+
data.frame(variable[sorted_indices, ], row.names = NULL),
250+
CDF = CDF
251+
)),
252+
"target.value" = P
253+
))
184254
}
185-
186-
return(list("CDF" = data.table::data.table(cbind((variable), CDF = CDF)),
187-
"P" = P))
188255
}
189256

190257

258+
191259
#' NNS moments
192260
#'
193261
#' This function returns the first 4 moments of the distribution.
@@ -227,7 +295,7 @@ NNS.moments <- function(x, population = TRUE){
227295
kurtosis <- ((n * (n+1)) / ((n-1)*(n-2)*(n-3))) * ((n*kurt_base) / (variance * (n / (n - 1)))^2) - ( (3 * ((n-1)^2)) / ((n-2)*(n-3)))
228296
variance <- variance * (n / (n - 1))
229297
}
230-
298+
231299
return(list("mean" = mean,
232300
"variance" = variance,
233301
"skewness" = skewness,

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44

55

6-
[![packageversion](https://img.shields.io/badge/NNS%20version-11.2-blue.svg?style=flat-square)](https://github.com/OVVO-Financial/NNS/commits/NNS-Beta-Version) [![Licence](https://img.shields.io/badge/licence-GPL--3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html)
6+
[![packageversion](https://img.shields.io/badge/NNS%20version-11.3-blue.svg?style=flat-square)](https://github.com/OVVO-Financial/NNS/commits/NNS-Beta-Version) [![Licence](https://img.shields.io/badge/licence-GPL--3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html)
77

88
<h2 style="margin: 0; padding: 0; border: none; height: 40px;"></h2>
99

@@ -56,7 +56,7 @@ Please see https://github.com/OVVO-Financial/NNS/blob/NNS-Beta-Version/examples/
5656
title = {NNS: Nonlinear Nonparametric Statistics},
5757
author = {Fred Viole},
5858
year = {2016},
59-
note = {R package version 11.2},
59+
note = {R package version 11.3},
6060
url = {https://CRAN.R-project.org/package=NNS},
6161
}
6262
```

man/NNS.rescale.Rd

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/NNS.dll

0 Bytes
Binary file not shown.

tests/testthat/Rplots.pdf

-32.9 KB
Binary file not shown.

tests/testthat/test_Partial_Moments.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ T1<-data.table::data.table(matrix(
192192
),
193193
ncol=2
194194
))
195-
colnames(T1) <- c("A", "Probability")
195+
colnames(T1) <- c("A", "S(x)")
196196
B<-NNS.CDF(A, type="survival")
197197
test_that(
198198
"NNS.CDF", {

0 commit comments

Comments
 (0)