In a recent project for my optimization and simulation class, I was tackling a portfolio optimization problem. I was asked to find a portfolio with the same return rate but lower portfolio variance. Using quadratic programming to obtain the minimal variance portfolio is not an issue for me.

The target portfolio has a expected return of 2.22% and the associated portfolio standard deviation is 3.31%. Using optimization, I found a portfolio maintaining the same return rate but a lower portfolio standard deviation of 2.85%.

Here is a plot comparing the simulated return distributions for these two portfolios.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
library(ggplot2) library(ggthemes) library(animation) theme_set(theme_minimal(12)) # simulate two samples from two different normal distributions # Note, in the actual project, I obtained these distributions via simulating stock returns. mean1 <- 2.22 mean2 <- 2.22 sd1 <- 3.31 sd2 <- 2.85 set.seed(1) expectedR1 <- rnorm(n=10000, mean = mean1, sd = sd1) expectedR2 <- rnorm(n=10000, mean = mean2, sd = sd2) # calculate the probability distributions d1 <- density(expectedR1) d2 <- density(expectedR2) # make a dataframe for plotting x <- c(d1$x, d2$x) y <- c(d1$y, d2$y) label <- c(rep("Target",512), rep("Optimized",512)) df <- cbind.data.frame(x,y,label) # make a plot to show difference ggplot(data = df, aes(x = x,y = y)) + geom_line(aes(color = label),size = 1.2) + geom_vline(x = 2.22, linetype = 2) + xlab("Expected Portfolio Return") + ylab("Frequency") + ggtitle("Difference between Two Portfolios") |

After I got this plot, I was thinking about a way to show the differences in a dynamic way, better if I can make an animation for it and I wish to do so in R. I found that the slope diagram might be a good chart type for this task and I found an R package called animation for creating animation within R.

There is no default geom in ggplot for creating the slope diagram, however, I found that one can create slope diagram using geom_segment().

Here is an example of slope diagram. Basically, the vertical position determines the portfolio returns and for each iteration in the simulation we add a line segment connecting the two different portfolio return values from both sides and coloring the line segment.

To use the animation package, one need to write a loop or a function that can plot all the plots needed to generate the animation in time sequence order.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
makePlot <- function(n = 100){ # n will be used to specify the number of frames in the animation # I am sampling the returns using the number n exp1<-expectedR1[seq(1,10000,10000/n)] exp2<-expectedR2[seq(1,10000,10000/n)] # create a dataframe for creating plots iteration<- 1:n df<-data.frame(exp1,exp2,iteration) # define the colors for the slope bars, red if target portfolio has higher return, green otherwise df$col <- ifelse(df$exp1 > df$exp2,I("#FF6464"),I("#00CCCC")) # a loop to create n plots in time sequence order for (i in 1:n){ # subset the dataframe pdf <- df[1:i,] # creating the slope diagram for this iteration p<-ggplot(pdf) + geom_segment(aes(x=0,xend=24,y=exp1,yend=exp2),size=.75, color = pdf$col, alpha = 0.4) # modifications p<-p + theme(panel.background = element_blank()) p<-p + theme(panel.grid=element_blank()) p<-p + theme(axis.ticks=element_blank()) p<-p + theme(axis.text=element_blank()) p<-p + theme(panel.border=element_blank()) p<-p + xlab("") + ylab("Portfolio Return") p<-p + xlim(-20,40) p<-p + ylim(-8.5,12.5) p<-p + geom_text(label=round(df$exp2[i],4), y=pdf$exp2[i], x=24, hjust=-0.2,size=3.5) p<-p + geom_text(label=round(df$exp1[i],4), y=pdf$exp1[i], x=0, hjust=1.2,size=3.5) p<-p + geom_text(label="Joe's Portfolio", x=0, y=13,hjust= 1.2,size=5) p<-p + geom_text(label="Optimized Portfolio", x=24,y=13,hjust=-0.1,size=5) p<-p + geom_text(label=paste("Iteration ",i), x = 12, y = 12, hjust = 0.6, size = 5) # plot the plotting object plot(p) } } |

You can define your own function to make all the plots needed for your animation. And once you have done this, you can use the saveVideo() function from the animation package to generate a .mp4 animation.

To do so, you just need to specify your operation system and the path to ffmpeg executable in your system and then calling saveVideo() by passing the plot making function along with some parameters for setting up the video quality.

1 2 3 4 5 6 7 8 9 |
oopts = if (.Platform$OS.type == "windows") { ani.options(ffmpeg = "D:/Program Files/ffmpeg/bin/ffmpeg.exe")} saveVideo({makePlot(500)}, video.name = "SlopeReturns.mp4", img.name = "Rplot", interval = 0.6, nmax = 500, other.opts = "-pix_fmt yuv420p -b 300k") |

Here is the animation created using the above code.

The animation dynamically showing the performance difference between two portfolios, while the minimal variance portfolio has a lower chance of losing a huge amount of money, it also gives up some chance to earning large returns. This is depicted by the difference between density of points on the lower and upper parts in two sides. Also, the amount of red color and green color are approximately equal, suggesting that half of the time the minimal variance will yield a lower return than the target portfolio.

There are many other options in the animation package. You can use it to generate GIF, HTML or SWF animations with similar method.