This dashboard runs a basic mean reversion contrarian trading strategy for a user input list of stocks using Yahoo Finance data.
The contrarian investment strategy this code runs is taken from the MIT
edX course Adaptive Markets: Financial Market Dynamics and Human
Behavior by Professor Andrew Lo. More information on this course can
be found
here.
This strategy determines the fraction of money in a portfolio
- Calculating the excess return that stock has generated over the
average return of all the stocks in the portfolio.
where the average return of all the stocks in the portfolio is calculated as
and
$k$ is the lag in the information used to determine these weights. For the purpose of this implementation,$k$ is equal to 1 day. - Dividing the excess return by the total number of stocks in the
portfolio (
$n$ ). - Multiplying the result of step 2 by -1. This ensures we are buying the stocks which performed below the average return of the stocks in the portfolio and selling the stocks which performed above the average return of the stocks in the portfolio (ie. buying the lows and selling the highs).
This process is summarized by the following formula:
The weights generated by this strategy sum to 0, creating an "arbitrage portfolio".
This portfolio costs nothing to create (Outside of brokerage and transaction fees) and looks to generate a profit every day.
The created portfolio is market neutral/dollar neutral, meaning the
amount invested long is equal to the amount invested short, leading to 0
net exposure. However, even though the net exposure is 0, the portfolio
is actually very exposed since these long and short positions won't
necessarily continue to balance out over time. As such, brokers will ask
for collateral. For the purpose of this implementation, we assume the
broker will allow us to have two-to-one leverage such that we can
calculate the required collateral at a given time (
The dashboard allows users to input:
- The tickers they are interested in, each separated by a comma, in the provided textbox
- The date range over which they want to test the contrarian strategy. Dates can be typed in or selected in the drop-down calendar that appears when you click on a date.
- The number of trading days per year they are interested in. This is also input in a provided textbox.
Once the "RUN CONTRARIAN STRATEGY" button is clicked, the dashboard will run its underlying code. This code outputs the following:
- Statistics that summarize the results of using the strategy with the provided tickers over the input date range
- A line plot of the strategy's daily returns
- A line plot of the strategy's annualized standard deviation of the strategy's daily returns overlaid on a bar plot of the strategy's annualized average daily returns for each year of the selected date range
- Exportable tables with the chosen stocks' daily returns, the Pearson correlations of the chosen stocks' daily returns, the daily calculated weights for each stock, required collateral, and strategy return, and the summary statistics from before by year. These tables export in csv format. The rows of the daily calculated weights for each stock, required collateral, and strategy return and the summary statistics from before by year tables are highlighted red when there is a loss that day and green when there is a gain that day.
One warning is that the yearly summary data is only computed within the date range provided. For instance, if your date range is 5/15/2019 - 12/31/2020, then the 2019 yearly data calculated by the dashboard will only include financial data from 5/15/2019 - 12/31/2019 for the year 2019 and from 1/1/2020 - 12/31/2020 for the year 2020. Same goes for using a date range of 12/31/2019-5/30/2020, where the dashboard will only include financial data from 1/1/2020-5/30/2020 for the year 2020.
Also, this code is still a work and progress and there are some issues that could make the dashboard unresponsive or unable to update user input data. Refreshing the browser typically resets the dashboard and allows you to start over when the following occurs:
- Don't put a comma at the very end of the stock ticker list. This makes the code assume you're looking for a ticker named ""
- The code doesn't check if an input ticker exists before running. Using a non-existent ticker can lead to unexpected results
- The code doesn't check if an input ticker has data for all the dates in a given date range. Using a date range where there is no date for a given ticker can lead to unexpected results
Hope this helps people explore this topic further and discover new things about it. If anything, it's a pretty fun way to spend a lunch break looking through different stock combinations and seeing how they stack up.