用聚类算法计算股票的支撑位和阻力位

来源:Python中文社区

本文将向您展示如何使用不同的聚类算法计算股票支撑位和阻力位。

股票数据 - 我在 mongoDB 数据库中有股票数据。您还可以免费从雅虎财经获取这些数据。

Python 连接 MongoDB 设置

In [1]:
import pymongo
from pymongo import MongoClient
client_remote = MongoClient('mongodb://localhost:27017')
db_remote = client_remote['stocktdb']
collection_remote = db_remote.stock_data

从 MongoDB 获取股票数据

我将使用过去 60 天的 Google 公司股票 数据进行分析。

In [2]:
mobj = collection_remote.find({'ticker':'GOOGL'}).sort([('_id',pymongo.DESCENDING)]).limit(60)

为数据分析准备数据

我将使用 Pandas 和 Numpy 进行数据操作。让我们首先从 Mongo Cursor 对象获取数据到 Python 列表。

In [3]:
prices = []
for doc in mobj:
    prices.append(doc['high'])

K-means聚类计算股票支撑位和阻力位

In [4]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import AgglomerativeClustering

对于 K-means聚类,我们需要将数据转换为 Numpy 数组格式。

In [5]:
X = np.array(prices)

对于K-means聚类来说,K-means聚类的数量非常重要。我们可以使用膝图找到最佳 K值,如下所示。

In [6]:
from sklearn.cluster import KMeans
import numpy as np
from kneed import KneeLocator

sum_of_sq_distances = []
K = range(1,10)
for k in K:
    km = KMeans(n_clusters=k)
    km = km.fit(X.reshape(-1,1))
    sum_of_sq_distances.append(km.inertia_)
kn = KneeLocator(K, sum_of_sq_distances,S=1.0, curve="convex", direction="decreasing")
kn.plot_knee()

ecf137bc6db4d159eb017c07c5b28b3b.png

让我们使用 kn.knee 检查 K 的值

In [7]:
kn.knee
Out[7]:
3
In [8]:
kmeans = KMeans(n_clusters= kn.knee).fit(X.reshape(-1,1))
c = kmeans.predict(X.reshape(-1,1))
min_and_max = []
for i in range(kn.knee):
    min_and_max.append([-np.inf,np.inf])
for i in range(len(X)):
    cluster = c[i]
    if X[i] > min_and_max[cluster][0]:
        min_and_max[cluster][0] = X[i]
    if X[i] < min_and_max[cluster][1]:
        min_and_max[cluster][1] = X[i]

让我们检查聚类的最小值和最大值。

In [9]:
min_and_max
Out[9]:
[[2461.9099, 2365.55], [2687.98, 2508.0801], [2357.02, 2239.4399]]

上面显示了3个簇,每个簇都有最大值和最小值。

在写本文的时候,谷歌的股价是2687.98(当日最高点),正好也是52周来的最高点。因此,基于上述聚类,我们可以说2687.98是阻力位,下一个支撑水平是2508.0801。下一个支持级别是2461.90992365.552357.022239.4399

记住,这些支撑位和阻力位将根据数据范围和聚类参数K的值而变化。

用层次聚类计算股票支撑位和阻力位

In [10]:
mobj = collection_remote.find({'ticker':'GOOGL'}).sort([('_id',pymongo.DESCENDING)]).limit(60)
prices = []
for doc in mobj:
    prices.append(doc['high'])

另一种可以使用的方法是凝聚聚类,即层次聚类。

凝聚聚类是一种自底向上的方法,它将子聚类合并以找出大的数据聚类。

层次聚类对股票滚动数据很有用。

让我们创建一个20天的滚动数据,用于计算最大值和最小值。

In [11]:
df = pd.DataFrame(prices)
max = df.rolling(20).max()
max.rename(columns={0: "price"},inplace=True)
min = df.rolling(20).min()
min.rename(columns={0: "price"},inplace=True)

需要以下步骤以两列格式准备数据。

In [12]:
maxdf = pd.concat([max,pd.Series(np.zeros(len(max))+1)],axis = 1)
mindf = pd.concat([min,pd.Series(np.zeros(len(min))+-1)],axis = 1)    
maxdf.drop_duplicates('price',inplace = True)
mindf.drop_duplicates('price',inplace = True)

让我们使用n_clusters=3值来表示聚类数量。

In [13]:
F = maxdf.append(mindf).sort_index()
F = F[ F[0] != F[0].shift() ].dropna()

# Create [x,y] array where y is always 1
X = np.concatenate((F.price.values.reshape(-1,1),
                    (np.zeros(len(F))+1).reshape(-1,1)), axis = 1 )

cluster = AgglomerativeClustering(n_clusters=3,
          affinity='euclidean', linkage='ward')
cluster.fit_predict(X)
F['clusters'] = cluster.labels_

F2 = F.loc[F.groupby('clusters')['price'].idxmax()]

# Plotit
fig, axis = plt.subplots()
for row in F2.itertuples():

    axis.axhline( y = row.price, 
            color = 'green', ls = 'dashed' )

axis.plot( F.index.values, F.price.values )
plt.show()

5e306866239dac4644a7a10fa041b799.png

现在让我们绘制聚类。如下图所示,找到了两个聚类。如果考虑到谷歌今天的收盘价2638.00,我们可以说2687.98是阻力位,2357.02是支撑位。

In [14]:
F2
Out[14]:

b4840010d0f2dad0ec47f20ffea15695.png

这里需要注意的一点是,只有2个聚类的价格是2357.02,这并不是很多。要查看是否可以找到更多的聚类,我们必须增加源数据中的价格点数量,或者增加聚类数量,或者缩小滚动窗口。

让我们将聚类的数量增加到5,看看会发生什么。

In [15]:
F = maxdf.append(mindf).sort_index()
F = F[ F[0] != F[0].shift() ].dropna()

# Create [x,y] array where y is always 1
X = np.concatenate((F.price.values.reshape(-1,1),
                    (np.zeros(len(F))+1).reshape(-1,1)), axis = 1 )

cluster = AgglomerativeClustering(n_clusters=5,
          affinity='euclidean', linkage='ward')
cluster.fit_predict(X)
F['clusters'] = cluster.labels_

F2 = F.loc[F.groupby('clusters')['price'].idxmax()]

# Plotit
fig, axis = plt.subplots()
for row in F2.itertuples():

    axis.axhline( y = row.price, 
            color = 'green', ls = 'dashed' )

axis.plot( F.index.values, F.price.values )
plt.show()

b49b71cf2171221e232de2943defe6fc.png

In [16]:
F2
Out[16]:

ca7f0589750a557b6eb794b686dd9352.png

好的,这次我们以2239.43的价格获得了更多的聚类,这与今天2638的收盘价相去甚远。然而,基于3个聚类,阻力值看起来不错,为2687.98

让我们把滚动窗口缩小一点。与其说是20天,不如说是10天。

In [17]:
df = pd.DataFrame(prices)
max = df.rolling(10).max()
max.rename(columns={0: "price"},inplace=True)
min = df.rolling(10).min()
min.rename(columns={0: "price"},inplace=True)
maxdf = pd.concat([max,pd.Series(np.zeros(len(max))+1)],axis = 1)
mindf = pd.concat([min,pd.Series(np.zeros(len(min))+-1)],axis = 1)    
maxdf.drop_duplicates('price',inplace = True)
mindf.drop_duplicates('price',inplace = True)
F = maxdf.append(mindf).sort_index()
F = F[ F[0] != F[0].shift() ].dropna()

# Create [x,y] array where y is always 1
X = np.concatenate((F.price.values.reshape(-1,1),
                    (np.zeros(len(F))+1).reshape(-1,1)), axis = 1 )

cluster = AgglomerativeClustering(n_clusters=5,
          affinity='euclidean', linkage='ward')
cluster.fit_predict(X)
F['clusters'] = cluster.labels_

F2 = F.loc[F.groupby('clusters')['price'].idxmax()]

# Plotit
fig, axis = plt.subplots()
for row in F2.itertuples():

    axis.axhline( y = row.price, 
            color = 'green', ls = 'dashed' )

axis.plot( F.index.values, F.price.values )
plt.show()

5e49622fe691bde1ce000aca968ba498.png

In [18]:
F2

bc01455efcf192980dd00603c9e3b4c6.png

好的,这个数据看起来好多了。Google的阻力值约为2687.98,支撑位约为2399.032412.8799,这与支撑位约为2400相当接近。

---------End---------

顺便给大家推荐下我的微信视频号「Python数据之道」,欢迎扫码关注。

705e38564fe58a927d9b3fc45a38d03b.gif

  • 0
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值