Professional Documents
Culture Documents
Stock Analyzer
Stock Analyzer
1 - Functions
Your second challenge is going to be developing a stock
analyzer app - a fully functional stock analysis application built
with shiny.
I. Setup
Let’s get started! You can either use the project already created in
the assignment or create your own new blank project. In RStudio
click
1. Click File
2. Click New Project
3. Select New Directory
4. Name it stock_analyzer_app.
5. Save it where you want
As you can see in the final app linked above, we will have to
implement a variety of steps to obtain a good functionality. We
can think of it as a Financial Analysis Code Workflow for our app.
It determines how the user is going to interact with the app and
what features are available.
We need to accomplish the following steps in our analysis:
1. Create a dropwdown list from that the user can select stock
indices (DAX, S&P 500, DOW, NASDAQ100).
2. Pull in the stock list from the selected stock index.
3. The user will select one stock from the selected stock index.
4. The functionality is designed to pull the past 180 days of
stock data.
5. Create an analysis button to start the analysis functions.
6. Plot the analysis itself with ggplotly (timeseries visualization).
7. We will implement two moving averages - short (fast) and
long (slow)
8. Output an automated commentary, that indicates positive or
negative trends based on the moving averages.
9. Add sliders to adjust the analysis.
10. Add a date range input field to adjust the default time
frame.
Before you start an app, you should always have an analysis that
you’ve completed. It should be functioning separately from the
web app. Let’s start with that before we implement the advanced
features into our app.
Website
stock_analysis_template.R
Tip: Break up your analysis into modular functions. This will help
big time in the Shiny Apps. In this section, we will build the
following functions:
The structure for these steps is as follows: For the most functions,
we prepared a Test code chunk that will help you to come up with
an approach to write the function in the Modularize
(function) chunk which then will be saved later. Good practice is to
also test if the function works under Example function falls.
1.1 - Stock List
We want to have a list of stocks, that the user can select from. We
need a function that retrieves all the stocks in a given index. The
following function is designed for the three major US indices and
the biggest German index containing the 30 largest German blue-
chip companies:
DAX30
SP500
DOW30
NASDAQ100
You can modify the list as you want. You can add any indices and
ETFs to the following scheme. The function is currently built for
retrieving the lists (names and symbols) from the corresponding
wikipedia pages:
# 1.0 GET STOCK LIST ----
get_stock_list <- function(stock_index = "DAX") {
# Sort
arrange(symbol) %>%
# Create the label for the dropdown list (Symbol + company name)
mutate(label = str_c(symbol, company, sep = ", ")) %>%
dplyr::select(label)
}
Example function calls
stock_list_tbl
## # A tibble: 30 x 1
## label
## <chr>
## 1 1COV.DE, Covestro
## 2 ADS.DE, Adidas
## 3 ALV.DE, Allianz
## 4 BAS.DE, BASF
## 5 BAYN.DE, Bayer
## 6 BEI.DE, Beiersdorf
## 7 BMW.DE, BMW
## 8 CON.DE, Continental
## 9 DAI.DE, Daimler
## 10 DB1.DE, Deutsche Börse
## # … with 20 more rows
Test code
user_input %>% ... %>% ...
## [1] "AAPL"
Modularize (function)
get_symbol_from_user_input <- function(user_input) {
user_input %>% ... %>% ...
}
Example function calls
"ADS.DE, Adidas" %>% get_symbol_from_user_input()
## [1] "ADS.DE"
"AAPL, Apple Inc." %>% get_symbol_from_user_input()
## [1] "AAPL"
Test code
# Convert to tibble
timetk::tk_tbl(preserve_index = T,
silent = T) %>%
# Modify tibble
set_names(c("date", "open", "high", "low", "close", "volume",
"adjusted", "currency")) %>%
drop_na() %>%
Basically, you just need to copy your code from above into
the function function.
get_stock_data <- function(stock_symbol,
from = today() - days(180),
to = today(),
mavg_short = 20, mavg_long = 50) {
}
Example function calls
stock_data_tbl <- get_stock_data("AAPL", from = "2020-06-01", to = "2021-01-
12", mavg_short = 5, mavg_long = 8)
## # A tibble: 156 x 4
## date adjusted mavg_short mavg_long
## <date> <dbl> <dbl> <dbl>
## 1 2020-06-01 80.2 NA NA
## 2 2020-06-02 80.6 NA NA
## 3 2020-06-03 81.0 NA NA
## 4 2020-06-04 80.3 NA NA
## 5 2020-06-05 82.6 80.9 NA
## 6 2020-06-08 83.1 81.5 NA
## 7 2020-06-09 85.7 82.5 NA
## 8 2020-06-10 87.9 83.9 82.7
## 9 2020-06-11 83.7 84.6 83.1
## 10 2020-06-12 84.4 84.9 83.6
## # … with 146 more rows
1.4 - Plot
Now that we are able to pull in the data, we can easily plot a time
series diagram with ggplot and ggplotly.
Test code
g <- stock_data_tbl %>%
# ggplot
ggplot(aes(..., ..., ... = ..., group = legend)) +
geom_line(aes(linetype = legend)) +
ggplotly(g)
In the interactive plot you see that the currency is displayed as
well. In order to control for different currencies - € for the German
stocks and $ for the US stocks - the y-axis needs to be formatted.
To do so we make use of the package scales. Add this function to
your script and insert the argument scale_y_continuous() to
your plot.
currency_format <- function(currency) {
if (currency == "dollar")
{ x <- scales::dollar_format(largest_with_cents = 10) }
if (currency == "euro")
{ x <- scales::dollar_format(prefix = "", suffix = " €",
big.mark = ".", decimal.mark = ",",
largest_with_cents = 10)}
return(x)
}
ggplotly(g)
}
Example function calls
"ADS.DE" %>%
get_stock_data() %>%
plot_stock_data()
Compare both moving averages on the last day. The logic goes
as this:
If short < long, this is a bad sign
If short > long, this is a good sign
if (..) {
str_glue(".. {user_input} .. {n_long} .. negative..")
} else {
str_glue(".. {user_input} .. {n_short} .. positive")
}
}
1.6 - Test
1.7 - Save
2 Layout
Now that we have all of our functions, we can start to build our
app. Let’s start with building the layout first. The layout refers to
the User Interface (Design & Structure of our App). You can
download the following template:
Website
01_stock_analyzer_layout_template.R
1. UI
2. Server
3. shinyApp()
# SERVER ----
server <- function(input, output, session) {
We could split our layout like this: 4 units on the left (input) and 8
units on the right (output). If you dragged your website, it would
adjust the content automatically. We call that a Responsive layout
(= Depending on the width of your screen, bootstrap adjusts the
columns), that helps apps look good on Mobile, Tablet & Desktop
devices.
# 2.0 APPLICATION UI -----
div(
column(width = 4, "UI"),
column(width = 8, "Plot")
)
Shiny has a lot of HTML Helpers: These are bootstrap
components that Shiny has turned into functions. We want to add
a wellPanel() and a pickerInput().
)
),
column(
width = 8,
div(
)
)
)
Let’s modify the above added pickerInput() for our use case
(the stock list dropdown selection). Check out the shinyWidgets
documentation for more information on available widgets
like pickerInput() and their options. Also run ?
pickerOptions for explanations of the arguments.
Steps:
Add two divisions for the title and for the plot
div(h4())
div(get_stock_data(), plot_stock_data())
For testing purposes you could store the data again at the top of
the script (like the index list). Now we should have the plot in
there. We cannot link our stock from the dropdown list with the
plot yet.
2.6 - Commentary
Suggested values:
width = 12
generate_commentary(user_input = “Placeholder”)
3. Server
Adding Server Functionality
stock_symbol() %>%
get_stock_data(from = today() - days(180),
to = today(),
mavg_short = 20,
mavg_long = 50)
})
Same as above.
3.6 - Index selection
Until now, we were just able to display stocks from one particular
index. In order to extend our app, we want to include other indices
as well and let the user select his preferred index using a
dropdown menu.
UI section
In the server section, the application generates the picker input for
the stocks based on the selected index. First, you have to
define stock_list_tbl which reacts to the index selection and
then extract the stock labels. Having those, you can again use the
picker input for the stocks (although this time in the server
section.)
# Create stock list ----
output$indices <- renderUI({
choices = stock_list_tbl() %>% purrr::pluck("label")
pickerInput(
...
)
})
3.7 - Moving average sliders
UI Placement:
o Add a horizontal rule between the Analyze button and
the new UI.
o Place the Sliders below the button and horizontal rule
Short MAVG Requirements: Starting value of 20, min of 5,
max of 40
Long MAVG Requirements: Starting value of 50, min of 50,
max of 120
Server requirements: Update immediately on change. We
don’t need eventReactive() but the changes in the slider
input should be directly have an impact
on stock_data_tbl().
Please provide use with the link to your application in the following
submission form!
Submission
Please share your URLs and your student information with us: