-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.R
More file actions
511 lines (442 loc) · 14.4 KB
/
app.R
File metadata and controls
511 lines (442 loc) · 14.4 KB
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
# Global items (load libraries, functions, global variables...) ####
source("Global/Global.R", local = T)$value
ui <- tagList(
# Head Tag #####
tags$head(
htmlwidgets::getDependency('sparkline'),
# to be able to use sparklines
tags$link(rel = "stylesheet", type = "text/css", href = "styles.css"),
# my styles
tags$script(src = "jscode.js"),
# My js code
tags$title("Shiny Test App")
)
,
useShinyjs()
,
# BS modal containing Data table on clicking "More Info" button ####
source("UI/DataTableModal.R", local = T)$value
,
# BS Modal containing dygraphs on clicking any ticker ui ####
source("UI/DygraphModal.R", local = T)$value
,
# BS modal containing Companies List on clicking list Icon in side bar ####
source("UI/CompaniesListModal.R", local = T)$value
,
# Sidebar ####
div(Id = "showsidebar",
icon("bars")),
source("UI/SideBar.R", local = T)$value
,
#### NavBar #####
navbarPageWithText(
id = "main_tabs",
div(
"Shiny Test App",
style = "line-height: 12px;",
span("Beta 0.01", style = "font-size:10px; font-style:italic;color: cyan;"),
tags$br(),
span("Best viewed on Chrome 1360 x 768 Resolution or higher", style = "font-size:9px; font-style:italic;")
),
position = "fixed-top" ,
collapsible = T,
selected = 5,
###__Overview Tab ####
source("UI/OverviewTab.R", local = T)$value
,
####__US Treasury yield curve rates #####
source("UI/RiskFree.R", local = T)$value
,
####__Ticker Details Tab #####
source("UI/TickerDetailsTab.R", local = T)$value
,
####__Portfolio Tab #####
source("UI/PortfolioTab.R", local = T)$value
,
source("UI/HelpTabUI.R", local = T)$value
,
alert = source("UI/NavBarAlert.R", local = T)$value
,
time = div(tags$span(icon("circle-o-notch fa-spin"), "Loading....",
style = "position: absolute;z-index: -1;margin-left: 115px;font-family: monospace;")
, uiOutput("time", style = "background-color: #f8f8f8;"),
style = "position: relative;z-index: 0;width: 255px;")
),
# to be able to use items form shiny dashboard, the body display is set as none in styles.css
dashboardPage(
body = dashboardBody(),
header = dashboardHeader(disable = T),
sidebar = dashboardSidebar(disable = T)
),
div(
id = "footer",
tags$div(
style = "margin-bottom: 0px; width: 300em;",
span(
icon("exclamation-triangle"),
"Important Warning",
icon("exclamation-triangle"),
style = "text-align: center;font-weight: 700;color: red;"
),
span(
style = "font-weight: 700;font-family: monospace;",
"This app is NOT intended to support any investment analysis or decisions and there is NO guarantee regarding the accuracy of data or calculations included in this app, the sole purpose of this app is to experiment with and test shinyApps."
)
)
)
)
server <- function(input, output, session) {
## Things to do in the begining of each session
scipenop <- getOption("scipen")
maxprint <- getOption("max.print")
options(scipen = 999999)
options(max.print = 999999)
### prep risk free/ yield curve dataset
### Update existing yield curve rates RDS with current year (bring it up to date for this session)
### OR
### do nothing and just Use existing Dataset preloaded on app start
RiskFree_dta <- if (UsePreLoadedTkrData) {
Preloaded_YieldCurveDta
} else {
fnRiskFreRateTables(x = readRDS("RDSs/YCHistory.rds"))
}
YC_melt <- RiskFree_dta$YC_melt
YC_monthly.df <- RiskFree_dta$YC_monthly.df
YC_xts <-
xts::last(RiskFree_dta$YC_xts, "100 months") # seems that 100 series is the limit for hc_motion
YCdf.mon <- RiskFree_dta$YCdf.mon
maxYCT_date <- RiskFree_dta$maxYCT_date
Max_Rf <- RiskFree_dta$Max_Rf
rm(RiskFree_dta) # clean up
###Reactive Values ####
RVs <-
reactiveValues(
# stores time and weather market is open or closed
timeNstats = format(Sys.time(), "%a, %b %d, %Y %I:%M %p %Z", tz = "EST")
,
# stores the selected tickers in the selectize input
t = vector()
,
# market indexes used, currently no UI input to change those, hard coded for now
indx = c("^GSPC", "^IXIC", "SPY", "^DJI")
,
# real time index data from getQuote
Indxdta = data.frame()
,
# real time tkr data from getQuote
tkrdta = data.frame()
,
# needed to detect top gainer
maxlim = 0.1
,
# needed to detect top loser
minlim = -0.1
,
# session gainer quote data
sessiongainer = data.frame()
,
# session loser quote data
sessionloser = data.frame()
,
# ticker symbols for gainer and loser
sessionGnrLsrNames = c()
,
# loser price history
sessiongnrloserHistory = list()
,
# gainer price history
sessionGnrLoserIntra = list()
,
# dataframe to populate bubbles visual
bblz = data.frame()
,
# used in constructing the color bar for the bubbles visual
seq = unique(c(
seq(-0.01, 0, length.out = 4), seq(0, 0.01, length.out = 4)
)) #unique(c(seq(-0.01,0, abs(-0.01)/3), seq(0, 0.01, 0.01/3)))
,
# data used in DataTable
dtable = data.frame()
,
# indexes history (10 years daily price, 52 weeks)
indxHistoryData = list()
,
# indexes intraday price for sparkline and charts
indxIntraday = list()
,
# All ticker History Data (10 years daily price, 52 weeks)
tkrHistoryData = list()
,
tkrIntraday = list()
,
# to store currently shown/selected area in the dygraph (used to adjust max/min prices markers for the shown area)
lims = as.character() # 10 years chart
,
lims2 = as.character() # intraday
,
# stores the symbol for the ticker shown in the value box visual
slctdbxsym = as.character()
,
# helper to trigger stop/resume observers when changed
resumeObs1 = 0
,
# helper to trigger stop/resume observers when changed
resumeobs2 = 0
,
# helper to trigger stop/resume observers when changed
rmnotify = 0
,
# stores the intial limit for dygraph chart
dyintitlim = NULL
,
# not used
strtdygraph = 0
,
# not used
chartrange = NULL # c(as_datetime(Sys.time(), "EST")-years(10),as_datetime(Sys.time(), "EST"))
,
# helper to trigger stop/resume observers when changed
resumeintraobs = 0
,
# helper to trigger stop/resume observers when changed
resumGnlsrNamsObs = 0
,
# helper to trigger stop/resume observers when changed
resumeintraobs3 = 0
,
# helper to trigger stop/resume observers when changed
intradone1 = 0
,
# Store ticker symbol selected in Financials and Ratios tab
fs_ratio_slctd_tkr = NA
,
fs_dataplt = NULL
,
fs_data = NULL
,
ratios_data = NULL
,
dfComp = data.frame()
,
candlestick_hc_daterange = paste(Sys.Date() - years(1), Sys.Date() , sep = "/")
,
Candlestick_qm_range = NULL
)
#### General UI Elements ######
####_ Toggle alert info on clicking alert icon ####
observeEvent(input$clkd, {
toggleElement("alertdropdown", anim = T)
})
###_ Calculate time and Market state #####
source("Server/TimeMarketState.R", local = T)$value
# Initial get indexes price history on change of selected indexes ####
# (currently only once per session - no option to change indexes)
observeEvent(RVs$indx, {
if (UsePreLoadedTkrData) {
RVs$indxHistoryData <- Preloaded_indxHistory
} else {
x <- mapply(
FUN = function(x, y) {
closeAllConnections()
tkr <- tryCatch({
tkr <- suppressWarnings(getSymbols(x, from = y, auto.assign = F))
tkr <- na.omit(tkr)
names(tkr) <-
c("Open", "High", "Low", "Close", "Volume", "AdjClose")
tkr <- round(tkr, 2)
Sys.sleep(.5)
return(list(History = tkr))
}, error = function(e)
NULL)
}
,
x = RVs$indx
,
y = Sys.Date() - years(10)
,
SIMPLIFY = F
)
RVs$indxHistoryData <- x
}
})
# Alert user to click submit when selectioned tickers change
observeEvent(input$input_tkr
,
if (!identical(RVs$t.all, toupper(input$input_tkr))) {
runjs(HTML(
"document.getElementById('btn_sbmt').style.backgroundColor = 'tomato'"
))
} else {
runjs(HTML(
"document.getElementById('btn_sbmt').style.backgroundColor = ''"
))
})
# Download ticker data on clicking "Get Data" after selecting tickers
# download takes a some time so intially all other observers are suspended to limit the mess as much as possible
observeEvent(input$btn_sbmt, {
# suspend regular quote updates
refreshObs$suspend()
# hide the alert in nav-bar for tickers with no data to prepare for the new download
runjs(
'
$( document ).ready(function() {
var a = document.getElementById("alert1");
$(a).css("visibility", "hidden");
});
'
)
source("Server/GetTickerData.R", local = T)$value
if (!identical(RVs$t.all, toupper(input$input_tkr))) {
runjs(
HTML(
"document.getElementById('btn_sbmt').style.backgroundColor = 'tomato'"
)
)
} else {
runjs(HTML(
"document.getElementById('btn_sbmt').style.backgroundColor = ''"
))
}
# to resume regular quote updates
RVs$resumeObs1 <- RVs$resumeObs1 + 1
}, priority = 50)
#### Organizing price history data in an easy to access form for use later
#### see function "fnAllTkrsAllPeriods" Global/fnFunctions/fnAllTkrsAllPeriodsDump.R
#### returns one xts for all tickers/indexes for each daily/weekly/monthly returns and closings
##### first indexes
observeEvent({
RVs$indxHistoryData
},
{
req(length(RVs$indxHistoryData) > 0, cancelOutput = T)
if (UsePreLoadedTkrData) {
RVs$rets_bm_allperiods <- Preloaded_indxRets
} else {
RVs$rets_bm_allperiods <-
fnAllTkrsAllPeriods(RVs$indxHistoryData, type = "History")
}
})
#### then tickers
observeEvent({
RVs$tkrHistoryData
},
{
req(length(RVs$tkrHistoryData) > 0, cancelOutput = T)
if (UsePreLoadedTkrData) {
RVs$rets_assts_allperiods <- Preloaded_TkrsRets
} else {
RVs$rets_assts_allperiods <-
fnAllTkrsAllPeriods(RVs$tkrHistoryData, type = "AdjHistory")
}
})
### Update Quote data ####
# Observer to restart trigger for regular quotes update (when stopped in previous process)
observeEvent({
RVs$resumeObs1
}, {
delay(10000, refreshObs$resume())
})
# Helper triggers value changing every X secs to trigger updates
trgr10 <- reactive({
invalidateLater(10000)
rnorm(1)
})
trgr60 <- reactive({
invalidateLater(60000)
rnorm(1)
})
# Process to update all quote data every X secs
refreshObs <-
observeEvent(trgr10(), {
req(input$main_tabs %in% c(1, 5)) # refresh only if "overview" tab is selected
source("Server/RefreshTickerData.R", local = T)$value
}, priority = 40)
output$tkr_stats <-
renderUI(HTML(paste0(RVs$tkrdta$Marqhtml))) #renderUI(HTML(paste0(RVs$tkrdta[with(RVs$tkrdta, order(-RVs$tkrdta$changeNum1)),]$Marqhtml)))
### Reneder Value Boxes ####
source("Server/ValueBoxes.R", local = T)$value
### Render Color bar and Bubbles Viz ####
# The bubles viz displays stock status with color of the buble representing how
# deep is the gain/loss and size representing the size of last trade.
# colors selection is in colorscaledf, 6 color buckets used (3 place for over and under -0- ).
# On download each stock is allocated to a bucket, a seq is used (n=7 from min to max change%)
# see( fnRefresh)
source("Server/BubblesViz.R", local = T)$value
### Data Table ####
# Prep data for the data table and sparklines
observeEvent(input$seeDetails, {
z <- isolate(RVs$tkrdta)
z$`52 Weeks` <-
mapply(function(x) {
paste(RVs$tkrHistoryData[[x]]$spark52wks, collapse = ",")
}, x = z$Symbol, USE.NAMES = F)
RVs$dtable <- z
toggleModal(
session = session,
modalId = "detailstable",
toggle = "open"
)
})
observeEvent(input$refreshTable, {
z <- isolate(RVs$tkrdta)
z$`52 Weeks` <-
mapply(function(x) {
paste(RVs$tkrHistoryData[[x]]$spark52wks, collapse = ",")
}, x = z$Symbol, USE.NAMES = F)
RVs$dtable <- z
})
# These vars store previous selections, searches and state of the table before data refresh
previousSelection <- NULL
tablesearch <- ""
rttablestate <- NULL
observeEvent(input$refreshTable, {
previousSelection <<- input$rttable_rows_selected
tablesearch <<- input$rttable_search
rttablestate <<- input$rttable_ordering
})
source("Server/RenderDataTable.R", local = T)$value
if (UsePreLoadedTkrData) {
source("Server/RenderCompaniesListDataTable.R", local = T)$value
}
#### Popup chart #####
#### This chart is displayed within a popup modal when boxes or bubbles are clicked
source("Server/PopupCharts.R", local = T)$value
#### Ticker Details Tab ############
source("Server/TickerDetailsTabServer.R", local = T)$value
#### Portfolio Tab ############
source("Server/PortfolionTabServer_main.R", local = T)$value
#### Risk Free Tab ############
source("Server/RiskFreeTabServer.R", local = T)$value
### Stop refreshes when modal is open or switching to a tab other than "overview" tab ####
observeEvent({
input$plot_modal_open
}
, {
refreshObs$suspend()
})
observeEvent({
input$plot_modal_close
}
, {
delay(500, refreshObs$resume())
})
observeEvent({
input$CompniesTable_modal_open
}
, {
refreshObs$suspend()
})
observeEvent({
input$CompniesTable_modal_close
}
, {
delay(500, refreshObs$resume())
})
onSessionEnded(function() {
options(scipen = scipenop)
options(max.print = maxprint)
closeAllConnections()
})
### End ####
}
shinyApp(ui = ui, server = server)