generated from jtr13/cctemplate
-
Notifications
You must be signed in to change notification settings - Fork 67
/
quantmod_and_tidyquant_tutorials_and_comparison.Rmd
732 lines (552 loc) · 33.5 KB
/
quantmod_and_tidyquant_tutorials_and_comparison.Rmd
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
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
# Quantmod & Tidyquant Tutorials and Comparison
Mildred Ouyang and Peishan Lyu
```{r, include=FALSE}
knitr::opts_chunk$set(warning = FALSE, message = FALSE)
```
```{r}
#install.packages(“quantmod”)
#install.packages("tidyverse")
#install.packages("tidyquant")
library("quantmod")
library("tidyverse")
library("tidyquant")
```
## Motivation:
All the Quantmod tutorials and documentations we have found did not provide a quick starter guide to beginners of R or people new to using Quantmod. The goal of our tutorial for Quantmod is to teach starters how to use the most essential exploratory data analysis tools and the most commonly used functions in Quantmod. We also hope that our tutorial can serve as a bridge for users to explore more advanced features of Quantmod in the future.
We feel that our tutorial does a nice job in telling the users the tasks can be completed by some cores functions in Quantmod and Tidyquant. To make improvements, we might create an additional cheatsheet to illustrate the required arguments of each function so that users can conveniently make flexible and more advanced adjustments based on their needs.
## Quantmod
### Getting Data:
The function used to load the data is : getSymbols(). This will return an object which stores the data.
If not specifying the source (src="source_name") in getSymbols(), Quantmod will use the default source which is Yahoo Finance. Some common data sources to download data from are:Yahoo, the Federal Reserve Economic Data (FRED), local database source using MySQL, csv files, and so on.(Note: Google Finance is no longer a data source. It stopped providing data in March, 2018.)
If getting data from local database using MySQL, username and password to access the database can be stored using the wrapper function: setDefaults(getSymbols.MySQL, user='____', password='____', dbname='_____'). After setting up, the user can get data using getSymbols() and change src='MySQL'.
Data range can be specified by passing in range start and end dates, but end date is optional. If no end date, the latest available data will be shown.
Example:
```{r}
getSymbols("META", src="yahoo", from="2022-01-01", to="2022-6-30")
getSymbols("TSLA;AAPL;UBER", src="yahoo", from="2022-01-01", to="2022-6-30")
```
### Data Visualization:
There are three primary chart types in Quantmod: bar chart, candle chart, and line chart.
Primary function to create charts: chartSeries() - by default, the open-high-low-close chart and the volume data will be shown.
Wrapper functions: barChart(), candleChart(), lineChart()
Modify the original chart: reChart() - can dynamically change the chart by only specifying the changing argument(s). This can be used to can the log-scale the y-axis, subset the data to show a specific time period, and set the ticks, range of y-axis, chart title, colors, and so on.
Examples:
```{r}
chartSeries(META)
```
The above shows the open-high-low-close chart and the volume data. The orange color signifies that the closing price was lower than the opening price of the same day. The green color signifies the opposite.
Users can also add stock indicators to the chart for analysis. There are 26 indicators available in Quantmod. Some commonly used stock indicators are: Bollinger Bands - addBBands(), Moving Average Convergence Divergence - addMACD(), Commodity Channel Index - addCCI(), Volume - addVo(), Williams %R - addWPR(), Simple Moving Average - addSMA(), Rate of Change - addROC(), Momentum - addMomentum(), Parabolic Stop and Reverse - addSAR(), and so on.
Example:
The below example adds the Moving Average Convergence Divergence (MACD) indicator to the original graph. The below method will output two graphs, one original and one with the MACD. Later, we will introduce a way to only output one graph. The MACD has the following arguments: fast, slow, signal, type, histogram, and col. The fast and slow address the length of fast and slow periods. The signal addresses the length of the signal period. The type indicates which type of moving average to use. The histogram takes in boolean values to either or not output a histogram. Lastly, the col is optional. It changes the color for the lines. The second graph below is drawn with the default values of MACD (fast = 12, slow = 26, signal = 9, type = "EMA", histogram = TRUE).
```{r}
chartSeries(META)
addMACD()
```
The indicator can also be passed directly as an argument into the chartSeries function. In this way, only one graph will be drawn.
Example:
The below chart shows the Bollinger Bands drawn with default argument values. The default sets the moving average period (n) to 20, the standard deviation (sd) to 2, moving average type (maType) to simple moving average (can also be changed to weighted moving avarage and so on), and also the indicator to draw (draw) to 'bands' (can also be changed to percent or width).
```{r}
chartSeries(META, TA = "addBBands(n=20, sd=2, maType = 'SMA', draw = 'bands')")
```
The below chart shows the moving average over a period of 20 days.
```{r}
chartSeries(META, TA = "addSMA(n=20)")
```
The below chart shows the moving average over a period of 40 days.
```{r}
chartSeries(META, TA = "addSMA(n=40)")
```
Multiple indicators can be passed in together and reflect on the same graph.
The below graph shows both the Bollinger Bands and the Moving Average Convergence Divergence indicator (with default argument values).
```{r}
chartSeries(META, TA = "addBBands();addMACD()")
```
The below line chart plots the opening data for the stock.
```{r}
lineChart(META)
```
The below bar chart plots the highest, lowest, opening(the right horizontal line), and closing (the left horizontal line) prices of the stock.
```{r}
barChart(META)
```
If only want to show the highest, lowest, and closing price of one day, the user can do the following:
```{r}
barChart(META, bar.type='hlc')
```
The candle chart below graphs the OHLC data.
```{r}
candleChart(META)
```
Customization of the chart's color can be done by passing the arguments multi.col and theme.
multi.col - changes the color of the bars
theme - changes the color of the background
Examples:
```{r}
chartSeries(META, multi.col = TRUE)
```
```{r}
chartSeries(META, theme = "white")
```
Moreover, Quantmod also allows only graphing a portion of the data. The subset argument can be used to select a specific range of data to graph.
Example:
The below graph only plots the first two months of data.
```{r}
chartSeries(META, multi.col = TRUE, theme = "white", subset = "2022-1::2022-2")
```
Subset can also take in value like "first 3 months" and "last 6 weeks".
```{r}
chartSeries(META, subset = "last 6 weeks")
```
Furthermore, Qauntmod allows modifications of the original graph without restating all the original arguments again.
Example:
```{r}
chartSeries(META, multi.col = TRUE)
reChart(major.ticks = "months") # change the tick mark to months
```
## Tidyquant
Tidyquant integrates quantmod, xts, zoo, TTR, and PerformanceAnalytics packages, and we can use it to generate tidier graphs than using Quantmod only. In general, we can use Tidyquant to compare stock prices, evaluate stock performance, and evaluate portfolio performance. We can easily perform financial analysis using some core tidyquant functions to get stock indexes/exchange, get quantitative data from various web-sources, transmute and mutate quantitative data, and analyze the performance of assets and portfolios.
The major functions introduced below are originally adapted from the documentation:
https://cran.r-project.org/web/packages/tidyquant/
which contains Vignettes introducing core functions and charting with Tidyquant.
We feel that the original documentation with core functions is very tidy and useful, but the authors derive different datasets using different tools, which makes it a little hard to compare similarities and differences among tools for deriving data. We attempted to use different tools to achieve data of the same four companies and included some details and new tips. This tutorial provides some basic ideas in how to get data, clean data, and chart with Tidyquant.
### Before Getting Data
Before getting quantitative data, we want to check the list of stock index we could possibly retrieve. There are eighteen available (only 5 are shown here). They measure the performance of assets from different perspectives.
```{r}
tq_index_options()
```
There are three stock exchanges (where exhange of securities happen) available.
```{r}
tq_exchange_options()
```
After browsing the specific data sources accessible from tq_get, we can get daily stock data from Yahoo Finance, economic data from FRED and Quandl, as well as financial data from Quandl, Tiingo, Alpha Vantage, and Bloomberg's Financial API (though paid account is required for Bloomberg).
* "stock.prices" - Yahoo Finance
* "economic.data" - FRED
* "quandl" and "quandl.datatable" - Nasdaq API
* "tiingo", "tiingo.iex", "tiingo.crypto" - Tiingo API
* "alphavantager", "alphavantage" - Alpha Vantage API
* "rblpapi" - Bloomberg
```{r}
tq_get_options()
```
### Getting Data
**Example for calling tq_index("INDEXNAME") function**
SP500 provides a dataset with 8 columns with a capitalization-weighted index such that companies with a higher market cap receives a higher weighting in the index.
```{r}
tq_index("SP500")
```
**Examples for calling tq_get() function**
(1). Getting data from Yahoo!Finance - set tq_get(...get = "stock.prices"...)
If we want to get stock prices of companies, Yahoo!Finance is a great choice.
Assume we want stock prices of Apple, Meta, Tesla, and Uber:
```{r}
aapl_price_yahoo <- tq_get("AAPL", get = "stock.prices", from = "2022-01-01", to = "2022-06-30")
aapl_price_yahoo
```
```{r}
meta_price_yahoo <- tq_get("META", get = "stock.prices", from = "2022-01-01", to = "2022-06-30")
meta_price_yahoo
```
```{r}
tsla_price_yahoo <- tq_get("TSLA", get = "stock.prices", from = "2022-01-01", to = "2022-06-30")
tsla_price_yahoo
```
```{r}
uber_price_yahoo <- tq_get("UBER", get = "stock.prices", from = "2022-01-01", to = "2022-06-30")
uber_price_yahoo
```
(2). Getting data from FRED Economic data - tq_get() function - set tq_get(...get = "economic.data"...)
When considering if we want to retrieve data from FRED, we consider it covers major areas of macroeconoc analysis, including some major indicators:
* Growth: GDP, real GDP, real potential GDP
* Prices and inflation: CPI for all urban consumers for all items/all items less food & energy, GDP: implicit price deflater
* Money Supply: St.Louise adjusted monetary, M1 money stock, M2 money stock, velocity of M1 money stock, velocity of M2 money stock
* Interest rates: effective federal funds rate, 3-month treasury bill, 5/10/30 year treasury constant maturity rate, 5/10 year breakeven inflation rate, 5 year forward inflation expectation rate, TED Spread, bank prime loan rate
* Employment: Civilian Unemployment Rate, Natural Long-Term/Short-Term Rate of Unemployment, Civilian Labor Force Participation Rate, Civilian Employment-Population Ratio, Unemployed, All Employees: Total nonfarm, All Employees: Manufacturing, Initial Claims, 4-Week Moving Average of Initial Claims
* Income and expenditure: Real Median Household Income in the United States, Real Disposable Personal Income, Personal Consumption Expenditures, Personal Consumption Expenditures: Durable Goods, Personal Saving Rate, Real Retail and Food Services Sales, Disposable personal income.
* Other economic indicators: Industrial Production Index, Capacity Utilization: Total Industry, Housing Starts: Total: New Privately Owned Housing Units Started, Gross Private Domestic Investment, Corporate Profits After Tax (without IVA and CCAdj), St. Louis Fed Financial Stress Index, Crude Oil Prices: West Texas Intermediate (WTI) - Cushing, Oklahoma, Leading Index for the United States, Trade Weighted U.S. Dollar Index: Major Currencies, Trade Weighted U.S. Dollar Index: Broad.
* Debt: Federal Debt: Total Public Debt, Federal Debt: Total Public Debt as Percent of Gross Domestic Product, Excess Reserves of Depository Institutions, Commercial and Industrial Loans, All Commercial Banks
(The code for these indicators can be accessed from the website:
https://data.nasdaq.com/data/FRED-federal-reserve-economic-data/documentation)
Assume we want to inspect the GDP within a given tiem window, we found only period data is available.
```{r}
gdp_fred <- tq_get("GDP", get = "economic.data", from = "2010-01-01", to = "2022-01-01")
gdp_fred
```
(3). Getting data from Nasdaq Data Link (Quandl) API - set tq_get(...get = "quandl"...)
a. quandl_search(... query = "KEY IN THE DATASET"...)
This is useful for deciding which dataset we want to use. We can get info about the newest and oldest available date as well as the frequency of data. If we want to look for all datasets with "GDP" as part of the name, we set query = "GDP".
We can also set database_code = "CODENAME" if already we know the code of the dataset. We can also set the number of returns per page.
Datasets are available here: https://data.nasdaq.com/search
```{r}
quandl_search(query = "GDP", page = 1)
```
b. tq_get(...get = "quandl"...) - get Quandl time series free data using the API key.
The code can run successfully if users uncomment the code and insert their api key into the "my_api_key" argument.
```{r}
#my_quandl_api <- quandl_api_key("my_api_key")
```
Types of free datasets in Quandl:
* Wiki Continuous Futures, which is curated by the Quandl community and built on top of raw data from ICE, CME, LIFFE, etc.
* Zillow Real Estate Data, which provides real estate and rental marketplace information.
* FRED Economic Data, including indicators for macroeconomic analysis mentioned above in section.
It provides additional info about dividends and split ratio as well as some adjusted measures than Yahoo!Finance, but data is not available for Meta and Uber, and for apple and tesla, and we can get 4 years from each call. No new data is available after 2018-03-27.
```{r}
#tq_get("WIKI/META", get = "quandl")
#tq_get("WIKI/AAPL", get = "quandl", from = "2017-01-01", to = "2020-12-31")
#tq_get("WIKI/TSLA", get = "quandl", from = "2017-01-01", to = "2020-12-31")
#tq_get("WIKI/UBER", get = "quandl")
```
c. tq_get(...get = "quandl.datatable", datatable_code = "CODENAME"...) to get some larger datasets not in time series, and note that the argument "datatable_code" is required to filled in before getting data.
(4). Getting data from Tiingo API - tq_get() - set tq_get(...get = "tiingo"/"tiingo.iex"...)
The first step is to get tiingo api key.
```{r}
#my_tiingo_api <- tiingo_api_key("my_api_key")
```
It kind of combined the benefits of Yahoo!Finance and Quandl API in the way that we have info about some adjusted measures while data is available for all four companies from the desired time window from a single call.
```{r}
#tq_get(c("AAPL", "META","TSLA","UBER"), get = "tiingo", from = "2022-01-01", to = "2022-06-30")
```
We can continue to look at data each hour within a specific day/multiple days.
```{r}
#tq_get(c("AAPL", "META","TSLA","UBER"), get = "tiingo.iex", from = "2022-11-01", to = "2022-11-01", resample_frequency = "60min")
```
(5). Getting data from Alpha Vantage - set tq_get(...get = "alphavantage"...)
Also, The first step is to get tiingo api key.
```{r}
#my_vantage_key <- av_api_key("my_api_key")
```
Like we did in former tools, we can get daily stock prices and adjusted info. The downside is it allows setting intervals only instead of the "from and to" date.
```{r}
#c("AAPL","META","TSLA", "UBER") %>%
#tq_get(get = "alphavantage", av_fun = "TIME_SERIES_DAILY_ADJUSTED", interval = "daily")
```
Like we did using Tiingo api, we can also easily inspect data for each hour by setting the interval, but also setting the start and end time is a concern.
```{r}
#c("AAPL","META","TSLA", "UBER") %>%
#tq_get(get = "alphavantage", av_fun = "TIME_SERIES_INTRADAY", interval = "60min")
```
(6). Bloomberg
Bloomberg charges, so it might not be the best choice for the beginners. If we still want to use it, there are some steps to take:
* create a Bloomberg Terminal account.
* run blpConnect()
* set tq_get(...get = "Rblpapi"...)
More details could be found in the original Tidyquant documentation.
### Data Handling
**Transmute**
We typically transmute when we want to change periodicity of data, and tq_transmute() will return a new data frame with new periodicity.
Before transmuting, we might explore compatible functions such that we could set tq_transmute(...mutate_fun = "CODEFROMPACKAGES"...). CODEFROMPACKAGES are returned from the call below.
```{r}
tq_transmute_fun_options()
```
For convenience, we only work with data retrieved for Meta from Yahoo!Finance as an example.
We transmute daily stock prices for Meta to weekly data.
```{r}
meta_price_yahoo_weekly <- meta_price_yahoo %>%
# No need to group at this point, but it allows the "META" name to show. can be deleted.
group_by(symbol) %>%
# set indexAt allow the date to be the last day of each week.
tq_transmute(select = adjusted, mutate_fun = to.weekly, indexAt = "lastof")
meta_price_yahoo_weekly
```
Tesla data is converted for regression in the next steps.
```{r}
tsla_price_yahoo_weekly <- tsla_price_yahoo %>%
# No need to group at this point, but it allows the "TSLA" name to show. can be deleted.
group_by(symbol) %>%
# set indexAt allow the date to be the last day of each week.
tq_transmute(select = adjusted, mutate_fun = to.weekly, indexAt = "lastof")
tsla_price_yahoo_weekly
```
**Mutate**
We mutate weekly return data with the original dataset to show how tq_mutate() works.
tq_mutate(mutate_fun = periodReturn, period = "weekly") gives a weekly return.
```{r}
meta_price_yahoo_weekly_returns <- meta_price_yahoo_weekly %>%
group_by(symbol) %>%
tq_mutate(mutate_fun = periodReturn, period = "weekly", type = "log")
meta_price_yahoo_weekly_returns
```
We might also want to show how to mutate info from computations across the columns in the original dataset. The original documentation takes rollapply from the zoo package as an example. Rollapply enables applying custom function across a rolling window. We may follow the documentation and use it to compute a rolling regression. We adapt the code from the original documentation and run the rolling regression on our Meta and Tesla dataset.
To prepare for showing how to mutate rolling regressions on the returns of Meta and Tesla, we mutate the weekly returns of Tesla with the original Tesla dataset from Yahoo!Finance as well.
```{r}
tsla_price_yahoo_weekly_returns <- tsla_price_yahoo_weekly %>%
group_by(symbol) %>%
tq_mutate( mutate_fun = periodReturn, period = "weekly", type = "log")
tsla_price_yahoo_weekly_returns
```
Again, to prepare for running rolling regressions, we select the weekly returns columns from each dataset and join them by date as shown below.
```{r}
meta_price_yahoo_weekly_returns_only <- meta_price_yahoo_weekly_returns %>%
select(weekly.returns, date)
tsla_price_yahoo_weekly_returns_only <- tsla_price_yahoo_weekly_returns %>%
select(weekly.returns, date)
joined_returns <- left_join(meta_price_yahoo_weekly_returns_only, tsla_price_yahoo_weekly_returns_only,
by ="date")
joined_returns
```
Here our joined_returns dataset will be passed into regr_fun as an xts object.
The timetk::tk_tbl function converts our data into the dataframe.
```{r}
regr_fun <- function(data) {
coef(lm(weekly.returns.x ~ weekly.returns.y, data = timetk::tk_tbl(data, silent = TRUE)))
}
```
Notice that we make computations within the tq_mutate() function. The new dataframe is created with the coefficients with regressions attached.
```{r}
joined_returns %>%
tq_mutate(mutate_fun = rollapply,
# 2-week window.
width = 2,
FUN = regr_fun,
# We need to specify by.column since we don't want the regression to run on each column in the dataset.
by.column = FALSE)
```
Also, mutate_fun may require two different inputs. In this case, we want to use tq_mutate_xy() instead of tq_mutate() only. For example, If we want to mutate some indicator with the original dataset calculated from two columns of data from the original dataset, we want to set mutate_fun = CODENAME of the new indicator, and input the name of the two columns of x and y. Example is shown in the original documentation.
### Charting with Tidyquant
**Line Chart**
Plotting opening price vs.time.
```{r}
meta_price_yahoo %>%
ggplot(aes(x = date, y = open)) +
geom_line() +
labs(title = "META Line Chart", y = "Opening Price", x = "") +
theme_tq()
```
```{r}
meta_price_yahoo %>%
ggplot(aes(x = date, y = volume)) +
geom_line() +
labs(title = "META Line Chart", y = "Volume", x = "") +
theme_tq()
```
Changing color of the theme, using the first plot as an example.
```{r}
meta_price_yahoo %>%
ggplot(aes(x = date, y = open)) +
geom_line() +
labs(title = "META Line Chart", y = "Opening Price", x = "") +
theme_tq_green()
```
```{r}
meta_price_yahoo %>%
ggplot(aes(x = date, y = open)) +
geom_line() +
labs(title = "META Line Chart", y = "Opening Price", x = "") +
theme_tq_dark()
```
Additionally, scale_color_tq(theme = "green"/"dark") and scale_fill_tq(theme = "green"/"dark") may be used when color and fill are specified as aes().
The change of themes applies for all other types of plots as well.
**Bar Chart**
```{r}
meta_price_yahoo %>%
# We can also set y = close, which is equivalent to setting y = close.
ggplot(aes(x = date, y = open)) +
geom_barchart(aes(open = open, high = high, low = low, close = close)) +
labs(title = "META Bar Chart", y = "Price", x = "") +
theme_tq()
```
**Candlestick Chart**
```{r}
meta_price_yahoo %>%
# We can also set y = close, which is equivalent to setting y = close.
ggplot(aes(x = date, y = open)) +
geom_candlestick(aes(open = open, high = high, low = low, close = close)) +
labs(title = "META Candlestick Chart", y = "Price", x = "") +
theme_tq()
```
We can further modify the candlestick chart by
* color, "color_up" and "color_down" modifies the color of lines, while fill_up and fill_down modifies the color of rectangle fills.
* range of graph, we may use coord_x_date(xlim = ...) to zoom into specific sections of data.
We may also set ylim = ... if zooming in causes a great change in the range of y values.
Preparing for only charting a portion of data. We set the range of x.
```{r}
start <- as_date("2022-04-30")
end <- as_date("2022-06-30")
```
Reseting the range of y if we adjust plotting the range of x.
```{r}
reset_y_range <- meta_price_yahoo %>%
# the last 60 lines of data.
tail(60) %>%
summarise(
# max value within the selected range
max_high = max(high),
# min value within the selected range
min_low = min(low)
)
reset_y_range
```
```{r}
meta_price_yahoo %>%
ggplot(aes(x = date, y = open)) +
geom_candlestick(aes(open = open, high = high, low = low, close = close), colour_up = "darkgreen", colour_down = "darkred",
fill_up = "darkgreen", fill_down = "darkred") +
labs(title = "META Candlestick Chart", subtitle = "Zoomed in Version", y = "Price", x = "") +
coord_x_date(xlim = c(start, end), ylim = c(reset_y_range$min_low, reset_y_range$max_high)) +
theme_tq()
```
**Graphing different data from different companies**
```{r}
concat1 <- rbind(meta_price_yahoo, aapl_price_yahoo)
concat2 <- rbind(tsla_price_yahoo, concat1)
concat3 <- rbind(uber_price_yahoo, concat2)
concat3
```
```{r}
concat3 %>%
ggplot(aes(x = date, y = close, group = symbol)) +
geom_candlestick(aes(open = open, high = high, low = low, close = close)) +
labs(title = "Multiple Candlestick Charts",
y = "Price", x = "") +
coord_x_date(xlim = c(start, end)) +
facet_wrap(~ symbol, ncol = 2, scale = "free_y") +
theme_tq()
```
Instead of zooming into specific sections using coord_x_date, we could run scale_x_date instead, which removes out-of-bounds data from charting. There is a trade off between distorting the scale of the y-axis (removing too little) and not getting a moving average (removing too much). We may call the filter() function to remove an appropriate number of days to find a balance. Examples are included in the original documentation.
**Visualizing Moving Averages**
Moving averages help to evaluate time-series trends, and they are applied as an added layer to a chart with geom_ma function. Different types of moving averages are available: Simple moving averages(SMA), exponential moving averages (EMA), weighted moving averages(WMA), double exponential moving averages (DEMA), zero-lag exponential moving averages (ZLEMA), volume-weighted moving averages (VWMA), and elastic volume-weighted moving averages (EVWMA).
We adapted sample code from the original documentation. We can set ma_fun argument equal to the types of moving average we want to graph and adjust the appearance by adjusting linetype, size, color, etc.
a. charting moving average (SMA) - identify the trend direction of a stock.
Graph SMA over 20/40 days:
```{r}
meta_price_yahoo %>%
ggplot(aes(x = date, y = open)) +
geom_candlestick(aes(open = open, high = high, low = low, close = close)) +
geom_ma(ma_fun = SMA, n = 20, linetype = 5, size = 1.25) +
geom_ma(ma_fun = SMA, n = 40, color = "red", size = 1.25) +
labs(title = "META Candlestick Chart",
subtitle = "20 and 40-Day SMA",
y = "Price", x = "") +
coord_x_date(xlim = c(start, end),
c(reset_y_range$min_low, reset_y_range$max_high)) +
theme_tq()
```
b. charting exponential moving average (EMA) - determine entry and exit points of a trade.
formula: closing price * multiplier + EMA of the previous day * (1-multiplier)
multiplier formula: [2/(number of days of observation+1)]
```{r}
meta_price_yahoo %>%
ggplot(aes(x = date, y = open)) +
geom_candlestick(aes(open = open, high = high, low = low, close = close)) +
geom_ma(ma_fun = EMA, n = 20, wilder = TRUE, linetype = 5, size = 1.25) +
geom_ma(ma_fun = EMA, n = 40, wilder = TRUE, color = "red", size = 1.25) +
labs(title = "META Candlestick Chart",
subtitle = "20 and 40-Day EMA",
y = "Price", x = "") +
coord_x_date(xlim = c(start, end),
c(reset_y_range$min_low, reset_y_range$max_high)) +
theme_tq()
```
c. charting weighted moving averages (WMA) - determine trend directions and help see when to buy or sell stocks
```{r}
meta_price_yahoo %>%
ggplot(aes(x = date, y = open)) +
geom_candlestick(aes(open = open, high = high, low = low, close = close)) +
geom_ma(ma_fun = WMA, n = 20, wilder = TRUE, linetype = 5, size = 1.25) +
geom_ma(ma_fun = WMA, n = 40, wilder = TRUE, color = "red", size = 1.25) +
labs(title = "META Candlestick Chart",
subtitle = "20 and 40-Day WMA",
y = "Price", x = "") +
coord_x_date(xlim = c(start, end),
c(reset_y_range$min_low, reset_y_range$max_high)) +
theme_tq()
```
d. charting double exponential moving averages (DEMA) - improved EMA, which removes the lag associated with moving averages by placing more weights on recent values
```{r}
meta_price_yahoo %>%
ggplot(aes(x = date, y = open)) +
geom_candlestick(aes(open = open, high = high, low = low, close = close)) +
geom_ma(ma_fun = DEMA, n = 20, wilder = TRUE, linetype = 5, size = 1.25) +
geom_ma(ma_fun = DEMA, n = 40, wilder = TRUE, color = "red", size = 1.25) +
labs(title = "META Candlestick Chart",
subtitle = "20 and 40-Day DEMA",
y = "Price", x = "") +
coord_x_date(xlim = c(start, end),
c(reset_y_range$min_low, reset_y_range$max_high)) +
theme_tq()
```
e. charting zero-lag exponential moving averages (ZLEMA) - improved EMA, reduce lags with removed inherent lag by removing data from lag days ago
```{r}
meta_price_yahoo %>%
ggplot(aes(x = date, y = open)) +
geom_candlestick(aes(open = open, high = high, low = low, close = close)) +
geom_ma(ma_fun = ZLEMA, n = 20, wilder = TRUE, linetype = 5, size = 1.25) +
geom_ma(ma_fun = ZLEMA, n = 40, wilder = TRUE, color = "red", size = 1.25) +
labs(title = "META Candlestick Chart",
subtitle = "20 and 40-Day ZLEMA",
y = "Price", x = "") +
coord_x_date(xlim = c(start, end),
c(reset_y_range$min_low, reset_y_range$max_high)) +
theme_tq()
```
f. charting volume-weighted moving averages (VWMA) - weighting prices based on the amount of trading activity within the time window
```{r}
meta_price_yahoo %>%
ggplot(aes(x = date, y = open, volume = volume)) +
geom_candlestick(aes(open = open, high = high, low = low, close = close)) +
geom_ma(ma_fun = VWMA, n = 20, wilder = TRUE, linetype = 5, size = 1.25) +
geom_ma(ma_fun = VWMA, n = 40, wilder = TRUE, color = "red", size = 1.25) +
labs(title = "META Candlestick Chart",
subtitle = "20 and 40-Day VWMA",
y = "Price", x = "") +
coord_x_date(xlim = c(start, end),
c(reset_y_range$min_low, reset_y_range$max_high)) +
theme_tq()
```
g. elastic volume-weighted moving averages (EVWMA) - approximate the average price paid per share. Large gaps between price and EVWMA is a signal of overbought/sold
```{r}
meta_price_yahoo %>%
ggplot(aes(x = date, y = close, volume = volume)) +
geom_candlestick(aes(open = open, high = high, low = low, close = close)) +
geom_ma(ma_fun = EVWMA, n = 20, wilder = TRUE, linetype = 5, size = 1.25) +
geom_ma(ma_fun = EVWMA, n = 40, wilder = TRUE, color = "red", size = 1.25) +
labs(title = "META Candlestick Chart",
subtitle = "20 and 40-Day EVWMA",
y = "Price", x = "") +
coord_x_date(xlim = c(start, end),
c(reset_y_range$min_low, reset_y_range$max_high)) +
theme_tq()
```
**Adding Bollinger Bands**
Bollinger bands are used to visualize volatility by plotting a range around a moving average two standard deviations up and down. Geom_bbands works almost identically to geom_ma. We can use color_ma, color_bands, alpha, and fill arguments to change the appearance of bollinger bands.
```{r}
meta_price_yahoo %>%
# high, low, and close information are required.
ggplot(aes(x = date, y = close, open = open, high = high, low = low, close = close)) +
geom_candlestick() +
# sd = 2 by default.
geom_bbands(ma_fun = SMA, sd = 2, n = 20) +
labs(title = "META Candlestick Chart",
subtitle = "BBands with SMA",
y = "Closing Price", x = "") +
coord_x_date(xlim = c(start, end),
c(reset_y_range$min_low, reset_y_range$max_high)) +
theme_tq()
```
## Quantmod vs. Tidyquant
### Quantmod:
Pros-
1. Beginner friendly, no need to have knowledge of other R libraries/packages to create graphs
2. Easy syntax
3. Contains all the essential tools and indicators for traders
Cons-
1. Not flexible (for example, cannot freely edit elements on the chart, like the caption and volume number)
2. Limited functions (for example, cannot conduct data cleaning directly and cannot create multi-facet plot)
3. Limited data source connections, currently only has 3 direct online data source connections (Yahoo Finance, FRED, oanda)
### Tidyquant:
Pros-
1. Can use tidyverse and ggplot packages, which contains functions to clean data, make tidy graphs, and implement modeling and scaling analysis
2. Contain all the quantitative analytical functions in Quantmod, xts, TTR, and PerformanceAnalytics
3. Multiple data source connections available, currently has 6 connections (Yahoo Finance, FRED, Quandl, Tiingo, Alpha Vantage, Bloomberg)
4. Flexible (since can use tidyverse and ggplot)
Cons-
1. Not beginner friendly comparing with Quantmod
2. Syntax can be complex
## Sources:
1. https://cran.r-project.org/web/packages/quantmod/quantmod.pdf
2. https://www.rdocumentation.org/packages/quantmod/versions/0.4.20
3. https://www.quantmod.com/documentation/
4. https://rdrr.io/cran/quantmod/
5. https://cran.r-project.org/web/packages/tidyquant/vignettes/
6. https://data.nasdaq.com/data/FRED-federal-reserve-economic-data/documentation
7. https://www.analyticsvidhya.com/blog/2017/09/comparative-stock-analysis/
8. https://www.business-science.io/code-tools/2017/03/19/tidyquant-quandl-integration.html