web-dev-qa-db-ja.com

相対強度指数python pandas

私はパンダが初めてです。パンダのRSIインジケータで相対強度部分を計算する最良の方法は何ですか?これまでのところ、私は次のものを得ました:

from pylab import *
import pandas as pd
import numpy as np



def Datapull(Stock):
    try:
        df = (pd.io.data.DataReader(Stock,'yahoo',start='01/01/2010'))
        return df
        print 'Retrieved', Stock
        time.sleep(5)
    except Exception, e:
        print 'Main Loop', str(e)


def RSIfun(price, n=14):
    delta = price['Close'].diff()
    #-----------
    dUp=
    dDown=

    RolUp=pd.rolling_mean(dUp, n)
    RolDown=pd.rolling_mean(dDown, n).abs()

    RS = RolUp / RolDown
    rsi= 100.0 - (100.0 / (1.0 + RS))
    return rsi

Stock='AAPL'
df=Datapull(Stock)
RSIfun(df)

これまでに正しくやっていますか?上向きと下向きの計算を分ける方程式の違いの部分に問題があります

24
user3084006
dUp= delta[delta > 0]
dDown= delta[delta < 0]

また、次のようなものが必要です:

RolUp = RolUp.reindex_like(delta, method='ffill')
RolDown = RolDown.reindex_like(delta, method='ffill')

さもないと RS = RolUp / RolDownはあなたが望むことをしない

編集:これはRS計算のより正確な方法のようです:

# dUp= delta[delta > 0]
# dDown= delta[delta < 0]

# dUp = dUp.reindex_like(delta, fill_value=0)
# dDown = dDown.reindex_like(delta, fill_value=0)

dUp, dDown = delta.copy(), delta.copy()
dUp[dUp < 0] = 0
dDown[dDown > 0] = 0

RolUp = pd.rolling_mean(dUp, n)
RolDown = pd.rolling_mean(dDown, n).abs()

RS = RolUp / RolDown
15
behzad.nouri

RSIを定義するさまざまな方法があることに注意することが重要です。通常、少なくとも2つの方法で定義されます。上記の単純移動平均(SMA)の使用、または指数移動平均(EMA)の使用です。 RSIの両方の定義を計算し、比較のためにプロットするコードスニペットを次に示します。定義により常にNaNであるため、差を取得した後、最初の行を破棄しています。

EMAを使用する場合は注意が必要です。データの先頭に戻るメモリが含まれているため、結果はどこから開始するかによって異なります。このため、通常、最初に100タイムステップなどのデータを追加してから、最初の100 RSI値を切り捨てます。

以下のプロットでは、SMAとEMAを使用して計算されたRSIの違いを見ることができます。SMAの方が感度が高い傾向があります。 EMAに基づくRSIは、最初のタイムステップ(最初の行を破棄するため、元の期間の2番目のタイムステップ)で最初の有限値を持ちますが、SMAに基づくRSIは、最初の有限値を持ちます。 14番目のタイムステップ。これは、デフォルトでrolling_mean()がウィンドウを埋めるのに十分な値がある場合にのみ有限値を返すためです。

A comparison of the RSI calculated using exponential or simple moving average

import pandas
import pandas.io.data
import datetime
import matplotlib.pyplot as plt

# Window length for moving average
window_length = 14

# Dates
start = datetime.datetime(2010, 1, 1)
end = datetime.datetime(2013, 1, 27)

# Get data
data = pandas.io.data.DataReader('AAPL', 'yahoo', start, end)
# Get just the close
close = data['Adj Close']
# Get the difference in price from previous step
delta = close.diff()
# Get rid of the first row, which is NaN since it did not have a previous 
# row to calculate the differences
delta = delta[1:] 

# Make the positive gains (up) and negative gains (down) Series
up, down = delta.copy(), delta.copy()
up[up < 0] = 0
down[down > 0] = 0

# Calculate the EWMA
roll_up1 = pandas.stats.moments.ewma(up, window_length)
roll_down1 = pandas.stats.moments.ewma(down.abs(), window_length)

# Calculate the RSI based on EWMA
RS1 = roll_up1 / roll_down1
RSI1 = 100.0 - (100.0 / (1.0 + RS1))

# Calculate the SMA
roll_up2 = pandas.rolling_mean(up, window_length)
roll_down2 = pandas.rolling_mean(down.abs(), window_length)

# Calculate the RSI based on SMA
RS2 = roll_up2 / roll_down2
RSI2 = 100.0 - (100.0 / (1.0 + RS2))

# Compare graphically
plt.figure()
RSI1.plot()
RSI2.plot()
plt.legend(['RSI via EWMA', 'RSI via SMA'])
plt.show()
35
Moot

私の答えは、StockChartsサンプルデータでテストされています。

[StockChart RSI情報] [1] http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:relative_strength_index_rsi

def RSI(series, period):
    delta = series.diff().dropna()
    u = delta * 0
    d = u.copy()
    u[delta > 0] = delta[delta > 0]
    d[delta < 0] = -delta[delta < 0]
    u[u.index[period-1]] = np.mean( u[:period] ) #first value is sum of avg gains
    u = u.drop(u.index[:(period-1)])
    d[d.index[period-1]] = np.mean( d[:period] ) #first value is sum of avg losses
    d = d.drop(d.index[:(period-1)])
    rs = pd.stats.moments.ewma(u, com=period-1, adjust=False) / \
         pd.stats.moments.ewma(d, com=period-1, adjust=False)
    return 100 - 100 / (1 + rs)


#sample data from StockCharts
data = pd.Series( [ 44.34, 44.09, 44.15, 43.61,
                    44.33, 44.83, 45.10, 45.42,
                    45.84, 46.08, 45.89, 46.03,
                    45.61, 46.28, 46.28, 46.00,
                    46.03, 46.41, 46.22, 45.64 ] )
print RSI( data, 14 )

#output
14    70.464135
15    66.249619
16    66.480942
17    69.346853
18    66.294713
19    57.915021
10
AAV

私もこの質問を持っていて、Jevが取ったrolling_applyパスをたどっていました。ただし、結果をテストしたとき、StockCharts.comやthinkorswimなど、私が使用している商用株価チャートプログラムとは一致しませんでした。そこで、私はいくつかの掘り下げを行い、Welles WilderがRSIを作成したときに、彼が現在Wilder Smoothingと呼ばれる平滑化手法を使用していることを発見しました。上記の商用サービスでは、単純な移動平均ではなく、Wilder Smoothingを使用して平均の損益を計算しています。

私はPython(およびPandas)が初めてなので、forループを高速化するために、他の誰かがその可能性についてコメントできるかもしれません。

これがあなたのお役に立てば幸いです。

詳細はこちら

def get_rsi_timeseries(prices, n=14):
    # RSI = 100 - (100 / (1 + RS))
    # where RS = (Wilder-smoothed n-period average of gains / Wilder-smoothed n-period average of -losses)
    # Note that losses above should be positive values
    # Wilder-smoothing = ((previous smoothed avg * (n-1)) + current value to average) / n
    # For the very first "previous smoothed avg" (aka the seed value), we start with a straight average.
    # Therefore, our first RSI value will be for the n+2nd period:
    #     0: first delta is nan
    #     1:
    #     ...
    #     n: lookback period for first Wilder smoothing seed value
    #     n+1: first RSI

    # First, calculate the gain or loss from one price to the next. The first value is nan so replace with 0.
    deltas = (prices-prices.shift(1)).fillna(0)

    # Calculate the straight average seed values.
    # The first delta is always zero, so we will use a slice of the first n deltas starting at 1,
    # and filter only deltas > 0 to get gains and deltas < 0 to get losses
    avg_of_gains = deltas[1:n+1][deltas > 0].sum() / n
    avg_of_losses = -deltas[1:n+1][deltas < 0].sum() / n

    # Set up pd.Series container for RSI values
    rsi_series = pd.Series(0.0, deltas.index)

    # Now calculate RSI using the Wilder smoothing method, starting with n+1 delta.
    up = lambda x: x if x > 0 else 0
    down = lambda x: -x if x < 0 else 0
    i = n+1
    for d in deltas[n+1:]:
        avg_of_gains = ((avg_of_gains * (n-1)) + up(d)) / n
        avg_of_losses = ((avg_of_losses * (n-1)) + down(d)) / n
        if avg_of_losses != 0:
            rs = avg_of_gains / avg_of_losses
            rsi_series[i] = 100 - (100 / (1 + rs))
        else:
            rsi_series[i] = 100
        i += 1

    return rsi_series
6
Bill

Rolling_applyをサブ関数と組み合わせて使用​​すると、次のようなクリーンな関数を作成できます。

def rsi(price, n=14):
    ''' rsi indicator '''
    gain = (price-price.shift(1)).fillna(0) # calculate price gain with previous day, first row nan is filled with 0

    def rsiCalc(p):
        # subfunction for calculating rsi for one lookback period
        avgGain = p[p>0].sum()/n
        avgLoss = -p[p<0].sum()/n 
        rs = avgGain/avgLoss
        return 100 - 100/(1+rs)

    # run for all periods with rolling_apply
    return pd.rolling_apply(gain,n,rsiCalc) 
4
Jev
# Relative Strength Index
# Avg(PriceUp)/(Avg(PriceUP)+Avg(PriceDown)*100
# Where: PriceUp(t)=1*(Price(t)-Price(t-1)){Price(t)- Price(t-1)>0};
#        PriceDown(t)=-1*(Price(t)-Price(t-1)){Price(t)- Price(t-1)<0};
# Change the formula for your own requirement
def rsi(values):
    up = values[values>0].mean()
    down = -1*values[values<0].mean()
    return 100 * up / (up + down)

stock['RSI_6D'] = stock['Momentum_1D'].rolling(center=False,window=6).apply(rsi)
stock['RSI_12D'] = stock['Momentum_1D'].rolling(center=False,window=12).apply(rsi)

Momentum_1D = Pt-P(t-1)ここで、Pは終値、tは日付です

1
pythonguy
def RSI(series):
    delta = series.diff()
    u = delta * 0 
    d = u.copy()
    i_pos = delta > 0
    i_neg = delta < 0
    u[i_pos] = delta[i_pos]
    d[i_neg] = delta[i_neg]
    rs = moments.ewma(u, span=27) / moments.ewma(d, span=27)
    return 100 - 100 / (1 + rs)
0
Shura