edgarmtze
edgarmtze

Reputation: 25058

Tradingview pinescript's RMA (Moving average used in RSI. It is the exponentially weighted moving average with alpha = 1 / length) in python, pandas

I've been trying to get same results from tradingviews RMA method but I dont know how to accomplish it

In their page RMA is computed as:

plot(rma(close, 15))

//the same on pine
pine_rma(src, length) =>
    alpha = 1/length
    sum = 0.0
    sum := na(sum[1]) ? sma(src, length) : alpha * src + (1 - alpha) * nz(sum[1])
plot(pine_rma(close, 15))

to test I used input and their result, this is input column and the same input after applying tradingview´s rma(input,14):

data = [[588.0,519.9035093599585],
[361.98999999999984,508.62397297710436],
[412.52000000000055,501.7594034787397],
[197.60000000000042,480.0337318016869],
[208.71999999999932,460.6541795301378],
[380.1100000000006,454.90102384941366],
[537.6599999999999,460.8123792887413],
[323.5600000000013,451.0086379109742],
[431.78000000000077,449.6351637744761],
[299.6299999999992,438.9205092191563],
[225.1900000000005,423.65404427493087],
[292.42000000000013,414.28018396957873],
[357.64999999999964,410.23517082889435],
[692.5100000000003,430.3976586268306],
[219.70999999999916,415.34854015348543],
[400.32999999999987,414.2757872853794],
[604.3099999999995,427.849659622138],
[204.29000000000087,411.8811125062711],
[176.26000000000022,395.0510330415374],
[204.1800000000003,381.41738782428473],
[324.0,377.3161458368358],
[231.67000000000007,366.91284970563316],
[184.21000000000092,353.8626461552309],
[483.0,363.08674285842864],
[290.6399999999994,357.911975511398],
[107.10000000000036,339.996834403441],
[179.0,328.49706051748086],
[182.36000000000058,318.05869905194663],
[275.0,314.98307769109323],
[135.70000000000073,302.17714357030087],
[419.59000000000015,310.56377617242225],
[275.6399999999994,308.06922073153487],
[440.48999999999984,317.5278478221396],
[224.0,310.8472872634153],
[548.0100000000001,327.78748103031415],
[257.0,322.73123238529183],
[267.97999999999956,318.82043007205664],
[366.51000000000016,322.2268279240526],
[341.14999999999964,323.57848307233456],
[147.4200000000001,310.9957342814536],
[158.78000000000063,300.12318183277836],
[416.03000000000077,308.4022402732943],
[360.78999999999917,312.14422311091613],
[1330.7299999999996,384.90035003156487],
[506.92000000000013,393.61603931502464],
[307.6100000000006,387.4727507925229],
[296.7299999999996,380.991125735914],
[462.0,386.7774738976345],
[473.8099999999995,392.9940829049463],
[769.4200000000002,419.88164841173585],
[971.4799999999997,459.2815306680404],
[722.1399999999994,478.0571356203232],
[554.9799999999996,483.5516259331572],
[688.5,498.19079550936027],
[292.0,483.462881544406],
[634.9500000000007,494.2833900055199]]

# Create the pandas DataFrame
dfRMA = pd.DataFrame(data, columns = ['input', 'wantedrma'])
dfRMA['try1'] = dfRMA['input'].ewm( alpha=1/14, adjust=False).mean()
dfRMA['try2'] = numpy_ewma_vectorized(dfRMA['input'],14)
dfRMA

ewm does not give me same results, so I searched and found this but I just replicated ewma

def numpy_ewma_vectorized(data, window):

    alpha = 1/window
    alpha_rev = 1-alpha

    scale = 1/alpha_rev
    n = data.shape[0]

    r = np.arange(n)
    scale_arr = scale**r
    offset = data[0]*alpha_rev**(r+1)
    pw0 = alpha*alpha_rev**(n-1)

    mult = data*pw0*scale_arr
    cumsums = mult.cumsum()
    out = offset + cumsums*scale_arr[::-1]
    return out

I am getting these results

enter image description here

Do you know how to translate pinescript rma method in pandas?

I realized that using pandas ewm it seems to converge, last rows are closer and closer to the value, is this correct?

enter image description here

... enter image description here

Upvotes: 3

Views: 3154

Answers (3)

AlexLi
AlexLi

Reputation: 51

I think you can try the following

def RMA(r, days, name=0):
    cps = [ v[name] for v in r ] if name else r
    rmas = [0 for i in range(len(cps))] 
    alpha = 1 / days

    for i in range(len(cps)):
        if i < days-1:
            rmas[i] = 0
        else:
            if rmas[i-1]:
                rmas[i] = alpha * cps[i] + (1 - alpha) * rmas[i-1]
            else:
                ma = 0
                for i2 in range(i-days,i):  
                    ma += cps[i2+1]
                rmas[i] = ma / days
    return rmas

Upvotes: 0

Brandon Ros
Brandon Ros

Reputation: 199

const cloneArray = (input) => [...input]

const pluck = (input, key) => input.map(element => element[key])

const pineSma = (source, length) => {
  let sum = 0.0
  for (let i = 0; i < length; ++i) {
    sum += source[i] / length
  }
  return sum
}

const pineRma = (src, length, last) => {
  const alpha = 1.0 / length
  return alpha * src[0] + (1.0 - alpha) * last
}

const calculatePineRma = (candles, sourceKey, length) => {
  const results = []
  for (let i = 0; i <= candles.length - length; ++i) {
    const sourceCandles = cloneArray(candles.slice(i, i + length)).reverse()
    const closes = pluck(sourceCandles, sourceKey)
    if (i === 0) {
      results.push(pineSma(closes, length))
      continue
    }
    results.push(pineRma(closes, length, results[results.length - 1]))
  }
  return results
}

Upvotes: 0

Ziur Olpa
Ziur Olpa

Reputation: 2133

As far as I know Pine-script will use data that is not exported, so the weighted mean is taking into account previous records that are not in your table, meaning that you can't reproduce the results without more information.

What you need to do is load around 50-100 points (depending on alpha) of data further into the past than what you actually will use, and use a threshold for the comparing the data. You need that both python and pine-script is using data with the same or at least similar "history".

So you make the calculations using the whole dataframe and then you skip the first rows. You can see the effect of the historical data in your own example as difference between your calculation and pine-script one is quickly vanishing after the 55 point, but of course the difference will also depend on alpha.

So actually your code could be already well written. In any case you can use the pandas implementation directly, it will be easier and probably faster.

Upvotes: 0

Related Questions