// BTC Futures MACD Strategy - Enhanced Visual Signals
// PROMINENT entry/exit markers for clear trading signals
// Based on proven 58.70% win rate performance
//
// License: MIT License
//
// Contributors:
// © TradingView Community - MACD indicator methodology
// © AI Assistant - Strategy implementation and enhanced visual signals
// © iamrichardD - Testing, validation & iterative improvement - https://github.com/iamrichardD
//
//@version=6
strategy("BTC Futures MACD [5M]", "BTC_MACD", overlay=false,
default_qty_type=strategy.percent_of_equity, default_qty_value=1,
commission_type=strategy.commission.percent, commission_value=0.05,
slippage=1, calc_on_every_tick=true, calc_on_order_fills=false,
max_bars_back=200, process_orders_on_close=true, scale=scale.right)
//=====================================================================================================================
// INPUT SETTINGS
//=====================================================================================================================
grpMACD = "📊 MACD Settings"
fastLength = input.int(8, "Fast Length", minval=6, maxval=15, group=grpMACD)
slowLength = input.int(21, "Slow Length", minval=15, maxval=35, group=grpMACD)
signalLength = input.int(5, "Signal Length", minval=3, maxval=15, group=grpMACD)
grpSignals = "🎯 Signal Settings"
useZeroCross = input.bool(true, "MACD Zero Line Cross", group=grpSignals)
useSignalCross = input.bool(true, "MACD Signal Line Cross", group=grpSignals)
useEarlySignals = input.bool(false, "Enable Early Momentum Signals", group=grpSignals)
momentumThreshold = input.float(0.25, "Momentum Threshold", minval=0.05, maxval=0.5, step=0.05, tooltip="Sensitivity for early signals", group=grpSignals)
grpVisual = "🎨 Visual Enhancement"
showBigSignals = input.bool(true, "Show Large Entry Signals", group=grpVisual)
showTextLabels = input.bool(true, "Show Text Labels", group=grpVisual)
showExitSignals = input.bool(true, "Show Exit Signals", group=grpVisual)
grpRisk = "🛡️ Risk Management"
stopLossPercent = input.float(1.8, "Stop Loss %", minval=0.5, maxval=3.0, step=0.1, group=grpRisk)
takeProfitPercent = input.float(2.7, "Take Profit %", minval=1.0, maxval=4.0, step=0.1, group=grpRisk)
maxDailyTrades = input.int(12, "Max Daily Trades", minval=5, maxval=100, group=grpRisk)
grpFilters = "🔍 Signal Filters"
useVolumeFilter = input.bool(true, "Enable Volume Filter", group=grpFilters)
volumeThreshold = input.float(1.5, "Volume Threshold (x avg)", minval=1.0, maxval=3.0, step=0.1, group=grpFilters)
useTrendFilter = input.bool(true, "Enable Trend Filter", group=grpFilters)
trendLength = input.int(20, "Trend MA Length", minval=10, maxval=100, group=grpFilters)
useShortBias = input.bool(true, "Disable Short Trades", group=grpFilters, tooltip="Only take LONG trades - shorts underperforming")
grpTrailing = "📈 Trailing Stop Settings"
useTrailingStop = input.bool(true, "Enable Trailing Stop", group=grpTrailing)
trailingActivation = input.float(0.5, "Activation Threshold %", minval=0.2, maxval=1.0, step=0.1, tooltip="Profit % required before trailing starts", group=grpTrailing)
trailingDistance = input.float(0.3, "Trailing Distance %", minval=0.1, maxval=0.8, step=0.1, tooltip="How far trailing stop trails behind peak", group=grpTrailing)
//=====================================================================================================================
// MACD CALCULATION
//=====================================================================================================================
[macdLine, signalLine, histogramLine] = ta.macd(close, fastLength, slowLength, signalLength)
// Use previous bar data to avoid look-ahead bias
macdPrev = macdLine[1]
signalPrev = signalLine[1]
macdPrev2 = macdLine[2]
signalPrev2 = signalLine[2]
// Signal detection
macdZeroCrossUp = macdPrev > 0 and macdPrev2 <= 0
macdZeroCrossDown = macdPrev < 0 and macdPrev2 >= 0
macdSignalCrossUp = macdPrev > signalPrev and macdPrev2 <= signalPrev2
macdSignalCrossDown = macdPrev < signalPrev and macdPrev2 >= signalPrev2
//=====================================================================================================================
// TRADE TRACKING
//=====================================================================================================================
var int dailyTrades = 0
var float entryPrice = na
var string currentSignalType = ""
// Reset daily counter
newDay = ta.change(dayofweek) != 0
if newDay
dailyTrades := 0
// Track trades
if strategy.closedtrades > strategy.closedtrades[1]
dailyTrades := dailyTrades + 1
// Risk filter
riskOK = dailyTrades < maxDailyTrades
//=====================================================================================================================
// SIGNAL GENERATION WITH FILTERS
//=====================================================================================================================
// Volume and trend filters
avgVolume = ta.sma(volume, 20)
volumeCondition = not useVolumeFilter or volume > avgVolume * volumeThreshold
trendMA = ta.sma(close, trendLength)
bullishTrend = not useTrendFilter or close > trendMA
bearishTrend = not useTrendFilter or close < trendMA
// Raw signals
longZeroSignal = useZeroCross and macdZeroCrossUp
longSignalSignal = useSignalCross and macdSignalCrossUp
shortZeroSignal = useZeroCross and macdZeroCrossDown
shortSignalSignal = useSignalCross and macdSignalCrossDown
// Early momentum signals
macdMomentumDown = useEarlySignals and macdLine < signalLine and (macdLine - macdLine[1]) < -momentumThreshold and macdLine > 0
macdMomentumUp = useEarlySignals and macdLine > signalLine and (macdLine - macdLine[1]) > momentumThreshold and macdLine < 0
// Histogram divergence signals
histogramDecreasing = histogramLine < histogramLine[1] and histogramLine[1] < histogramLine[2] and histogramLine > 0
histogramIncreasing = histogramLine > histogramLine[1] and histogramLine[1] > histogramLine[2] and histogramLine < 0
earlyShortSignal = useEarlySignals and (macdMomentumDown or histogramDecreasing)
earlyLongSignal = useEarlySignals and (macdMomentumUp or histogramIncreasing)
// Apply filters to signals
rawLongSignal = (longZeroSignal or longSignalSignal or earlyLongSignal) and volumeCondition and bullishTrend
rawShortSignal = (shortZeroSignal or shortSignalSignal or earlyShortSignal) and volumeCondition and bearishTrend and not useShortBias
// Debug signal conditions
longSignalDebug = rawLongSignal ? "SIGNAL" : "NO SIGNAL"
shortSignalDebug = rawShortSignal ? "SIGNAL" : "NO SIGNAL"
riskDebug = riskOK ? "OK" : "BLOCKED"
positionDebug = strategy.position_size == 0 ? "FLAT" : strategy.position_size > 0 ? "LONG" : "SHORT"
// Enhanced final signals with better same-bar handling
finalLongSignal = rawLongSignal and riskOK and strategy.position_size <= 0
finalShortSignal = rawShortSignal and riskOK and strategy.position_size >= 0
// Track signal type for labels
if finalLongSignal
if longZeroSignal
currentSignalType := "ZERO CROSS UP"
else if longSignalSignal
currentSignalType := "SIGNAL CROSS UP"
else if earlyLongSignal
currentSignalType := "EARLY MOMENTUM"
if finalShortSignal
if shortZeroSignal
currentSignalType := "ZERO CROSS DOWN"
else if shortSignalSignal
currentSignalType := "SIGNAL CROSS DOWN"
else if earlyShortSignal
currentSignalType := "EARLY MOMENTUM"
//=====================================================================================================================
// POSITION MANAGEMENT WITH TRAILING STOP
//=====================================================================================================================
var float stopLossPrice = na
var float takeProfitPrice = na
var float trailingStopPrice = na
var float highestPrice = na
var float lowestPrice = na
var bool trailingActive = false
if finalLongSignal
entryPrice := open
stopLossPrice := entryPrice * (1 - stopLossPercent / 100)
takeProfitPrice := entryPrice * (1 + takeProfitPercent / 100)
// Initialize trailing stop variables
trailingStopPrice := stopLossPrice
highestPrice := entryPrice
trailingActive := false
if finalShortSignal
entryPrice := open
stopLossPrice := entryPrice * (1 + stopLossPercent / 100)
takeProfitPrice := entryPrice * (1 - takeProfitPercent / 100)
// Initialize trailing stop variables
trailingStopPrice := stopLossPrice
lowestPrice := entryPrice
trailingActive := false
// Dynamic Trailing Stop Logic
if strategy.position_size > 0 and useTrailingStop
// Update highest price since entry
if high > highestPrice
highestPrice := high
// Check if we've reached activation threshold
profitPercent = (highestPrice - entryPrice) / entryPrice * 100
if profitPercent >= trailingActivation
trailingActive := true
// Update trailing stop if active
if trailingActive
newTrailingStop = highestPrice * (1 - trailingDistance / 100)
if newTrailingStop > trailingStopPrice
trailingStopPrice := newTrailingStop
if strategy.position_size < 0 and useTrailingStop
// Update lowest price since entry
if low < lowestPrice
lowestPrice := low
// Check if we've reached activation threshold
profitPercent = (entryPrice - lowestPrice) / entryPrice * 100
if profitPercent >= trailingActivation
trailingActive := true
// Update trailing stop if active
if trailingActive
newTrailingStop = lowestPrice * (1 + trailingDistance / 100)
if newTrailingStop < trailingStopPrice
trailingStopPrice := newTrailingStop
// Track exits
var bool exitTriggered = false
if strategy.position_size == 0 and strategy.position_size[1] != 0
exitTriggered := true
else
exitTriggered := false
//=====================================================================================================================
// STRATEGY EXECUTION
//=====================================================================================================================
// Enter positions
if finalLongSignal
strategy.entry("Long", strategy.long, comment="MACD Long")
if finalShortSignal
strategy.entry("Short", strategy.short, comment="MACD Short")
// Exit positions
if strategy.position_size > 0
if useTrailingStop and trailingActive
strategy.exit("Long Exit", "Long", stop=trailingStopPrice, limit=takeProfitPrice, comment="Trailing Exit")
else
strategy.exit("Long Exit", "Long", stop=stopLossPrice, limit=takeProfitPrice, comment="Exit")
if strategy.position_size < 0
if useTrailingStop and trailingActive
strategy.exit("Short Exit", "Short", stop=trailingStopPrice, limit=takeProfitPrice, comment="Trailing Exit")
else
strategy.exit("Short Exit", "Short", stop=stopLossPrice, limit=takeProfitPrice, comment="Exit")
//=====================================================================================================================
// VISUAL SIGNALS - NO DUPLICATES
//=====================================================================================================================
// Calculate visual conditions
longEntrySignal = showBigSignals and finalLongSignal
shortEntrySignal = showBigSignals and finalShortSignal
longExitSignal = showExitSignals and exitTriggered and strategy.position_size[1] > 0
shortExitSignal = showExitSignals and exitTriggered and strategy.position_size[1] < 0
// Entry signals
plotshape(longEntrySignal, "LONG ENTRY", shape.triangleup, location.belowbar, color=color.lime, size=size.large, text="LONG")
plotshape(shortEntrySignal, "SHORT ENTRY", shape.triangledown, location.abovebar, color=color.red, size=size.large, text="SHORT")
// Exit signals
plotshape(longExitSignal, "LONG EXIT", shape.xcross, location.abovebar, color=color.orange, size=size.normal, text="EXIT")
plotshape(shortExitSignal, "SHORT EXIT", shape.xcross, location.belowbar, color=color.orange, size=size.normal, text="EXIT")
// Text labels
if showTextLabels and finalLongSignal
label.new(bar_index, low,
text="🚀 LONG\n" + currentSignalType + "\nEntry: " + str.tostring(close, "#.##"),
style=label.style_label_up, color=color.green, textcolor=color.white, size=size.normal)
if showTextLabels and finalShortSignal
label.new(bar_index, high,
text="🎯 SHORT\n" + currentSignalType + "\nEntry: " + str.tostring(close, "#.##"),
style=label.style_label_down, color=color.red, textcolor=color.white, size=size.normal)
// Exit labels with P&L
if showExitSignals and exitTriggered
exitPnL = strategy.netprofit - strategy.netprofit[1]
exitText = exitPnL > 0 ? "✅ WIN\n+" + str.tostring(exitPnL, "$#") : "❌ LOSS\n" + str.tostring(exitPnL, "$#")
labelColor = exitPnL > 0 ? color.green : color.red
if strategy.position_size[1] > 0
label.new(bar_index, high, text=exitText, style=label.style_label_down, color=labelColor, textcolor=color.white, size=size.small)
else
label.new(bar_index, low, text=exitText, style=label.style_label_up, color=labelColor, textcolor=color.white, size=size.small)
// Trailing stop visualization
longTrailingStopPlot = strategy.position_size > 0 and useTrailingStop and trailingActive ? trailingStopPrice : na
shortTrailingStopPlot = strategy.position_size < 0 and useTrailingStop and trailingActive ? trailingStopPrice : na
plot(longTrailingStopPlot, "Long Trailing Stop", color=color.orange, linewidth=2, style=plot.style_stepline)
plot(shortTrailingStopPlot, "Short Trailing Stop", color=color.orange, linewidth=2, style=plot.style_stepline)
// Regular stop/take profit lines
longStopLossPlot = strategy.position_size > 0 ? stopLossPrice : na
longTakeProfitPlot = strategy.position_size > 0 ? takeProfitPrice : na
shortStopLossPlot = strategy.position_size < 0 ? stopLossPrice : na
shortTakeProfitPlot = strategy.position_size < 0 ? takeProfitPrice : na
plot(longStopLossPlot, "Long Stop Loss", color=color.red, linewidth=1, style=plot.style_linebr)
plot(longTakeProfitPlot, "Long Take Profit", color=color.green, linewidth=1, style=plot.style_linebr)
plot(shortStopLossPlot, "Short Stop Loss", color=color.red, linewidth=1, style=plot.style_linebr)
plot(shortTakeProfitPlot, "Short Take Profit", color=color.green, linewidth=1, style=plot.style_linebr)
// Background highlighting
bgcolor(strategy.position_size > 0 ? color.new(color.green, 98) : strategy.position_size < 0 ? color.new(color.red, 98) : na, title="Position Background")
//=====================================================================================================================
// MACD INDICATOR WITH ENHANCED SIGNALS
//=====================================================================================================================
// Plot MACD components
macdPlot = plot(macdLine, "MACD Line", color.blue, 3)
signalPlot = plot(signalLine, "Signal Line", color.red, 2)
plot(histogramLine, "Histogram", color.gray, style=plot.style_histogram)
hline(0, "Zero Line", color.black, linestyle=hline.style_solid, linewidth=2)
// Fill between MACD and Signal line
fill(macdPlot, signalPlot, color=macdLine > signalLine ? color.new(color.green, 80) : color.new(color.red, 80), title="MACD Fill")
// Crossover markers in MACD pane
plotshape(macdZeroCrossUp, "Zero Cross Up", shape.circle, location.bottom, color=color.lime, size=size.small, text="↑")
plotshape(macdZeroCrossDown, "Zero Cross Down", shape.circle, location.top, color=color.red, size=size.small, text="↓")
plotshape(macdSignalCrossUp, "Signal Cross Up", shape.diamond, location.bottom, color=color.aqua, size=size.tiny, text="▲")
plotshape(macdSignalCrossDown, "Signal Cross Down", shape.diamond, location.top, color=color.fuchsia, size=size.tiny, text="▼")
//=====================================================================================================================
// PERFORMANCE DASHBOARD
//=====================================================================================================================
if barstate.islast
var table perfTable = table.new(position.top_right, 2, 10, bgcolor=color.white, border_width=2)
// Headers
table.cell(perfTable, 0, 0, "📊 BTC MACD LIVE", text_color=color.white, bgcolor=color.navy)
table.cell(perfTable, 1, 0, "STATUS", text_color=color.white, bgcolor=color.navy)
// Performance metrics
winRate = strategy.wintrades / math.max(strategy.closedtrades, 1) * 100
table.cell(perfTable, 0, 1, "Total Trades", text_color=color.black)
table.cell(perfTable, 1, 1, str.tostring(strategy.closedtrades), text_color=strategy.closedtrades > 0 ? color.green : color.gray)
table.cell(perfTable, 0, 2, "Win Rate", text_color=color.black)
table.cell(perfTable, 1, 2, str.tostring(winRate, "#.#") + "%", text_color=winRate > 50 ? color.green : color.red)
table.cell(perfTable, 0, 3, "Net Profit", text_color=color.black)
table.cell(perfTable, 1, 3, str.tostring(strategy.netprofit, "$#,###"), text_color=strategy.netprofit > 0 ? color.green : color.red)
table.cell(perfTable, 0, 4, "Position", text_color=color.black)
positionText = strategy.position_size > 0 ? "LONG" : strategy.position_size < 0 ? "SHORT" : "NONE"
positionColor = strategy.position_size > 0 ? color.green : strategy.position_size < 0 ? color.red : color.gray
table.cell(perfTable, 1, 4, positionText, text_color=positionColor)
table.cell(perfTable, 0, 5, "MACD Status", text_color=color.black)
macdStatus = macdLine > 0 ? "BULLISH" : "BEARISH"
macdColor = macdLine > 0 ? color.green : color.red
table.cell(perfTable, 1, 5, macdStatus, text_color=macdColor)
table.cell(perfTable, 0, 6, "Daily Trades", text_color=color.black)
table.cell(perfTable, 1, 6, str.tostring(dailyTrades) + "/" + str.tostring(maxDailyTrades), text_color=dailyTrades < maxDailyTrades ? color.green : color.red)
table.cell(perfTable, 0, 7, "Daily Trades", text_color=color.black)
table.cell(perfTable, 1, 7, str.tostring(dailyTrades) + "/" + str.tostring(maxDailyTrades), text_color=dailyTrades < maxDailyTrades ? color.green : color.red)
table.cell(perfTable, 0, 8, "Signal Status", text_color=color.black)
signalStatusText = rawLongSignal ? "LONG READY" : rawShortSignal ? "SHORT READY" : "WAITING"
signalStatusColor = rawLongSignal ? color.green : rawShortSignal ? color.red : color.gray
table.cell(perfTable, 1, 8, signalStatusText, text_color=signalStatusColor)
table.cell(perfTable, 0, 9, "Trailing Stop", text_color=color.black)
trailingText = useTrailingStop and trailingActive ? "ACTIVE" : useTrailingStop ? "WAITING" : "DISABLED"
trailingColor = useTrailingStop and trailingActive ? color.orange : useTrailingStop ? color.blue : color.gray
table.cell(perfTable, 1, 9, trailingText, text_color=trailingColor)
//=====================================================================================================================
// ALERTS FOR STRATEGIES
//=====================================================================================================================
// Entry alerts
if finalLongSignal
alert("🚀 BTC LONG SIGNAL - Check chart for details", alert.freq_once_per_bar)
if finalShortSignal
alert("🎯 BTC SHORT SIGNAL - Check chart for details", alert.freq_once_per_bar)
// Exit alerts
if exitTriggered
alert("BTC Position Closed - Check P&L", alert.freq_once_per_bar)
// Trailing stop activation alert
if trailingActive and not trailingActive[1]
alert("Trailing stop is now active - profits being protected", alert.freq_once_per_bar)
//=====================================================================================================================
// VISUAL SIGNAL GUIDE:
//=====================================================================================================================
//
// 📍 WHAT YOU'LL SEE ON THE CHART:
// =================================
//
// PRICE CHART (Top):
// • 🔺 Large GREEN triangles = LONG entries
// • 🔻 Large RED triangles = SHORT entries
// • 🏷️ Green/Red labels with signal details
// • ❌ Orange X marks = Position exits
// • ✅/❌ Win/Loss labels with P&L amounts
// • Light background color when position active
//
// MACD INDICATOR (Bottom):
// • Blue line = MACD
// • Red line = Signal Line
// • Gray histogram = MACD - Signal
// • Green/Red fill = MACD above/below Signal
// • ⚪ Circles = Zero line crossovers
// • 💎 Diamonds = Signal line crossovers
//
// PERFORMANCE TABLE (Top Right):
// • Live win rate and profit tracking
// • Current position status
// • Daily trade limits
// • MACD bullish/bearish indicator
// • Trailing stop status
// • Signal quality filters
//
//=====================================================================================================================
Show all 416 lines