本页源码来自 TradingView 公开发布的开源脚本,版权归原作者所有, 请遵循其原始许可(Pine 脚本常见 CC BY-NC-SA / MPL-2.0 / MIT)。 本项目仅用于研究检索与许可范围内的移植。
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © BOSWaves
//@version=5
indicator("Smart Money Trades Pro [BOSWaves]", overlay=true, max_lines_count=500)
// === Input Parameters ===
structurePeriod = input.int(20, "Structure Detection Period", minval=5, maxval=50, tooltip="Lookback period for swing point detection")
confirmationType = input.string("Body", "Break Confirmation", options=["Body", "Wick"], tooltip="Use candle body or wick for break confirmation")
showCHoCH = input.bool(true, "Display Change of Character", tooltip="Show CHoCH when trend changes")
showTrendBars = input.bool(true, "Color Trend Bars", tooltip="Color candles based on market structure trend")
showTable = input.bool(true, "Show Info Table", tooltip="Display current trade information table")
tablePosition = input.string("Top Right", "Table Position", options=["Top Left", "Top Right", "Bottom Left", "Bottom Right"])
// Enhanced Color Scheme
bullColor = input.color(#26A69A, "Bullish", group="Colors")
bearColor = input.color(#EF5350, "Bearish", group="Colors")
neutralColor = input.color(#9E9E9E, "Neutral", group="Colors")
successColor = input.color(#4CAF50, "Success/TP", group="Colors")
dangerColor = input.color(#F44336, "Danger/SL", group="Colors")
bgColor = input.color(color.new(#1E1E1E, 95), "Table Background", group="Colors")
textColor = input.color(color.white, "Table Text", group="Colors")
// === Market Structure Function ===
getMarketStructure() =>
var float lastHigh = na
var float lastLow = na
var int lastHighBar = na
var int lastLowBar = na
var int trendDirection = 0
var bool highBreakPending = false
var bool lowBreakPending = false
// Detect swing points
swingHigh = ta.pivothigh(high, structurePeriod, structurePeriod)
swingLow = ta.pivotlow(low, structurePeriod, structurePeriod)
// Update swing levels
if not na(swingHigh)
lastHigh := swingHigh
lastHighBar := bar_index - structurePeriod
highBreakPending := true
if not na(swingLow)
lastLow := swingLow
lastLowBar := bar_index - structurePeriod
lowBreakPending := true
// Check for breaks
breakPrice = confirmationType == "Body" ? close : (trendDirection > 0 ? high : low)
highBroken = false
lowBroken = false
if highBreakPending and not na(lastHigh)
if (confirmationType == "Body" and close > lastHigh) or (confirmationType == "Wick" and high > lastHigh)
highBroken := true
highBreakPending := false
if lowBreakPending and not na(lastLow)
if (confirmationType == "Body" and close < lastLow) or (confirmationType == "Wick" and low < lastLow)
lowBroken := true
lowBreakPending := false
// Update trend direction
prevTrend = trendDirection
if highBroken
trendDirection := 1
else if lowBroken
trendDirection := -1
isChoch = (prevTrend == -1 and trendDirection == 1) or (prevTrend == 1 and trendDirection == -1)
[highBroken, lowBroken, lastHigh, lastLow, lastHighBar, lastLowBar, trendDirection, isChoch]
// Get market structure data
[bullBreak, bearBreak, structHigh, structLow, highBar, lowBar, trend, chochSignal] = getMarketStructure()
// === Enhanced Target Logic ===
var float entryLevel = na
var float tp1Level = na
var float tp2Level = na
var float tp3Level = na
var float stopLevel = na
var int tradeDirection = 0
var bool tp1Hit = false
var bool tp2Hit = false
var bool tp3Hit = false
var int lastTradeBar = na
var tp1line = line(na)
var tp2line = line(na)
var tp3line = line(na)
var stopline = line(na)
var entryline = line(na)
var box entryBox = na
var box riskBox = na
var box rewardBox = na
// Calculate dynamic range for targets
atr = ta.atr(14)
volatilityMultiplier = 2
if bullBreak and not na(structHigh)
entryLevel := structHigh
targetRange = atr * volatilityMultiplier
tp1Level := entryLevel + targetRange * 0.8
tp2Level := entryLevel + targetRange * 1.6
tp3Level := entryLevel + targetRange * 2.8
stopLevel := entryLevel - targetRange * 1.2
tradeDirection := 1
tp1Hit := false
tp2Hit := false
tp3Hit := false
lastTradeBar := bar_index
tp1line := line(na)
tp2line := line(na)
tp3line := line(na)
stopline := line(na)
entryline := line(na)
box.delete(entryBox)
box.delete(riskBox)
box.delete(rewardBox)
if bearBreak and not na(structLow)
entryLevel := structLow
targetRange = atr * volatilityMultiplier
tp1Level := entryLevel - targetRange * 0.8
tp2Level := entryLevel - targetRange * 1.6
tp3Level := entryLevel - targetRange * 2.8
stopLevel := entryLevel + targetRange * 1.2
tradeDirection := -1
tp1Hit := false
tp2Hit := false
tp3Hit := false
lastTradeBar := bar_index
tp1line := line(na)
tp2line := line(na)
tp3line := line(na)
stopline := line(na)
entryline := line(na)
box.delete(entryBox)
box.delete(riskBox)
box.delete(rewardBox)
// Check TP hits
if tradeDirection == 1
if not tp1Hit and high >= tp1Level
tp1Hit := true
line.delete(tp1line)
tp1line := line(na)
if not tp2Hit and high >= tp2Level
tp2Hit := true
line.delete(tp2line)
tp2line := line(na)
if not tp3Hit and high >= tp3Level
tp3Hit := true
line.delete(tp3line)
tp3line := line(na)
line.delete(entryline)
entryline := line(na)
if tradeDirection == -1
if not tp1Hit and low <= tp1Level
tp1Hit := true
line.delete(tp1line)
tp1line := line(na)
if not tp2Hit and low <= tp2Level
tp2Hit := true
line.delete(tp2line)
tp2line := line(na)
if not tp3Hit and low <= tp3Level
tp3Hit := true
line.delete(tp3line)
tp3line := line(na)
line.delete(stopline)
stopline := line(na)
line.delete(entryline)
entryline := line(na)
// Update line positions - keep lines visible
if not na(tp1line)
tp1line.set_x2(bar_index + 15)
if not na(tp2line)
tp2line.set_x2(bar_index + 15)
if not na(tp3line)
tp3line.set_x2(bar_index + 15)
if not na(stopline)
stopline.set_x2(bar_index + 15)
if not na(entryline)
entryline.set_x2(bar_index + 15)
// Update boxes
if not na(entryBox)
box.set_right(entryBox, bar_index + 15)
if not na(riskBox)
box.set_right(riskBox, bar_index + 15)
if not na(rewardBox)
box.set_right(rewardBox, bar_index + 15)
// Reset trade if stopped out
stopHit = (tradeDirection == 1 and low <= stopLevel) or (tradeDirection == -1 and high >= stopLevel)
if stopHit
line.delete(stopline)
line.delete(entryline)
line.delete(tp1line)
line.delete(tp2line)
line.delete(tp3line)
stopline := line(na)
entryline := line(na)
tp1line := line(na)
tp2line := line(na)
tp3line := line(na)
tradeDirection := 0
box.delete(entryBox)
box.delete(riskBox)
box.delete(rewardBox)
// === Visualizations ===
// Enhanced trend coloring with gradient effect
trendBarColor = showTrendBars ?
(trend == 1 ? color.new(bullColor, 10) :
trend == -1 ? color.new(bearColor, 10) :
color.new(neutralColor, 60)) : na
barcolor(trendBarColor)
// Structure break lines and labels with enhanced styling
if bullBreak and not na(structHigh) and not na(highBar)
breakLine = line.new(highBar, structHigh, bar_index, structHigh,
color=color.new(bullColor, 30), width=2, style=line.style_dotted, extend=extend.none)
labelText = chochSignal and showCHoCH ? "CHoCH ↗" : "BOS ↗"
// Position label above the high with offset
labelOffset = ta.highest(high, 5) + (atr * 0.5)
breakLabel = label.new(bar_index, labelOffset, labelText,
color=color.new(bullColor, 0), textcolor=color.white,
style=label.style_label_down, size=size.normal, force_overlay=true)
if bearBreak and not na(structLow) and not na(lowBar)
breakLine = line.new(lowBar, structLow, bar_index, structLow,
color=color.new(bearColor, 30), width=2, style=line.style_dotted, extend=extend.none)
labelText = chochSignal and showCHoCH ? "CHoCH ↘" : "BOS ↘"
// Position label below the low with offset
labelOffset = ta.lowest(low, 5) - (atr * 0.5)
breakLabel = label.new(bar_index, labelOffset, labelText,
color=color.new(bearColor, 0), textcolor=color.white,
style=label.style_label_up, size=size.normal, force_overlay=true)
// Enhanced target visualization with zones
if tradeDirection != 0 and not na(entryLevel) and bar_index == lastTradeBar
lineExtend = 15
// Entry level with zone
entryline := line.new(bar_index, entryLevel, bar_index + lineExtend, entryLevel,
color=color.new(color.white, 20), width=2, style=line.style_solid)
// Create visual zones
if tradeDirection == 1
// Risk zone (Entry to Stop)
riskBox := box.new(bar_index, entryLevel, bar_index + lineExtend, stopLevel,
border_color=color.new(dangerColor, 80), border_width=1,
bgcolor=color.new(dangerColor, 95))
// Reward zone (Entry to TP3)
rewardBox := box.new(bar_index, entryLevel, bar_index + lineExtend, tp3Level,
border_color=color.new(successColor, 80), border_width=1,
bgcolor=color.new(successColor, 97))
else
// Risk zone (Entry to Stop)
riskBox := box.new(bar_index, entryLevel, bar_index + lineExtend, stopLevel,
border_color=color.new(dangerColor, 80), border_width=1,
bgcolor=color.new(dangerColor, 95))
// Reward zone (Entry to TP3)
rewardBox := box.new(bar_index, entryLevel, bar_index + lineExtend, tp3Level,
border_color=color.new(successColor, 80), border_width=1,
bgcolor=color.new(successColor, 97))
// Take profit levels with progressive styling
if not tp1Hit
tp1line := line.new(bar_index, tp1Level, bar_index + lineExtend, tp1Level,
color=color.new(successColor, 40), width=1, style=line.style_dashed)
// Position TP labels to the right with extra offset
label.new(bar_index + lineExtend + 2, tp1Level, " TP1: " + str.tostring(tp1Level, format.mintick),
color=color.new(color.white, 100), textcolor=successColor,
style=label.style_label_left, size=size.small)
if not tp2Hit
tp2line := line.new(bar_index, tp2Level, bar_index + lineExtend, tp2Level,
color=color.new(successColor, 30), width=1, style=line.style_dashed)
label.new(bar_index + lineExtend + 2, tp2Level, " TP2: " + str.tostring(tp2Level, format.mintick),
color=color.new(color.white, 100), textcolor=successColor,
style=label.style_label_left, size=size.small)
if not tp3Hit
tp3line := line.new(bar_index, tp3Level, bar_index + lineExtend, tp3Level,
color=color.new(successColor, 20), width=2, style=line.style_solid)
label.new(bar_index + lineExtend + 2, tp3Level, " TP3: " + str.tostring(tp3Level, format.mintick),
color=color.new(color.white, 100), textcolor=successColor,
style=label.style_label_left, size=size.small)
// Stop loss with emphasis
stopline := line.new(bar_index, stopLevel, bar_index + lineExtend, stopLevel,
color=color.new(dangerColor, 20), width=2, style=line.style_solid)
label.new(bar_index + lineExtend + 2, stopLevel, " SL: " + str.tostring(stopLevel, format.mintick),
color=color.new(color.white, 100), textcolor=dangerColor,
style=label.style_label_left, size=size.small)
// Signal shapes with enhanced visibility
plotshape(bullBreak, "Bull Signal", shape.triangleup, location.belowbar,
color=color.new(bullColor, 0), size=size.normal)
plotshape(bearBreak, "Bear Signal", shape.triangledown, location.abovebar,
color=color.new(bearColor, 0), size=size.normal)
// === Information Table ===
if showTable and tradeDirection != 0
tablePos = tablePosition == "Top Left" ? position.top_left :
tablePosition == "Top Right" ? position.top_right :
tablePosition == "Bottom Left" ? position.bottom_left : position.bottom_right
infoTable = table.new(tablePos, 3, 8, bgcolor=bgColor,
frame_color=color.new(color.gray, 50), frame_width=1,
border_color=color.new(color.gray, 70), border_width=1)
// Header
table.cell(infoTable, 0, 0, "TRADE INFO", text_color=textColor, bgcolor=color.new(color.gray, 80),
text_size=size.normal, text_halign=text.align_center)
table.merge_cells(infoTable, 0, 0, 2, 0)
// Trade Direction
directionText = tradeDirection == 1 ? "LONG ↗" : "SHORT ↘"
directionColor = tradeDirection == 1 ? bullColor : bearColor
table.cell(infoTable, 0, 1, "Direction", text_color=color.new(textColor, 30), text_size=size.small)
table.cell(infoTable, 1, 1, directionText, text_color=directionColor, text_size=size.normal, text_halign=text.align_right)
table.merge_cells(infoTable, 1, 1, 2, 1)
// Entry Price
table.cell(infoTable, 0, 2, "Entry", text_color=color.new(textColor, 30), text_size=size.small)
table.cell(infoTable, 1, 2, str.tostring(entryLevel, format.mintick),
text_color=textColor, text_size=size.small, text_halign=text.align_right)
table.merge_cells(infoTable, 1, 2, 2, 2)
// Stop Loss
slDistance = math.abs(entryLevel - stopLevel)
slPercent = (slDistance / entryLevel) * 100
table.cell(infoTable, 0, 3, "Stop Loss", text_color=color.new(dangerColor, 20), text_size=size.small)
table.cell(infoTable, 1, 3, str.tostring(stopLevel, format.mintick),
text_color=dangerColor, text_size=size.small, text_halign=text.align_right)
table.cell(infoTable, 2, 3, "(-" + str.tostring(slPercent, "#.##") + "%)",
text_color=color.new(dangerColor, 30), text_size=size.tiny, text_halign=text.align_right)
// TP1
tp1Distance = math.abs(tp1Level - entryLevel)
tp1Percent = (tp1Distance / entryLevel) * 100
tp1Status = tp1Hit ? " ✓" : ""
tp1Color = tp1Hit ? color.new(successColor, 50) : successColor
table.cell(infoTable, 0, 4, "TP 1" + tp1Status, text_color=color.new(tp1Color, 20), text_size=size.small)
table.cell(infoTable, 1, 4, str.tostring(tp1Level, format.mintick),
text_color=tp1Color, text_size=size.small, text_halign=text.align_right)
table.cell(infoTable, 2, 4, "(+" + str.tostring(tp1Percent, "#.##") + "%)",
text_color=color.new(tp1Color, 30), text_size=size.tiny, text_halign=text.align_right)
// TP2
tp2Distance = math.abs(tp2Level - entryLevel)
tp2Percent = (tp2Distance / entryLevel) * 100
tp2Status = tp2Hit ? " ✓" : ""
tp2Color = tp2Hit ? color.new(successColor, 50) : successColor
table.cell(infoTable, 0, 5, "TP 2" + tp2Status, text_color=color.new(tp2Color, 20), text_size=size.small)
table.cell(infoTable, 1, 5, str.tostring(tp2Level, format.mintick),
text_color=tp2Color, text_size=size.small, text_halign=text.align_right)
table.cell(infoTable, 2, 5, "(+" + str.tostring(tp2Percent, "#.##") + "%)",
text_color=color.new(tp2Color, 30), text_size=size.tiny, text_halign=text.align_right)
// TP3
tp3Distance = math.abs(tp3Level - entryLevel)
tp3Percent = (tp3Distance / entryLevel) * 100
tp3Status = tp3Hit ? " ✓" : ""
tp3Color = tp3Hit ? color.new(successColor, 50) : successColor
table.cell(infoTable, 0, 6, "TP 3" + tp3Status, text_color=color.new(tp3Color, 20), text_size=size.small)
table.cell(infoTable, 1, 6, str.tostring(tp3Level, format.mintick),
text_color=tp3Color, text_size=size.small, text_halign=text.align_right)
table.cell(infoTable, 2, 6, "(+" + str.tostring(tp3Percent, "#.##") + "%)",
text_color=color.new(tp3Color, 30), text_size=size.tiny, text_halign=text.align_right)
// Risk/Reward Ratio
avgReward = (tp1Distance + tp2Distance + tp3Distance) / 3
rrRatio = avgReward / slDistance
table.cell(infoTable, 0, 7, "Risk/Reward", text_color=color.new(textColor, 30), text_size=size.small)
table.cell(infoTable, 1, 7, "1:" + str.tostring(rrRatio, "#.##"),
text_color=color.new(successColor, 0), text_size=size.normal, text_halign=text.align_right)
table.merge_cells(infoTable, 1, 7, 2, 7)