This dashboard will show the summary of author’s personal investment position (dummy data), as well as stock swing trading recommendation using MA (Moving Average) line.
Moving average (MA) is a calculation used to analyze data points by creating a series of averages of different subset of the full data set. In asset technical analysis, MA gives information about the average value of an assets over a given period of time. Exponential Moving Average (EMA) is the average calculation that place more weight to the more recent information, as opposed to the other calculation where every information across timeline hold the same weight. It is more widely used by asset traders to assist in making trading plan, as it shows at least three informations:
Price general trend
Current price point position within market cycle
Asset buy/sell point, including its support & resistance line
Moving Average (either EMA or SMA, with each of their respective nature) is a lagging indicators, thus it is not to be used a future price predictor. In this tools, this indicator will be used as a filter to help user to choose which stocks are starting a confirmed uptrend (hence give recommendation to start buying), and which are declining so that the user can sell their asset before it drops too deeply.
The wide type of investment across multiple platform is often exhaustive to monitor. This dashboard will show how are they performing at any point of the day in one single click. Especially for the stock trading activity, the dashboard will show which stocks are worth checking amongst 400 listed companies before executing the buy/sell decision.
This dashboard will be helpful for people who have multiple investments, also those with financial asset trading activities.
This dashboard will require the following data:
Time series data of daily closing, daily high and daily low price of stocks listed in IDX. Considering the tight deadline, the data used in this paper contains only LQ45 & JII70 stocks from Jan 1, 2010.
Stock historical data are acquired from yahoofinance platform (https://finance.yahoo.com) and Indonesia Stock Exchange website (www.idx.co.id)
Gold price time series data acquired from World Gold Council website (www.gold.org)
Stock portfolio (stock name, current average price, volume in hand)
Bond portfolio (bond name, buying value, expiration date, stated return, return acquired)
Time Deposit (bank name, deposit value, due date, the stated return, return acquired)
Gold portfolio (stock name, current average price, volume in hand)
More detail on this in next sections: Pre-processing and Exploratory Data Analysis
In this paper, there are 2 (two) groups of data: portfolio data and industry historical data.
Portfolio data shows the (dummy) data of current assets in hand. All 4 assets will be imported separatedly, as they have different variables each. Meanwhile the industry historical data will be used to create filter and recommendation.
#Stock
stockporto <- read.csv("data/stockporto.csv")
#Bond
bondporto<- read.csv("data/bondporto.csv")
#TD
tdporto<- read.csv("data/tdporto.csv")
#Gold
goldporto<- read.csv("data/goldporto.csv")
#> Rows: 13
#> Columns: 4
#> $ name <fct> BBTN, BBCA, ACES, MIKA, MDKA, JSMR, BBRI, ADRO, BSDE, JPF...
#> $ avg_price <int> 1290, 27982, 1489, 2280, 1518, 5530, 2980, 1011, 1187, 12...
#> $ volume <int> 2000, 1200, 1800, 1000, 2900, 1400, 3200, 700, 3500, 3000...
#> $ value <int> 2580000, 33578400, 2680200, 2280000, 4402200, 7742000, 95...
Name
: Name of stock acquired
avg_price
: Average of stock acquisition price, in IDR
volume
: Total of share in hand
value
: Total of money invested/ avg_price
x volume
, in IDR
#> Rows: 7
#> Columns: 9
#> $ name <fct> ST 005, ORI 012, SBR 004, ST 007, SBR 006, SBR 007, ORI 018
#> $ face <int> 50000000, 82000000, 45000000, 180000000, 75000000, 5750000...
#> $ price <int> 50000000, 82000000, 45000000, 180000000, 75000000, 5750000...
#> $ coupon <fct> 8.00%, 7.90%, 7.60%, 7.20%, 6.80%, 6.60%, 6.50%
#> $ acq_int <dbl> 22126713.4, 29727810.0, 14289042.1, 40056168.3, 11648403.4...
#> $ exp_date <fct> 2023-05-11, 2023-10-02, 2023-12-22, 2024-06-10, 2024-10-09...
#> $ plc_date <fct> 2018-06-06, 2018-10-28, 2019-01-17, 2019-07-07, 2019-11-05...
#> $ term <int> 1800, 1800, 1800, 1800, 1800, 1800, 1800
#> $ category <fct> government, government, government, government, government...
Name
: Name of Bond
Face
: Bond face value, the money amount the bond will be worth at maturity, in IDR
Price
: The price at which the bond were purchased, in IDR
coupon
: The stated coupon (interest/return) rate of the bond
acq_int
: Portion of interest already realized, in IDR
exp_date
: Bond maturity date
plc_date
: Bond purchasing date
term
: Bond maturity term in days
category
: Bond categories: corporate/government
#> Rows: 5
#> Columns: 7
#> $ name <fct> Bank 1, Bank 2, Bank 3, Bank 4, Bank 5
#> $ deposit <int> 10000000, 82000000, 950000000, 120000000, 10000000
#> $ interest_pa <fct> 5.00%, 4.50%, 5.50%, 4.30%, 4.70%
#> $ acq_int <dbl> 320547.9, 2032027.4, 22617808.2, 1767123.3, 27041.1
#> $ exp_date <fct> 2020-12-13, 2021-01-15, 2021-02-27, 2021-04-01, 2020-09-17
#> $ plc_date <fct> 2019-12-19, 2020-01-21, 2020-03-04, 2020-04-06, 2020-07-19
#> $ term <int> 360, 360, 360, 360, 60
Name
: Name of Bank
deposit
: The amount of deposit locked for the specified maturity term, in IDR
interest_pa
: The stated interest/return rate of the deposit
acq_int
: Portion of interest already realized, in IDR
exp_date
: Time Deposit maturity date
plc_date
: Time Deposit placement date
term
: Time Deposit maturity term in days
#> Rows: 5
#> Columns: 4
#> $ name <fct> Marketplace 1, Marketplace 2, Marketplace 3, Marketplace ...
#> $ avg_price <int> 875534, 785534, 897534, 860283, 905534
#> $ volume <int> 15, 6, 10, 7, 4
#> $ value <int> 13133010, 4713204, 8975340, 6021981, 3622136
Name
: Name of gold marketplace, where the user got them from
avg_price
: : Average of gold acquisition price, in IDR
volume
: Total of gold on hand, in gr
value
: Total of money invested/ avg_price
x volume
, in IDR
We will only need stock and gold historical data, as these two have the biggest daily volatility. Stock historical data is collected from yahoofinance and idx, and gold one from The Gold Council.
stock_data <- stock_dat %>%
mutate(Date= ymd(Date)) %>%
mutate_at(vars(Open,High,Low,Close, Volume), as.character) %>%
mutate_at(vars(Open,High,Low,Close, Volume), as.integer) %>%
mutate_at(vars(Open,High,Low,Close, Volume), as.numeric)
#dailymaintenance
ags10 <- read.csv("data/IHSG_Ags10.csv",)
ags11 <- read.csv("data/IHSG_Ags11.csv")
ags12 <- read.csv("data/IHSG_Ags12.csv")
ags13 <- read.csv("data/IHSG_Ags13.csv")
ags14 <- read.csv("data/IHSG_Ags14.csv")
ags18 <- read.csv("data/IHSG_Ags18.csv")
ags19 <- read.csv("data/IHSG_Ags19.csv")
ags24 <- read.csv("data/IHSG_Ags24.csv")
ags25 <- read.csv("data/IHSG_Ags25.csv")
stock_data <- stock_data %>% select(Name,Date,Company,Open,High,Low,Close,Volume)
stockupdate <- rbind(stock_data,ags10,ags11,ags12,ags13,ags14,ags18,ags19,ags24,ags25) %>%
mutate(Date= ymd(Date)) %>%
mutate_at(vars(Open,High,Low,Close, Volume), as.character) %>%
mutate_at(vars(Open,High,Low,Close, Volume), as.integer) %>%
mutate_at(vars(Open,High,Low,Close, Volume), as.numeric) %>%
group_by(Name) %>%
filter(n()>20) #to remove non-LQ45 & non-JII70 #to be updated when the number of daily patching exceed the set number
#> Rows: 180,958
#> Columns: 8
#> Groups: Name [81]
#> $ Name <fct> ACES, ACES, ACES, ACES, ACES, ACES, ACES, ACES, ACES, ACES,...
#> $ Date <date> 2010-01-04, 2010-01-05, 2010-01-06, 2010-01-07, 2010-01-08...
#> $ Company <fct> Ace Hardware Indonesia Tbk., Ace Hardware Indonesia Tbk., A...
#> $ Open <dbl> 148, 149, 150, 149, 149, 150, 151, 151, 149, 148, 147, 147,...
#> $ High <dbl> 151, 149, 150, 149, 149, 150, 151, 151, 151, 148, 147, 147,...
#> $ Low <dbl> 147, 147, 149, 147, 148, 148, 149, 150, 147, 146, 141, 147,...
#> $ Close <dbl> 148, 149, 150, 149, 149, 150, 151, 151, 149, 148, 147, 147,...
#> $ Volume <dbl> 1380000, 2630000, 495000, 995000, 405000, 455000, 150000, 5...
Name
: Name of stock listed
Date
: Active trading day
Company
: The full name of the company listed
4.Open
: Stock price at the beginning of Date
trading day, in IDR
High
: The highest price a stock traded within Date
trading period,in IDR
Low
: The lowest price a stock traded within Date
trading period, in IDR
Close
: Stock price at the ending of Date
trading period, in IDR
Volume
: Number of share traded within Date
trading period
#> Rows: 10,851
#> Columns: 3
#> $ Date <fct> 12/29/1978, 1/1/1979, 1/2/1979, 1/3/1979, 1/4/1979, 1/5...
#> $ spot_daily <dbl> 0.0, 0.0, 138160.5, 138877.0, 139616.3, 142069.1, 14187...
#> $ price_in_gr <dbl> 0.000, 0.000, 4441.963, 4464.999, 4488.768, 4567.628, 4...
Date
: Active trading day
Daily_price
: Gold spot price per troy oz at the Date
trading day, in IDR
price_in_gr
: Daily_price
converted to gr, in IDR
As the portfolio data is already quite tidy and small in number, we will only include them to show in the dashboard. Hence, we will only conduct simple adjustment to them.
#> 'data.frame': 13 obs. of 4 variables:
#> $ name : Factor w/ 13 levels "ACES","ADRO",..: 5 3 1 10 9 8 4 2 6 7 ...
#> $ avg_price: int 1290 27982 1489 2280 1518 5530 2980 1011 1187 1290 ...
#> $ volume : int 2000 1200 1800 1000 2900 1400 3200 700 3500 3000 ...
#> $ value : int 2580000 33578400 2680200 2280000 4402200 7742000 9536000 707700 4154500 3870000 ...
For stock portfolio dataframe, We will only change the data type of the first variable into character
, as each stocks will only be showed once
#> 'data.frame': 5 obs. of 4 variables:
#> $ name : Factor w/ 5 levels "Marketplace 1",..: 1 2 3 4 5
#> $ avg_price: int 875534 785534 897534 860283 905534
#> $ volume : int 15 6 10 7 4
#> $ value : int 13133010 4713204 8975340 6021981 3622136
For gold portfolio dataframe, We will also only change the data type of the first variable into character
, as each entry will only be showed once
#> 'data.frame': 5 obs. of 7 variables:
#> $ name : Factor w/ 5 levels "Bank 1","Bank 2",..: 1 2 3 4 5
#> $ deposit : int 10000000 82000000 950000000 120000000 10000000
#> $ interest_pa: Factor w/ 5 levels "4.30%","4.50%",..: 4 2 5 1 3
#> $ acq_int : num 320548 2032027 22617808 1767123 27041
#> $ exp_date : Factor w/ 5 levels "2020-09-17","2020-12-13",..: 2 3 4 5 1
#> $ plc_date : Factor w/ 5 levels "2019-12-19","2020-01-21",..: 1 2 3 4 5
#> $ term : int 360 360 360 360 60
For this entries, we will implement the following steps:
Change exp_date
and plc_date
from factor data type to date
Remove the ‘%’ symbol in interest_pa
and later change it into numeric data type.
#> 'data.frame': 7 obs. of 9 variables:
#> $ name : Factor w/ 7 levels "ORI 012","ORI 018",..: 6 1 3 7 4 5 2
#> $ face : int 50000000 82000000 45000000 180000000 75000000 57500000 82500000
#> $ price : int 50000000 82000000 45000000 180000000 75000000 57500000 82500000
#> $ coupon : Factor w/ 7 levels "6.50%","6.60%",..: 7 6 5 4 3 2 1
#> $ acq_int : num 22126713 29727810 14289042 40056168 11648403 ...
#> $ exp_date: Factor w/ 7 levels "2023-05-11","2023-10-02",..: 1 2 3 4 5 6 7
#> $ plc_date: Factor w/ 7 levels "2018-06-06","2018-10-28",..: 1 2 3 4 5 6 7
#> $ term : int 1800 1800 1800 1800 1800 1800 1800
#> $ category: Factor w/ 1 level "government": 1 1 1 1 1 1 1
For this portfolio entries, we will implement the following steps:
Change name
into character data type, as each stocks will only be showed once
Change exp_date
and plc_date
from factor data type to date
Remove the ‘%’ symbol in coupon
and later change it into numeric data type
#> 'data.frame': 10851 obs. of 3 variables:
#> $ Date : Factor w/ 10851 levels "1/1/1979","1/1/1980",..: 3336 1 331 662 753 783 871 902 32 62 ...
#> $ spot_daily : num 0 0 138161 138877 139616 ...
#> $ price_in_gr: num 0 0 4442 4465 4489 ...
For this dataframe entries, we will change the Date
variable into proper format of date and remove the spot_daily as this column isn’t necessary. After that, we will remove the first two rows as it have no value.
implement the following steps:
#> Rows: 180,958
#> Columns: 8
#> Groups: Name [81]
#> $ Name <fct> ACES, ACES, ACES, ACES, ACES, ACES, ACES, ACES, ACES, ACES,...
#> $ Date <date> 2010-01-04, 2010-01-05, 2010-01-06, 2010-01-07, 2010-01-08...
#> $ Company <fct> Ace Hardware Indonesia Tbk., Ace Hardware Indonesia Tbk., A...
#> $ Open <dbl> 148, 149, 150, 149, 149, 150, 151, 151, 149, 148, 147, 147,...
#> $ High <dbl> 151, 149, 150, 149, 149, 150, 151, 151, 151, 148, 147, 147,...
#> $ Low <dbl> 147, 147, 149, 147, 148, 148, 149, 150, 147, 146, 141, 147,...
#> $ Close <dbl> 148, 149, 150, 149, 149, 150, 151, 151, 149, 148, 147, 147,...
#> $ Volume <dbl> 1380000, 2630000, 495000, 995000, 405000, 455000, 150000, 5...
No need any further adjustment as the format is pretty much correct
This section contains quick summary of each portfolio
#> name avg_price volume value
#> Length:13 Min. : 287 Min. : 700 Min. : 707700
#> Class :character 1st Qu.: 1187 1st Qu.:1400 1st Qu.: 2280000
#> Mode :character Median : 1489 Median :2500 Median : 3870000
#> Mean : 3791 Mean :2323 Mean : 6121808
#> 3rd Qu.: 2280 3rd Qu.:3000 3rd Qu.: 4782000
#> Max. :27982 Max. :4000 Max. :33578400
User have 13 stock code under her tab, with acquisition price ranging from IDR287 to IDR27.982 each. Total money invested for all stocks in hand is amounted to IDR 79.583.500
#> name face price coupon
#> Length:7 Min. : 45000000 Min. : 45000000 Min. :6.500
#> Class :character 1st Qu.: 53750000 1st Qu.: 53750000 1st Qu.:6.700
#> Mode :character Median : 75000000 Median : 75000000 Median :7.200
#> Mean : 81714286 Mean : 81714286 Mean :7.229
#> 3rd Qu.: 82250000 3rd Qu.: 82250000 3rd Qu.:7.750
#> Max. :180000000 Max. :180000000 Max. :8.000
#> acq_int exp_date plc_date term
#> Min. : 713244 Min. :2023-05-11 Min. :2018-06-06 Min. :1800
#> 1st Qu.: 8804006 1st Qu.:2023-11-11 1st Qu.:2018-12-07 1st Qu.:1800
#> Median :14289042 Median :2024-06-10 Median :2019-07-07 Median :1800
#> Mean :17788713 Mean :2024-05-26 Mean :2019-06-22 Mean :1800
#> 3rd Qu.:25927262 3rd Qu.:2024-11-24 3rd Qu.:2019-12-21 3rd Qu.:1800
#> Max. :40056168 Max. :2025-06-30 Max. :2020-07-26 Max. :1800
#> category
#> government:7
#>
#>
#>
#>
#>
User have invested in 7 bond series under her tab, with value ranging from IDR45 mio to IDR180 mio each. Total money invested in bonds is amounted to IDR 572 mio, with expected interest ranging from 6.5% to 8% pa.
#> name deposit interest_pa acq_int
#> Bank 1:1 Min. : 10000000 Min. :4.3 Min. : 27041
#> Bank 2:1 1st Qu.: 10000000 1st Qu.:4.5 1st Qu.: 320548
#> Bank 3:1 Median : 82000000 Median :4.7 Median : 1767123
#> Bank 4:1 Mean :234400000 Mean :4.8 Mean : 5352910
#> Bank 5:1 3rd Qu.:120000000 3rd Qu.:5.0 3rd Qu.: 2032027
#> Max. :950000000 Max. :5.5 Max. :22617808
#> exp_date plc_date term
#> Min. :2020-09-17 Min. :2019-12-19 Min. : 60
#> 1st Qu.:2020-12-13 1st Qu.:2020-01-21 1st Qu.:360
#> Median :2021-01-15 Median :2020-03-04 Median :360
#> Mean :2021-01-08 Mean :2020-03-14 Mean :300
#> 3rd Qu.:2021-02-27 3rd Qu.:2020-04-06 3rd Qu.:360
#> Max. :2021-04-01 Max. :2020-07-19 Max. :360
User have invested in 5 time deposits under her tab, with value ranging from IDR10 mio to IDR950 mio. Total money invested in bonds is amounted to IDR 1.172 mio, with expected interest ranging from 4.3% to 5.5% pa.
#> name avg_price volume value
#> Length:5 Min. :785534 Min. : 4.0 Min. : 3622136
#> Class :character 1st Qu.:860283 1st Qu.: 6.0 1st Qu.: 4713204
#> Mode :character Median :875534 Median : 7.0 Median : 6021981
#> Mean :864884 Mean : 8.4 Mean : 7293134
#> 3rd Qu.:897534 3rd Qu.:10.0 3rd Qu.: 8975340
#> Max. :905534 Max. :15.0 Max. :13133010
User have bought gold from 5 marketplaces, with average acquisition value ranging from IDR785.534 to IDR 905.534 per gr. Total money invested in gold is amounted to IDR 36,4 mio.
#>
#> FALSE TRUE
#> 1434369 13295
stockupdate
dataframe does have 13.295 amount of NAs out of 180.958 rows. Those NAs came from the rows added by yahoofinance to announce dividend payment time. As this information is irrelevant to the data purpose, we remove those rows from analysis.
We would first analyze how each stocks are doing.
#group stock by name and return the statistics (max, min, Last Close)
stocksumm <- stockupdate %>%
select(Name, Date, Company, Open, High, Low, Close, Volume) %>%
group_by(Name) %>%
summarise(Last_Close=last(Close),
Max_Price=max(High, na.rm = T),
Min_Price=min(Low, na.rm = T),
Avg_Volume=median(Volume, na.rm = T))
Quick visualization of some sample stocks
#chart
aces_plot <- stockupdate[stockupdate$Name=='ACES',]
aces_plot %>% ggplot(aes(x=Date,y=Close))+
geom_line()+
labs(title = 'Closing Price:ACE Hardware Indonesia', x='Date', y='Price (in IDR)')+
theme_minimal()
ACES had a quite stable price increase over time with four notable price decline around 2014, 2016, and early 2020.
#chart
bbca_plot <- stockupdate[stockupdate$Name=='BBCA',]
bbca_plot %>% ggplot(aes(x=Date,y=Close))+
geom_line()+
labs(title = 'Closing Price:Bank Central Asia, Tbk.', x='Date', y='Price (in IDR)')+
theme_minimal()
BBCA had a quite stable price increase over time with barely significant drops in price. However, it faces sudden drop in early 2020, even though it’s currently crawling back to it’s last high.
#chart
apln_plot <- stockupdate[stockupdate$Name=='APLN',]
apln_plot %>% ggplot(aes(x=Date,y=Close))+
geom_line()+
labs(title = 'Closing Price:Agung Podomoro Land', x='Date', y='Price (in IDR)')+
theme_minimal()
From the issuance date, APLN shows quite a consistent decline in price. The last top happened around 2019, which was already half the price of its all-time high back in 2013.
#> Min. 1st Qu. Median Mean 3rd Qu. Max.
#> 4344 22367 79101 183205 344009 922326
#>
#> FALSE
#> 21698
There are no NA in gold historical data.
#chart
goldpricechart <- golddata %>% ggplot(aes(x=Date,y=price_in_gr))+
geom_line()+
labs(title = 'Gold Price in IDR', x='Date', y='Price (in IDR)')+
theme_minimal()
goldpricechart
Gold shows quite consistent increase over time, where it’s currently still reaching all-time high (trading against IDR)
Setting EMA: EMA 2, EMA 9, EMA 30, EMA 200
If the latest closing price cross up/ higher than EMA 30 line (number), uptrend alert
If the latest closing price cross down/ lower than EMA 30 line (number), downtrend alert