Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Indicators to Strategy Blueprint

The provided Pine Script is a visual tool designed to identify the highest and lowest price points within the user’s visible chart area. This functionality, relying on chart.left_visible_bar_time, is inherently subjective and cannot be used for automated execution, as a server-side algorithm has no concept of a “visible screen.”

To transform this into a professional trading algorithm, we must first translate its core intent—trading based on recent extremes—into an objective, quantifiable rule. We will replace the “visible range” with a fixed lookbackPeriod. This creates a classic “Donchian Channel” or “Price Channel” breakout strategy, which we will then build into a robust execution framework.

1. Execution Triggers (Entry & Direction)

The strategy will be a breakout system. We will enter a long position when the price breaks above the highest high of a defined lookback period and a short position when it breaks below the lowest low.

2. Multi-Tiered Exit Logic

A professional strategy never enters a trade without a pre-defined exit plan. We will implement a three-pronged exit logic.

3. Capital Allocation & Risk Management

Position sizing is arguably more important than the entry signal itself. We will use a fixed-fractional risk model.

4. Implementation Snippet (Pine Logic)

This snippet demonstrates the transformation from the visual indicator to a professional strategy, incorporating the principles above.

//@version=5
// TRANSITIONED FROM A VISUAL TOOL TO AN AUTOMATED EXECUTION STRATEGY
strategy("Price Channel Breakout - Pro Framework", 
     overlay=true, 
     initial_capital=100000,
     commission_type=strategy.commission.percent,
     commission_value=0.075, // Example: 0.075% per trade
     slippage=2, // Example: 2 ticks of slippage per order
     process_orders_on_close=true, // For robust, non-repainting execution
     pyramiding=0) // Disable adding to positions for risk control

// --- Inputs ---
var lookbackPeriod = input.int(50, title="Channel Lookback Period", minval=10)
var atrLength = input.int(14, title="ATR Length", minval=1)
var stopAtrMult = input.float(2.5, title="Stop Loss ATR Multiplier", minval=0.1, step=0.1)
var trailAtrMult = input.float(3.0, title="Trailing Stop ATR Multiplier", minval=0.1, step=0.1)
var riskPercent = input.float(1.0, title="Risk per Trade (%)", minval=0.1, maxval=10.0)
var maxBarsInTrade = input.int(100, title="Max Bars in Stagnant Trade", minval=1)

// --- Core Calculations ---
float channelHigh = ta.highest(high, lookbackPeriod)
float channelLow = ta.lowest(low, lookbackPeriod)
float atr = ta.atr(atrLength)

// --- Entry Conditions ---
bool longCondition = ta.crossover(close, channelHigh[1])
bool shortCondition = ta.crossunder(close, channelLow[1])

// --- Position Sizing & Risk Management ---
float pointValue = syminfo.pointvalue
float riskPerShare = atr * stopAtrMult
float riskInCurrency = riskPerShare * pointValue
float capitalToRisk = (riskPercent / 100.0) * strategy.equity
int positionSize = math.max(1, math.floor(capitalToRisk / riskInCurrency))

// --- Exit Conditions ---
// Time-based exit for stagnant trades
bool timeExitCondition = strategy.opentrades > 0 and (bar_index - strategy.opentrades.entry_bar_index(0)) > maxBarsInTrade

// --- Execution Logic ---
if (longCondition)
    // Close any existing short position and go long
    strategy.entry("Breakout", strategy.long, qty=positionSize, comment="Long Entry")
    
if (shortCondition)
    // Close any existing long position and go short
    strategy.entry("Breakout", strategy.short, qty=positionSize, comment="Short Entry")

// --- Exit Order Management ---
if (strategy.opentrades > 0)
    // Define stop loss and trailing stop levels for the current open trade
    float stopLossLevel = strategy.opentrades.entry_price(0) + (strategy.opentrades.direction(0) == strategy.long ? -riskPerShare : riskPerShare)
    float trailOffset = atr * trailAtrMult
    
    // Submit a versatile exit order that handles initial stop and dynamic trailing
    strategy.exit("Exit SL/Trail", from_entry="Breakout", stop=stopLossLevel, trail_price=close, trail_offset=trailOffset)

// Close position if it's stagnant
strategy.close("Breakout", when=timeExitCondition, comment="Time Exit")

// --- Visuals ---
plot(channelHigh[1], "Channel High", color=color.new(color.red, 50))
plot(channelLow[1], "Channel Low", color=color.new(color.green, 50))