在本章中,我们将介绍:
- 获取股市数据
- 汇总数据
- 清理和浏览数据
- 产生相对估值
- 筛选库存并分析历史价格
本章将引导您完成一个财务分析项目,在此项目中,您将分析股票市场数据,确定股票是被高估还是被低估,使用此信息来识别可以进行良好投资的目标股票列表,并直观地分析价格历史 的目标股票。
我们必须警告,本章的目的不是要使您成为股票分析专家或使您变得有钱。 《华尔街定量研究》研究的工程模型所执行的操作比我们将在此处涉及的操作要复杂得多。 整本书都写有关于股票市场模型和金融工程的书,但是我们只有一章专门讨论这个主题。 因此,鉴于时间和格式的限制,本章的目标将是:
- 基本了解我们将使用的数据
- 寻找有用且有趣的方式来分析和建模数据
- 要了解如何利用数据科学工具和技术来执行我们需要对数据执行的分析任务的类型
我们将在本章中使用的数据包括网站 finviz.com 跟踪的股票的当前数据以及从 Yahoo!获得的股价的每日历史记录。 金融。
如前几章所述,我们将用于该项目的工具将是 R 统计编程语言。 您可能已经注意到,R 具有强大的软件包,可以帮助我们完成所需的分析任务。 我们将在本章中利用其中一些软件包。 此外,本章中的方法将大致遵循数据科学的流程,我们将根据我们正在使用的数据类型以及我们希望对数据进行的分析类型进行调整。
对于本章,您将需要一台可访问互联网的计算机。 您还需要安装 R 并安装以下软件包,然后再加载:
install.packages("XML")
install.packages("ggplot2")
install.packages("plyr")
install.packages("reshape2")
install.packages("zoo")
library(XML)
library(ggplot2 ,quietly=TRUE)
library(plyr ,quietly=TRUE)
library(reshape2 ,quietly=TRUE)
library(zoo ,quietly=TRUE)
XML
软件包将帮助我们从互联网上获取数据,ggplot2
将使我们能够从数据中创建漂亮的图形和可视化图像,plyr
和reshape2
将帮助我们汇总数据,而zoo
一揽子计划将使我们能够计算移动平均线。
您还将需要设置一个工作目录,在该目录中将保存我们生成的某些图表:
setwd("path/where/you/want/to save/charts")
如果您在互联网上查找股票市场数据,您会很快发现自己被提供股票行情和财务数据的资源所淹没。 获取数据时一个重要且经常被忽略的因素是获取数据的效率。 在其他所有条件都相同的情况下,您不想花费数小时将您可以在更短的时间内获取的数据集拼凑在一起。 考虑到这一点,我们将尝试从最少数量的源中获取最大量的数据。 这不仅有助于保持数据尽可能一致,而且还可以提高分析的可重复性和结果的可重复性。
我们要获取的第一笔数据是我们要分析的股票的快照。 最好的方法之一是从现有的许多股票筛选器应用之一下载数据。 我们最喜欢的从其中下载股票数据的筛选器属于这个页面。
让我们在以下步骤的帮助下获取将在本章中使用的股票市场数据:
- 首先,让我们拉起这个页面上的 finviz 股票筛选器:
如您所见,该站点具有多个可以过滤的字段。 如果单击 All
选项卡,则可以看到所有可以显示的字段。
- 对于此项目,我们要导出筛选器中所有公司的所有字段。 您可以在编写本文时通过选中 69 个复选框来自定义筛选器,也可以使用以下 URL 自动显示所有字段:
现在,您应该看到带有所有可用字段的筛选器。
- 如果一直滚动到屏幕的右下角,应该有一个
export
链接。 单击此链接,然后将 CSV 文件另存为finviz.csv
。 - 最后,我们将启动 **RStudio,**从保存文件的路径中读取
finviz.csv
文件,并将其分配给数据帧,如下所示:
finviz <- read.csv("path/finviz.csv")
在数据分析中,最好将执行的每个步骤都包含在代码中,而不是将其作为一系列需要人工干预的点击操作。 这样,可以更轻松,更快地重现您的结果。
- 首次执行步骤 1 至 4 (并从浏览器中聪明地读取了 URL)之后,我们可以使用以下两个命令替换前面的代码行:
url_to_open <-
'http://finviz.com/export.ashx?v=152&c=0,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,5
2,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68'
finviz <- read.csv(url(url_to_open))
注意步骤 2 中 URL 的结构; 它包含我们要选择的复选框的逗号分隔列表。 您可以以编程方式生成此 URL,以轻松选择要下载的公司数据的任意组合。 如果要避免输入数字 0 到 68,可以结合使用sprintf
和粘贴命令来完成相同的操作:url_to_open <-
sprintf("http://finviz.com/export.ashx?v=152&c=%s", paste(0:68, collapse = ","))
现在,我们已经获取了库存数据,让我们使用几个命令找出数据中包含哪些字段,并获取有关这些字段中包含的值的一些有用信息。
您将需要从以前的配方和要获取股票市场数据中下载的数据来开始汇总。
以下步骤将引导您快速浏览数据摘要:
- 查看使用以下命令导入的字段:
> head(finviz[,1:4])
该命令将向您显示数据的前六行,如以下代码片段所示,以便您可以查看数据中包含哪些字段以及该字段的可能值示例。 在此示例中,我们还可以看到有一些丢失的数据,由NA
标识:
No. Ticker Company Sector
1 1 A Agilent Technologies Inc. Healthcare
2 2 AA Alcoa, Inc. Basic Materials
3 3 AADR WCM/BNY Mellon Focused Growth ADR ETF Financial
4 4 AAIT iShares MSCI AC Asia Information Tech Financial
5 5 AAL American Airlines Group Inc. Services
6 6 AAMC Altisource Asset Management Corporation Financial
- 下一条命令将返回每个字段的摘要。 对于数字字段,它将告诉您最小,最大,均值,中位数和四分位数;对于字符字段,它将告诉您最常出现的字段:
既然我们已经初步了解了数据,那么花点时间找出对我们最重要的字段并了解这些字段的含义就很重要。
前几个字段包含有关公司的标识信息。
股票代码(有时也称为股票代号)是公司股票的标识符。 没有两家公司会使用完全相同的股票代号。 因此AA
始终为Alcoa
,AAPL
始终为Apple
,依此类推。
接下来,我们有公司的名称,部门,行业和公司的母国。 行业和行业详细信息可作为对股票进行分类的方式,以告知我们每个公司的主要业务范围; 行业更一般(较高级别),行业更具体(较低级别)。 例如,Apple Inc.(AAPL)在消费品领域,主要在电子设备行业生产消费品。
一旦我们越过了这些字段,数据集中的其他大多数字段都是数字。 让我们定义一些最重要的:
- 价格:这表示购买公司股票的当前美元价值。
- 交易量:这表示一天内交易的股票的最新数量。
- 发行在外的股票:这是公司已发行的股票总数。
- 市盈率:市盈率是公司股票的价格除以公司在外每股收益。
- PEG:市盈率增长率是公司的市盈率除以年增长率,它使您对公司收益相对于其增长率的估值有所了解。
- 明年每股收益增长:这是公司明年的每股收益的预期增长率。
- 总债务/权益:总债务与权益之比用作财务状况的度量,方法是将公司总债务的美元价值除以公司权益。 这使您对公司如何为增长和运营进行融资提供了一种感觉。 债务比股本更具风险,因此高比率将引起人们的关注。
- Beta:这是相对于整个股票市场的股票波动(价格波动)的度量。 Beta 值为 1 表示股票与市场一样动荡。 Beta 大于 1 意味着它的波动性更大,而 Beta 小于 1 意味着它的波动性较小。
- RSI:相对强度指数是基于股票价格活动的度量标准,该指标使用的是股票收盘价高于开盘价的天数和股票收盘价低于开盘价的天数。 在最近两周内确定 0 到 100 之间的得分。较高的指数值表示该股票可能被高估了,因此价格可能很快下降; 较低的值表示股票可能被低估了,因此价格可能很快就会上涨。
如果您想了解其他一些字段的定义,这个页面是查找财务和投资术语定义的好地方。
现在我们已经获取了数据并了解了一些字段的含义,下一步就是清理数据并进行一些探索性分析。
确保已安装本章开头提到的要求部分下的软件包,并且已按照前面几节中的步骤将FINVIZ
数据成功导入到 R 中。
要清理和浏览数据,请严格遵循以下说明:
- 导入的数字数据通常包含特殊字符,例如百分比符号,美元符号,逗号等。 这使 R 认为该字段是字符字段而不是数字字段。 例如,我们的
FINVIZ
数据集包含许多带有百分号的值,必须将其删除。 为此,我们将创建一个clean_numeric
函数,该函数将使用gsub
命令删除所有不需要的字符。 我们将创建一次此函数,然后在本章中多次使用它:
clean_numeric <- function(s){
s <- gsub("%|\\$|,|\\)|\\(", "", s)
s <- as.numeric(s)
}
- 接下来,我们将此功能应用于
finviz
数据框中的数字字段:
finviz <- cbind(finviz[,1:6],apply(finviz[,7:68], 2, clean_numeric))
- 如果再次查看数据,所有讨厌的百分比符号都将消失,并且所有字段均为数字。
在该命令中以及本章的其余部分,将有很多实例通过列号引用列。 如果列数由于某些原因发生变化,则引用的数字将需要相应地进行调整。
- 现在,我们准备好开始真正地探索我们的数据了! 首先要做的是看一下价格的分配方式,以便直观地了解什么是高股票价格,什么是低股票价格以及大多数股票的价格下跌的地方:
hist(finviz$Price, breaks=100, main="Price Distribution", xlab="Price")
您将获得以下图形作为输出:
在这里,我们遇到了第一个问题。 价格非常高的离群股票导致 R 缩放直方图的x
轴,从而使该图无用。 我们根本无法看到定价更高的股票的分布情况如何。 在生成直方图时,这是一个非常常见的问题。
- 让我们在 $ 150 的
x
轴上加一个上限,看看会为我们带来什么:
hist(finviz$Price[finviz$Price<150], breaks=100, main=
"Price Distribution", xlab="Price")
您将获得以下图形作为输出:
这样好多了! 它表明我们数据集中的大多数股票的价格都在 50 美元以下。 因此,以绝对值计算,定价为 100 美元的股票将被认为是昂贵的。
- 但是当然事情并不是那么简单。 也许不同的部门和行业具有不同的价格水平。 因此,从理论上讲,如果该行业中的所有其他股票的定价都在 120 美元至 150 美元之间,那么 100 美元的股票可能会便宜。 让我们获取按部门划分的平均价格,并查看它们之间的比较。 请注意,我们不排除任何库存:
sector_avg_prices <- aggregate(Price~Sector,data=finviz,FUN="mean")
colnames(sector_avg_prices)[2] <- "Sector_Avg_Price"
ggplot(sector_avg_prices, aes(x=Sector, y=Sector_Avg_Price,
fill=Sector)) + geom_bar(stat="identity") + ggtitle("Sector Avg Prices") + theme(axis.text.x = element_text(angle = 90, hjust = 1))
您将获得以下图形作为输出:
这是有趣的。 金融部门的股票似乎具有比其他部门的股票更高的平均价格。 我敢打赌,这是由于一些离群值更早干扰了我们的分布。
- 让我们深入到此! 让我们找出哪些行业和公司负责使金融部门的平均价格远高于其他所有行业和公司。
首先,我们按行业创建平均价格摘要:
industry_avg_prices <- aggregate(Price~Sector+Industry,data=finviz,FUN="mean")
industry_avg_prices <- industry_avg_prices[order( industry_avg_prices$Sector,industry_avg_prices$Industry),]
colnames(industry_avg_prices)[3] <- "Industry_Avg_Price"
然后,我们将金融部门中的行业隔离开来:
industry_chart <- subset(industry_avg_prices,Sector=="Financial")
最后,我们创建一个图表,显示金融部门每个行业的平均价格:
ggplot(industry_chart, aes(x=Industry, y=Industry_Avg_Price,
fill=Industry)) + geom_bar(stat="identity") + theme(legend.position="none") + ggtitle("Industry Avg Prices") + theme(axis.text.x = element_text(angle = 90, hjust = 1))
您将获得以下图形作为输出:
从该图可以看出,财产&伤亡保险行业是推动平均价格上涨的罪魁祸首。
- 接下来,我们将进一步深入
Property & Casualty Insurance
行业,以找出哪些公司是异常公司:
company_chart <- subset(finviz,Industry=="Property & Casualty Insurance")
ggplot(company_chart, aes(x=Company, y=Price, fill=Company)) +
geom_bar(stat="identity") + theme(legend.position="none") +
ggtitle("Company Avg Prices") +
theme(axis.text.x = element_text(angle = 90, hjust = 1))
您将获得以下图形作为输出:
很难看到,因为有这么多公司,但是如果您放大图表,就会发现离群的公司是 Berkshire Hathaway,该公司的股价目前超过每股 172,000 美元。
- 由于它们的股价是如此之高,因此让我们将其从数据集中删除,然后对这些行业进行平均,以使我们能够更准确地得出金融行业的平均价格:
finviz <- subset(finviz, Ticker!="BRK-A")
sector_avg_prices <- aggregate(Price~Sector,data=finviz,FUN="mean")
colnames(sector_avg_prices)[2] <- "Sector_Avg_Price"
ggplot(sector_avg_prices, aes(x=Sector, y=Sector_Avg_Price,
fill=Sector)) + geom_bar(stat="identity") + ggtitle("Sector Avg Prices") + theme(axis.text.x = element_text(angle = 90, hjust = 1))
您将获得以下图形作为输出:
现在,我们的平均值看起来要好得多,而且我们有相当不错的基础将股票价格与其行业和行业平均值进行比较。
在本节中,我们使用aggregate
命令来汇总我们的数据。 这是我们使用的代码的提醒:
sector_avg_prices <- aggregate(Price~Sector,data=finviz,FUN="mean")
另一种执行此方法的方法是使用plyr
程序包中的ddply
命令:
sector_avg_prices <- ddply(finviz, "Sector", summarise,
Price=mean(Price, na.rm=TRUE))
无论您在何处看到本章中使用的aggregate
命令,都可以尝试通过使用ddply
命令来汇总数据来挑战自己。
您可以使用股市数据做的最有趣的事情之一就是评估模型。 最终目标是就股票是被高估还是被低估做出决定。 有两种主要方法可以做到这一点。 内部估值通常更耗时,因为它涉及挖掘公司的财务报表以得出估值决策。 另一种方法是相对估值,它可以快速提供股票的估值方式,但不考虑一系列综合因素。 基本思想是将股票的价格和估值比率与相似的股票进行比较,以得出结论。 在本节中,我们将使用更简单的相对估值方法对股票进行估值。
此食谱需要下载和清除先前食谱中的数据。
在本节中,我们基本上将做三件事。 首先,我们计算可用于相对估值工作中的字段的行业平均值。 然后,我们在行业层面上也做同样的事情。 最后,我们将股票的统计数据与平均值进行比较,以得出每只股票的指数值,该指数值指示该股票是否可能被低估了。 以下步骤将指导您:
- 为了计算 R 中多列的平均值,我们首先需要融合数据。 这将使
Sector
之后的每一列都成为一行,然后显示其值,从本质上讲使数据变长而不是变宽。 请查看以下屏幕快照,了解此食谱中的不同步骤,以更好地了解数据如何改变形状。 它从宽到长,然后又回到宽,但以摘要形式:
我们将使用以下命令执行此操作:
sector_avg <- melt(finviz, id="Sector")
- 接下来,我们需要过滤,以便数据框仅包含我们要平均的字段:
sector_avg <- subset(sector_avg,variable %in% c("Price","P.E","PEG","P.S", "P.B"))
现在您的sector_avg
数据框应如下所示:
现在,每个列标题(变量)都在其值旁边垂直列出。 这使我们以后可以进行一些分组以获得每个变量的平均值。
- 并非原始数据集中的所有股票都具有所有这些值。 如果这些值为空,则我们要删除记录。 我们还想确保我们所有的值都是数字:
sector_avg <- (na.omit(sector_avg))
sector_avg$value <- as.numeric(sector_avg$value)
- 下一步是转换数据以使其再次变宽。 这将为我们过滤的每个字段产生一列,并且现在将包含按扇区划分的平均值。 我们还将重命名这些列,以便我们知道它们是部门平均值:
sector_avg <- dcast(sector_avg, Sector~variable, mean)
colnames(sector_avg)[2:6] <- c("SAvgPE","SAvgPEG","SAvgPS","SAvgPB", "SAvgPrice")
您将获得以下图作为输出:
- 现在,我们将在行业级别上做完全相同的事情:
industry_avg <- melt(finviz, id=c("Sector","Industry"))
industry_avg <- subset(industry_avg,variable %in% c("Price","P.E","PEG","P.S","P.B"))
industry_avg <- (na.omit(industry_avg))
industry_avg$value <- as.numeric(industry_avg$value)
industry_avg <- dcast(industry_avg, Sector+Industry~variable, mean)
industry_avg <- (na.omit(industry_avg))
colnames(industry_avg)[3:7] <-
c("IAvgPE","IAvgPEG","IAvgPS","IAvgPB","IAvgPrice")
- 现在,我们将部门和行业平均值列添加到原始
finviz
数据集中:
finviz <- merge(finviz, sector_avg, by.x="Sector", by.y="Sector")
finviz <- merge(finviz, industry_avg, by.x=c("Sector","Industry"), by.y=c("Sector","Industry"))
您可能已经注意到,当我们执行最后一行代码时,finviz
数据框中的记录数减少了。 它从数据集中删除了所有没有行业平均值的股票。 这样做很好,因为总体目标是缩小股票清单的范围,而且我们将始终没有足够的信息来生成这些股票的估值。
- 现在是时候使用这些新字段了。 首先,我们将添加 10 个包含所有
0
的占位符字段。 基于低于行业或行业平均水平,这些信息将用于跟踪股票是否被低估:
finviz$SPEUnder <- 0
finviz$SPEGUnder <- 0
finviz$SPSUnder <- 0
finviz$SPBUnder <- 0
finviz$SPriceUnder <- 0
finviz$IPEUnder <- 0
finviz$IPEGUnder <- 0
finviz$IPSUnder <- 0
finviz$IPBUnder <- 0
finviz$IPriceUnder <- 0
- 接下来,只要股票的各自价值小于平均值,我们就将 0 替换为 1,以表明根据该指标这些股票可能被低估了:
finviz$SPEUnder[finviz$P.E<finviz$SAvgPE] <- 1
finviz$SPEGUnder[finviz$PEG<finviz$SAvgPEG] <- 1
finviz$SPSUnder[finviz$P.S<finviz$SAvgPS] <- 1
finviz$SPBUnder[finviz$P.B<finviz$SAvgPB] <- 1
finviz$SPriceUnder[finviz$Price<finviz$SAvgPrice] <- 1
finviz$IPEUnder[finviz$P.E<finviz$IAvgPE] <- 1
finviz$IPEGUnder[finviz$PEG<finviz$IAvgPEG] <- 1
finviz$IPSUnder[finviz$P.S<finviz$IAvgPS] <- 1
finviz$IPBUnder[finviz$P.B<finviz$IAvgPB] <- 1
finviz$IPriceUnder[finviz$Price<finviz$IAvgPrice] <- 1
- 最后,我们将对这 10 列进行求和,以创建一个新的索引值列,以 1 到 10 的比例告诉您,股票是如何根据所考虑的不同维度而被低估的:
finviz$RelValIndex <- apply(finviz[79:88],1,sum)
相对估值涉及将股票的统计数据与类似股票的统计数据进行比较,以确定该股票是被高估还是被低估。 在一个过于简化的示例中,相对于其行业的行业平均 P / E 比(所有其他条件都相同),具有较低市盈率的股票可以被认为价值低估,并且如果 公司财务状况良好。 一旦有了这些,我们就可以筛选出最有前途的股票,例如RelValIndex
为 8 或更大的股票。
potentially_undervalued <- subset(finviz,RelValIndex>=8)
我们刚刚创建的potentially_undervalued
数据框应如下所示:
我们承认这是一种过于简单的方法。 但是,它提供了扩展到更复杂的计算的框架。 例如,一旦对此过程感到满意,您可以:
- 添加自定义条件以分配
1
,以表明股票被低估了 - 权衡不同的值
- 添加或删除条件
- 创建比 1 和 0 更精确的索引值,依此类推
天空是这里的极限,但是过程是一样的。
当我们寻找股票进行投资时,我们需要一种方法来缩小列表的范围。 换句话说,我们需要消除那些我们认为不是好的投资的股票。 优质投资的定义因人而异,但是在本节中,我们将使用一些基本标准将主股票清单减少到我们认为可能具有良好前景的少数股票。 一旦适应了这一过程,我们鼓励您根据自己对有价值股票定义的观点进行修改。一旦有了前景,我们将分析其历史价格,并从中得出结论。
我们将从上一节结尾处的finviz
数据集开始,并与行业和行业平均值列,二进制低估列以及将二进制列中的值求和的索引值相加。
除了本章到目前为止使用的软件包之外,本节还将需要 zoo 软件包。 这将有助于我们计算将要拉升的历史股价的移动平均线。
您将要执行的步骤将使您可以筛选库存:
- 首先,选择一些股票筛选标准,即在
finviz
数据集中选择我们认为有可能成为良好投资潜力的股票的方法。 以下是一些示例标准,以开始:- 只有美国公司
- 每股价格在 20 到 100 美元之间
- 数量大于 10,000
- 当前和未来预期的正每股收益
- 总负债权益比小于 1
- Beta 小于 1.5
- 机构所有权少于 30%
- 相对估值指数值大于 8
- 如前所述,这些只是示例。 随意删除条件,添加条件或根据您认为将为您提供最佳输出的内容进行更改。 目标是将清单缩小到少于 10 只股票。
- 接下来,我们应用我们的标准将
finviz
数据帧子集化为名为target_stocks
的新数据帧:
target_stocks <- subset(finviz, Price>20 & Price<100 & Volume>10000 &
Country=="USA" &
EPS..ttm.>0 &
EPS.growth.next.year>0 &
EPS.growth.next.5.years>0 &
Total.Debt.Equity<1 & Beta<1.5 &
Institutional.Ownership<30 &
RelValIndex>8)
在撰写本文时,这将产生六只股票的目标清单,如以下屏幕快照所示。 如果您从网上提取更新的数据,则可能会得到不同的数量或不同的库存:
- 现在,让我们出去获取目标股票清单的历史价格,以便我们了解其价格随时间的变化。 我们将使用
for
循环来遍历符号列表并为每个价格拉价,但是我们将通过几个步骤来分解循环,并解释每个块在做什么:
counter <- 0
for (symbol in target_stocks$Ticker){
前面的命令初始化一个计数器,以跟踪我们在目标股票列表中的位置。 之后,我们通过告诉目标列表中的每个符号执行以下操作来开始 for 循环:
url <- paste0("http://ichart.finance.yahoo.com/table.csv?s=",symbol,
"&a=08&b=7&c=1984&d=01&e=23&f=2014&g=d&ignore=.csv")
**stock <- read.csv(url)**
**stock <- na.omit(stock)**
**colnames(stock)[7] <- "AdjClose"**
**stock[,1] <- as.Date(stock[,1])**
**stock <- cbind(Symbol=symbol,stock)**
此代码将 URL 分配给已嵌入当前股票代码的 URL 变量。 然后,我们读取位于该 URL 的数据,并将其分配给名为stock
的数据帧。 然后,我们进行一些清理和格式化,方法是从数据框中删除所有空值,重命名最后一列,确保Date
列的格式设置为 R 可以识别的日期,然后将股票代码添加到 数据框。
for
循环的接下来的几行将计算一些移动平均线,以便我们可以将它们与每日股价进行比较。 对于此步骤,请确保已安装并加载了本节开头提到的zoo
程序包。
第一部分将计算 50 天移动平均线和 200 天移动平均线:
**maxrow <- nrow(stock)-49**
**ma50 <- cbind(stock[1:maxrow,1:2],rollmean(stock$AdjClose, 50,align="right"))**
**maxrow <- nrow(stock)-199**
**ma200 <- cbind(stock[1:maxrow,1:2],rollmean(stock$AdjClose,200,align="right"))**
第二部分将移动平均数据框与包含历史股票价格的数据框组合在一起,以便所有内容都属于同一数据集:
stock <- merge(stock,ma50,by.x=c("Symbol","Date"),by.y=c("Symbol",
"Date"), all.x=TRUE)
colnames(stock)[9] <- "MovAvg50"
stock <- merge(stock,ma200,by.x=c("Symbol","Date"),by.y=c("Symbol", "Date"),all.x=TRUE)
colnames(stock)[10] <- "MovAvg200"
- 接下来,我们将为我们的
for
循环迭代的每种股票绘制历史图表,然后保存该图表:
price_chart <- melt(stock[,c(1,2,8,9,10)],id=c("Symbol","Date"))
qplot(Date, value, data=price_chart, geom="line", color=variable, main=paste(symbol,"Daily Stock Prices"),ylab="Price")
ggsave(filename=paste0("stock_price_",counter,".png"))
生成并保存的图表应类似于以下两个图表:
循环的下一部分总结了当前股票的开盘价,最高价,最低价和收盘价:
price_summary <- ddply(stock, "Symbol", summarise, open=Open[nrow(stock)], high=max(High),low=min(Low),close=AdjClose[1])
然后,它将汇总的开盘价,最高价,最低价和收盘价汇总到一个称为股票的数据框中,以便以后可以比较不同的股票。 而且,它在称为价格摘要的数据框中单独累积了股票的所有每日历史价格,以便也可以将它们进行比较:
if(counter==0){
stocks <- rbind(stock)
price_summaries <- rbind(price_summary)
}else{
stocks <- rbind(stocks, stock)
price_summaries <- rbind(price_summaries, price_summary)
}
在循环结束时,我们将计数器加 1,然后用花括号将 for 循环关闭:
counter <- counter+1
}
我们将循环分成几部分,以解释循环的每个部分的功能。 如果要查看整个 for 循环的外观,请查看本章随附的代码文件。
完整的代码块在此处以图像形式给出:
遍历所有股票代码之后,我们将得到一个名为stocks
的数据框,其中包含目标列表中所有符号的历史价格,以及一个名为price_summaries
的数据框,其中包含所有股票的摘要 。 让我们绘制它们的图,看看它们的外观。
- 首先,我们将绘制所有股票的历史价格:
qplot(Date, AdjClose, data=stocks, geom="line", color=Symbol, main="Daily Stock Prices")
ggsave(filename=("stock_price_combined.png"))
前面的命令将产生以下图形:
- 然后,让我们可视化价格摘要:
summary <- melt(price_summaries,id="Symbol")
ggplot(summary, aes(x=variable, y=value, fill=Symbol)) + geom_bar(stat="identity") + facet_wrap(~Symbol)
ggsave(filename=("stock_price_summaries.png"))
生成的图形应类似于以下内容:
每日股价图表非常尖刻或易变,这有时使它们难以阅读。 移动平均线可以平滑股票的价格波动,因此您可以更好地了解股票是随时间上涨还是下跌。
移动平均线还用于对股票投资进行计时。 换句话说,它们用作确定是立即投资股票还是等待股票的指南。 关于什么是最佳时间的信号,人们意见不一,但其中一个例子是,该股的 50 天移动平均线低于其 200 天移动平均线,但仍在上升。 有关移动平均线的更多信息,请参见这个页面。
我们在本节中生成的组合历史价格图表向我们显示了目标股票的价格串联变化的程度。 如果您打算投资多只股票,那么最好投资价格之间的相关性不高的股票。 您还可以可视化一种股票与另一种股票相比的波动性。 在我们的图形中,您可以看到符号WPZ
和NRCIB
的波动性很强,而其他符号的波动性较小。
查看价格比较的另一种方法是检查我们创建的价格摘要条形图。 该图表显示了所分析期间的开盘价,最高价,最低价和收盘价。 开盘价是股票交易的第一个价格,收盘价是迄今为止股票交易的最后一个价格,高价是该期间股票的最高价格,而低价是 股票在此期间的最低价格。 可以在此图上以不同的方式查看前面提到的波动率,因为您可以清楚地看到我们两个波动最大的股票的高点和低点之间的差异。 该图表还可以让您查看股票的收盘价相对于其历史最高价和历史最低价的位置,这可能有助于您了解其当前估值的公平性。