← К каталогу
Исходный код · ID 4167

Reaction Path

indicator reaction path for tradingview.pine
Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

Reaction Path — это индикатор для TradingView, написанный на Pine Script v6. Он предназначен для анализа поведения цены, объёма и времени и отображает на графике возможные реакции и продолжения движения. Индикатор не использует классические осцилляторы, такие как RSI, MACD или Bollinger Bands.

В основе индикатора лежат расчёт справедливой цены с адаптивной полосой отклонения, центр давления, проекционный коридор и адаптивная память неудач. Справедливая цена рассчитывается как взвешенная средняя типичной цены за последние N баров, где свечи с большими тенями получают больший вес. Центр давления показывает, где внутри диапазона бара закрылась цена, усреднённо за окно. Проекционный коридор — это визуальный ориентир, ширина которого зависит от текущей неопределённости рынка, а не от фиксированного процента. Память неудач повышает требования к новым сигналам после убыточной сделки.

Индикатор работает только на стандартных типах графиков и отключается на Heikin Ashi, Renko и других нестандартных типах. Сигналы формируются только по подтверждённым барам, без использования будущих данных. Отображаются уровни входа, цели, инвалидации, полоса реакции и панель состояния. Индикатор не является торговым советником и не даёт гарантий доходности.

Настройки программы

НастройкаОписание
signalModeInput Выбор семейства сигналов: Reaction Only (только реакции), Continuation Only (только продолжения) или Both (оба).
sensitivityInput Общая настройка чувствительности движка. Меньшие значения ужесточают требования к расстоянию и расширению, ослабляя пороги качества; большие значения действуют наоборот.
t1AtrInput Расстояние от точки входа до Path Level 1, измеряется в единицах ATR.
t2AtrInput Расстояние от точки входа до Path Level 2, измеряется в единицах ATR. Это основная проекционная цель индикатора.
invalidationAtrInput Расстояние за экстремум реакции для определения границы инвалидации, измеряется в единицах ATR.
showHistoryInput Если включено, завершённые сетапы остаются видимыми на графике до достижения лимита максимального количества. Если выключено, отрисовка сетапа удаляется сразу после его закрытия.
maxHistoryInput Максимальное количество завершённых сетапов, отображаемых на графике одновременно. Старые удаляются при превышении лимита.
showFairBandInput Отображает зону справедливой цены в виде трёх вложенных полос на графике цены, показывая текущую взвешенную область стоимости и диапазон отклонения.
showDashboardInput Показывает или скрывает панель состояния на графике с текущим рыночным состоянием, направлением пути, расположением цены относительно справедливой цены и уровнями активного сетапа.
dashboardSizeInput Размер текста панели состояния: Small, Medium или Large.
dashboardPositionInput Выбор угла графика для размещения панели состояния: Top Left, Top Right, Bottom Left или Bottom Right.
Получить полный код

Поиск по коду файла

indicator("Reaction Path", overlay = false, max_lines_count = 500, max_labels_count = 500, max_bars_back = 500)

var string GRP_PATH = "Trade Geometry"
var string GRP_VIS = "Visual System"
var string GRP_DASH = "Dashboard"
var string GRP_ENGINE = "Engine Sensitivity"

string signalModeInput = input.string(
     "Both",
     "Signal Mode",
     options = ["Reaction Only", "Continuation Only", "Both"],
     group = GRP_ENGINE,
     tooltip = "Choose which signal family the engine is allowed to open: Reaction setups (mean-reversion off fair value), Continuation setups (trend persistence), or both."
     )

float sensitivityInput = input.float(
     0.75,
     "Setup Sensitivity",
     minval = 0.50,
     maxval = 1.50,
     step = 0.05,
     group = GRP_ENGINE,
     tooltip = "Adjusts the overall qualification balance. Lower values tighten distance and expansion requirements while relaxing several quality thresholds; higher values do the opposite. Use this control to adapt overall setup selectivity."
     )

float t1AtrInput = input.float(
     1.2,
     "Path Level 1",
     minval = 0.3,
     maxval = 8.0,
     step = 0.1,
     group = GRP_PATH,
     tooltip = "Distance from the setup entry reference to Path Level 1, measured in ATR units."
     )

float t2AtrInput = input.float(
     2.4,
     "Path Level 2",
     minval = 0.5,
     maxval = 12.0,
     step = 0.1,
     group = GRP_PATH,
     tooltip = "Distance from the setup entry reference to Path Level 2, measured in ATR units. This is the primary projected objective used by the indicator's trade geometry."
     )

float invalidationAtrInput = input.float(
     1.2,
     "Invalidation",
     minval = 0.3,
     maxval = 8.0,
     step = 0.1,
     group = GRP_PATH,
     tooltip = "Distance beyond the reaction extreme used to define the setup invalidation boundary. It is a reference level, not a guarantee of execution or outcome."
     )

bool showHistoryInput = input.bool(
     true,
     "Show Historical Setups",
     group = GRP_VIS,
     tooltip = "When enabled, completed setups stay visible on the chart (up to the Maximum Historical Setups limit below) instead of disappearing once they close, so you can review how past setups played out. When disabled, a setup's drawings are removed as soon as it closes."
     )

int maxHistoryInput = input.int(
     20,
     "Maximum Historical Setups",
     minval = 3,
     maxval = 25,
     group = GRP_VIS,
     tooltip = "Caps how many completed setups stay drawn on the chart at once. The oldest setup is automatically removed once this limit is reached. This is kept intentionally bounded to stay comfortably within TradingView's per-script drawing-object limits."
     )

bool showFairBandInput = input.bool(
     true,
     "Show Reaction Band",
     group = GRP_VIS,
     tooltip = "Displays the Fair Price zone as three nested bands on the price chart, showing the current wick-weighted value area and its deviation range. Turn off for a cleaner chart if you only want the pane readout and trade markers."
     )

bool showPathInput = input.bool(
     true,
     "Show Projected Path",
     group = GRP_VIS,
     tooltip = "Displays the Projected Path corridor running from the setup's entry toward Path Level 2. This is a visual route built from current market conditions, not a price forecast or guarantee. Turn off to show only the entry, target and invalidation lines without the corridor."
     )

bool showDashboardInput = input.bool(
     true,
     "Show Dashboard",
     group = GRP_DASH,
     tooltip = "Displays the on-chart panel summarising the current market state, path direction, price location relative to fair value, and the active setup's levels (if any)."
     )

string dashboardSizeInput = input.string(
     "Small",
     "Dashboard Size",
     options = ["Small", "Medium", "Large"],
     group = GRP_DASH,
     tooltip = "Controls the text size of the on-chart dashboard panel."
     )

string dashboardPositionInput = input.string(
     "Top Right",
     "Dashboard Position",
     options = ["Top Left", "Top Right", "Bottom Left", "Bottom Right"],
     group = GRP_DASH,
     tooltip = "Controls which corner of the chart the dashboard panel is anchored to."
     )

int N = 20              // Lookback window for fair price and volume baseline.
int M = 5               // Short window for recent candle character (wicks, range, direction).
int K = 10              // Window for the pressure-centre calculation.
int J = 5               // Offset used to measure how far pressure has migrated.
int ATR_LENGTH = 14     // Standard ATR length used throughout for normalisation.

float MIN_DISPLACEMENT = 0.8               // Minimum distance from fair price, in half-bands, to qualify a reaction.
float MIN_DIRECTIONAL_EFFICIENCY = 0.55    // Minimum body-to-range quality required of the recent directional bars.
float MIN_SPEED = 0.9                      // Minimum bar range relative to the recent average range.
float MIN_VOLUME = 0.8                     // Minimum volume relative to its recent average.
float MIN_DEPTH = 0.5                      // Minimum penetration beyond fair price required for a reaction.

float SPIKE_MULTIPLIER = 3.0               // A bar this many times the average range is treated as a spike, not normal behaviour.
float SPIKE_EFFICIENCY = 0.2               // Efficiency threshold used to classify outsized bars as low-quality spike behaviour.
float CONTINUATION_MAX_WICK = 0.35         // Maximum wick ratio allowed on a continuation bar before it looks indecisive.

float EXHAUSTION_HIGH = 0.80               // Pressure centre above this is considered exhausted to the upside.
float EXHAUSTION_LOW = 0.20                // Pressure centre below this is considered exhausted to the downside.
float STALL_THRESHOLD = 0.015              // Minimum migration required before it counts as real directional drift, not noise.
float BUILD_THRESHOLD = 0.70               // Pressure centre level that marks the start of a "building" state.
float APPROACH_MINIMUM = 0.02              // How close to BUILD_THRESHOLD price must be to count as approaching it.

float MIGRATION_SCALE = 3.0                // Scales raw migration into the visual reaction-field units.

int TREND_WINDOW = 15                      // Lookback used to measure whether the market is actually trending before allowing a continuation signal.
float MIN_TREND_EFFICIENCY = 0.38          // Minimum net-displacement-to-path-length ratio required to qualify as trend-aligned.

float displacementThreshold = MIN_DISPLACEMENT / sensitivityInput
float directionalEfficiencyThreshold = MIN_DIRECTIONAL_EFFICIENCY * sensitivityInput
float speedThreshold = MIN_SPEED * sensitivityInput
float depthThreshold = MIN_DEPTH / sensitivityInput
float continuationWickThreshold = CONTINUATION_MAX_WICK / sensitivityInput
float volumeThresholdSensitivity = MIN_VOLUME * sensitivityInput
float stallThreshold = STALL_THRESHOLD * sensitivityInput
float expansionAtrFloor = 0.70 / sensitivityInput
float trendEfficiencyThreshold = MIN_TREND_EFFICIENCY * sensitivityInput

bool reactionSignalsEnabled = signalModeInput != "Continuation Only"
bool continuationSignalsEnabled = signalModeInput != "Reaction Only"

color COLOR_UP_REACTION = #38D9C4
color COLOR_UP_TRAVEL = #5B8CFF
color COLOR_DOWN_REACTION = #FF708A
color COLOR_DOWN_TRAVEL = #B56CFF

color COLOR_REACTION = #38D9C4
color COLOR_CONTINUATION = #6F8CFF
color COLOR_SHIFT = #FFC857
color COLOR_BUILDING = #55D8FF
color COLOR_EXHAUSTION = #B974FF
color COLOR_NEUTRAL = #9BA8B5
color COLOR_INVALIDATION = #FFAA4A
color COLOR_PATH_LEVEL_ONE = #4CAF50
color COLOR_PATH_LEVEL_TWO = #D6249F
color COLOR_WHITE = #F4F7FA

color COLOR_PANEL = #11161D
color COLOR_PANEL_BORDER = #2A323C

safeDiv(float numerator, float denominator, float fallback) =>
    denominator == 0.0 or na(denominator) ? fallback : numerator / denominator

clamp(float value, float minimum, float maximum) =>
    math.max(minimum, math.min(value, maximum))

volumeReliable() =>
    float volumeSum = 0.0
    float volumeSquares = 0.0

    for i = 0 to N - 1
        float currentVolume = nz(volume[i], 0.0)
        volumeSum += currentVolume
        volumeSquares += currentVolume * currentVolume

    float meanVolume = safeDiv(volumeSum, N, 0.0)
    float variance = safeDiv(volumeSquares, N, 0.0) - meanVolume * meanVolume
    float coefficient = safeDiv(math.sqrt(math.max(variance, 0.0)), meanVolume, 0.0)

    coefficient > 0.05

dashboardTextSize(string value) =>
     value == "Large"
         ? size.normal
         : value == "Medium"
             ? size.small
             : size.tiny

dashboardPosition(string value) =>
    value == "Top Left" ? position.top_left :
     value == "Bottom Left" ? position.bottom_left :
     value == "Bottom Right" ? position.bottom_right :
     position.top_right

stateColor(string value) =>
    value == "REACTION" ? COLOR_REACTION :
     value == "TRAVEL" ? COLOR_CONTINUATION :
     value == "BUILDING" ? COLOR_BUILDING :
     value == "SHIFT" ? COLOR_SHIFT :
     value == "EXHAUSTION" ? COLOR_EXHAUSTION :
     value == "MOVING UP" ? COLOR_UP_REACTION :
     value == "MOVING DOWN" ? COLOR_DOWN_REACTION :
     COLOR_NEUTRAL

buildAlertMessage(string eventLabel, string signalType, float priceLevel) =>
    syminfo.prefix + ":" + syminfo.ticker + " | " + timeframe.period + " | " + eventLabel + " | " + signalType + " | Price: " + str.tostring(priceLevel, format.mintick)

float atrValue = ta.atr(ATR_LENGTH)

bool engineReady = chart.is_standard and bar_index > N + J + M + ATR_LENGTH

var label nonStandardWarning = na

if not chart.is_standard and barstate.islast
    label.delete(nonStandardWarning)
    nonStandardWarning := label.new(
         bar_index,
         high,
         "Reaction Path requires a standard chart.\nSignals are disabled on non-standard chart types.",
         color = COLOR_INVALIDATION,
         textcolor = COLOR_WHITE,
         style = label.style_label_left,
         size = size.normal,
         force_overlay = true
         )

fairCalc(int offset) =>
    float weightedBase = 0.0
    float totalWeight = 0.0

    for i = offset to offset + N - 1
        float basePrice = (high[i] + low[i] + 2.0 * close[i]) / 4.0
        float candleRange = high[i] - low[i]
        float candleBody = math.abs(close[i] - open[i])
        float weight = 1.0 - safeDiv(candleBody, candleRange, 1.0)

        weightedBase += basePrice * weight
        totalWeight += weight

    float fallbackFair = (high[offset] + low[offset] + 2.0 * close[offset]) / 4.0
    float fair = safeDiv(weightedBase, totalWeight, fallbackFair)

    float weightedDeviation = 0.0
    float deviationWeight = 0.0

    for i = offset to offset + N - 1
        float basePrice = (high[i] + low[i] + 2.0 * close[i]) / 4.0
        float candleRange = high[i] - low[i]
        float candleBody = math.abs(close[i] - open[i])
        float weight = 1.0 - safeDiv(candleBody, candleRange, 1.0)

        weightedDeviation += math.abs(basePrice - fair) * weight
        deviationWeight += weight

    float fallbackHalf = math.abs(close[offset] - fair) * 0.5

    float halfBand = math.max(
         safeDiv(weightedDeviation, deviationWeight, fallbackHalf),
         syminfo.mintick * 2.0
         )

    [fair, halfBand]

[fairPrice, fairHalf] = fairCalc(0)
[previousFair, previousHalf] = fairCalc(1)

float fairUpper = fairPrice + fairHalf
float fairLower = fairPrice - fairHalf

float previousUpper = previousFair + previousHalf
float previousLower = previousFair - previousHalf

bool aboveFair = close > fairUpper
bool belowFair = close < fairLower

bool previousAboveFair = close[1] > previousUpper
bool previousBelowFair = close[1] < previousLower

bool acceptingAbove = aboveFair and previousAboveFair
bool acceptingBelow = belowFair and previousBelowFair

pressureCentreAt(int offset) =>
    float pressureSum = 0.0
    float pressureWeight = 0.0

    for i = offset to offset + K - 1
        float candleRange = high[i] - low[i]
        float candleBody = math.abs(close[i] - open[i])
        float weight = 1.0 - safeDiv(candleBody, candleRange, 1.0)
        float closeLocation = safeDiv(close[i] - low[i], candleRange, 0.5)

        pressureSum += closeLocation * weight
        pressureWeight += weight

    safeDiv(pressureSum, pressureWeight, 0.5)

float pressureNow = pressureCentreAt(0)
float pressurePrior = pressureCentreAt(J)
float pressurePrevious = pressureCentreAt(1)
float pressurePreviousPrior = pressureCentreAt(J + 1)

float migration = pressureNow - pressurePrior
float previousMigration = pressurePrevious - pressurePreviousPrior

bool approachingBuild =
     pressureNow >= BUILD_THRESHOLD - APPROACH_MINIMUM and
     pressureNow < BUILD_THRESHOLD and
     pressureNow > pressurePrior

bool exhaustion =
     pressureNow >= EXHAUSTION_HIGH or
     pressureNow <= EXHAUSTION_LOW

bool reversing =
     not exhaustion and
     (
         (migration >= stallThreshold and previousMigration <= -stallThreshold) or
         (migration <= -stallThreshold and previousMigration >= stallThreshold)
     )

bool building =
     not exhaustion and
     not reversing and
     (approachingBuild or pressureNow >= BUILD_THRESHOLD) and
     migration > 0.0

bool migratingUp =
     not exhaustion and
     not reversing and
     not building and
     migration > stallThreshold

bool migratingDown =
     not exhaustion and
     not reversing and
     not building and
     not migratingUp and
     migration < -stallThreshold

bool pressureUp =
     migration > 0.0 and
     (migratingUp or building or reversing)

bool pressureDown =
     migration < 0.0 and
     (migratingDown or reversing)

bool continuationLong =
     migration > 0.0 and
     (building or migratingUp)

bool continuationShort =
     migration < 0.0 and
     migratingDown

float trendNetDisplacement = close - close[TREND_WINDOW]

float trendPathLength = 0.0

for i = 0 to TREND_WINDOW - 1
    trendPathLength += math.abs(close[i] - close[i + 1])

float trendEfficiencyRatio = safeDiv(math.abs(trendNetDisplacement), trendPathLength, 0.0)

bool trendAlignedLong = trendNetDisplacement > 0.0 and trendEfficiencyRatio >= trendEfficiencyThreshold
bool trendAlignedShort = trendNetDisplacement < 0.0 and trendEfficiencyRatio >= trendEfficiencyThreshold

float barRange = high - low
float barBody = math.abs(close - open)

float efficiency = safeDiv(barBody, barRange, 1.0)

float upperWick = high - math.max(open, close)
float lowerWick = math.min(open, close) - low

float upperWickRatio = safeDiv(upperWick, barRange, 0.0)
float lowerWickRatio = safeDiv(lowerWick, barRange, 0.0)

float averageRange = 0.0

for i = 1 to M
    averageRange += high[i] - low[i]

averageRange := safeDiv(averageRange, M, barRange)

float speedRatio = safeDiv(barRange, averageRange, 1.0)

bool reliableVolume = volumeReliable()

float averageVolume = 0.0

for i = 1 to N
    averageVolume += nz(volume[i], 0.0)

averageVolume := safeDiv(averageVolume, N, 0.0)

float volumeRatio = reliableVolume ? safeDiv(volume, averageVolume, 1.0) : 1.0

float directionalEfficiencyLong = 0.0
float directionalEfficiencyShort = 0.0

int directionalCountLong = 0
int directionalCountShort = 0

for i = 0 to M - 1
    float historicalRange = high[i] - low[i]
    float historicalBody = math.abs(close[i] - open[i])
    float historicalEfficiency = safeDiv(historicalBody, historicalRange, 1.0)

    if close[i] > open[i]
        directionalEfficiencyLong += historicalEfficiency
        directionalCountLong += 1
    else if close[i] < open[i]
        directionalEfficiencyShort += historicalEfficiency
        directionalCountShort += 1

float meanDirectionalEfficiencyLong = safeDiv(directionalEfficiencyLong, directionalCountLong, 0.0)
float meanDirectionalEfficiencyShort = safeDiv(directionalEfficiencyShort, directionalCountShort, 0.0)

float directionalDominanceLong = safeDiv(directionalCountLong, M, 0.0)
float directionalDominanceShort = safeDiv(directionalCountShort, M, 0.0)

float displacement = safeDiv(close - fairPrice, fairHalf, 0.0)

float depthBelowFair = 0.0
float depthAboveFair = 0.0

for i = 1 to M
    depthBelowFair := math.max(depthBelowFair, safeDiv(fairPrice - low[i], fairHalf, 0.0))
    depthAboveFair := math.max(depthAboveFair, safeDiv(high[i] - fairPrice, fairHalf, 0.0))

bool currentSpike =
     barRange > SPIKE_MULTIPLIER * averageRange and
     efficiency < SPIKE_EFFICIENCY

bool previousSpikeReversal =
     (high[1] - low[1]) > SPIKE_MULTIPLIER * averageRange and
     safeDiv(
         math.abs(close[1] - open[1]),
         math.max(high[1] - low[1], syminfo.mintick),
         1.0
         ) < SPIKE_EFFICIENCY and
     close >= low[1] and
     close <= high[1]

bool normalBar =
     not currentSpike and
     not previousSpikeReversal

float previousMaximumRange = 0.0

for i = 1 to M
    previousMaximumRange := math.max(previousMaximumRange, high[i] - low[i])

bool newExpansion =
     barRange >= previousMaximumRange and
     barRange >= atrValue * expansionAtrFloor

bool longReactionGate =
     displacement < -displacementThreshold and
     meanDirectionalEfficiencyLong >= directionalEfficiencyThreshold and
     directionalDominanceLong >= 0.40 and
     lowerWickRatio > upperWickRatio and
     lowerWick > upperWick and
     speedRatio >= speedThreshold and
     volumeRatio >= volumeThresholdSensitivity and
     depthBelowFair >= depthThreshold and
     normalBar

bool shortReactionGate =
     displacement > displacementThreshold and
     meanDirectionalEfficiencyShort >= directionalEfficiencyThreshold and
     directionalDominanceShort >= 0.40 and
     upperWickRatio > lowerWickRatio and
     upperWick > lowerWick and
     speedRatio >= speedThreshold and
     volumeRatio >= volumeThresholdSensitivity and
     depthAboveFair >= depthThreshold and
     normalBar

bool longContinuationGate =
     (aboveFair or acceptingAbove) and
     newExpansion and
     upperWickRatio < continuationWickThreshold and
     efficiency > 0.5 and
     speedRatio >= speedThreshold and
     volumeRatio >= volumeThresholdSensitivity and
     trendAlignedLong and
     normalBar

bool shortContinuationGate =
     (belowFair or acceptingBelow) and
     newExpansion and
     lowerWickRatio < continuationWickThreshold and
     efficiency > 0.5 and
     speedRatio >= speedThreshold and
     volumeRatio >= volumeThresholdSensitivity and
     trendAlignedShort and
     normalBar
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)

type Trade
    int sigBar
    int closeBar
    bool isLong
    string signalType
    float entry
    float targetOne
    float targetTwo
    float invalidation
    bool active
    int extensionCount
    line entryLine
    line targetOneLine
    line targetTwoLine
    line invalidationLine
    label signalLabel
    line pathUpperOne
    line pathUpperTwo
    line pathUpperThree
    line pathLowerOne
    line pathLowerTwo
    line pathLowerThree
    line pathCenterOne
    line pathCenterTwo
    line pathCenterThree
    linefill pathFillOne
    linefill pathFillTwo
    linefill pathFillThree

var bool rearmReady = true
var bool rearmPending = false
var bool tradeClosedThisBar = false

var Trade activeTrade = na
var Trade[] historicalTrades = array.new<Trade>()
var bool signalEventLocked = false
var int signalEventDirection = 0
var int signalEventFamily = 0
var label liveTargetOneLabel = na
var label liveTargetTwoLabel = na
var label liveEntryLabel = na
var label liveInvalidationLabel = na

var bool failureMemoryActive = false
var int failureMemoryBar = na
var int lastFailureBar = na
var int failureCount = 0
var bool failedDirectionLong = false
var int failedSignalFamily = 0

var float failedDisplacement = na
var float failedMigration = na
var float failedEfficiency = na
var float failedSpeedRatio = na
var float failedDepth = na
var float failedVolumeRatio = na
var float failedPressure = na
var float failedRangeRatio = na

var int FAILURE_MEMORY_LIMIT = 30
var int FAILURE_MAX_COUNT = 3
var int MAX_TARGET_EXTENSIONS = 3

featureSimilarity(float currentValue, float referenceValue, float tolerance) =>
    float similarity = 0.0
    if not na(referenceValue)
        similarity := 1.0 - clamp(math.abs(currentValue - referenceValue) / tolerance, 0.0, 1.0)
    similarity

currentFailureSimilarity(bool isLong) =>
    float currentEfficiency = isLong ? meanDirectionalEfficiencyLong : meanDirectionalEfficiencyShort
    float currentDepth = isLong ? depthBelowFair : depthAboveFair
    float similarityDisplacement = featureSimilarity(math.abs(displacement), failedDisplacement, 0.80)
    float similarityMigration = featureSimilarity(migration, failedMigration, 0.12)
    float similarityEfficiency = featureSimilarity(currentEfficiency, failedEfficiency, 0.25)
    float similaritySpeed = featureSimilarity(speedRatio, failedSpeedRatio, 0.80)
    float similarityDepth = featureSimilarity(currentDepth, failedDepth, 1.00)
    float similarityVolume = featureSimilarity(volumeRatio, failedVolumeRatio, 0.75)
    float similarityPressure = featureSimilarity(pressureNow, failedPressure, 0.20)
    float currentRangeRatio = safeDiv(barRange, atrValue, 1.0)
    float similarityRange = featureSimilarity(currentRangeRatio, failedRangeRatio, 0.80)
    float similarityTotal = similarityDisplacement + similarityMigration + similarityEfficiency + similaritySpeed + similarityDepth + similarityVolume + similarityPressure + similarityRange
    similarityTotal / 8.0

failureMemoryExpired() =>
    bool expired = false
    if failureMemoryActive and not na(failureMemoryBar)
        expired := bar_index - failureMemoryBar > FAILURE_MEMORY_LIMIT
    expired

failureBehaviourReset() =>
    bool resetDetected = false

    if failureMemoryActive
        bool displacementReset = math.abs(displacement) < 0.35
        bool pressureReset = math.abs(migration) < 0.025
        bool directionReset = false

        if failedDirectionLong and migration < -0.025
            directionReset := true

        if not failedDirectionLong and migration > 0.025
            directionReset := true

        float currentRangeRatio = safeDiv(barRange, atrValue, 1.0)
        bool rangeExpansionReset = false

        if not na(failedRangeRatio)
            rangeExpansionReset := currentRangeRatio > failedRangeRatio * 1.25

        resetDetected := displacementReset or pressureReset or directionReset or rangeExpansionReset

    resetDetected

signalBehaviourReset(int direction, int family) =>

    bool resetDetected = false

    if family == 1

        if direction == 1
            resetDetected := displacement > 0.15 and migration <= 0.0
        else
            resetDetected := displacement < -0.15 and migration >= 0.0

    else

        if direction == 1
            bool acceptanceBroken = not aboveFair and not acceptingAbove
            bool pressureReversed = migration <= -stallThreshold
            resetDetected := acceptanceBroken and pressureReversed
        else
            bool acceptanceBroken = not belowFair and not acceptingBelow
            bool pressureReversed = migration >= stallThreshold
            resetDetected := acceptanceBroken and pressureReversed

    resetDetected

computeLevels(bool isLong, bool isReaction, float atr) =>
    float direction = isLong ? 1.0 : -1.0

    float computedTargetOne = close + direction * t1AtrInput * atr
    float computedTargetTwo = close + direction * t2AtrInput * atr

    float computedInvalidation =
         isReaction
             ? (isLong ? low - invalidationAtrInput * atr : high + invalidationAtrInput * atr)
             : fairPrice

    [computedTargetOne, computedTargetTwo, computedInvalidation]

tradeColor(Trade trade) =>
    trade.signalType == "LONG_REACTION" ? COLOR_UP_REACTION :
     trade.signalType == "SHORT_REACTION" ? COLOR_DOWN_REACTION :
     trade.signalType == "LONG_CONT" ? COLOR_UP_TRAVEL :
     COLOR_DOWN_TRAVEL

createPath(Trade trade) =>

    float direction = trade.isLong ? 1.0 : -1.0
    float totalTravel = math.abs(trade.targetTwo - trade.entry)

    float pressureDrive = clamp(math.abs(migration) * 7.0, 0.0, 1.0)
    float directionalDrive = clamp(math.abs(displacement) * 0.12, 0.0, 0.50)

    float stateDrive =
         continuationLong or continuationShort
             ? 0.35
             : building
                 ? 0.22
                 : reversing
                     ? -0.18
                     : 0.0

    float routeDrive = clamp(pressureDrive + directionalDrive + stateDrive, -0.25, 1.0)
    float routeCurve = direction * totalTravel * 0.18 * routeDrive

    float pointOne = trade.entry + direction * totalTravel * 0.30 + routeCurve * 0.45
    float pointTwo = trade.entry + direction * totalTravel * 0.65 + routeCurve

    float uncertainty =
         exhaustion or reversing
             ? 0.34
             : building
                 ? 0.27
                 : pressureUp or pressureDown
                     ? 0.20
                     : 0.24

    float corridor = math.max(atrValue * uncertainty, syminfo.mintick * 12.0)

    float upperEntry = trade.entry + corridor
    float upperOne = pointOne + corridor * 0.82
    float upperTwo = pointTwo + corridor * 0.64
    float upperThree = trade.targetTwo + corridor * 0.38

    float lowerEntry = trade.entry - corridor
    float lowerOne = pointOne - corridor * 0.82
    float lowerTwo = pointTwo - corridor * 0.64
    float lowerThree = trade.targetTwo - corridor * 0.38

    int x0 = trade.sigBar
    int x1 = trade.sigBar + 4
    int x2 = trade.sigBar + 9
    int x3 = trade.sigBar + 16

    color pathColor = tradeColor(trade)

    trade.pathUpperOne := line.new(x0, upperEntry, x1, upperOne, color = color.new(pathColor, 78), width = 1, force_overlay = true)
    trade.pathUpperTwo := line.new(x1, upperOne, x2, upperTwo, color = color.new(pathColor, 78), width = 1, force_overlay = true)
    trade.pathUpperThree := line.new(x2, upperTwo, x3, upperThree, color = color.new(pathColor, 82), width = 1, force_overlay = true)

    trade.pathLowerOne := line.new(x0, lowerEntry, x1, lowerOne, color = color.new(pathColor, 78), width = 1, force_overlay = true)
    trade.pathLowerTwo := line.new(x1, lowerOne, x2, lowerTwo, color = color.new(pathColor, 78), width = 1, force_overlay = true)
    trade.pathLowerThree := line.new(x2, lowerTwo, x3, lowerThree, color = color.new(pathColor, 82), width = 1, force_overlay = true)

    trade.pathCenterOne := line.new(x0, trade.entry, x1, pointOne, color = color.new(pathColor, 22), width = 2, force_overlay = true)
    trade.pathCenterTwo := line.new(x1, pointOne, x2, pointTwo, color = color.new(pathColor, 22), width = 2, force_overlay = true)
    trade.pathCen

Показано первые 50% кода (символов: 41402)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
4 140,20₽ ≈ $50.61