pandas 利用Python计算OHLC数据的平均真距(ATR)

mepcadol  于 2023-02-07  发布在  Python
关注(0)|答案(6)|浏览(225)

ATR是给定时间段内真实范围的平均值。真实范围是(高-低),这意味着我用以下公式计算了它:

df['High'].subtract(df['Low']).rolling(distance).mean()

然而,如果需要短周期(或上例中的“距离”),ATR可能非常跳跃,即在一些数字之间出现大的零星间隙。
真实的的ATR方程认识到这一点,并通过以下方式将其平滑:

Current ATR = [(Prior ATR x 13) + Current TR] / 14

然而,我不确定如何以与上面相同的方式进行此操作,即列宽操作。
样本数据包括我的原始方法中的TR和ATR(10):

Date        Time            Open    High    Low     Close   TR      ATR
30/09/16    14:45:00+00:00  1.1216  1.1221  1.1208  1.1209  0.0013  0.0013
30/09/16    15:00:00+00:00  1.1209  1.1211  1.1203  1.1205  0.0008  0.0013
30/09/16    15:15:00+00:00  1.1205  1.1216  1.1204  1.1216  0.0012  0.0013
30/09/16    15:30:00+00:00  1.1217  1.1222  1.1213  1.1216  0.0008  0.0013
30/09/16    15:45:00+00:00  1.1216  1.1240  1.1216  1.1240  0.0025  0.0015
30/09/16    16:00:00+00:00  1.1239  1.1246  1.1228  1.1242  0.0019  0.0015
30/09/16    16:15:00+00:00  1.1242  1.1251  1.1235  1.1240  0.0016  0.0016
30/09/16    16:30:00+00:00  1.1240  1.1240  1.1234  1.1236  0.0007  0.0014
30/09/16    16:45:00+00:00  1.1237  1.1245  1.1235  1.1238  0.0009  0.0012
30/09/16    17:00:00+00:00  1.1238  1.1239  1.1231  1.1233  0.0008  0.0012
30/09/16    17:15:00+00:00  1.1233  1.1245  1.1232  1.1240  0.0013  0.0012
30/09/16    17:30:00+00:00  1.1240  1.1242  1.1228  1.1230  0.0013  0.0013
30/09/16    17:45:00+00:00  1.1230  1.1230  1.1221  1.1227  0.0009  0.0013
30/09/16    18:00:00+00:00  1.1227  1.1232  1.1227  1.1232  0.0005  0.0012
30/09/16    18:15:00+00:00  1.1232  1.1232  1.1227  1.1227  0.0005  0.0010
30/09/16    18:30:00+00:00  1.1227  1.1231  1.1225  1.1231  0.0006  0.0009
30/09/16    18:45:00+00:00  1.1231  1.1237  1.1230  1.1232  0.0007  0.0008
30/09/16    19:00:00+00:00  1.1232  1.1233  1.1229  1.1231  0.0004  0.0008
30/09/16    19:15:00+00:00  1.1231  1.1234  1.1230  1.1230  0.0004  0.0007
30/09/16    19:30:00+00:00  1.1231  1.1234  1.1230  1.1234  0.0004  0.0007
30/09/16    19:45:00+00:00  1.1233  1.1240  1.1230  1.1239  0.0010  0.0007
30/09/16    20:00:00+00:00  1.1239  1.1242  1.1237  1.1238  0.0005  0.0006
30/09/16    20:15:00+00:00  1.1238  1.1240  1.1235  1.1237  0.0005  0.0006
30/09/16    20:30:00+00:00  1.1237  1.1238  1.1235  1.1235  0.0003  0.0005
30/09/16    20:45:00+00:00  1.1235  1.1236  1.1233  1.1233  0.0003  0.0005
30/09/16    21:00:00+00:00  1.1233  1.1238  1.1233  1.1237  0.0006  0.0005
30/09/16    21:15:00+00:00  1.1237  1.1244  1.1237  1.1242  0.0008  0.0005
30/09/16    21:30:00+00:00  1.1242  1.1243  1.1239  1.1239  0.0004  0.0005
30/09/16    21:45:00+00:00  1.1239  1.1244  1.1236  1.1241  0.0008  0.0006
x8goxv8g

x8goxv8g1#

对于其他想知道如何做到这一点的人,这里是我的答案。

def wwma(values, n):
    """
     J. Welles Wilder's EMA 
    """
    return values.ewm(alpha=1/n, adjust=False).mean()

def atr(df, n=14):
    data = df.copy()
    high = data[HIGH]
    low = data[LOW]
    close = data[CLOSE]
    data['tr0'] = abs(high - low)
    data['tr1'] = abs(high - close.shift())
    data['tr2'] = abs(low - close.shift())
    tr = data[['tr0', 'tr1', 'tr2']].max(axis=1)
    atr = wwma(tr, n)
    return atr
owfi6suc

owfi6suc2#

这不是TR的正确计算方法(参见-ATR),但我会这样做:
其中α = 2 /(跨度+1)
df['ATR'] = df['TR'].ewm(span = 10).mean()
否则,你应该能够轻松地做你自己的平滑像这样:
df['ATR'] = ( df['ATR'].shift(1)*13 + df['TR'] ) / 14
Pandas ewm

balp4ylt

balp4ylt3#

完全有效的功能:

def ATR(data: pd.DataFrame, window=14, use_nan=True) -> pd.Series:
   
    df_ = data.copy(deep=True)

    df_.loc[:, 'H_L'] = df_['High'] - df_['Low']
    df_.loc[:, 'H_Cp'] = abs(df_['High'] - df_['Close'].shift(1))
    df_.loc[:, 'L_Cp'] = abs(df_['Low'] - df_['Close'].shift(1))
    df_.loc[:, 'TR'] = df_[["H_L", "H_Cp", "L_Cp"]].max(axis=1)
    df_.loc[:, 'ATR'] = df_['TR'].rolling(window).mean()

    for i in range(window, len(df_)):
        df_.iloc[i, df_.columns.get_loc('ATR')] = (((df_.iloc[i - 1, df_.columns.get_loc('ATR')]) * (window - 1)) + df_.iloc[
            i, df_.columns.get_loc('TR')]) / window

    if use_nan:
        df_.iloc[:window, df_.columns.get_loc('ATR')] = np.nan

    return df_['ATR']
j7dteeu8

j7dteeu84#

这个答案使用了与Andrew的prior correct answer基本相同的逻辑。但是它避免了复制 Dataframe ,也避免了shift的重复使用,并且更DRY一些。在实现时,它匹配TradingView的值。

import pandas as pd

def rma(s: pd.Series, period: int) -> pd.Series:
    return s.ewm(alpha=1 / period).mean()

def atr(df: pd.DataFrame, length: int = 14) -> pd.Series:
    # Ref: https://stackoverflow.com/a/74282809/
    high, low, prev_close = df['high'], df['low'], df['close'].shift()
    tr_all = [high - low, high - prev_close, low - prev_close]
    tr_all = [tr.abs() for tr in tr_all]
    tr = pd.concat(tr_all, axis=1).max(axis=1)
    atr_ = rma(tr, length)
    return atr_
dpiehjr4

dpiehjr45#

接受的答案是正确的,但仍然可以缩减为一行:

ATR = pd.concat([df.High.sub(df.Low), df.High.sub(df.Close.shift()), df.Low.sub(df.Close.shift())], axis=1).max(1).ewm(span=14).mean()
z4bn682m

z4bn682m6#

关于TR计算的免责声明:它实际上是这三个选项中最大的价值:
1.当前高-当前低;

  1. abs(当前最高值-上次收盘价);
  2. abs(当前低点-上次收盘价);
    在python中你可以通过几种方式得到它,这里我介绍一下我的编码方式:
df['TR'] = [max(tup) for tup in list(zip(df['High'] - df['Low'],
                                        (df['High'] - df['Close'].shift(1)).abs(),
                                        (df['Low']  - df['Close'].shift(1)).abs()))]

我这样做是为了避免在我的 Dataframe 上创建其他列,所以我基本上创建了一个元组列表,每个元组包含上面列出的3个可能的值,然后创建了每个元组的最大值的列表。

相关问题