Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
freem
Search
Search
Appearance
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Openai/694a9127-1940-8001-9b22-f125f741a780
(section)
Add languages
Page
Discussion
English
Read
Edit
Edit source
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
Edit source
View history
General
What links here
Related changes
Special pages
Page information
Appearance
move to sidebar
hide
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
=== User: //@version6 === //@version=6 indicator('CTRADE-PROD-XAUUSD-1.8 RedMagmaEA (VERTICAL MARKERS)', overlay=true, max_bars_back=1000, max_labels_count=300, max_lines_count=500, max_boxes_count=500) // ========================================== // 1. INPUT CONFIGURATION // ========================================== var GRP_TF1 = "β’β’β’β’β’β’β’β’ Timeframe 1 Market Structure β’β’β’β’β’β’β’β’" tf1_useStructure = input.bool(true, "", inline="1", group=GRP_TF1) tf1_timeframe = input.timeframe("", "Timeframe 1", inline="1", group=GRP_TF1) tf1_min = input.timeframe("", "Min", inline="1", group=GRP_TF1) tf1_div1 = input.bool(false, "----------------------------------", group=GRP_TF1) tf1_structureTopColor = input.color(color.new(color.green, 70), "Top", group = GRP_TF1, inline="2") tf1_structureBottomColor = input.color(color.new(color.green, 70), "Bottom", group = GRP_TF1, inline="2") tf1_structurelabelSize = input.string(title='Size', defval='auto', options=['auto', 'Tiny', 'Small'], group=GRP_TF1, inline="2") tf1_showHhll = input.bool(true, "HH/LL Labels", inline="2b", group=GRP_TF1) tf1_hhllBullColor = input.color(color.lime, "Bull", group = GRP_TF1, inline="2b") tf1_hhllBearColor = input.color(color.red, "Bear", group = GRP_TF1, inline="2b") tf1_hhllLabelSize = input.string(title='Size', defval='Small', options=['auto', 'Tiny', 'Small', 'Normal'], group=GRP_TF1, inline="2b") tf1_div2 = input.bool(false, "----------------------------------", group=GRP_TF1) tf1_showIlq = input.bool(true, "Show ILQ ?", inline="3", group=GRP_TF1) tf1_ilqText = input.string(defval='ILQ', title='Text', inline="3", group=GRP_TF1) tf1_ilqStyle = input.string(title="Style", defval="Solid", options=["Solid", "Dashed", "Dotted"], inline="4", group=GRP_TF1) tf1_ilqWidth = input.int(2, 'Width', minval=1, maxval=4, inline="4", group=GRP_TF1) tf1_ilqCol = input.color(color.orange, title='Col', inline='4', group=GRP_TF1) tf1_div3 = input.bool(false, "----------------------------------", group=GRP_TF1) tf1_showTlq = input.bool(true, "Show TLQ (Breakout Lines) ?", inline="5", group=GRP_TF1) tf1_tlqText = input.string(defval='TLQ', title='Text', inline="5", group=GRP_TF1) tf1_showBos = input.bool(true, "Show BOS Lines ?", inline="5", group=GRP_TF1) tf1_tlqStyle = input.string(title="Style", defval="Solid", options=["Solid", "Dashed", "Dotted"], inline="6", group=GRP_TF1) tf1_tlqWidth = input.int(1, 'Width', minval=1, maxval=4, inline="6", group=GRP_TF1) tf1_tlqCol = input.color(color.lime, title='Col', inline='6', group=GRP_TF1) tf1_div4 = input.bool(false, "----------------------------------", group=GRP_TF1) tf1_showEpa = input.bool(true, "Show EPA ?", inline="7", group=GRP_TF1) tf1_epaText = input.string(defval='EPA', title='Text', inline="7", group=GRP_TF1) tf1_epaDelete = input.bool(true, "Delete Unfilled", inline="7", group=GRP_TF1) tf1_epaStyle = input.string(title="Style", defval="Dashed", options=["Solid", "Dashed", "Dotted"], inline="8", group=GRP_TF1) tf1_epaWidth = input.int(1, 'Width', minval=1, maxval=4, inline="8", group=GRP_TF1) tf1_epaCol = input.color(color.blue, title='Col', inline='8', group=GRP_TF1) tf1_div5 = input.bool(false, "----------------------------------", group=GRP_TF1) tf1_showMsu = input.bool(true, "Show MSU Arrows ?", inline="9", group=GRP_TF1) tf1_div6 = input.bool(false, "----------------------------------", group=GRP_TF1) tf1_showExtreme = input.bool(true, "Show Extreme ?", inline="10", group=GRP_TF1) tf1_extremeText = input.string(defval='Extreme', title='Text', inline="10", group=GRP_TF1) tf1_extremeCol = input.color(color.new(color.gray, 80), title='Col', inline='10', group=GRP_TF1) tf1_div8 = input.bool(false, "----------------------------------", group=GRP_TF1) tf1_changeBarCol = input.bool(true, "Change bar colors?", inline="13", group=GRP_TF1) tf1_bullishBullBarCol = input.color(color.rgb(68, 199, 177), title='Bullish Bull', inline='14', group=GRP_TF1) tf1_bullishBearBarCol = input.color(color.rgb(37, 177, 160), title='Bullish Bear', inline='14', group=GRP_TF1) tf1_bearishBullBarCol = input.color(color.rgb(247,134,143), title='Bearish Bull', inline='15', group=GRP_TF1) tf1_bearishBearBarCol = input.color(color.rgb(193,81,95), title='Bearish Bear', inline='15', group=GRP_TF1) // ========== STRATEGY SETTINGS (NEW) ========== var GRP_STRAT = "β’β’β’β’β’β’β’β’ Strategy Logic: Retracement β’β’β’β’β’β’β’β’" entry_padding_pips = input.float(2.0, "Entry Zone Padding (Pips)", minval=0.0, tooltip="Expands the entry zone to catch price turning just before the level.", group=GRP_STRAT) use_zone_integrity = input.bool(true, "Use Zone Integrity Filter", tooltip="If enabled, ignores trades where the signal candle closes BEYOND the HARD level (Body Break).", group=GRP_STRAT) show_mitigation_lines = input.bool(true, "Show Active Mitigation Zones", group=GRP_STRAT) // ========== MULTI-WEBHOOK ALERT SYSTEM ========== var GRP_ALERT_SYSTEM = "β’β’β’β’β’β’β’β’ Multi-Webhook Alert System β’β’β’β’β’β’β’β’" range_width_dollars = input.float(5.0, "Entry Fill Zone Width ($)", minval=0.1, group=GRP_ALERT_SYSTEM) entry_buffer_pips = input.float(2.0, "Entry Buffer (Pips)", minval=0.0, group=GRP_ALERT_SYSTEM) sl_offset_pips = input.float(5.0, "SL Offset (Pips)", minval=0.0, group=GRP_ALERT_SYSTEM) send_signal_with_detail = input.bool(true, "π§ SEND REAL VALUES (OFF=Send Zeros)", group=GRP_ALERT_SYSTEM) show_popup_alerts = input.bool(false, "Show Popup Alerts", group=GRP_ALERT_SYSTEM) alert_on_grid = input.bool(true, "Alert on Retracement", group=GRP_ALERT_SYSTEM) // ========== MULTI-WEBHOOK CONFIGURATION (Max 10) ========== var GRP_WEBHOOKS = "π Multi-Webhook Configuration (Max 10)" webhook1_enabled = input.bool(true, "β Webhook 1 - Enable", group=GRP_WEBHOOKS) webhook1_url = input.string("https://aaron-sedimentologic-mikaela.ngrok-free.dev/pushSignal", "Webhook 1 - URL", group=GRP_WEBHOOKS) webhook1_key = input.string("RUNPRODD01", "Webhook 1 - SENDER_ID", group=GRP_WEBHOOKS) webhook2_enabled = input.bool(false, "β Webhook 2 - Enable", group=GRP_WEBHOOKS) webhook2_url = input.string("", "Webhook 2 - URL", group=GRP_WEBHOOKS) webhook2_key = input.string("", "Webhook 2 - SENDER_ID", group=GRP_WEBHOOKS) webhook3_enabled = input.bool(false, "β Webhook 3 - Enable", group=GRP_WEBHOOKS) webhook3_url = input.string("", "Webhook 3 - URL", group=GRP_WEBHOOKS) webhook3_key = input.string("", "Webhook 3 - SENDER_ID", group=GRP_WEBHOOKS) webhook4_enabled = input.bool(false, "β Webhook 4 - Enable", group=GRP_WEBHOOKS) webhook4_url = input.string("", "Webhook 4 - URL", group=GRP_WEBHOOKS) webhook4_key = input.string("", "Webhook 4 - SENDER_ID", group=GRP_WEBHOOKS) webhook5_enabled = input.bool(false, "β Webhook 5 - Enable", group=GRP_WEBHOOKS) webhook5_url = input.string("", "Webhook 5 - URL", group=GRP_WEBHOOKS) webhook5_key = input.string("", "Webhook 5 - SENDER_ID", group=GRP_WEBHOOKS) webhook6_enabled = input.bool(false, "β Webhook 6 - Enable", group=GRP_WEBHOOKS) webhook6_url = input.string("", "Webhook 6 - URL", group=GRP_WEBHOOKS) webhook6_key = input.string("", "Webhook 6 - SENDER_ID", group=GRP_WEBHOOKS) webhook7_enabled = input.bool(false, "β Webhook 7 - Enable", group=GRP_WEBHOOKS) webhook7_url = input.string("", "Webhook 7 - URL", group=GRP_WEBHOOKS) webhook7_key = input.string("", "Webhook 7 - SENDER_ID", group=GRP_WEBHOOKS) webhook8_enabled = input.bool(false, "β Webhook 8 - Enable", group=GRP_WEBHOOKS) webhook8_url = input.string("", "Webhook 8 - URL", group=GRP_WEBHOOKS) webhook8_key = input.string("", "Webhook 8 - SENDER_ID", group=GRP_WEBHOOKS) webhook9_enabled = input.bool(false, "β Webhook 9 - Enable", group=GRP_WEBHOOKS) webhook9_url = input.string("", "Webhook 9 - URL", group=GRP_WEBHOOKS) webhook9_key = input.string("", "Webhook 9 - SENDER_ID", group=GRP_WEBHOOKS) webhook10_enabled = input.bool(false, "β Webhook 10 - Enable", group=GRP_WEBHOOKS) webhook10_url = input.string("", "Webhook 10 - URL", group=GRP_WEBHOOKS) webhook10_key = input.string("", "Webhook 10 - SENDER_ID", group=GRP_WEBHOOKS) var GRP_TEST = "π§ Test & Debug" test_webhook_now = input.bool(false, "π SEND TEST ALERT NOW", group=GRP_TEST, tooltip="Toggle ON then OFF to send test webhook") debug_mode = input.bool(true, "Enable Debug Panel", group=GRP_TEST) show_alert_log = input.bool(true, "Show Alert History", group=GRP_TEST) // ========== RISK MANAGEMENT ========== var GRP_RISK_MANAGEMENT = "β’β’β’β’β’β’β’β’ Risk Management β’β’β’β’β’β’β’β’" max_risk_percent = input.float(2.0, "Max Risk %", minval=0.1, maxval=5.0, group=GRP_RISK_MANAGEMENT) min_rr_ratio = input.float(1.5, "Min Risk/Reward", minval=1.0, maxval=10.0, group=GRP_RISK_MANAGEMENT) var GRP_OTHER_STRUCTURE = "β’β’β’β’β’β’β’β’ Other Structure Settings β’β’β’β’β’β’β’β’" max_historical_boxes = input.int(10, "Max Historical Markers", minval=1, maxval=100, group=GRP_OTHER_STRUCTURE) structure_show_table = input.bool(true, "Table", inline="1", group=GRP_OTHER_STRUCTURE) structure_table_vertical = input.string("bottom", "β", inline = "2", group = GRP_OTHER_STRUCTURE, options = ["top", "middle", "bottom"]) structure_table_horizontal = input.string("right", "β", inline = "2", group = GRP_OTHER_STRUCTURE, options = ["left", "center", "right"]) info_panel_position = input.string("top_center", "Info Panel Position", options=["top_left", "top_center", "top_right", "middle_left", "middle_center", "middle_right", "bottom_left", "bottom_center", "bottom_right"], group=GRP_OTHER_STRUCTURE) indicator_start_time = input.time(timestamp("02 Jan 2015 00:00 +0300"), title="Indicator Start Date", group = GRP_OTHER_STRUCTURE) // --- CONSTANTS --- TRANSPARENT = color.new(color.white, 100) LABEL_SPACE = " " MIN = -9999999999999999999.0 MAX = 9999999999999999999.0 VERSION_NUMBER = "1.8 (VERTICAL MARKERS)" // Maintain array of time values for all bars. var array<int> timesArray = array.new<int>() array.push(timesArray, time) string currentChartTimeframe = timeframe.period string indicatorTimeframe = tf1_timeframe == "" or tf1_timeframe == currentChartTimeframe ? currentChartTimeframe : tf1_timeframe bool isCorrectTimeframe = true // Alert tracking var array<string> alert_history = array.new_string(0) var array<int> alert_times = array.new_int(0) var bool lastBullishAlert = false var bool lastBearishAlert = false var int lastAlertTime = 0 var int lastWebhookTime = 0 var bool shouldTriggerBuyAlert = false var bool shouldTriggerSellAlert = false var string lastAlertSymbol = "" var string lastAlertAction = "" // MOMENTUM VARIABLES bool tf1_bos_bullish = false bool tf1_bos_bearish = false // ALERT VARIABLES var float tf1_entryPrice = na var float tf1_slPrice = na var float tf1_lastAlertPrice = na var float tf1_rangeHigh = na var float tf1_rangeLow = na var string tf1_lastAlertDirection = "" var bool is_news_period = false var bool last_test_state = false var array<string> enabled_webhook_urls = array.new_string(0) var array<string> enabled_webhook_keys = array.new_string(0) // --- GLOBAL ARRAYS FOR HISTORICAL MARKERS (LINES) --- // Changed from Box arrays to Line arrays to support vertical lines var array<line> tf1_historical_lines = array.new_line(0) // Helper for cleaning up old lines clean_old_lines() => // We multiply max_historical_boxes by 2 because each trade draws 2 lines (Vertical + Horizontal Dash) int max_lines = max_historical_boxes * 2 if array.size(tf1_historical_lines) > max_lines int num_to_delete = array.size(tf1_historical_lines) - max_lines for i = 0 to num_to_delete - 1 line l = array.pop(tf1_historical_lines) line.delete(l) // --- HELPERS AND FUNCTIONS --- get_sym_pip_size() => float _pip = 0.1 if syminfo.type == "forex" and str.contains(syminfo.ticker, "JPY") _pip := 0.001 else if syminfo.type == "forex" _pip := 0.00001 if syminfo.mintick < 0.0001 _pip := syminfo.mintick _pip check_duplicate_alert(string symbol, string direction, float price_level, int current_time) => string price_key = str.tostring(math.round(price_level)) key = symbol + "_" + direction + "_" + price_key + "_" + str.tostring(time) is_duplicate = false if array.size(alert_history) > 0 for i = array.size(alert_history) - 1 to 0 if current_time - array.get(alert_times, i) > 30000 array.remove(alert_history, i) array.remove(alert_times, i) if array.includes(alert_history, key) is_duplicate := true else array.push(alert_history, key) array.push(alert_times, current_time) is_duplicate isNeutral(i=0) => open[i] == close[i] isBearish(i=0) => _n = isNeutral(i) _temp = _n ? close[i+1] < open[i+1] : close[i] < open[i] _temp isBullish(i=0) => _n = isNeutral(i) _temp = _n ? close[i+1] > open[i+1] : close[i] > open[i] _temp getLineStyle(_style) => _style == "Solid" ? line.style_solid : _style == "Dashed" ? line.style_dashed : line.style_dotted getlabelSize(_labelSize) => _labelSize == "auto" ? size.auto : _labelSize == "Tiny" ? size.tiny : _labelSize == "Small" ? size.small : _labelSize == "Normal" ? size.normal : size.huge getTextSize(_textSize) => _textSize == "tiny" ? size.tiny : _textSize == "small" ? size.small : _textSize == "normal" ? size.normal : _textSize == "large" ? size.large : size.huge getTextHAlign(_align) => _align == "left" ? text.align_left : _align == "center" ? text.align_center : text.align_right getTextVAlign(_align) => _align == "top" ? text.align_top : _align == "middle" ? text.align_center : text.align_bottom addToArray(_array, _val) => array.unshift(_array, _val) removeFromArray(_array, _index) => array.remove(_array, _index) updateArrayElement(_array, _index, _val) => array.set(_array, _index, _val) getLastElementInArray(_arr) => _size = array.size(_arr) _el = _size > 0 ? array.get(_arr, _size-1) : na _el _get(_array, _i=0) => array.size(_array) > _i ? array.get(_array, _i) : na get5ArrayValues(_array) => _0 = array.size(_array) > 0 ? array.get(_array, 0) : na _1 = array.size(_array) > 1 ? array.get(_array, 1) : na _2 = array.size(_array) > 2 ? array.get(_array, 2) : na _3 = array.size(_array) > 3 ? array.get(_array, 3) : na _4 = array.size(_array) > 4 ? array.get(_array, 4) : na [_0, _1, _2, _3, _4] _bottom(_id) => box.get_bottom(_id) _top(_id) => box.get_top(_id) _left(_id) => box.get_left(_id) _right(_id) => box.get_right(_id) isRegularFractal(mode, n) => mode == 'Buy' ? high[n - 1] < high[n] and high[n + 1] < high[n] : mode == 'Sell' ? low[n - 1] > low[n] and low[n + 1] > low[n] : false isBWFractal(mode, n) => mode == 'Buy' ? high[n - 2] < high[n] and high[n - 1] < high[n] and high[n + 1] < high[n] and high[n + 2] < high[n] : mode == 'Sell' ? low[n - 2] > low[n] and low[n - 1] > low[n] and low[n + 1] > low[n] and low[n + 2] > low[n] : false isFractalHigh(i, _filter) => _filter == '3' ? isRegularFractal('Buy', i) : isBWFractal('Buy', i + 1) isFractalLow(i, _filter) => _filter == '3' ? isRegularFractal('Sell', i) : isBWFractal('Sell', i + 1) delete_label(_l) => if not na(_l) label.delete(_l) delete_line(_l) => if not na(_l) line.delete(_l) delete_box(_l) => if not na(_l) box.delete(_l) reso(exp, res) => request.security(syminfo.tickerid, res, exp, lookahead=barmerge.lookahead_on) resolutionInMinutes(tf = "") => chartTf = timeframe.multiplier '' (timeframe.isseconds ? 1. / 60 : timeframe.isminutes ? 1. : timeframe.isdaily ? 60. '' 24 : timeframe.isweekly ? 60. '' 24 '' 7 : timeframe.ismonthly ? 60. '' 24 '' 30.4375 : na) float result = tf == "" ? chartTf : request.security(syminfo.tickerid, tf, chartTf) f_timeFrom(length, _tf = timeframe.period) => int _timeFrom = na _timeFrom := int(time + resolutionInMinutes(_tf) '' 60 '' 1000 * length) _timeFrom isHigherTimeframe(tf, eq = false) => eq ? resolutionInMinutes() >= resolutionInMinutes(tf) : resolutionInMinutes() > resolutionInMinutes(tf) isLowerTimeframe(tf, eq = false) => eq ? resolutionInMinutes() <= resolutionInMinutes(tf) : resolutionInMinutes() < resolutionInMinutes(tf) timeToBarIndex(_from) => __cond = math.round((time - _from) / (1000 * timeframe.in_seconds(timeframe.period))) _cond = __cond <= 5000 ? math.abs(math.round(__cond)) : 5000 _cond barIndexAtTime(_arr, series int timeToFind) => int barOfTime = array.indexof(_arr, timeToFind) int _result = na if barOfTime == -1 _timetobars = timeToBarIndex(timeToFind) _result := _timetobars else _result := bar_index - barOfTime result = _result <= 5000 ? math.abs(math.round(_result)) : 5000 result findHtfTimeInLtf(_src, _pivotPrice, _maxBack) => int _time = na int _bar_index = na float _delta = 10e10 if not na(_pivotPrice) for _i = _maxBack to 0 _thisDelta = _src == "high" ? math.abs(high[_i] - _pivotPrice) : math.abs(low[_i] - _pivotPrice) if _thisDelta < _delta _delta := _thisDelta _time := time[_i] _bar_index := bar_index[_i] [_time, _bar_index] getExactTime(_time, _price, _timeframe, _direction) => _pivotTime = _time if isLowerTimeframe(_timeframe) _barsback = barIndexAtTime(timesArray, _time) [__hTime, __hBi] = findHtfTimeInLtf(_direction, _price, _barsback) _pivotTime := __hTime _pivotTime findHighestBetweenTimes(_time1, _time2, _defaultH) => _highest = _defaultH _highestTime = _time1 sBi0 = barIndexAtTime(timesArray, _time1) sBi1 = barIndexAtTime(timesArray, _time2) if _time1 > _time2 _startFrom = isBullish(sBi1) ? sBi1 : sBi1-1 _endTo = isBearish(sBi0) ? sBi0 : sBi0+1 for i = _startFrom to _endTo if high[i] > _highest _highest := high[i] _highestTime := time[i] [_highest, _highestTime] findLowestBetweenTimes(_time1, _time2, _defaultL) => _lowest = _defaultL _lowestTime = _time1 sBi0 = barIndexAtTime(timesArray, _time1) sBi1 = barIndexAtTime(timesArray, _time2) if _time1 > _time2 _startFrom = isBearish(sBi1) ? sBi1 : sBi1-1 _endTo = isBullish(sBi0) ? sBi0 : sBi0+1 for i = _startFrom to _endTo if low[i] < _lowest _lowest := low[i] _lowestTime := time[i] [_lowest, _lowestTime] get_pivot_ohlc(i=0) => [open, high, low, close, time, open[1], high[1], low[1], close[1], time[1], open[2], high[2], low[2], close[2], time[2]] get_phpl(countSinceBullCandle, countSinceBearCandle) => _highest = countSinceBullCandle >= 0 ? ta.highest(countSinceBullCandle + 1) : -1 _highestBi = ta.valuewhen(high == _highest, bar_index, 0) _highestTime = ta.valuewhen(high == _highest, time, 0) _lowest = countSinceBearCandle >= 0 ? ta.lowest(countSinceBearCandle + 1) : -1 _lowestBi = ta.valuewhen(low == _lowest, bar_index, 0) _lowestTime = ta.valuewhen(low == _lowest, time, 0) [_highest, _highestTime, _lowest, _lowestTime] getPhlData(_t, _offset) => h = reso(high[_offset], _t) l = reso(low[_offset], _t) _time = time(_t) newbar = na(_time[1]) or _time > _time[1] [h, l, newbar, _time] _TimeTo = f_timeFrom(7) // ========== ALERT FUNCTIONS ========== format_symbol(string symbol) => base_symbol = str.upper(str.replace(symbol, " ", "")) if str.contains(base_symbol, "ETH") base_symbol := "ETHUSD" if str.contains(base_symbol, "BTC") and not str.contains(base_symbol, "USD") base_symbol := "BTCUSD" if str.contains(base_symbol, "XAU") and not str.contains(base_symbol, "USD") base_symbol := "XAUUSD" base_symbol // UPDATED: Now supports start/end range separation + fixed 0,0 TPs format_signal_message(string symbol, string action, float start_price, float end_price, float sl_price) => formatted_symbol = format_symbol(symbol) formatted_start = str.tostring(start_price, "#.#####") formatted_end = str.tostring(end_price, "#.#####") formatted_sl = str.tostring(sl_price, "#.#####") // FORMAT: SYMBOL, DIRECTION, START, END, SL, TP1, TP2 // TP1 and TP2 are strictly 0.00 as requested formatted_symbol + "," + action + "," + formatted_start + "," + formatted_end + "," + formatted_sl + ",0.00,0.00" create_webhook_payload(string sender_id, string signal_message) => "{\"key\":\"" + sender_id + "\",\"signal\":\"" + signal_message + "\",\"timestamp\":\"" + str.tostring(timenow) + "\"}" validate_webhook_json(string json) => bool valid = true valid := str.contains(json, '{"key":"') valid := valid and str.contains(json, '","signal":"') valid := valid and str.contains(json, '","timestamp":"') valid validate_sender_id(string sender_id) => bool valid = true valid := str.length(sender_id) > 0 and str.length(sender_id) <= 20 valid := valid and not str.contains(sender_id, " ") valid := valid and not str.contains(sender_id, ",") valid := valid and not str.contains(sender_id, "\n") valid := valid and not str.contains(sender_id, '"') valid validate_signal_format(string signal) => parts = str.split(signal, ",") int part_count = array.size(parts) bool valid = part_count == 7 // Must be exactly 7 for new format if part_count >= 2 action = array.get(parts, 1) valid := valid and (action == "BUY" or action == "SELL" or action == "TEST") else valid := false valid // UPDATED PREPARE FUNCTION: USES MARKET ENTRY + STRUCTURAL SL prepare_alert_data(string symbol, string action, float entry_ref_price, float extreme_price) => float top_range = na float bottom_range = na float sl_price = na string signal_message = "" float _dynamic_pip = get_sym_pip_size() float _sl_offset = sl_offset_pips * _dynamic_pip if not send_signal_with_detail signal_message := format_symbol(symbol) + "," + action + ",0,0,0,0,0" top_range := 0.0 bottom_range := 0.0 sl_price := 0.0 else // RETRACEMENT ENTRY LOGIC (STOP ORDER) if action == "BUY" // Entry: STOP Price (High of Signal Bar) bottom_range := entry_ref_price // Range Limit: Entry + Width (Visualizing Fill Zone) top_range := bottom_range + range_width_dollars // SL: At Structural Low (Extreme) - Offset sl_price := extreme_price - _sl_offset else if action == "SELL" // Entry: STOP Price (Low of Signal Bar) bottom_range := entry_ref_price // Range Limit: Entry - Width top_range := bottom_range - range_width_dollars // SL: At Structural High (Extreme) + Offset sl_price := extreme_price + _sl_offset if na(bottom_range) or na(top_range) bottom_range := 0.0 top_range := 0.0 sl_price := 0.0 signal_message := format_symbol(symbol) + "," + action + ",0,0,0,0,0" else // Format: SYMBOL, DIR, START(Trigger), END(Zone Limit), SL, TP1, TP2 signal_message := format_signal_message(symbol, action, bottom_range, top_range, sl_price) [signal_message, top_range, bottom_range, sl_price] get_enabled_webhooks() => array.clear(enabled_webhook_urls) array.clear(enabled_webhook_keys) if webhook1_enabled and webhook1_url != "" and webhook1_key != "" if validate_sender_id(webhook1_key) array.push(enabled_webhook_urls, webhook1_url) array.push(enabled_webhook_keys, webhook1_key) if webhook2_enabled and webhook2_url != "" and webhook2_key != "" if validate_sender_id(webhook2_key) array.push(enabled_webhook_urls, webhook2_url) array.push(enabled_webhook_keys, webhook2_key) if webhook3_enabled and webhook3_url != "" and webhook3_key != "" if validate_sender_id(webhook3_key) array.push(enabled_webhook_urls, webhook3_url) array.push(enabled_webhook_keys, webhook3_key) if webhook4_enabled and webhook4_url != "" and webhook4_key != "" if validate_sender_id(webhook4_key) array.push(enabled_webhook_urls, webhook4_url) array.push(enabled_webhook_keys, webhook4_key) if webhook5_enabled and webhook5_url != "" and webhook5_key != "" if validate_sender_id(webhook5_key) array.push(enabled_webhook_urls, webhook5_url) array.push(enabled_webhook_keys, webhook5_key) if webhook6_enabled and webhook6_url != "" and webhook6_key != "" if validate_sender_id(webhook6_key) array.push(enabled_webhook_urls, webhook6_url) array.push(enabled_webhook_keys, webhook6_key) if webhook7_enabled and webhook7_url != "" and webhook7_key != "" if validate_sender_id(webhook7_key) array.push(enabled_webhook_urls, webhook7_url) array.push(enabled_webhook_keys, webhook7_key) if webhook8_enabled and webhook8_url != "" and webhook8_key != "" if validate_sender_id(webhook8_key) array.push(enabled_webhook_urls, webhook8_url) array.push(enabled_webhook_keys, webhook8_key) if webhook9_enabled and webhook9_url != "" and webhook9_key != "" if validate_sender_id(webhook9_key) array.push(enabled_webhook_urls, webhook9_url) array.push(enabled_webhook_keys, webhook9_key) if webhook10_enabled and webhook10_url != "" and webhook10_key != "" if validate_sender_id(webhook10_key) array.push(enabled_webhook_urls, webhook10_url) array.push(enabled_webhook_keys, webhook10_key) [array.size(enabled_webhook_urls), enabled_webhook_urls, enabled_webhook_keys] // ROBUST MULTI-WEBHOOK SENDING send_to_all_webhooks(string signal_message) => [webhook_count, urls, keys] = get_enabled_webhooks() if webhook_count > 0 for i = 0 to webhook_count - 1 string current_url = array.get(urls, i) string current_key = array.get(keys, i) // Only proceed if data is present if not na(current_url) and not na(current_key) and current_url != "" string json_payload = create_webhook_payload(current_key, signal_message) // Alert execution alert(json_payload, freq=alert.freq_once_per_bar_close) // --- HELPER FOR HISTORICAL MARKERS (VERTICAL LINES) --- // Note: Arrays defined at Global Scope now (Lines 185) // Helper to draw the Vertical Range Line draw_historical_marker(bool isBull, float startPrice, float width, int t1) => float endPrice = isBull ? startPrice + width : startPrice - width color lineColor = isBull ? color.green : color.red // Draw thick Vertical Line at Signal Candle line newLine = line.new(bar_index, startPrice, bar_index, endPrice, xloc=xloc.bar_index, width=4, color=lineColor) // Draw small Horizontal Dash at Entry Price line entryDash = line.new(bar_index, startPrice, bar_index+1, startPrice, xloc=xloc.bar_index, width=1, color=lineColor) // Store in array array.unshift(tf1_historical_lines, newLine) array.unshift(tf1_historical_lines, entryDash) clean_old_lines() // --------------- MAIN LOGIC --------------- [tf1_open, tf1_high, tf1_low, tf1_close, tf1_time, tf1_open1, tf1_high1, tf1_low1, tf1_close1, tf1_time1, tf1_open2, tf1_high2, tf1_low2, tf1_close2, tf1_time2] = request.security(syminfo.tickerid, tf1_timeframe, get_pivot_ohlc(), lookahead=barmerge.lookahead_on) isUseTimeframe1 = not isHigherTimeframe(tf1_timeframe) and isHigherTimeframe(tf1_min, true) and tf1_useStructure and time > indicator_start_time var tf1_lastBullCandle = false var tf1_lastBearCandle = false if tf1_close1 > tf1_open1 tf1_lastBullCandle := true tf1_lastBearCandle := false if tf1_close1 < tf1_open1 tf1_lastBullCandle := false tf1_lastBearCandle := true _tf1_countBull = ta.barssince(tf1_lastBullCandle) tf1_countSinceBullCandle = request.security(syminfo.tickerid, tf1_timeframe, _tf1_countBull, lookahead = barmerge.lookahead_on) _tf1_countBear = ta.barssince(tf1_lastBearCandle) tf1_countSinceBearCandle = request.security(syminfo.tickerid, tf1_timeframe, _tf1_countBear, lookahead = barmerge.lookahead_on) tf1_newbar = ta.change(time(tf1_timeframe)) > 0 var tf1_pivotHighs = array.new_float(5, MIN) var tf1_pivotHighsTime = array.new_int(5) var tf1_pivotLows = array.new_float(5, MAX) var tf1_pivotLowsTime = array.new_int(5) var label tf1_pivotHighLabel = na var label tf1_pivotLowLabel = na var label tf1_pivotHighHhllLabel = na var label tf1_pivotLowHhllLabel = na tf1_isStructureHigh = false tf1_isStructureLow = false tf1_canPlot = tf1_newbar and isUseTimeframe1 var tf1_mostRecentBullCount1 = time var tf1_mostRecentBearCount1 = time var tf1_initialised = false if tf1_canPlot and not tf1_initialised addToArray(tf1_pivotHighsTime, tf1_time) addToArray(tf1_pivotHighs, tf1_high) addToArray(tf1_pivotLowsTime, tf1_time) addToArray(tf1_pivotLows, tf1_low) tf1_initialised := true if tf1_canPlot // --- STRUCTURE HIGH --- if tf1_countSinceBullCandle >= 1 __time = tf1_close1 > tf1_open1 ? tf1_time1 : tf1_time [tf1_highest, tf1_highestTime] = findHighestBetweenTimes(__time, _get(tf1_pivotHighsTime), MIN) if tf1_countSinceBullCandle == 1 tf1_mostRecentBullCount1 := __time if tf1_highest > _get(tf1_pivotHighs) if (tf1_countSinceBullCandle == 1 and tf1_close1 != tf1_open1) or (tf1_countSinceBullCandle > 1 and tf1_highestTime >= tf1_mostRecentBullCount1 and tf1_close < tf1_open) tf1_isStructureHigh := true addToArray(tf1_pivotHighsTime, tf1_highestTime) addToArray(tf1_pivotHighs, tf1_highest) tf1_pivotHighLabel := label.new(tf1_highestTime, tf1_highest, xloc=xloc.bar_time, style=label.style_circle, size=getlabelSize(tf1_structurelabelSize), color=tf1_structureTopColor) if tf1_showHhll tf1_pivotHighHhllLabel := label.new(tf1_highestTime, tf1_highest, xloc=xloc.bar_time, yloc=yloc.abovebar, text="HH", style=label.style_none, size=getlabelSize(tf1_hhllLabelSize), textcolor=tf1_hhllBullColor) [tf1_lowest, tf1_lowestTime] = findLowestBetweenTimes(_get(tf1_pivotHighsTime), _get(tf1_pivotHighsTime, 1), MAX) if tf1_lowestTime != _get(tf1_pivotLowsTime) addToArray(tf1_pivotLowsTime, tf1_lowestTime) addToArray(tf1_pivotLows, tf1_lowest) tf1_pivotLowLabel := label.new(tf1_lowestTime, tf1_lowest, xloc=xloc.bar_time, style=label.style_circle, size=getlabelSize(tf1_structurelabelSize), color=tf1_structureBottomColor) if tf1_showHhll tf1_pivotLowHhllLabel := label.new(tf1_lowestTime, tf1_lowest, xloc=xloc.bar_time, yloc=yloc.belowbar, text="HL", style=label.style_none, size=getlabelSize(tf1_hhllLabelSize), textcolor=tf1_hhllBullColor) else if tf1_countSinceBullCandle > 1 and _get(tf1_pivotHighsTime) >= tf1_mostRecentBullCount1 and tf1_close < tf1_open updateArrayElement(tf1_pivotHighsTime, 0, tf1_highestTime) updateArrayElement(tf1_pivotHighs, 0, tf1_highest) label.delete(tf1_pivotHighLabel[0]) tf1_pivotHighLabel := label.new(tf1_highestTime, tf1_highest, xloc=xloc.bar_time, style=label.style_circle, size=getlabelSize(tf1_structurelabelSize), color=tf1_structureTopColor) if tf1_showHhll label.delete(tf1_pivotHighHhllLabel[0]) tf1_pivotHighHhllLabel := label.new(tf1_highestTime, tf1_highest, xloc=xloc.bar_time, yloc=yloc.abovebar, text="HH", style=label.style_none, size=getlabelSize(tf1_hhllLabelSize), textcolor=tf1_hhllBullColor) // --- STRUCTURE LOW --- if tf1_countSinceBearCandle >= 1 __time = tf1_close1 < tf1_open1 ? tf1_time1 : tf1_time [tf1_lowest, tf1_lowestTime] = findLowestBetweenTimes(__time, _get(tf1_pivotLowsTime), MAX) if tf1_countSinceBearCandle == 1 tf1_mostRecentBearCount1 := __time if tf1_lowest < _get(tf1_pivotLows) if (tf1_countSinceBearCandle == 1 and tf1_close1 != tf1_open1) or (tf1_countSinceBearCandle > 1 and tf1_lowestTime >= tf1_mostRecentBearCount1 and tf1_close > tf1_open) tf1_isStructureLow := true addToArray(tf1_pivotLowsTime, tf1_lowestTime) addToArray(tf1_pivotLows, tf1_lowest) tf1_pivotLowLabel := label.new(tf1_lowestTime, tf1_lowest, xloc=xloc.bar_time, style=label.style_circle, size=getlabelSize(tf1_structurelabelSize), color=tf1_structureBottomColor) if tf1_showHhll tf1_pivotLowHhllLabel := label.new(tf1_lowestTime, tf1_lowest, xloc=xloc.bar_time, yloc=yloc.belowbar, text="LL", style=label.style_none, size=getlabelSize(tf1_hhllLabelSize), textcolor=tf1_hhllBearColor) [tf1_highest, tf1_highestTime] = findHighestBetweenTimes(_get(tf1_pivotLowsTime), _get(tf1_pivotLowsTime, 1), MIN) if tf1_highestTime != _get(tf1_pivotHighsTime) addToArray(tf1_pivotHighsTime, tf1_highestTime) addToArray(tf1_pivotHighs, tf1_highest) tf1_pivotHighLabel := label.new(tf1_highestTime, tf1_highest, xloc=xloc.bar_time, style=label.style_circle, size=getlabelSize(tf1_structurelabelSize), color=tf1_structureTopColor) if tf1_showHhll tf1_pivotHighHhllLabel := label.new(tf1_highestTime, tf1_highest, xloc=xloc.bar_time, yloc=yloc.abovebar, text="LH", style=label.style_none, size=getlabelSize(tf1_hhllLabelSize), textcolor=tf1_hhllBearColor) else if tf1_countSinceBearCandle > 1 and _get(tf1_pivotLowsTime) >= tf1_mostRecentBearCount1 and tf1_close > tf1_open updateArrayElement(tf1_pivotLowsTime, 0, tf1_lowestTime) updateArrayElement(tf1_pivotLows, 0, tf1_lowest) label.delete(tf1_pivotLowLabel[0]) tf1_pivotLowLabel := label.new(tf1_lowestTime, tf1_lowest, xloc=xloc.bar_time, style=label.style_circle, size=getlabelSize(tf1_structurelabelSize), color=tf1_structureBottomColor) if tf1_showHhll label.delete(tf1_pivotLowHhllLabel[0]) tf1_pivotLowHhllLabel := label.new(tf1_lowestTime, tf1_lowest, xloc=xloc.bar_time, yloc=yloc.belowbar, text="LL", style=label.style_none, size=getlabelSize(tf1_hhllLabelSize), textcolor=tf1_hhllBearColor) [tf1_ph0, tf1_ph1, tf1_ph2, tf1_ph3, tf1_ph4] = get5ArrayValues(tf1_pivotHighs) [tf1_pl0, tf1_pl1, tf1_pl2, tf1_pl3, tf1_pl4] = get5ArrayValues(tf1_pivotLows) [tf1_ph0Time, tf1_ph1Time, tf1_ph2Time, tf1_ph3Time, tf1_ph4Time] = get5ArrayValues(tf1_pivotHighsTime) [tf1_pl0Time, tf1_pl1Time, tf1_pl2Time, tf1_pl3Time, tf1_pl4Time] = get5ArrayValues(tf1_pivotLowsTime) var tf1_isPriceEfficient = false var tf1_structureDirection = "bullish" var tf1_isMSU = false bool tf1_isBullishMsu = false bool tf1_isBearishMsu = false bool tf1_isBullishVta = false bool tf1_isBearishVta = false var float tf1_bottomTlqPrice = na var float tf1_topTlqPrice = na tf1_isValidHH = tf1_structureDirection == "bullish" ? tf1_isStructureHigh and tf1_ph0 > tf1_ph1 and tf1_ph0 > tf1_ph2 : tf1_isStructureHigh and tf1_ph0 > nz(tf1_topTlqPrice) tf1_isValidLL = tf1_structureDirection == "bearish" ? tf1_isStructureLow and tf1_pl0 < tf1_pl1 and tf1_pl0 < tf1_pl2 : tf1_isStructureLow and tf1_pl0 < nz(tf1_bottomTlqPrice) // --------------- ILQ --------------- var float tf1_bottomIlqPrice = na var float tf1_topIlqPrice = na var line tf1_bottomIlqLine = na var line tf1_topIlqLine = na var label tf1_bottomIlqLabel = na var label tf1_topIlqLabel = na if tf1_showIlq and tf1_canPlot if tf1_isValidHH or tf1_isValidLL delete_line(tf1_bottomIlqLine) delete_line(tf1_topIlqLine) delete_label(tf1_bottomIlqLabel) delete_label(tf1_topIlqLabel) if tf1_isValidHH tf1_bottomIlqPrice := tf1_pl0 tf1_topIlqPrice := na tf1_bottomIlqLine := line.new(tf1_pl0Time, tf1_pl0, _TimeTo, tf1_pl0, xloc=xloc.bar_time, color=tf1_ilqCol, style=getLineStyle(tf1_ilqStyle), width=tf1_ilqWidth) tf1_bottomIlqLabel := label.new(_TimeTo, tf1_pl0, tf1_ilqText + LABEL_SPACE, xloc=xloc.bar_time, style=label.style_none, size=getlabelSize("Normal"), textcolor=tf1_ilqCol) if tf1_isValidLL tf1_topIlqPrice := tf1_ph0 tf1_bottomIlqPrice := na tf1_topIlqLine := line.new(tf1_ph0Time, tf1_ph0, _TimeTo, tf1_ph0, xloc=xloc.bar_time, color=tf1_ilqCol, style=getLineStyle(tf1_ilqStyle), width=tf1_ilqWidth) tf1_topIlqLabel := label.new(_TimeTo, tf1_ph0, tf1_ilqText + LABEL_SPACE, xloc=xloc.bar_time, style=label.style_none, size=getlabelSize("Normal"), textcolor=tf1_ilqCol) if not na(tf1_bottomIlqLine) line.set_x2(tf1_bottomIlqLine, _TimeTo) if not na(tf1_bottomIlqLabel) label.set_x(tf1_bottomIlqLabel, _TimeTo) if not na(tf1_bottomIlqLine) and tf1_low < tf1_bottomIlqPrice line.delete(tf1_bottomIlqLine) if not na(tf1_bottomIlqLabel) label.delete(tf1_bottomIlqLabel) if not na(tf1_topIlqLine) line.set_x2(tf1_topIlqLine, _TimeTo) if not na(tf1_topIlqLabel) label.set_x(tf1_topIlqLabel, _TimeTo) if not na(tf1_topIlqLine) and tf1_high > tf1_topIlqPrice line.delete(tf1_topIlqLine) if not na(tf1_topIlqLabel) label.delete(tf1_topIlqLabel) // ================================================================= // π DYNAMIC STATE VARIABLES FOR RETRACEMENT (Moved to Global Scope) // ================================================================= var float active_mitigation_level = na var string active_mitigation_type = na var box active_mitigation_box = na // --------------- TLQ --------------- var line tf1_bottomTlqLine = na var line tf1_topTlqLine = na var label tf1_bottomTlqLabel = na var label tf1_topTlqLabel = na var ex_usedBosTimes = array.new_int(0) // Helper for Padding Logic float _pad_val = entry_padding_pips * get_sym_pip_size() if tf1_showTlq if not na(tf1_bottomTlqLine) and ((low < tf1_bottomTlqPrice) or (tf1_isValidHH[1] and low[1] < tf1_bottomTlqPrice) or (low[2] < tf1_pl1 and low[2] < tf1_pl2 and low[2] < tf1_bottomTlqPrice)) and not array.includes(ex_usedBosTimes, line.get_x1(tf1_bottomTlqLine)) tf1_structureDirection := "bearish" tf1_bottomTlqPrice := na addToArray(ex_usedBosTimes, line.get_x1(tf1_bottomTlqLine)) tf1_bos_bearish := true tf1_bos_bullish := false if tf1_showBos line.new(line.get_x1(tf1_bottomTlqLine), line.get_y1(tf1_bottomTlqLine), time, line.get_y1(tf1_bottomTlqLine), xloc=xloc.bar_time, color=color.red) label.new(time, line.get_y1(tf1_bottomTlqLine), "BOS" + LABEL_SPACE, xloc=xloc.bar_time, style=label.style_none, size=getlabelSize("Normal"), textcolor=color.red) line.delete(tf1_bottomTlqLine) if not na(tf1_bottomTlqLabel) label.delete(tf1_bottomTlqLabel) if not na(tf1_topTlqLine) and ((high > tf1_topTlqPrice) or (tf1_isValidLL[1] and high > tf1_topTlqPrice) or (high[2] > tf1_ph1 and high[2] > tf1_ph2 and high[2] > tf1_topTlqPrice)) and not array.includes(ex_usedBosTimes, line.get_x1(tf1_bottomTlqLine)) tf1_structureDirection := "bullish" tf1_topTlqPrice := na addToArray(ex_usedBosTimes, line.get_x1(tf1_topTlqLine)) tf1_bos_bullish := true tf1_bos_bearish := false if tf1_showBos line.new(line.get_x1(tf1_topTlqLine), line.get_y1(tf1_topTlqLine), time, line.get_y1(tf1_topTlqLine), xloc=xloc.bar_time, color=color.green) label.new(time, line.get_y1(tf1_topTlqLine), "BOS" + LABEL_SPACE, xloc=xloc.bar_time, style=label.style_none, size=getlabelSize("Normal"), textcolor=color.green) line.delete(tf1_topTlqLine) if not na(tf1_topTlqLabel) label.delete(tf1_topTlqLabel) if close < line.get_y1(tf1_topTlqLine) tf1_structureDirection := "bearish" if close > line.get_y1(tf1_bottomTlqLine) tf1_structureDirection := "bullish" if tf1_canPlot if tf1_isValidHH or tf1_isValidLL delete_line(tf1_bottomTlqLine) delete_line(tf1_topTlqLine) delete_label(tf1_bottomTlqLabel) delete_label(tf1_topTlqLabel) // --- BULLISH STRUCTURE UPDATE LOGIC --- if tf1_isValidHH tf1_bottomTlqPrice := tf1_pl1 < tf1_pl0 ? tf1_pl1 : tf1_pl0 tf1_bottomTlqTime = tf1_pl1 < tf1_pl0 ? tf1_pl1Time : tf1_pl0Time tf1_topTlqPrice := na if not array.includes(ex_usedBosTimes, tf1_bottomTlqTime) tf1_bottomTlqLine := line.new(tf1_bottomTlqTime, tf1_bottomTlqPrice, _TimeTo, tf1_bottomTlqPrice, xloc=xloc.bar_time, color=tf1_tlqCol, style=getLineStyle(tf1_tlqStyle), width=tf1_tlqWidth) tf1_bottomTlqLabel := label.new(_TimeTo, tf1_bottomTlqPrice, tf1_tlqText + LABEL_SPACE, xloc=xloc.bar_time, style=label.style_none, size=getlabelSize("Normal"), textcolor=tf1_tlqCol) // --- π FIX: DYNAMICALLY UPDATE RETRACE ZONE WITH PADDING --- if tf1_structureDirection == "bullish" active_mitigation_level := tf1_bottomTlqPrice active_mitigation_type := "demand" box.delete(active_mitigation_box) if show_mitigation_lines // Box shows the "Front Run" area: From Padded Level down to Pivot active_mitigation_box := box.new(bar_index, active_mitigation_level + _pad_val, bar_index + 10, active_mitigation_level, border_color=color.lime, bgcolor=color.new(color.lime, 80), xloc=xloc.bar_index) // --- BEARISH STRUCTURE UPDATE LOGIC --- if tf1_isValidLL tf1_topTlqPrice := tf1_ph1 > tf1_ph0 ? tf1_ph1 : tf1_ph0 tf1_topTlqTime = tf1_ph1 > tf1_ph0 ? tf1_ph1Time : tf1_ph0Time tf1_bottomTlqPrice := na if not array.includes(ex_usedBosTimes, tf1_topTlqTime) tf1_topTlqLine := line.new(tf1_topTlqTime, tf1_topTlqPrice, _TimeTo, tf1_topTlqPrice, xloc=xloc.bar_time, color=tf1_tlqCol, style=getLineStyle(tf1_tlqStyle), width=tf1_tlqWidth) tf1_topTlqLabel := label.new(_TimeTo, tf1_topTlqPrice, tf1_tlqText + LABEL_SPACE, xloc=xloc.bar_time, style=label.style_none, size=getlabelSize("Normal"), textcolor=tf1_tlqCol) // --- π FIX: DYNAMICALLY UPDATE RETRACE ZONE WITH PADDING --- if tf1_structureDirection == "bearish" active_mitigation_level := tf1_topTlqPrice active_mitigation_type := "supply" box.delete(active_mitigation_box) if show_mitigation_lines // Box shows the "Front Run" area: From Padded Level up to Pivot active_mitigation_box := box.new(bar_index, active_mitigation_level - _pad_val, bar_index + 10, active_mitigation_level, border_color=color.red, bgcolor=color.new(color.red, 80), xloc=xloc.bar_index) if not na(tf1_bottomTlqLine) line.set_x2(tf1_bottomTlqLine, _TimeTo) if not na(tf1_bottomTlqLabel) label.set_x(tf1_bottomTlqLabel, _TimeTo) if not na(tf1_topTlqLine) line.set_x2(tf1_topTlqLine, _TimeTo) if not na(tf1_topTlqLabel) label.set_x(tf1_topTlqLabel, _TimeTo) // --------------- EXTREME --------------- var box tf1_bottomExtremeBox = na var box tf1_topExtremeBox = na if tf1_showExtreme if tf1_canPlot if tf1_isValidHH or tf1_isValidLL delete_box(tf1_bottomExtremeBox) delete_box(tf1_topExtremeBox) if tf1_isValidHH tf1_bottomExtremePrice = tf1_pl1 < tf1_pl0 ? tf1_pl1 : tf1_pl0 tf1_bottomExtremeTime = tf1_pl1 < tf1_pl0 ? tf1_pl1Time : tf1_pl0Time _biL = barIndexAtTime(timesArray, tf1_bottomExtremeTime) lowestBody = open[_biL] > close[_biL] ? close[_biL] : open[_biL] if _biL > 1 tf1_bottomExtremeBox := box.new(tf1_bottomExtremeTime, lowestBody, _TimeTo, tf1_bottomExtremePrice, xloc=xloc.bar_time, border_color=TRANSPARENT, bgcolor=tf1_extremeCol, text=tf1_extremeText, text_color=color.new(tf1_extremeCol, 0), text_halign=text.align_right, text_valign=text.align_top, text_size=getlabelSize("Small")) delete_box(tf1_bottomExtremeBox[1]) if tf1_isValidLL tf1_topExtremePrice = tf1_ph1 > tf1_ph0 ? tf1_ph1 : tf1_ph0 tf1_topExtremeTime = tf1_ph1 > tf1_ph0 ? tf1_ph1Time : tf1_ph0Time _biH = barIndexAtTime(timesArray, tf1_topExtremeTime) highestBody = open[_biH] < close[_biH] ? close[_biH] : open[_biH] if _biH > 1 tf1_topExtremeBox := box.new(tf1_topExtremeTime, tf1_topExtremePrice, _TimeTo, highestBody, xloc=xloc.bar_time, border_color=TRANSPARENT, bgcolor=tf1_extremeCol, text=tf1_extremeText, text_color=color.new(tf1_extremeCol, 0), text_halign=text.align_right, text_valign=text.align_bottom, text_size=getlabelSize("Small")) delete_box(tf1_topExtremeBox[1]) if not na(tf1_bottomExtremeBox) box.set_right(tf1_bottomExtremeBox, _TimeTo) if not na(tf1_bottomExtremeBox) and low < _bottom(tf1_bottomExtremeBox) delete_box(tf1_bottomExtremeBox) if not na(tf1_topExtremeBox) box.set_right(tf1_topExtremeBox, _TimeTo) if not na(tf1_topExtremeBox) and high > _top(tf1_topExtremeBox) delete_box(tf1_topExtremeBox) // --------------- EPA --------------- var float tf1_bearEpaPrice = na var float tf1_bullEpaPrice = na var line tf1_bearEpaLine = na var line tf1_bullEpaLine = na var label tf1_bearEpaLabel = na var label tf1_bullEpaLabel = na if tf1_showEpa if tf1_canPlot if tf1_isValidHH or tf1_isValidLL tf1_isPriceEfficient := false if tf1_epaDelete delete_line(tf1_bearEpaLine) delete_line(tf1_bullEpaLine) delete_label(tf1_bearEpaLabel) delete_label(tf1_bullEpaLabel) if tf1_isValidLL tf1_bearEpaPrice := tf1_pl1 tf1_bullEpaPrice := na tf1_bearEpaLine := line.new(tf1_pl1Time, tf1_pl1, _TimeTo, tf1_pl1, xloc=xloc.bar_time, color=tf1_epaCol, style=getLineStyle(tf1_epaStyle), width=tf1_epaWidth) tf1_bearEpaLabel := label.new(_TimeTo, tf1_pl1, tf1_epaText + LABEL_SPACE, xloc=xloc.bar_time, style=label.style_none, size=getlabelSize("Normal"), textcolor=tf1_epaCol) if tf1_isValidHH tf1_bullEpaPrice := tf1_ph1 tf1_bearEpaPrice := na tf1_bullEpaLine := line.new(tf1_ph1Time, tf1_ph1, _TimeTo, tf1_ph1, xloc=xloc.bar_time, color=tf1_epaCol, style=getLineStyle(tf1_epaStyle), width=tf1_epaWidth) tf1_bullEpaLabel := label.new(_TimeTo, tf1_ph1, tf1_epaText + LABEL_SPACE, xloc=xloc.bar_time, style=label.style_none, size=getlabelSize("Normal"), textcolor=tf1_epaCol) if not na(tf1_bearEpaLine) line.set_x2(tf1_bearEpaLine, _TimeTo) if not na(tf1_bearEpaLabel) label.set_x(tf1_bearEpaLabel, _TimeTo) if not na(tf1_bearEpaLine) and high > tf1_bearEpaPrice tf1_isPriceEfficient := true line.delete(tf1_bearEpaLine) if not na(tf1_bearEpaLabel) label.delete(tf1_bearEpaLabel) if not na(tf1_bullEpaLine) line.set_x2(tf1_bullEpaLine, _TimeTo) if not na(tf1_bullEpaLabel) label.set_x(tf1_bullEpaLabel, _TimeTo) if not na(tf1_bullEpaLine) and low < tf1_bullEpaPrice tf1_isPriceEfficient := true line.delete(tf1_bullEpaLine) if not na(tf1_bullEpaLabel) label.delete(tf1_bullEpaLabel) // --------------- MSU --------------- tf1_isBearishMsu := (tf1_ph0 < tf1_ph1) and (tf1_pl0 < tf1_pl1) and (high > tf1_ph0 and high < tf1_ph1) tf1_isBullishMsu := (tf1_pl0 > tf1_pl1) and (tf1_ph0 > tf1_ph1) and (low < tf1_pl0 and low > tf1_pl1) plotshape(tf1_showMsu and tf1_isBearishMsu, color=color.red, style=shape.arrowdown, location=location.abovebar, size=size.tiny, editable=false) plotshape(tf1_showMsu and tf1_isBullishMsu, color=color.lime, style=shape.arrowup, location=location.belowbar, size=size.tiny, editable=false) tf1_barcolor = not isUseTimeframe1 ? na : tf1_structureDirection == "bullish" and close > open ? tf1_bullishBullBarCol : tf1_structureDirection == "bullish" and close < open ? tf1_bullishBearBarCol : tf1_structureDirection == "bearish" and close > open ? tf1_bearishBullBarCol : tf1_structureDirection == "bearish" and close < open ? tf1_bearishBearBarCol : na plotcandle(tf1_changeBarCol ? open : na, high, low, close, title='Title', color =tf1_barcolor, wickcolor=tf1_barcolor, bordercolor=tf1_barcolor) tf1_isBullishPattern = false tf1_isBearishPattern = false tf1_isBearishPattern := (tf1_ph2 > tf1_ph3) and (tf1_ph1 > tf1_ph2) and (tf1_ph0 < tf1_ph1) and (tf1_pl1 < tf1_pl2) and (tf1_pl0 < tf1_pl1) and (close > tf1_pl0) tf1_isBullishPattern := (tf1_pl2 < tf1_pl3) and (tf1_pl1 < tf1_pl2) and (tf1_pl0 > tf1_pl1) and (tf1_ph1 > tf1_ph2) and (tf1_ph0 > tf1_ph1) and (close < tf1_ph0) plotshape(tf1_div8 and tf1_isBearishPattern and tf1_structureDirection == "bearish", color=color.red, style=shape.xcross, location=location.belowbar, size=size.tiny, editable=false) plotshape(tf1_div8 and tf1_isBullishPattern and tf1_structureDirection == "bullish", color=color.lime, style=shape.xcross, location=location.abovebar, size=size.tiny, editable=false) // ========== TEST BUTTON ========== if test_webhook_now and not last_test_state test_symbol = format_symbol(syminfo.ticker) test_signal = test_symbol + ",TEST,0,0,0,0,0" send_to_all_webhooks(test_signal) last_test_state := true lastWebhookTime := time if not test_webhook_now last_test_state := false // ================================================================= // π NEW LOGIC: RETRACEMENT / MITIGATION (WITH CONFIRMATION PATTERNS) // ================================================================= // --- 1. PATTERN RECOGNITION FUNCTIONS --- // Check for 2 consecutive candles in direction f_is_two_candles(bool is_bull) => is_bull ? (close > open and close[1] > open[1]) : (close < open and close[1] < open[1]) // Check for Engulfing Pattern f_is_engulfing(bool is_bull) => if is_bull // Bullish Engulfing: Current Bullish, Prev Bearish, Current Body covers Prev Body close > open and close[1] < open[1] and close >= open[1] and open <= close[1] else // Bearish Engulfing close < open and close[1] > open[1] and close <= open[1] and open >= close[1] // Check for Wick Rejection (Wick is 2x larger than body) f_is_wick_rejection(bool is_bull) => bodySize = math.abs(close - open) if is_bull // Buy Rejection: Long Lower Wick lowerWick = open < close ? open - low : close - low lowerWick > (bodySize * 2) else // Sell Rejection: Long Upper Wick upperWick = open > close ? high - open : high - close upperWick > (bodySize * 2) // --- 2. EXTEND VISUAL BOX (Keep shifting until touched) --- if not na(active_mitigation_box) box.set_right(active_mitigation_box, bar_index + 5) // --- 3. RETRACEMENT ENTRY LOGIC --- // We reset signal states every bar bool retrace_buy_signal = false bool retrace_sell_signal = false // Helper pip size float _pip_size_ret = get_sym_pip_size() float _buffer_ret = entry_buffer_pips * _pip_size_ret float _pad_val_ret = entry_padding_pips * _pip_size_ret if alert_on_grid and barstate.isconfirmed and not na(active_mitigation_level) // --- DEMAND (BUY) LOGIC --- if active_mitigation_type == "demand" // 1. Check if Price is in/touching the Zone (Level + Padding) bool zone_touched = (low <= (active_mitigation_level + _pad_val_ret) and high >= active_mitigation_level) // 2. Integrity Filter (Body must not break structure lower) bool integrity_pass = use_zone_integrity ? (close >= active_mitigation_level) : true // 3. CONFIRMATION PATTERNS (The new requirement) bool confirmed = f_is_two_candles(true) or f_is_engulfing(true) or f_is_wick_rejection(true) // FIRE: If Touched + Safe + Confirmed if zone_touched and integrity_pass and confirmed retrace_buy_signal := true tf1_entryPrice := high + _buffer_ret tf1_slPrice := active_mitigation_level - (sl_offset_pips * _pip_size_ret) // Reset Zone (Trade Taken) active_mitigation_level := na active_mitigation_type := na box.delete(active_mitigation_box) // --- SUPPLY (SELL) LOGIC --- else if active_mitigation_type == "supply" // 1. Check if Price is in/touching the Zone (Level - Padding) bool zone_touched = (high >= (active_mitigation_level - _pad_val_ret) and low <= active_mitigation_level) // 2. Integrity Filter (Body must not break structure higher) bool integrity_pass = use_zone_integrity ? (close <= active_mitigation_level) : true // 3. CONFIRMATION PATTERNS (The new requirement) bool confirmed = f_is_two_candles(false) or f_is_engulfing(false) or f_is_wick_rejection(false) // FIRE: If Touched + Safe + Confirmed if zone_touched and integrity_pass and confirmed retrace_sell_signal := true tf1_entryPrice := low - _buffer_ret tf1_slPrice := active_mitigation_level + (sl_offset_pips * _pip_size_ret) // Reset Zone (Trade Taken) active_mitigation_level := na active_mitigation_type := na box.delete(active_mitigation_box) // --- 4. EXECUTE ALERTS & VISUALS --- if retrace_buy_signal [signal_message, top_range, bottom_range, sl_price] = prepare_alert_data(syminfo.ticker, "BUY", tf1_entryPrice, tf1_slPrice) draw_historical_marker(true, tf1_entryPrice, range_width_dollars, time) if validate_signal_format(signal_message) send_to_all_webhooks(signal_message) lastBullishAlert := true lastBearishAlert := false lastAlertTime := time lastAlertSymbol := syminfo.ticker if show_popup_alerts alert("π BUY RETRACE SIGNAL: " + syminfo.ticker + "\nEntry: " + str.tostring(tf1_entryPrice) + "\nSL: " + str.tostring(tf1_slPrice), freq=alert.freq_once_per_bar) if retrace_sell_signal [signal_message, top_range, bottom_range, sl_price] = prepare_alert_data(syminfo.ticker, "SELL", tf1_entryPrice, tf1_slPrice) draw_historical_marker(false, tf1_entryPrice, range_width_dollars, time) if validate_signal_format(signal_message) send_to_all_webhooks(signal_message) lastBearishAlert := true lastBullishAlert := false lastAlertTime := time lastAlertSymbol := syminfo.ticker if show_popup_alerts alert("π SELL RETRACE SIGNAL: " + syminfo.ticker + "\nEntry: " + str.tostring(tf1_entryPrice) + "\nSL: " + str.tostring(tf1_slPrice), freq=alert.freq_once_per_bar) // ========== STATUS TABLE (UPDATED v1.8) ========== var table alert_status_table = na if barstate.islast and debug_mode [webhook_count, _, _] = get_enabled_webhooks() alert_status_table := table.new(info_panel_position, 3, 40, bgcolor=color.new(color.black, 95), border_color=color.new(color.white, 50), border_width=2, frame_color=color.new(color.blue, 80), frame_width=1) // Header table.cell(alert_status_table, 0, 0, "REDMAGMA SYSTEM v1.8", text_color=color.white, bgcolor=color.new(color.blue, 80), text_size=size.normal) table.cell(alert_status_table, 1, 0, "STATUS", text_color=color.white, bgcolor=color.new(color.blue, 80)) table.cell(alert_status_table, 2, 0, "VALUES", text_color=color.white, bgcolor=color.new(color.blue, 80)) // 1. Version Information table.cell(alert_status_table, 0, 1, "Version:", text_color=color.white, bgcolor=color.new(color.gray, 70)) table.cell(alert_status_table, 1, 1, VERSION_NUMBER, text_color=color.yellow, bgcolor=color.new(color.gray, 70)) table.cell(alert_status_table, 2, 1, "RETRACE", text_color=color.lime, bgcolor=color.new(color.gray, 70)) // 2. Symbol Information table.cell(alert_status_table, 0, 2, "Current Symbol:", text_color=color.white, bgcolor=color.new(color.gray, 80)) string formatted_symbol = format_symbol(syminfo.ticker) table.cell(alert_status_table, 1, 2, formatted_symbol, text_color=color.orange, bgcolor=color.new(color.gray, 80)) table.cell(alert_status_table, 2, 2, "ACTIVE", text_color=color.lime, bgcolor=color.new(color.gray, 80)) // 3. Signal Mode table.cell(alert_status_table, 0, 3, "π§ Signal Mode:", text_color=color.white, bgcolor=color.new(color.gray, 70)) string mode_text = send_signal_with_detail ? "REAL VALUES β" : "ZEROS β‘" table.cell(alert_status_table, 1, 3, mode_text, text_color=send_signal_with_detail ? color.lime : color.yellow, bgcolor=color.new(color.gray, 70)) table.cell(alert_status_table, 2, 3, "Stop Order", text_color=color.aqua, bgcolor=color.new(color.gray, 70)) // 4. Webhook Status table.cell(alert_status_table, 0, 4, "Webhooks Active:", text_color=color.white, bgcolor=color.new(color.gray, 80)) table.cell(alert_status_table, 1, 4, str.tostring(webhook_count) + "/10", text_color=webhook_count > 0 ? color.lime : color.red, bgcolor=color.new(color.gray, 80)) table.cell(alert_status_table, 2, 4, webhook_count > 0 ? "BROADCASTING" : "NO WEBHOOKS", text_color=webhook_count > 0 ? color.lime : color.red, bgcolor=color.new(color.gray, 80)) // 5. SL Offset table.cell(alert_status_table, 0, 5, "SL Offset:", text_color=color.white, bgcolor=color.new(color.gray, 70)) table.cell(alert_status_table, 1, 5, str.tostring(sl_offset_pips) + " pips", text_color=color.yellow, bgcolor=color.new(color.gray, 70)) table.cell(alert_status_table, 2, 5, "From Zone", text_color=color.lime, bgcolor=color.new(color.gray, 70)) // 6. Active Zone Status (New for Retracement) table.cell(alert_status_table, 0, 6, "Active Zone:", text_color=color.white, bgcolor=color.new(color.gray, 80)) string zone_status = na(active_mitigation_type) ? "WAITING..." : (active_mitigation_type == "demand" ? "DEMAND (BUY)" : "SUPPLY (SELL)") color zone_col = na(active_mitigation_type) ? color.gray : (active_mitigation_type == "demand" ? color.lime : color.red) table.cell(alert_status_table, 1, 6, zone_status, text_color=zone_col, bgcolor=color.new(color.gray, 80)) table.cell(alert_status_table, 2, 6, na(active_mitigation_level) ? "---" : str.tostring(active_mitigation_level, "#.##"), text_color=color.white, bgcolor=color.new(color.gray, 80)) // 7. Last Signal (Action) table.cell(alert_status_table, 0, 7, "Last Signal:", text_color=color.white, bgcolor=color.new(color.gray, 70)) table.cell(alert_status_table, 1, 7, lastBullishAlert ? "BUY RETRACE" : lastBearishAlert ? "SELL RETRACE" : "NONE", text_color=lastBullishAlert ? color.lime : lastBearishAlert ? color.red : color.gray, bgcolor=color.new(color.gray, 70)) table.cell(alert_status_table, 2, 7, lastAlertSymbol, text_color=color.aqua, bgcolor=color.new(color.gray, 70)) // 8. Last Signal (Time) table.cell(alert_status_table, 0, 8, "Signal Time:", text_color=color.white, bgcolor=color.new(color.gray, 80)) string _timeText = lastAlertTime > 0 ? str.format("{0,date,HH:mm:ss}", lastAlertTime) : "---" string _agoText = lastAlertTime > 0 ? str.tostring(math.round((time - lastAlertTime)/60000)) + " min ago" : "WAITING..." table.cell(alert_status_table, 1, 8, _timeText, text_color=lastAlertTime > 0 ? color.yellow : color.gray, bgcolor=color.new(color.gray, 80)) table.cell(alert_status_table, 2, 8, _agoText, text_color=color.lime, bgcolor=color.new(color.gray, 80)) // --------------- DETAILS TABLE WITH SENTIMENT ---------------- if barstate.islast and structure_show_table table _table = table.new(structure_table_vertical + "_" + structure_table_horizontal, 6, 6, border_width=3,bgcolor=color.new(color.black, 95),border_color=color.new(color.white, 30),frame_color=color.new(color.blue, 60),frame_width=2) table.cell(_table, 0, 0, "") table.cell(_table, 0, 1, "Structure", text_color=color.white, bgcolor=color.new(color.blue, 80), text_size=size.small) table.cell(_table, 0, 2, "Sentiment", text_color=color.white, bgcolor=color.new(color.blue, 80), text_size=size.small) table.cell(_table, 0, 3, "Efficiency", text_color=color.white, bgcolor=color.new(color.blue, 80), text_size=size.small) table.cell(_table, 0, 4, "MSU", text_color=color.white, bgcolor=color.new(color.blue, 80), text_size=size.small) if isUseTimeframe1 _timeframeString = indicatorTimeframe string sentiment = "Neutral" color sentimentColor = color.gray if tf1_structureDirection == "bullish" and tf1_isPriceEfficient sentiment := "Bullish" sentimentColor := color.lime else if tf1_structureDirection == "bearish" and tf1_isPriceEfficient sentiment := "Bearish" sentimentColor := color.red else if tf1_structureDirection == "bullish" and not tf1_isPriceEfficient sentiment := "Neutral (Bull Bias)" sentimentColor := color.new(color.lime, 50) else if tf1_structureDirection == "bearish" and not tf1_isPriceEfficient sentiment := "Neutral (Bear Bias)" sentimentColor := color.new(color.red, 50) table.cell(_table, 1, 0, str.tostring(_timeframeString), text_color=color.white, bgcolor=color.new(color.green, 90), text_size=size.normal) table.cell(_table, 1, 1, isUseTimeframe1 ? tf1_structureDirection == "bullish" ? "Bullish β²" : "Bearish βΌ" : "NA", text_color=tf1_structureDirection == "bullish" ? color.lime : color.red, bgcolor=color.new(color.black, 80), text_size=size.normal) table.cell(_table, 1, 2, sentiment, text_color=sentimentColor, bgcolor=color.new(color.black, 80), text_size=size.normal) table.cell(_table, 1, 3, isUseTimeframe1 ? tf1_isPriceEfficient ? "Efficient β" : "Inefficient π" : "NA", text_color=tf1_isPriceEfficient ? color.lime : color.red, bgcolor=color.new(color.black, 80), text_size=size.normal) table.cell(_table, 1, 4, isUseTimeframe1 ? tf1_isBullishMsu ? "MSU β²" : tf1_isBearishMsu ? "MSU βΌ" : "" : "NA", text_color=tf1_isBullishMsu ? color.lime : color.red, bgcolor=color.new(color.black, 80), text_size=size.normal)
Summary:
Please note that all contributions to freem are considered to be released under the Creative Commons Attribution-ShareAlike 4.0 (see
Freem:Copyrights
for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)