web-dev-qa-db-fra.com

Indice de force relative chez les pandas de python

Je suis nouveau aux pandas. Quel est le meilleur moyen de calculer la part de force relative dans l’indicateur RSI chez les pandas? Jusqu'à présent, j'ai obtenu ce qui suit:

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)

Est-ce que je le fais correctement jusqu'à présent? J'ai des problèmes avec la partie différence de l'équation où vous séparez les calculs à la hausse et à la baisse

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

aussi vous avez besoin de quelque chose comme:

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

sinon RS = RolUp / RolDown ne fera pas ce que vous désirez

Edit: semble que ce soit un moyen plus précis de calcul 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

Il est important de noter qu'il existe différentes manières de définir le RSI. Il est généralement défini d'au moins deux manières: en utilisant une moyenne mobile simple (SMA) comme ci-dessus, ou en utilisant une moyenne mobile exponentielle (EMA). Voici un extrait de code qui calcule les deux définitions de RSI et les trace à des fins de comparaison. Je rejette la première ligne après avoir pris la différence, car il s'agit toujours de NaN par définition.

Notez que lorsque vous utilisez EMA, vous devez faire attention: comme il inclut une mémoire remontant au début des données, le résultat dépend du point de départ! Pour cette raison, les utilisateurs ajoutent généralement des données au début, par exemple 100 pas de temps, puis coupent les 100 premières valeurs RSI. 

Dans le graphique ci-dessous, on peut voir la différence entre le RSI calculé avec SMA et EMA: le SMA a tendance à être plus sensible. Notez que le RSI basé sur EMA a sa première valeur finie au premier pas de temps (qui est le deuxième pas de la période d'origine, en raison de la suppression de la première ligne), alors que le RSI basé sur SMA a sa première valeur finie à 14ème pas de temps. En effet, rolling_mean () ne renvoie par défaut une valeur finie que lorsque le nombre de valeurs est suffisant pour remplir la fenêtre.

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()
30
Moot

Ma réponse est testée sur des exemples de données StockCharts.

[StockChart RSI info] [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
8
AAV

Moi aussi, j'avais cette question et je travaillais dans le chemin rolling_apply que Jev a pris. Toutefois, lorsque j'ai testé mes résultats, ils ne correspondaient pas aux programmes commerciaux de cartographie boursière que j'utilise, tels que StockCharts.com ou thinkorswim. J'ai donc creusé un peu et découvert que, lorsque Welles Wilder a créé le RSI, il utilisait une technique de lissage maintenant appelée Wilder Smoothing. Les services commerciaux ci-dessus utilisent Wilder Smoothing plutôt qu'une simple moyenne mobile pour calculer les gains et pertes moyens.

Je connais Python (et les Pandas), alors je me demande s’il existe un moyen génial de refactoriser la boucle pour ci-dessous pour accélérer les choses. Peut-être que quelqu'un d'autre peut commenter cette possibilité.

J'espère que vous trouvez ça utile.

Plus d'infos ici .

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
4
Bill

Vous pouvez utiliser rolling_apply en combinaison avec une sous-fonction pour créer une fonction propre comme celle-ci:

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) 
3
Jev
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
# 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) où P représente le cours de clôture et t la date.

0
pythonguy