This is an extension of Tutorial 06. It adds a "histogram strength filter" to the MACD backtest. Instead of trading every time MACD crosses the Signal line, it only trades when the MACD histogram is strong enough (above a minimum threshold). This filters out weak signals and only keeps the high-conviction ones.
The histogram is the difference between the MACD line and the Signal line:
Histogram = MACD Line - Signal Line
The key insight: not all crossovers are equal. A crossover with a tiny histogram is a weak signal. A crossover with a large histogram is a strong signal.
| Threshold | Meaning | Effect |
|---|---|---|
| 1 | Very low - almost any signal passes | Many trades, lower quality |
| 5 | Low - moderate filter | Still many trades |
| 10 | Medium - only decent signals | Fewer trades, better quality |
| 20 | High - only strong signals | Very few trades, highest quality |
| 50 | Very high - only extreme signals | Tiny number of trades |
| 100 | Extreme - only the strongest | Almost no trades |
The script tests a nested grid of parameter combinations:
Why this matters: In trading, there's a tradeoff between signal quality and quantity. Low thresholds give you many trades but more noise. High thresholds give you fewer but higher-quality trades. The backtest finds the sweet spot.
# For each MACD parameter combination...
for fast, slow, signal_period in MACD_COMBOS:
# Compute MACD with these parameters
compute_macd(df, fast, slow, signal_period)
build_5min_markets(df)
# For each histogram threshold...
for threshold in HIST_THRESHOLDS:
# Only keep markets where |histogram| >= threshold
filtered = markets[abs(markets['histogram_at_open']) >= threshold]
# Calculate win rate and P&L on filtered trades
simulate_pnl(filtered)
What it does: For every combination of MACD settings and histogram thresholds, it filters the signals and simulates trading. This creates a grid of results that can be compared.
# Only show combos with positive edge (above breakeven)
positive = results_df[results_df['edge'] > 0]
for _, row in positive.iterrows():
print(f"MACD({row['fast']}/{row['slow']}/{row['signal_period']}) hist>{row['hist_threshold']} | "
f"Trades: {row['trades']} | WR: {row['win_rate']:.2f}% | "
f"Edge: +{row['edge']:.2f}% | P&L: ${row['pnl']:,.2f}")
What it does: Sorts all results by edge and only shows the ones that are profitable. This helps you quickly see which parameter combinations actually work.
Best reported result: MACD(6/20/5) with histogram > 10 gives 55.12% win rate with +$480 P&L.
How to read results:
Warning: A strategy that looks great in backtesting may not work in live trading due to slippage, fees, market impact, and changing market conditions.
pip install pandas pandas_ta numpy
| Term | Meaning |
|---|---|
| Histogram | The difference between MACD line and Signal line, shown as bars |
| Threshold | A minimum value that must be exceeded for a signal to be used |
| Filter | A rule that removes weak or unwanted signals |
| Grid Search | Testing all combinations of multiple parameters |
| Overfitting | When a strategy works on historical data but fails on new data |
| Edge | The statistical advantage of a strategy over random/breakeven |
# --- PYTHON ---
MACD_COMBOS = [(6, 20, 5), (6, 26, 5)]
HIST_THRESHOLDS = [1, 5, 10, 20, 50, 100]
ENTRY_PRICE = 0.54
USD_PER_BET = 10.0
# --- PSEUDO-CODE ---
SET the MACD parameter combinations to test:
Combo 1: fast=6, slow=20, signal=5
Combo 2: fast=6, slow=26, signal=5
SET the histogram strength thresholds to test: 1, 5, 10, 20, 50, 100
SET Polymarket entry price to $0.54 per share
SET bet size to $10 per trade
# --- PYTHON ---
shares_per_bet = USD_PER_BET / ENTRY_PRICE # 10.0 / 0.54 = ~18.5
win_profit = (1.0 - ENTRY_PRICE) * shares_per_bet # ~$8.52
loss_amount = ENTRY_PRICE * shares_per_bet # ~$10.00
breakeven_wr = loss_amount / (win_profit + loss_amount) * 100 # ~54%
# --- PSEUDO-CODE ---
CALCULATE shares per bet = $10.00 / $0.54 = about 18.5 shares
CALCULATE profit per win = ($1.00 - $0.54) x 18.5 = about $8.52
CALCULATE loss per loss = $0.54 x 18.5 = about $10.00
CALCULATE breakeven win rate = $10.00 / ($8.52 + $10.00) = about 54%
(You need to win more than 54% of bets to be profitable)
# --- PYTHON ---
for fast, slow, signal in MACD_COMBOS:
macd_result = ta.macd(df['close'], fast=fast, slow=slow, signal=signal)
df_temp['macd_line'] = macd_result[...]
df_temp['macd_signal'] = macd_result[...]
df_temp['macd_histogram'] = macd_result[...]
# Build 5-min markets
markets = df_temp.groupby('market_start').agg(...)
# For each threshold
for threshold in HIST_THRESHOLDS:
filtered = markets[markets['histogram_at_open'].abs() > threshold]
filtered['pick'] = np.where(
filtered['macd_at_open'] > filtered['signal_at_open'], 'UP', 'DOWN')
filtered['win'] = filtered['pick'] == filtered['actual']
trades = len(filtered)
wins = filtered['win'].sum()
win_rate = wins / trades * 100
edge = win_rate - breakeven_wr
total_pnl = wins * win_profit - (trades - wins) * loss_amount
# --- PSEUDO-CODE ---
FOR EACH MACD parameter combination (fast, slow, signal):
CALCULATE MACD using these specific parameters
ADD macd_line, macd_signal, and macd_histogram columns to data
GROUP 1-minute data into 5-minute market windows
FOR EACH histogram threshold value (1, 5, 10, 20, 50, 100):
FILTER: keep ONLY markets where the absolute histogram value
is GREATER THAN the threshold
(This removes weak signals)
FOR each remaining market:
IF MACD > Signal at market open: PREDICT "UP"
ELSE: PREDICT "DOWN"
CHECK: did the prediction match the actual outcome?
COUNT total trades, wins, losses
CALCULATE win rate = wins / total trades x 100
CALCULATE edge = win rate minus breakeven (54%)
CALCULATE total P&L = (wins x profit) - (losses x loss_amount)
RECORD all these results
# --- PYTHON ---
results_df = pd.DataFrame(all_results).sort_values('edge', ascending=False)
positive = results_df[results_df['edge'] > 0]
for _, row in positive.iterrows():
print(f"MACD({row['fast']}/{row['slow']}/{row['signal_period']}) "
f"hist>{row['hist_threshold']} | "
f"Trades: {row['trades']} | WR: {row['win_rate']:.2f}% | "
f"Edge: +{row['edge']:.2f}% | P&L: ${row['pnl']:,.2f}")
# --- PSEUDO-CODE ---
COMPILE all results into a table
SORT by edge (best edge first)
FILTER to show ONLY combinations with positive edge (above breakeven)
FOR each profitable combination:
PRINT in a readable format:
"MACD(6/20/5) with histogram > 10 |
5420 trades | 55.12% win rate |
+1.12% edge over breakeven |
$480 total profit"
SAVE all results to a CSV file for later analysis