Pandas是对金融商场数据进行时刻序列剖析的一个巨大东西。由于pandasDataFrames和Series 与基于日期/时刻的指数作业得很好,它们能够有用地用于剖析前史数据。我所说的金融商场数据是指揭露买卖的金融东西的前史价格信息等数据。可是,任何种类的前史金融信息都能够被剖析。

时刻序列数据将以不同的频率供给。有些金融东西的流动性很强,咱们简直能够在任何时刻点检查价格。价格或其他一些特征简直不断变化。一个东西具有流动性的主见意味着在正常的买卖时刻内,有乐意买卖的买家和卖家预备与之买卖。他们乐意购买和出售满足的东西来满足你的买卖需求。关于在买卖所买卖的东西,买家和卖家乐意支付或供给的价格在该东西的正常买卖时刻内都能够得到。

由于大量的金融数据是可用的,其间大部分是免费的,所以它是学习更多关于剖析和处理时刻序列数据的绝佳场所。经过这些数据,咱们能够学到许多关于公共商场和熊猫的东西。在这篇文章中,我将指导你怎么做一些简略的剖析。在这个过程中,咱们或许会发现一些关于股票商场和熊猫的作业。

关于这篇文章,咱们将看看金融商场中常见的一个效应:季节性。季节性是时刻序列数据的一个特色,在这儿能够看到基于时刻的规则性影响。它或许是一年的时刻,一个月的时刻,一天的时刻,乃至是每小时的分钟。我将向你展现怎么下载一些数据(在这种状况下是每日股票数据),然后运用pandas和matplotlib来验证数据是否看起来合理。然后,咱们将调查数据中是否存在每月的季节性。在这一过程中,我将浏览一下代码,并供给一些指针,假如你有爱好的话,能够去了解更多。

在未来的文章中,我将研讨在每日(每天一个数据点)和日内(每天许多数据点)数据中看到的一些其他风趣的作用。

获取数据

处理商场数据的最大挫折之一是首要要掌握它。金融数据或许是有价值的,因此具有这些数据的人一般会对其收费。数据在广度、时刻和质量等多个方面变得更有价值。

数据的广度

在广度方面,咱们有关于一个金融东西的信息。考虑一个这样的金融东西,一个公司的揭露买卖的普通股。咱们能够获取该股票的价格,但哪个价格?关于每日的股票价格数据,这个价格一般是该股票在16:00美国/纽约的收盘价。但咱们也或许想知道该股票在美国/纽约9:30开盘时的价格。

或许咱们还想知道当天的最高价格和最低价格。最终,咱们或许想知道在整个一天的过程中,有多少股买卖(称为成交量)。在这个每日数据的比如中,广度维度包含5个信息:最终买卖价格(或收盘价),榜首个买卖价格(或开盘价),最高买卖价格(高)和最低买卖价格(低),以及当天的总成交量。

数据越具体,成本就越高。除了买卖价格,咱们还能够得到买入和卖出价格。这些是有人乐意为一个给定的东西支付(出价)或出售(要价)的价格。除了价格,咱们或许想知道买方要求的股票数量(出价巨细)或卖方的报价(要价巨细)。这些数据能够在极端细微的层次上供给(一般称为tick数据),也能够汇总成摘要数据(一般称为条形)。

咱们何时和多长时刻得到更新,以及多少前史数据?

让咱们考虑一下时刻维度。咱们处理的是每日数据,但咱们能得到多少天的数据?你能得到的前史数据越多,关于剖析曩昔的趋势和影响就越有价值,所以咱们要尽或许地回到曩昔,在商场上寻觅信息。

现在咱们也能够经过缩小时刻维度来改动它。与其每天看数据,咱们能够每小时看一次,或每15分钟看一次,或每分钟看一次。咱们乃至或许想看每一次的数据更新。事实证明,每天的数据是很简单得到的,但更细化的数据却很难免费得到。

在时刻维度上,咱们还应该考虑数据交给的速度。关于这篇文章,咱们只看前史数据,但关于软件或人需求对数据做出反响的用例,数据越早到达,就越有价值。

数据的质量怎么?

质量关于金融数据也非常重要。假如数据缺失或不精确,或许会产生不正确的成果。一般状况下,数据剖析会保证数据是合理的,但检测全部的过错或许是非常困难的。

一个好的数据要看一看

现在,让咱们先来看看股票代码为SPY的买卖所买卖基金(ETF)的一些前史数据。SPY有点特别。SPY不是一家公司的股票,而是一种特殊的东西,大致反映了整个标普500指数的价值。这个指数中有大约500家最大的美国上市公司的股票,并且这个指数会定期更新。假如公司是盈利的(大部分),并且大致在市值前500名的公司,就会被纳入该指数。ETF的价格在一个正常的买卖日期间,将以归纳股票乘以其指数权重的相同速度上下动摇(大致如此)。咱们现在运用它的主要原因是,它是一个很好的办法,能够(免费)粗略了解美国股市在一年中任何一天的体现。它还具有高度的流动性,所以精确的价格简直总是可用的,许多商场参与者乐意在任何时候购买和出售它。

一个数据源

获取前史价格数据有多种途径,我曾经写过 一些。关于这篇文章,我将运用Alpha Vantage,一个金融商场数据的供货商。你能够取得一个免费的API密钥,自己跟着做。

请留意,我不会在这儿(或其他地方)向你供给这些数据,由于我并不具有这些数据。一般来说,当你想与金融数据打交道时,你将需求找到一家被授权向你供给这些信息的公司。前史上越是完好、精确和精确的信息,你将期望必须支付更多的费用来取得这些信息的运用。就本文而言,这些数据是相当普遍的,所以你能够免费取得它。

下载前史数据

我会在Alpha Vantage答应的规模内取得尽或许多的SPY ETF的前史数据。你能够阅览Alpha Vantage的文档,看看其他的选项,但现在,咱们仅仅查询他们的每日时刻序列数据。

import io
import pandas as pd
import requests
import matplotlib.pyplot as plt
API_KEY='demo' # replace with your API_KEY from Alpha Vantage

数据能够用CSV(逗号分隔值)或JSONJavaScript目标符号)格局从Alpha Vantage获取。 咱们先来看看CSV。你经过对他们的服务端点进行HTTP调用来获取成果。假如咱们依照他们的主张运用requests 库,成果会以字节的办法存储在content 变量中。咱们能够把它变成一个字符串,然后检查前几行,看看数据是什么姿态。

# full history of daily data
function = "TIME_SERIES_DAILY_ADJUSTED" # daily data
outputsize = "full"                     # all of it
datatype = "csv"                        # CSV - comma separated values
url = f"https://www.alphavantage.co/query?function={function}&symbol=SPY&outputsize=full&apikey={API_KEY}&datatype={datatype}"
res = requests.get(url)
# the CSV file content is all available in the reponse
res.content.decode().split("\r\n")[0:2]
['timestamp,open,high,low,close,adjusted_close,volume,dividend_amount,split_coefficient', '2021-11-29,464.07,466.56,461.73,464.6,464.6,82666545,0.0000,1.0']

由于该服务首要回来最近的数据,咱们将运用pandas解析csv,并保证咱们对索引进行排序,以便最早的数据在咱们的DataFrame 。咱们需求给read_csv 一些提示,告知它将榜首列解析为日期时刻数据,然后将该列作为DataFrame 的索引。

由于最近的一行是榜首个元素,咱们也将经过它的索引对DataFrame 进行排序,由于咱们期望数据按时刻顺序排列。

留意我在这儿也运用了io.StringIO ,由于我已经把数据都放在了内存中。稍后你会看到,假如咱们想的话,彻底能够在pandas中更快地完结这全部。

你有关于pandas索引的问题吗?你能够从这儿开端了解他们的全部。

spy_daily = pd.read_csv(io.StringIO(res.content.decode()),
                        parse_dates=['timestamp'],
                        index_col='timestamp').sort_index()
spy_daily.head()
                  open        high         low       close  adjusted_close  \
timestamp                                                                    
1999-11-01  136.500000  137.000000  135.562500  135.562500       90.318326   
1999-11-02  135.968704  137.250000  134.593704  134.593704       89.672867   
1999-11-03  136.000000  136.375000  135.125000  135.500000       90.276685   
1999-11-04  136.750000  137.359299  135.765594  136.531204       90.963724   
1999-11-05  138.625000  139.109299  136.781204  137.875000       91.859026   
             volume  dividend_amount  split_coefficient  
timestamp                                                
1999-11-01  4006500              0.0                1.0  
1999-11-02  6516900              0.0                1.0  
1999-11-03  7222300              0.0                1.0  
1999-11-04  7907500              0.0                1.0  
1999-11-05  7431500              0.0                1.0  

咱们能够看到,Alpha Vantage给咱们供给的数据能够一向追溯到1999年,不错!咱们有20多年的数据。具有超越20年的数据是很有帮助的。

正如我之前所说,咱们能够在pandas中一步完结这些作业(也便是说,不需求运用requests 库或StringIO ),只需将网址传到上面的read_csv 调用中,像这样。

spy_daily = pd.read_csv(url, parse_dates=['timestamp'], index_col='timestamp').sort_index()
spy_daily.tail()
              open     high     low   close  adjusted_close     volume  \
timestamp                                                                
2021-11-22  470.89  473.540  467.35  467.57          467.57   72761954   
2021-11-23  467.22  469.095  464.45  468.19          468.19   73206538   
2021-11-24  466.06  469.570  465.19  469.44          469.44   61858813   
2021-11-26  462.34  463.900  457.77  458.97          458.97  112669636   
2021-11-29  464.07  466.560  461.73  464.60          464.60   82666545   
            dividend_amount  split_coefficient  
timestamp                                       
2021-11-22              0.0                1.0  
2021-11-23              0.0                1.0  
2021-11-24              0.0                1.0  
2021-11-26              0.0                1.0  
2021-11-29              0.0                1.0  
spy_daily.dtypes
open                 float64
high                 float64
low                  float64
close                float64
adjusted_close       float64
volume                 int64
dividend_amount      float64
split_coefficient    float64
dtype: object

Pandas留意到了榜首个参数是一个URL,获取了成果,然后将数据转化为DataFrame 。它乃至将数据转化为有用类型。

那JSON呢?

由于数据也是以JSON格局供给的,让咱们利用这个时机看看怎么将JSON数据也读到DataFrame

datatype = "json"   # everything else the same, but let's get JSON instead
url = f"https://www.alphavantage.co/query?function={function}&symbol=SPY&outputsize=full&apikey={API_KEY}&datatype={datatype}"
res = requests.get(url)

回来的数据与csv格局有一些不同。它是一个有两个成员的JSON目标。榜首个是一些元数据,咱们在上面的csv格局中没有得到。请留意,数据的时刻戳是US/Eastern ,美国的证券买卖所就在那里。

res.json().keys()
dict_keys(['Meta Data', 'Time Series (Daily)'])
res.json()['Meta Data']
{'1. Information': 'Daily Time Series with Splits and Dividend Events',
 '2. Symbol': 'SPY',
 '3. Last Refreshed': '2021-11-29',
 '4. Output Size': 'Full size',
 '5. Time Zone': 'US/Eastern'}
res.json()['Time Series (Daily)']['2021-11-22']
{'1. open': '470.89',
 '2. high': '473.54',
 '3. low': '467.35',
 '4. close': '467.57',
 '5. adjusted close': '467.57',
 '6. volume': '72761954',
 '7. dividend amount': '0.0000',
 '8. split coefficient': '1.0'}

由于时刻序列中的每个元素都是单日的,所以数值是以DataFrame的时刻序列索引为导向。咱们能够运用pandasDataFrame.from_dict 办法,从这些值中创立一个有用的DataFrame 。你需求保证你将数据的方向定为index 。默许选项是columns ,它假定每个目标是一整列数据。而咱们得到的是每一行的一个目标,关键是索引,在咱们的比如中是日期。

spy_daily = pd.DataFrame.from_dict(res.json()['Time Series (Daily)'], orient='index')
spy_daily.head()
           1. open  2. high  3. low 4. close 5. adjusted close  6. volume  \
2021-11-29  464.07   466.56  461.73    464.6             464.6   82666545   
2021-11-26  462.34    463.9  457.77   458.97            458.97  112669636   
2021-11-24  466.06   469.57  465.19   469.44            469.44   61858813   
2021-11-23  467.22  469.095  464.45   468.19            468.19   73206538   
2021-11-22  470.89   473.54  467.35   467.57            467.57   72761954   
           7. dividend amount 8. split coefficient  
2021-11-29             0.0000                  1.0  
2021-11-26             0.0000                  1.0  
2021-11-24             0.0000                  1.0  
2021-11-23             0.0000                  1.0  
2021-11-22             0.0000                  1.0  
spy_daily.index
Index(['2021-11-29', '2021-11-26', '2021-11-24', '2021-11-23', '2021-11-22',       '2021-11-19', '2021-11-18', '2021-11-17', '2021-11-16', '2021-11-15',       ...       '1999-11-12', '1999-11-11', '1999-11-10', '1999-11-09', '1999-11-08',       '1999-11-05', '1999-11-04', '1999-11-03', '1999-11-02', '1999-11-01'],
      dtype='object', length=5556)

但咱们还没有完结。首要,索引还没有被解析为一个日期,留意它的dtype 是目标。不过咱们能够很简单地处理这个问题。在pandas中咱们有几个转化类型的选项,我将运用to_datetime

spy_daily = spy_daily.set_index(pd.to_datetime(spy_daily.index)).sort_index()

咱们要整理的第二件事是列名。你能够运用重命名办法来做这件事,咱们只需供给一个函数,接收旧的列名并回来一个新的。假如咱们在空格上分割旧名称,删去榜首个符号,并用下划线衔接剩下的符号,咱们能够创立与csv格局相同的列。

def convert_name(name):
    tokens = name.split()
    return "_".join(tokens[1:])
convert_name("1. open") # see how this works?
'open'
# normally, I'd do this in one go like this: spy_daily.rename(columns=lambda c: "_".join(c.split()[1:]))
spy_daily = spy_daily.rename(columns=convert_name) 
spy_daily.head()
                  open        high         low       close adjusted_close  \
1999-11-01       136.5       137.0    135.5625    135.5625  90.3183258389   
1999-11-02  135.968704      137.25  134.593704  134.593704  89.6728668602   
1999-11-03       136.0     136.375     135.125       135.5  90.2766853014   
1999-11-04      136.75  137.359299  135.765594  136.531204  90.9637235227   
1999-11-05     138.625  139.109299  136.781204     137.875  91.8590257264   
             volume dividend_amount split_coefficient  
1999-11-01  4006500          0.0000               1.0  
1999-11-02  6516900          0.0000               1.0  
1999-11-03  7222300          0.0000               1.0  
1999-11-04  7907500          0.0000               1.0  
1999-11-05  7431500          0.0000               1.0  

最终,你看到JSON数据是以字符串格局呈现的。仔细看看这些数据。假如你开端运用DataFrame ,你很快就会发现它的行为并不正常。

spy_daily.dtypes
open                 object
high                 object
low                  object
close                object
adjusted_close       object
volume               object
dividend_amount      object
split_coefficient    object
dtype: object

假如咱们不把这些值转化为数字类型,咱们就会有问题。在某些状况下,你会得到一个答案(将是过错的),或许仅仅一个过错。比如说。

spy_daily['high'].max()
'99.879997'

这是一个字符串,必定不是SPY的最高价格。咱们需求将其转化为一个数字值。同样,你能够在这篇文章中阅览更多关于pandas的类型转化,可是一个简略的办法是在每一列上运用to_numeric

for c in spy_daily.columns:
    spy_daily[c] = pd.to_numeric(spy_daily[c])
spy_daily.dtypes
open                 float64
high                 float64
low                  float64
close                float64
adjusted_close       float64
volume                 int64
dividend_amount      float64
split_coefficient    float64
dtype: object

咱们什么时候能够运用这些数据?

与仅仅运用csv格局相比,这看起来有许多额定的作业,可是我选择了这两种办法,所以你能够看到只需求花一点功夫就能够处理不同的数据源格局。请留意,pandas也有一个read_json 办法,能够用于从JSON源创立DataFrame ,可是由于这个数据的实践数据埋藏在目标的深处,所以运用上面的办法更有意义。就像pandas的状况相同,有不止一种办法能够做!或许你能找到一个更好的办法来做。

初始验证

一般状况下,快速验证价格数据的最好办法之一便是直接看它。运用DataFrame.plot ,是快速完结这一作业的好办法。

spy_daily[['open', 'high', 'low', 'close']].plot()

用 Pandas 进行金融市场数据分析

完好数据集的SPY高点、低点、开盘、收盘图

首要,咱们能够看到咱们的数据能够追溯到2020年,它是连续的,并且依据咱们之前看到的状况,看起来很像SPY的价格。我制作了全部4个价格(开盘价、最高价、最低价和收盘价),以保证数据中没有任何0或张狂的不精确的价格。数据中也没有显着的缺口,所以这是一个好兆头。

假如数据缺失,你会看到两个日期之间有一条直线(只要差距满足大)。假如有野生值,如0或无穷大,你必定会在图上留意到这一点。

咱们能够编写整本关于数据验证的书,所以现在咱们将继续了解数据。

柱状图,或称蜡烛图

经过上面的图表,你能够看到很难分辨出四条线之间的区别。即便仅仅几天,当全部四条线都显现出来时,也不是彻底清晰的阅览。

spy_daily[-20:][['high', 'low', 'open', 'close']].plot()

用 Pandas 进行金融市场数据分析

咱们能够用一种更有用的办法来显现数据,一般称为条形图,或蜡烛图。在我的专业经验中,我一向把价格数据的滚动时刻段称为条形,但它们也常常被称为蜡烛,由于它们在制作时的姿态。咱们能够运用matplotlib的条形图轻松地做到这一点。

假如价格在当天上涨,每个条形图的色彩为绿色,假如下跌,则为赤色。柱状图的 “烛台 “部分是以开盘价和收盘价为界。蜡烛的 “烛芯 “部分以最高价和最低价为界限。从这张图中,你能够很快看到每天发生了什么–也便是说,价格在这一天中是否有很大的动摇?它是否有一个广泛的规模,但在开盘和收盘之间的移动很少?价格是上升仍是下降?

def plot_bars(bars, show_lines=False):
    plt.figure(figsize=(10,8))
    # pick the up (or green) bars
    up = bars.loc[bars['close'] >= bars['open']]
    # pick the down (or red) bars
    down = bars.loc[bars['close'] < bars['open']]
    # both up and down periods will have a thin bar between
    # the high and low, the "wick" of the candle
    plt.bar(up.index, up.high - up.low, bottom=up.low, color="green", width=0.05)
    plt.bar(down.index, down.high - down.low, bottom=down.low, color="red", width=0.05)
    # then, we plot the thicker candle part. 
    plt.bar(up.index, up.close - up.open, bottom=up.open, color="green", width=0.25)
    plt.bar(down.index, down.open - down.close, bottom=down.close, color="red", width=0.25)
    plt.xticks(rotation=45)
    plt.title(f'Price of SPY from {bars.index[0]:%Y-%m-%d} to {bars.index[-1]:%Y-%m-%d}')
    if show_lines:
        plt.plot(bars['high'], color='green', alpha=0.25, label='high')
        plt.plot(bars['low'], color='red', alpha=0.25, label='low')
        plt.plot(bars['open'], color='black', ls=':', alpha=0.25, label='open')
        plt.plot(bars['close'], color='black', ls='--', alpha=0.25, label='close')
        plt.legend()
plot_bars(spy_daily.iloc[-20:])

用 Pandas 进行金融市场数据分析

现在这不是更好吗?这需求一点操练来快速阅览,但一目了然,信息量更大。假如你把高点/低点/开盘/收盘显现成线,你能够看到它们与蜡烛上的点是怎么对应的(并且条形图比线更清晰)。

plot_bars(spy_daily.iloc[-20:], show_lines=True)

用 Pandas 进行金融市场数据分析

为了清晰起见,假如收盘价高于开盘价,条形图将是绿色的。假如收盘价低于开盘价,它将是赤色的。而条形图中较细的部分显现的是当天的最高和最低价格。

现在咱们有超越20年的SPY价格能够看,每个买卖日都有一个单条,就像上面的数值。作为一个操练,你能够把更多的数据制作成条状。

季节性

为了保持简略,咱们将在本文中只看季节性的主见,咱们将只运用一天结束时的价格,收盘价。现在,咱们也将忽略股息和闰年。

首要,让咱们谈谈什么是季节性。季节性背后的主见是,存在某种有规则的季节性形式比影响股票价格。假如存在季节性影响,咱们认为能够经过调查全部年份的均匀报答率来感受一下,看看报答率在一年的不同阶段是否有不同的趋势。

报答

咱们需求做的榜首件事是取得SPY的报答。咱们这样做是由于比较各年的价格是没有意义的。咱们想看到的是SPY的百分比变化,而不是价格的差异。有多种办法来核算报答率,但在pandas中核算报答率百分比的一个简略办法是运用pct_change

spy_daily['daily_return'] = spy_daily['close'].pct_change()
spy_daily.head()
                  open        high         low       close  adjusted_close  \
1999-11-01  136.500000  137.000000  135.562500  135.562500       90.318326   
1999-11-02  135.968704  137.250000  134.593704  134.593704       89.672867   
1999-11-03  136.000000  136.375000  135.125000  135.500000       90.276685   
1999-11-04  136.750000  137.359299  135.765594  136.531204       90.963724   
1999-11-05  138.625000  139.109299  136.781204  137.875000       91.859026   
             volume  dividend_amount  split_coefficient  daily_return  
1999-11-01  4006500              0.0                1.0           NaN  
1999-11-02  6516900              0.0                1.0     -0.007146  
1999-11-03  7222300              0.0                1.0      0.006734  
1999-11-04  7907500              0.0                1.0      0.007610  
1999-11-05  7431500              0.0                1.0      0.009842  

你能够看到,daily_return 列有每天的价格增减百分比。咱们能够运用cumsum 办法来检查一段时刻内的总报答率是什么样的。

spy_daily['daily_return'].cumsum().plot()

用 Pandas 进行金融市场数据分析

现在咱们有了简略的百分比报答,咱们看到图表从0开端,然后上升到150%以上的报答。这模仿了上面的价格图,但咱们现在能够把咱们的年份放在上面。做到这一点的一个办法是,只看一年中每一天的均匀报答。

咱们该怎么做呢?首要,咱们能够从咱们的指数中的日期得到一年中的哪一天。

spy_daily.index.day_of_year
Int64Index([305, 306, 307, 308, 309, 312, 313, 314, 315, 316,
            ...
            319, 320, 321, 322, 323, 326, 327, 328, 330, 333],
           dtype='int64', length=5556)

下一步是对咱们的报答进行分组,使每年的榜首天在一起,每年的第二天,以此类推。这便是DataFrame.groupby 办法所做的。它为传入函数的每一个值建立一个组,并能够对该组应用聚合函数。咱们能够经过运用mean ,只看daily_return ,得到整个数据会集当年那一天的均匀日收益。

spy_daily.groupby(spy_daily.index.day_of_year).mean()['daily_return']
2      0.006570
3      0.004355
4     -0.002164
5     -0.001901
6      0.000482
         ...   
362   -0.000548
363    0.001660
364   -0.002844
365   -0.000749
366    0.008551
Name: daily_return, Length: 365, dtype: float64

这仅仅给了咱们一个单一的系列,一年中的每一天都包含了均匀值。请留意,数据从第2天开端,由于股票商场每年元旦都会关闭。它有366天,由于有闰年(我之前说过会忽略这一点)。现在咱们能够制作均匀每日报答的累积总和,看看均匀数是什么姿态的。

spy_daily.groupby(spy_daily.index.day_of_year).mean()['daily_return'].cumsum().plot()

用 Pandas 进行金融市场数据分析

嗯,这看起来很风趣。好像年头的报答率很低,春天的报答率很高,秋天的报答率很低,而年末的报答率很高。

看数据的另一个风趣的办法是看每月的均匀报答。咱们能够再次用groupby ,但运用柱状图更有意义。

spy_daily.groupby(spy_daily.index.month).mean()['daily_return'].plot.bar()

用 Pandas 进行金融市场数据分析

在这儿,看起来9月是一个可怕的月份,而4月是巨大的。

现在股票收益或许有非常大的离群值,这些必定会影响成果,所以运用均匀值或许不是最好的主见。这些反常值也很难(不或许)猜测,大多数投资者不会无法防止坏的反常值而参与好的反常值。看看中位数报答是什么姿态的,或许更有意义。

spy_daily.groupby(spy_daily.index.month).median()['daily_return'].plot.bar()

用 Pandas 进行金融市场数据分析

从中位数报答来看,咱们能够看到每个月都有正的中位数报答,除了9月。看起来确实或许有一点季节性的影响,但没有像看均匀值那样显着。

这意味着什么呢?

现在咱们不会从这个快速的剖析中得出任何定论,可是股票报答的季节性一般被讨论,有些人说你应该在5月卖掉你的股票,比及10月再入市。咱们乃至能够看到这样的观念:5月、6月和9月的报答率不如一年中的其他时刻强劲。但这仅仅均匀水平,一年中仍有正的报答(其间7月和8月相当高)。假如你卖掉你的股票,并在10月份重新买入,你会失掉全部这些报答,别的你还必须支付买卖成本来进出商场。

或许咱们能够看看每一年的数据,看看是否有任何年份倾向于杰出,这样咱们就能够了解这些年份的反常值是什么?咱们能够经过迭代各年的数据,用布尔表达式抓取该年的部分DataFrame ,并制作该年的报答率来做到这一点。你能够在这儿阅览更多关于布尔索引的信息。

for year in spy_daily.index.year.unique():
    sub = spy_daily.loc[spy_daily.index.year == year]
    plt.plot(sub.index.day_of_year, sub['daily_return'].cumsum())

用 Pandas 进行金融市场数据分析

让我印象深入的是那些有很大跌幅的年份。上升的大峰值较少。(这符合关于股票的古老谚语,它是一个向上的扶梯,但也是一个向下的电梯)。让咱们来看看这些是什么。假如咱们做一个简略的函数来寻觅某一年的最低累计报答值,咱们就能够看到上面的图中有哪些年份的低点。

def min_return(rets):
    # get the index of the minimum value, and the value itself
    return rets.loc[rets.idxmin()], rets.idxmin()
for year in spy_daily.index.year.unique():
    sub = spy_daily.loc[spy_daily.index.year == year]
    minimum, dt = min_return(sub['daily_return'].cumsum())
    print(f"{year} {minimum * 100:6.2f}% on {dt:%Y-%m-%d}")
1999  -0.71% on 1999-11-02
2000 -12.35% on 2000-12-20
2001 -28.00% on 2001-09-21
2002 -35.37% on 2002-10-09
2003  -8.74% on 2003-03-11
2004  -3.64% on 2004-08-06
2005  -5.85% on 2005-04-20
2006  -1.32% on 2006-06-13
2007  -2.93% on 2007-03-05
2008 -59.01% on 2008-11-20
2009 -26.86% on 2009-03-09
2010  -7.63% on 2010-07-02
2011 -11.63% on 2011-10-03
2012   1.59% on 2012-01-03
2013   2.22% on 2013-01-08
2014  -5.77% on 2014-02-03
2015  -8.72% on 2015-08-25
2016 -10.61% on 2016-02-11
2017   0.77% on 2017-01-03
2018 -11.66% on 2018-12-24
2019  -2.28% on 2019-01-03
2020 -33.64% on 2020-03-23
2021  -1.36% on 2021-01-04

好吧,咱们能够看到2001年和2002年(科技泡沫),2008年、2009年(大金融危机),以及2020年(Covid)都在这儿杰出。让咱们看看这些东西本身是什么姿态的。

for year in [2020, 2001, 2002, 2008, 2009]:
    sub = spy_daily[f"{year}":f"{year}"]
    plt.plot(sub.index.day_of_year, sub['daily_return'].cumsum(), label=year)
plt.legend()

用 Pandas 进行金融市场数据分析

因此,咱们能够把2008年、2009年和2020年这几个大的反常年份从咱们先前的成果中删去,仅仅为了看看 “正常 “的季节性是什么,特别是在日历年的开端和结束。请留意,在建立买卖模型时,这不是一个好主见,但现在咱们仅仅试图探究和了解数据。我在pandas中经过运用另一个布尔表达式来做到这一点,但运用逆运算符~isin 来撤销选择这些年份的全部值。

spy_daily_red = spy_daily.loc[~spy_daily.index.year.isin([2001, 2002, 2008, 2019, 2020])]
spy_daily_red.groupby(spy_daily_red.index.day_of_year).mean()['daily_return'].cumsum().plot()

用 Pandas 进行金融市场数据分析

现在,这就更顺利了。留意到报答仅仅有点向上和向右移动,没有任何向上或向下的趋势?有了这些信息,存在继续的多月季节性的主见好像不像曾经那样站得住脚。

用这个减少的数据集看每月的成果怎么呢?

spy_daily_red.groupby(spy_daily_red.index.month).mean()['daily_return'].plot.bar()

用 Pandas 进行金融市场数据分析

风趣的是,即便去掉最糟糕的年份,9月和6月的均匀利润仍然不高。

咱们能够从这儿做什么?

咱们不打算从这个简短的探究中得出清晰的定论,为投资或买卖的决策供给参阅,但这个开始的调查能够把作业推向一些风趣的方向。或许你在阅览这篇文章时想到了一些问题,你想考虑一下你能够探究的其他信息。

更多数据

假如你能得到更多的前史数据,这将是很有价值的。在咱们的免费数据会集,咱们只能追溯到20年前,但假如有更多的前史数据,咱们或许能看到更多显现季节性的一致的月份。或许曩昔的作用更强,咱们能够比较不同的几十年。尽管咱们能够用现在的数据做一些作业,但假如有更多的数据,咱们会更有决心。

另一个选择是取得更细化的数据,或许是以1分钟或1小时为单位。这将使咱们能够研讨日内的季节性,是否有一天中的某些时刻,商场倾向于比其他时刻更简单上涨?或许用咱们现在的数据,或许季节性是在每月的基础上可见的?许多月度事情影响商场,包含重要数据的发布或月初和月底存入银行账户的薪酬。在年度基础上,缴税和分配退税会影响商场。在未来的文章中,我将研讨这些主见中的一些。

假如你喜爱这篇文章,请注册我的通讯,当我发布新的文章时,我会告知你。

The postFinancial market data analysis with pandasappeared first onwrighters.io.