Calculate the days between dates by hand - r

I suspect R has a built-in method to do this, but I'm new to programming and was trying to figure out how to calculate the days between dates by hand as practice. Here is my code:
isLeapYear <- function(year) {
if (year %% 400 == 0) {
return (TRUE)
}
if (year %% 100 == 0) {
return (FALSE)
}
if (year %% 4 == 0) {
return (TRUE)
}
else{ return (FALSE)}
}
daysInMonth <- function(year,month){
if (month == 1 | month == 3| month == 5 | month == 7 | month == 8 | month == 10 | month == 12) {
return (31)
}
else if (month == 2){
if (isLeapYear(year)){
return (29)
}
else {return (28)}
}
else {return (30)}
}
nextDay <- function(year, month, day){
if (day < daysInMonth(year,month)){
return (list(year, month, day + 1))
}
else{
if (month == 12){
return (list(year + 1, 1, 1))
}
else{return (list(year, month + 1, 1))}
}
}
dateIsBefore <- function(year1, month1, day1, year2, month2, day2){
if (year1 < year2){
return(TRUE)
}
if (year1 == year2){
if (month1 < month2){
return(TRUE)
}
if (month1 == month2){
return (day1 < day2)
}
}
return (FALSE)
}
daysBetweenDates <- function(year1, month1, day1, year2, month2, day2){
days <- 0
while (dateIsBefore(year1, month1, day1, year2, month2, day2)){
result = nextDay(year1,month1,day1)
year1 = result[1]
month1 = result[2]
day1 = result[3]
days = days+1
}
return (days)
}
I wrote a code to determine the number of day between two dates using python. I'm now trying to convert it to R for another assignment I'm doing. When I run each indiviual function, they seem to work fine. When I call daysBetweenDates(2012,1,1,2012,2,28) I get the following error:
Error in day + 1 : non-numeric argument to binary operator

> as.Date("2012/02/28") - as.Date("2012/01/01")
# Time difference of 58 days
> as.Date("2012/01/01") - as.Date("2012/02/28")
# Time difference of -58 days
Improvement suggested by Dirk in comments on just to get the number as a difference using as.integer(), here it is
> as.integer(as.Date("2012/02/28") - as.Date("2012/01/01"))
# [1] 58
> as.integer(as.Date("2012/01/01") - as.Date("2012/02/28"))
# [1] -58

The reason your code isn't working is because of the way you are assigning the three elements of result to year1, month1, and day1 in the while loop in your daysBetweenDates function. If you change it like this it should work:
daysBetweenDates <- function(year1, month1, day1, year2, month2, day2){
days <- 0
while (dateIsBefore(year1, month1, day1, year2, month2, day2)){
result = nextDay(year1,month1,day1)
year1 = result[[1]]
month1 = result[[2]]
day1 = result[[3]]
days = days + 1
}
return (days)
}
If you do return <- list(2012, 1, 1) and then return[1] and compare that with return[[1]] you should see the difference. This is common mistake when using lists. You might want to take a look at this for an excellent discussion of subsetting: http://adv-r.had.co.nz/Subsetting.html.

Related

How do I amend this code to better incorporate the grace period

I would like to update my amortisation schedule (in R code) so that it correctly amortises loans where there is a grace period (months where only interest is paid but not principal). The code correctly amortises where there isn't a grace period but fails where there is. The issue is that the loan payment function doesn't factor in that a grace period shortens the amount of periods available to pay off a loan.
The payment function (typical of what you find online) looks like this
PMT <- function(rate, nper,pv, fv=0, type=0){
pmt = ifelse(rate!=0,
(rate*(fv+pv*(1+ rate)^nper))/((1+rate*type)*(1-(1+ rate)^nper)),
(-1*(fv+pv)/nper )
)
return(pmt)
}
Ideally I would like to reword to say where there is a grace period nper (which is the number of periods) should be shorter.
I have tried this
PMT <- function(rate, nper, pv, fv=0, type=0, grace_period, instalment_amount){
if (grace_period == 0){
pmt = ifelse(rate!=0,
(rate*(fv+pv*(1+ rate)^nper))/((1+rate*type)*(1-(1+ rate)^nper)),
(-1*(fv+pv)/nper )
)
} else {
pmt = ifelse(rate!=0,
(rate*(fv+pv*(1+ rate)^(nper-grace_period)))/((1+rate*type)*(1-(1+ rate)^(nper-grace_period))) + (instalment_amount*grace_period),
(-1*(fv+pv)/nper )
)
}
return(pmt)
}
I also do this for my interest and principal instalment functions. I then run the code below (and all 3 functions which are not shown) but it doesn't work as I get the error message
"Error in PPMT(rate, 1:nper, nper, amount, grace_period) :
argument "grace_period" is missing, with no default"
This is the code after I run the 3 functions referenced above
amortization <- function(amount, annualinterestrate, paymentsperyear, years, grace_period) {
nper = paymentsperyear * years
rate = annualinterestrate / paymentsperyear
grace_period= grace_period
amortization <- data.frame(
Principal = PPMT(rate, 1:nper, nper, amount,grace_period)*-1,
Interest = IPMT(rate, 1:nper, nper, amount,grace_period)*-1
) %>% mutate(Instalment = Principal + Interest,
Balance = round(amount - cumsum(Principal),2))
if (grace_period == 0) {
return(amortization)
}
for (i in 1:nper) {
if (i <= grace_period) {
amortization$Principal[i] <- 0
amortization$Interest[i] <- rate*amount
amortization$Instalment[i] <- rate*amount
amortization$Balance[i] <- amount
} else {
amortization$Balance[i] <- amortization$Balance[i-1]- amortization$Principal[i]
#last_payment = nrow(amortization)
#amortization[last_payment, 'Principal'] = amortization[last_payment, 'Balance']
#amortization[last_payment, 'Instalment'] = amortization[last_payment, 'Balance']
#amortization[last_payment, 'Interest'] = 0
#amortization[last_payment, 'Balance'] = 0
}
}
return(amortization)
}
for (i in 1:nper) {
if (i <= grace) {
amortization$Principal[i] <- 0
amortization$Interest[i] <- rate*amount
amortization$Instalment[i] <- rate*amount
amortization$Balance[i] <- amount
} else {
amortization$Balance[i] <- amortization$Balance[i-1]- amortization$Principal[i]
}
}
return(amortization)
}
test <- amortization(1000,.06,12,10,10)

Why does a piece of code that works on its own not work in parallel in R?

I wrote a piece of code (appended below) that works fine when I run it in serial, but when I use the foreach and doparallel libraries in R, I get an error code that reads: " task 1 failed - "missing value where TRUE/FALSE needed"
Everything inside the for each loop works on its own, and on a smaller batch, I can run it serially and it works.
ListOfColumns <- colnames(tempdata)
foreach(i = 1:nSubsets,
.export = ls(globalenv())) %dopar% {
DoubleTempData <- get(paste0("Subset", i))
DoubleTempData <- subset(DoubleTempData, select = -c(subset))
RowCounter <- 2
ColumnFigurer <- 2
LastCATEGORYIndicator <- "THERE IS NO CATEGORY, ONLY ZUUL"
while (RowCounter <= nrow(DoubleTempData)) {
print(paste("Checking row ", RowCounter))
RowChecker <- max(1, RowCounter - 5)
while (RowChecker < RowCounter) {
print(paste("Checking row",
RowCounter,
"against row",
RowChecker))
if (DoubleTempData$CATEGORY[RowChecker] == DoubleTempData$CATEGORY[RowCounter])
{
print("The rows match!")
while (ColumnFigurer > 0) {
if (DoubleTempData$CATEGORY[RowCounter] != LastCATEGORYIndicator) {
ColumnFigurer <- 2
}
print(paste ("Checking Iteration", ColumnFigurer))
if (ColumnFigurer * length(ListOfColumns) <= length(colnames(DoubleTempData)))
{
print(paste("Iteration", ColumnFigurer, " exists"))
CellChecker <-
((ColumnFigurer - 1) * length(ListOfColumns) + 1)
if (is.na(DoubleTempData[[RowChecker, CellChecker]])) {
print(paste("Current value is NA. Writing in new value."))
ColumnCounter <- 1
while (ColumnCounter <= length(ListOfColumns)) {
DoubleTempData[[RowChecker, (ColumnFigurer - 1) * length(ListOfColumns) +
ColumnCounter]] <-
DoubleTempData[[RowCounter, ColumnCounter]]
ColumnCounter <- ColumnCounter + 1
}
DoubleTempData <- DoubleTempData[-RowCounter]
LastCATEGORYIndicator <-
DoubleTempData$CATEGORY[RowChecker]
RowCounter <- max(2, RowCounter - 1)
ColumnFigurer <- ColumnFigurer + 1
break
}
else
{
print(paste(
"Current value is not NA, increasing iteration count."
))
ColumnFigurer <- ColumnFigurer + 1
}
}
if (ColumnFigurer * length(ListOfColumns) > length(colnames(DoubleTempData)))
{
print(paste(
"Iteration ",
ColumnFigurer,
"does not exist, adding iteration."
))
ColumnAdder <- 1
while (ColumnAdder <= length(ListOfColumns)) {
NewColumnName <-
paste0(ListOfColumns[ColumnAdder], "_", ColumnFigurer)
DoubleTempData[, NewColumnName] <- NA
ColumnAdder <- ColumnAdder + 1
}
}
}
}
RowChecker <- RowChecker + 1
}
RowCounter <- RowCounter + 1
}
assign(paste0("Subset", i), DoubleTempData)
}
For example, here is a sample of a randomly generated Subset1 that I ran, with about 70 observations and 7 columns (one of which gets dropped by the program as intended):
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/Jlytj.png
It then outputs a dataset with 9 observations, and 60 columns:

My yathzee function stucks in the if statement

I just started to learn R and I am asked to write a function for a simplified Yahtzee game. The objective of the game is to score points by rolling five dice to make certain combinations.
There are 6 different categories:
If all five dice the same, the player gets 50 points (Yahtzee).
Five sequential dices (i.e, all unique dices) yields 40 points (Straight)
Three of one number and two of another yields 25 points.
If four dices are the same, it gives a score of the sum of all dices.
If three dices are the same, it gives a score of the sum of all dices.
Any remaining condition gives a score of the sum of all dices.
Here is how I have tried (Although I think that the last three categories can be condensed into the same logical test):
yahtzee <- function(){
dices <- sample(1:6,5,TRUE)
t <- table(dices)
t.x <- unname(t)
if(length(unique(dices) == 1)){
print("Yahtzee")
score <- 50
}
else if(dices == c(1,2,3,4,5) | dices == c(2,3,4,5,6)){
print("Straight")
score <- 40
}
else if(t.x[1] == 3 & t.x[2] == 2 | t.x[1] == 2 & t.x[2] == 3){
print("Full House")
score <- 25
}
else if(t.x[1] == 4 & t.x[2] == 1 | t.x[1] == 1 & t.x[2] == 4){
print("Four Of A Kind")
score <- sum(dices)
}
else if(t.x[1] == 3 & t.x[2] == 1 & t.x[3] == 1 | t.x[1] == 1 & t.x[2] == 3 & t.x[3] == 1 | t.x[1] == 1 & t.x[2] == 1 & t.x[3] == 3){
print("Three Of A Kind")
score <- sum(dices)
}
else{
print("Chance")
score <- sum(dices)
}
print(dices)
print(score)
}
When I run the function, I always earn 50 points and 'Yahtzee' occurs no matter what the dice combination is. My code does not go over the remaining else if statements or somehow stucks in the first line. How can I fix it?
You basically just had a couple parens mismatched. I don't think you need t.x and can just leverage properties of t combined with the any function. Here's how I'd rewrite your function:
yahtzee <- function(){
dices <- sample(1:6,5,TRUE)
t <- table(dices)
if(length(unique(dices)) == 1){
print("Yahtzee")
score <- 50
}
else if(length(unique(dices)) == 5){
print("Straight")
score <- 40
}
else if(any(t == 3) * any(t == 2)){
print("Full House")
score <- 25
}
else if(any(t == 4)){
print("Four Of A Kind")
score <- sum(dices)
}
else if(any(t == 3)){
print("Three Of A Kind")
score <- sum(dices)
}
else{
print("Chance")
score <- sum(dices)
}
print(dices)
print(score)
}
yahtzee()
yahtzee <- function () {
dices <- sample(1:6, 5, TRUE)
if( length(unique(dices)) == 1 ) {
print("Yahtzee")
score <- 50
} else if ( length(unique(dices)) == 5 ) {
print("Straight")
score <- 40
} else if ( length(unique(dices)) == 2 && length(which(dices ==
unique(dices)[1])) == 2 ||
length(which(dices == unique(dices)[2])) == 2 ) {
print("Full House")
score <- 25
} else if ( length(unique(dices)) == 2 && length(which(dices ==
unique(dices)[1])) == 1 ||
length(which(dices == unique(dices)[2])) == 1 ) {
print("Four Of A Kind")
score <- sum(dices)
} else if ( length(unique(dices)) == 3 && length(which(dices ==
unique(dices)[1])) == 3 ||
length(which(dices == unique(dices)[2])) == 3 ||
length(which(dices == unique(dices)[3])) == 3 ) {
print("Three Of A Kind")
score <- sum(dices)
} else {
print("Chance")
score <- sum(dices)
}
print(dices)
print(score)
}

How to add surcharge

I have this process, the user selects 2 dates. The system will then check if there are weekends. Weekends are:
Friday
Saturday
Sunday
Every time there are weekends, there would be additional charge + $10 PER DAY OF THE WEEKEND.
I have this code below, what I want is the process to add the surcharge.
http://jsfiddle.net/xtD5V/71/
function isWeekend(date1, date2) {
var d1 = new Date(date1),
d2 = new Date(date2),
isWeekend = false;
while (d1 < d2) {
var day = d1.getDay();
isWeekend = (day == 6) || (day == 0);
if (isWeekend) { return true; }
d1.setDate(d1.getDate() + 1);
}
return false;
}
alert(isWeekend(date1, date2));
You can opt to try this option.
Loop through all the dates and check for weekends like you did.
Store it in a variable
Option 1:
function noOfWeekends(date1, date2) {
//record number of weekends
var no_of_weekends = 0;
var d1 = new Date(date1),
d2 = new Date(date2),
isWeekend = false;
while (d1 < d2) {
var day = d1.getDay();
isWeekend = (day == 6) || (day == 0);
if (isWeekend) { no_of_weekends++; }
d1.setDate(d1.getDate() + 1);
}
return no_of_weekends;
}
//noOfWeekends now returns the number of weekends. You can do more stuff with it
alert(noOfWeekends(date1, date2) > 0);
alert("surcharge: " + noOfWeekends * 10);
*P/s: You can opt to write a formula to calculate the number of weekends without a loop since we can derive the information from your current day and number of days left. Do give it a try.

R: data.frame too slow in loops?

I'm backtesting trading strategies with R. This is at the moment my code.
- MergedSet$FXCloseRate contains the closing price for a certain currency pair
- MergedSet$RiskMA is the moving average of a certain risk index
- the rest should be clear
This formula at the Moment is not really fast over 11'000 entries. Why? Are data frames too slow? Where can I optimise here?
############
# STRATEGY #
############
#Null out trades and position
MergedSet$Trade <- 0
MergedSet$Position<-0
MergedSet$DailyReturn<-0
MergedSet$CumulativeReturn<-0
MergedSet$Investment<-0
MergedSet$CumulativeReturn[1:MAPeriod] <- 1
MergedSet$Investment[1:MAPeriod] <- InitialInvestment
#Strategy
n<-nrow(MergedSet)
for(i in seq(MAPeriod+1,n)){
#Updating the position
if(MergedSet$RiskMA[i] <= ParamDwn && MergedSet$RiskMA[i-1] > ParamDwn){
#sell signal, so short if no or long position active otherwise do nothing
if(MergedSet$Position[i-1] == 0 || MergedSet$Position[i-1] == 1){
MergedSet$Position[i] = -1
MergedSet$Trade[i] = 1
}
} else if(MergedSet$RiskMA[i] >= ParamUp && MergedSet$RiskMA[i-1] < ParamUp){
#buy signal, go long if no or short position active, otherwise do nothing
if(MergedSet$Position[i-1] == 0 || MergedSet$Position[i-1] == -1){
MergedSet$Position[i] = 1
MergedSet$Trade[i] = 1
}
} else {
MergedSet$Position[i] = MergedSet$Position[i-1]
}
#Return calculation
if(MergedSet$Position[i] == 1){
#long
MergedSet$DailyReturn[i] = MergedSet$FXCloseRate[i]/MergedSet$FXCloseRate[i-1]-1
} else if(MergedSet$Position[i] == -1){
#short
MergedSet$DailyReturn[i] = MergedSet$FXCloseRate[i-1]/MergedSet$FXCloseRate[i]-1
}
}

Resources