16

在此处输入图像描述 我正在定义一个函数 Heiken Ashi,它是技术分析中流行的图表类型之一。我正在使用 Pandas 在其上编写一个函数,但发现没有什么困难。这就是 Heiken Ashi [HA] 的样子——

                 Heikin-Ashi Candle Calculations
           HA_Close = (Open + High + Low + Close) / 4
           HA_Open = (previous HA_Open + previous HA_Close) / 2
           HA_Low = minimum of Low, HA_Open, and HA_Close
           HA_High = maximum of High, HA_Open, and HA_Close

               Heikin-Ashi Calculations on First Run
            HA_Close = (Open + High + Low + Close) / 4
                   HA_Open = (Open + Close) / 2
                           HA_Low = Low
                           HA_High = High

使用 for 循环和纯 python 的各种网站上有很多可用的东西,但我认为 Pandas 也可以做得很好。这是我的进步——

   def HA(df):

       df['HA_Close']=(df['Open']+ df['High']+ df['Low']+ df['Close'])/4

       ha_o=df['Open']+df['Close']  #Creating a Variable
       #(for 1st row)

       HA_O=df['HA_Open'].shift(1)+df['HA_Close'].shift(1) #Another variable
       #(for subsequent rows)

       df['HA_Open']=[ha_o/2 if df['HA_Open']='nan' else HA_O/2]     
       #(error Part Where am i going wrong?)

       df['HA_High']=df[['HA_Open','HA_Close','High']].max(axis=1)

       df['HA_Low']=df[['HA_Open','HA_Close','Low']].min(axis=1)

       return df

任何人都可以帮我解决这个问题吗?`它不起作用......我试过这个 -

  import pandas_datareader.data as web 
  import HA
  import pandas as pd
  start='2016-1-1'
  end='2016-10-30'
  DAX=web.DataReader('^GDAXI','yahoo',start,end)

这是我写的新代码

    def HA(df):
            df['HA_Close']=(df['Open']+ df['High']+ df['Low']+df['Close'])/4
...:        ha_o=df['Open']+df['Close']
...:        df['HA_Open']=0.0
...:        HA_O=df['HA_Open'].shift(1)+df['HA_Close'].shift(1)
...:        df['HA_Open']= np.where( df['HA_Open']==np.nan, ha_o/2, HA_O/2 )
...:        df['HA_High']=df[['HA_Open','HA_Close','High']].max(axis=1)
...:        df['HA_Low']=df[['HA_Open','HA_Close','Low']].min(axis=1)
...:        return df

但 HA_Open 的结果仍然不能令人满意

4

10 回答 10

17

根据我的测试,这是最快、准确和有效的实现:

def HA(df):
    df['HA_Close']=(df['Open']+ df['High']+ df['Low']+df['Close'])/4

    idx = df.index.name
    df.reset_index(inplace=True)

    for i in range(0, len(df)):
        if i == 0:
            df.set_value(i, 'HA_Open', ((df.get_value(i, 'Open') + df.get_value(i, 'Close')) / 2))
        else:
            df.set_value(i, 'HA_Open', ((df.get_value(i - 1, 'HA_Open') + df.get_value(i - 1, 'HA_Close')) / 2))

    if idx:
        df.set_index(idx, inplace=True)

    df['HA_High']=df[['HA_Open','HA_Close','High']].max(axis=1)
    df['HA_Low']=df[['HA_Open','HA_Close','Low']].min(axis=1)
    return df

这是我的测试算法(基本上我使用了这篇文章中提供的算法来对速度结果进行基准测试):

import quandl
import time

df = quandl.get("NSE/NIFTY_50", start_date='1997-01-01')

def test_HA():
    print('HA Test')
    start = time.time()
    HA(df)
    end = time.time()
    print('Time taken by set and get value functions for HA {}'.format(end-start))

    start = time.time()
    df['HA_Close_t']=(df['Open']+ df['High']+ df['Low']+df['Close'])/4

    from collections import namedtuple
    nt = namedtuple('nt', ['Open','Close'])
    previous_row = nt(df.ix[0,'Open'],df.ix[0,'Close'])
    i = 0
    for row in df.itertuples():
        ha_open = (previous_row.Open + previous_row.Close) / 2
        df.ix[i,'HA_Open_t'] = ha_open
        previous_row = nt(ha_open, row.Close)
        i += 1

    df['HA_High_t']=df[['HA_Open_t','HA_Close_t','High']].max(axis=1)
    df['HA_Low_t']=df[['HA_Open_t','HA_Close_t','Low']].min(axis=1)
    end = time.time()
    print('Time taken by ix (iloc, loc) functions for HA {}'.format(end-start))

这是我在 i7 处理器上得到的输出(请注意,结果可能会因您的处理器速度而异,但我认为结果会相似):

HA Test
Time taken by set and get value functions for HA 0.05005788803100586
Time taken by ix (iloc, loc) functions for HA 0.9360761642456055

我使用 Pandas 的经验表明,与和函数相比,像ix, loc,之类的函数要慢一些。此外,使用函数计算列本身的值会产生错误的结果。ilocset_valueget_valueshift

于 2017-10-02T08:35:18.567 回答
3
def heikenashi(df):
    df['HA_Close'] = (df['Open'] + df['High'] + df['Low'] + df['Close']) / 4
    df['HA_Open'] = (df['Open'].shift(1) + df['Open'].shift(1)) / 2
    df.iloc[0, df.columns.get_loc("HA_Open")] = (df.iloc[0]['Open'] + df.iloc[0]['Close'])/2
    df['HA_High'] = df[['High', 'Low', 'HA_Open', 'HA_Close']].max(axis=1)
    df['HA_Low'] = df[['High', 'Low', 'HA_Open', 'HA_Close']].min(axis=1)
    df = df.drop(['Open', 'High', 'Low', 'Close'], axis=1)  # remove old columns
    df = df.rename(columns={"HA_Open": "Open", "HA_High": "High", "HA_Low": "Low", "HA_Close": "Close", "Volume": "Volume"})
    df = df[['Open', 'High', 'Low', 'Close', 'Volume']]  # reorder columns
    return df
于 2018-02-03T04:48:09.197 回答
3

我对 Python 或 Pandas 不是很了解,但经过一些研究,我认为这是一个很好的解决方案。

请随时添加任何评论。我非常感谢。

我使用了 namedtuples 和itertuples(如果循环通过 DataFrame,似乎是最快的)。

我希望它有帮助!

def HA(df):
    df['HA_Close']=(df['Open']+ df['High']+ df['Low']+df['Close'])/4

    nt = namedtuple('nt', ['Open','Close'])
    previous_row = nt(df.ix[0,'Open'],df.ix[0,'Close'])
    i = 0
    for row in df.itertuples():
        ha_open = (previous_row.Open + previous_row.Close) / 2
        df.ix[i,'HA_Open'] = ha_open
        previous_row = nt(ha_open, row.Close)
        i += 1

    df['HA_High']=df[['HA_Open','HA_Close','High']].max(axis=1)
    df['HA_Low']=df[['HA_Open','HA_Close','Low']].min(axis=1)
    return df
于 2017-02-09T13:03:34.953 回答
2

我调整了代码以使其适用于 Python 3.7

def HA(df):
    df_HA = df
    df_HA['Close']=(df['Open']+ df['High']+ df['Low']+df['Close'])/4

    #idx = df_HA.index.name
    #df_HA.reset_index(inplace=True)

    for i in range(0, len(df)):
        if i == 0:
            df_HA['Open'][i]= ( (df['Open'][i] + df['Close'][i] )/ 2)
        else:
            df_HA['Open'][i] = ( (df['Open'][i-1] + df['Close'][i-1] )/ 2)


    #if idx:
        #df_HA.set_index(idx, inplace=True)

    df_HA['High']=df[['Open','Close','High']].max(axis=1)
    df_HA['Low']=df[['Open','Close','Low']].min(axis=1)
    return df_HA
于 2020-05-23T16:20:54.680 回答
2

完美运作的 HekinAshi 功能。我不是这段代码的原作者。我在 Github 上找到了这个(https://github.com/emreturan/heikin-ashi/blob/master/heikin_ashi.py

def heikin_ashi(df):
        heikin_ashi_df = pd.DataFrame(index=df.index.values, columns=['open', 'high', 'low', 'close'])
    
    heikin_ashi_df['close'] = (df['open'] + df['high'] + df['low'] + df['close']) / 4
    
    for i in range(len(df)):
        if i == 0:
            heikin_ashi_df.iat[0, 0] = df['open'].iloc[0]
        else:
            heikin_ashi_df.iat[i, 0] = (heikin_ashi_df.iat[i-1, 0] + heikin_ashi_df.iat[i-1, 3]) / 2
        
    heikin_ashi_df['high'] = heikin_ashi_df.loc[:, ['open', 'close']].join(df['high']).max(axis=1)
    
    heikin_ashi_df['low'] = heikin_ashi_df.loc[:, ['open', 'close']].join(df['low']).min(axis=1)
    
    return heikin_ashi_df
于 2020-12-30T18:04:57.217 回答
2

不幸的是,不推荐使用 set_value() 和 get_value()。根据 arkochhar 的回答,通过使用以下列表理解方法和我自己的 OHLC 数据(7000 行数据),我能够将速度提高 75%。它也比使用 at 和 iat 更快。

def HA( dataframe ):

    df = dataframe.copy()

    df['HA_Close']=(df.Open + df.High + df.Low + df.Close)/4

    df.reset_index(inplace=True)

    ha_open = [ (df.Open[0] + df.Close[0]) / 2 ]
    [ ha_open.append((ha_open[i] + df.HA_Close.values[i]) / 2) \
    for i in range(0, len(df)-1) ]
    df['HA_Open'] = ha_open

    df.set_index('index', inplace=True)

    df['HA_High']=df[['HA_Open','HA_Close','High']].max(axis=1)
    df['HA_Low']=df[['HA_Open','HA_Close','Low']].min(axis=1)

    return df
于 2019-03-11T21:04:57.067 回答
1

使用 numpy 会更快。

 def HEIKIN(O, H, L, C, oldO, oldC):
     HA_Close = (O + H + L + C)/4
     HA_Open = (oldO + oldC)/2
     elements = numpy.array([H, L, HA_Open, HA_Close])
     HA_High = elements.max(0)
     HA_Low = elements.min(0)
     out = numpy.array([HA_Close, HA_Open, HA_High, HA_Low])  
     return out
于 2018-08-13T10:18:20.410 回答
0

我找到的最快的解决方案。

def HA(df):
    df['HA_Close']=(df['Open']+ df['High']+ df['Low']+df['Close'])/4

    idx = df.index.name
    df.reset_index(inplace=True)

    ha_close_values = self.data['HA_Close'].values

    length = len(df)
    ha_open = np.zeros(length, dtype=float)
    ha_open[0] = (df['Open'][0] + df['Close'][0]) / 2

    for i in range(0, length - 1):
        ha_open[i + 1] = (ha_open[i] + ha_close_values[i]) / 2

    df['HA_Open'] = ha_open

    df['HA_High']=df[['HA_Open','HA_Close','High']].max(axis=1)
    df['HA_Low']=df[['HA_Open','HA_Close','Low']].min(axis=1)
    return df

此解决方案与user11186769类似,但有 2 个额外优化。

提供 3.5-4 倍加速的主要优化是这部分:

ha_close_values = self.data['HA_Close'].values

length = len(df)
ha_open = np.zeros(length, dtype=float)
ha_open[0] = (df['Open'][0] + df['Close'][0]) / 2

for i in range(0, length - 1):
    ha_open[i + 1] = (ha_open[i] + ha_close_values[i]) / 2

与这个:

[ha_open.append((ha_open[i] + df.HA_Close.values[i]) / 2) for i in range(0, len(df)-1)]

第一个区别是,在该答案中,每次迭代都有一个不必要且昂贵的调用。这是:df.HA_Close.values[i]。(它在每次迭代中将系列转换为一个 numpy 数组。)

如您所见,在我的解决方案中,我只计算了一次该值并将其存储为:ha_close_values = self.data['HA_Close'].values,并在 for 循环中使用了该值。

另一个优化是使用具有固定大小的 numpy 数组而不是 python 列表。我没有在每次迭代中附加到该列表,而是使用当前索引+1 来设置ha_open.

于 2021-07-21T11:34:24.683 回答
0

数据帧无循环解决方案

这是我能为dataframes想出的最简单、易于理解、无循环的解决方案。

  • 将 Heikin-Ashi 输出临时存储在 'o'、'h'、'l'、'c' 列中
  • 'h' 基于昨天的值,所以我们可以使用.shift(1)和复制第一个条目
  • 将 'Open'、'High'、'Low'、'Close' 替换为 'o'、'h'、'l'、'c'

蟒蛇 3.9.7

def heikin_ashi(df):
    df = df.copy()
    df['c'] = (df['Open'] + df['High'] + df['Low'] + df['Close']) / 4
    df['o'] = ((df['Open'] + df['Close']) / 2).shift(1)
    df.iloc[0,-1] = df['o'].iloc[1]
    df['h'] = df[['High', 'o', 'c']].max(axis=1)
    df['l'] = df[['Low', 'o', 'c']].min(axis=1)
    df['Open'], df['High'], df['Low'], df['Close'] = df['o'], df['h'], df['l'], df['c']
    return df.drop(['o', 'h', 'l', 'c'], axis=1)
于 2022-02-02T23:35:08.277 回答
0

与 Numba 一起使用的 Numpy 版本

@jit(nopython=True)
def heiken_ashi_numpy(c_open, c_high, c_low, c_close):
    ha_close = (c_open + c_high + c_low + c_close) / 4
    ha_open = np.empty_like(ha_close)
    ha_open[0] = (c_open[0] + c_close[0]) / 2
    for i in range(1, len(c_close)):
        ha_open[i] = (c_open[i - 1] + c_close[i - 1]) / 2
    ha_high = np.maximum(np.maximum(ha_open, ha_close), c_high)
    ha_low = np.minimum(np.minimum(ha_open, ha_close), c_low)
    return ha_open, ha_high, ha_low, ha_close
于 2021-12-06T14:08:04.830 回答