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

Here is the architectural blueprint for transforming the KNN Machine Learning Momentum Indicator into a production-grade automated trading strategy.

1. Execution Triggers (Entry & Direction)

The provided indicator generates signals based on a KNN model’s probability output. To trade these signals effectively, we must define precise, non-repainting entry conditions that account for market noise and trend context.

2. Multi-Tiered Exit Logic

A profitable entry is meaningless without a disciplined exit strategy. We will replace the non-existent exit logic with a three-pronged approach: an initial volatility-based stop, a dynamic trailing mechanism, and a time-based kill switch.

3. Capital Allocation & Risk Management

Professional trading is synonymous with professional risk management. We will size every position to risk a fixed percentage of the total account equity, ensuring no single trade can cause catastrophic losses.

4. Implementation Snippet (Pine Logic)

This snippet demonstrates the architectural transition from an indicator to a strategy, incorporating the principles of professional execution.

//@version=5
// --- STRATEGY DECLARATION ---
// Note: initial_capital, slippage, and commission are critical for realistic backtests.
strategy("Production KNN Execution Engine", 
     overlay=true, 
     process_orders_on_close=true,
     initial_capital=100000,
     default_qty_type=strategy.fixed, // We will calculate qty manually
     commission_type=strategy.commission.percent,
     commission_value=0.04, // Realistic broker commission
     slippage=2) // Slippage in ticks

// --- STRATEGY-SPECIFIC INPUTS ---
group_risk = "🛡️ Risk & Trade Management"
risk_per_trade_pct = input.float(1.0, "Risk Per Trade (%)", group=group_risk, minval=0.1, maxval=5.0)
atr_period         = input.int(14, "ATR Period", group=group_risk)
atr_multiplier     = input.float(2.0, "ATR Stop Multiplier", group=group_risk)
use_trend_filter   = input.bool(true, "Enable Trend Filter", group=group_risk)
use_time_exit      = input.bool(true, "Enable Time-Based Exit", group=group_risk)
stagnation_bars    = input.int(25, "Max Bars Before Stagnation Exit", group=group_risk)

// ... [Paste the entire original script from line 5 to the 'SIGNAL GENERATION' section] ...
// ... [This includes constants, inputs, feature engineering, PCA, and KNN core engine] ...

// ==========================================
// --- SIGNAL GENERATION (FROM ORIGINAL SCRIPT) ---
// ==========================================
bool raw_long_signal = ta.crossover(prob_up, prob_threshold)
bool raw_short_signal = ta.crossover(prob_down, prob_threshold)

// EMA Trend Filter
ema = ta.ema(close, ema_len)
ema_bull = close > ema
ema_bear = close <= ema

// --- FINAL EXECUTION TRIGGERS ---
bool long_entry_condition = raw_long_signal and (ema_bull or not use_trend_filter)
bool short_entry_condition = raw_short_signal and (ema_bear or not use_trend_filter)

// ==========================================
// --- RISK & POSITION SIZING ENGINE ---
// ==========================================
float atr_val = ta.atr(atr_period)

// Calculate Stop Loss Price *before* entry to determine size
float long_stop_price = close - (atr_val * atr_multiplier)
float short_stop_price = close + (atr_val * atr_multiplier)

// Risk-based position sizing calculation
float risk_per_unit = syminfo.pointvalue * atr_val * atr_multiplier
float risk_amount = (risk_per_trade_pct / 100) * strategy.equity
float position_size = risk_amount / risk_per_unit
position_size := math.max(position_size, 0.00001) // Ensure size is not zero

// ==========================================
// --- TRADE EXECUTION & MANAGEMENT ---
// ==========================================
// --- ENTRY LOGIC ---
if (long_entry_condition and strategy.position_size <= 0)
    // Close any existing short and go long
    strategy.entry("KNN Long", strategy.long, qty=position_size, comment="Entry Long")
    // We use strategy.exit to place the stop loss order immediately
    strategy.exit("SL/TP Long", from_entry="KNN Long", loss=long_stop_price)

if (short_entry_condition and strategy.position_size >= 0)
    // Close any existing long and go short
    strategy.entry("KNN Short", strategy.short, qty=position_size, comment="Entry Short")
    // We use strategy.exit to place the stop loss order immediately
    strategy.exit("SL/TP Short", from_entry="KNN Short", loss=short_stop_price)

// --- TIME-BASED EXIT LOGIC ---
bool in_long_trade = strategy.position_size > 0
bool in_short_trade = strategy.position_size < 0
int bars_since_entry = bar_index - strategy.opentrades.entry_bar_index(strategy.opentrades - 1)

if (use_time_exit and (in_long_trade or in_short_trade) and bars_since_entry >= stagnation_bars)
    strategy.close_all(comment="Stagnation Exit")

// Note: The multi-stage TP and dynamic trailing logic is more complex and often
// requires a state machine to manage partial exits. The above provides the robust
// foundation (entry + initial stop). A full implementation would expand the 
// strategy.exit calls or use separate strategy.close calls based on profit levels.