【问题标题】:Identify in a pandas series when the trend changes from positive to negative当趋势从正面变为负面时,在 pandas 系列中识别
【发布时间】:2022-01-04 22:23:35
【问题描述】:

我有一个熊猫数据框,其中包含证券价格和几条不同移动平均长度的移动平均趋势线。数据框足够大,我想确定最有效的方法来捕获斜率变化的特定系列的索引(在这个例子中,我们只是说数据框中给定系列的正数到负数。)

我的 hack 看起来很“hacky”。我目前正在执行以下操作(注意,假设这是针对单个移动平均线系列):

filter = (df.diff()>0).diff().dropna(axis=0)
new_df = df[filter].dropna(axis=0)

下面的完整示例代码:

import pandas as pd
import numpy as np
from datetime import datetime, timedelta

# Create a sample Dataframe
date_today = datetime.now()
days = pd.date_range(date_today, date_today + timedelta(7), freq='D')
close = pd.Series([1,2,3,4,2,1,4,3])
df = pd.DataFrame({"date":days, "prices":close})
df.set_index("date", inplace=True)
print("Original DF")
print(df)

# Long Explanation
updays = (df.diff()>0) # Show True for all updays false for all downdays
print("Updays df is")
print(updays)
reversal_df = (updays.diff()) # this will only show change days as True
reversal_df.dropna(axis=0, inplace=True) # Handle the first day
trade_df = df[reversal_df].dropna() # Select only the days where the trend reversed
print("These are the days where the trend reverses it self from negative to positive or vice versa ")
print(trade_df)

# Simplified below by combining the above into two lines
filter = (df.diff()>0).diff().dropna(axis=0)
new_df = df[filter].dropna(axis=0)
print("The final result is this: ")
print(new_df)

我们将不胜感激。请注意,我更感兴趣的是如何在如何最好地做到这一点以便我理解它以及如何使其足够快地进行计算之间平衡效率。

【问题讨论】:

  • 您是否需要发现移动平均线的斜率何时改变符号或仅改变幅度?
  • @MarcelloChiuminatto 在这种情况下,我正在寻找他们,因为他们改变了标志。

标签: python pandas dataframe time-series


【解决方案1】:

多重移动平均解法。

查找注释 # *** THE SOLUTION BEGINS HERE *** 查看解决方案,在此之前只是生成数据、打印和绘图以进行验证。

我在这里做的是计算 MVA 斜率的符号,因此正斜率的值为 1,负斜率的值为 -1。

  • Slope_i = MVA(i, ask;periods) - MVA(i, ask;periods)
  • m_slp_sgn_i = Sign(Slope_i)

然后发现坡度变化我计算:

  • mslp_chg = sign(m_slp_sgn_i - m_slp_sgn_i-1)

例如,如果斜率从 1(正)变为 -1(负):

  • 符号 (-1 - 1) = 符号(-2) = -1

另一方面,如果从 -1 变为 1:

  • 符号 (1 - - 1) = 符号(2) = 1
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

# GENERATE DATA RANDOM PRICE

_periods = 1000
_value_0 = 1.1300
_std = 0.0005
_freq = '5T'
_output_col = 'ask'

_last_date = pd.to_datetime('2021-12-15')
_p_t = np.zeros(_periods)
_wn = np.random.normal(loc=0, scale=_std, size=_periods)
_p_t[0] = _value_0
_wn[0] = 0
_date_index = pd.date_range(end=_last_date, periods=_periods, freq=_freq)
df= pd.DataFrame(np.stack([_p_t, _wn], axis=1), columns=[_output_col, "wn"], index=_date_index)

for i in range(1, _periods):
    df.iloc[i][_output_col] = df.iloc[i - 1][_output_col] + df.iloc[i].wn

print(df.head(5))

# CALCULATE MOVING AVERAGES (3)

df['mva_25'] = df['ask'].rolling(25).mean()
df['mva_50'] = df['ask'].rolling(50).mean()
df['mva_100'] = df['ask'].rolling(100).mean()

# plot to check 

df['ask'].plot(figsize=(15,5))
df['mva_25'].plot(figsize=(15,5))
df['mva_50'].plot(figsize=(15,5))
df['mva_100'].plot(figsize=(15,5))
plt.show()

# *** THE SOLUTION BEGINS HERE ***

# calculate mva slopes directions
# positive slope: 1, negative slope -1
df['m25_slp_sgn'] = np.sign(df['mva_25'] - df['mva_25'].shift(1))
df['m50_slp_sgn'] = np.sign(df['mva_50'] - df['mva_50'].shift(1))
df['m100_slp_sgn'] = np.sign(df['mva_100'] - df['mva_100'].shift(1))


# CALCULATE CHANGE IN SLOPE

# from 1 to -1: -1
# from -1 to 1: 1

df['m25_slp_chg'] = np.sign(df['m25_slp_sgn'] - df['m25_slp_sgn'].shift(1))
df['m50_slp_chg'] = np.sign(df['m50_slp_sgn'] - df['m50_slp_sgn'].shift(1))
df['m100_slp_chg'] = np.sign(df['m100_slp_sgn'] -  df['m100_slp_sgn'].shift(1))

# clean NAN
df.dropna(inplace=True)

# print data to visually check
print(df.iloc[20:40][['mva_25', 'm25_slp_sgn', 'm25_slp_chg']])

# query where slope of MVA25 changes from positive to negative
df[(df['m25_slp_chg'] == -1)].head(5)

警告:数据是随机生成的,因此每次执行代码时,您都会看到图表和打印内容发生变化。

【讨论】:

  • 感谢您的及时答复@marcellochiuminatto。
猜你喜欢
  • 2017-11-29
  • 1970-01-01
  • 2014-05-27
  • 2014-07-30
  • 1970-01-01
  • 2020-10-19
  • 1970-01-01
  • 2020-09-20
  • 1970-01-01
相关资源
最近更新 更多