Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

211
Views
How to implement the Hindenburg omen indicator?

As defined here the Hindenburg omen indicator is:

The daily number of new 52-week highs and 52-week lows in a stock market index are greater than a threshold amount (typically 2.2%).

To me it means, we roll daily and look back 52 weeks or 252 business/trading days, then count the number of highs (or lows) and finally compute the return of that or pct_change, which is the ratio of new highs (or lows) they want to monitor e.g., being above 2.2%

import pandas as pd
import numpy as np
import yfinance as yf

# download the S&P500 
df = yf.download('^GSPC')
# compute the "highs" and "lows"
df['Highs'] = df['Close'].rolling(252).apply(lambda x: x.cummax().diff().
    apply(lambda x: np.where(x > 0, 1, 0)).sum()).pct_change()
df['Lows'] = df['Close'].rolling(252).apply(lambda x: x.cummin().diff().
    apply(lambda x: np.where(x < 0, 1, 0)).sum()).pct_change()

Did we understand it the same way? is there a better way to do it?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Interesting question! Could I suggest the following code - it runs much faster than the apply solution because it is vectorised, and also lays out the steps a bit more clearly so you can inspect the interim results.

I got a different result to your code - you can compare by also plotting your result on the timeseries at bottom.

import pandas as pd
import numpy as np
import yfinance as yf

# download the S&P500 
df = yf.download('^GSPC')

# Constants
n_trading_day_window = 252

# Simplify the input dataframe to only the relevant column
df_hin_omen = df[['Close']]
# Calculate rolling highs and lows
df_hin_omen.insert(1, 'rolling_high', df_hin_omen['Close'].rolling(n_trading_day_window).max())
df_hin_omen.insert(2, 'rolling_low', df_hin_omen['Close'].rolling(n_trading_day_window).min())
# High and low are simply when the given row matches the 252 day high or low
df_hin_omen.insert(3, 'is_high', df_hin_omen.Close == df_hin_omen.rolling_high)
df_hin_omen.insert(4, 'is_low', df_hin_omen.Close == df_hin_omen.rolling_low)
# Calculate rolling percentages
df_hin_omen.insert(5, 'percent_highs', df_hin_omen.is_high.rolling(n_trading_day_window).sum() / n_trading_day_window)
df_hin_omen.insert(6, 'percent_lows', df_hin_omen.is_low.rolling(n_trading_day_window).sum() / n_trading_day_window)

Once you have run this, you can inspect the results as follows:

import matplotlib, matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(16, 6))
df_hin_omen.resample('w').mean().percent_highs.plot(ax=ax)
df_hin_omen.resample('w').mean().percent_lows.plot(ax=ax)

From the Hindenburg Omen Definition, "The Hindenburg Omen looks for a statistical deviation from the premise that under normal conditions, some stocks are either making new 52-week highs or new 52-week lows. It would be abnormal if both were occurring at the same time."

So from a look at our graph, my interpretation is that the stock market is currently closing at a lot of 52 week highs, but is not showing many 52 week lows. Please also note the article cited states that "It was reported that it had correctly predicted a significant stock market decline only 25% of the time." so I'm not sure if we can read too much into this...

enter image description here

Edit

I've had a look at your code and I don't think that the use of the pct_change function is correct - that will calculate the change on the rolling differential, so a movement from eg 0.10% to 0.11% would actually equate to a 10% change. Instead you want the rolling sum over the past year and divide that by the number of days in the year, per my code above.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!