技术 | 从0开始搭建智能投资顾问(一)

这篇是技术系列《从0开始搭建智能投资顾问》的第一部分,后续内容请持续关注!

推荐这篇文章的3个理由:

  1. 解释了如何从Yahoo Finance API 获取数据
  2. 利用dash库对数据进行可视化处理
  3. 对智能投顾进行了介绍并给出了例子

引言:

数据的整合处理是股票投资中至关重要的一环,我们可以使用Python来进行金融分析,特别是其中广泛应用于数据分析的Pandas库。在这篇文章中首先会介绍如何利用一些非常有用的在线资源,例如 Yahoo Finance API 和 Jupyter notebook 来实现自动跟踪和检测股票投资组合的表现。然后我们利用这些资源和Python的Plotly模块生成可视化图表。最后利用这些东西构建自己的智能投资顾问。下面将分三个部分分步进行分析。
 

第一部分 投资组合分析
 

我们在这一部分将完成下面这些任务:

  • 使用雅虎财经API接口(Yahoo Finance API)导入S&P 500指数和股票样本行情数据
  • 创建一个合并的投资组合“主”文件,该文件将样本投资组合数据帧、历史股票代码和历史S&P 500数据相结合
  • 确定每笔投资收购之日的S&P 500收盘价,这样我们就可以用同样的投资额计算出S&P 500对应的等价值的股票头寸
  • 计算一段时间内投资组合头寸的相对百分比回报和美元价值绝对数量回报,并且与S&P 500指数回报进行对比
  • 计算累积投资组合回报和投资回报率(ROI)乘数,以评估该投资组合与市场指数相比孰优孰劣
  • 其中一个更重要的一点是:动态计算每一个仓位相对于跟踪止损的表现,例如,如果一个仓位收盘时低于收盘高点25%,就考虑在下一个交易日卖出该仓位
  • 可视化
  • 总回报的百分比比较——每个投资组合相对于基准指数的回报百分差异
  • 一段时间内的累积回报——每个投资组合相对于基准指数的美元数额绝对收益/损失
  • 一段时间内的累积投资——鉴于上述分析,与同等权重和时间段的S&P 500投资相比,总体投资回报如何?
  • 调整后的收盘价相对于高位收盘的差离率%——相对于自购买以来调整后的收盘价高点,每个头寸最近的收盘价是多少?

 

数据导入和数据帧操作

 

我们从导入必要的Python模块开始,先将Plotly offline模块导入,然后读入我们投资组合数据帧样本。

 


现在您已经阅读了投资组合文件示例,您将创建几个变量来捕获S&P 500指数和所有投资组合的报价的数据范围。请注意,这是Jupyter Notebook中需要每周更新的少数几个地方之一(调整日期范围以囊括最近的交易周数据——在这里,我们用2017年3月9日之前的价格数据来运行程序)。

 

正如Python财经培训帖子中提到的,我们可以用pandas-datareader包从Google、Yahoo! Finance和世界银行读入数据。在这里,我将关注Yahoo! Finance,虽然我已经开始初步在美股量化策略平台Quantopian上运行程序,并且已经开始把Quandl作为数据源。正如美股量化策略平台 DataCamp帖子中提到的,雅虎API端点最近发生了变化,这需要为雅虎安装一个临时补丁来让Yahoo! Finance数据继续可以调用。我在下面的代码中做了一些必要的调整。我注意到一些小的数据问题——数据并不总是像预期方式那样被读入,或者最后一个交易日数据有时会丢失。虽然这些问题相对来说并不常见,但我仍然会继续关注Yahoo! Finance是否会是未来最好和最可靠的数据源。

 

 

如果你正在看着你的Notebook上的进度,那么一旦你成功地从雅虎API(应用编程接口)中读取了数据,你应该会看到如下的内容:

 

载入S&P 500数据后,你会看到我检查了数据帧的头部和尾部,并压缩了数据帧,使其只包含调整关闭列。调整后收盘价和收盘价的区别在于调整后的收盘价反映股息(见下文未来发展领域)。当一家公司发行股息时,由于该公司正在分配公司的一部分收益,股价会减少每股股息的大小。出于此分析的目的,您只需要分析此列。我还创建了一个数据框架,该框架仅包括S&P在2017年最后一天(2018年初)调整后的收盘价;这是为了相对于S&P 500的表现进行年初至今的比较。
 

在下面的代码中,我们在样本投资组合数据帧中创建一个包含所有股票的数组。然后编写一个函数将将所有股票以及相关数据读取到一个新的数据帧中,这与S&P500指数所采用的方法基本相同,但适用于所有股票投资组合。


 

 


和S&P500数据帧一样,我们将创建一个adj_close数据帧,该数据帧仅包括所有股票代码的 Adj Close列,在GitHub的repo里面的笔记本中,这个代码会被嵌入更多的模块中,而不是像下面这样。但为了描述如何操作,我将初始化merged_portfolio数据帧的所有代码放在了下面

 

 

我们已经获得了S&P500指数和每个股票的各个数据帧,下面我们来创建一个“master”数据帧,并进一步使用Pandas库中merge函数,然后重置当前数据帧索引并将较小的数据帧插入‘master’中。

 

我们进一步开发“master”数据帧来实现以下内容:

每个投资组合头寸的价格,股票和头寸在获取日的价格,以及最新市场的收盘价。

标准普尔500指数相当于每个股票的等价头寸收购日的价格,以及最新的标准普尔500收盘价。

为了实现上面的内容,我们需要进行必要的计算,在相同的美元投资和S&P500指数的持有时间下比较每个头寸的表现和该策略下股票组合的整体表现。

 

 

为了比较你的投资组合和与S&P500同等的投资组合的表现,下面两段代码将实现下面这两个功能:

比较每个头寸相对于S&P500指数年初累计的表现

比较每个投资组合的头寸相对于其最近收盘价的最近的收盘高点(这使您可以评估是否需要触发追踪止损,例如收盘价低于收盘高点25%)

 

下面我们将从处理年初累计的代码开始,进一步来分析代码:
 


在下面的这段代码中,我们使用 sort_values 方法对‘master’数据帧进行重新排序,然后计算投资组合的累计投资(头寸获取成本的总和),包括投资组合头寸的累计值和理论上S&P500投资。这使我们能够了解整个时期不同时间投资头寸在整个投资组合的总体情况,并将其与只是投资于指数的策略进行比较。之后使用['Cum Ticker ROI Mult']来展现出每一项投资对您的总体投资回报(ROI)的贡献多少。

 

 

现在我们已经接近尾声,可以开始准备将数据进行可视化处理。并评估我们投资组合的单支股票和总体策略的优缺点。

和前面一样,我们来解析下面这段用于确定最近交易收盘高点的头寸的代码

 

 

这是我们非常重要的一步,现在我们可以进行期待已久的可视化步骤,在执行完之前的代码后,我们现在有了一个非常丰富的数据帧,其中包含许多计算过的投资组合的各种指标,如下所示:
 


 

总回报和累计回报可视化

 

我们虽然可以使用Matplotlib或Seaborn来进行可视化操作,但在这里我们使用plotly,因为它允许你完全不使用代码来制作D3图表。Plotly的交互性很好,一旦你习惯了它,你会发现他的语法十分简单,并且很容易用它来制作动态图表。

下面第一个表格比较了每只股票相对于S&P500指数的总回报(相同持仓时间下头寸和假设的S&P500投资)。在下文中我们看到了在持仓期间,8个头寸中有6个头寸优于S&P500指数,最后两个Twitter(实际上有负回报)和沃尔玛落后于同等的S&P500投资。
 

每一个可视化操作都十分类似,我将解释生成上面的Plotly可视化图像所需要的代码,对于其余图像我们只进行简单分析

 


 

下图显示了每个头寸相对于S&P500指数的收益或亏损的美元金额,并显示了股票的总回报率。虽然通常建议你给每个头寸分配相同的头寸大小(或根据隐含波动率确定潜在的头寸大小),但是事实情况却不可能总是如此,相对于波动性较大的投资,你更可能会更多的投资于波动性较小的投资(或者其他投资规则)。考虑到这一点下面这个图表显示了每个头寸的回报对整体投资的回报的贡献。

 

在这里,你可以看到,尽管你在Facebook上的投资比其他头寸略少,但在这个模拟投资组合中,这只股票的回报率约为2万美元,比标准普尔500指数(S&P 500)同期投资的4倍还要高。
 


 

我们利用之前的 'Cum Invst', 'Cum SP Returns', 'Cum Ticker Returns', 和 'Cum Ticker ROI Mult'.列来创建下面的图表。

 


 

调整后的相对高位收盘价百分比
 

我们最后一个图表比较了每个头寸最新收盘价与自购买头寸以来的调整收盘价相差的距离。这通常是一个我们需要考虑的重要图表