优化移动平均线

Optimize a moving average

提问人:Question1010 提问时间:11/6/2023 更新时间:11/7/2023 访问量:61

问:

我编写了计算每周指数移动平均线的代码,为每天提供一个值。为此,我使用数据帧中每周指数移动平均线的最新值来计算第 “d” 天的值,其中包括截至第 “d” 天的数据

我有以下代码:

def weekly_exponential_moving_average(data: pd.DataFrame, window: int, column: Optional[str] = 'Close_Price') -> pd.Series:

def compute_ema_for_day(day):
    day_before_d = data[data.index <= day][column]
    weekly_data = day_before_d.resample('W').last()
    return weekly_data.ewm(span=window, adjust=False).mean().iloc[-1]

weekly_ema = data.index.to_series().apply(compute_ema_for_day)

return weekly_ema

这给出了所需的结果:它计算 data[column] 窗口上的每周移动平均线。

然而,这段代码是非常不可靠的,因为compute_ema_for_day在整个时间序列中每次都运行。

有没有办法以更有效的方式(如线性时间)计算我想要什么?

Python Pandas 时间序列

评论

0赞 algebruh 11/7/2023
你确定这计算了你希望它计算的内容吗?我想你想要一周中每一天的ewm .这不是您的函数所做的,因为它会根据当前工作日的值和过去周日的值来计算 ewm。
0赞 Question1010 11/7/2023
@algebruh 是的,这正是我想要的!:“它根据当前工作日的值和过去周日的值计算 ewm”。对不起,如果我在我的帖子中不清楚,所以现在它计算了这个,我想知道是否有可能优化这个功能

答:

0赞 armamut 11/6/2023 #1

我的东西过滤是不必要的。您可以重新采样并返回每周 ema:


def weekly_exponential_moving_average(data: pd.DataFrame, window: int, column: Optional[str] = 'Close_Price') -> pd.Series:

    weekly_data = data.resample('W').last()
    weekly_ema = weekly_data.ewm(span=window, adjust=False).mean()
    return weekly_ema

或者,如果需要与输入相同的形状,则可以将 weekly_ema DataFrame 映射到原始 DataFrame。data

评论

0赞 Question1010 11/6/2023
不,但这不会给出与我上面的函数相同的结果。正如我所说,我每天都有不同的值,您提供的功能显然不是这种情况,因为它在几周内是恒定的
0赞 armamut 11/7/2023
我不明白,因为这一行> weekly_data = day_before_d.resample('W').last() 你能提供样本数据吗
1赞 algebruh 11/7/2023 #2

我认为在大熊猫中没有优雅而快速的方法可以做到这一点。我认为你必须自己编写指数移动平均线类和一个自定义的 for 循环。它可能看起来像这样: (根据一些测试数据,它返回与您的函数相同的值)

import pandas as pd

class ExponentialMovingAverage:
    def __init__(self, alpha : float):
        self.current_value = None
        self.alpha = alpha

    def update(self, value, update_current_value = False) -> float:
        if self.current_value is None:
            self.current_value = value

        new_value = self.alpha * value + (1 - self.alpha) * self.current_value
        if update_current_value:
            self.current_value = new_value

        return new_value

def get_ewm_values(ewm: ExponentialMovingAverage, df: pd.DataFrame, column='Close_Price'):
    values = []
    for index,row in df.iterrows():

        sunday_index = 6
        day_of_week = index.day_of_week
        if day_of_week == sunday_index:
            ewm_value = ewm.update(row[column], True)
        else:
            ewm_value = ewm.update(row[column])
        values.append(ewm_value)
    return values


emv = ExponentialMovingAverage(0.5)
df['ewm'] = get_ewm_values(emv, df)

评论

0赞 Question1010 11/7/2023
非常感谢您的回答。是的,实际上这可能是唯一的方法,但我没有找到完全相同的结果,例如使用: np.random.seed(0) start_date = datetime(2021, 1, 1) num_dates = 100 date_list = [start_date] for _ in range(num_dates - 1): date_list.append(date_list[-1] + timedelta(days=np.random.randint(1, 4))) close_prices = np.random.rand(num_dates) * 100 df = pd.数据帧({'Close_Price': close_prices}, index=date_list) 打印(df)
0赞 Question1010 11/7/2023
这是因为我的 datframe 中可能缺少日期
0赞 algebruh 11/7/2023
是的,我明白了。然后你需要调整班级。不确定熊猫的实现如何处理不规则采样的系列......只是好奇,你为什么要计算这个?