jofaichow commited on
Commit
68ad1d6
1 Parent(s): cd7dab8

0.1.0 first prototype

Browse files
Files changed (1) hide show
  1. app/app.R +360 -0
app/app.R ADDED
@@ -0,0 +1,360 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ library(shiny)
2
+ library(shinydashboard)
3
+ library(shinydashboardPlus)
4
+ library(shinyWidgets)
5
+ library(shinycssloaders)
6
+ library(data.table)
7
+ library(Rnumerai)
8
+ library(DT)
9
+
10
+
11
+ # ==============================================================================
12
+ # Leaderboard
13
+ # ==============================================================================
14
+
15
+ # Download latest leaderboard from Numerai and get a list of all models
16
+ d_lb <- get_leaderboard()
17
+ ls_model <- sort(d_lb$username)
18
+
19
+
20
+ # ==============================================================================
21
+ # Helper Functions
22
+ # ==============================================================================
23
+
24
+ # Download raw data
25
+ download_raw_data <- function(model_name) {
26
+
27
+ # Download data from Numerai
28
+ d_raw <- round_model_performances(model_name)
29
+
30
+ # Remove rows without CORR
31
+ d_raw <- d_raw[!is.na(d_raw$corr), ]
32
+
33
+ # Add the model name
34
+ d_raw$model <- model_name
35
+
36
+ # Return
37
+ return(d_raw)
38
+
39
+ }
40
+
41
+ # Reformat
42
+ reformat_data <- function(d_raw) {
43
+
44
+ # Keep some columns only
45
+ col_keep <- c("model", "corr", "corrPercentile", "corrWMetamodel",
46
+ "fncV3", "fncV3Percentile", "payout", "roundPayoutFactor",
47
+ "roundNumber", "roundResolved", "selectedStakeValue",
48
+ "tc", "tcPercentile")
49
+ d_munged <- as.data.table(d_raw[, col_keep])
50
+
51
+ # Reformat percentile
52
+ d_munged[, corrPercentile := round(corrPercentile * 100, 6)]
53
+ d_munged[, fncV3Percentile := round(fncV3Percentile * 100, 6)]
54
+ d_munged[, tcPercentile := round(tcPercentile * 100, 6)]
55
+
56
+ # Reorder columns
57
+ setcolorder(d_munged, c("model", "roundNumber", "roundResolved",
58
+ "selectedStakeValue",
59
+ "corr", "corrPercentile",
60
+ "fncV3", "fncV3Percentile",
61
+ "tc", "tcPercentile",
62
+ "corrWMetamodel",
63
+ "roundPayoutFactor", "payout"))
64
+
65
+ # Rename columns
66
+ colnames(d_munged) <- c("model", "round", "resolved",
67
+ "stake",
68
+ "corr", "corr_pct",
69
+ "fncv3", "fncv3_pct",
70
+ "tc", "tc_pct",
71
+ "corr_meta",
72
+ "pay_ftr", "payout")
73
+
74
+ # Return
75
+ return(d_munged)
76
+
77
+ }
78
+
79
+
80
+ # ==============================================================================
81
+ # UI
82
+ # ==============================================================================
83
+
84
+ ui <- shinydashboardPlus::dashboardPage(
85
+
86
+ title = "Shiny Numerati",
87
+
88
+ skin = "black-light",
89
+
90
+ options = list(sidebarExpandOnHover = TRUE),
91
+
92
+ header = shinydashboardPlus::dashboardHeader(
93
+ title = "✨ Shiny Numerati",
94
+ userOutput("user")
95
+ ),
96
+
97
+ sidebar = shinydashboardPlus::dashboardSidebar(
98
+ id = "sidebar",
99
+ sidebarMenu(
100
+ menuItem(text = "Start Here", tabName = "start", icon = icon("play")),
101
+ menuItem(text = "Performance", tabName = "performance", icon = icon("line-chart")),
102
+ menuItem(text = "Payout", tabName = "payout", icon = icon("credit-card")),
103
+ menuItem(text = "About", tabName = "about", icon = icon("question-circle"))
104
+ ),
105
+ minified = TRUE,
106
+ collapsed = FALSE
107
+ ),
108
+
109
+ body = dashboardBody(
110
+
111
+ tabItems(
112
+
113
+ # ========================================================================
114
+
115
+ tabItem(tabName = "start",
116
+
117
+ fluidPage(
118
+
119
+ markdown("# **Shiny Numerati**"),
120
+ markdown("### Community Dashboard for the Numerai Classic Tournament"),
121
+
122
+ br(),
123
+
124
+ fluidRow(
125
+
126
+ column(6,
127
+
128
+ markdown("## **Step 1 - Select Your Models**"),
129
+
130
+ markdown("### First, click this ⬇"),
131
+
132
+ pickerInput(inputId = "model",
133
+ label = " ",
134
+ choices = ls_model,
135
+ multiple = TRUE,
136
+ width = "100%",
137
+ options = list(
138
+ `title` = "---------->>> HERE <<<----------",
139
+ `header` = "Notes: 1) Use the search box below to find and select your models. 2) Use 'Select All' for quick selection.",
140
+ size = 20,
141
+ `actions-box` = TRUE,
142
+ `live-search` = TRUE,
143
+ `live-search-placeholder` = "For example, try lgbm_v4 or integration_test",
144
+ `virtual-scroll` = TRUE,
145
+ `multiple-separator` = ", ",
146
+ `selected-text-format`= "count > 3",
147
+ `count-selected-text` = "{0} models selected (out of {1})",
148
+ `deselect-all-text` = "Deselect All",
149
+ `select-all-text` = "Select All"
150
+ )
151
+ )
152
+ ),
153
+
154
+ column(6,
155
+
156
+ markdown("## **Step 2 - Download Data**"),
157
+
158
+ markdown("### Next, click this ⬇ (it may take a while)"),
159
+
160
+ br(),
161
+
162
+ actionBttn(inputId = "button_download",
163
+ label = "Download Data from Numerai",
164
+ color = "primary",
165
+ icon = icon("cloud-download"),
166
+ style = "gradient",
167
+ block = TRUE
168
+ )
169
+ )
170
+ ),
171
+
172
+ br(),
173
+
174
+ h3(strong(textOutput(outputId = "text_download"))),
175
+ verbatimTextOutput(outputId = "print_download"),
176
+
177
+ br(),
178
+
179
+ h3(strong(textOutput(outputId = "text_preview"))),
180
+ shinycssloaders::withSpinner(DTOutput("dt_model")),
181
+
182
+ br(),
183
+
184
+ h3(strong(textOutput(outputId = "text_next")))
185
+
186
+ )
187
+ ),
188
+
189
+ # ========================================================================
190
+
191
+ tabItem(tabName = "performance",
192
+ fluidPage(
193
+ markdown("![image](https://media.giphy.com/media/cftSzNoCTfSyAWctcl/giphy.gif)")
194
+ )
195
+ ),
196
+
197
+ tabItem(tabName = "payout",
198
+ fluidPage(
199
+ markdown("![image](https://media.giphy.com/media/cftSzNoCTfSyAWctcl/giphy.gif)")
200
+ )
201
+ ),
202
+
203
+ # ========================================================================
204
+
205
+ tabItem(tabName = "about",
206
+ markdown("## **About this App**"),
207
+ markdown('#### Yet another Numerai community dashboard by <b><a href="https://linktr.ee/jofaichow" target="_blank">Jo-fai Chow</a></b>.'),
208
+
209
+ br(),
210
+ markdown("## **Acknowledgement**"),
211
+ markdown("#### This hobby project was inspired by Rajiv's <a href='https://huggingface.co/spaces/rajistics/shiny-kmeans' target='_blank'>shiny-kmeans</a> on 🤗 Spaces."),
212
+
213
+ br(),
214
+ markdown("## **Changelog**"),
215
+ markdown(
216
+ "
217
+ - #### **0.1.0** — First prototype with an interactive table output
218
+ "),
219
+ br(),
220
+ markdown("## **Session Info**"),
221
+ verbatimTextOutput(outputId = "session_info")
222
+ )
223
+
224
+ # ========================================================================
225
+
226
+ ) # end of tabItems
227
+
228
+ ),
229
+
230
+ footer = shinydashboardPlus::dashboardFooter(
231
+ left = "Powered by ❤️, ☕, Shiny, and 🤗 Spaces",
232
+ right = paste0("Version 0.1.0"))
233
+
234
+ )
235
+
236
+
237
+
238
+ # ==============================================================================
239
+ # Server
240
+ # ==============================================================================
241
+
242
+ server <- function(input, output) {
243
+
244
+ # About Joe
245
+ output$user <- renderUser({
246
+ dashboardUser(
247
+ name = "JC",
248
+ image = "https://numerai-public-images.s3.amazonaws.com/profile_images/aijoe_v5_compressed-iJWEo1WeHkpH.jpg",
249
+ subtitle = "@matlabulous",
250
+ footer = p('"THE NMR LIFE CHOSE ME."', class = 'text-center')
251
+ )
252
+ })
253
+
254
+
255
+ # ============================================================================
256
+ # Reactive --> Download Model Data
257
+ # ============================================================================
258
+
259
+ react_download <- eventReactive(input$button_download, {sort(input$model)})
260
+
261
+ output$print_download <- renderPrint({react_download()})
262
+
263
+ output$text_download <- renderText({
264
+ if (length(react_download()) >= 1) "Your Selection:" else " "
265
+ })
266
+
267
+ output$text_preview <- renderText({
268
+ if (length(react_download()) >= 1) "Data Preview:" else " "
269
+ })
270
+
271
+ output$text_next <- renderText({
272
+ if (length(react_download()) >= 1) "⬅ [Coming Soon] Performance and Payout Charts 📈📊🔥" else " "
273
+ })
274
+
275
+ react_d_model <- eventReactive(
276
+ input$button_download,
277
+ {
278
+
279
+ # Download dataframes one by one (may parallelise this in the future)
280
+ d_raw <- c()
281
+ for (item in input$model) d_raw <- rbind(d_raw, download_raw_data(item))
282
+
283
+ # Data munging
284
+ d_munged <- reformat_data(d_raw)
285
+
286
+ # Return final result
287
+ d_munged
288
+
289
+ }
290
+ )
291
+
292
+ output$dt_model <- DT::renderDT({
293
+
294
+ DT::datatable(
295
+
296
+ # Data
297
+ react_d_model(),
298
+
299
+ # Other Options
300
+ rownames = FALSE,
301
+ extensions = "Buttons",
302
+ options =
303
+ list(
304
+ dom = 'Bflrtip', # https://datatables.net/reference/option/dom
305
+ buttons = list('csv', 'excel', 'copy', 'print'), # https://rstudio.github.io/DT/003-tabletools-buttons.html
306
+ order = list(list(0, 'asc'), list(1, 'asc')),
307
+ pageLength = 5,
308
+ lengthMenu = c(5, 10, 20, 100, 500, 1000, 50000),
309
+ columnDefs = list(list(className = 'dt-center', targets = "_all")))
310
+ ) |>
311
+
312
+ # Reformat individual columns
313
+ formatRound(columns = c("corr", "tc", "fncv3", "corr_meta", "pay_ftr"), digits = 4) |>
314
+ formatRound(columns = c("corr_pct", "tc_pct", "fncv3_pct"), digits = 1) |>
315
+ formatRound(columns = c("stake", "payout"), digits = 2) |>
316
+
317
+ formatStyle(columns = c("model"),
318
+ fontWeight = "bold") |>
319
+
320
+ formatStyle(columns = c("stake"),
321
+ fontWeight = "bold",
322
+ color = styleInterval(cuts = -1e-15, values = c("#D24141", "#2196F3"))) |>
323
+
324
+ formatStyle(columns = c("corr", "fncv3"),
325
+ color = styleInterval(cuts = -1e-15, values = c("#D24141", "black"))) |>
326
+
327
+ formatStyle(columns = c("tc"),
328
+ color = styleInterval(cuts = -1e-15, values = c("#D24141", "#A278DC"))) |>
329
+
330
+ formatStyle(columns = c("corr_pct", "tc_pct", "fncv3_pct"),
331
+ color = styleInterval(cuts = c(1, 5, 15, 85, 95, 99),
332
+ values = c("#692020", "#9A2F2F", "#D24141",
333
+ "#D1D1D1", # light grey
334
+ "#00A800", "#007000", "#003700"))) |>
335
+
336
+ formatStyle(columns = c("payout"),
337
+ fontWeight = "bold",
338
+ color = styleInterval(cuts = c(-1e-15, 1e-15),
339
+ values = c("#D24141", "#D1D1D1", "#00A800")))
340
+
341
+ })
342
+
343
+
344
+ # ============================================================================
345
+ # Session Info
346
+ # ============================================================================
347
+
348
+ output$session_info <- renderPrint({
349
+ sessionInfo()
350
+ })
351
+
352
+ }
353
+
354
+
355
+ # ==============================================================================
356
+ # App
357
+ # ==============================================================================
358
+
359
+ shinyApp(ui, server)
360
+