【问题标题】:Detecting areas in a Python dataset检测 Python 数据集中的区域
【发布时间】:2021-02-17 15:25:03
【问题描述】:

我正在尝试处理一个不应该太难解决的问题,但我很难找到解决方法。

基本上,我有一组 OHLC 数据:

>>print(df)

                       Open    High     Low   Close       Volume                Date
Date
2020-11-02 00:00:00  396.68  401.01  396.44  400.70  41468.48318 2020-11-02 00:00:00
2020-11-02 00:30:00  400.68  404.50  400.61  402.45  35209.25068 2020-11-02 00:30:00
2020-11-02 01:00:00  402.48  403.14  400.62  401.89  18107.53656 2020-11-02 01:00:00
2020-11-02 01:30:00  401.88  402.88  401.26  402.48  13852.17215 2020-11-02 01:30:00
2020-11-02 02:00:00  402.49  403.85  398.82  401.17  21853.35028 2020-11-02 02:00:00
...                     ...     ...     ...     ...          ...                 ...
2020-11-04 19:30:00  401.88  403.88  401.88  402.46  17944.49509 2020-11-04 19:30:00
2020-11-04 20:00:00  402.50  404.23  397.72  399.59  41674.44864 2020-11-04 20:00:00
2020-11-04 20:30:00  399.60  402.26  399.40  401.21  18606.38545 2020-11-04 20:30:00
2020-11-04 21:00:00  401.20  403.15  400.79  402.70  14408.66482 2020-11-04 21:00:00
2020-11-04 21:30:00  402.69  403.01  401.74  402.71   8873.15569 2020-11-04 21:30:00

给定一个可以为 10 的 固定 范围(因此从 350 到 360、351 到 361 等等)检测何时超过 N 根蜡烛在该范围内收盘。所以基本上这个范围需要“滑动”整个图表并找到符合我上面描述的标准的区域(超过 N 数量的蜡烛关闭在该范围内)。

这是一个视觉示例:

在这种情况下,白色盒子里有 6 支蜡烛,所以这就是我要找的,注意蜡烛必须穿过盒子,它只需要“开始“在那里。

我试图使其尽可能清晰和详细。我想发布更多代码,但我真的很难找到解决方法,尽管我很确定 Pandas、Numpy 或 scipy 应该很容易。谁能帮我找到这方面的方向?欢迎任何建议

【问题讨论】:

标签: python pandas numpy scipy


【解决方案1】:

您可以通过以下方式在 numpy 中找到区域:1) 制作一个整数 T/F 数组来标记区域中的点; 2)通过减去相邻点来查找步骤(进出区域)的位置; 3) 使用np.nonzero 查找步骤 2 中的边界。

这是一个示例(最后图中的绿色带标记了仅由从nonzero 返回的两个索引标识的区域):

import matplotlib.pyplot as plt
import numpy as np

# make some data
dmin, dmax = 0.3, 0.7
x = np.linspace(0, 100, 300)
data = 1 - 1/(1+np.exp(-(x-70)/2))

# do the three step above:
region = ((data>dmin) & (data<dmax)).astype(int)  # mark region with 1s and 0s
boundaries = region[1:] - region[:-1]  # calculate the boundaries to 1s and -1s corresponding to "into" and "out of", or use np.diff
indices = np.nonzero(boundaries)   # find the indices of the boundary points

fig, axs = plt.subplots(3, 1)
axs[0].plot(x, data)
axs[1].plot(x, region)
axs[2].plot(x[1:], boundaries)
axs[2].axvspan(x[indices[0][0]], x[indices[0][1]], facecolor='g', alpha=0.2)

为了找到大于某个长度的多个区域,循环遍历边界索引列表以构建边界对列表,这主要是记账和担心端点的问题(例如,如果你从地区等)。

这是一个执行此操作的示例。两个主要变化是:1)我将boundaries拆分为生成startsstops索引;并且,2)我计算large_rios

dmin, dmax = 0.3, 1000  # just look for being above a min: for multiple regions, make some data that oscillates and this is easier to visualize
minL = 10

# make up  some data
x = np.linspace(0, 98.5, 600)  # 98.5 so data ends in a region of interest, which is a case I wanted to check for
data0 = 1-np.exp(-(x-50)**2/400.)
data = 0.5 + 0.5*np.sin((1+1*(data0+1))*x)

rois = ((data>dmin) & (data<dmax)).astype(int) # roi = "region of interest"
boundaries = rois[1:] - rois[:-1]
starts = list(np.nonzero(boundaries>0)[0])  # starting points of roi, and make a list for easy insertion
stops = list(np.nonzero(boundaries<0)[0])   # stopping points of roi, and make a list for easy appending

if stops[0] < starts[0]: # if data starts in a roi, fix it
    starts.insert(0,0)

if starts[-1]>stops[-1]: # if data stops in a roi, fix it
    stops.append(len(data))

large_rois = [(start, stop) for (start, stop) in zip(starts, stops) if stop-start > minL]

print(large_rois)

fig, axs = plt.subplots(3, 1)
axs[0].plot(x, data)
axs[1].plot(x, rois)
axs[2].plot(x[1:], boundaries)
for (start, stop) in large_rois:
    axs[2].axvspan(x[start], x[stop], facecolor='r', alpha=0.4)

另外,请注意,我在列表中有一个循环,通常在使用 pandas 和 numpy 时,最好尽量避免这样的循环,但在这种情况下,循环不是通过所有数据,而只是端点列表,比原始数据短得多。

最后,请注意,与您尝试查找离散数据区域的所有问题一样,存在关于如何处理边界的问题,因此如果这很重要,请务必根据需要解决此问题。

【讨论】:

  • 这很有趣。万分感谢!我只是在理解如何将其应用于我自己的代码时遇到了麻烦。在我自己的情况下,我需要扫描整个数据集并找到超过 N 个关闭或蜡烛“结束”的区域
  • @JayK23:我编辑了答案以包括多个区域的情况并根据它们的长度选择它们。
  • 这是一个非常有趣的方法。 Numpy 和 Pandas 真的可以做很多事情!如果我有任何问题,我将尝试此代码并报告。非常感谢!
【解决方案2】:

您的描述有点模糊,但也许这会有所帮助:

假设您在一个名为 start 的 numpy 数组中有起点,找到这些点在 350 到 360 之间的位置:

np.where((start > 350) & (start < 360))

要查看这些是多少分:

len(np.where((start  >350) & (start  < 360))[0])

【讨论】:

  • 感谢您的回答!你能告诉我哪个部分含糊不清,以便我改进问题吗?这是一个开始!问题是我需要在整个数据集中搜索这些区域,因此范围需要在整个数据集中“移动”,例如:350-360、351-361 等等。我希望我不会太困惑
【解决方案3】:

我建议您在代码中添加一个循环。大概是这样的:

mini = df['close'].min()
maxi  = df['close'].max()

candles = []
for i in range(mini, maxi-10):
    n = len(df[df['Close'].between(i,i+10)])
    if n>=6:
        candles.append((mini, maxi, n))  

请您在您的 DataFrame 上尝试一下,看看它是否有效!

【讨论】:

  • 非常感谢!我试过了,但出现以下错误:TypeError: 'numpy.float64' object cannot be mapped as an integer
  • range(mini, maxi-10) -> range(int(mini), int(maxi-10))
  • TypeError: 'numpy.float64' 对象不能被解释为整数
  • 您可以将mini = df['close'].min() 更改为mini = int(df['close'].min()),类似于maxi。
猜你喜欢
  • 1970-01-01
  • 2018-05-15
  • 2017-02-25
  • 2016-09-30
  • 1970-01-01
  • 1970-01-01
  • 2021-03-09
  • 1970-01-01
  • 2014-01-06
相关资源
最近更新 更多