by damianpitt· code credited to Capital41 | MIT License
This strategy plots an EMA or SMA on the price chart and enters long when price is above the average and both RSI and Williams %R meet the long condition, or short when price is below the average and both oscillators meet the short condition.
// Copyright (c) 2026 Capital41 | MIT License
// C41 CORE STRATEGY v2 (MA + RSI + W%R)
// What it does:
// - Minimal strategy using only moving average trend, RSI, and Williams %R.
// - Enters when all three conditions align in the same direction.
// - Exits on MA failure, opposite setup, or ATR-based TP/SL.
// - Designed as a simpler baseline next to Fusion strategies.
//
// v2 changes:
// - FIXED: Commission increased from 0.01% to 0.075% (realistic for crypto exchanges).
// - ADDED: ATR-based stop-loss and take-profit with entry-locked ATR values.
// The ATR is captured at entry time and does NOT shift on subsequent bars.
// - ADDED: Configurable risk-reward ratio for TP target.
//
// TradingView setup:
// 1) Open TradingView -> Pine Editor.
// 2) Paste this script, Save, and Add to chart.
// 3) Use 30m on BTC or US stocks.
// 4) Keep defaults first, then tune MA/RSI/W%R thresholds.
//
// Usage guide (30m):
// - Long entry: close above MA + RSI long condition + W%R long condition.
// - Short entry: close below MA + RSI short condition + W%R short condition.
// - Exit when trend fails, opposite setup appears, or ATR TP/SL is hit.
//@version=6
strategy("C41 Core Strategy v2", overlay = true, pyramiding = 0,
initial_capital = 10000, commission_type = strategy.commission.percent, commission_value = 0.075)
// Inputs
maType = input.string("EMA", "MA type", options = ["EMA", "SMA"])
maLen = input.int(50, "MA length", minval = 5)
showMA = input.bool(true, "Show MA")
rsiLen = input.int(14, "RSI length", minval = 2)
rsiOB = input.int(65, "RSI overbought", minval = 50, maxval = 90)
rsiOS = input.int(35, "RSI oversold", minval = 10, maxval = 50)
wrLen = input.int(14, "Williams %R length", minval = 2)
wrOB = input.float(-20.0, "W%R overbought")
wrOS = input.float(-80.0, "W%R oversold")
requireTurn = input.bool(true, "Require RSI/W%R turn")
// v2: Risk management inputs
useAtrRisk = input.bool(true, "Use ATR TP/SL")
atrLen = input.int(14, "ATR length", minval = 1)
atrStopMult = input.float(2.0, "ATR stop multiplier", minval = 0.2, maxval = 10.0)
rrTarget = input.float(1.5, "Risk-reward target", minval = 0.5, maxval = 10.0)
showSignals = input.bool(true, "Show entry markers")
showBg = input.bool(true, "Show setup background")
showBadge = input.bool(true, "Show status badge")
colorBull = color.new(color.lime, 0)
colorBear = color.new(color.red, 0)
colorNeutral = color.new(color.gray, 80)
// Williams %R helper
wr_manual(_high, _low, _close, _len) =>
hh = ta.highest(_high, _len)
ll = ta.lowest(_low, _len)
rng = hh - ll
rng == 0 ? -50.0 : (hh - _close) / rng * -100
// Core metrics
ma = maType == "EMA" ? ta.ema(close, maLen) : ta.sma(close, maLen)
trendLong = close > ma
trendShort = close < ma
plot(showMA ? ma : na, title = "MA", color = trendLong ? colorBull : trendShort ? colorBear : color.new(color.gray, 0), linewidth = 2)
rsi = ta.rsi(close, rsiLen)
rsiLongTurn = rsi[1] < rsiOS and rsi > rsi[1]
rsiShortTurn = rsi[1] > rsiOB and rsi < rsi[1]
rsiLong = requireTurn ? rsiLongTurn : rsi < rsiOS
rsiShort = requireTurn ? rsiShortTurn : rsi > rsiOB
wr = wr_manual(high, low, close, wrLen)
wrLongTurn = wr[1] < wrOS and wr > wr[1]
wrShortTurn = wr[1] > wrOB and wr < wr[1]
wrLong = requireTurn ? wrLongTurn : wr < wrOS
wrShort = requireTurn ? wrShortTurn : wr > wrOB
// v2: ATR for risk management
atr = ta.atr(atrLen)
// Entry and exit logic
longSetup = trendLong and rsiLong and wrLong
shortSetup = trendShort and rsiShort and wrShort
longEntry = barstate.isconfirmed and longSetup and not longSetup[1]
shortEntry = barstate.isconfirmed and shortSetup and not shortSetup[1]
// v2: Lock ATR at entry time so stop/target levels don't shift bar-to-bar
var float entryAtr = na
if longEntry
entryAtr := atr
strategy.entry("Long", strategy.long)
if shortEntry
entryAtr := atr
strategy.entry("Short", strategy.short)
// Signal-based exits
longExit = strategy.position_size > 0 and (trendShort or shortSetup)
shortExit = strategy.position_size < 0 and (trendLong or longSetup)
if longExit
strategy.close("Long", comment = "C41 Exit")
if shortExit
strategy.close("Short", comment = "C41 Exit")
// v2: ATR-based TP/SL with entry-locked ATR
if useAtrRisk and strategy.position_size != 0 and not na(entryAtr)
atrStop = entryAtr * atrStopMult
atrTP = atrStop * rrTarget
if strategy.position_size > 0
strategy.exit("Long TP/SL", "Long",
stop = strategy.position_avg_price - atrStop,
limit = strategy.position_avg_price + atrTP)
if strategy.position_size < 0
strategy.exit("Short TP/SL", "Short",
stop = strategy.position_avg_price + atrStop,
limit = strategy.position_avg_price - atrTP)
plotshape(showSignals and longEntry, title = "C41 Long Entry", style = shape.triangleup,
location = location.belowbar, color = colorBull, size = size.small, text = "L")
plotshape(showSignals and shortEntry, title = "C41 Short Entry", style = shape.triangledown,
location = location.abovebar, color = colorBear, size = size.small, text = "S")
bgcolor(showBg ? (longSetup ? color.new(colorBull, 90) : shortSetup ? color.new(colorBear, 90) : na) : na)
// Status badge
var table status = table.new(position.bottom_left, 4, 1, border_width = 1)
if barstate.islast
if showBadge
maText = trendLong ? " MA+ " : trendShort ? " MA- " : " MA0 "
rsiText = rsiLong ? " RSI+ " : rsiShort ? " RSI- " : " RSI0 "
wrText = wrLong ? " WR+ " : wrShort ? " WR- " : " WR0 "
sigText = longSetup ? " SET L " : shortSetup ? " SET S " : " SET - "
table.cell(status, 0, 0, maText, bgcolor = trendLong ? color.new(colorBull, 70) : trendShort ? color.new(colorBear, 70) : colorNeutral, text_color = color.white, text_size = size.tiny)
table.cell(status, 1, 0, rsiText, bgcolor = rsiLong ? color.new(colorBull, 70) : rsiShort ? color.new(colorBear, 70) : colorNeutral, text_color = color.white, text_size = size.tiny)
table.cell(status, 2, 0, wrText, bgcolor = wrLong ? color.new(colorBull, 70) : wrShort ? color.new(colorBear, 70) : colorNeutral, text_color = color.white, text_size = size.tiny)
table.cell(status, 3, 0, sigText, bgcolor = longSetup ? color.new(colorBull, 60) : shortSetup ? color.new(colorBear, 60) : colorNeutral, text_color = color.white, text_size = size.tiny)
else
for i = 0 to 3
table.cell(status, i, 0, "", bgcolor = color.new(color.black, 100), text_color = color.new(color.black, 100))
alertcondition(longEntry, title = "C41 Long", message = "C41 Strategy: long entry on {{ticker}} ({{interval}})")
alertcondition(shortEntry, title = "C41 Short", message = "C41 Strategy: short entry on {{ticker}} ({{interval}})")
alertcondition(longExit, title = "C41 Long Exit", message = "C41 Strategy: long exit on {{ticker}} ({{interval}})")
alertcondition(shortExit, title = "C41 Short Exit", message = "C41 Strategy: short exit on {{ticker}} ({{interval}})")
Overview
An optional turn filter requires those oscillators to reverse before entry. It exits when the moving-average trend fails, the opposite setup appears, or an entry-locked ATR stop and risk-reward target is hit. Settings change average type and length, oscillator thresholds, and ATR risk. It is aimed at 30-minute charts on Bitcoin and US stocks.
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
MA type
string
EMA
maType
MA length
int
50
maLen
Show MA
bool
true
showMA
RSI length
int
14
rsiLen
RSI overbought
int
65
rsiOB
RSI oversold
int
35
rsiOS
Williams %R length
int
14
wrLen
W%R overbought
float
-20.0
wrOB
W%R oversold
float
-80.0
wrOS
Require RSI/W%R turn
bool
true
requireTurn
Use ATR TP/SL
bool
true
useAtrRisk
ATR length
int
14
atrLen
Show all 17 settings
Setting
Type
Default
Variable
ATR stop multiplier
float
2.0
atrStopMult
Risk-reward target
float
1.5
rrTarget
Show entry markers
bool
true
showSignals
Show setup background
bool
true
showBg
Show status badge
bool
true
showBadge
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.
This strategy overlays a trend moving average and Supertrend bands directly on the price chart while calculating Stochastic RSI values internally. Long positions trigger when price exceeds the moving average, Supertrend signals bullish momentum, and the StochR
This trading strategy combines three Exponential Moving Averages (8, 14, and 50 periods by default) with Stochastic RSI and Average True Range (ATR). It enters a long position when EMA 1 is above EMA 2, EMA 2 is above EMA 3, and the Stochastic RSI %K line cros
This strategy combines exponential moving averages (EMA 9, 21, 50), RSI, MACD, and Supertrend indicators to enter long positions. It triggers trades using six dynamic setups based on momentum breakouts, EMA crossovers, and pullbacks. Position sizing is compute
CombinedBinHAndClucV6 is a trading strategy based on the popular BinHV45 and ClucMay72018 algorithms. It calculates dual Bollinger Bands, Exponential Moving Averages, Relative Strength Index, Average True Range, and volume metrics across primary and one-hour h
This strategy calculates Bollinger Bands, a configurable moving average slope, Stochastic RSI, ATR, and ADX directly on the price chart. It evaluates trend bias and momentum conditions to generate long and short swing entries using percent-of-equity sizing. Th
This strategy trades long and short on the price chart using a multi-timeframe TradingLatino setup. It requires EMA 10 to cross or sit above or below EMA 55 on the one-hour, four-hour, and daily charts, together with a positive ADX slope, a directional monitor