// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © trading-setups
//@version=5
strategy(title="Polish Setup Strategy", shorttitle="Polish Strategy", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.1, slippage=2)
// ═══════════════════════════════════════════════════════════════════════════════════════════
// INPUT PARAMETERS
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Smoothed Moving Average Settings
smma_fast_period = input.int(21, title="Fast SMMA Period", minval=1, group="Moving Averages")
smma_medium_period = input.int(50, title="Medium SMMA Period", minval=1, group="Moving Averages")
smma_slow_period = input.int(200, title="Slow SMMA Period", minval=1, group="Moving Averages")
// Pattern Recognition Settings
pattern_lookback = input.int(7, title="Pattern Lookback Period", minval=3, maxval=20, group="Pattern Recognition")
pattern_similarity = input.float(2.0, title="Pattern Similarity %", minval=0.5, maxval=5.0, group="Pattern Recognition")
require_volume_confirmation = input.bool(true, title="Require Volume Confirmation", group="Pattern Recognition")
// RSI Settings
rsi_period = input.int(14, title="RSI Period", minval=2, maxval=50, group="Momentum")
rsi_midline = input.int(50, title="RSI Midline", minval=30, maxval=70, group="Momentum")
// Extension Levels
extension_primary = input.float(4.669, title="Primary Extension Level", minval=1.0, maxval=10.0, group="Targets")
extension_secondary = input.float(2.618, title="Secondary Extension Level", minval=1.0, maxval=5.0, group="Targets")
// Trading Session
session_start_hour = input.int(8, title="Session Start Hour", minval=0, maxval=23, group="Trading Session")
session_start_minute = input.int(30, title="Session Start Minute", minval=0, maxval=59, group="Trading Session")
session_end_hour = input.int(12, title="Session End Hour", minval=0, maxval=23, group="Trading Session")
session_end_minute = input.int(0, title="Session End Minute", minval=0, maxval=59, group="Trading Session")
session_timezone = input.string("America/Chicago", title="Timezone", options=["America/New_York", "America/Chicago", "Europe/London", "Asia/Tokyo"], group="Trading Session")
// Risk Management
base_risk_percent = input.float(2.0, title="Base Risk %", minval=0.5, maxval=10.0, group="Risk Management")
max_risk_percent = input.float(5.0, title="Maximum Risk %", minval=1.0, maxval=20.0, group="Risk Management")
enable_stop_management = input.bool(true, title="Enable Stop Management", group="Risk Management")
stop_trail_percent = input.float(66.0, title="Trailing Stop Activation %", minval=50.0, maxval=100.0, group="Risk Management")
// Strategy Controls
allow_long = input.bool(true, title="Allow Long Trades", group="Strategy Controls")
allow_short = input.bool(true, title="Allow Short Trades", group="Strategy Controls")
max_concurrent_trades = input.int(1, title="Max Concurrent Trades", minval=1, maxval=3, group="Strategy Controls")
close_at_session_end = input.bool(true, title="Close at Session End", group="Strategy Controls")
// Visual Settings
show_ma_stack = input.bool(true, title="Show Moving Average Stack", group="Display")
show_patterns = input.bool(true, title="Show W/M Patterns", group="Display")
show_signals = input.bool(true, title="Show Entry Signals", group="Display")
show_targets = input.bool(true, title="Show Extension Targets", group="Display")
show_session = input.bool(true, title="Show Trading Session", group="Display")
// ═══════════════════════════════════════════════════════════════════════════════════════════
// SMOOTHED MOVING AVERAGE CALCULATION
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Smoothed Moving Average (SMMA) function
smma(src, length) =>
var float smma_val = na
smma_val := na(smma_val[1]) ? ta.sma(src, length) : (smma_val[1] * (length - 1) + src) / length
smma_val
// Calculate smoothed moving averages
smma_fast = smma(close, smma_fast_period)
smma_medium = smma(close, smma_medium_period)
smma_slow = smma(close, smma_slow_period)
// Moving average stack conditions
bullish_stack = smma_fast > smma_medium and smma_medium > smma_slow
bearish_stack = smma_fast < smma_medium and smma_medium < smma_slow
// ═══════════════════════════════════════════════════════════════════════════════════════════
// TRADING SESSION DETECTION
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Current time in specified timezone
current_time = time(timeframe.period, session_timezone)
session_start_time = timestamp(session_timezone, year, month, dayofmonth, session_start_hour, session_start_minute)
session_end_time = timestamp(session_timezone, year, month, dayofmonth, session_end_hour, session_end_minute)
// Check if current time is within trading session
in_session = current_time >= session_start_time and current_time <= session_end_time and dayofweek != dayofweek.saturday and dayofweek != dayofweek.sunday
// Session end detection
session_ending = math.abs(current_time - session_end_time) <= 30 * 60 * 1000 // 30 minutes before end
// ═══════════════════════════════════════════════════════════════════════════════════════════
// PATTERN DETECTION FUNCTIONS
// ═══════════════════════════════════════════════════════════════════════════════════════════
// W Pattern Detection (Double Bottom)
detect_w_pattern() =>
var float left_low = na
var float right_low = na
var float middle_high = na
var int pattern_bars = 0
// Look for potential W pattern
for i = 2 to pattern_lookback
if low[i] <= low[i-1] and low[i] <= low[i+1] // Local low
if na(left_low)
left_low := low[i]
pattern_bars := i
else if na(right_low) and i > pattern_bars + 2
right_low := low[i]
// Find highest point between lows
for j = i to pattern_bars
if na(middle_high) or high[j] > middle_high
middle_high := high[j]
break
// Validate W pattern
pattern_valid = false
if not na(left_low) and not na(right_low) and not na(middle_high)
similarity = math.abs(left_low - right_low) / left_low * 100
higher_middle = middle_high > math.max(left_low, right_low)
breakout = close > middle_high
pattern_valid := similarity <= pattern_similarity and higher_middle and breakout
// Volume confirmation
volume_confirmed = true
if require_volume_confirmation
avg_volume = ta.sma(volume, 20)
volume_confirmed := volume > avg_volume
[pattern_valid and volume_confirmed, left_low, right_low, middle_high]
// M Pattern Detection (Double Top)
detect_m_pattern() =>
var float left_high = na
var float right_high = na
var float middle_low = na
var int pattern_bars = 0
// Look for potential M pattern
for i = 2 to pattern_lookback
if high[i] >= high[i-1] and high[i] >= high[i+1] // Local high
if na(left_high)
left_high := high[i]
pattern_bars := i
else if na(right_high) and i > pattern_bars + 2
right_high := high[i]
// Find lowest point between highs
for j = i to pattern_bars
if na(middle_low) or low[j] < middle_low
middle_low := low[j]
break
// Validate M pattern
pattern_valid = false
if not na(left_high) and not na(right_high) and not na(middle_low)
similarity = math.abs(left_high - right_high) / left_high * 100
lower_middle = middle_low < math.min(left_high, right_high)
breakdown = close < middle_low
pattern_valid := similarity <= pattern_similarity and lower_middle and breakdown
// Volume confirmation
volume_confirmed = true
if require_volume_confirmation
avg_volume = ta.sma(volume, 20)
volume_confirmed := volume > avg_volume
[pattern_valid and volume_confirmed, left_high, right_high, middle_low]
// ═══════════════════════════════════════════════════════════════════════════════════════════
// MOMENTUM ANALYSIS
// ═══════════════════════════════════════════════════════════════════════════════════════════
// RSI calculation
rsi_value = ta.rsi(close, rsi_period)
// Momentum conditions
bullish_momentum = rsi_value >= rsi_midline
bearish_momentum = rsi_value <= rsi_midline
// ═══════════════════════════════════════════════════════════════════════════════════════════
// STRUCTURE ANALYSIS
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Pattern detection
[w_pattern_detected, w_left_low, w_right_low, w_middle_high] = detect_w_pattern()
[m_pattern_detected, m_left_high, m_right_high, m_middle_low] = detect_m_pattern()
// Pullback conditions
bullish_pullback = close > smma_slow and (low <= smma_medium or low[1] <= smma_medium[1])
bearish_pullback = close < smma_slow and (high >= smma_medium or high[1] >= smma_medium[1])
// ═══════════════════════════════════════════════════════════════════════════════════════════
// ENTRY SIGNAL GENERATION
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Bullish Polish Setup
bullish_setup = in_session and bullish_stack and (w_pattern_detected or bullish_momentum) and bullish_pullback and allow_long and strategy.position_size == 0
// Bearish Polish Setup
bearish_setup = in_session and bearish_stack and (m_pattern_detected or bearish_momentum) and bearish_pullback and allow_short and strategy.position_size == 0
// ═══════════════════════════════════════════════════════════════════════════════════════════
// PROFIT TARGET AND STOP LOSS CALCULATION
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Calculate ATR for stop loss
atr_value = ta.atr(14)
// Calculate targets based on patterns
var float bull_primary_target = na
var float bull_secondary_target = na
var float bear_primary_target = na
var float bear_secondary_target = na
if bullish_setup
if w_pattern_detected
pattern_height = w_middle_high - math.min(w_left_low, w_right_low)
bull_secondary_target := w_middle_high + (pattern_height * extension_secondary)
bull_primary_target := w_middle_high + (pattern_height * extension_primary)
else
// Use price-based targets for RSI-only setups
bull_secondary_target := close + (close * 0.02) // 2% target
bull_primary_target := close + (close * 0.05) // 5% target
if bearish_setup
if m_pattern_detected
pattern_height = math.max(m_left_high, m_right_high) - m_middle_low
bear_secondary_target := m_middle_low - (pattern_height * extension_secondary)
bear_primary_target := m_middle_low - (pattern_height * extension_primary)
else
// Use price-based targets for RSI-only setups
bear_secondary_target := close - (close * 0.02) // 2% target
bear_primary_target := close - (close * 0.05) // 5% target
// Calculate stop losses
bull_stop_loss = ta.lowest(low, 3) - (atr_value * 0.5)
bear_stop_loss = ta.highest(high, 3) + (atr_value * 0.5)
// ═══════════════════════════════════════════════════════════════════════════════════════════
// RISK MANAGEMENT
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Calculate risk percentage
current_risk_percent = base_risk_percent
if not w_pattern_detected and not m_pattern_detected
current_risk_percent := math.min(current_risk_percent + 1.0, max_risk_percent) // Higher risk for RSI-only setups
// Position sizing
calculate_position_size(entry_price, stop_price, risk_percent) =>
account_value = strategy.equity
risk_amount = account_value * (risk_percent / 100)
stop_distance = math.abs(entry_price - stop_price)
position_size = risk_amount / stop_distance
max_position = account_value * 0.1 // 10% maximum position size
math.min(position_size, max_position)
// ═══════════════════════════════════════════════════════════════════════════════════════════
// STRATEGY EXECUTION
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Entry logic
if bullish_setup
pos_size = calculate_position_size(close, bull_stop_loss, current_risk_percent)
strategy.entry("Polish Long", strategy.long, qty=pos_size, comment="Polish Bull")
// Set stop loss and take profit
strategy.exit("Polish Long Exit", from_entry="Polish Long", stop=bull_stop_loss, limit=bull_primary_target, comment="Bull Exit")
if bearish_setup
pos_size = calculate_position_size(close, bear_stop_loss, current_risk_percent)
strategy.entry("Polish Short", strategy.short, qty=pos_size, comment="Polish Bear")
// Set stop loss and take profit
strategy.exit("Polish Short Exit", from_entry="Polish Short", stop=bear_stop_loss, limit=bear_primary_target, comment="Bear Exit")
// ═══════════════════════════════════════════════════════════════════════════════════════════
// POSITION MANAGEMENT
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Progressive stop management
if enable_stop_management and strategy.position_size > 0
// Calculate progress toward target
entry_price = strategy.position_avg_price
target_distance = bull_primary_target - entry_price
current_distance = close - entry_price
progress = current_distance / target_distance
// Move stop to secondary target at specified progress
if progress >= (stop_trail_percent / 100)
new_stop = bull_secondary_target
strategy.exit("Polish Long Trail", from_entry="Polish Long", stop=new_stop, limit=bull_primary_target, comment="Bull Trail")
if enable_stop_management and strategy.position_size < 0
// Calculate progress toward target
entry_price = strategy.position_avg_price
target_distance = entry_price - bear_primary_target
current_distance = entry_price - close
progress = current_distance / target_distance
// Move stop to secondary target at specified progress
if progress >= (stop_trail_percent / 100)
new_stop = bear_secondary_target
strategy.exit("Polish Short Trail", from_entry="Polish Short", stop=new_stop, limit=bear_primary_target, comment="Bear Trail")
// Close positions at session end
if close_at_session_end and session_ending
strategy.close_all(comment="Session End")
// ═══════════════════════════════════════════════════════════════════════════════════════════
// VISUAL ELEMENTS
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Plot smoothed moving averages
plot(show_ma_stack ? smma_fast : na, title="Fast SMMA", color=color.green, linewidth=2)
plot(show_ma_stack ? smma_medium : na, title="Medium SMMA", color=color.yellow, linewidth=2)
plot(show_ma_stack ? smma_slow : na, title="Slow SMMA", color=color.red, linewidth=2)
// Moving average stack background
bgcolor(show_ma_stack and bullish_stack ? color.new(color.green, 95) : show_ma_stack and bearish_stack ? color.new(color.red, 95) : na, title="MA Stack Background")
// Trading session background
bgcolor(show_session and in_session ? color.new(color.blue, 98) : na, title="Trading Session")
// Pattern signals
plotshape(show_patterns and w_pattern_detected, title="W Pattern", location=location.belowbar, color=color.green, style=shape.labelup, text="W", size=size.small)
plotshape(show_patterns and m_pattern_detected, title="M Pattern", location=location.abovebar, color=color.red, style=shape.labeldown, text="M", size=size.small)
// Entry signals
plotshape(show_signals and bullish_setup, title="Bullish Polish Setup", location=location.belowbar, color=color.lime, style=shape.triangleup, text="POLISH\nBULL", size=size.normal)
plotshape(show_signals and bearish_setup, title="Bearish Polish Setup", location=location.abovebar, color=color.red, style=shape.triangledown, text="POLISH\nBEAR", size=size.normal)
// Extension targets for active positions
plot(show_targets and strategy.position_size > 0 and not na(bull_secondary_target) ? bull_secondary_target : na, title="Bull Secondary Target", color=color.lime, linewidth=1, style=plot.style_circles)
plot(show_targets and strategy.position_size > 0 and not na(bull_primary_target) ? bull_primary_target : na, title="Bull Primary Target", color=color.green, linewidth=2, style=plot.style_circles)
plot(show_targets and strategy.position_size < 0 and not na(bear_secondary_target) ? bear_secondary_target : na, title="Bear Secondary Target", color=color.orange, linewidth=1, style=plot.style_circles)
plot(show_targets and strategy.position_size < 0 and not na(bear_primary_target) ? bear_primary_target : na, title="Bear Primary Target", color=color.red, linewidth=2, style=plot.style_circles)
// Stop loss levels for active positions
plot(show_targets and strategy.position_size > 0 ? bull_stop_loss : na, title="Bull Stop Loss", color=color.red, linewidth=1, style=plot.style_cross)
plot(show_targets and strategy.position_size < 0 ? bear_stop_loss : na, title="Bear Stop Loss", color=color.red, linewidth=1, style=plot.style_cross)
// ═══════════════════════════════════════════════════════════════════════════════════════════
// ALERTS
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Strategy alerts
alertcondition(bullish_setup, title="Polish Long Entry", message="{{ticker}} - Polish Long Entry at {{close}} | Target: " + str.tostring(bull_primary_target) + " | Stop: " + str.tostring(bull_stop_loss))
alertcondition(bearish_setup, title="Polish Short Entry", message="{{ticker}} - Polish Short Entry at {{close}} | Target: " + str.tostring(bear_primary_target) + " | Stop: " + str.tostring(bear_stop_loss))
// Exit alerts
alertcondition(strategy.position_size[1] > 0 and strategy.position_size == 0, title="Polish Long Exit", message="{{ticker}} - Polish Long Exit at {{close}}")
alertcondition(strategy.position_size[1] < 0 and strategy.position_size == 0, title="Polish Short Exit", message="{{ticker}} - Polish Short Exit at {{close}}")
// ═══════════════════════════════════════════════════════════════════════════════════════════
// PERFORMANCE METRICS
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Calculate performance metrics
var int total_trades = 0
var int winning_trades = 0
var float total_pnl = 0.0
if strategy.closedtrades > total_trades
total_trades := strategy.closedtrades
if strategy.closedtrades.profit(strategy.closedtrades - 1) > 0
winning_trades := winning_trades + 1
total_pnl := strategy.netprofit
// Calculate win rate
win_rate = total_trades > 0 ? (winning_trades / total_trades) * 100 : 0
// ═══════════════════════════════════════════════════════════════════════════════════════════
// LABELS AND STATUS
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Current position status
pos_text = strategy.position_size > 0 ? "LONG" : strategy.position_size < 0 ? "SHORT" : "FLAT"
pos_color = strategy.position_size > 0 ? color.green : strategy.position_size < 0 ? color.red : color.gray
// Performance status
perf_text = "Trades: " + str.tostring(total_trades) + " | WR: " + str.tostring(math.round(win_rate, 1)) + "% | PnL: $" + str.tostring(math.round(total_pnl, 2))
// Session and stack status
session_text = in_session ? "IN SESSION" : "OUT OF SESSION"
stack_text = bullish_stack ? "BULL STACK" : bearish_stack ? "BEAR STACK" : "NEUTRAL"
// Add labels
if barstate.islast
label.new(bar_index, high + (atr_value * 3), text=pos_text, color=pos_color, textcolor=color.white, style=label.style_label_down, size=size.normal)
label.new(bar_index, high + (atr_value * 2), text=perf_text, color=color.blue, textcolor=color.white, style=label.style_label_down, size=size.small)
label.new(bar_index, high + (atr_value * 1), text=session_text, color=in_session ? color.yellow : color.gray, textcolor=color.white, style=label.style_label_down, size=size.small)
label.new(bar_index, high + (atr_value * 0), text=stack_text, color=bullish_stack ? color.green : bearish_stack ? color.red : color.gray, textcolor=color.white, style=label.style_label_down, size=size.small)
// ═══════════════════════════════════════════════════════════════════════════════════════════
// TABLE DISPLAY
// ═══════════════════════════════════════════════════════════════════════════════════════════
// Create performance table
if barstate.islast
var table perf_table = table.new(position.bottom_right, 2, 5, bgcolor=color.white, border_width=1)
table.cell(perf_table, 0, 0, text="Metric", bgcolor=color.blue, text_color=color.white, text_size=size.small)
table.cell(perf_table, 1, 0, text="Value", bgcolor=color.blue, text_color=color.white, text_size=size.small)
table.cell(perf_table, 0, 1, text="Position", bgcolor=color.white, text_color=color.black, text_size=size.small)
table.cell(perf_table, 1, 1, text=pos_text, bgcolor=pos_color, text_color=color.white, text_size=size.small)
table.cell(perf_table, 0, 2, text="Total Trades", bgcolor=color.white, text_color=color.black, text_size=size.small)
table.cell(perf_table, 1, 2, text=str.tostring(total_trades), bgcolor=color.gray, text_color=color.white, text_size=size.small)
table.cell(perf_table, 0, 3, text="Win Rate", bgcolor=color.white, text_color=color.black, text_size=size.small)
table.cell(perf_table, 1, 3, text=str.tostring(math.round(win_rate, 1)) + "%", bgcolor=win_rate >= 50 ? color.green : color.red, text_color=color.white, text_size=size.small)
table.cell(perf_table, 0, 4, text="Net P&L", bgcolor=color.white, text_color=color.black, text_size=size.small)
table.cell(perf_table, 1, 4, text="$" + str.tostring(math.round(total_pnl, 2)), bgcolor=total_pnl >= 0 ? color.green : color.red, text_color=color.white, text_size=size.small)
Show all 413 lines