Numpy:如何检查一个数字是否是前K个数字中的最小值/最大值?

huangapple go评论74阅读模式
英文:

Numpy: How to check if a number is the minimum/maximum among the previous K numbers?

问题

我尝试自动化一个交易策略,该策略应在当前价格是前k个价格中的最小值/最大值时进入/退出多头头寸。

结果应包含以下内容:如果当前数字是前k个数字中的最大值,则为1,如果是最小值则为-1,如果没有条件成立则为0。

例如,如果k = 3,numpy数组 = [1, 2, 3, 2, 1, 6],结果应该是一个类似的数组:
[0, 0, 1, 0, -1, 1]。

英文:

I'm trying to automate a trading strategy which should enter/exit a long position when the current price is the minimum/maximum among the previous k prices.

The result should contain 1 if the current number is maximum among previous k numbers, -1 if it is the minimum and 0 if none of the conditions are true.

For example if k = 3 and the numpyp array = [1, 2, 3, 2, 1, 6], the result should be an array like:
[0, 0, 1, 0, -1, 1].

I tried the numpy's max function but don't know how to take into account the previous k numbers instead of fixed index and how to switch to default condition for the first k - 1 numbers which should be 0 since there are not k number available to compare them with.

答案1

得分: 4

import pandas as pd
array = [1, 2, 3, 2, 1, 6]
df = pd.DataFrame(array)
df['rolling_max'] = df[0].rolling(3).max()
df['rolling_min'] = df[0].rolling(3).min()
df['result'] = df.apply(lambda row: 1 if row[0] == row['rolling_max'] else (-1 if row[0] == row['rolling_min'] else 0), axis=1)

英文:

I will use Pandas

import pandas as pd
array = [1, 2, 3, 2, 1, 6]
df = pd.DataFrame(array)
df['rolling_max'] = df[0].rolling(3).max()
df['rolling_min'] = df[0].rolling(3).min()
df['result'] = df.apply(lambda row: 1 if row[0] == row['rolling_max'] else (-1 if row[0] == row['rolling_min'] else 0), axis=1)

答案2

得分: 1

以下是使用numpy的解决方案,使用了numpy.lib.stride_tricks.sliding_window_view介绍的方法,该方法在版本1.20.0中引入。

注意,这个解决方案(与@Hanwei Tang提出的解决方案一样)并不完全符合您的要求,因为在第二个窗口([2, 3, 2])中,2是最小值,因此返回-1而不是您要求的零。但也许您应该重新考虑是否真的希望在第二个窗口中得到零,还是-1。

编辑:如果一个窗口只包含相同的数字,即最小值和最大值相同,这个方法返回零。

import numpy as np

def rolling_max(a, wsize):
    windows = np.lib.stride_tricks.sliding_window_view(a, wsize)
    return np.max(windows, axis=-1)

def rolling_min(a, wsize):
    windows = np.lib.stride_tricks.sliding_window_view(a, wsize)
    return np.min(windows, axis=-1)

def check_prize(a, wsize):
    rmax = rolling_max(a, wsize)
    rmin = rolling_min(a, wsize)
    ismax = np.where(a[wsize-1:] == rmax, 1, 0)
    ismin = np.where(a[wsize-1:] == rmin, -1, 0)
    result = np.zeros_like(a)
    result[wsize-1:] = ismax + ismin
    return result

a = np.array([1, 2, 3, 2, 1, 6])
check_prize(a, wsize=3)
# 输出:
# array([ 0,  0,  1, -1, -1,  1])

b = np.array([1, 2, 4, 3, 1, 6])
check_prize(b, wsize=3)
# 输出:
# array([ 0,  0,  1,  0, -1,  1])

c = np.array([1, 2, 2, 2, 1, 6])
check_prize(c, wsize=3)
# 输出:
# array([ 0,  0,  1,  0, -1,  1])
英文:

Here is a solution with numpy using numpy.lib.stride_tricks.sliding_window_view, which was introduced in version 1.20.0.

Note that this solution (like the one proposed by @Hanwei Tang) does not exactly yield the result you was looking for, because in the second window ([2, 3, 2]) 2 is the minimum value and thus a -1 is returned instead of zero (what you requested). But maybe you should rethink whether you really want a zero for the second window or a -1.

EDIT: If a windows only contains same numbers, i.e. the minimum and maximum are the same, this method returns a zero.

import numpy as np

def rolling_max(a, wsize):
    windows = np.lib.stride_tricks.sliding_window_view(a, wsize)
    return np.max(windows, axis=-1)

def rolling_min(a, wsize):
    windows = np.lib.stride_tricks.sliding_window_view(a, wsize)
    return np.min(windows, axis=-1)

def check_prize(a, wsize):
    rmax = rolling_max(a, wsize)
    rmin = rolling_min(a, wsize)
    ismax = np.where(a[wsize-1:] == rmax, 1, 0)
    ismin = np.where(a[wsize-1:] == rmin, -1, 0)
    result = np.zeros_like(a)
    result[wsize-1:] = ismax + ismin
    return result

a = np.array([1, 2, 3, 2, 1, 6])
check_prize(a, wsize=3)
# Output:
# array([ 0,  0,  1, -1, -1,  1])

b = np.array([1, 2, 4, 3, 1, 6])
check_prize(b, wsize=3)
# Output:
# array([ 0,  0,  1,  0, -1,  1])

c = np.array([1, 2, 2, 2, 1, 6])
check_prize(c, wsize=3)
# Output:
# array([ 0,  0,  1,  0, -1,  1])

答案3

得分: 1

以下是翻译好的部分:

"Another approach using sliding_window_view with pad:"

from numpy.lib.stride_tricks import sliding_window_view as swv

k = 3
a = np.array([1, 2, 3, 2, 1, 6])

# create sliding window
v = swv(np.pad(a.astype(float), (k-1, 0), constant_values=np.nan), k)

# compare each element to min/max of sliding window
out = np.select([np.max(v, 1)==a, np.min(v, 1)==a], [1, -1], 0)

Output: array([ 0, 0, 1, -1, -1, 1])

英文:

Another approach using sliding_window_view with pad:

from numpy.lib.stride_tricks import sliding_window_view as swv

k = 3
a = np.array([1, 2, 3, 2, 1, 6])

# create sliding window
v = swv(np.pad(a.astype(float), (k-1, 0), constant_values=np.nan), k)

# compare each element to min/max of sliding window
out = np.select([np.max(v, 1)==a, np.min(v, 1)==a], [1, -1], 0)

Output: array([ 0, 0, 1, -1, -1, 1])

huangapple
  • 本文由 发表于 2023年2月8日 16:04:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75382825.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定