#Import Libraries 
library("quantmod")
## Warning: package 'quantmod' was built under R version 4.3.3
## Loading required package: xts
## Warning: package 'xts' was built under R version 4.3.2
## Loading required package: zoo
## Warning: package 'zoo' was built under R version 4.3.2
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## Loading required package: TTR
## Warning: package 'TTR' was built under R version 4.3.2
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
#Download Monthly Data

start_date = "2016-01-01"
end_date = "2023-12-31"

#BRK 
getSymbols("BRK-A", from = start_date, to = end_date, src = "yahoo", periodicity = "monthly")
## [1] "BRK-A"
BRK = `BRK-A`
BRK_16_24 = BRK$`BRK-A.Adjusted` #Extracted adjusted prices and created new data frame
BRK_16_18 = BRK_16_24[1:36,1] #Extracted 1 to 36 rows and from column 1
Rbrk_16_18 = diff(log(BRK_16_18)) #Calculated returns by taking the log of asset prices
Rbrk_16_24 = diff(log(BRK_16_24))
hist(Rbrk_16_18, xlab="Returns of BRK", main="BRK - Normal Distribution")

#Walmart 
getSymbols("WMT", from = start_date, to = end_date, src = "yahoo", periodicity = "monthly")
## [1] "WMT"
WMT_16_24 = WMT$WMT.Adjusted 
WMT_16_18 = WMT_16_24[1:36,1] 
Rwmt_16_18 = diff(log(WMT_16_18)) 
Rwmt_16_24 = diff(log(WMT_16_24))
hist(Rwmt_16_18, xlab="Returns of Walmart", main="Walmart - Normal Distribution")

#Nvidia
getSymbols("NVDA", from=start_date, to=end_date, src = "yahoo" , periodicity="monthly")
## [1] "NVDA"
NVDA_16_24 = NVDA$NVDA.Adjusted 
NVDA_16_18 = NVDA_16_24[1:36,1] 
RNVDA_16_18 = diff(log(NVDA_16_18)) 
RNVDA_16_24 = diff(log(NVDA_16_24))
hist(RNVDA_16_18, xlab="Returns of Starbucks", main="Starbucks- Normal Distribution")

#Mastercard 
getSymbols("MA", from=start_date, to=end_date, src = "yahoo" , periodicity="monthly")
## [1] "MA"
MA_16_24 = MA$MA.Adjusted 
MA_16_18 = MA_16_24[1:36,1] 
Rma_16_18 = diff(log(MA_16_18)) 
Rma_16_24 = diff(log(MA_16_24))
hist(Rma_16_18, xlab="Returns of Mastercard", main="Mastercard- Normal Distribution")

#LVMH
getSymbols("LVMUY", from=start_date, to=end_date, src = "yahoo" , periodicity="monthly")
## [1] "LVMUY"
LV_16_24 = LVMUY$LVMUY.Adjusted 
LV_16_18 = LV_16_24[1:36,1] 
Rlv_16_18 = diff(log(LV_16_18)) 
Rlv_16_24 = diff(log(LV_16_24))
hist(Rlv_16_18, xlab="Returns of LVMH", main="LVMH- Normal Distribution")

#Treasury Rate
getSymbols("^TNX", from = start_date, to = end_date, src = "yahoo")
## Warning: ^TNX contains missing values. Some functions will not work if objects
## contain missing values in the middle of the series. Consider using na.omit(),
## na.approx(), na.fill(), etc to remove or replace them.
## [1] "TNX"
mtnx <- to.monthly(TNX)
## Warning in to.period(x, "months", indexAt = indexAt, name = name, ...): missing
## values removed from data
tnx_16_24 <- mtnx$TNX.Adjusted
tnx_16_18 <- tnx_16_24[1:36,1]
rtnx_16_18<- tnx_16_18/1200
#Calculate Excess Returns 
Re_brk = Rbrk_16_18 - rtnx_16_18
Re_wmt = Rwmt_16_18 - rtnx_16_18
Re_NVDA = RNVDA_16_18 - rtnx_16_18
Re_ma = Rma_16_18 - rtnx_16_18
Re_lv = Rlv_16_18 - rtnx_16_18
#Data Frames & Matrix of Asset Metrics
AssetPrices = data.frame(BRK_16_18, WMT_16_18, NVDA_16_18, MA_16_18, LV_16_18)
AssetReturns = data.frame(Rbrk_16_18,Rwmt_16_18,RNVDA_16_18,Rma_16_18,Rlv_16_18)
AssetExcessR = data.frame(Re_brk,Re_wmt, Re_NVDA, Re_ma, Re_lv)
AssetReturns = AssetReturns[-1,]
AssetExcessR = AssetExcessR[-1,]
AssetPrices_Matrix = matrix(c(BRK_16_18,WMT_16_18, NVDA_16_18, MA_16_18, LV_16_18), nrow = length(MA_16_18), ncol = 5, byrow = TRUE)  #Generating a matrix format for statistical purposes instead of a simple table. 
#Finding Variance-Covariance Matrix
asset.names <- c("BRK", "WMT", "NVDA", "MA", "LVMH")
VCV <- matrix(c(cov(AssetReturns)), nrow = 5, ncol = 5, byrow = TRUE)
dimnames(VCV) = list(asset.names, asset.names) 
#Calculate Returns
AssetReturns_Matrix <- matrix(colMeans(AssetReturns, na.rm = TRUE))
AssetExcessR_Matrix <- matrix(colMeans(AssetExcessR, na.rm = TRUE))
tnxy_mean <- mean((rtnx_16_18)[-1,])
#Create Return and Excess Return Table 
Return_Matrix <- matrix(c(AssetReturns_Matrix,AssetExcessR_Matrix), ncol=2)
dimnames(Return_Matrix) = list(asset.names, c("Returns", "Excess Returns"))
#Display Data
VCV
##                BRK          WMT        NVDA           MA          LVMH
## BRK   1.456492e-03 6.201981e-04 0.001478205 0.0003922688 -1.218749e-05
## WMT   6.201981e-04 2.867651e-03 0.001383689 0.0001044939  7.673969e-05
## NVDA  1.478205e-03 1.383689e-03 0.018266094 0.0031105174  3.333210e-03
## MA    3.922688e-04 1.044939e-04 0.003110517 0.0022608166  1.398364e-03
## LVMH -1.218749e-05 7.673969e-05 0.003333210 0.0013983640  3.277513e-03
Return_Matrix 
##         Returns Excess Returns
## BRK  0.01296780    0.011002609
## WMT  0.01175084    0.009785649
## NVDA 0.04380277    0.041837577
## MA   0.02205118    0.020085990
## LVMH 0.01868937    0.016724182
#Optimum Weights
Z_weight <- solve(VCV,AssetExcessR_Matrix)
W_weight <- Z_weight/sum(Z_weight)
dimnames(W_weight) <- list(asset.names, "Weights")
print(W_weight)
##         Weights
## BRK  0.30888759
## WMT  0.12725563
## NVDA 0.02044932
## MA   0.40718712
## LVMH 0.13622033
#Investing USD 100 in 2018 end 
#Positions 

BRK_position = W_weight[1,1]*100
WMT_position =W_weight[2,1]*100
NVDA_position = W_weight[3,1]*100
MA_position = W_weight[4,1]*100
LVMH_position = W_weight[5,1]*100

Positions = c(BRK_position, WMT_position, NVDA_position, MA_position, LVMH_position)
labels = c("BRK", "WMT", "NVDA", "MA", "LVMH")
pie(Positions, labels, main = "Position sizes", col = rainbow(length(Positions)))

#Portfolio Value
#BRK
BRK_19_24 = BRK_16_24[37:96]
BRK_shares = BRK_position/BRK_19_24[1,1]
df_brk = data.frame(value = rep(BRK_shares, 60))
BRK_port = df_brk$value*BRK_19_24$`BRK-A.Adjusted`
print(BRK_port)
##            BRK-A.Adjusted
## 2019-01-01       30.88876
## 2019-02-01       29.96656
## 2019-03-01       29.86888
## 2019-04-01       32.23537
## 2019-05-01       29.45687
## 2019-06-01       31.56801
## 2019-07-01       30.60774
## 2019-08-01       30.05362
## 2019-09-01       30.92168
## 2019-10-01       31.62642
## 2019-11-01       32.77233
## 2019-12-01       33.67420
## 2020-01-01       33.31782
## 2020-02-01       30.65038
## 2020-03-01       26.97189
## 2020-04-01       27.93375
## 2020-05-01       27.63032
## 2020-06-01       26.50583
## 2020-07-01       29.11685
## 2020-08-01       32.48129
## 2020-09-01       31.73173
## 2020-10-01       29.99631
## 2020-11-01       34.08056
## 2020-12-01       34.48980
## 2021-01-01       34.12142
## 2021-02-01       36.15224
## 2021-03-01       38.24673
## 2021-04-01       40.90406
## 2021-05-01       43.23435
## 2021-06-01       41.50904
## 2021-07-01       41.53869
## 2021-08-01       42.62946
## 2021-09-01       40.79290
## 2021-10-01       42.92715
## 2021-11-01       41.33799
## 2021-12-01       44.68825
## 2022-01-01       46.58650
## 2022-02-01       47.22113
## 2022-03-01       52.44852
## 2022-04-01       48.02781
## 2022-05-01       47.00744
## 2022-06-01       40.55203
## 2022-07-01       44.79118
## 2022-08-01       41.77747
## 2022-09-01       40.30611
## 2022-10-01       44.13176
## 2022-11-01       47.62521
## 2022-12-01       46.47801
## 2023-01-01       46.90332
## 2023-02-01       45.96376
## 2023-03-01       46.16952
## 2023-04-01       49.86626
## 2023-05-01       48.39312
## 2023-06-01       51.34674
## 2023-07-01       53.09098
## 2023-08-01       54.21399
## 2023-09-01       52.70197
## 2023-10-01       51.34822
## 2023-11-01       54.13218
## 2023-12-01       53.80743
#WMT
WMT_19_24 = WMT_16_24[37:96]
WMT_shares = WMT_position/WMT_19_24[1,1]
df_wmt = data.frame(value = rep(WMT_shares, 60))
WMT_port = df_wmt$value*WMT_19_24$WMT.Adjusted
print(WMT_port)
##            WMT.Adjusted
## 2019-01-01     12.72556
## 2019-02-01     13.14519
## 2019-03-01     12.95131
## 2019-04-01     13.72992
## 2019-05-01     13.54301
## 2019-06-01     14.82962
## 2019-07-01     14.81486
## 2019-08-01     15.33561
## 2019-09-01     16.00726
## 2019-10-01     15.81574
## 2019-11-01     16.06257
## 2019-12-01     16.02885
## 2020-01-01     15.51139
## 2020-02-01     14.58875
## 2020-03-01     15.39352
## 2020-04-01     16.54077
## 2020-05-01     16.88233
## 2020-06-01     16.37160
## 2020-07-01     17.68646
## 2020-08-01     18.97810
## 2020-09-01     19.20160
## 2020-10-01     19.04240
## 2020-11-01     20.96928
## 2020-12-01     19.78351
## 2021-01-01     19.35167
## 2021-02-01     17.89572
## 2021-03-01     18.70979
## 2021-04-01     19.35225
## 2021-05-01     19.64549
## 2021-06-01     19.58238
## 2021-07-01     19.79484
## 2021-08-01     20.56553
## 2021-09-01     19.42587
## 2021-10-01     20.82518
## 2021-11-01     19.60009
## 2021-12-01     20.16595
## 2022-01-01     19.56426
## 2022-02-01     18.91356
## 2022-03-01     20.83906
## 2022-04-01     21.49140
## 2022-05-01     18.06941
## 2022-06-01     17.14114
## 2022-07-01     18.61727
## 2022-08-01     18.68776
## 2022-09-01     18.36559
## 2022-10-01     20.15400
## 2022-11-01     21.58275
## 2022-12-01     20.07754
## 2023-01-01     20.44886
## 2023-02-01     20.20155
## 2023-03-01     20.95770
## 2023-04-01     21.54597
## 2023-05-01     20.96083
## 2023-06-01     22.51745
## 2023-07-01     22.90139
## 2023-08-01     23.29535
## 2023-09-01     22.99286
## 2023-10-01     23.49318
## 2023-11-01     22.38329
## 2023-12-01     22.66507
#NVDA
NVDA_19_24 = NVDA_16_24[37:96]
NVDA_shares = NVDA_position/NVDA_19_24[1,1]
df_nvda = data.frame(value = rep(NVDA_shares, 60))
NVDA_port = df_nvda$value*NVDA_19_24$NVDA.Adjusted
print(NVDA_port)
##            NVDA.Adjusted
## 2019-01-01      2.044932
## 2019-02-01      2.194443
## 2019-03-01      2.556984
## 2019-04-01      2.577490
## 2019-05-01      1.928988
## 2019-06-01      2.341350
## 2019-07-01      2.405362
## 2019-08-01      2.388111
## 2019-09-01      2.484091
## 2019-10-01      2.868684
## 2019-11-01      3.093019
## 2019-12-01      3.360359
## 2020-01-01      3.376497
## 2020-02-01      3.856916
## 2020-03-01      3.766769
## 2020-04-01      4.176597
## 2020-05-01      5.073134
## 2020-06-01      5.428806
## 2020-07-01      6.070038
## 2020-08-01      7.648200
## 2020-09-01      7.737407
## 2020-10-01      7.169704
## 2020-11-01      7.665931
## 2020-12-01      7.467727
## 2021-01-01      7.432598
## 2021-02-01      7.847293
## 2021-03-01      7.637727
## 2021-04-01      8.591241
## 2021-05-01      9.298141
## 2021-06-01     11.449169
## 2021-07-01     11.163531
## 2021-08-01     12.815818
## 2021-09-01     11.862378
## 2021-10-01     14.640152
## 2021-11-01     18.710902
## 2021-12-01     16.841300
## 2022-01-01     14.022869
## 2022-02-01     13.965027
## 2022-03-01     15.626396
## 2022-04-01     10.623476
## 2022-05-01     10.695074
## 2022-06-01      8.682873
## 2022-07-01     10.405725
## 2022-08-01      8.647471
## 2022-09-01      6.954528
## 2022-10-01      7.734834
## 2022-11-01      9.698201
## 2022-12-01      8.377106
## 2023-01-01     11.199092
## 2023-02-01     13.307986
## 2023-03-01     15.922462
## 2023-04-01     15.909115
## 2023-05-01     21.691067
## 2023-06-01     24.252669
## 2023-07-01     26.793541
## 2023-08-01     28.299238
## 2023-09-01     24.941517
## 2023-10-01     23.384419
## 2023-11-01     26.819259
## 2023-12-01     28.397333
#MA
MA_19_24 = MA_16_24[37:96]
MA_shares = MA_position/MA_19_24[1,1]
df_ma= data.frame(value = rep(MA_shares, 60))
MA_port = df_ma$value*MA_19_24$MA.Adjusted
print(MA_port)
##            MA.Adjusted
## 2019-01-01    40.71871
## 2019-02-01    43.42428
## 2019-03-01    45.48759
## 2019-04-01    49.11771
## 2019-05-01    48.65428
## 2019-06-01    51.17705
## 2019-07-01    52.67446
## 2019-08-01    54.50108
## 2019-09-01    52.60282
## 2019-10-01    53.61780
## 2019-11-01    56.67335
## 2019-12-01    57.90677
## 2020-01-01    61.27152
## 2020-02-01    56.36446
## 2020-03-01    46.90922
## 2020-04-01    53.39721
## 2020-05-01    58.52103
## 2020-06-01    57.51162
## 2020-07-01    60.00695
## 2020-08-01    69.75851
## 2020-09-01    65.85957
## 2020-10-01    56.21347
## 2020-11-01    65.61258
## 2020-12-01    69.59603
## 2021-01-01    61.67010
## 2021-02-01    69.08098
## 2021-03-01    69.51048
## 2021-04-01    74.58833
## 2021-05-01    70.47843
## 2021-06-01    71.35996
## 2021-07-01    75.43527
## 2021-08-01    67.75332
## 2021-09-01    68.03709
## 2021-10-01    65.65751
## 2021-11-01    61.70419
## 2021-12-01    70.40374
## 2022-01-01    75.70578
## 2022-02-01    70.79042
## 2022-03-01    70.11551
## 2022-04-01    71.29269
## 2022-05-01    70.30910
## 2022-06-01    61.98093
## 2022-07-01    69.50752
## 2022-08-01    63.82518
## 2022-09-01    55.94861
## 2022-10-01    64.57486
## 2022-11-01    70.24076
## 2022-12-01    68.53204
## 2023-01-01    73.03934
## 2023-02-01    70.13564
## 2023-03-01    71.73856
## 2023-04-01    75.01941
## 2023-05-01    72.16942
## 2023-06-01    77.76075
## 2023-07-01    77.95452
## 2023-08-01    81.70252
## 2023-09-01    78.39000
## 2023-10-01    74.51712
## 2023-11-01    82.05692
## 2023-12-01    84.57120
#LVMH
LV_19_24 = LV_16_24[37:96]
LVMH_shares = LVMH_position/LV_19_24[1,1]
df_lv= data.frame(value = rep(LVMH_shares, 60))
LV_port = df_lv$value*LV_19_24$LVMUY.Adjusted
print(LV_port)
##            LVMUY.Adjusted
## 2019-01-01       13.62203
## 2019-02-01       14.54643
## 2019-03-01       15.62771
## 2019-04-01       16.66023
## 2019-05-01       16.19028
## 2019-06-01       18.25348
## 2019-07-01       17.74305
## 2019-08-01       17.11250
## 2019-09-01       17.01814
## 2019-10-01       18.30495
## 2019-11-01       19.15639
## 2019-12-01       20.00355
## 2020-01-01       18.80268
## 2020-02-01       17.84076
## 2020-03-01       16.04849
## 2020-04-01       16.60278
## 2020-05-01       18.39228
## 2020-06-01       19.32774
## 2020-07-01       18.86001
## 2020-08-01       20.62513
## 2020-09-01       20.73294
## 2020-10-01       20.71094
## 2020-11-01       25.39527
## 2020-12-01       27.55358
## 2021-01-01       26.96155
## 2021-02-01       28.05724
## 2021-03-01       29.56603
## 2021-04-01       33.32364
## 2021-05-01       35.73675
## 2021-06-01       35.08529
## 2021-07-01       35.66115
## 2021-08-01       32.93749
## 2021-09-01       31.85691
## 2021-10-01       34.98747
## 2021-11-01       34.81182
## 2021-12-01       36.79731
## 2022-01-01       36.48911
## 2022-02-01       32.54766
## 2022-03-01       31.83976
## 2022-04-01       28.99254
## 2022-05-01       29.13014
## 2022-06-01       27.59911
## 2022-07-01       31.33409
## 2022-08-01       29.23402
## 2022-09-01       26.53327
## 2022-10-01       28.50237
## 2022-11-01       34.54970
## 2022-12-01       32.95038
## 2023-01-01       39.73287
## 2023-02-01       37.89965
## 2023-03-01       41.78900
## 2023-04-01       43.66772
## 2023-05-01       40.12715
## 2023-06-01       43.27838
## 2023-07-01       42.68481
## 2023-08-01       38.79562
## 2023-09-01       34.63141
## 2023-10-01       32.84152
## 2023-11-01       34.78725
## 2023-12-01       37.52659
#No. of Shares
Shares = c(BRK_shares, WMT_shares, NVDA_shares, MA_shares, LVMH_shares)
print(Shares)
##            BRK-A.Adjusted
## 2019-01-01   9.916135e-05
## 2019-01-01   4.358847e-01
## 2019-01-01   5.735060e-02
## 2019-01-01   1.988742e-01
## 2019-01-01   2.332116e-01
#Total Portfolio 
Portfolio = data.frame(BRK_port, WMT_port, NVDA_port, MA_port, LV_port)
Portfolio$Total = rowSums(Portfolio)
print(Portfolio$Total)
##  [1] 100.0000 103.2769 106.4925 114.3207 109.7734 118.1695 118.2455 119.3909
##  [9] 119.0340 122.2336 127.7577 130.9737 132.2799 123.3013 109.0899 118.6511
## [17] 126.4991 125.1456 131.7403 149.4912 145.2632 133.1328 153.7236 158.8906
## [25] 149.5373 159.0335 163.6708 176.7595 178.3932 178.9858 183.5935 176.7016
## [33] 171.9751 179.0375 176.1650 188.8965 192.3685 183.4378 190.8693 180.4279
## [41] 175.2112 155.9561 174.6558 162.1719 148.1081 165.0978 183.6966 176.4151
## [49] 191.3235 187.5086 196.5772 206.0085 203.3416 219.1560 223.4252 226.3067
## [57] 213.6578 205.5845 220.1789 226.9676
Total_Portfolio = data.frame(Portfolio$Total)
print(Total_Portfolio)
##    Portfolio.Total
## 1         100.0000
## 2         103.2769
## 3         106.4925
## 4         114.3207
## 5         109.7734
## 6         118.1695
## 7         118.2455
## 8         119.3909
## 9         119.0340
## 10        122.2336
## 11        127.7577
## 12        130.9737
## 13        132.2799
## 14        123.3013
## 15        109.0899
## 16        118.6511
## 17        126.4991
## 18        125.1456
## 19        131.7403
## 20        149.4912
## 21        145.2632
## 22        133.1328
## 23        153.7236
## 24        158.8906
## 25        149.5373
## 26        159.0335
## 27        163.6708
## 28        176.7595
## 29        178.3932
## 30        178.9858
## 31        183.5935
## 32        176.7016
## 33        171.9751
## 34        179.0375
## 35        176.1650
## 36        188.8965
## 37        192.3685
## 38        183.4378
## 39        190.8693
## 40        180.4279
## 41        175.2112
## 42        155.9561
## 43        174.6558
## 44        162.1719
## 45        148.1081
## 46        165.0978
## 47        183.6966
## 48        176.4151
## 49        191.3235
## 50        187.5086
## 51        196.5772
## 52        206.0085
## 53        203.3416
## 54        219.1560
## 55        223.4252
## 56        226.3067
## 57        213.6578
## 58        205.5845
## 59        220.1789
## 60        226.9676
plot(Portfolio$Total, main = "Hypothetical Path of USD 100", type="l", col= "black")

#Calculate Stats
Return_Portfolio <- t(W_weight)%*%AssetReturns_Matrix
Variance_Portfolio <- t(W_weight)%*%VCV%*%(W_weight)
SD_Portfolio <- Variance_Portfolio^0.5
Sharpe_Ratio <- ((Return_Portfolio - tnxy_mean)/SD_Portfolio)

Monthly Optimal Stats table indicate strong performance

#Optimal Stats Table 
PortfolioStats_Matrix <- matrix(c(Return_Portfolio, Variance_Portfolio, SD_Portfolio, Sharpe_Ratio))
PortfolioStats.names <- c("Return", "Variance", "SD", "Sharpe Ratio")
dimnames(PortfolioStats_Matrix) <- list(PortfolioStats.names, "Opt. Portfolio")
PortfolioStats_Matrix
##              Opt. Portfolio
## Return          0.017921519
## Variance        0.001039977
## SD              0.032248670
## Sharpe Ratio    0.494790279
#Global Minimum Variance Portfolio 
ZGMV <- solve(VCV,matrix(c(1,1,1,1,1), byrow = TRUE))
WGMV <- ZGMV/sum(ZGMV)                                
dimnames(WGMV) <- list(asset.names, "Weights")
print(WGMV)
##          Weights
## BRK   0.45824952
## WMT   0.18731268
## NVDA -0.08898693
## MA    0.22720437
## LVMH  0.21622037
#Calculate GMV Portfolio Stats 
RGMV <- t(WGMV)%*%AssetReturns_Matrix
VGMV <- t(WGMV)%*%VCV%*%WGMV
SDGMV <- VGMV^0.5 
#Create GMV Stats Table 
GTBL <- matrix(c(RGMV, VGMV, SDGMV), nrow = 3)         
gmvstat.names <- c("Return", "Variance", "Std Dev")    
dimnames(GTBL) <- list(gmvstat.names, "GMV Portfolio")
#Efficient Frontier and CAL
j <- 0                                                            
return_p <- rep(0, 50000)
sd_p <- rep(0, 50000) 
vect_0 <- rep(0, 50000)                                           #create a matrix of 0
fractions <- matrix(vect_0, 10000,5)

for (a in seq(-.2, 1, 0.1)) {                                     #iterate through weights for asset 1 from -20% to 100% by 10%
  for (b in seq(-.2, 1, 0.1)) {                                 #iterate through weights for asset 2 from -20% to 100% by 10%
    for(c in seq(-.2, 1, 0.1)){                               #iterate through weights for asset 3 from -20% to 100% by 10%
      for(d in seq(-.2, 1, 0.1)){                           #iterate through weights for asset 4 from -20% to 100% by 10%
        for(e in seq(-.2, 1, 0.1)){                       #iterate through weights for asset 5 from -20% to 100% by 10%
          if(a+b+c+d+e==1) {                                        #test that the weights are equal to 1
            j=j+1                                                 #increment j by 1 if a+b+c+d+e is equal to 1 (valid weights)
            fractions[j,] <- c(a,b,c,d,e)                             #load a,b,c,d,e values into row j of the matrix
            sd_p[j] <-  (t(fractions[j,])%*%VCV%*%fractions[j,])^.5  #calculate the std dev of the portfolio at a given weight of assets
            return_p[j] <-  fractions[j,]%*%AssetReturns_Matrix                       #calcuate the return of the portfolio at a given weight of assets
            
          }
        }
      }
    }
  }
}           
Rport <- return_p[1:j]                                            #assign filled vector spots in return_p to the R_p matrix to omit empty spots
Stddev_p <- sd_p[1:j]                                             #assign filled vector spots in sd_p to the sigma_p matrix to omit empty spots

##Create Capital Asset Line
f <- seq(0,.24, .24)                                              #create x-coordinates for CAL points
CAL <- tnxy_mean+Sharpe_Ratio*f
## Warning in Sharpe_Ratio * f: Recycling array of length 1 in array-vector arithmetic is deprecated.
##   Use c() or as.vector() instead.
Sharpe_Ratio
##              [,1]
## Weights 0.4947903
#Plot 
plot(Stddev_p, Rport, col="yellow1", xlab="Portfolio Standard Deviation", ylab= "Portfolio expected return", xlim=c(0, .12), ylim= c(0, .035)) 
points(SDGMV, RGMV, col="blue3", pch=17)
points(SD_Portfolio, Return_Portfolio, col= "black", pch=16, bg="black") 
points(f, CAL, col= "cadetblue", type="l")
legend("bottomright",c("SD/R", "GMV", "Tangency Portfolio"),cex=.8,col=c("yellow1","blue3", "black","cadetblue"),lty = c(0,0,0,1),pch=c(1,17,16,NA_integer_))