How can I set a loop to run to a maximum value (Dend)?
I just want to see how fast and deep it will grow but I want to set a maximum to say that it can't grow beyond Dend.
I get an error stating
In if (D == Dend) { :
the condition has length > 1 and only the first element will be used
Code
D0 <- 0
Dend <- 4200
r <- 5 growth rate
days <- 1000
n_steps <- days*1
D <- rep(NA, n_steps+1)
D <- D0
for (time in seq_len(n_steps)){
if (D == Dend){
break} else
D[time + 1] <- r + D[time]
}
D
plot(-D, las=1)
If you want a for loop, it might be something like below
for (time in seq_len(n_steps)){
if (tail(D,1) >= Dend) break
D[time + 1] <- r + D[time]
}
I think what you want can be achieved with seq without any loops :
D <- seq(D0, Dend, r)
If you have to use for loop you can use :
for (time in seq_len(n_steps)){
temp <- r + D[time]
if (temp >= Dend) break
D[time + 1] <- temp
}
We can also use a while loop :
i <- 1
while(TRUE) {
temp <- r + D[i]
if(temp > Dend) break
i <- i + 1
D[i] <- temp
}
Related
I am trying to write a function to calculate h-point. the function is defined over a rank frequency data frame.
consider the following data.frame :
DATA <-data.frame(frequency=c(49,48,46,38,29,24,23,22,15,12,12,10,10,9,9), rank=c(seq(1, 15)))
and the formula for h-point is :
if {there is an r = f(r), h-point = r }
else { h-point = f(i)j-f(j)i / j-i+f(i)-f(j) }
where f(i) and f(j) are corresponding frequencies for ith and jth ranks and i and j are adjacent ranks that i<f(i) and j>f(j).
NOW, i have tried the following codes :
fr <-function(x){d <-DATA$frequency[x]
return(d)}
for (i in 1:length(DATA$rank)) {
j <- i+1
if (i==fr(i))
return(i)
else(i<fr(i) && j>fr(j)) {
s <-fr(i)*j-fr(j)*i/j-i+fr(i)-fr(j)
return(s)
}}
I also tried:
for (i in 1:length(DATA$rank)) {
j <- i+1
if (i==fr(i))
return(i)
if (i<fr(i) while(j>fr(j))) {
s <-fr(i)*j-fr(j)*i/j-i+fr(i)-fr(j)
return(s)
}}
and neither of them works. for the DATA ,the desired result would be i=11 and j=12, so:
h-point=12×12 - 10×11 / 12 - 11 + 12 - 10
can you please tell me what I`m doing wrong here?
You could do:
h_point <- function(data){
x <- seq(nrow(data))
f_x <- data[["frequency"]][x]
h <- which(x == f_x)
if(length(h)>1) h
else{
i <- which(x<f_x)
j <- which(x>f_x)
s <- which(outer(i,j,"-") == -1, TRUE)
i <- i[s[,1]]
j <- j[s[,2]]
cat("i: ",i, "j: ", j,"\n")
f_x[i]*j - f_x[j]*i / (i-j + f_x[i]-f_x[j])
}
}
h_point(DATA)
i: 11 j: 12
[1] 34
I think I have figured out what you are trying to achieve. My loop will go through DATA and break at any point if rank == frequency for a given row. If might be more prudent to explicitly test this with DATA$rank[i] == fr(i) rather than relying on i, in case tied ranks etc.
The second if statement calculates h-point (s) for rows i and j if row i has rank that is lower than freq and row j has a rank that is higher.
Is this what you wanted?
DATA <-data.frame(frequency=c(49,48,46,38,29,24,23,22,15,12,12,10,10,9,9), rank=c(seq(1, 15)))
fr <-function(x){d <-DATA$frequency[x]
return(d)}
for(i in 1:nrow(DATA)){
j <- i+1
if (i==fr(i)){
s <- list(ij=c(i=i,j=j), h=i)
break
}else if(i <fr(i) && j>fr(j)){
s <-list(ij=c(i=i,j=j),h=fr(i)*j-fr(j)*i/j-i+fr(i)-fr(j))
}}
I am not sure the formula is correct, in your loop you had j-i but in explanation it was i-j. Not sure if the entire i-j+fr(i)-fr(j) is the denominator and similarly for the numerator. Simple fixes.
I am working with a time-series raster brick. The brick has 365 layers representing a value for each day of the year.
I want to create a new layer in which each cell holds the number of day of year in which a certain condition is met.
My current approach is the following (APHRO being the raster brick), but returns the error message below:
enter code here
r <- raster(ncol=40, nrow=20)
r[] <- rnorm(n=ncell(r))
APHRO <- brick(x=c(r, r*2, r))
NewLayer <- calc(APHRO, fun=FindOnsetDate(APHRO))
Returning this error:
Error in .local(x, ...) : not a valid subset
And the function being parsed:
FindOnsetDate <- function (s) {
x=0
repeat {
x+1
if(s[[x]] >= 20 | s[[x]] + s[[x+1]] >= 20 & ChkFalseOnset() == FALSE)
{break}
}
return(x);
}
With the function for the 3rd condition being:
ChkFalseOnset <- function (x) {
for (i in 0:13){
if (sum(APHRO[[x+i:x+i+7]]) >= 5)
{return(FALSE); break}
return(TRUE)
}
}
Thank you in advance!!!!
And please let me know if I should provide more information - tried to keep it parsimonious.
The problem is that your function is no good:
FindOnsetDate <- function (s) {
x=0
repeat {
x+1
if(s[[x]] >= 20 | s[[x]] + s[[x+1]] >= 20)
{break}
}
return(x);
}
FindOnsetDate(1:100)
#Error in s[[x]] :
# attempt to select less than one element in get1index <real>
Perhaps something like this:
FindOnsetDate <- function (s) {
j <- s + c(s[-1], 0)
sum(j > 20 | s > 20)
# if all values are positive, just do sum(j > 20)
}
FindOnsetDate(1:20)
#10
This works now:
r <- calc(APHRO, FindOnsetDate)
I would suggest a basic two-step process. With a 365-days example:
set.seed(123)
r <- raster(ncol=40, nrow=20)
r_list <- list()
for(i in 1:365){
r_list[[i]] <- setValues(r,rnorm(n=ncell(r),mean = 10,sd = 5))
}
APHRO <- brick(r_list)
Use a basic logic test for each iteration:
r_list2 <- list()
for(i in 1:365){
if(i != 365){
r_list2[[i]] <- APHRO[[i]] >= 20 | APHRO[[i]] + APHRO[[i+1]] >= 20
}else{
r_list2[[i]] <- APHRO[[i]] >= 20
}
}
Compute sum by year:
NewLayer <- calc(brick(r_list2), fun=sum)
plot(NewLayer)
I have a large loop that will take too long (~100 days). I'm hoping to speed it up with the snow library, but I'm not great with apply statements. This is only part of the loop, but if I can figure this part out, the rest should be straightforward. I'm ok with a bunch of apply statements or loops, but one apply statement using a function to get object 'p' would be ideal.
Original data
dim(m1) == x x # x >>> 0
dim(m2) == y x # y >>> 0, y > x, y > x-10
dim(mout) == x x
thresh == x-10 #specific to my data, actual number probably unimportant
len(v1) == y #each element is a random integer, min==1, max==thresh
len(v2) == y #each element is a random integer, min==1, max==thresh
Original loop
p <- rep(NA,y)
for (k in 1:y){
mout <- m1 * matrix(m2[k,],x,x)
mout <- mout/sum(mout)
if (v1[k] < thresh + 1){
if(v2[k] < thresh + 1){
p[k] <- out[v1[k],v2[k]]
}
if(v2[k] > thresh){
p[k] <- sum(mout[v1[k],(thresh+1):x])
}
}
#do stuff with object 'p'
}
library(snow)
dostuff <- function(k){
#contents of for-loop
mout <- m1 * matrix(m2[k,],x,x)
mout <- mout/sum(mout)
if (v1[k] < thresh + 1){
if(v2[k] < thresh + 1){
p <- out[v1[k],v2[k]]
}
if(v2[k] > thresh){
p <- sum(mout[v1[k],(thresh+1):x])
}
}
#etc etc
return(list(p,
other_vars))
}
exports = c('m1',
'm2',
'thresh',
'v1',
'x' ,
'v2')
cl = makeSOCKcluster(4)
clusterExport(cl,exports)
loop <- as.array(1:y)
out <- parApply(cl,loop,1,dostuff)
p <- rep(NA,y)
for(k in 1:y){
p[k] <- out[[k]][[1]]
other_vars[k] <- out[[k]][[2]]
}
I have generated an infinite loop and don't know how to fix it.
I essentially want to go through the data frame rnumbers and generate rstate2 with 1, -1, or 0 depending on what is in rnumbers
The function step_generator is getting stuck at the repeat function. I am not sure how to make the code put -1 in rstate2 if rnumber is less than C and then repeat an ifelse function for the next rows until a value of D or greater is obtained. Once D is obtained exit the repeat function and go back into the original for loop.
Here is my code:
rnumbers <- data.frame(replicate(5,runif(20000, 0, 1)))
dt <- c(.01)
A <- .01
B <- .0025
C <- .0003
D <- .003
E <- .05
rstate <- rnumbers # copy the structure
rstate[] <- NA # preserve structure with NA's
# Init:
rstate[1, ] <- c(0)
step_generator <- function(col, rnum){
for (i in 2:length(col) ){
if( rnum[i] < C) {
col[i] <- -1
repeat {
ifelse(rnum[i] < E, -1, if(rnum[i] >= D) {break})
}
}
else { if (rnum[i] < B) {col[i] <- -1 }
else {ifelse(rnum[i] < A, 1, 0) } }
}
return(col)
}
# Run for each column index:
for(cl in 1:5){ rstate[ , cl] <-
step_generator(rstate[,cl], rnumbers[,cl]) }
Thanks for any help.
The problem is that you are not increasing i inside repeat loop, so basically you are testing the same i all the time, and because rnum[i] < C (from if condition) it will always be rnum[i] < E since C < E, and loop never breaks.
However, if you increase i inside repeat it still will come back to value resulting from for loop, so you have to do it in different way, for example using while loop. I'm not exactly sure if I understand what you are trying to do, but basing on your description I've made this function:
step_generator <- function(col, rnum){
i <- 2
while (i <= length(col)){
if (rnum[i] < C) {
col[i] <- -1
while ((i < length(col)) & (rnum[i + 1] < D)){
i <- i + 1
col[i] <- -1
}
} else if (rnum[i] < B){
col[i] <- -1
} else if (rnum[i] < A){
col[i] <- 1
} else {
col [i] <- 0
}
i <- i + 1
}
return(col)
}
I (being an absolut beginner with R and programming) have to do some analysis with R for my thesis in finance :(
The purpose is to simulate data (stock prices) with a GBM and run over the results 2 trading strategies. Within the GBM I'll have to "play" with the veriables "r" and "sigma" (3 different values for each, thus 9 combinations). Each combination needs to be simulated 10000 times over a period T=10, N=250. To all these simulations 2 trading strategies have to be applied - MACD and RSI (within the TTR-package).
Now I'm facing an issue with writing the code :(
#Geometrical Brownian Motion
Sim <- GBM(x, r, sigma, T, N)
x <-100
r <-0
sigma <-1
T <- 10
N <- 250
#Additional info for RSI-strategy
retSim <- ROC(Sim)
SimRSI <- RSI(Sim, 14,)
SimRSI[is.na(SimRSI)] <- 0
#Create a vector for the results of the inner loop
portfolio <- rep(0:N)
portfolio[1] <- 100
runs <- 10000
#Creating vectors for final results of portfolio and simulation after 10000 runs (only the last value of each of the 10000 simulations and portfolio results of the strategy required)
resultsSimGBM <- rep(0:runs)
resultsRSIr1sig1 <- rep(0:runs)
#orders
buyRSI<-portfolio[i-1]*exp(retSim[i])
holdRSI<-portfolio[i-1]
#Simulation
portfolio[1]<-100
i <- 1
j <- 1
#Second loop
for(j in 0:runs){
#Simulation GBM
x <-100
r <-0
sigma <-1
T <- 10
N <- 250
Sim <- GBM(x, r, sigma, T, N)
retSim <- ROC(Sim)
SimRSI <- RSI(Sim, 14,)
SimRSI[is.na(SimRSI)] <- 0
portfolio[1] <- 100
#First loop
for(i in 2:length(Sim)){
#Apply RSI on GBM
buyRSI<-portfolio[i-1]*exp(retSim[i])
holdRSI<-portfolio[i-1]
if(SimRSI[i-1]<50 && SimRSI[i]>50){portfolio[i]=buyRSI}
if(SimRSI[i-1]>50 && SimRSI[i]<50){portfolio[i]=holdRSI}
if(SimRSI[i-1]<50 && SimRSI[i]<50){portfolio[i]=holdRSI}
if(SimRSI[i-1]>50 && SimRSI[i]>50){portfolio[i]=buyRSI}
i <- i+1
}
resultsRSI[j] <- portfolio[N]
resultsSimGBM[j] <- Sim[N]
j <- j+1
}
Anyway, this is what I have until now and it seems to work. However, into the first (inner) loop, I need to include also the second strategy (which until now, singled out) looked following :
#MACD strategy
portfolioMACD[1]<-100
i <- 1
j <- 1
for(j in 0:runs){
Sim <- BMSim
retSim <- ROC(Sim)
SimMACD <- MACD(Sim, 12, 26, 9, myType="EMA")
DataSimMACD <- data.frame(SimMACD)
DataSimMACD$macd[is.na(DataSimMACD$macd)] <- 0
DataSimMACD$signal[is.na(DataSimMACD$signal)] <- 0
for(i in 2:length(Sim)){
buyMACD<-portfolioMACD[i-1]*exp(retSim[i])
sellMACD<-portfolioMACD[i-1]
holdMACD<-portfolioMACD[i-1]*exp(retSim[i])
if(DataSimMACD$macd[i-1]<DataSimMACD$signal[i-1] && DataSimMACD$macd[i]>DataSimMACD$signal[i]){portfolioMACD[i]=buyMACD}
if(DataSimMACD$macd[i-1]>DataSimMACD$signal[i-1] && DataSimMACD$macd[i]<DataSimMACD$signal[i]){portfolioMACD[i]=sellMACD}
if(DataSimMACD$macd[i-1]>DataSimMACD$signal[i-1] && DataSimMACD$macd[i]>DataSimMACD$signal[i]){portfolioMACD[i]=holdMACD}
if(DataSimMACD$macd[i-1]<DataSimMACD$signal[i-1] && DataSimMACD$macd[i]<DataSimMACD$signal[i]){portfolioMACD[i]=sellMACD}
if(DataSimMACD$macd[i]==DataSimMACD$signal[i]){portfolioMACD[i]=sellMACD}
if(DataSimMACD$macd[i-1]==DataSimMACD$signal[i-1] && DataSimMACD$macd[i]!=DataSimMACD$signal[i]){portfolioMACD[i]=buyMACD}
i <- i+1
}
resultsMACD[j] <- portfolioMACD[length(Sim)]
j <- j+1
}
BASICALLY:
1-One Brownian motion has to consist of 2500 elements, to which both trading strategies have to be applied separately
2-this whole procedure has to be repeated 10000 times for each out of 9 combinations of variables r and sigma (r1sigma1, r1sigma2, r1sigma3,.....,r3sigma3) (this I don't have included in my code yet - no clue how to construct those 2 loops around it all...) :(
3-the endresult should be a 10000x27 matrix with 10000rows (for amount of runs) and 27 colums (9x GBM, RSI, MACD) filled only with the 2500th (endvalue) of each simulation (from point 1.) --> how to do it?
SOS! Could someone of you PLEASE PLEASE PLEASE help me with this mess? I'm completely lost and it's my graduation paper -.-
Every help will be highly praised and deeply appreciated!
Thanks in advance and sorry for the long post.
Cheers from Berlin, Ana :)
EDIT AND ANOTHER SIMPLIFIED EXAMPLE
library(sde)
#Vectors for results
Returns <- rep(0:N)
LogReturns <- rep(0:N)
Simulation <- rep(0:N)
ResultsSimulation <- rep(0:runs)
ResultsReturns <- rep(0:runs)
ResultsLog <- rep(0:runs)
runs=50 #how ofthen the Simulation of GBM should be repeated
i <- 1
j <- 1
#second loop
for(j in 2:runs){
Simulation <- GBM(x, r, sigma, T, N)
x=100
r=0
sigma=1
T=1
N=20
#first loop
for(i in 2:length(BM)){
Returns <- ROC(Simulation)
LogReturns[i+1] <- log(Simulation[i+1]/Simulation[i])
i <- i+1
}
ResultsSimulation[j]<-Simulation[N]
ResultsReturns[j]<-Returns[N]
ResultsLog[j]<-LogReturns[N]
j <- j+1
}
ResultsMatrix <- as.matrix(data.frame(ResultsSimulation, ResultsReturns, ResultsLog))
The structure of this example is basically what I have. I need to construct around it 2 more loops which will do the same simulations and calculations for 3 different "r" values and "sigma" values (variables within the GBM-function). The resuls (the final value of each Simulation and calculation from the first loop) should be saved in separate vectors or in a matrix consisting of those --> thus, 27 vestors of length 50 (3 results for each combination of variables r and sigma)
for example, if sigma=0.1; 0.3; 0,6 and r=0,03; 0,05; 0,08
How to construct those loops around it all and save the data accordingly?
Sorry for the questions guys, but I'm really lost :(
Cheers and thanks a lot in advance! At least for reading ;)
Is this close to what you need? If so, you can add new trading functions to return a portfolio, then just call it (see the example):
warning: It took about 1.5 hours to run with N_SIMS = 100000!
get.simulation.GBM = function(TIME = 10, N = 250, N_SIMS = 1000, x0 = 100, sigma = c(0.1, 0.3, 0.6), r = c(0.03, 0.05, 0.08))
{
require(sde)
params = expand.grid(sigma = sigma, r = r)
# pre-allocate matrix
results = matrix(0, ncol = N_SIMS * nrow(params), nrow = N)
for (i in 1:nrow(params))
{
idx.range = ((i - 1)*N_SIMS + 1):((i - 1)*N_SIMS + N_SIMS)
temp.res = replicate(N_SIMS, GBM(x0, r = params[i, 'r'], sigma = params[i, 'sigma'], T = TIME, N = N - 1 ))
results[, idx.range] = temp.res
}
return(results)
}
apply.MACD = function(serie, nFast = 12, nSlow = 26, nSig = 9, p0 = 100)
{
require(TTR)
roc = ROC(serie)
sim.MACD = MACD(serie, nFast, nSlow, nSig, maType = "EMA")
portfolio = rep(0, length = length(serie))
portfolio[1] = p0
sim.MACD[is.na(sim.MACD)] = 0
sim.MACD = as.data.frame(sim.MACD)
for (i in 2:length(serie))
{
buy = portfolio[i - 1] * exp(roc[i])
sell = portfolio[i - 1]
hold = buy
if(sim.MACD$macd[i - 1] < sim.MACD$signal[i - 1] && sim.MACD$macd[i] > sim.MACD$signal[i]){portfolio[i] = buy}
if(sim.MACD$macd[i - 1] > sim.MACD$signal[i - 1] && sim.MACD$macd[i] < sim.MACD$signal[i]){portfolio[i] = sell}
if(sim.MACD$macd[i - 1] > sim.MACD$signal[i - 1] && sim.MACD$macd[i] > sim.MACD$signal[i]){portfolio[i] = hold}
if(sim.MACD$macd[i - 1] < sim.MACD$signal[i - 1] && sim.MACD$macd[i] < sim.MACD$signal[i]){portfolio[i] = sell}
if(sim.MACD$macd[i] == sim.MACD$signal[i]){portfolio[i] = sell}
if(sim.MACD$macd[i - 1] == sim.MACD$signal[i - 1] && sim.MACD$macd[i] != sim.MACD$signal[i]){portfolio[i] = buy}
}
return(portfolio)
}
apply.RSI = function(serie, p0 = 100, n = 14)
{
require(TTR)
roc = ROC(serie)
sim.RSI = RSI(serie, n = n)
sim.RSI[is.na(sim.RSI)] = 0
portfolio = rep(0, length = length(serie))
portfolio[1] = p0
for (i in 2:length(serie))
{
buy = portfolio[i - 1] * exp(roc[i])
hold = portfolio[i - 1]
if(sim.RSI[i - 1] < 50 && sim.RSI[i] > 50){portfolio[i] = buy}
if(sim.RSI[i - 1] > 50 && sim.RSI[i] < 50){portfolio[i] = hold}
if(sim.RSI[i - 1] < 50 && sim.RSI[i] < 50){portfolio[i] = hold}
if(sim.RSI[i - 1] > 50 && sim.RSI[i] > 50){portfolio[i] = buy}
}
return(portfolio)
}
# Example (this is SLOW)
simulation.matrix = get.simulation.GBM()
portfolio.RSI = apply(simulation.matrix, 2, apply.RSI)
portfolio.MACD = apply(simulation.matrix, 2, apply.MACD)
# if you need only the last values
portfolio.RSI.last = tail(portfolio.RSI, 1)
portfolio.MACD.last = tail(portfolio.MACD, 1)