Created
April 8, 2025 19:57
-
-
Save feliperazeek/bdacc901f9ce3e561f14145681af60f6 to your computer and use it in GitHub Desktop.
123-UShape-strategy.pine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//@version=5 | |
strategy("NakInvest - 123 Strategy (Full Control)", overlay=true, | |
default_qty_type=strategy.percent_of_equity, | |
default_qty_value=1, | |
commission_type=strategy.commission.percent, | |
commission_value=0.045) | |
// === INPUTS === | |
// Pattern | |
minBodyRatio = input.float(0.7, "Min Body Size Ratio (Candle 3 vs 1)", minval=0.1, group="123 Pattern") | |
maxBody2Ratio = input.float(0.3, "Max Body Size Ratio for Candle 2 (vs Candle 1)", minval=0.05, group="123 Pattern") | |
showPatternLabels = input.bool(true, "Show 123 Pattern Labels", group="123 Pattern") | |
// Trade Direction | |
enableLong = input.bool(true, "Enable Long Trades", group="Trade Direction") | |
enableShort = input.bool(true, "Enable Short Trades", group="Trade Direction") | |
// Moving Averages | |
maType = input.string("EMA", "MA Type", options=["EMA", "SMA"], group="Moving Averages") | |
fastLength = input.int(40, "Fast MA Length", group="Moving Averages") | |
slowLength = input.int(80, "Slow MA Length", group="Moving Averages") | |
// MA Filters | |
useTrendFilter = input.bool(false, "Use Trend Filter (Fast > Slow)", group="MA Filter") | |
useMASlope = input.bool(false, "Use MA Slope Filter", group="MA Filter") | |
requirePriceAboveBelowMA = input.bool(false, "Require Price Above/Below Both MAs", group="MA Filter") | |
// Stop Loss Options | |
slType = input.string("Candle", "Stop Loss Type", options=["Candle", "Percentage"], group="Stop Loss") | |
slPerc = input.float(5.0, "Stop Loss %", minval=0, maxval=100, group="Stop Loss") | |
// Take Profit Options | |
tpType = input.string("Percentage", "Take Profit Type", options=["Percentage", "MA Exit", "Risk-Reward"], group="Take Profit") | |
tpPerc = input.float(1.0, "Target Profit %", minval=0, maxval=100, group="Take Profit") | |
rrRatio = input.float(2.0, "Risk-Reward Ratio (for RR TP)", minval=0.5, step=0.1, group="Take Profit") | |
atrMultiplier = input.float(1.0, "ATR Multiplier (RR TP)", minval=0.1, group="Take Profit") | |
atrLength = input.int(14, "ATR Length (RR TP)", group="Take Profit") | |
// Date Filter | |
startDate = input.time(timestamp("2025-01-01 00:00 +0000"), "Start Date", group="Date Filter") | |
endDate = input.time(timestamp("2030-01-01 00:00 +0000"), "End Date", group="Date Filter") | |
inDateRange = time >= startDate and time <= endDate | |
// Time-of-Day Filter | |
useSessionTime = input.bool(false, "Enable Time of Day Filter", group="Time Filter") | |
sessionStart = input.time(timestamp("1970-01-01 09:30 +0000"), "Session Start (UTC)", group="Time Filter") | |
sessionEnd = input.time(timestamp("1970-01-01 16:00 +0000"), "Session End (UTC)", group="Time Filter") | |
t = time % 86400000 | |
inSession = not useSessionTime or (t >= (sessionStart % 86400000) and t <= (sessionEnd % 86400000)) | |
// Day-of-Week Filter | |
useWeekdayFilter = input.bool(false, "Enable Weekday Filter", group="Time Filter") | |
mon = input.bool(true, "Monday", group="Time Filter") | |
tue = input.bool(true, "Tuesday", group="Time Filter") | |
wed = input.bool(true, "Wednesday", group="Time Filter") | |
thu = input.bool(true, "Thursday", group="Time Filter") | |
fri = input.bool(true, "Friday", group="Time Filter") | |
allowedWeekday = dayofweek == dayofweek.monday and mon or | |
dayofweek == dayofweek.tuesday and tue or | |
dayofweek == dayofweek.wednesday and wed or | |
dayofweek == dayofweek.thursday and thu or | |
dayofweek == dayofweek.friday and fri | |
inWeekday = not useWeekdayFilter or allowedWeekday | |
// === MA CALCULATION === | |
getMA(src, len) => maType == "EMA" ? ta.ema(src, len) : ta.sma(src, len) | |
fastMA = getMA(close, fastLength) | |
slowMA = getMA(close, slowLength) | |
fastSlope = fastMA - fastMA[1] | |
slowSlope = slowMA - slowMA[1] | |
plot(fastMA, title="Fast MA", color=color.green) | |
plot(slowMA, title="Slow MA", color=color.red) | |
// === PATTERN LOGIC === | |
bodySize(idx) => math.abs(close[idx] - open[idx]) | |
isGreen(idx) => close[idx] > open[idx] | |
isRed(idx) => close[idx] < open[idx] | |
c1_body = bodySize(2) | |
c2_body = bodySize(1) | |
c3_body = bodySize(0) | |
is123Bullish = isRed(2) and c2_body < c1_body * maxBody2Ratio and isGreen(0) and bodySize(0) >= c1_body * minBodyRatio | |
is123Bearish = isGreen(2) and c2_body < c1_body * maxBody2Ratio and isRed(0) and bodySize(0) >= c1_body * minBodyRatio | |
// === LABELS === | |
if showPatternLabels | |
if enableLong and is123Bullish | |
label.new(bar_index, low, "123-U", style=label.style_label_up, color=color.green, textcolor=color.white, size=size.small) | |
if enableShort and is123Bearish | |
label.new(bar_index, high, "123-∩", style=label.style_label_down, color=color.red, textcolor=color.white, size=size.small) | |
// === FILTERS === | |
trendLong = not useTrendFilter or (fastMA > slowMA) | |
trendShort = not useTrendFilter or (fastMA < slowMA) | |
slopeLong = not useMASlope or (fastSlope > 0) | |
slopeShort = not useMASlope or (fastSlope < 0) | |
priceAboveMAs = close > fastMA and close > slowMA | |
priceBelowMAs = close < fastMA and close < slowMA | |
inTimeAndDate = inDateRange and inSession and inWeekday | |
// === ATR === | |
atr = ta.atr(atrLength) | |
// === LONG TRADE === | |
if enableLong and is123Bullish and trendLong and slopeLong and (not requirePriceAboveBelowMA or priceAboveMAs) and inTimeAndDate | |
slLong = slType == "Candle" ? low : close * (1 - slPerc / 100), tpLong = tpType == "Percentage" ? close * (1 + tpPerc / 100) : tpType == "Risk-Reward" ? close + (close - slLong) * rrRatio : na | |
strategy.entry("Long", strategy.long), strategy.exit("Exit Long", from_entry="Long", stop=slLong, limit=tpType == "MA Exit" ? na : tpLong) | |
line.new(bar_index, tpType == "MA Exit" ? na : tpLong, bar_index + 1, tpType == "MA Exit" ? na : tpLong, color=color.green, width=1) | |
line.new(bar_index, slLong, bar_index + 1, slLong, color=color.red, width=1) | |
// === SHORT TRADE === | |
if enableShort and is123Bearish and trendShort and slopeShort and (not requirePriceAboveBelowMA or priceBelowMAs) and inTimeAndDate | |
slShort = slType == "Candle" ? high : close * (1 + slPerc / 100), tpShort = tpType == "Percentage" ? close * (1 - tpPerc / 100) : tpType == "Risk-Reward" ? close - (slShort - close) * rrRatio : na | |
strategy.entry("Short", strategy.short), strategy.exit("Exit Short", from_entry="Short", stop=slShort, limit=tpType == "MA Exit" ? na : tpShort) | |
line.new(bar_index, tpType == "MA Exit" ? na : tpShort, bar_index + 1, tpType == "MA Exit" ? na : tpShort, color=color.green, width=1) | |
line.new(bar_index, slShort, bar_index + 1, slShort, color=color.red, width=1) | |
// === MA EXIT === | |
if tpType == "MA Exit" | |
strategy.close("Long", when=close < fastMA) | |
strategy.close("Short", when=close > fastMA) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment