Skip to content

Commit 1ca7612

Browse files
authored
Add portfolio-report to Gallery (#72)
* Add `portfolio-report` to extensions * Add portfolio-report to the workflow * Change `r.requires` version * Update README and `files`, and fix copy-paste error * Rewrite manifest for portfolio-report * Update the manifest part 2 * Add `minimumConnectVersion` to manifest * Ensure the report is the `primary_rmd` * Bump R requires version and updated description
1 parent 420eea3 commit 1ca7612

File tree

7 files changed

+2849
-0
lines changed

7 files changed

+2849
-0
lines changed

.github/workflows/extensions.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ jobs:
4141
connectwidgets-example: extensions/connectwidgets-example/**
4242
plumbertableau-example: extensions/plumbertableau-example/**
4343
fastapitableau-example: extensions/fastapitableau-example/**
44+
portfolio-report: extensions/portfolio-report/**
4445
4546
# Runs for each extension that has changed from `simple-extension-changes`
4647
# Lints and packages in preparation for tests and and release.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Custom Portfolio Report
2+
3+
## About this example
4+
5+
This R Markdown document includes parameters, making it easier for stakeholders to customize the report's assumptions and create their own version. The main document serves as a standard base template, containing your core code and analysis, so you don't have to copy, paste, and republish.
6+
7+
8+
## Learn more
9+
10+
* [R Markdown Documentation](https://rmarkdown.rstudio.com/)
11+
* [Using Parameters in R Markdown](https://rmarkdown.rstudio.com/lesson-6.html)
12+
* [Gallery of example R Markdown documents](https://rmarkdown.rstudio.com/gallery.html)
13+
* [Articles on R Markdown](https://rmarkdown.rstudio.com/articles.html)
14+
15+
## Requirements
16+
17+
* R version 4.0 or higher

extensions/portfolio-report/manifest.json

Lines changed: 2601 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
title: "Portfolio Updates"
3+
output: blastula::blastula_email
4+
---
5+
6+
Hi Team,
7+
8+
Here is information on the **`r params$portfolio`** as of `r Sys.Date()`:
9+
10+
```{r}
11+
# embed a table with some of the numeric data in the email
12+
sign_formatter <- formatter("span",
13+
style = x ~ formattable::style(color = ifelse(x > 0, "green",
14+
ifelse(x < 0, "red", "black")
15+
))
16+
)
17+
18+
portfolio_selected %>%
19+
arrange(desc(date)) %>%
20+
head() %>%
21+
format_table(
22+
x = .,
23+
list(returns = sign_formatter)
24+
)
25+
```
26+
27+
28+
Let me know if you have any questions!
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
---
2+
title: "Portfolio Report"
3+
params:
4+
date:
5+
input: date
6+
label: Start Date
7+
value: '2010-01-01'
8+
mar:
9+
input: slider
10+
label: Min Acceptable Rate
11+
min: 0
12+
max: 0.1
13+
step: 0.001
14+
value: 0.008
15+
portfolio:
16+
choices:
17+
- balanced_portfolio_returns
18+
- aggressive_portfolio_returns
19+
- conservative_portfolio_returns
20+
input: select
21+
label: portfolio
22+
value: balanced_portfolio_returns
23+
portfolioName:
24+
input: text
25+
label: title
26+
value: Balanced
27+
window:
28+
input: numeric
29+
label: Rolling Window
30+
min: 6
31+
max: 36
32+
value: 12
33+
resource_files:
34+
- "returns.rds"
35+
output:
36+
flexdashboard::flex_dashboard:
37+
orientation: rows
38+
source_code: embed
39+
---
40+
41+
```{r setup, include=FALSE}
42+
knitr::opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE)
43+
44+
library(blastula)
45+
library(dplyr)
46+
library(flexdashboard)
47+
library(formattable)
48+
library(plotly)
49+
50+
library(openxlsx)
51+
library(PerformanceAnalytics)
52+
library(xts)
53+
library(zoo)
54+
55+
returns <- readRDS("returns.rds")
56+
```
57+
58+
```{r}
59+
MAR <- params$mar
60+
# run our calculations
61+
62+
portfolio_selected <- as_tibble(returns[[params$portfolio]]) %>%
63+
select(date, returns) %>%
64+
collect() %>%
65+
mutate(date = as.Date(date)) %>%
66+
filter(date >= params$date)
67+
68+
ts_prepare <- xts::xts(portfolio_selected$returns, order.by = portfolio_selected$date)
69+
70+
rolling_sortino <-
71+
ts_prepare %>%
72+
rollapply(params$window, function(x) SortinoRatio(x, MAR = MAR)) %>%
73+
`colnames<-`("24-rolling")
74+
75+
76+
sortino_byhand <-
77+
portfolio_selected %>%
78+
mutate(ratio = mean(returns - MAR) / sqrt(sum(pmin(returns - MAR, 0)^2) / nrow(.))) %>%
79+
mutate(status = ifelse(returns < MAR, "down", "up"))
80+
```
81+
82+
83+
Sortino Ratio Report for `r params$portfolioName` Portfolio
84+
=================================
85+
86+
Row
87+
-----------------------------------------------------------------------
88+
89+
### Rolling Sortino
90+
91+
```{r}
92+
plot_ly() %>%
93+
add_lines(
94+
x = index(rolling_sortino), y = as.numeric(rolling_sortino),
95+
hovertemplate = "Sortino: %{y:.2r}", name = ""
96+
) %>%
97+
layout(
98+
hovermode = "x",
99+
xaxis = list(
100+
hoverformat = '%A, %b %d, %Y',
101+
tickformat = '%b %Y',
102+
rangeslider = list(visible = TRUE),
103+
rangeselector = list(
104+
x = 0, y = 1, xanchor = 'left', yanchor = "top", font = list(size = 9),
105+
buttons = list(
106+
list(count = 1, label = 'RESET', step = 'all'),
107+
list(count = 1, label = '1 YR', step = 'year', stepmode = 'backward'),
108+
list(count = 3, label = '3 MO', step = 'month', stepmode = 'backward'),
109+
list(count = 1, label = '1 MO', step = 'month', stepmode = 'backward')
110+
)
111+
)
112+
)
113+
)
114+
```
115+
116+
117+
Row
118+
-------------------------------------
119+
120+
### Scatterplot
121+
122+
```{r}
123+
portfolio_scatter <- ggplot(sortino_byhand, aes(x = date, y = returns, color = status) )+
124+
geom_point() +
125+
geom_vline(xintercept = as.numeric(as.Date("2016-11-30")), color = "blue") +
126+
geom_hline(yintercept = MAR, color = "purple", linetype = "dotted") +
127+
scale_color_manual(values = c("tomato", "chartreuse3")) +
128+
theme(legend.position = "none") + ylab("percent monthly returns")
129+
130+
ggplotly(portfolio_scatter) %>%
131+
add_annotations(
132+
text = "Trump", x = as.numeric(as.Date("2016-11-30")),
133+
y = -.05, xshift = -10, textangle = -90, showarrow = FALSE
134+
)
135+
```
136+
137+
138+
### Histogram
139+
140+
```{r}
141+
p <- ggplot(sortino_byhand, aes(x = returns)) +
142+
geom_histogram(alpha = 0.25, binwidth = .01, fill = "cornflowerblue") +
143+
geom_vline(xintercept = MAR, color = "green")
144+
ggplotly(p) %>%
145+
add_annotations(text = "MAR", x = MAR, y = 10, xshift = 10, showarrow = FALSE, textangle = -90)
146+
```
147+
148+
### Density
149+
150+
```{r}
151+
sortino_density_plot <- ggplot(sortino_byhand, aes(x = returns)) +
152+
stat_density(geom = "line", size = 1, color = "cornflowerblue")
153+
154+
shaded_area_data <- ggplot_build(sortino_density_plot)$data[[1]] %>%
155+
filter(x < MAR)
156+
157+
sortino_density_plot <-
158+
sortino_density_plot +
159+
geom_area(data = shaded_area_data, aes(x = x, y = y), fill = "pink", alpha = 0.5) +
160+
geom_segment(
161+
data = shaded_area_data, aes(x = MAR, y = 0, xend = MAR, yend = y),
162+
color = "red", linetype = "dotted"
163+
)
164+
165+
ggplotly(sortino_density_plot) %>%
166+
add_annotations(
167+
x = MAR, y = 5, text = paste("MAR =", MAR, sep = ""), textangle = -90
168+
) %>%
169+
add_annotations(
170+
x = (MAR - .02), y = .1, text = "Downside",
171+
xshift = -20, yshift = 10, showarrow = FALSE
172+
)
173+
```
174+
175+
```{r, echo = FALSE}
176+
portfolio_file <- paste(params$portfolio, Sys.Date(), ".xlsx", sep = "")
177+
write.xlsx(portfolio_selected, file = portfolio_file)
178+
```
179+
180+
```{r, echo = FALSE}
181+
# have the report send out an email with
182+
# important results included in-line
183+
render_connect_email(input = "portfolio-report-email.Rmd") %>%
184+
attach_connect_email(
185+
subject = sprintf("%s portfolio Sortino report",params$portfolioName),
186+
attach_output = TRUE,
187+
attachments = c(portfolio_file)
188+
)
189+
```
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Version: 1.0
2+
3+
RestoreWorkspace: Default
4+
SaveWorkspace: Default
5+
AlwaysSaveHistory: Default
6+
7+
EnableCodeIndexing: Yes
8+
UseSpacesForTab: Yes
9+
NumSpacesForTab: 2
10+
Encoding: UTF-8
11+
12+
RnwWeave: Sweave
13+
LaTeX: pdfLaTeX
23.7 KB
Binary file not shown.

0 commit comments

Comments
 (0)