twopirllc / pandas-ta

Technical Analysis Indicators - Pandas TA is an easy to use Python 3 Pandas Extension with 150+ Indicators
https://twopirllc.github.io/pandas-ta/
MIT License
5.21k stars 1.02k forks source link

Hilbert Transform - Instantaneous Trendline #411

Closed rafalsza closed 6 months ago

rafalsza commented 2 years ago

Version: 0.3.14b0

Please add overlap: Hilbert Transform - Instantaneous Trendline

twopirllc commented 2 years ago

Hello @rafalsza,

Finishing off all the TA Lib versions in Python is on the agenda.

Kind Regards, KJ

aligheshlaghi97 commented 1 year ago

Hey there everyone!

I found this link useful for implementation.

Is this article a correct representative of Hilbert Transform - Instantaneous Trendline?

rafalsza commented 1 year ago

def ehlers_instantaneous_trendline(source, alpha):
    itrend = np.zeros_like(source)
    trigger = np.zeros_like(source)

    for i in range(len(source)):
        if i < 7:
            itrend[i] = (source[i] + (2 * source[i - 1]) + source[i - 2]) / 4
        else:
            itrend[i] = (
                ((alpha - (alpha**2 / 4)) * source[i])
                + (0.5 * alpha**2 * source[i - 1])
                - ((alpha - (0.75 * alpha**2)) * source[i - 2])
                + (2 * (1 - alpha) * itrend[i - 1])
                - ((1 - alpha) ** 2 * itrend[i - 2])
            )

        trigger[i] = (2 * itrend[i]) - itrend[i - 2]

    return itrend, trigger
aligheshlaghi97 commented 1 year ago

Hello @rafalsza

Thank you so much for the code you provided. I checked it, it seems work properly without error, except that it is not making output of between -1 to 1. I think it should be normalized, do you agree with me?

On the other hand, I checked tradingview but I couldn't find Hilbert Transfrom with just one input 'alpha'. Here is a photo I want to share with you from tradingview with two inputs 'Lpperiod' and 'Filttop'.

Screenshot from 2023-06-01 20-24-30

rafalsza commented 1 year ago

I've already tested only this script:

Sample Code

import yfinance as yf
import numpy as np
import plotly.graph_objects as go

def ehlers_instantaneous_trendline(source, alpha):
    itrend = np.zeros_like(source)
    trigger = np.zeros_like(source)

    for i in range(len(source)):
        if i < 7:
            itrend[i] = (source[i] + (2 * source[i - 1]) + source[i - 2]) / 4
        else:
            itrend[i] = (
                    ((alpha - (alpha ** 2 / 4)) * source[i])
                    + (0.5 * alpha ** 2 * source[i - 1])
                    - ((alpha - (0.75 * alpha ** 2)) * source[i - 2])
                    + (2 * (1 - alpha) * itrend[i - 1])
                    - ((1 - alpha) ** 2 * itrend[i - 2])
            )

        trigger[i] = (2 * itrend[i]) - itrend[i - 2]

    return itrend, trigger

Example


# Define the ticker symbol and time period
ticker = "BTC-USD"
start = "2020-01-01"
end_date = "2022-01-01"
interval = "1d"

# Retrieve the stock data using yfinance
data = yf.download(ticker, start, interval=interval)

# Extract the OHLC data
ohlc_data = data.loc[:, ["Open", "High", "Low", "Close"]]

# Set the alpha value for the Ehlers Instantaneous Trendline V2 indicator
alpha = 0.07

# Calculate the Ehlers Instantaneous Trendline V2 indicator
itrend, trigger = ehlers_instantaneous_trendline(ohlc_data["Close"].values, alpha)

# Create the figure and add Candlestick and Line traces
fig = go.Figure()

fig.add_trace(
    go.Candlestick(
        x=data.index,
        open=ohlc_data["Open"],
        high=ohlc_data["High"],
        low=ohlc_data["Low"],
        close=ohlc_data["Close"],
        name="OHLC",
    )
)

fig.add_trace(go.Scatter(x=data.index, y=itrend, mode="lines", name="ITrend"))

fig.add_trace(go.Scatter(x=data.index, y=trigger, mode="lines", name="Trigger"))

# Set the layout
fig.update_layout(
    title="Ehlers Instantaneous Trendline V2 with Candlestick OHLC",
    xaxis_rangeslider_visible=False,
    xaxis_title="Date",
    yaxis_title="Price",
    legend=dict(x=0.9, y=1, bgcolor="rgba(255, 255, 255, 0.5)", bordercolor="rgba(0, 0, 0, 0.5)"),
    showlegend=True,
    yaxis=dict(type="log"),  # Set the y-axis scale to logarithmic
)

# Show the plot
fig.show()
aligheshlaghi97 commented 1 year ago

Hello everyone

@rafalsza thank you so much for providing the whole code, However unfortunately, I got the same results when I ran new code: The output of the function is a different from the output of TradingView's Hilbert Transform indicator over the same data. And also the inputs are different as mentioned in my previous comment.

@twopirllc can you please provide some hint for us what should we do at this point? Should we care about TradingView's output or not? And if you think we should not care about it and use the current logic, I would be happy to find a pandas way to implement this piece of code with the help of @rafalsza in order to create new PR.

Thank you all for your time and considerations.

Bests Regards, Ali Gheshlaghi

twopirllc commented 1 year ago

Hi @rafalsza & @aligheshlaghi97,

Yes. Thanks for providing some sample code to get started with. 😎

Pandas TA's primary purpose is to replicate the indicators from the de facto TA-Lib. If an indicator does not exist in TA-Lib, then the goal is to port it from TradingView (TV); preferably from TV's ta standard library. If an indicator exists in both TA-Lib and TV, the default indicator mode favors TA-Lib over TV.

Furthermore if the indicator is loop based, like TA-Lib, it is preferred to have implementation in numpy/numba to boost calculation speeds.

For an example, see the development version of SMA which has both TA-Lib's call as well as a numpy/numba implementation. There is no TV version of SMA since it is identical to TA-Lib. Other currently implemented indicators in numpy/numba on the [development]() branch include: atrts, ha, mama, pivots, reflex, ssf, ssf3, and trendflex.

For the case of ht_trendline, it is preferred to port TA-Lib's ht_trendline to numpy/numba and/or Ehler's or a TV version if possible.

In short:

  1. If it exists in TA-Lib, port it and make it the default.
  2. If it exists in TV also, include that implementation.
  3. Similarily for other sources...

Hope this makes sense!

aligheshlaghi97 commented 1 year ago

@twopirllc Thank you so much Kevin for your complete explanations.

I will start trying to implement as you described, with the help of the sources you mentioned and the code @rafalsza provided. I will sent you feedback about the progress in this issue and hopefully, make a PR asap.

twopirllc commented 6 months ago

@rafalsza

Finally @aligheshlaghi97 and I were able to complete this indicator. It is now on the develpoment branch.

KJ