//@version=6 indicator("HTF + LTF Engine PRO V2.9 SIGNAL", overlay=true, max_lines_count=500, max_labels_count=500, max_boxes_count=500) // ====================================================== // DATE FILTER // ====================================================== dateMode = input.string("This Month", "Backtest Range", options=["This Month", "Last X Days", "Custom"]) xDays = input.int(30, "Last X Days") customStart = input.time(timestamp("2025-01-01 00:00 +0000"), "Custom Start") customEnd = input.time(timestamp("2025-12-31 23:59 +0000"), "Custom End") var int rangeStart = na var int rangeEnd = na if dateMode == "This Month" rangeStart := timestamp(year, month, 1, 0, 0) rangeEnd := timestamp(year, month + 1, 1, 0, 0) if dateMode == "Last X Days" rangeStart := timenow - (xDays * 24 * 60 * 60 * 1000) rangeEnd := timenow if dateMode == "Custom" rangeStart := customStart rangeEnd := customEnd inDateRange = time >= rangeStart and time <= rangeEnd // ====================================================== // SETTINGS // ====================================================== htf_tf = input.timeframe("240", "HTF Bias TF") pivotLen = input.int(5, "Pivot Length") atrPeriod = input.int(10, "Supertrend ATR") factor = input.float(3.0, "Supertrend Factor") rr = input.float(1.5, "Risk Reward") // ====================================================== // HTF BIAS // ====================================================== [st, dir] = request.security(syminfo.tickerid, htf_tf, ta.supertrend(factor, atrPeriod)) bullBias = dir == 1 bearBias = dir == -1 // ====================================================== // STRUCTURE // ====================================================== ph = ta.pivothigh(high, pivotLen, pivotLen) pl = ta.pivotlow(low, pivotLen, pivotLen) var float lastPH = na var float lastPL = na if not na(ph) lastPH := ph if not na(pl) lastPL := pl // ====================================================== // TRADE ARRAYS (Magic Engine) // ====================================================== var int tradeCounter = 0 var tradeIDArr = array.new_int() var entryArr = array.new_float() var slArr = array.new_float() var tpArr = array.new_float() var dirArr = array.new_int() // 1 long, -1 short var statusArr = array.new_int() // 0 active, 1 TP, -1 SL var barArr = array.new_int() // ====================================================== // ENTRY CONDITIONS // ====================================================== volMA = ta.sma(volume, 20) highVolume = volume > volMA strongBull = close > open and (close - open) > (high - low) * 0.65 strongBear = close < open and (open - close) > (high - low) * 0.65 buyBreak = bullBias and close > lastPH and strongBull sellBreak = bearBias and close < lastPL and strongBear buyPull = bullBias and low <= lastPH and close > open and strongBull sellPull = bearBias and high >= lastPL and close < open and strongBear sellSignal = (buyBreak or buyPull) and inDateRange and highVolume buySignal = (sellBreak or sellPull) and inDateRange and highVolume // ====================================================== // OPEN TRADE // ====================================================== if sellSignal and not na(lastPL) tradeCounter += 1 entry = close entryBar = bar_index sl = lastPL tp = entry + (entry - sl) * rr // ---- SAFETY CHECK (LONG) ---- if sl > entry float temp = sl sl := entry - math.abs(entry - temp) tp := entry + math.abs(entry - sl) * rr array.push(tradeIDArr, tradeCounter) array.push(entryArr, entry) array.push(slArr, sl) array.push(tpArr, tp) array.push(dirArr, 1) array.push(statusArr, 0) array.push(barArr, entryBar) label.new(bar_index, entry, "SHORT #" + str.tostring(tradeCounter) + "\nEntry: " + str.tostring(entry) + "\nTP: " + str.tostring(sl) + "\nSL: " + str.tostring(tp), style=label.style_label_down, color=color.red) if buySignal and not na(lastPH) tradeCounter += 1 entry = close entryBar = bar_index sl = lastPH tp = entry - (sl - entry) * rr // ---- SAFETY CHECK (SHORT) ---- if sl < entry float temp = sl sl := entry + math.abs(entry - temp) tp := entry - math.abs(sl - entry) * rr array.push(tradeIDArr, tradeCounter) array.push(entryArr, entry) array.push(slArr, sl) array.push(tpArr, tp) array.push(dirArr, -1) array.push(statusArr, 0) array.push(barArr, entryBar) label.new(bar_index, entry, "LONG #" + str.tostring(tradeCounter) + "\nEntry: " + str.tostring(entry) + "\nTP: " + str.tostring(sl) + "\nSL: " + str.tostring(tp), style=label.style_label_up, color=color.green) // ====================================================== // TRADE MANAGEMENT // ====================================================== wins = 0 losses = 0 tradeSize = array.size(tradeIDArr) if tradeSize > 0 for i = 0 to tradeSize - 1 tradeStatus = array.get(statusArr, i) if tradeStatus == 0 tradeOpenBar = array.get(barArr, i) // Only evaluate AFTER entry candle closes if bar_index > tradeOpenBar entryPrice = array.get(entryArr, i) slPrice = array.get(slArr, i) tpPrice = array.get(tpArr, i) tradeDir = array.get(dirArr, i) tradeID = array.get(tradeIDArr, i) hitTP = false hitSL = false float labelPrice = na if tradeDir == 1 // SHORT if low <= slPrice hitTP := true labelPrice := low else if high >= tpPrice hitSL := true labelPrice := high else // LONG if high >= slPrice hitTP := true labelPrice := high else if low <= tpPrice hitSL := true labelPrice := low if hitSL array.set(statusArr, i, -1) label.new(bar_index, labelPrice, "SL #" + str.tostring(tradeID), style=label.style_label_up, color=color.orange) if hitTP array.set(statusArr, i, 1) label.new(bar_index, labelPrice, "TP #" + str.tostring(tradeID), style=label.style_label_down, color=color.blue) // ====================================================== // COUNT RESULTS // ====================================================== statusSize = array.size(statusArr) if statusSize > 0 for i = 0 to statusSize - 1 stt = array.get(statusArr, i) if stt == 1 wins += 1 if stt == -1 losses += 1 // ====================================================== // STATS PANEL (CLEAN VERSION) // ====================================================== total = wins + losses winRate = total > 0 ? (wins * 100.0) / total : 0.0 var table stats = table.new(position.top_right, 1, 4) if barstate.islast table.cell(stats, 0, 0, "Wins: " + str.tostring(wins)) table.cell(stats, 0, 1, "Losses: " + str.tostring(losses)) table.cell(stats, 0, 2, "Total: " + str.tostring(total)) table.cell(stats, 0, 3, "Winrate: " + str.tostring(winRate, "#.##") + "%")