Skip to content

Commit 9ab72a3

Browse files
committed
Functionality for continuous inputs
1 parent f573714 commit 9ab72a3

File tree

3 files changed

+98
-2
lines changed

3 files changed

+98
-2
lines changed

R/dynamic.R

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,34 @@
9898
dynpv <- function(
9999
uptakes = 1,
100100
payoffs,
101-
horizon = length(payoffs),
101+
horizon = NA,
102102
tzero = 0,
103-
prices = rep(1, length(payoffs)+tzero),
103+
prices = NA,
104104
discrate = 0
105105
){
106+
# If payoffs are discrete
107+
if (class(payoffs)=="numeric") {
108+
# Horizon defaults to length of payoffs
109+
if (class(horizon)=="logical") {horizon <- length(payoffs)}
110+
# Price index defaults to (1, ..., 1)
111+
if (class(prices)=="logical") {prices <- rep(1, length(payoffs)+tzero)}
112+
# Call calculation
113+
dpv <- dynpv_discrete(uptakes, payoffs, horizon, tzero, prices, discrate)
114+
}
115+
# If payoffs are not discrete and uptake is discrete
116+
if ((class(uptakes)=="numeric") & (class(payoffs)=="function")) {
117+
dpv <- dynpv_semicts(uptakes, payoffs, horizon, tzero, prices, discrate)
118+
}
119+
# If payoffs and uptake are not discrete
120+
if ((class(uptakes)=="function") & (class(payoffs)=="function")) {
121+
dpv <- dynpv_fullycts(uptakes, payoffs, horizon, tzero, prices, discrate)
122+
}
123+
# Return
124+
return(dpv)
125+
}
126+
127+
# Discrete function
128+
dynpv_discrete <- function(uptakes, payoffs, horizon, tzero, prices, discrate){
106129
# Avoid no visible binding note
107130
j <- k <- l <- uj <- pk <- R <- v <- NULL
108131
# Trim
@@ -137,3 +160,42 @@ trim_vec <- function(vec){
137160
# Return trimmed vector
138161
return(vec[1:trimto])
139162
}
163+
164+
# Function if payoffs, prices and discounting are functions; but uptakes is a vector
165+
dynpv_semicts <- function(uptakes, payoffs, horizon, tzero, prices, discrate){
166+
# Avoid no visible binding note
167+
j <- uj <- pRv <- pv <- NULL
168+
# Trim
169+
uptakes <- trim_vec(uptakes)
170+
# Integrand function
171+
integrand <- function(k, j) {
172+
payoffs(k) * prices(j+k+tzero) * discrate(j+k)
173+
}
174+
# Create a dataset for each combination of time
175+
df <- expand_grid(j=1:length(uptakes)) |>
176+
dplyr::mutate(
177+
uj = uptakes[j],
178+
pRv = stats::integrate(integrand, lower=0, upper=horizon-j, j=j)$value,
179+
pv = uj * pRv
180+
)
181+
class(df) <- c("dynpv", class(df))
182+
return(df)
183+
}
184+
185+
# Function if uptakes, payoffs, prices and discounting are functions
186+
dynpv_fullycts <- function(uptakes, payoffs, horizon, tzero, prices, discrate){
187+
# First integrand function - pRv, to be integrated between k=0 and k=T-j
188+
integrand1 <- function(k, j) {
189+
payoffs(k) * prices(j+k+tzero) * discrate(j+k)
190+
}
191+
# Second integrand function, uj I, to be integrated between j=0 and j=T
192+
integrand2 <- function(j) {
193+
pRv <- stats::integrate(integrand1, lower=0, upper=horizon-j, j=j)$value
194+
uptakes(j) * pRv
195+
}
196+
# Needs to be vectorized before integrating
197+
integrand2 <- Vectorize(integrand2, "j")
198+
# Calculate double integral
199+
df <- stats::integrate(integrand2, lower=0, upper=horizon)
200+
return(df$value)
201+
}

tests/testthat/test-fullycts.R

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Test new fullycts calculations
2+
3+
# Example
4+
payoffs <- function(t) {100+50*t}
5+
prices <- function(t) {1.03 ^ (floor(t))}
6+
discrate <- function(t) {0.97 ^ t}
7+
uptakes <- function(t) {exp(-t/2)}
8+
9+
# 1. Full function calls intermediate function ok
10+
test_that("Full function calls intermediate function ok", {
11+
int <- dynpv_fullycts(uptakes=uptakes, payoffs=payoffs, horizon=5, tzero=0, prices=prices, discrate=discrate)
12+
full <- dynpv(uptakes=uptakes, payoffs=payoffs, horizon=5, prices=prices, discrate=discrate)
13+
expect_equal(int, full)
14+
}
15+
)

tests/testthat/test-semicts.R

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Test new semicts calculations
2+
3+
# Example
4+
payoffs <- function(t) {100+50*t}
5+
prices <- function(t) {1.03 ^ (floor(t))}
6+
discrate <- function(t) {0.97 ^ t}
7+
8+
# 1. Full function calls intermediate function ok
9+
test_that("Full function calls intermediate function ok", {
10+
int <- dynpv_semicts(uptakes=1, payoffs=payoffs, horizon=5, tzero=0, prices=prices, discrate=discrate)
11+
full <- dynpv(payoffs=payoffs, horizon=5, prices=prices, discrate=discrate)
12+
expect_equal(int, full)
13+
}
14+
)
15+
16+
17+
18+
19+

0 commit comments

Comments
 (0)