technical icon indicating copy to clipboard operation
technical copied to clipboard

Trend Step Channel - appreciate it

Open krazykoder opened this issue 2 years ago • 4 comments

https://www.tradingview.com/script/nXhuJpwr-Efficient-Trend-Step-Channel/ Can anyone code this indicator in python/numba please. Seems like i am getting stuck at this line not sure what it means abs(change(src,length))/sum(abs(change(src)),length) the result is supposedly a series but the seems to be a ratio of two series. Appreciate any help.

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © alexgrover

//@version=4
study("Efficient Trend Step Channel",overlay=true)
length = input(100),fast = input(50),slow = input(200),src = input(close)
//----
er = abs(change(src,length))/sum(abs(change(src)),length)
dev = er*stdev(src*2,fast) + (1-er)*stdev(src*2,slow)
//----
a=0.,a := src > nz(a[1],src) + dev ? src : src < nz(a[1],src) - dev ? src : nz(a[1],src)
upper = valuewhen(change(a),a + dev,0)
lower = valuewhen(change(a),a - dev,0)

krazykoder avatar Jun 12 '22 17:06 krazykoder

if you're stuck at some line - best share what you have so far, so we can determine where the most likely error is ?

xmatthias avatar Jun 12 '22 18:06 xmatthias

Thanks for responding, appreciate it. I have gotten this far. Basically i have verified that deviation dev is correct and matching trading view values. Where I am stuck is these 3 lines from the pine version

a=0.,a := src > nz(a[1],src) + dev ? src : src < nz(a[1],src) - dev ? src : nz(a[1],src)
upper = valuewhen(change(a),a + dev,0)
lower = valuewhen(change(a),a - dev,0)

Below is my python version (non optimized). I am using pandas ts for stddev, mom calculation which is equivalent of change

import pandas_ta as ta
## dfInd is the input dataframe that contain ohlcv data 

length = 100
fast = 50
slow = 200
src = dfInd['Close']  # control src : Close, hl2, hlc3, etc 

slowChange = ta.mom(src,length=length).abs()
fastChangeSum = ta.mom(src,length=1).abs().rolling(length).sum()

er = slowChange/fastChangeSum
dev = er*ta.stdev(src*2,fast) + (1-er)*ta.stdev(src*2,slow) # verified and correct 

## ------------- Code below this line is where i am struggling !! 

a = pd.DataFrame(0., index=dfInd.index, columns=['a'])
a=a['a']
# len(src.values)
# len(src.shift().fillna(0).values)

# # a['a'] = src.shift().fillna(0).values

value = np.where(a.shift(1).notnull(), a, src)

tsc = np.where (src > value + dev , value, src)
# tsc = np.where (src > value + dev , src, (np.where (src < value - dev , src , value)))  

dfInd['TSC'] = tsc
dfInd['TSCdev'] = dev

# ----------- not reached to upper and lower bands calculations yet
# chang_a = ta.mom(dfInd['TSC'],1)
# dfInd['TSC_U'] = dfInd['TSC'] + dev
# dfInd['TSC_L'] = dfInd['TSC'] - dev

Appreciate if you can take a look at it.

krazykoder avatar Jun 13 '22 08:06 krazykoder

a[1] is referencing the prior row. as this happens as part of the assignment to a - this means that you cannot really vectorize this indicator - but you'll have to loop - as the result of each row depends on the result from the calculation of the prior row.

You can find an example for this for example here:

https://github.com/freqtrade/technical/blob/7accaf535ee603c83a142e9830c775be8bf8bedb/technical/indicators/indicators.py#L1002-L1007

Obviously, this will have a quite severe performance penalty - as you'll loop through a dataframe with potentially 1000nds rows.

xmatthias avatar Jun 13 '22 09:06 xmatthias

I understand what you are referring. Thanks for the quick response. I will try out just looping through as you suggested here and see what results i get.

krazykoder avatar Jun 13 '22 10:06 krazykoder