momentum strategy backtest

I have write the beneath code for momentum strategy for my thesis. It should change portofolio every week based on momentum and callulate the returns of the portofolios from this strategy on the end but it gives me the same portofolio as the optimal every week. This make me think that there is a mistake can anyone can anyone spot it? and give me some improvments? think the problem is on the potitions matrix

`# Load required libraries
library(readxl)
library(quantmod)
library(TTR)


#DATA PATH
data_path <- '/Users/kiriakos/Documents/Μεταπτυχιακό/MSc_Thesis_Momentum strategy/'

#PRICES
data <- readxl::read_excel(paste0(data_path, 'DATAMS2.xlsx'), sheet = 'Weekly_data_ATH_21', range = 'a1:z1000')
prices <- as.data.frame(data[, 2:ncol(data)])
prices <-na.omit(prices)
symbols <- as.vector(head(data[1,], -1))
#Returns
data2 <- readxl::read_excel(paste0(data_path, 'DATAMS2.xlsx'), sheet = 'Weekly_data_ATH_21b', range = 'a1:z1000')
returns <- as.data.frame(data2[, 2:ncol(data2)])
returns <-na.omit(returns)
#portofolio returns based on momentum
portofolio_returns<-data.frame(matrix(nrow=100,ncol=1))

# Define the number of rows to remove
rows_to_remove <- 100

# Remove the first 'rows_to_remove' rows from 'prices' and 'returns' using a for loop
for (i in 1:rows_to_remove) {
  prices <- prices[-1, ]  # Remove the first row from 'prices'
  returns <- returns[-1, ]  # Remove the first row from 'returns'
  data<-data[-1,]
################################################################################
######################### MOMENTUM STRATEGY ###################################
#RSI
symbols <- as.vector(head(data[1,], -1))
rsi<- lapply(prices, RSI, n = 12) #<-calculate rsi of 12 weeks
rsi <- do.call(cbind, rsi)
ma <- apply(prices, 2, TTR::SMA, n = 12)

# Initialize positions
positions <- matrix(0, nrow = nrow(prices), ncol = ncol(prices))

# Enter long position when price crosses above the 3-week moving average and RSI 
#is above 50
positions[prices > ma & rsi < 30] <- 1

# Enter short position when price crosses below the 3-week moving average and 
#RSI is below 50
positions[prices < ma & rsi > 70] <- -1

# Compute portfolio returns
port_returns <- positions[-nrow(positions), ] * returns

# Compute asset weights based on momentum
momentum_scores <- colSums(port_returns[(nrow(port_returns) - 11):nrow(port_returns), ])
momentum_scores<-as.matrix(momentum_scores)
momentum_scores <- momentum_scores[order(-momentum_scores[,1]), ]

buy_assets <- names(momentum_scores)[1:5]
sell_assets <- names(momentum_scores)[(length(momentum_scores) - 5):length(momentum_scores)]

print("Assets to Buy:")
print(buy_assets)
print("Assets to Sell:")
print(sell_assets)

#portofolio prices
portfolio1 <- data[12:25, buy_assets]
portfolio2 <-data[12:25,sell_assets]*-1
portfolio <- data.frame(c(portfolio1, portfolio2))

# Calculate returns for each column in the portfolio data frame
mom_returns <- lapply(portfolio, function(x) c(NA, diff(x) / x[-length(x)]))
mom_returns <- as.data.frame(mom_returns)
mom_returns<-na.omit(mom_returns)
PortRet <- rowSums(mom_returns)
mom_returns <-cbind(mom_returns,rowSums(mom_returns))
total_portofolio_returns<-sum(mom_returns$`rowSums(mom_returns)`)
portofolio_returns[1+i,] <- total_portofolio_returns
RETTT<-sum(portofolio_returns[-1,])

}
print(RETTT)`

This is a classic situation where one programs a loop and the teturn value is not accumulative but overwritten each time. RETT is replaced each go around the loop

1 Like

Or just

input <- mtcars[1:2]
head(input)
#>                    mpg cyl
#> Mazda RX4         21.0   6
#> Mazda RX4 Wag     21.0   6
#> Datsun 710        22.8   4
#> Hornet 4 Drive    21.4   6
#> Hornet Sportabout 18.7   8
#> Valiant           18.1   6
rows_to_remove <- 2
tail(input,-rows_to_remove)
#>                      mpg cyl
#> Datsun 710          22.8   4
#> Hornet 4 Drive      21.4   6
#> Hornet Sportabout   18.7   8
#> Valiant             18.1   6
#> Duster 360          14.3   8
#> Merc 240D           24.4   4
#> Merc 230            22.8   4
#> Merc 280            19.2   6
#> Merc 280C           17.8   6
#> Merc 450SE          16.4   8
#> Merc 450SL          17.3   8
#> Merc 450SLC         15.2   8
#> Cadillac Fleetwood  10.4   8
#> Lincoln Continental 10.4   8
#> Chrysler Imperial   14.7   8
#> Fiat 128            32.4   4
#> Honda Civic         30.4   4
#> Toyota Corolla      33.9   4
#> Toyota Corona       21.5   4
#> Dodge Challenger    15.5   8
#> AMC Javelin         15.2   8
#> Camaro Z28          13.3   8
#> Pontiac Firebird    19.2   8
#> Fiat X1-9           27.3   4
#> Porsche 914-2       26.0   4
#> Lotus Europa        30.4   4
#> Ford Pantera L      15.8   8
#> Ferrari Dino        19.7   6
#> Maserati Bora       15.0   8
#> Volvo 142E          21.4   4

Created on 2023-11-11 with reprex v2.0.2