本页源码来自 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/
// © mickes
//@version=5
indicator("Order blocks", overlay = true, max_boxes_count = 500, max_lines_count = 500, max_labels_count = 500)
import mickes/Touched/14
_timeframe = input.timeframe("", "Timeframe")
_count = input.int(3, "Count")
_type = input.string("Both", "Type", ["Bullish", "Bearish", "Both"])
_history = input.bool(true, "Keep history", tooltip = "Check this if you want old zones to be keept. They are removed if they are broken (if you have 'Remove broken zones' checked) or if a new zone is created and the count is reached. This means that zones can go 'old' even if thay are not interacted with.")
_removeBroken = input.bool(true, "Remove broken zones")
_reactionFactor = input.float(3, "Reaction", inline = "reaction", group = "Requirements")
_reactionShow = input.bool(true, "", tooltip = "A factor (%) of the Average True Range (of length 14) that the total reaction must have. And check the checkbox if you want the limit to be displayed.", inline = "reaction", group = "Requirements")
_takeOut = input.bool(true, "Take out", tooltip = "The bar that start the reaction must take out the previous bar high/low (liquidity sweep).", group = "Requirements")
_consecutiveRisingIrFalling = input.bool(true, "Consecutive rising/falling", tooltip = "The candles in the reaction must consecutivly rise or fall.", group = "Requirements")
_fairValueGap = input.bool(true, "Fair Value Gap", group = "Requirements")
_color = input.color(color.fuchsia, "Zones", group = "Display")
_colorReplaced = input.color(color.aqua, "Replaced zones", group = "Display")
_colorBroken = input.color(color.red, "Broken zones", group = "Display")
type Visual
array<box> Boxes
array<line> Lines
array<label> Labels
type Zone
int Time
int TimeClose
float High
float Low
float ReactionLimit
Touched.Zone TouchedZone
Visual Visual
int Type // -1 = bearish, 1 = bullish
type Zones
int Index
int Maximum
array<Zone> Zones
Zone Remove
CreateUp() =>
satisfied = true
for i = 2 to 1
if _consecutiveRisingIrFalling
if low[i - 1] < low[i]
satisfied := false
break
if _fairValueGap
if high[2] >= low
satisfied := false
satisfied
CreateDown() =>
satisfied = true
for i = 3 to 1
if _consecutiveRisingIrFalling
if low[i - 1] > low[i]
satisfied := false
break
if _fairValueGap
if low[2] <= high
satisfied := false
satisfied
Create() =>
pivotHigh = ta.pivothigh(_takeOut ? 1 : 0, 2)
pivotLow = ta.pivotlow(_takeOut ? 1 : 0, 2)
atr = ta.atr(14)
reactionLimit = atr * _reactionFactor
widthUp = high - low[2]
widthDown = high[2] - low
zone = Zone.new(time[2], time_close[2], high[2], low[2], reactionLimit, Touched.Zone.new(high[2], low[2], time[2]))
create = false
if widthUp >= reactionLimit
if not na(pivotLow) and barstate.isconfirmed // only create an order block if the HTF bar is closed
if _type == "Both" or _type == "Bullish"
if CreateUp()
zone.Type := 1
create := true
if widthDown >= reactionLimit
if not na(pivotHigh) and barstate.isconfirmed // only create an order block if the HTF bar is closed
if _type == "Both" or _type == "Bearish"
if CreateDown()
zone.Type := -1
create := true
if create
zone
method Replace(Zones zones, Zone zone) =>
zones.Remove := zones.Zones.get(zones.Index)
zones.Zones.set(zones.Index, zone)
zones.Index := (zones.Index + 1) % _count
zones
method RemoveVisuals(Zone zone, color newColor) =>
for [i, b] in zone.Visual.Boxes
if _history
if i != 0 // don't change the creation box
b.set_right(time)
b.set_extend(extend.none)
b.set_bgcolor(color.new(newColor, 80))
else
b.set_border_color(newColor)
else
b.delete()
for l in zone.Visual.Lines
if _history
l.set_color(newColor)
else
l.delete()
for l in zone.Visual.Labels
l.delete()
zone.Visual := na
method Remove(Zones zones) =>
if not na(zones.Remove)
if not na(zones.Remove.Visual)
zones.Remove.RemoveVisuals(_colorReplaced)
zones
method Draw(Zone zone) =>
reactionLimit = switch zone.Type
-1 => zone.High - zone.ReactionLimit
1 => zone.Low + zone.ReactionLimit
zone.Visual := Visual.new(
array.from(
box.new(zone.Time, zone.High, zone.TimeClose, zone.Low, xloc = xloc.bar_time, bgcolor = na, border_color = _color), // the creation zone
box.new(zone.Time, zone.High, zone.TimeClose, zone.Low, xloc = xloc.bar_time, bgcolor = color.new(_color, 70), border_width = 0, extend = extend.right) // the extended zone
),
array.from(_reactionShow ? line.new(zone.Time, reactionLimit, time, reactionLimit, xloc = xloc.bar_time, color = _color) : line(na)),
array.new<label>())
zone
method Interaction(Zone zone, Touched.Touch touch, color c, string lbl) =>
interacted = false
if touch.Down
zone.Visual.Labels.push(label.new(bar_index - touch.ExtremeIndexBack, low[touch.ExtremeIndexBack], lbl, color = c, style = label.style_label_up))
interacted := true
if touch.Up
zone.Visual.Labels.push(label.new(bar_index - touch.ExtremeIndexBack, high[touch.ExtremeIndexBack], lbl, color = c))
interacted := true
interacted
method Interactions(Zones zones) =>
for [i, zone] in zones.Zones
if na(zone)
continue
if na(zone.Visual)
continue
zone.Interaction(Touched.Retest(zone.TouchedZone, 30), color.new(color.blue, 30), "R")
zone.Interaction(Touched.FalseBreakout(zone.TouchedZone, 30), color.new(color.orange, 30), "FB")
if zone.Interaction(Touched.Breakout(zone.TouchedZone, 50), color.new(color.red, 30), "B") and _removeBroken
zone.RemoveVisuals(_colorBroken)
var zones = Zones.new(0, _count, array.new<Zone>(_count))
zone = request.security(syminfo.tickerid, _timeframe, Create(), lookahead = barmerge.lookahead_off)
if not na(zone) and na(zone[1]) // only draw order block on one bar
zone.Draw()
zones.Replace(zone)
.Remove()
zones.Interactions()