統計學(二) 筆記 - 期末專案 國內股票型基金分析

筆記說明

我們根據台灣銀行可申購的基金,針對國內股票開放型中小型基金、國內股票開放型科技型基金、國內股票開放型一般股票型基金做探討。

國內股票開放型中小型基金、國內股票開放型科技型基金、國內股票開放型一般股票型基金,以下簡稱為三類基金
我們主要想探討的是,在這三種類型的所有基金中,透過統計的方式找出哪些基金值得被購買,適合消費者購買。

過程中我們使用 R 語言 進行分析。
我們這組的期末 ppt 報告

此文章記錄用途只在於台北科技大學資訊與財金管理系大二下期末專案
並非所有人都適用,部分對我而言稍加容易的內容並不會寫在此內。

章節

  • 蒐集資料,透過 yahoo 基金網頁下載歷史資料。
  • 根據國內股票開放型中小型基金、國內股票開放型科技型基金、國內股票開放型一般股票型基金,分別選出最好的基金。
    • 其中國內股票開放型一般股票型基金最好的基金定義為 normal_fund
    • 其中國內股票開放型中小型基金最好的基金定義為 small_fund
    • 其中國內股票開放型科技型基金最好的基金定義為 tech_fund
  • 再來我們針對 normal_fund、small_fund、tech_fund 比較看看這些基金是否有差異。
  • 再來為這 normal_fund、small_fund、tech_fund 基金做迴歸分析,X 變數是 normal_fund、small_fund、tech_fund 的前十大股票,使用迴歸分析來看基金的前十大標的是否對這基金影響力很強。
  • 再來做最適資產配置,推薦投資者應該將投資如何比例至這些基金中
  • 資料來源
  • 心得

如果想跳到這些章節,請點選右邊的章節列描點過去。

以下的統計分析的 alpha 都是 0.05。

資料取得

  • 我們資料使用 yahoo 基金 從 2017~2020 的資料作統計分析。
  • 之後透過 R 語言處理資料。
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
#### file name
#merge.data.R
####
library(magrittr)
library(quantmod)
library(agricolae)
library(tibble)
setwd("D:\\NTUT\\大二下\\統計\\報告")

data_merge <- function(folder_name){
#"一般股票型"
path <- file.path(getwd(), "基金CSV", folder_name)
files <- dir(path)
data <- tibble(YM = character(), name = character(), return = numeric(),
sharpe = numeric(), sd = numeric())

for (fname in files){

path <- file.path(getwd(), "基金CSV", folder_name, fname)
fund <- read.csv(path)
fname <- gsub(".csv", "", fname)
fund$date <- fund$日期 %>% as.Date() %>% as.character() #將日期與 yahoo 股價一致
fund$漲跌幅 <- gsub("%", "", fund$漲跌幅) %>% as.numeric() #子串轉數字
fund <- fund[-grep("2021", fund$date) ,] #消除 2021 的資料
fund <- fund[-grep("2016", fund$date) ,] #消除 2016 的資料
if(nrow(fund) <= 0) next

fund$YM <- substr(fund$date, 1, 4)#year with month 取出年份與月份
YMs <- unique(fund$YM)

#將基金的每日資料合併成每年的資料
for(ym in YMs){
sub_fund <- fund[fund$YM == ym, ]
return <- (tail(sub_fund$淨值,1) - head(sub_fund$淨值,1)) / head(sub_fund$淨值,1) #計算報酬率
data <- data %>% add_row(YM = ym, name = fname,
return = return,
sharpe = (mean(sub_fund$漲跌幅) - 0.0000232) / sd(sub_fund$漲跌幅) * (sqrt(252)), # sharpe ratio
sd = sd(sub_fund$漲跌幅)) # 標準差
#sharpe ratio 的無風險利率使用台灣銀行一天的利息做標準 0.0000232
}
}
return(data)
}

蒐集資料,透過 yahoo 基金網頁下載歷史資料。

選擇 yahoo 某一檔基金,這裡用安聯台灣科技基金為例,點擊 歷史淨值 > 往下看,會看到一個下載歷史報價,選擇自己想要的期間去下載。

根據國內股票開放型中小型基金、國內股票開放型科技型基金、國內股票開放型一般股票型基金,分別選出最好的基金。

  • 將資料轉化成以每年為單位的基金資料
  • 再來我們做 ANOVA 分析,看看這些基金的 報酬率、sharpe ratio 是否都一樣
  • 如果 ANOVA 分析這些基金的 報酬率、sharpe ratio 不一樣,則做 LSD 找出最前段班的組別。
    我們會先做報酬率,並取出 LSD 最好的一組,再去做 sharpe ratio 分析
  • 下結論
  • 從最好的基金們中找出最好的基金。
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
#### file name
#fund.R
####
library(magrittr)
library(quantmod)
library(agricolae)
library(stats)
setwd("D:\\NTUT\\大二下\\統計\\報告")

source("./merge_data.R", encoding = "UTF-8")
source("./loading_data.R", encoding = "UTF-8")

fund_type <- c("一般股票型", "中小型", "科技型")
#data_return <- function(folder_name)
data <- data_merge("一般股票型")
#write.csv(data, "一般股票型.csv")
write.csv(data, "./ppt材料/一般股票型統計.csv")

#報酬率
fit <- aov(formula = return ~ name, data = data) # anova 分析
anova_table <- anova(fit)
lsd <- LSD.test(fit, "name", p.adj ="none", alpha = 0.05) #判斷 LSD 分析
lsd$groups$name <- lsd$groups %>% row.names()
row.names(lsd$groups) <- NULL #將 rownames 轉為 index
View(lsd$groups)
good_funds <- lsd$groups$name[grep("a", lsd$groups$groups)]
data <- data[data$name %in% good_funds, ]

#sharpe
fit <- aov(formula = sharpe ~ name, data = data) #anova 分析
anova_table <- anova(fit)
lsd <- LSD.test(fit, "name", p.adj ="none", alpha = 0.05) #判斷 LSD 分析
lsd$groups$name <- lsd$groups %>% row.names()
row.names(lsd$groups) <- NULL #將 rownames 轉為 index
View(lsd$groups)
good_funds <- lsd$groups$name[grep("a", lsd$groups$groups)]
data <- data[data$name %in% good_funds, ]

結果與結論

  • 一般股票型

    • return
      • ANOVA,一般股票型基金的報酬差沒有明顯差異

      • LSD

    • sharpe ratio
      • ANOVA,一般股票型基金的 sharpe ratio 沒有明顯差異

      • LSD

  • 中小型

    • return
      • ANOVA,中小型基金的報酬差沒有明顯差異

      • LSD

    • sharpe ratio
      • ANOVA,中小型基金的 sharpe ratio 沒有明顯差異

      • LSD

  • 科技型

    • return
      • ANOVA,科技型的報酬差沒有明顯差異

      • LSD

    • sharpe ratio
      • ANOVA,科技型基金的 sharpe ratio 沒有明顯差異

      • LSD

  • 結論

    • 蠻意外的,沒想到在 2017~2020 中每個類型中的所有基金的 return、sharpe ratio 全部都一樣。ummm…所以這樣應該也就表示其實所有的基金管理人都差不多優秀,沒有明顯被坑的情況。

    • 因此我們就選出三類基金中的 return、sharpe ratio LSD 綜合排名第一名,來當作我們這三類基金的 normal_fund、small_fund、tech_fund

      • 其中國內股票開放型一般股票型基金最好的基金安聯台灣智慧基金定義為 normal_fund
      • 其中國內股票開放型中小型基金最好的基金復華中小精選基金定義為 small_fund
      • 其中國內股票開放型科技型基金最好的基金安聯台灣科技基金定義為 tech_fund
    • normal_fund、small_fund、tech_fund 的報酬率、sharpe ratio 折線圖

      • return

      • sharpe ratio 折線圖

再來我們針對 normal_fund、small_fund、tech_fund 比較看看這些基金是否有差異。

  • 結論:normal_fund、small_fund、tech_fund 這三個基金的變異數都相等。
  • 下面有六張圖,請根據圖片中的 data: xxx_fund and aaa_fund,來得知是哪兩個基金比較。
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
#### file name
#var.R
####
library(magrittr)
library(quantmod)
library(agricolae)
library(stats)
setwd("D:\\NTUT\\大二下\\統計\\報告")

source("./merge_data.R", encoding = "UTF-8")

#在使用此函式前,必須先使用 *_fund.R 先判斷哪些基金最好

fund_type <- c("一般股票型", "中小型", "科技型")
#data_return <- function(folder_name)
normal_fund <- data_merge("一般股票型")
small_fund <- data_merge("中小型")
tech_fund <- data_merge("科技型")

write.csv(normal_fund[normal_fund$name == "安聯台灣智慧基金",], "./ppt材料/安聯台灣智慧基金統計.csv")
write.csv(small_fund[small_fund$name == "復華中小精選基金",], "./ppt材料/復華中小精選基金統計.csv")
write.csv(tech_fund[tech_fund$name == "安聯台灣科技基金",], "./ppt材料/安聯台灣科技基金統計.csv")
normal_fund <- normal_fund$return[normal_fund$name == "安聯台灣智慧基金"]
small_fund <- small_fund$return[small_fund$name == "復華中小精選基金"]
tech_fund <- tech_fund$return[tech_fund$name == "安聯台灣科技基金"]


var(normal_fund)
var(small_fund)
var(tech_fund)
#Reject
var.test(normal_fund,
small_fund,
alternative = "two.sided") #less 表示 A 股票比 B 股票標準差更大

再來為這 normal_fund、small_fund、tech_fund 基金做迴歸分析,X 變數是 normal_fund、small_fund、tech_fund 的前十大股票,使用迴歸分析來看基金的前十大標的是否對這基金影響力很強。

  • 以下的 x 變數是前十大股票當天漲跌幅
  • y 都是基金當天漲跌幅

normal_fund 基金回歸

  • 共線性測試,並沒有明顯共線性問題

  • 回歸模型,\(adj_R^2 = 0.7381\)

  • 所有 x 係數

  • 所有 x 的 t test,每一個都與 y 有關聯

  • 殘差分析、常態機率等圖

  • 結論
    如果我們買前十大基金並搭配 x 係數的資金分配,那我們就可以達到基金大約 73% 的功效,也就是說我們如果單純只買這幾支股票,那麼我們理論上會跟這基金有百分之 73% 漲幅相同,也許投資人可以嘗試看看自己買股票,就可以減少基金投資人手續費。

small_fund 基金回歸

  • 共線性測試,並沒有明顯共線性問題

  • 回歸模型,\(adj_R^2 = 0.6952\)

  • 所有 x 係數

  • 所有 x 的 t test,每一個都與 y 有關聯

  • 殘差分析、常態機率等圖

  • 結論
    如果我們買前十大基金並搭配 x 係數的資金分配,那我們就可以達到基金大約 70% 的功效,也就是說我們如果單純只買這幾支股票,那麼我們理論上會跟這基金有百分之 70% 漲幅相同,也許投資人可以嘗試看看自己買股票,就可以減少基金投資人手續費。

tech_fund 基金回歸

  • 共線性測試,2327 與 2492 有明顯貢獻性關係,2492 在這檔基金的權重較高,因此我們刪除 2327

  • 回歸模型,\(adj_R^2 = 0.8399\)

  • 所有 x 係數

  • 所有 x 的 t test,每一個都與 y 有關聯

  • 殘差分析、常態機率等圖

  • 結論
    如果我們買前十大基金並搭配 x 係數的資金分配,那我們就可以達到基金大約 84% 的功效,也就是說我們如果單純只買這幾支股票,那麼我們理論上會跟這基金有百分之 84% 漲幅相同,也許投資人可以嘗試看看自己買股票,就可以減少基金投資人手續費。

程式碼

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
#### file name
# lm.R
####
library(magrittr)
library(quantmod)
library(agricolae)
library(tibble)
library(ggfortify)
source("./merge_data.R", encoding = "UTF-8")

setwd("D:\\NTUT\\大二下\\統計\\報告")

fund_type <- c("一般股票型", "中小型", "科技型")
#data_return <- function(folder_name)

path <- file.path(getwd(), "基金CSV", "科技型", "安聯台灣科技基金.csv")

fund <- read.csv(path)
fund$date <- fund$日期 %>% as.Date() %>% as.character()

fund$return <- gsub("%", "", fund$漲跌幅) %>% as.numeric()
fund$return <- fund$return * 0.01
date <- fund$date

#基金的前十大股票
codes <- c("2330.TW", "3529.TWO", "2492.TW", "2327.TW", "2337.TW", "8016.TW", "6510.TWO",
"6732.TWO", "4966.TWO", "3035.TW")
for (code in codes){ #找出所有股票的共同日期
stock <- getSymbols(code, auto.assign = FALSE , from = "2016-01-01" ) %>% na.omit() %>% data.frame()
names(stock) <- c("open", "high", "low", "close", "vol", "adjPrice")
stock$date <- rownames(stock) %>% as.Date() %>% as.character()
rownames(stock) <- NULL
date <- intersect(date, stock$date)
}

data <- tibble(date = date, return = fund$return[fund$date %in% date])
for(code in codes){ #找出所有股票的共同日期的報酬率
stock <- getSymbols(code, auto.assign = FALSE , from = "2016-01-01" ) %>% na.omit() %>% data.frame()
names(stock) <- c("open", "high", "low", "close", "vol", "adjPrice")
stock$date <- rownames(stock) %>% as.Date() %>% as.character()
stock$last_close <- c(Inf, head(stock$close, length(stock$close)-1))
stock$return <- (stock$close - stock$last_close) / stock$last_close
rownames(stock) <- NULL
data[ , code] <- stock$return[stock$date %in% date]
}


#共線性測試,
cor.test <- cor(data[3:ncol(data)])
cor.test

#將共線性過高的刪除
data["2327.TW"] <- NULL
write.csv(data, "科技股回歸資料.csv")

#迴歸分析
model <- lm(formula = return ~ ., data = data[, 2:ncol(data)])
View(model)
sum_model <- summary(model)
View(sum_model)

#殘差圖、標準常態圖
autoplot(model)

再來做最適資產配置,推薦投資者應該將投資如何比例至這些基金中

  • 我們有請教王甡老師 如果要做三檔基金時要怎麼樣計算,老師給了我們一份 word 資料,提供我們學習。
    我將檔案連結放在這邊,由於是老師的檔案我沒有權力共享,因此只有設定我的帳號才可以查看、瀏覽,提供我學習XD
  • 再來我們借助 excel 的矩陣運算與最佳求解,找出三種資產的最適資產配置比例
    • 利用前面假設檢定挑選出的各基金類別中最好的基金進行最適資產配置
    • 計算年化報酬率、共變異數矩陣
    • 最適風險性資產投資組合的權重是投資組合變異數最小的權重
    • 最小變異數的投資組合為標準差4.79%,預期報酬率31.2%
  • 結論資產配置
    • 權重為安聯台灣智慧基金111.00%
    • 復華中小精選基金-18.71%
    • 安聯台灣科技基金7.71%
  • 表示若要選擇風險最小的投資組合必須將投資在復華中小精選基金的資金,投資到另外兩檔基金,需要借貸資金才能達到風險最小的投資組合
  • 圖表

非常有趣的資產配置方法

  • 由於我們知道資產配置不可以有負值,如果有,表示這三種並不適合一起拿來做資產配置,或負比例基金移除。
  • 但我們這邊做一個啟發。
  • 公式推導
    • A:安聯台灣智慧基金 B:復華中小精選基金C:安聯台灣科技基金
    • A+B+C = 100,其中因為 B 是負,導致投資人沒辦法正確資產配置,因此我們將 B 改為 0。
    • \(A+B+C=100\) ,\(A+C=100+B\) ,其中 \(B = -18.71\)
    • \(A+C = 100 + B = 118.71\) ,\(A+C=118.71\)
    • \(111+7.71 = 118.71\),\(A+C=100\) ,\(同除 1.1871\)
    • \(C=6.4948%\) ,\(A=93.505%\)
  • 因此我們推薦投資人買安聯台灣智慧基金 93.505% ,安聯台灣科技基金 = 6.4948%
  • 這個完全沒有任何論文根據,純粹個人推導,如果並不是這樣我不負責喔XD。不過可以跟我說我錯在哪裡。

資料來源

row.names: Get and Set Row Names for Data Frames by rdrr.io
Chapter 6 基本函式 by bookdown
[R] subsetting a data frame using string matching by stat.ethz
Select column 2 to last column in R by stackoverflow
Using R’s lm on a dataframe with a list of predictors by stackoverflow
Remove an entire column from a data.frame in R by stackoverflow
33.2 线性回归模型 by bookdown
lm: Fitting Linear Models by rdocu
Correlations by Quick-R
F-Test: Compare Two Variances in R by STHDA
[R] Extract R-squared from summary of lm by stat.ethz
R语言(3)-四张图检验线性回归模型 by 知乎
R教學 變異數分析R指令與範例 by 羅琪老師.
Selecting columns in R data frame based on those not in a vector by stackoverflow

心得

好累阿,不過先謝謝我們的組員們,畢竟我們一起努力生出這份專案 吳淑萍、彭元俊、王奕淇,也要謝謝丁秀儀老師,其實我一直很想用統計做一個投資的專案,終於讓我做出來了www。
也要謝謝王甡老師,有他在後面督促我們,引導方向,我們才可以順利產出,並且有符合實務。

其實一路上再用 R 寫統計專案真的是很累QQ,不過這已經比其他的程式語言都還好用,只是自己摸不熟拉,剛好透過這次的專案摸熟。
其實 R 真的很有用,建議大家有機會的話可以學學他。

謝謝吳淑萍幫我們做 PPT,還有跟我開那麼多會,一直跟我溝通,辛苦了XD。
謝謝彭元俊幫我們做資產配置,使用 excel 做資產配置最適規劃。
謝謝王奕淇幫我們蒐集資料。

總之我覺得我們這組做的很棒,也很不賴!有各位才順利。

不過老實講,我自己在弄統計的時候,其實寫程式寫久都會有一種負能量產生,因為寫程式寫太久一直再找 bug 常常腦中就會有RRRRR,怎麼只有我一個人再找 bug,不行,工作質量分配不均!我要上訴,之類的奇怪想法在我腦海裏面wwww,可是其實我就會想一下,我除了寫程式以外其他都沒有比較擅長的,我也只有這個會做,有了這個反擊後,我就又會乖乖的寫程式。
直到下一次 bug 找不到為止www。

不過也要很感謝 R 開放套件的人,如果沒有他們,我就會更難寫程式了!

附上一張詢問王甡老師的照片

  • 版權聲明: 本部落格所有文章除有特別聲明外,均採用 Apache License 2.0 許可協議。轉載請註明出處!
  • © 2020-2021 John Doe
  • Powered by Hexo Theme Ayer
  • PV: UV: