
Business news as it should be.
Join 4M+ professionals who start their day with Morning Brew—the free newsletter that makes business news quick, clear, and actually enjoyable.
Each morning, it breaks down the biggest stories in business, tech, and finance with a touch of wit to keep things smart and interesting.
🚀 Your Investing Journey Just Got Better: Premium Subscriptions Are Here! 🚀
It’s been 4 months since we launched our premium subscription plans at GuruFinance Insights, and the results have been phenomenal! Now, we’re making it even better for you to take your investing game to the next level. Whether you’re just starting out or you’re a seasoned trader, our updated plans are designed to give you the tools, insights, and support you need to succeed.
Here’s what you’ll get as a premium member:
Exclusive Trading Strategies: Unlock proven methods to maximize your returns.
In-Depth Research Analysis: Stay ahead with insights from the latest market trends.
Ad-Free Experience: Focus on what matters most—your investments.
Monthly AMA Sessions: Get your questions answered by top industry experts.
Coding Tutorials: Learn how to automate your trading strategies like a pro.
Masterclasses & One-on-One Consultations: Elevate your skills with personalized guidance.
Our three tailored plans—Starter Investor, Pro Trader, and Elite Investor—are designed to fit your unique needs and goals. Whether you’re looking for foundational tools or advanced strategies, we’ve got you covered.
Don’t wait any longer to transform your investment strategy. The last 4 months have shown just how powerful these tools can be—now it’s your turn to experience the difference.
“Most quants lose money not because they can’t find patterns, but because they find too many that aren’t real.”
— David Leinweber, author of Nerds on Wall StreetWe believe that a key success factor of SMC trading is the ability to avoid knee-jerk decisions due to market noise.
The crucial point of SMC is that financial markets often exhibit repetitive patterns influenced by institutional participants (aka smart money). Recognizing these patterns can bring to light the hidden phases of accumulation, trend progression, and reversals.

SMC + EODHD Backtesting in a Nutshell (Modified Canva Template).
In this post, we’ll walk through backtesting (lookahead bias avoided) SMC Swing Highs & Lows as compared to the bullish/bearish Fair Value Gap (FVG) trading signals [1].
Core Library: smartmoneyconcepts 0.0.26 inspired by Inner Circle Trader (ICT) concepts like Order blocks, Liquidity, Fair Value Gap, Swing Highs and Lows, Break of Structure, Change of Character, and more.
!pip install smartmoneyconceptsChallenge [3]: Implement and (back)test robust algorithmic trading strategies that can help traders identify and manage false signals effectively, including fake reversals, breakouts, etc.
Objective: Backtest the following two SMC methods of the class smc with input_=”ohlc”:
swing_highs_lows (cls, ohlc: DataFrame, swing_length: int = 50)
Swing Highs and Lows
A swing high is when the current high is the highest high out of the swing_length amount of candles before and after.
A swing low is when the current low is the lowest low out of the swing_length amount of candles before and after.
Find your customers on Roku this Black Friday
As with any digital ad campaign, the important thing is to reach streaming audiences who will convert. To that end, Roku’s self-service Ads Manager stands ready with powerful segmentation and targeting options. After all, you know your customers, and we know our streaming audience.
Worried it’s too late to spin up new Black Friday creative? With Roku Ads Manager, you can easily import and augment existing creative assets from your social channels. We also have AI-assisted upscaling, so every ad is primed for CTV.
Once you’ve done this, then you can easily set up A/B tests to flight different creative variants and Black Friday offers. If you’re a Shopify brand, you can even run shoppable ads directly on-screen so viewers can purchase with just a click of their Roku remote.
Bonus: we’re gifting you $5K in ad credits when you spend your first $5K on Roku Ads Manager. Just sign up and use code GET5K. Terms apply.
Parameters:
swing_length: int — the amount of candles to look back and forward to determine the swing high or low.
Returns:
HighLow = 1 if swing high, -1 if swing low
Level = the level of the swing high or low
2. fvg (cls, ohlc: DataFrame, join_consecutive=False)
FVG — Fair Value Gap
A fair value gap is when the previous high is lower than the next low if the current candle is bullish.
Or when the previous low is higher than the next high if the current candle is bearish.
Parameters:
join_consecutive: bool — if there are multiple FVG in a row then they will be merged into one using the highest top and the lowest bottom
Returns:
FVG = 1 if bullish fair value gap, -1 if bearish fair value gap
Top = the top of the fair value gap
Bottom = the bottom of the fair value gap
MitigatedIndex = the index of the candle that mitigated the fair value gap.
The remainder of this paper is organized into three main steps:
Loading Stock Historical Data from EODHD API
Use real-time and historical stock data from reliable sources like EODHD API for producing realistic and trustworthy performance results with improved timing on breakout entries [3]. Recall that poor/incomplete data and subsequent data cleaning can unintentionally bias results [4].
2. Fair Value Gap (FVG) Trading Strategy
Identify price inefficiencies where the squares of the candlestick chart do not entirely overlap, thus producing zones with a high probability for trading.
3. Swing Highs & Lows Trading Strategy
Our main framework is to unveil swing highs and lows:
A swing high happens when a candle has two lower highs on either side.
A swing low is the opposite — one low candle with two higher lows on each side.
Once we’ve marked these two swings, we can figure out whether we’re in an uptrend (higher highs, higher lows) or a downtrend (lower highs, lower lows). That tells us whether to look for long (buy) or short (sell) setups.
This is to be benchmarked against the FVG.
Let’s break down the specifics of these steps.
Loading Stock Historical Data from EODHD API
!pip install eodhd
from eodhd import APIClient
import pandas as pd
api = APIClient("YOUR API CODE")
resp = api.get_eod_historical_stock_market_data(symbol = 'AAPL.US', period='d', from_date = '2025-01-01', to_date = '2025-10-09', order='a')
df = pd.DataFrame(resp)
df.tail()
     date      open          high         low         close       adjusted_close volume
187 2025-10-02 256.58000000 258.18000000 254.15000000 257.13000000 257.13000000 42630200
188 2025-10-03 254.67000000 259.24000000 253.95000000 258.02000000 258.02000000 49155600
189 2025-10-06 257.99000000 259.07000000 255.05000000 256.69000000 256.69000000 44664100
190 2025-10-07 256.81000000 257.40000000 255.43000000 256.48000000 256.48000000 31955800
191 2025-10-08 256.52000000 258.52000000 256.11000000 258.06000000 258.06000000 36465000Examining the overall structure of this dataset
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 192 entries, 0 to 191
Data columns (total 7 columns):
 #   Column          Non-Null Count  Dtype  
---  ------          --------------  -----  
 0   date            192 non-null    object 
 1   open            192 non-null    float64
 2   high            192 non-null    float64
 3   low             192 non-null    float64
 4   close           192 non-null    float64
 5   adjusted_close  192 non-null    float64
 6   volume          192 non-null    int64  
dtypes: float64(5), int64(1), object(1)
memory usage: 10.6+ KBVisualizing OHLC & Volume with Plotly
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# Create subplots and mention plot grid size
fig = make_subplots(rows=2, cols=1, shared_xaxes=True, 
               vertical_spacing=0.03, subplot_titles=('OHLC AAPL.US', 'Volume'), 
               row_width=[0.2, 0.7])
# Plot OHLC on 1st row
fig.add_trace(go.Candlestick(x=df["date"], open=df["open"], high=df["high"],
                low=df["low"], close=df["close"], name="OHLC"), 
                row=1, col=1
)
# Bar trace for volumes on 2nd row without legend
fig.add_trace(go.Bar(x=df['date'], y=df['volume'], showlegend=False), row=2, col=1)
# Do not show OHLC's rangeslider plot 
fig.update(layout_xaxis_rangeslider_visible=False)
fig.show()
OHLC & Volume AAPL.US 2025
200+ AI Side Hustles to Start Right Now
From prompt engineering to AI apps, there are countless ways to profit from AI now. Our guide reveals 200+ actionable AI business models, from no-code solutions to advanced applications. Learn how people are earning $500-$10,000 monthly with tools that didn't exist last year. Sign up for The Hustle to get the guide and daily insights.
Using the column “date” to set the time series index
df_ind = df.set_index(['date'])
ohlc=df_ind.copy()Fair Value Gap (FVG) Trading Strategy
Applying the smc.fvg method [1] to our data
myfvg=smc.fvg(ohlc, join_consecutive=False)
myfvg.columns
Index(['FVG', 'Top', 'Bottom', 'MitigatedIndex'], dtype='object')Creating a DF with the FVG column
df = pd.DataFrame(index=(ohlc.index))
mylist=myfvg["FVG"]
se = pd.Series(mylist)
df['FVG']=se.valuesComputing the bullish and bearish FVG entry signals
bullsignals = ohlc['close'][df["FVG"] == 1]
bearsignals = ohlc['close'][df["FVG"] == -1]Visualizing these trading signals [2]
plt.plot(ohlc['close'],alpha=0.4)
for idx in bullsignals.index:
  plt.plot(
      idx,
      ohlc.loc[idx]["close"],
      "g*",
      markersize=25
  )
for idx in bearsignals.index:
  plt.plot(
      idx,
      ohlc.loc[idx]["close"],
      "r*",
      markersize=25
  )
plt.xticks([])
plt.title('AAPL.US FVG Bullish (Green) / Bearish (Red) Signals')
plt.ylabel('Price USD')
listOf_Xticks = np.arange(0, 192, 35)
plt.xticks(listOf_Xticks)   
plt.show()
AAPL.US FVG Bullish (Green) / Bearish (Red) Signals
Backtesting the FVG strategy by creating position
position = []
df["FVG"]=df["FVG"].shift(1)
for i in range(len(ohlc['close'])):
        position.append(0)
        
for i in range(len(ohlc['close'])):
    if df["FVG"][i] == 1:
        position[i] = 1
    elif df["FVG"][i] == -1:
        position[i] = 0
    else:
        position[i] = position[i-1]Calculating and plotting daily/cumulative returns of the FVG strategy
rets = ohlc.close.pct_change()[1:]
strat_rets = position[1:] * rets
plt.title('Daily Returns')
rets.plot(color = 'blue', alpha = 0.3, linewidth = 7,label='Buy&Hold')
strat_rets.plot(color = 'r', linewidth = 1,label='FVG')
plt.legend()
plt.show()
rets_cum = (1 + rets).cumprod() - 1 
strat_cum = (1 + strat_rets).cumprod() - 1
plt.title('Cumulative Returns')
rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7,label='Buy&Hold')
strat_cum.plot(color = 'r', linewidth = 2,label='FVG')
plt.legend()
plt.show()
FVG Strategy Daily Returns

FVG Strategy Cumulative Returns
Swing Highs & Lows Trading Strategy
Applying the smc.swing_highs_lows method [1] with weekly swings to our data
myswing=smc.swing_highs_lows(ohlc, swing_length = 5)
myswing.columns
Index(['HighLow', 'Level'], dtype='object')Creating a DF with the HighLow column
dfs = pd.DataFrame(index=(ohlc.index))
mylist=myswing["HighLow"]
se = pd.Series(mylist)
dfs['HighLow']=se.valuesDetecting Swing-5 Highs and Lows
highsignals = ohlc['close'][dfs["HighLow"] == 1]
lowsignals = ohlc['close'][dfs["HighLow"] == -1]Visualizing these Highs and Lows [2]
plt.plot(ohlc['close'],alpha=0.4)
for idx in highsignals.index.tolist():
  plt.plot(
      idx,
      ohlc.loc[idx]["close"],
      "g*",
      markersize=25
  )
for idx in lowsignals.index.tolist():
  plt.plot(
      idx,
      ohlc.loc[idx]["close"],
      "r*",
      markersize=25
  )
plt.xticks([])
plt.title('AAPL.US FVG Swing-5 Highs (Green) & Lows (Red) Signals')
plt.ylabel('Price USD')
listOf_Xticks = np.arange(0, 192, 35)
plt.xticks(listOf_Xticks)  
plt.show()
AAPL.US FVG Swing-5 Highs (Green) & Lows (Red) Signals
Compared to the FVG, the present strategy provides more distinct and interpretable trading signals, facilitating more reliable decision-making. These signals are better aligned with true market movements than those of the FVG.
Backtesting the Swing-5 Highs and Lows by creating position
dfs["HighLow"]=dfs["HighLow"].shift(1)
position = []
for i in range(len(ohlc['close'])):
        position.append(0)
        
for i in range(len(ohlc['close'])):
    if dfs["HighLow"][i] == -1:
        position[i] = 1
    elif dfs["HighLow"][i] == 1:
        position[i] = 0
    else:
        position[i] = position[i-1]Calculating and plotting daily/cumulative returns of Swing-5 Highs and Lows
rets = ohlc.close.pct_change()[1:]
strat_rets = position[1:] * rets
plt.title('Daily Returns')
rets.plot(color = 'blue', alpha = 0.3, linewidth = 7,label='Buy&Hold')
strat_rets.plot(color = 'r', linewidth = 1,label='Swing Highs & Lows')
plt.legend()
plt.show()
rets_cum = (1 + rets).cumprod() - 1 
strat_cum = (1 + strat_rets).cumprod() - 1
plt.title('Cumulative Returns')
rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7,label='Buy&Hold')
strat_cum.plot(color = 'r', linewidth = 2,label='Swing Highs & Lows')
plt.legend()
plt.show()
Swing-5 Highs and Lows Daily Returns

Swing-5 Highs and Lows Cumulative Returns
Observe that the above strategy delivers cumulative returns roughly 9× higher than the FVG and 35× higher than Buy & Hold during the testing period.
Conclusions
This paper demonstrates the effectiveness of the SMC Swing Highs & Lows strategy compared with FVG and Buy & Hold benchmarks.
Expected returns were calculated using a look-ahead bias-free backtesting analysis of AAPL.US stock data from 2025–01–02 to 2025–10–08.
If you’re a swing trader aiming to avoid liquidity sweeps and market manipulation traps, it’s essential to understand this approach.





