Wedge & Channel Detector
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «indicator_automatic_wedge_&_channel_detector_for_tradingview.pine» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
Индикатор «Wedge & Channel Detector» предназначен для автоматического и ручного обнаружения схожих ценовых структур — клиньев и каналов — на графиках TradingView. Он определяет пивоты (вершины и впадины), строит верхнюю и нижнюю граничные линии, рассчитывает их характеристики и отображает результаты прямо на графике в виде линий и заливок.
Индикатор оценивает качество каждой структуры по совокупности касаний границ, нарушений, баланса между верхней и нижней сторонами, ширины и давности. На основе этих оценок присваивается текстовая категория качества (Excellent, Good, Fair, Poor) и уровень уверенности (High, Medium, Low). Также определяется тип структуры: канал, симметричный треугольник, нисходящий/возрастающий треугольник или клин, расширяющаяся структура.
Встроена система жизненного цикла структуры: отслеживаются подтверждённые пробои вверх и вниз, восстановление ценой внутри структуры, поздняя стадия схождения и прохождение вершины. Пользователь может настраивать все ключевые параметры через панель настроек, включая режим выбора структуры, пороги качества, визуальные элементы и условия оповещений. Доступны два условных оповещения — на подтверждённый пробой вверх и вниз.
Индикатор работает поверх графика (overlay), поддерживает до 60 линий и 100 меток, позволяет задавать пользовательский источник данных и отображает дополнительные зоны: центральную линию, зону без торговли, а также зоны поддержки и сопротивления.
Настройки программы
| Настройка | Описание |
|---|---|
| selectionMode | Режим подбора структуры: автоматический (поиск наилучшей по качеству) или ручной (выбор конкретных пивотов). |
| autoPivotCount | Число наиболее недавних пивотов, используемых для автоматического подбора верхней и нижней границ структуры. |
| autoLookbackBars | Количество баров назад, в пределах которых оценивается качество и релевантность обнаруженной структуры при автоматическом режиме выбора. |
| minAnchorSpacing | Минимальное расстояние в барах между двумя якорными точками одной границы структуры. |
| upperLen | Период обнаружения пивота высоких цен, определяющий чувствительность поиска верхних якорных точек. |
| lowerLen | Период обнаружения пивота низких цен, определяющий чувствительность поиска нижних якорных точек. |
| manualUpperStart | Номер начального пивота для ручного выбора верхней границы структуры. |
| manualUpperEnd | Номер конечного пивота для ручного выбора верхней границы структуры. |
| manualLowerStart | Номер начального пивота для ручного выбора нижней границы структуры. |
| manualLowerEnd | Номер конечного пивота для ручного выбора нижней границы структуры (отсчёт от текущего бара). |
| useCustomSource | Переключатель, активирующий использование пользовательского источника данных вместо стандартных значений High и Low. |
| customSource | Источник данных, используемый для расчёта верхних и нижних пивотов при включённом переключателе пользовательского источника. |
| showCenterline | Включает или отключает отображение центральной линии структуры, проведённой посередине между верхней и нижней границами. |
| showNoTradeZone | Включает или отключает отображение центральной зоны без торговли между верхним и нижним процентными порогами. |
| noTradeLowPct | Нижний процент от ширины структуры, определяющий границу центральной зоны без торговли. |
| noTradeHighPct | Верхний процент от ширины структуры, определяющий границу центральной зоны без торговли. |
| showBoundaryZones | Включает или отключает отображение зон поддержки и сопротивления у нижней и верхней границ структуры. |
| boundaryZonePct | Процент от общей ширины структуры, определяющий толщину зон поддержки и сопротивления у нижней и верхней границ. |
| breakoutATR | Множитель ATR, задающий минимальное расстояние от границы структуры для подтверждения пробоя ценой. |
| breakoutConfirmBars | Количество последовательных баров, на которых цена должна оставаться за пределами границы для подтверждения пробоя. |
| expireAfterBreakBars | Количество баров после подтверждённого пробоя, по истечении которого структура считается истёкшей и перестаёт отображаться как активная. |
| reclaimBars | Количество баров, в течение которых цена должна вернуться внутрь структуры после пробоя для подтверждения восстановления. |
| lateStageWidthATR | Максимальная нормализованная ширина структуры (в единицах ATR), при которой она считается находящейся в поздней стадии схождения. |
| lateStageApexBars | Максимальное расстояние в барах до расчётной вершины схождения, при котором структура считается находящейся в поздней стадии. |
| showBrokenStructures | Определяет, продолжают ли отображаться линии и зоны структуры после её пробоя или истечения. |
| touchToleranceATR | Множитель ATR, задающий допустимое отклонение цены от линии границы для распознавания касания. |
| violationToleranceATR | Множитель ATR, задающий порог, превышение которого ценой считается нарушением границы структуры. |
| minTouchSpacing | Минимальное количество баров между двумя последовательными касаниями одной и той же границы структуры. |
| minStructureWidthATR | Минимальная нормализованная ширина структуры в единицах ATR; структуры уже получают сниженную оценку. |
| maxStructureWidthATR | Максимальная допустимая нормализованная ширина структуры в единицах ATR; структуры шире получают сниженную оценку. |
| balancePenaltyStart | Порог отношения количества касаний верхней и нижней сторон, при превышении которого начинается штраф за дисбаланс в итоговой оценке качества. |
| balancePenaltyStrength | Множитель, определяющий силу штрафа за дисбаланс касаний между верхней и нижней сторонами структуры. |
| convergenceProjectionBars | Количество баров вперёд, на которое проецируется оценка силы конвергенции границ структуры. |
| weakConvergencePct | Порог процентного сжатия структуры, при превышении которого конвергенция классифицируется как слабая. |
| strongConvergencePct | Порог процентного сжатия структуры, при превышении которого конвергенция классифицируется как сильная. |
| highConfidenceQuality | Минимальная оценка качества структуры, необходимая для присвоения категории высокой уверенности. |
| mediumConfidenceQuality | Минимальная оценка качества структуры, необходимая для присвоения категории средней уверенности. |
| highConfidenceMinTouches | Минимальное количество касаний каждой из сторон структуры, требуемое для категории высокой уверенности. |
| mediumConfidenceMinTouches | Минимальное количество касаний каждой из сторон структуры, требуемое для категории средней уверенности. |
| highConfidenceMaxViolations | Максимальное допустимое суммарное количество нарушений границ для присвоения структуре категории высокой уверенности. |
| mediumConfidenceMaxViolations | Максимальное допустимое суммарное количество нарушений границ для присвоения структуре категории средней уверенности. |
| lineWidth | Толщина линий верхней и нижней границ структуры, отображаемых на графике. |
| showPivotMarkers | Включает или отключает отображение графических маркеров на графике в местах обнаруженных пивотов высоких и низких цен. |
Поиск по коду файла
indicator(
"Wedge & Channel Detector",
overlay = true,
max_bars_back = 5000,
max_lines_count = 60,
max_labels_count = 100
)
groupMode = "Structure Selection"
selectionMode = input.string(
"Auto",
"Selection Mode",
options = ["Auto", "Manual"],
group = groupMode
)
autoPivotCount = input.int(
5,
"Recent Pivots To Test",
minval = 3,
maxval = 7,
group = groupMode
)
autoLookbackBars = input.int(
250,
"Auto Scoring Lookback",
minval = 50,
maxval = 500,
group = groupMode
)
minAnchorSpacing = input.int(
10,
"Minimum Anchor Spacing",
minval = 2,
maxval = 200,
group = groupMode
)
groupPivot = "Pivot Detection"
upperLen = input.int(
20,
"Upper Pivot Length",
minval = 1,
group = groupPivot
)
lowerLen = input.int(
20,
"Lower Pivot Length",
minval = 1,
group = groupPivot
)
groupManual = "Manual Pivot Selection"
manualUpperStart = input.int(
2,
"Upper: From Pivot #",
minval = 0,
group = groupManual,
inline = "upper"
)
manualUpperEnd = input.int(
0,
"To Pivot #",
minval = 0,
group = groupManual,
inline = "upper"
)
manualLowerStart = input.int(
3,
"Lower: From Pivot #",
minval = 0,
group = groupManual,
inline = "lower"
)
manualLowerEnd = input.int(
0,
"To Pivot #",
minval = 0,
group = groupManual,
inline = "lower"
)
groupSource = "Source"
useCustomSource = input.bool(
false,
"Use Custom Source",
group = groupSource
)
customSource = input.source(
close,
"Custom Source",
group = groupSource
)
groupZones = "Structure Zones"
showCenterline = input.bool(
true,
"Show Centerline",
group = groupZones
)
showNoTradeZone = input.bool(
true,
"Show Middle No-Trade Zone",
group = groupZones
)
noTradeLowPct = input.float(
40.0,
"No-Trade Lower %",
minval = 0.0,
maxval = 100.0,
step = 1.0,
group = groupZones
)
noTradeHighPct = input.float(
60.0,
"No-Trade Upper %",
minval = 0.0,
maxval = 100.0,
step = 1.0,
group = groupZones
)
showBoundaryZones = input.bool(
true,
"Show Support / Resistance Zones",
group = groupZones
)
boundaryZonePct = input.float(
20.0,
"Boundary Zone %",
minval = 1.0,
maxval = 49.0,
step = 1.0,
group = groupZones
)
groupLifecycle = "Structure Lifecycle"
breakoutATR = input.float(
0.30,
"Breakout Distance (ATR)",
minval = 0.05,
maxval = 3.0,
step = 0.05,
group = groupLifecycle
)
breakoutConfirmBars = input.int(
2,
"Breakout Confirmation Bars",
minval = 1,
maxval = 10,
group = groupLifecycle
)
expireAfterBreakBars = input.int(
10,
"Expire After Break Bars",
minval = 1,
maxval = 100,
group = groupLifecycle
)
reclaimBars = input.int(
2,
"Reclaim Bars",
minval = 1,
maxval = 10,
group = groupLifecycle
)
lateStageWidthATR = input.float(
1.5,
"Late Stage Width (ATR)",
minval = 0.1,
maxval = 10.0,
step = 0.1,
group = groupLifecycle
)
lateStageApexBars = input.int(
15,
"Late Stage Apex Distance",
minval = 1,
maxval = 100,
group = groupLifecycle
)
showBrokenStructures = input.bool(
true,
"Keep Broken Structure Visible",
group = groupLifecycle
)
groupQuality = "Structure Quality"
touchToleranceATR = input.float(
0.20,
"Touch Tolerance (ATR)",
minval = 0.05,
maxval = 2.0,
step = 0.05,
group = groupQuality
)
violationToleranceATR = input.float(
0.35,
"Violation Tolerance (ATR)",
minval = 0.05,
maxval = 3.0,
step = 0.05,
group = groupQuality
)
minTouchSpacing = input.int(
5,
"Minimum Bars Between Touches",
minval = 1,
maxval = 100,
group = groupQuality
)
minStructureWidthATR = input.float(
1.0,
"Minimum Width (ATR)",
minval = 0.1,
maxval = 20.0,
step = 0.1,
group = groupQuality
)
maxStructureWidthATR = input.float(
20.0,
"Maximum Preferred Width (ATR)",
minval = 2.0,
maxval = 100.0,
step = 1.0,
group = groupQuality
)
balancePenaltyStart = input.float(
1.50,
"Touch Imbalance Penalty Starts At",
minval = 1.0,
maxval = 5.0,
step = 0.25,
group = groupQuality
)
balancePenaltyStrength = input.float(
8.0,
"Touch Imbalance Penalty Strength",
minval = 1.0,
maxval = 20.0,
step = 1.0,
group = groupQuality
)
groupConvergence = "Convergence Strength"
convergenceProjectionBars = input.int(
50,
"Measure Convergence Over Bars",
minval = 10,
maxval = 250,
group = groupConvergence
)
weakConvergencePct = input.float(
10.0,
"Weak Convergence %",
minval = 0.0,
maxval = 100.0,
step = 1.0,
group = groupConvergence
)
strongConvergencePct = input.float(
30.0,
"Strong Convergence %",
minval = 0.0,
maxval = 100.0,
step = 1.0,
group = groupConvergence
)
groupConfidence = "Structure Confidence"
highConfidenceQuality = input.float(
82.0,
"High Confidence Minimum Quality",
minval = 0.0,
maxval = 100.0,
step = 1.0,
group = groupConfidence
)
mediumConfidenceQuality = input.float(
65.0,
"Medium Confidence Minimum Quality",
minval = 0.0,
maxval = 100.0,
step = 1.0,
group = groupConfidence
)
highConfidenceMinTouches = input.int(
3,
"High Confidence Min Touches Each Side",
minval = 1,
maxval = 10,
group = groupConfidence
)
mediumConfidenceMinTouches = input.int(
2,
"Medium Confidence Min Touches Each Side",
minval = 1,
maxval = 10,
group = groupConfidence
)
highConfidenceMaxViolations = input.int(
2,
"High Confidence Max Total Violations",
minval = 0,
maxval = 25,
group = groupConfidence
)
mediumConfidenceMaxViolations = input.int(
5,
"Medium Confidence Max Total Violations",
minval = 0,
maxval = 50,
group = groupConfidence
)
groupVisual = "Visuals"
color upperColor = #A83A68
color lowerColor = #26C6B8
color centerColor = #667582
color noTradeColor = color.new(#667582, 88)
color supportZoneColor = color.new(#26C6B8, 90)
color resistanceZoneColor = color.new(#A83A68, 90)
color brokenColor = #FF4F87
color lateStageColor = #67F5C4
lineWidth = input.int(
2,
"Boundary Width",
minval = 1,
maxval = 4,
group = groupVisual
)
showPivotMarkers = input.bool(
true,
"Show Pivot Markers",
group = groupVisual
)
float upperSource = useCustomSource ? customSource : high
float lowerSource = useCustomSource ? customSource : low
float atr = ta.atr(14)
f_line_price(
int x1,
float y1,
int x2,
float y2,
int targetX
) =>
float result = na
if (
not na(x1) and
not na(x2) and
x1 != x2
)
float slope = (y2 - y1) / float(x2 - x1)
result := y1 + slope * float(targetX - x1)
result
f_score_structure(
int ux1,
float uy1,
int ux2,
float uy2,
int lx1,
float ly1,
int lx2,
float ly2
) =>
float finalScore = na
int upperTouchesLocal = 0
int lowerTouchesLocal = 0
int upperViolationsLocal = 0
int lowerViolationsLocal = 0
int lastUpperTouchX = na
int lastLowerTouchX = na
bool candidateValid = (
ux2 > ux1 and
lx2 > lx1 and
ux2 - ux1 >= minAnchorSpacing and
lx2 - lx1 >= minAnchorSpacing
)
if candidateValid
float uSlope = (uy2 - uy1) / float(ux2 - ux1)
float lSlope = (ly2 - ly1) / float(lx2 - lx1)
int structureStart = math.max(
ux1,
lx1
)
float upperAtStart = f_line_price(
ux1,
uy1,
ux2,
uy2,
structureStart
)
float lowerAtStart = f_line_price(
lx1,
ly1,
lx2,
ly2,
structureStart
)
float widthAtStart = (
upperAtStart -
lowerAtStart
)
float upperCurrent = f_line_price(
ux1,
uy1,
ux2,
uy2,
bar_index
)
float lowerCurrent = f_line_price(
lx1,
ly1,
lx2,
ly2,
bar_index
)
float currentWidthLocal = (
upperCurrent -
lowerCurrent
)
bool convergingCandidate = (
uSlope < lSlope
)
float candidateApexX = na
float denominator = (
uSlope -
lSlope
)
if math.abs(denominator) > 0.0000001
float upperIntercept = (
uy1 -
uSlope *
float(ux1)
)
float lowerIntercept = (
ly1 -
lSlope *
float(lx1)
)
candidateApexX := (
lowerIntercept -
upperIntercept
) / denominator
bool apexAlreadyPassed = (
convergingCandidate and
not na(candidateApexX) and
candidateApexX <= float(bar_index)
)
bool orderedAtStart = (
widthAtStart > 0.0
)
bool orderedNow = (
currentWidthLocal > 0.0
)
if (
orderedAtStart and
orderedNow and
not apexAlreadyPassed
)
int availableBars = (
bar_index -
structureStart
)
int scanBars = math.min(
autoLookbackBars,
math.max(
0,
availableBars
)
)
for offset = 0 to scanBars
int testX = (
bar_index -
offset
)
if testX >= structureStart
float testUpper = f_line_price(
ux1,
uy1,
ux2,
uy2,
testX
)
float testLower = f_line_price(
lx1,
ly1,
lx2,
ly2,
testX
)
float testATR = atr[offset]
float touchTol = (
not na(testATR)
? testATR * touchToleranceATR
: 0.0
)
float violationTol = (
not na(testATR)
? testATR * violationToleranceATR
: 0.0
)
bool upperNear = (
math.abs(
high[offset] -
testUpper
) <= touchTol
)
bool lowerNear = (
math.abs(
low[offset] -
testLower
) <= touchTol
)
bool upperViolation = (
close[offset] >
testUpper +
violationTol
)
bool lowerViolation = (
close[offset] <
testLower -
violationTol
)
if upperNear
bool spacedUpper = (
na(lastUpperTouchX) or
math.abs(
testX -
lastUpperTouchX
) >= minTouchSpacing
)
if spacedUpper
upperTouchesLocal += 1
lastUpperTouchX := testX
if lowerNear
bool spacedLower = (
na(lastLowerTouchX) or
math.abs(
testX -
lastLowerTouchX
) >= minTouchSpacing
)
if spacedLower
lowerTouchesLocal += 1
lastLowerTouchX := testX
if upperViolation
upperViolationsLocal += 1
if lowerViolation
lowerViolationsLocal += 1
int totalTouchesLocal = (
upperTouchesLocal +
lowerTouchesLocal
)
int totalViolationsLocal = (
upperViolationsLocal +
lowerViolationsLocal
)
int minTouches = math.min(
upperTouchesLocal,
lowerTouchesLocal
)
int maxTouches = math.max(
upperTouchesLocal,
lowerTouchesLocal
)
float touchScore = math.min(
35.0,
float(totalTouchesLocal) *
5.0
)
float balanceFactor = (
totalTouchesLocal > 0
? (
1.0 -
math.abs(
float(
upperTouchesLocal -
lowerTouchesLocal
)
) /
float(totalTouchesLocal)
)
: 0.0
)
float balanceScore = (
balanceFactor *
15.0
)
float violationScore = math.max(
0.0,
25.0 -
float(totalViolationsLocal) *
3.0
)
int upperSpan = (
ux2 -
ux1
)
int lowerSpan = (
lx2 -
lx1
)
float averageSpan = (
float(upperSpan) +
float(lowerSpan)
) / 2.0
float spanScore = math.min(
10.0,
averageSpan /
15.0
)
int newestAnchor = math.max(
ux2,
lx2
)
float recencyScore = math.max(
0.0,
10.0 -
float(
bar_index -
newestAnchor
) *
0.15
)
float candidateWidthATR = (
atr > 0.0
? currentWidthLocal /
atr
: na
)
float widthScore = 0.0
if not na(candidateWidthATR)
if (
candidateWidthATR >= minStructureWidthATR and
candidateWidthATR <= maxStructureWidthATR
)
widthScore := 5.0
else if (
candidateWidthATR <
minStructureWidthATR
)
widthScore := math.max(
0.0,
(
candidateWidthATR /
minStructureWidthATR
) *
5.0
)
else
widthScore := math.max(
0.0,
5.0 -
(
candidateWidthATR -
maxStructureWidthATR
) *
0.25
)
finalScore := (
touchScore +
balanceScore +
violationScore +
spanScore +
recencyScore +
widthScore
)
if minTouches < 2
finalScore := math.min(
finalScore,
59.0
)
else if minTouches < 3
finalScore := math.min(
finalScore,
84.0
)
if minTouches > 0
float touchRatio = float(maxTouches) / float(minTouches)
if touchRatio > balancePenaltyStart
float imbalancePenalty = (touchRatio - balancePenaltyStart) * balancePenaltyStrength
finalScore -= imbalancePenalty
if touchRatio >= 2.0
finalScore := math.min(finalScore, 84.0)
if touchRatio >= 2.5
finalScore := math.min(finalScore, 74.0)
if touchRatio >= 3.0
finalScore := math.min(finalScore, 59.0)
finalScore := math.max(0.0, math.min(100.0, finalScore))
float pivotHigh = ta.pivothigh(
upperSource,
upperLen,
upperLen
)
float pivotLow = ta.pivotlow(
lowerSource,
lowerLen,
lowerLen
)
bool newUpperPivot = (
not na(pivotHigh)
)
bool newLowerPivot = (
not na(pivotLow)
)
var array<int> upperPivotBars = array.new_int()
var array<float> upperPivotPrices = array.new_float()
var array<int> lowerPivotBars = array.new_int()
var array<float> lowerPivotPrices = array.new_float()
if newUpperPivot
array.unshift(
upperPivotBars,
bar_index -
upperLen
)
array.unshift(
upperPivotPrices,
pivotHigh
)
if (
array.size(
upperPivotBars
) >
autoPivotCount
)
array.pop(
upperPivotBars
)
array.pop(
upperPivotPrices
)
if newLowerPivot
array.unshift(
lowerPivotBars,
bar_index -
lowerLen
)
array.unshift(
lowerPivotPrices,
pivotLow
)
if (
array.size(
lowerPivotBars
) >
autoPivotCount
)
array.pop(
lowerPivotBars
)
array.pop(
lowerPivotPrices
)
var int autoUpperX1 = na
var float autoUpperY1 = na
var int autoUpperX2 = na
var float autoUpperY2 = na
var int autoLowerX1 = na
var float autoLowerY1 = na
var int autoLowerX2 = na
var float autoLowerY2 = na
var float autoSelectionScore = na
bool shouldRescanAuto = (
selectionMode == "Auto" and
(
newUpperPivot or
newLowerPivot or
na(autoSelectionScore)
)
)
if (
shouldRescanAuto and
array.size(
upperPivotBars
) >= 2 and
array.size(
lowerPivotBars
) >= 2
)
float bestScore = na
int bestUX1 = na
float bestUY1 = na
int bestUX2 = na
float bestUY2 = na
int bestLX1 = na
float bestLY1 = na
int bestLX2 = na
float bestLY2 = na
int upperCount = array.size(
upperPivotBars
)
int lowerCount = array.size(
lowerPivotBars
)
for uNew = 0 to upperCount - 2
for uOld = uNew + 1 to upperCount - 1
int testUX1 = array.get(
upperPivotBars,
uOld
)
float testUY1 = array.get(
upperPivotPrices,
uOld
)
int testUX2 = array.get(
upperPivotBars,
uNew
)
float testUY2 = array.get(
upperPivotPrices,
uNew
)
for lNew = 0 to lowerCount - 2
for lOld = lNew + 1 to lowerCount - 1
int testLX1 = array.get(
lowerPivotBars,
lOld
)
float testLY1 = array.get(
lowerPivotPrices,
lOld
)
int testLX2 = array.get(
lowerPivotBars,
lNew
)
float testLY2 = array.get(
lowerPivotPrices,
lNew
)
float candidateScore = f_score_structure(
testUX1,
testUY1,
testUX2,
testUY2,
testLX1,
testLY1,
testLX2,
testLY2
)
bool betterCandidate = (
not na(candidateScore) and
(
na(bestScore) or
candidateScore >
bestScore
)
)
if betterCandidate
bestScore := candidateScore
bestUX1 := testUX1
bestUY1 := testUY1
bestUX2 := testUX2
bestUY2 := testUY2
bestLX1 := testLX1
bestLY1 := testLY1
bestLX2 := testLX2
bestLY2 := testLY2
if not na(bestUX1)
autoUpperX1 := bestUX1
autoUpperY1 := bestUY1
autoUpperX2 := bestUX2
autoUpperY2 := bestUY2
autoLowerX1 := bestLX1
autoLowerY1 := bestLY1
autoLowerX2 := bestLX2
autoLowerY2 := bestLY2
autoSelectionScore := bestScore
float manualUpperY1 = ta.valuewhen(
newUpperPivot,
pivotHigh,
manualUpperStart
)
float manualUpperY2 = ta.valuewhen(
newUpperPivot,
pivotHigh,
manualUpperEnd
)
int manualUpperX1 = int(
ta.valuewhen(
newUpperPivot,
bar_index -
upperLen,
manualUpperStart
)
)
int manualUpperX2 = int(
ta.valuewhen(
newUpperPivot,
bar_index -
upperLen,
manualUpperEnd
)
)
float manualLowerY1 = ta.valuewhen(
newLowerPivot,
pivotLow,
manualLowerStart
)
float manualLowerY2 = ta.valuewhen(
newLowerPivot,
pivotLow,
manualLowerEnd
)
int manualLowerX1 = int(
ta.valuewhen(
newLowerPivot,
bar_index -
lowerLen,
manualLowerStart
)
)
int manualLowerX2 = int(
ta.valuewhen(
newLowerPivot,
bar_index -
lowerLen,
manualLowerEnd
)
)
var table wm = table.new(position.bottom_right, 1, 1)
if barstate.isfirst
table.cell(wm, 0, 0, "Telegram @SimpleForexTools", text_color = color.new(color.gray, 70), text_size = size.large)
int upperX1 = (
selectionMode ==
"Auto"
? autoUpperX1
: manualUpperX1
)
float upperY1 = (
selectionMode ==
"Auto"
? autoUpperY1
: manualUpperY1
)
int upperX2 = (
selectionMode ==
"Auto"
? autoUpperX2
: manualUpperX2
)
float upperY2 = (
selectionMode ==
"Auto"
? autoUpperY2
: manualUpperY2
)
int lowerX1 = (
selectionMode ==
"Auto"
? autoLowerX1
: manualLowerX1
)
float lowerY1 = (
selectionMode ==
"Auto"
? autoLowerY1
: manualLowerY1
)
int lowerX2 = (
selectionMode ==
"Auto"
? autoLowerX2
: manualLowerX2
)
float lowerY2 = (
selectionMode ==
"Auto"
? autoLowerY2
: manualLowerY2
)
bool validUpper = (
not na(upperX1) and
not na(upperX2) and
not na(upperY1) and
not na(upperY2) and
upperX1 != upperX2
)
bool validLower = (
not na(lowerX1) and
not na(lowerX2) and
not na(lowerY1) and
not na(lowerY2) and
lowerX1 != lowerX2
)
bool structureValid = (
validUpper and
validLower
)
float upperNow = (
validUpper
? f_line_price(
upperX1,
upperY1,
upperX2,
upperY2,
bar_index
)
: na
)
float lowerNow = (
validLower
? f_line_price(
lowerX1,
lowerY1,
lowerX2,
lowerY2,
bar_index
)
: na
)
float structureWidth = (
structureValid
? upperNow -
lowerNow
: na
)
bool boundariesOrdered = (
structureValid and
not na(structureWidth) and
structureWidth > 0.0
)
float upperSlope = (
validUpper
? (
upperY2 -
upperY1
) /
float(
upperX2 -
upperX1
)
: na
)
float lowerSlope = (
validLower
? (
lowerY2 -
lowerY1
) /
float(
lowerX2 -
lowerX1
)
: na
)
bool converging = (
structureValid and
upperSlope <
lowerSlope
)
bool expanding = (
structureValid and
upperSlope >
lowerSlope
)
float slopeDiff = (
structureValid
? math.abs(
upperSlope -
lowerSlope
)
: na
)
float largestSlope = (
structureValid
? math.max(
math.abs(
upperSlope
),
math.abs(
lowerSlope
)
)
: na
)
bool roughlyParallel = (
structureValid and
(
largestSlope == 0.0 or
slopeDiff <=
largestSlope *
0.10
)
)
float apexX = na
if (
structureValid and
not roughlyParallel
)
float upperIntercept = (
upperY1 -
upperSlope *
float(
upperX1
)
)
float lowerIntercept = (
lowerY1 -
lowerSlope *
float(
lowerX1
)
)
float denominator = (
upperSlope -
lowerSlope
)
if (
math.abs(
denominator
) >
0.0000001
)
apexX := (lowerIntercept - upperIntercept) / denominator
float barsToApex = (
converging and
not na(apexX)
? apexX -
float(
bar_index
)
: na
)
bool apexPassed = (
converging and
not na(
barsToApex
) and
barsToApex <= 0.0
)
float widthATR = (
boundariesOrdered and
atr > 0.0
? structureWidth /
atr
: na
)
float projectedUpper = (
structureValid
? f_line_price(
upperX1,
upperY1,
upperX2,
upperY2,
bar_index +
convergenceProjectionBars
)
: na
)
float projectedLower = (
structureValid
? f_line_prПоказано первые 50% кода (символов: 29181)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.