1. 程式人生 > 實用技巧 >Python資料分析之亞馬遜股價

Python資料分析之亞馬遜股價

今天用Python簡單分析一下亞馬遜上市至今的股價,沒有太多實質性的東西,但學學技術還可以。主要包括下面幾個方面:

  1. 畫股價走勢圖
  2. 計算年度收益率
  3. 用股價擬合多項式曲線並預測股價
  4. 畫K線圖

首先,匯入模組

import pandas as pd
import matplotlib.pylab as plt
import numpy as np
# 繪圖顯示中文
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

讀入檔案,預覽資料

data = pd.read_csv('./data/Amazon.csv')
data

資料包含亞馬遜1997年5月到今年7月底的股價,共5842條。

來看看上市至今的股價走勢

# 整體走勢
data.plot(x='Date', y='Close', rot=30, figsize=(15, 8), title='amazon股價')

這個漲勢太厲害了,上市至今暴漲了1600倍。

再來看看每年的收益率,先增加年份列,然後按照該列分組,用當年的第一天和最後一天的收盤價計算漲跌幅。

# 計算每年收益率
data['year'] = data['Date'].apply(lambda x: x[:4])

def get_rate_of_change(group):
    price1 = group.sort_values(by='Date')[:1]['Close']
    price2 = group.sort_values(by='Date', ascending=False)[:1]['Close']
    
    return (price2.values[0] / price1.values[0] - 1) * 100

data.groupby('year').apply(get_rate_of_change).plot(kind='bar', rot=30, figsize=(15, 8), title='每年收益率')

大部分年份都是上漲的,尤其是上市後的第二年漲了將近10倍。當然也有些年份是跌的,只要長期持有都會轉正,但前提得是好股票。

既然股票收益率能達到如此高,那麼有沒有可能通過歷史股價的走勢來預測未來股價呢?下面我們就將2020年之前的股價作為樣本,擬合一個多項式函式,來預測2020年的股價,看看跟實際的差異。

我們先在資料集上增加一列,作為自變數x,收盤價Close列作為因變數y

# 計算Date列與1997-05-15相差的天數,作為自變數x
from datetime import datetime

start_date = datetime(1997, 5, 15)
def get_Date_diff(date1):
    date1_arr = date1.split('-')
    cur_date = datetime(int(date1_arr[0]), int(date1_arr[1]), int(date1_arr[2]))
    
    return (cur_date - start_date).days

data['day'] = data['Date'].apply(get_Date_diff)

# 2020年之前的作為擬合的樣本
data_before_2020 = data[data['Date'] < '2020-01-01']

data_2020 = data[data['Date'] >= '2020-01-01']

有了樣本後,我們用numpy模組的polyval函式進行擬合

# 對2020年之前的股價進行多項式擬合
x = data_before_2020['day'].values
y = data_before_2020['Close'].values
# 擬合
reg = np.polyfit(x, y, deg=15)
# 計算擬合後的值
y_predict = np.polyval(reg, x)

引數deg代表多項式的次數,如果是deg=2,最終擬合的多項式函式就是y = a*x^2 + b*x + c,函式返回值reg就是係數abc。上述程式碼裡deg=15,說明擬合了一個15次多項式函式,次數越高擬合的結果越接近樣本,當然要注意過擬合。

np.polyval函式可以根據給定的多項式係數和自變數x計算因變數y,即:預測值。

下面我們將實際股價和預測股價畫在同一個圖裡來觀察擬合的效果

plt.figure(figsize=(15, 8))
plt.plot(x, y, 'b')
plt.plot(x, y_predict, 'r.')
plt.xlabel('日期')
plt.ylabel('股價')
plt.show()

效果看起來還湊合,我們就可以用這個多項式來預測2020年股價

# 使用之前擬合的多項式預測2020年股價
x_2020 = data_2020['day'].values
y_2020 = data_2020['Close'].values
y_predict_2020 = np.polyval(reg, x_2020)

plt.figure(figsize=(15, 8))
plt.plot(x_2020, y_2020, 'b')
plt.plot(x_2020, y_predict_2020, 'r.')
plt.xlabel('日期')
plt.ylabel('股價')
plt.show()

可以看到,圖的右半部分預測股價(紅色虛線)明顯高於實際股價(藍線),這種方式預測股價還是不靠譜的。因為該方式只用了價格這一個因素,而影響股價的因素特別多,因此拋開其他因素單純看股票價格的波動是沒有規律的。

當然我們可以考慮一些優秀的機器學習模型或者深度學習模型來進行預測,但我覺得精確到天級的預測難度很大,並且意義也不大。但我們可以將問題簡化為預測趨勢,或者將預測結果作為一個資訊輔助人來做判斷。

進行到這裡貌似還不太過癮,那就畫個K線圖吧,說不定以後能用上。

# 畫K線圖
from pyecharts import options as opts
from pyecharts.charts import Kline, Line

def calculate_ma(day_count: int, prices):
    result: List[Union[float, str]] = []

    for i in range(len(prices)):
        if i < day_count:
            result.append("-")
            continue
        sum_total = 0.0
        for j in range(day_count):
            sum_total += float(prices[i - j][1])
        result.append(abs(float("%.2f" % (sum_total / day_count))))
    return result

x = data_2020['Date'].values.tolist()
y = data_2020[['Open', 'Close', 'Low', 'High']].values.tolist()


kline = (
    Kline()
    .add_xaxis(x)
    .add_yaxis(
        "kline",
        y,
        itemstyle_opts=opts.ItemStyleOpts(
            color="#ec0000",
            color0="#00da3c",
            border_color="#8A0000",
            border_color0="#008F28",
        ),
    )
    .set_global_opts(
        xaxis_opts=opts.AxisOpts(is_scale=True),
        yaxis_opts=opts.AxisOpts(
            is_scale=True,
            splitarea_opts=opts.SplitAreaOpts(
                is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1)
            ),
        ),
        datazoom_opts=[opts.DataZoomOpts(type_="inside")],
        title_opts=opts.TitleOpts(title="2020年K線圖"),
    )
)

kline_line = (
    Line()
    .add_xaxis(x)
    .add_yaxis(
        series_name="MA5",
        y_axis=calculate_ma(5, y),
        is_smooth=True,
        linestyle_opts=opts.LineStyleOpts(opacity=0.5),
        label_opts=opts.LabelOpts(is_show=False),
    )
    .set_global_opts(
        xaxis_opts=opts.AxisOpts(
            type_="category",
            grid_index=1,
            axislabel_opts=opts.LabelOpts(is_show=False),
        ),
        yaxis_opts=opts.AxisOpts(
            grid_index=1,
            split_number=3,
            axisline_opts=opts.AxisLineOpts(is_on_zero=False),
            axistick_opts=opts.AxisTickOpts(is_show=False),
            splitline_opts=opts.SplitLineOpts(is_show=False),
            axislabel_opts=opts.LabelOpts(is_show=True),
        ),
    )
)
# Overlap Kline + Line
overlap_kline_line = kline.overlap(kline_line)

overlap_kline_line.render_notebook()

這裡只用了2020年的資料進行繪製,看起來還像是那麼回事。這個圖包含兩部分,一部分是單純呼叫Kline繪製的K線圖,另一部分是呼叫Line繪製了一個折線圖,它的y座標呼叫calculate_ma函式,計算5日平均收盤價。最後呼叫overlap_kline_line = kline.overlap(kline_line)將二者合併在一起。

我的分析就到這裡了,感興趣的朋友可以自行分析。公眾號回覆關鍵字亞馬遜股價獲取資料和原始碼。

歡迎公眾號 「渡碼」