OPEN-SOURCE SCRIPT
Penguin Volatility State Strategy

Penguin Volatility State Strategy
This document provides details on the "Penguin Volatility State" trading strategy for the TradingView platform. It is a strategy designed to identify different market conditions and execute trades based on momentum and volatility.
Overview
This strategy uses a combination of several popular indicators, including Bollinger Bands (BB), Keltner Channels (KC), Exponential Moving Averages (EMAs), and the Relative Strength Index (RSI), to classify the market into four main states, represented by different colors on the chart:
Green: Strong uptrend.
Red: Strong downtrend.
Yellow: A pullback or consolidation phase within an uptrend (potential reversal signal).
Blue: A pullback or consolidation phase within a downtrend (potential reversal signal).
The goal of the strategy is to enter trades in the direction of the strong trend (Green and Red states) and allow the user to filter out noise during sideways market conditions (Yellow and Blue states).
How the Indicators Work
Bollinger Bands & Keltner Channels: Used to measure market volatility. The difference between the width of the BB and KC (diff) is used to calculate an RSI to measure the "acceleration" of volatility.
EMAs (Fast & Slow): Used to determine the primary trend direction. If the fast EMA is above the slow EMA, it is considered an uptrend, and vice versa.
RSI of Diff: This is the core component for measuring the momentum of volatility. When this RSI value is above its own moving average, it signifies strong momentum, which is a key condition for entering a trade.
Filters and Strategy Logic
Users can customize the strategy's behavior through three main filters:
Filter Sideways Markets (RULE 1): If enabled, the strategy will only enter trades in the Green state (for Longs) and Red state (for Shorts), avoiding sideways conditions (Yellow and Blue).
Trade Only on Strong Momentum (RULE 2): If enabled, the strategy will only enter trades when there is strong momentum (when the RSI of Diff is above its moving average).
Enter/Exit on Exact Transition (RULE 3): If enabled, the strategy will enter and exit orders only at the exact crossover of the RSI of Diff and its moving average. This can lead to more precise entries/exits but may also cause some opportunities to be missed.
Inputs
BB/KC Length: The number of bars used to calculate Bollinger Bands and Keltner Channels.
BB Multiplier: The standard deviation multiplier for the Bollinger Bands.
KC Multiplier: The ATR multiplier for the Keltner Channels.
Fast EMA Length: The number of bars for the fast EMA.
Slow EMA Length: The number of bars for the slow EMA.
RSI of Diff Length: The number of bars for the RSI of diff.
SMA of RSI Length: The number of bars for the moving average of the RSI of Diff.
Trade Direction: Choose to trade Long Only, Short Only, or Both.
Filters (RULE 1, 2, 3): Enable/disable the filters as described above.
Pine Script Code
Here is the full code for the strategy. You can copy and paste it into the Pine Editor on TradingView.
//version=5
strategy("Penguin Volatility State Strategy", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_value=0.075)
// ===================================================================
// INPUTS
// ===================================================================
// --- Indicator Settings ---
string group_indicators = "Indicator Settings"
bb_len = input.int(20, "BB/KC Length", group=group_indicators)
bb_mult = input.float(2.0, "BB Multiplier", group=group_indicators)
kc_mult = input.float(2.0, "KC Multiplier", group=group_indicators)
ema_fast_len = input.int(12, "Fast EMA Length", group=group_indicators)
ema_slow_len = input.int(26, "Slow EMA Length", group=group_indicators)
rsi_diff_len = input.int(14, "RSI of Diff Length", group=group_indicators)
rsi_avg_len = input.int(7, "SMA of RSI Length", group=group_indicators)
// --- Strategy Filter Settings ---
string group_filters = "Strategy Filters"
trade_direction = input.string("Both", "Trade Direction", options=["Both", "Long Only", "Short Only"], group=group_filters)
use_regime_filter = input.bool(true, "RULE 1: Filter Sideways Markets (Yellow & Blue)?", group=group_filters)
use_strength_filter = input.bool(true, "RULE 2: Trade Only on Strong Momentum (RSI Accel)?", group=group_filters)
use_timing_filter = input.bool(false, "RULE 3: Enter/Exit on Exact Transition?", group=group_filters)
// ===================================================================
// INDICATOR CALCULATIONS
// ===================================================================
// --- Bollinger Bands & Keltner Channel ---
basisBB = ta.sma(close, bb_len)
dev = bb_mult * ta.stdev(close, bb_len)
upperBB = basisBB + dev
lowerBB = basisBB - dev
atr = ta.atr(bb_len)
upperKC = basisBB + kc_mult * atr
lowerKC = basisBB - kc_mult * atr
// --- Diff & RSI of Diff Calculation ---
diff = (upperBB - upperKC) / upperKC * 100
diff_change = ta.change(diff)
up = ta.rma(math.max(diff_change, 0), rsi_diff_len)
down = ta.rma(-math.min(diff_change, 0), rsi_diff_len)
rsi_diff = down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))
rsi_diff2 = ta.sma(rsi_diff, rsi_avg_len)
// --- EMAs for Market State ---
fast_ma = ta.ema(close, ema_fast_len)
slow_ma = ta.ema(close, ema_slow_len)
apcdc = ta.ema(ohlc4, 2)
// ===================================================================
// STATE DEFINITIONS
// ===================================================================
isBullishTrend = fast_ma > slow_ma
isBearishTrend = fast_ma < slow_ma
isGreen = isBullishTrend and apcdc > fast_ma
isRed = isBearishTrend and apcdc < fast_ma
isYellow = isBullishTrend and apcdc < fast_ma
isBlue = isBearishTrend and apcdc > fast_ma
isRsiAccel = rsi_diff > rsi_diff2
// ===================================================================
// STRATEGY LOGIC
// ===================================================================
// --- Apply Filters to define tradable conditions ---
can_long_base = use_regime_filter ? isGreen : (isGreen or isYellow)
can_short_base = use_regime_filter ? isRed : (isRed or isBlue)
long_condition = use_strength_filter ? can_long_base and isRsiAccel : can_long_base
short_condition = use_strength_filter ? can_short_base and isRsiAccel : can_short_base
entry_long_timing = ta.crossunder(rsi_diff2, rsi_diff) and can_long_base
exit_long_timing = ta.crossunder(rsi_diff, rsi_diff2)
entry_short_timing = ta.crossunder(rsi_diff2, rsi_diff) and can_short_base
exit_short_timing = ta.crossunder(rsi_diff, rsi_diff2)
// --- Determine Final Entry/Exit Conditions ---
final_entry_long = use_timing_filter ? entry_long_timing : long_condition
final_exit_long = use_timing_filter ? exit_long_timing : not long_condition
final_entry_short = use_timing_filter ? entry_short_timing : short_condition
final_exit_short = use_timing_filter ? exit_short_timing : not short_condition
// --- Check Trade Direction permission ---
allow_long = trade_direction == "Both" or trade_direction == "Long Only"
allow_short = trade_direction == "Both" or trade_direction == "Short Only"
// --- Execute Trades ---
if (final_entry_long and allow_long)
strategy.entry("Long", strategy.long)
if (final_exit_long)
strategy.close("Long")
if (final_entry_short and allow_short)
strategy.entry("Short", strategy.short)
if (final_exit_short)
strategy.close("Short")
// ===================================================================
// VISUALIZATION
// ===================================================================
bgcolor(isGreen ? color.new(color.green, 85) : isRed ? color.new(color.red, 85) : isYellow ? color.new(color.yellow, 85) : isBlue ? color.new(color.blue, 85) : na)
Disclaimer
This strategy is provided for educational and informational purposes only and is not financial advice.
Past performance from backtesting does not guarantee future results.
Trading involves risk. Investors should conduct their own research and exercise due diligence before making any investment decisions and should manage their own risk.
This document provides details on the "Penguin Volatility State" trading strategy for the TradingView platform. It is a strategy designed to identify different market conditions and execute trades based on momentum and volatility.
Overview
This strategy uses a combination of several popular indicators, including Bollinger Bands (BB), Keltner Channels (KC), Exponential Moving Averages (EMAs), and the Relative Strength Index (RSI), to classify the market into four main states, represented by different colors on the chart:
Green: Strong uptrend.
Red: Strong downtrend.
Yellow: A pullback or consolidation phase within an uptrend (potential reversal signal).
Blue: A pullback or consolidation phase within a downtrend (potential reversal signal).
The goal of the strategy is to enter trades in the direction of the strong trend (Green and Red states) and allow the user to filter out noise during sideways market conditions (Yellow and Blue states).
How the Indicators Work
Bollinger Bands & Keltner Channels: Used to measure market volatility. The difference between the width of the BB and KC (diff) is used to calculate an RSI to measure the "acceleration" of volatility.
EMAs (Fast & Slow): Used to determine the primary trend direction. If the fast EMA is above the slow EMA, it is considered an uptrend, and vice versa.
RSI of Diff: This is the core component for measuring the momentum of volatility. When this RSI value is above its own moving average, it signifies strong momentum, which is a key condition for entering a trade.
Filters and Strategy Logic
Users can customize the strategy's behavior through three main filters:
Filter Sideways Markets (RULE 1): If enabled, the strategy will only enter trades in the Green state (for Longs) and Red state (for Shorts), avoiding sideways conditions (Yellow and Blue).
Trade Only on Strong Momentum (RULE 2): If enabled, the strategy will only enter trades when there is strong momentum (when the RSI of Diff is above its moving average).
Enter/Exit on Exact Transition (RULE 3): If enabled, the strategy will enter and exit orders only at the exact crossover of the RSI of Diff and its moving average. This can lead to more precise entries/exits but may also cause some opportunities to be missed.
Inputs
BB/KC Length: The number of bars used to calculate Bollinger Bands and Keltner Channels.
BB Multiplier: The standard deviation multiplier for the Bollinger Bands.
KC Multiplier: The ATR multiplier for the Keltner Channels.
Fast EMA Length: The number of bars for the fast EMA.
Slow EMA Length: The number of bars for the slow EMA.
RSI of Diff Length: The number of bars for the RSI of diff.
SMA of RSI Length: The number of bars for the moving average of the RSI of Diff.
Trade Direction: Choose to trade Long Only, Short Only, or Both.
Filters (RULE 1, 2, 3): Enable/disable the filters as described above.
Pine Script Code
Here is the full code for the strategy. You can copy and paste it into the Pine Editor on TradingView.
//version=5
strategy("Penguin Volatility State Strategy", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_value=0.075)
// ===================================================================
// INPUTS
// ===================================================================
// --- Indicator Settings ---
string group_indicators = "Indicator Settings"
bb_len = input.int(20, "BB/KC Length", group=group_indicators)
bb_mult = input.float(2.0, "BB Multiplier", group=group_indicators)
kc_mult = input.float(2.0, "KC Multiplier", group=group_indicators)
ema_fast_len = input.int(12, "Fast EMA Length", group=group_indicators)
ema_slow_len = input.int(26, "Slow EMA Length", group=group_indicators)
rsi_diff_len = input.int(14, "RSI of Diff Length", group=group_indicators)
rsi_avg_len = input.int(7, "SMA of RSI Length", group=group_indicators)
// --- Strategy Filter Settings ---
string group_filters = "Strategy Filters"
trade_direction = input.string("Both", "Trade Direction", options=["Both", "Long Only", "Short Only"], group=group_filters)
use_regime_filter = input.bool(true, "RULE 1: Filter Sideways Markets (Yellow & Blue)?", group=group_filters)
use_strength_filter = input.bool(true, "RULE 2: Trade Only on Strong Momentum (RSI Accel)?", group=group_filters)
use_timing_filter = input.bool(false, "RULE 3: Enter/Exit on Exact Transition?", group=group_filters)
// ===================================================================
// INDICATOR CALCULATIONS
// ===================================================================
// --- Bollinger Bands & Keltner Channel ---
basisBB = ta.sma(close, bb_len)
dev = bb_mult * ta.stdev(close, bb_len)
upperBB = basisBB + dev
lowerBB = basisBB - dev
atr = ta.atr(bb_len)
upperKC = basisBB + kc_mult * atr
lowerKC = basisBB - kc_mult * atr
// --- Diff & RSI of Diff Calculation ---
diff = (upperBB - upperKC) / upperKC * 100
diff_change = ta.change(diff)
up = ta.rma(math.max(diff_change, 0), rsi_diff_len)
down = ta.rma(-math.min(diff_change, 0), rsi_diff_len)
rsi_diff = down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))
rsi_diff2 = ta.sma(rsi_diff, rsi_avg_len)
// --- EMAs for Market State ---
fast_ma = ta.ema(close, ema_fast_len)
slow_ma = ta.ema(close, ema_slow_len)
apcdc = ta.ema(ohlc4, 2)
// ===================================================================
// STATE DEFINITIONS
// ===================================================================
isBullishTrend = fast_ma > slow_ma
isBearishTrend = fast_ma < slow_ma
isGreen = isBullishTrend and apcdc > fast_ma
isRed = isBearishTrend and apcdc < fast_ma
isYellow = isBullishTrend and apcdc < fast_ma
isBlue = isBearishTrend and apcdc > fast_ma
isRsiAccel = rsi_diff > rsi_diff2
// ===================================================================
// STRATEGY LOGIC
// ===================================================================
// --- Apply Filters to define tradable conditions ---
can_long_base = use_regime_filter ? isGreen : (isGreen or isYellow)
can_short_base = use_regime_filter ? isRed : (isRed or isBlue)
long_condition = use_strength_filter ? can_long_base and isRsiAccel : can_long_base
short_condition = use_strength_filter ? can_short_base and isRsiAccel : can_short_base
entry_long_timing = ta.crossunder(rsi_diff2, rsi_diff) and can_long_base
exit_long_timing = ta.crossunder(rsi_diff, rsi_diff2)
entry_short_timing = ta.crossunder(rsi_diff2, rsi_diff) and can_short_base
exit_short_timing = ta.crossunder(rsi_diff, rsi_diff2)
// --- Determine Final Entry/Exit Conditions ---
final_entry_long = use_timing_filter ? entry_long_timing : long_condition
final_exit_long = use_timing_filter ? exit_long_timing : not long_condition
final_entry_short = use_timing_filter ? entry_short_timing : short_condition
final_exit_short = use_timing_filter ? exit_short_timing : not short_condition
// --- Check Trade Direction permission ---
allow_long = trade_direction == "Both" or trade_direction == "Long Only"
allow_short = trade_direction == "Both" or trade_direction == "Short Only"
// --- Execute Trades ---
if (final_entry_long and allow_long)
strategy.entry("Long", strategy.long)
if (final_exit_long)
strategy.close("Long")
if (final_entry_short and allow_short)
strategy.entry("Short", strategy.short)
if (final_exit_short)
strategy.close("Short")
// ===================================================================
// VISUALIZATION
// ===================================================================
bgcolor(isGreen ? color.new(color.green, 85) : isRed ? color.new(color.red, 85) : isYellow ? color.new(color.yellow, 85) : isBlue ? color.new(color.blue, 85) : na)
Disclaimer
This strategy is provided for educational and informational purposes only and is not financial advice.
Past performance from backtesting does not guarantee future results.
Trading involves risk. Investors should conduct their own research and exercise due diligence before making any investment decisions and should manage their own risk.
Skrip sumber terbuka
Dalam semangat sebenar TradingView, pencipta skrip ini telah menjadikannya sumber terbuka supaya pedagang dapat menilai dan mengesahkan kefungsiannya. Terima kasih kepada penulis! Walaupun anda boleh menggunakannya secara percuma, ingat bahawa menerbitkan semula kod ini adalah tertakluk kepada Peraturan Dalaman kami.
Penafian
Maklumat dan penerbitan adalah tidak dimaksudkan untuk menjadi, dan tidak membentuk, nasihat untuk kewangan, pelaburan, perdagangan dan jenis-jenis lain atau cadangan yang dibekalkan atau disahkan oleh TradingView. Baca dengan lebih lanjut di Terma Penggunaan.
Skrip sumber terbuka
Dalam semangat sebenar TradingView, pencipta skrip ini telah menjadikannya sumber terbuka supaya pedagang dapat menilai dan mengesahkan kefungsiannya. Terima kasih kepada penulis! Walaupun anda boleh menggunakannya secara percuma, ingat bahawa menerbitkan semula kod ini adalah tertakluk kepada Peraturan Dalaman kami.
Penafian
Maklumat dan penerbitan adalah tidak dimaksudkan untuk menjadi, dan tidak membentuk, nasihat untuk kewangan, pelaburan, perdagangan dan jenis-jenis lain atau cadangan yang dibekalkan atau disahkan oleh TradingView. Baca dengan lebih lanjut di Terma Penggunaan.