Global Macro 30-Min Inside Bar Breakout

🦊 Premium Script

Strategy Overview: The Global Macro 30-Min Inside Bar Breakout is a potent, pure price-action framework engineered to exploit volatility compression and subsequent expansion. Completely devoid of lagging indicators, this algorithm systematically scans the 30-minute timeframe to identify “Inside Bars”β€”periods where price action is entirely engulfed by the preceding “Mother Bar,” signaling a state of market equilibrium and coiled energy. When the Nifty aggressively breaks above the Mother Bar’s high, the script fires a long entry to capture the bullish expansion. Conversely, a decisive breakdown below the Mother Bar’s low triggers a short position to ride the bearish cascade. The strategy utilizes robust asymmetric risk management, targeting 100-point profit zones while rigidly capping drawdowns with a 50-point stop loss. To ensure seamless execution, it employs a dynamic tracking system that forward-fills the Mother Bar parameters until a breakout materializes. A built-in reversal mechanism guarantees that if a false breakout occurs, the algorithm instantly flips its directional bias to catch the true momentum wave. Finally, an automated 15:15 time-based exit protocol aggressively squares off all open positions, neutralizing overnight gap risks and locking in intraday alpha.

πŸ“ˆ EXPECTED WIN RATE
38.34%
πŸ“‰ MAX DRAWDOWN
808 Pts
πŸ’° TOTAL PNL
+11,617 Pts
πŸ”„ TOTAL TRADES
1664
πŸ† TOTAL WINS
638
!
Important This strategy is configured for the 30-minute timeframe. It utilizes Pandas .shift(1) and .ffill() to correctly map and persist the Mother Bar highs and lows until a definitive price action breakout occurs.
ℹ️
Disclaimer These results are generated based on automated backtesting performed using Python code and algorithms. Actual results may vary, and manual backtesting outcomes could differ due to varying assumptions, data interpretation, and market conditions. This information is provided for educational and informational purposes only and should not be considered as financial advice. Before making any trading or investment decisions, please consult with a qualified financial advisor or professional.

1. Imports and Configuration

Summary: This section establishes the base libraries and configurable variables. It configures the algorithm to run on a 30-minute timeframe, enforces the 15:15 automated exit, and defines the structural risk parameters (50-point stop loss and 100-point profit).

python script Copy Code
import pandas as pd
import numpy as np
import datetime as dt

# ===================== CONFIG =====================
FILE_PATH = "Index_1_minute.csv"  
DAYFIRST = True                    
EXIT_TIME = dt.time(15, 15)        
SLIPPAGE = 0.5                     

# Strategy params
TIMEFRAME = "30min"   

# Risk Management
STOP_LOSS_POINTS = 50.0            
TARGET_POINTS = 100.0              
# ==================================================

2. Data Loading and Preparation

Summary: This segment reliably processes historical CSV data by parsing date strings into standardized datetime objects, converting price fields into numeric values, eliminating missing entries, and aggregating minute-level data into well-structured 30-minute OHLC candles.

python script Copy Code
# ----------------- LOAD & PREP --------------------
print("Loading and preparing data...")
df = pd.read_csv(FILE_PATH)
df.columns = [c.strip().lower() for c in df.columns]
required = {"date","open","high","low","close"}
missing = required - set(df.columns)
if missing:
    raise ValueError(f"CSV missing columns: {missing}. Need exactly {sorted(required)}")

df["dt"] = pd.to_datetime(df["date"], dayfirst=DAYFIRST)
df = df.sort_values("dt").reset_index(drop=True)

for c in ["open","high","low","close"]:
    df[c] = pd.to_numeric(df[c], errors="coerce")
df = df.dropna(subset=["open","high","low","close","dt"]).copy()

# Resampling
df = df.set_index("dt").resample(TIMEFRAME).agg({
    "open": "first",
    "high": "max",
    "low": "min",
    "close": "last"
}).dropna().reset_index()

df["d"] = df["dt"].dt.date
df["t"] = df["dt"].dt.time

3. Inside Bar Pattern Recognition

Summary: The core logic that shifts the data to compare current bars against previous ones. It flags a candle as an “inside bar” if its high is lower than the previous high and its low is higher than the previous low. Crucially, it then uses ffill() to persist those Mother Bar limits until a breakout trigger fires.

python script Copy Code
# ----------------- INDICATORS --------------------
print("Finding Inside Bars and Mother Bar levels...")

# Shift data to compare with the previous candle
df["prev_high"] = df["high"].shift(1)
df["prev_low"] = df["low"].shift(1)
df["prev_close"] = df["close"].shift(1)

# An inside bar has a lower high and a higher low than the preceding candle
is_inside = (df["high"] < df["prev_high"]) & (df["low"] > df["prev_low"])

# Store the Mother Bar High and Low when an inside bar is detected
df["mother_high"] = np.where(is_inside, df["prev_high"], np.nan)
df["mother_low"] = np.where(is_inside, df["prev_low"], np.nan)

# Forward fill the levels so they remain active until a new inside bar forms
df["mother_high"] = df["mother_high"].ffill()
df["mother_low"] = df["mother_low"].ffill()

4. Utility Functions

Summary: Helper functions for evaluating backtest health. The stats block computes win rate and general PnL, while close_out systematically records long versus short point differentials upon trade exit.

python script Copy Code
# -------------- UTILITIES ----------------
def stats(trades):
    if not trades:
        return {"trades":0,"wins":0,"win_rate":0.0,"avg_pnl":0.0,"total_pnl":0.0}
    pnl = np.array([x["pnl"] for x in trades])
    wins = (pnl > 0).sum()
    return {
        "trades": len(trades),
        "wins": int(wins),
        "win_rate": round(100*wins/len(trades), 2),
        "avg_pnl": round(pnl.mean(), 2),
        "total_pnl": round(pnl.sum(), 2),
    }

def close_out(direction, entry, row_close):
    return (row_close - entry) if direction=="long" else (entry - row_close)

5. The Core Backtest Engine

Summary: Iterates row by row through the market data. It calculates SL/TP conditions dynamically, manages the 15:15 structural time exit, and initiates positions when a confirmed crossover of the Mother Bar limits takes place. If a breakout collapses back through the opposite bound, the system executes an automatic reversal trade.

python script Copy Code
# -------------- STRATEGY: INSIDE BAR BREAKOUT --------------
def backtest_inside_bar(df):
    print("Running backtest loop...")
    trades = []
    in_trade = False
    direction = None
    entry = None
    entry_time = None

    for _, r in df.iterrows():
        # 1. INTRADAY TIME EXIT
        if r["t"] >= EXIT_TIME:
            if in_trade:
                pnl = close_out(direction, entry, r["close"]) - SLIPPAGE
                trades.append({
                    "date": r["d"], "entry_time": entry_time, "exit_time": r["dt"],
                    "strategy":"INSIDE_BAR", "dir":direction, "entry":entry,
                    "exit":r["close"], "pnl":pnl, "outcome":"TIME_EXIT"
                })
                in_trade = False
            continue

        if pd.isna(r["mother_high"]) or pd.isna(r["mother_low"]):
            continue

        # 2. SL / TP LOGIC
        if in_trade:
            sl_hit = False
            tp_hit = False
            exit_price = None
            outcome = None

            # Check conservative High/Low hits within the current candle
            if direction == "long":
                if r["low"] <= entry - STOP_LOSS_POINTS:
                    sl_hit = True
                    exit_price = entry - STOP_LOSS_POINTS
                    outcome = "STOP_LOSS"
                elif r["high"] >= entry + TARGET_POINTS:
                    tp_hit = True
                    exit_price = entry + TARGET_POINTS
                    outcome = "TARGET"
            elif direction == "short":
                if r["high"] >= entry + STOP_LOSS_POINTS:
                    sl_hit = True
                    exit_price = entry + STOP_LOSS_POINTS
                    outcome = "STOP_LOSS"
                elif r["low"] <= entry - TARGET_POINTS:
                    tp_hit = True
                    exit_price = entry - TARGET_POINTS
                    outcome = "TARGET"

            # If stopped out or target reached, close the trade
            if sl_hit or tp_hit:
                pnl = close_out(direction, entry, exit_price) - SLIPPAGE
                trades.append({
                    "date": r["d"], "entry_time": entry_time, "exit_time": r["dt"],
                    "strategy":"INSIDE_BAR", "dir":direction, "entry":entry,
                    "exit":exit_price, "pnl":pnl, "outcome":outcome
                })
                in_trade = False
                direction = None
                entry = None
                entry_time = None
                # Skip entry logic on the same candle we hit SL/TP
                continue

        # Signal Logic - Ensure it's a fresh crossover, not just sitting above/below the line
        breakout_up = (r["close"] > r["mother_high"]) and (r["prev_close"] <= r["mother_high"])
        breakout_down = (r["close"] < r["mother_low"]) and (r["prev_close"] >= r["mother_low"])

        # 3. ENTRY LOGIC
        if not in_trade:
            if breakout_up:
                direction = "long"
                entry = r["close"]
                entry_time = r["dt"]
                in_trade = True
            elif breakout_down:
                direction = "short"
                entry = r["close"]
                entry_time = r["dt"]
                in_trade = True

        # 4. REVERSAL LOGIC
        else:
            if direction=="long" and breakout_down:
                exit_price = r["close"]
                pnl = (exit_price - entry) - SLIPPAGE
                trades.append({
                    "date": r["d"], "entry_time": entry_time, "exit_time": r["dt"],
                    "strategy":"INSIDE_BAR", "dir":"long", "entry":entry,
                    "exit":exit_price, "pnl":pnl, "outcome":"REVERSE"
                })
                # Reverse to short
                direction = "short"
                entry = r["close"]
                entry_time = r["dt"]

            elif direction=="short" and breakout_up:
                exit_price = r["close"]
                pnl = (entry - exit_price) - SLIPPAGE
                trades.append({
                    "date": r["d"], "entry_time": entry_time, "exit_time": r["dt"],
                    "strategy":"INSIDE_BAR", "dir":"short", "entry":entry,
                    "exit":exit_price, "pnl":pnl, "outcome":"REVERSE"
                })
                # Reverse to long
                direction = "long"
                entry = r["close"]
                entry_time = r["dt"]

    return trades

6. Execution and Reporting

Summary: Acts as the execution trigger. Once the backtest loops complete, it outputs high-level data to the console and subsequently processes all individual trade logs into a segmented Excel file (inside_bar_results.xlsx) for deep dive drawdown and weekly/monthly performance reviews.

python script Copy Code
# -------------- EXECUTION & REPORTING --------------
ib_trades = backtest_inside_bar(df)
summary = {"INSIDE_BAR": stats(ib_trades)}

print(f"βœ… Backtest complete ({TIMEFRAME} candles)")
for name, s in summary.items():
    print(f"\n{name} -> Trades: {s['trades']}, Wins: {s['wins']}, WinRate: {s['win_rate']}%, "
          f"AvgPnL: {s['avg_pnl']}, TotalPnL: {s['total_pnl']}")

# Write results to Excel
output_file = "inside_bar_results.xlsx"
print(f"\nSaving results to {output_file}...")

with pd.ExcelWriter(output_file, engine="xlsxwriter") as writer:
    if ib_trades:
        trades_df = pd.DataFrame(ib_trades)
        trades_df.to_excel(writer, sheet_name="INSIDE_BAR", index=False)

        trades_df["date_dt"] = pd.to_datetime(trades_df["date"])
        trades_df["week"] = trades_df["date_dt"].dt.to_period("W-FRI")
        weekly = trades_df.groupby("week", as_index=False)["pnl"].sum()
        weekly.rename(columns={"pnl": "total_points"}, inplace=True)
        weekly["week"] = weekly["week"].astype(str)
        weekly.to_excel(writer, sheet_name="Weekly_Report", index=False)

        trades_df["month"] = trades_df["date_dt"].dt.to_period("M")
        monthly = trades_df.groupby("month", as_index=False)["pnl"].sum()
        monthly.rename(columns={"pnl": "total_points"}, inplace=True)
        monthly["month"] = monthly["month"].astype(str)
        monthly.to_excel(writer, sheet_name="Monthly_Report", index=False)

        dd_rows = []
        for m, mdf in trades_df.groupby("month"):
            mdf = mdf.sort_values("exit_time")
            cum = mdf["pnl"].cumsum()
            max_dd = cum.min()
            dd_rows.append({"month": str(m), "max_drawdown": max_dd})
        dd_df = pd.DataFrame(dd_rows)
        dd_df.to_excel(writer, sheet_name="Drawdown_Report", index=False)

    pd.DataFrame([{"strategy": k, **v} for k, v in summary.items()]).to_excel(
        writer, sheet_name="Summary", index=False
    )

print("Process finished successfully.")