My name is Henry Bowers, I graduated from CUNY Baruch College, Zicklin School of Business with a Bachelors of Business Administration in Finance & Investments. I have always had an interest in learning data science for finance to make better informed investment decisions. After taking online courses through Data Camp and reading many articles on R for finance. I decided to take a capstone course in financial econometrics, which was my favorite course in college. Throughout the class I was able to learn even more about risk management and data visualization of time series. I have a growing passion for understanding data science for finance and applying those skills to make better-informed investment decisions for my personal portfolio using quantitative investment strategies with R programming. Skills I developed include multi-asset portfolio construction, optimization, and quantitative risk management.
Since I started learning how to invest in the markets, I have also had an interest in analyzing companies based on their fundamental performances and then eager to backtest results to see how that portfolio would have performed against the SP500 or other related indexes. Warren Buffet and Harry Markowitz influenced me to combine my passion for value investing with a mix of applying financial econometrics methodologies to build a portfolio that could potentially outperform the SP500 over the 3-to-5-year period and even achieve lower levels of risks.
Data gathered for research has been downloaded from yahoo finance API, there is other sources to obtain data if you want to pay for a service. for retail investors obtaining data through yahoo finance is one of the best options. Historical returns are also not predictors of future performance.
first.date = "2016-6-1"
last.date = "2022-6-23"
getSymbols("^GSPC", from = first.date, to = last.date, periodicity = "daily")
[1] "^GSPC"
SP500.rets <- Return.calculate(Ad(GSPC), method = "log")
colnames(SP500.rets) <- "SP500"
p1 <- chart.CumReturns(SP500.rets, plot.engine = "ggplot2") + theme_classic() + scale_y_continuous(labels = scales::percent, breaks = seq(-1,2,0.3)) +
scale_x_date(date_breaks = "years", date_labels = "%Y") + labs(title = "SP500 Performance", x = "Date", y = "Cumulative returns")
p2 <- chart.Drawdown(SP500.rets, plot.engine = "ggplot2") + theme_classic() + scale_y_continuous(labels = scales::percent, breaks = seq(-1,2,0.1)) +
scale_x_date(date_breaks = "years", date_labels = "%Y") + labs(x = "Date", y = "Drawdowms")
grid.arrange(p1,p2)
Return.cumulative(SP500.rets) * 100
SP500
Cumulative Return 59.94126
From 2016 the SP500 has achieved roughly 60% overall, which is not bad at all despite everything that has happened in the market, investors who have bought VOO, SPY, or any other passive fund that tracks the SP500 would still be at a net positive. Throughout the past 7 years, the SP500 has experienced many drawdowns most notably now to COVID-19 and the war in Ukraine.
table.Drawdowns(SP500.rets, top = 5, geometric = TRUE)
From Trough To Depth Length To Trough Recovery
1 2020-02-20 2020-03-23 2020-09-02 -0.3610 137 23 114
2 2022-01-04 2022-06-16 <NA> -0.2467 118 114 NA
3 2018-09-21 2018-12-24 2019-07-01 -0.2025 194 65 129
4 2018-01-29 2018-04-02 2018-08-27 -0.1056 147 44 103
5 2020-09-03 2020-09-23 2020-11-16 -0.0979 52 14 38
SP500.price <- Ad(GSPC)
colnames(SP500.price) <- "SP500"
dygraph(SP500.price, main = "SP500 <br> Red Shading Indicates Drawdowns", ylab = "Prices") %>%
dyShading(from = "2018-09-21", to = "2019-07-01", color = "#FFE6E6") %>%
dyShading(from = "2018-01-29", to = "2018-08-27", color = "#FFE6E6") %>%
dyShading(from = "2020-02-20", to = "2020-09-02", color = "#FFE6E6") %>%
dyShading(from = "2020-09-03", to = "2020-11-16", color = "#FFE6E6") %>%
dyShading(from = "2022-01-04", to = "2022-06-16", color = "#FFE6E6")
Out of the top 5 drawdowns, now of this data, COVID-19 has the largest drop, and it took the market 114 days to recover from those losses. Since the war in Ukraine, the market has fallen roughly 25% and potentially could lose a lot more in value and even take longer to recover. Investors should note that it took 129 days for the market to recover in 2018. I remember this was the beginning of my investing journey and I did not know the information I know now on how to manage risk and build conviction with my investments. 2018 was a rough year for the market, the major trade war between the U.S. and China was going on, technology companies were facing a lot of privacy issues at this time, and earnings were inflated. Fred also hiked interest rates just as they did this year. Investors could now potentially prepare for a long drawdown period and buy companies at a “discounted” market price.
Throughout my research and experience, I have always kept in mind of this one cardinal rule investing should be boring. I always had a long-term mindset when it came to investing in the market. As we saw above despite market drawdowns, the market has always recovered and when it has it experienced a greater amount of growth. When I select potential investments for my portfolio, I look at the asset from a fundamental perspective and psychological perspective.
Fundamental: My accounting background taught me to always pay close attention to a company’s debt and how much cash they have on hand regarding an emergency. The current ratio is a big factor for me, I need to see that a company could pay off any short-term obligations in case of another emergency. In my advanced corporate finance class, we learned about capital structures of business, ever since then I look for companies with a moderate debt ratio (total debt / total capital) of 30 to 60%. companies with higher than 60% leverage have a much greater chance of defaulting on their debts, especially if their Current ratio is low and don’t have stable leverage-free cash flows. Which is another factor that I look at when adding another company to my portfolio. Increasing leverage-free cash flows indicates that a firm has more cash to potentially use to expand business operations or pay out more in dividends. Leverage free cash flows consider all payments, which is why I love to see a steady increase over time.
Psychological: Behavioral finance plays a big role in portfolio construction for me. Most investors decide to sell their holdings during bad times, by letting their emotions get the best of them. I too am, a victim of this. I did this twice throughout my investing journey, once in 2018 and again in 2020 during the beginning of the COVID-19 crash. In 2018, I did not have a strong fundamental knowledge of investing and analyzing financials, it was not until 2019 that I started to become more educated on financial statement analysis. When COVID-19 happed I had all very strong financially stable companies, however, what I lacked the most at that time was risk management and conviction. What helped me build both risk management and conviction was not only learning a programming language such as R to backtest strategies but was to ask myself what are the true purposes of this company? Are these companies going to be around in the future and not easily replaced? Are these companies benefiting society through the services they are providing? Once I have the answer to those questions, I feel more confident regarding opening a new position.
I did not disclose which assets I have in my personal portfolio because I am not a financial advisor, so I want to avoid viewers believing that my portfolio is the absolute best, however that is not the case, and it is still a work in progress. I will share what sectors my portfolio is exposed to and how I derived these allocations.
port.allo <- data.frame(sectors = c("REIT", "Medical", "Consumer.Defensive", "Consumer.Cyclical", "Technology", "Financial"),
weights = c(26,24,18,11,11,10))
head(port.allo)
sectors weights
1 REIT 26
2 Medical 24
3 Consumer.Defensive 18
4 Consumer.Cyclical 11
5 Technology 11
6 Financial 10
port.allocations <- ggplot(port.allo, aes(x="", y = weights, fill = sectors)) + geom_bar(width = 1, stat = "identity")
pie <- port.allocations + coord_polar("y", start=0)
pie + scale_fill_brewer("Blues") + theme_classic() +
theme(axis.text.x=element_blank())+
geom_text(aes(y = weights/6 + c(0, cumsum(weights)[-length(weights)]),
label = percent(weights/100)), size = 4)
Earlier I mentioned how Harry Markowitz also had an influence on me regarding applying financial econometrics to my investing strategy. After researching the Modern Portfolio Theory (MPT), which mentioned the mean-variance portfolio. I created an optimization model that considers many different factors that were influenced by MPT. The Mean-Variance portfolio’s sole purpose is to maximize returns and minimize variance, by utilizing a linear program optimization model. However, this may sound good for investors at first, but this model does not consider downside risk which later Markowitz adds on those who use the model should change to Mean - Semi Variance, which does consider downside risk. The downside risk is the potential losses that an asset could fall, variance although it is a measurement of volatility, it does not take into consideration of values that fall below the mean which is essential to considerations of all observations. For my personal portfolio, I utilize DEoptim a stochastic global optimization algorithm that allows me to backtest portfolios with more complex constraints than a linear program would be able to handle.
For my constraints I use multiple factor exposures, to name a few beta and CDaR. CDaR is the conditional Drawdown at Risk, it outputs the expected drawdowns of an asset given a confidence level. Since I am a long-term investor, I also set a full investment constraint and box constraint for my optimization. what the full investment constraint does is it makes sure the optimizer weights sum up to 1 and not below or above, and with a box constraint it allows me to set a minimum and max allocation. The brokerage I currently use does not have any transaction cost, however, if my brokerage had a transaction cost, I would add that as a constraint.
Regarding my objectives for optimization, I have many. Instead of just doing a simple Mean-Variance, optimization, or Mean - Semi Variance. I set an objective to maximize return, and minimize standard deviation, ETL at a confidence level of 0.95 utilizing the “modified” method, and CDaR at a confidence level of 0.95 as well. These objectives also have contributions limits, an example of a few would be, that no asset could contribute to 10% of volatility or no asset can contribute to 5% ETL. By setting these constraints and objectives I have been able to successfully derive an optimized asset allocation for my portfolio.
After obtaining the optimal asset allocations for my portfolio, the next step would be to backtest the strategy to see how well it performed against the SP500. Since this is my personal portfolio, I am acting as my own “active fund manager” so my end goal is to outperform the SP500 over a 3 to 5-year period following the strategies mentioned previously. Since I am a long-term investor and I want to minimize any capital gains tax as possible, I choose to rebalance only once a year. The following showcases how well my strategy performed against the SP500.
load(file = "/Users/henrybowers/Bowers.Index")
perf <- na.omit(cbind(SP500.rets, Bowers.Index))
chart.CumReturns(perf, plot.engine = "ggplot2") + theme_classic() + scale_y_continuous(labels = scales::percent, breaks = seq(-1,2,0.2)) +
scale_x_date(date_breaks = "years", date_labels = "%Y") + labs(title = "My Strategy Vs SP500", x = "Date", y = "Cumulative returns")
Return.cumulative(perf) * 100
SP500 My.Strategy
Cumulative Return 59.94126 100.0505
chart.RelativePerformance(Bowers.Index, SP500.rets, main = "Relative Performance to SP500")
As the visuals show my portfolio has well outperformed the SP500 throughout the 7-year period. My strategy was able to achieve 100% in cumulative returns as opposed to the SP500 at 60% (rounded). Was able to beat the market by roughly 40% overall throughout the 7-year period which beat my own expectations. One of the important measures to analyze a portfolio performance would be relative performance, which is the asset return - benchmark return.
By analyzing relative return, investors would be able to see how well a portfolio manager really is doing against the SP500. If you gave money to a portfolio manager and you notice historically the portfolio has been underperforming the market, then you are 1. better off just taking back your money and investing into a low-cost ETF that tracks a market index, or 2. find a new portfolio manager that has historically outperformed the market in most periods of time. My portfolio objective was to hopefully outperform the market through a 3 to 5-year period because I know there might be years where my portfolio may not perform as well. However, as shown from the relative performance my portfolio outperformed the market throughout most of the time, where in early 2017 it fell below 1.00 which represents underperformance that did not last long and had extreme performance after.
At the time I was conducting my research paper, the 10 year risk free rate had a yield of 2.95%
SharpeRatio(perf, Rf = 0.0295/252, annualize = TRUE, FUN = "ES", p = 0.95)
SP500 My.Strategy
Annualized ES Sharpe (Rf=2.9%, p=95%): 1.212093 3.002161
SharpeRatio(perf, Rf = 0.0295/252, annualize = TRUE, FUN = "StdDev")
SP500 My.Strategy
Annualized StdDev Sharpe (Rf=2.9%, p=95%): 0.2561315 0.4555866
table.DownsideRisk(perf, ci = 0.95, scale = 252, Rf = 0.0295/252, MAR = 0.0295/252, p = 0.95)
SP500 My.Strategy
Semi Deviation 0.0092 0.0093
Gain Deviation 0.0083 0.0084
Loss Deviation 0.0110 0.0113
Downside Deviation (MAR=2.95%) 0.0091 0.0091
Downside Deviation (Rf=2.95%) 0.0091 0.0091
Downside Deviation (0%) 0.0091 0.0091
Maximum Drawdown 0.3610 0.3556
Historical VaR (95%) -0.0183 -0.0183
Historical ES (95%) -0.0315 -0.0310
Modified VaR (95%) -0.0184 -0.0177
Modified ES (95%) -0.0407 -0.0296
CAPM.beta(Bowers.Index, SP500.rets, 0.0295/252)
[1] 0.9773303
Earlier I mentioned how my portfolio is still a work in progress and is not 100% perfect. For instance, in accordance with Harry Markowitz, a portfolio should have a Sharpe Ratio above 1 unless it won’t be a sound investment. This is taking into consideration utilizing the standard deviation as the risk measure, however if we choose to use the modified Sharpe Ratio, which takes into consideration of a different risk measure such as CVaR/ES/ETL (All the same) at a given confidence level of 0.95, will achieve a much higher result above 1. Using ES, the expected shortfall as the risk measure is a much better measurement as opposed to standard deviation because it outputs the values of expected losses taking into consideration of downside risk which as mentioned earlier standard deviation does not. ES is a very important measure to look at cause investors could use that information to potentially hedge their portfolios and try to minimize the ES value to an amount they are okay with.
When looking at downside risk, my portfolio has reached lower daily expected losses and lower maximum drawdowns when compared to the SP500. However, what is interesting to note is my portfolio has achieved a beta of 0.97 which states, that my strategy does have a close correlation to the SP500 performance, however, it also means my portfolio does have a chance of following the SP500 during periods of time and my portfolio in terms of volatility is less risky compared to the market index.
table.Drawdowns(Bowers.Index, top = 5, geometric = TRUE)
From Trough To Depth Length To Trough Recovery
1 2020-02-20 2020-03-23 2020-08-17 -0.3556 125 23 102
2 2022-01-04 2022-06-16 <NA> -0.2845 118 114 NA
3 2018-09-21 2018-12-24 2019-04-12 -0.1909 140 65 75
4 2018-01-29 2018-02-08 2018-07-18 -0.1003 119 9 110
5 2016-01-06 2016-02-11 2016-03-11 -0.0974 46 26 20
chart.CumReturns(Bowers.Index, plot.engine = "dygraph") %>%
dyShading(from = "2018-01-29", to = "2018-07-18", color = "#FFE6E6") %>%
dyShading(from = "2018-09-21", to = "2019-04-12", color = "#FFE6E6") %>%
dyShading(from = "2016-01-06", to = "2016-03-11", color = "#FFE6E6") %>%
dyShading(from = "2020-02-20", to = "2020-08-17", color = "#FFE6E6") %>%
dyShading(from = "2022-01-04", to = "2022-06-16", color = "#FFE6E6")
Overall the backtest has shown my investment thesis has the ability to outperform the market, meanwhile generating lower expected losses, drawdowns and achieving a faster recovery back to the high. Thank you for taking the time to read over the research. If any questions, please reach out via Linkedin.