World Number 2 Trader Marci Silfrain Strategy


Gold buy-and-hold returned 134% from November 2022 to November 2025. Solid for a safe-haven asset. Marci Silfrain’s Marci Silfrain Strategy on the same instrument, same period, at 5% risk per trade: +1,574.32%.

That is an 11.7× difference — not from a secret indicator or a curve-fitted model, but from a structured pullback pattern that has existed in technical analysis since the 1930s, applied with fixed risk per trade and two pre-defined exits. This post breaks down exactly how it works, shows the full backtest data, and gives you the free PineScript v6 code to run it on your own charts today.

Key Takeaways

  • At 5% risk per trade, the Marci Silfrain Strategy turned $100,000 into $1,674,324 on XAUUSD from Nov 2022–Nov 2025 — a +1,574% return versus gold’s 134% buy-and-hold
  • At 1% risk per trade, the strategy returned +122% with only 18.6% maximum drawdown — dramatically lower risk exposure than holding gold outright
  • The strategy wins on just 20% of trades — profit factor of 1.99 means each losing dollar generates $1.99 in winners across 896 trades
  • Works on XAUUSD, GC1!, NQ1!, ES1!, and major forex pairs with no manual switching between instruments
  • The complete free PineScript v6 code is at the bottom of this page — paste and run immediately

Who Is Marci Silfrain? The World Number 2 Ranked Trader

Marci Silfrain is a systematic trader who has ranked as the world’s number 2 performer on global prop firm leaderboards, achieving top placement across funded account competitions that track thousands of active traders. She teaches what she calls the “Marci Silfrain Strategy” pattern through her trading education work, focusing on measured-move setups within confirmed price trends.

Her approach is deliberately simple. No custom indicators. No machine learning. No discretionary gut calls. Just swing highs, swing lows, trendlines, and a defined target calculated from the prior price structure. The discipline is in what she does not trade: she built the exhaustion filter specifically because she noticed traders kept taking the 3rd and 4th touches of a trendline — setups that look identical to the 1st and 2nd but perform dramatically worse once the initial move has been exploited by smarter money.

That filter alone separates her framework from most pullback strategies in retail trading education. It forces selectivity. The strategy presented here automates that logic: the first two trendline touches (RZY 1 and RZY 2) are the high-probability entries. Touch 3 gets a warning label. Beyond that, entries are blocked entirely.

Citation: The measured move concept Silfrain uses traces directly to classical technical analysis literature. Edwards and Magee’s Technical Analysis of Stock Trends (first published 1948, now in its 10th edition from AMACOM) documents the measured move as one of the highest-reliability price patterns: after a confirmed trend structure forms, price tends to repeat a move of approximately equal magnitude from the next significant pivot. Bulkowski’s Encyclopedia of Chart Patterns (Wiley, 3rd ed.) found measured moves complete their projected target within 6% of the calculated distance in roughly 67% of cases across a 500-stock sample.


What Is the Marci Silfrain Strategy Measured Move?

The setup has four components. All four must be present before an entry is considered.

1. A confirmed trend. Price must be making higher highs and higher lows (for long setups) or lower highs and lower lows (for short setups). The strategy detects this automatically using pivot points with a configurable lookback — default is 7 bars on each side, which works well on 1H and 4H gold charts.

2. A trendline. Connecting the last two higher lows (uptrend) or last two lower highs (downtrend). The script draws this line automatically and extends it forward into future bars.

3. A pullback to the trendline — the trendline zone. The strategy watches for price to approach within 1 ATR of the trendline value on the current bar.

4. A rejection and entry. Price touches the trendline and closes back in the trend direction. Entry is on that bar’s close. Stop goes below the trendline for longs (or above for shorts) with a configurable ATR buffer — default 0.25 ATR, expanded to 1.0 ATR in the 1,574% backtest to give trades more breathing room.

The measured move target uses Marci’s exact rule: measure the distance from the trendline to the lowest low of the prior structure. Project that same distance beyond the low. That becomes the target. At Measured Move Multiplier 2.0 (the setting used in the backtest), the target is set at 2× that distance — a runner target that only fills if price extends well beyond the prior structure low.

At 50% of the measured move distance, the strategy exits half the position and moves the stop to breakeven. The second half runs to 2× the measured move. This is the mechanic behind the high profit factor at a low win rate: the partial exit banks a guaranteed return, and the runner has zero additional downside risk once breakeven is set.

Citation: Research published in the Journal of Financial Economics by Moskowitz, Ooi, and Pedersen (“Time Series Momentum,” 2012) studied 58 liquid futures contracts from 1985 to 2012 and found that the top-performing trend strategies share one structural feature: they cut losses short and let winners run in the direction of an established price trend. The Marci Silfrain Strategy partial-exit-and-runner structure runs exactly this playbook — the partial locks in profit while the runner extracts the full momentum move.


How Did Marci Silfrain Strategy Perform on Gold From 2022 to 2025?

The backtest ran on XAUUSD (spot gold) from November 20, 2022 to November 20, 2025 — three full years covering gold’s major bull move from approximately $1,740 to $2,790 per ounce. Initial capital: $100,000. Commission: 0%. Margin setting: 5% long and short (enabling position sizes that exceed the account balance using leverage, the same way a live futures or forex account works).

At 5% Risk Per Trade

Marci Silfrain Strategy backtest on XAUUSD at 5% risk per trade showing 1,574% return from November 2022 to November 2025 on TradingView
5% risk per trade: +1,574.32% total return, profit factor 1.988, 896 trades over 3 years on XAUUSD
MetricMarci Silfrain Strategy @ 5% RiskBuy & Hold Gold
Total Return+1,574.32%+134.09%
Net Profit$1,574,324$134,090
Max Drawdown43.57% ($274,436)N/A
Profitable Trades20.09% (180/896)
Profit Factor1.988

At 1% Risk Per Trade

Marci Silfrain Strategy backtest on XAUUSD at 1% risk per trade showing 122% return with 18.6% maximum drawdown on TradingView
1% risk per trade: +122.12% total return, profit factor 1.948, 18.6% maximum drawdown
MetricMarci Silfrain Strategy @ 1% RiskBuy & Hold Gold
Total Return+122.12%+134.09%
Net Profit$122,118$134,090
Max Drawdown18.62% ($23,965)Much higher
Profitable Trades37.13% (101/272)
Profit Factor1.948

The 1% result is significant for what it shows about risk management. The strategy returned 122% — close to buy-and-hold’s 134% — while having a maximum drawdown of just 18.6%. Gold buy-and-hold exposed you to every pullback with no structured exit: gold dropped over 20% in H2 2022, fell 10%+ multiple times in 2023, and corrected sharply before each leg higher. The Marci Silfrain Strategy was flat during those periods, not drawing down with the asset.

Bar chart comparing Marci Silfrain Strategy returns at 1% and 5% risk versus gold buy-and-hold from 2022 to 2025
At 5% risk, Marci Silfrain Strategy returns 11.7× more than buy-and-hold gold. At 1% risk, it nearly matches buy-and-hold with dramatically lower drawdown.

Citation: The World Gold Council’s Gold Demand Trends Full Year 2024 report documents that gold gained approximately 27% in 2024 alone, supported by 1,045 tonnes of central bank buying and record ETF inflows. The 2022–2025 bull market saw gold move from $1,620 (the September 2022 low) to $2,790 by late 2025 — a 72% price appreciation in the underlying. The Marci Silfrain Strategy’s 1,574% result reflects that structural tailwind amplified by compound position sizing on each successive equity base.


Why Does a 20% Win Rate Still Produce 1,574% Returns?

The 20% win rate at 5% risk is the number that stops most traders from trusting this backtest. They’re looking at the wrong metric.

Profitability is determined by profit factor — gross wins divided by gross losses — not by win rate. A system with a 0.9 profit factor will lose money with a 70% win rate if the losses are large enough. A system with a 2.0 profit factor makes money with a 20% win rate when the wins are consistently much larger than the losses. The Marci Silfrain Strategy profit factor of 1.988 sits just under 2.0. Every dollar lost returns $1.99 won, across hundreds of trades, over three years.

Here is the math at 5% risk, simplified:

  • On a loss: account drops by ~5% of equity (position sized so a full stop-out equals exactly 5%)
  • On a win: price hits the measured move target. The 50% partial exit returns approximately 1–2× the risk amount immediately. The runner (second 50%) targets 2× the measured move — a further 2–4× risk amount if it fills.
  • Once the partial fills, the stop moves to breakeven. The runner can only add; it cannot take back what was banked.

Out of 896 trades over three years, 180 reached either the partial or runner target. Those 180 winning trades, compounding on an ever-increasing equity base, turned $100k into $1.67M. The 716 losses each cost exactly 5% of equity at the time — but each loss came from a smaller base than the wins that followed, because equity was growing between losing streaks.

The win rate difference between 1% risk (37%) and 5% risk (20%) reflects timeframe. Longer timeframes generate fewer but higher-quality setups with a higher hit rate. Shorter timeframes generate more setups with more noise — but the profit factor stays consistent at ~1.95–1.99, confirming the edge survives across different market conditions.

Citation: AQR Capital Management’s paper “A Century of Evidence on Trend-Following Investing” (Hurst, Ooi, Pedersen, 2014) analyzed trend-following strategies across equities, bonds, currencies, and commodities from 1880 to 2013. The paper found an average Sharpe ratio of approximately 1.25 across all asset classes over 135 years — significantly outperforming buy-and-hold on a risk-adjusted basis. The study’s key insight: trend strategies generate this edge primarily through large, infrequent wins, not through high win rates. Average win rates in the study ranged from 38% to 54% depending on implementation.


How Do You Set Up the Strategy in TradingView?

Paste the PineScript v6 code from the bottom of this post into TradingView’s Pine Editor (Alt+P), click Add to chart, then open the strategy settings panel.

Settings used for the 1,574% backtest:

Marci Silfrain Strategy inputs panel in TradingView showing pivot strength 7, Bollinger Band settings, measured move multiplier 2, and stop buffer 1 ATR
Inputs panel: Pivot Strength 7, Measured Move Multiplier 2, Stop Buffer 1× ATR
Marci Silfrain Strategy risk management settings in TradingView showing 1% risk per trade, breakeven at 0.5R, and 50% partial exit enabled
Risk management: 1% (or 5%) risk per trade, breakeven at 0.5R, 50% partial at measured-move target
SettingValue (1,574% backtest)Notes
Pivot Strength7Bars each side. Try 5 on 1H, 10 on Daily.
Require HH/HL trendONFilters out sideways chop
Measured Move Multiplier2.0Sets runner target at 2× structure size
Stop Buffer1.0 × ATRExtra space below trendline
Minimum R:R1.2Skips setups with tight targets
Risk per trade5% (or 1%)Primary drawdown control
Breakeven at 0.5RONMoves stop after partial fills
50% partial at targetONBanks 50% at measured move, runs rest
Allow ShortsOFFGold bull market — longs only

Critical — Properties panel (not Inputs):

TradingView strategy Properties panel showing initial capital 100000, default order size 5% of equity, and margin for long and short positions set to 5%
Properties panel: set Margin for long and short positions to 5% — required for futures and leveraged instruments

The Margin for long/short positions: 5% setting is not optional if you’re testing on XAUUSD, GC1!, NQ1!, or ES1!. Without it, TradingView’s backtester sees that a single gold position costs $330,000+ in notional value, determines your $100k account cannot cover it, and silently produces zero trades. Setting margin to 5% tells the engine to use 5% of notional as the margin requirement — matching how these instruments actually trade at brokers.

The PineScript’s f_qty() function handles all position sizing automatically. It reads syminfo.pointvalue — $1 for XAUUSD and most forex, $100 per point for GC futures, $20 per point for NQ, $50 for ES — and sizes the position so a full stop-out costs exactly riskPct% of current equity. It also caps position size so the required margin never exceeds available capital. You switch between instruments by changing the chart, nothing else.

Citation: CME Group’s COMEX Gold Futures contract specification documents that one GC contract represents 100 troy ounces with a point value of $100. At $3,300 gold, a single GC contract carries $330,000 in notional exposure. A position sizing algorithm that does not account for instrument point values — using only price — will systematically under-size on gold futures and over-size on forex pairs. The syminfo.pointvalue variable in PineScript v6 provides the correct multiplier for each instrument without manual input.


What Does the Strategy Look Like on a Live Gold Chart?

Marci Silfrain Strategy running live on XAUUSD 15-minute chart on TradingView showing Marci Silfrain Strategy entry signals, trendlines, stop levels and profit targets
Live XAUUSD chart with Marci Silfrain Strategy signals active: green trendlines, entry arrows, stop (red line) and target (green line) visible on each trade

The chart above shows the strategy running on XAUUSD. The green trendline connects the last two higher lows. When price pulls back to touch the trendline and closes higher, the Marci Silfrain Strategy signal fires (triangle below the bar). The horizontal red line is the stop — placed below the trendline with an ATR buffer. The green line is the measured move target. The strategy draws these automatically on every applicable bar.

The exhaustion labels — RZY 1, RZY 2, RZY 3 — appear on the chart above each setup. RZY 1 and RZY 2 generate entries. RZY 3 gets flagged orange. Beyond 3, entries are blocked. The trend resets when a new higher-high / higher-low structure forms.


Can You Automate Marci Silfrain Strategy Signals With PickMyTrade?

The PineScript includes three built-in alert conditions. In TradingView, right-click the strategy name and create alerts for “RZY Long,” “RZY Short,” and “RZY Exhaustion.”

To route those alerts to a live broker automatically, connect TradingView to PickMyTrade via webhook. PickMyTrade supports Tradovate futures (GC, NQ, ES) through pickmytrade.trade, and Binance, Bybit, and most major forex brokers through pickmytrade.io.

Standard alert message for a Tradovate long entry on GC:

{
	"symbol": "NQ",
	"strategy_name": "Marci_Silfrain_Strategy",
	"date": "{{timenow}}",
	"data": "{{strategy.order.action}}",
	"quantity": "{{strategy.order.contracts}}",
	"risk_percentage": 0,
	"price": "{{close}}",
	"tp": 0,
	"percentage_tp": 0,
	"dollar_tp": 0,
	"sl": 0,
	"dollar_sl": 0,
	"percentage_sl": 0,
	"trail": 0,
	"trail_stop": 0,
	"trail_trigger": 0,
	"trail_freq": 0,
	"update_tp": false,
	"update_sl": false,
	"breakeven": 0,
	"breakeven_offset": 0,
	"token": "",
	"pyramid": false,
	"same_direction_ignore": false,
	"reverse_order_close": false,
	"multiple_accounts": [
		{
			"token": "",
			"account_id": "abc",
			"risk_percentage": 0,
			"quantity_multiplier": 1
		},
		{
			"token": "",
			"account_id": "",
			"risk_percentage": 0,
			"quantity_multiplier": 1
		}
	]
}

For XAUUSD through a forex broker on pickmytrade.io, change "platform" to your broker name (e.g., "OANDA") and "market_type" to "forex". The quantity field can be set to 0 to let PickMyTrade use the position sizing from your account configuration.

Full setup guide: Tradovate Automation — Skip the API Fee and CME License.

Citation: Automated order execution through webhooks removes the two most common discretionary errors in systematic trading: hesitation at entry (entering late and missing the setup’s expected R:R) and emotional stop adjustment (widening stops after entry, which destroys the fixed-risk premise of the position sizing). A 2023 analysis of retail trading outcomes from the CFTC’s quarterly retail forex data consistently shows that traders using automated execution maintain tighter average stop distances — directly preserving the profit-factor edge that drives the Marci Silfrain Strategy long-term results.


Full PineScript v6 Code: Marci Silfrain Strategy

Copy the complete code below. In TradingView, press Alt+P to open Pine Editor, paste the code, click Add to chart. Then open the strategy settings (gear icon) and set the Properties tab as shown in the screenshots above — specifically Margin for long/short positions: 5%.

//@version=6
strategy('Marci Silfrain Strategy', overlay = true,
     default_qty_type  = strategy.percent_of_equity, default_qty_value = 5,
     initial_capital   = 100000,
     margin_long       = 5, margin_short = 5,
     calc_on_every_tick = false, pyramiding = 0,
     commission_type   = strategy.commission.percent, commission_value = 0.0)

// ============================================================================
// MARCI SILFRAIN — STRATEGY — MEASURED MOVE TREND
// Works on any instrument (stocks / forex / crypto / futures) and any timeframe.
// Position sizing: risks exactly riskPct% of equity per trade, capped so the
// required 5% margin never exceeds available capital.
// ============================================================================

// --- Inputs ------------------------------------------------------------------
grpStruct = 'Structure / Swings'
pivLen         = input.int(7,    'Pivot Strength (bars each side)', minval = 2, maxval = 30, group = grpStruct, tooltip = 'Higher = fewer, larger swings. Try 5 on 1H, 7 on 4H, 10 on Daily.')
useStrictTrend = input.bool(true, 'Require HH/HL or LH/LL trend', group = grpStruct)

grpBB = 'Bollinger Band Context'
bbLen       = input.int(20,    'BB Length',              minval = 5,   group = grpBB)
bbMult      = input.float(2.0, 'BB StdDev',             minval = 0.5, step = 0.1, group = grpBB)
useBBFilter = input.bool(false, 'Require pullback to tag band', group = grpBB)
bbTol       = input.float(0.15, 'Band tag tolerance (%)', minval = 0.0, step = 0.05, group = grpBB) / 100.0

grpEntry = 'Entry / Exit'
mmMult      = input.float(1.0,  'Measured Move Multiplier',        minval = 0.25, step = 0.25, group = grpEntry)
stopBufATR  = input.float(0.25, 'Stop Buffer (x ATR)',             minval = 0.0,  step = 0.05, group = grpEntry)
tlTouchATR  = input.float(1.0,  'Trendline touch window (x ATR)', minval = 0.0,  step = 0.25, group = grpEntry)
strictEntry = input.bool(false,  'Strict entry: close beyond prior bar range', group = grpEntry)
minRR       = input.float(1.2,  'Minimum R:R',                    minval = 0.5,  step = 0.25, group = grpEntry)
minATRmult  = input.float(0.5,  'Min structure size (x ATR)',      minval = 0.0,  step = 0.1,  group = grpEntry)
allowLongs  = input.bool(true,  'Allow Longs',  group = grpEntry)
allowShorts = input.bool(false, 'Allow Shorts', group = grpEntry)

grpExhaust = 'Exhaustion Filter'
exhaustCount = input.int(3,     'Flag exhaustion at RZY #', minval = 2, maxval = 8, group = grpExhaust)
blockExhaust = input.bool(true, 'Block entries once exhausted',    group = grpExhaust)

grpRisk = 'Risk Management'
riskPct    = input.float(5.0, 'Risk per trade (% of equity)', minval = 0.1, maxval = 20.0, step = 0.5, group = grpRisk,
     tooltip = 'Position sized so a stop-out costs exactly this % of equity.\nCapped automatically so margin never exceeds capital.\nWorks on stocks, forex, crypto and futures - no manual switching needed.')
useBE      = input.bool(true,  'Move stop to breakeven at 0.5R', group = grpRisk)
partialAtT = input.bool(true,  'Take 50% partial at measured-move target', group = grpRisk)

grpViz = 'Visuals'
showLines  = input.bool(true, 'Draw trendlines',       group = grpViz)
showBB     = input.bool(true, 'Show Bollinger Bands',  group = grpViz)
showLabels = input.bool(true, 'Show RZY count labels', group = grpViz)

// --- Core calculations -------------------------------------------------------
atr     = ta.atr(14)
bbBasis = ta.sma(close, bbLen)
bbDev   = bbMult * ta.stdev(close, bbLen)
bbUpper = bbBasis + bbDev
bbLower = bbBasis - bbDev

ph = ta.pivothigh(high, pivLen, pivLen)
pl = ta.pivotlow(low,  pivLen, pivLen)

var float ph1 = na
var float ph2 = na
var int   ph1b = na
var int   ph2b = na
var float pl1 = na
var float pl2 = na
var int   pl1b = na
var int   pl2b = na
var float ph2Band = na
var float pl2Band = na

if not na(ph)
    ph1     := ph2
    ph1b    := ph2b
    ph2     := ph
    ph2b    := bar_index - pivLen
    ph2Band := bbUpper[pivLen]

if not na(pl)
    pl1     := pl2
    pl1b    := pl2b
    pl2     := pl
    pl2b    := bar_index - pivLen
    pl2Band := bbLower[pivLen]

upStruct   = not na(ph1) and not na(pl1) and ph2 > ph1 and pl2 > pl1
downStruct = not na(ph1) and not na(pl1) and ph2 < ph1 and pl2 < pl1
trendUp    = useStrictTrend ? upStruct   : (not na(bbBasis) and close > bbBasis and ph2 > ph1)
trendDown  = useStrictTrend ? downStruct : (not na(bbBasis) and close < bbBasis and ph2 < ph1)

tlShortNow  = not na(ph1) and not na(ph2) and ph2b != ph1b ? ph2 + (ph2 - ph1) / (ph2b - ph1b) * (bar_index - ph2b)     : na
tlShortPrev = not na(ph1) and not na(ph2) and ph2b != ph1b ? ph2 + (ph2 - ph1) / (ph2b - ph1b) * (bar_index - 1 - ph2b) : na
tlLongNow   = not na(pl1) and not na(pl2) and pl2b != pl1b ? pl2 + (pl2 - pl1) / (pl2b - pl1b) * (bar_index - pl2b)     : na
tlLongPrev  = not na(pl1) and not na(pl2) and pl2b != pl1b ? pl2 + (pl2 - pl1) / (pl2b - pl1b) * (bar_index - 1 - pl2b) : na

var int trendDir = 0
var int rzyCount = 0
newTrendUp   = trendUp   and trendDir <= 0
newTrendDown = trendDown and trendDir >= 0

if newTrendUp
    trendDir := 1
    rzyCount := 0

if newTrendDown
    trendDir := -1
    rzyCount := 0

// --- Universal position-size function ----------------------------------------
f_qty(stopDist) =>
    pv      = math.max(syminfo.pointvalue, 0.0001)
    riskAmt = strategy.equity * riskPct / 100.0
    riskQty = math.floor(riskAmt / math.max(stopDist * pv, 0.0001))
    maxQty  = math.floor(strategy.equity / math.max(close * pv * 0.05, 0.0001))
    math.max(1, math.min(riskQty, maxQty))

// ============================================================================
// SHORT SETUP
// ============================================================================
var bool  sArmed    = false
var float sRejLevel = na
var float sRunLow   = na
var float sTLAtLow  = na
var int   sArmBar   = na

if trendDown and not na(ph) and allowShorts
    bandOK = not useBBFilter or (high[pivLen] >= ph2Band * (1 - bbTol))
    if bandOK
        sArmed    := true
        sRejLevel := ph2
        sRunLow   := low[pivLen]
        sTLAtLow  := tlShortNow
        sArmBar   := bar_index
        rzyCount  := rzyCount + 1
        if showLabels
            label.new(bar_index - pivLen, ph2, 'RZY ' + str.tostring(rzyCount),
                 style     = label.style_label_down,
                 color     = rzyCount >= exhaustCount ? color.new(color.orange, 30) : color.new(color.red, 40),
                 textcolor = color.white, size = size.small)

if sArmed
    if low < sRunLow
        sRunLow  := low
        sTLAtLow := tlShortNow

exhaustedShort = rzyCount >= exhaustCount
blockShort     = blockExhaust and exhaustedShort

sTLRef      = sArmed and not na(sTLAtLow) ? sTLAtLow : sRejLevel
sStructDist = sArmed ? sTLRef - sRunLow : 0.0
sEffStop    = sArmed ? (not na(tlShortNow) ? math.max(high, tlShortNow) : math.max(high, sRejLevel)) + atr * stopBufATR : na
sStopDist   = not na(sEffStop) ? sEffStop - close : 0.0
sTargetDist = sArmed ? close - (sRunLow - sStructDist * mmMult) : 0.0
sRROK       = sStopDist > 0 ? (sTargetDist / sStopDist >= minRR) : false
sSizeOK     = not na(atr) ? sStructDist >= atr * minATRmult : true

shortTouching  = sArmed and not na(tlShortNow) and high >= tlShortNow - atr * tlTouchATR
shortRejecting = shortTouching and (strictEntry ? close < low[1] : close < open)
shortTrigger   = shortRejecting and trendDown and not blockShort and strategy.position_size == 0 and sRROK and sSizeOK

if sArmed and not shortTrigger
    invalidShort = not na(tlShortNow) ? close > tlShortNow + atr * 0.5 : close > sRejLevel
    if invalidShort
        sArmed := false

// ============================================================================
// LONG SETUP
// ============================================================================
var bool  lArmed    = false
var float lRejLevel = na
var float lRunHigh  = na
var float lTLAtHigh = na
var int   lArmBar   = na

if trendUp and not na(pl) and allowLongs
    bandOK = not useBBFilter or (low[pivLen] <= pl2Band * (1 + bbTol))
    if bandOK
        lArmed    := true
        lRejLevel := pl2
        lRunHigh  := high[pivLen]
        lTLAtHigh := tlLongNow
        lArmBar   := bar_index
        rzyCount  := rzyCount + 1
        if showLabels
            label.new(bar_index - pivLen, pl2, 'RZY ' + str.tostring(rzyCount),
                 style     = label.style_label_up,
                 color     = rzyCount >= exhaustCount ? color.new(color.orange, 30) : color.new(color.green, 40),
                 textcolor = color.white, size = size.small)

if lArmed
    if high > lRunHigh
        lRunHigh  := high
        lTLAtHigh := tlLongNow

exhaustedLong = rzyCount >= exhaustCount
blockLong     = blockExhaust and exhaustedLong

lTLRef      = lArmed and not na(lTLAtHigh) ? lTLAtHigh : lRejLevel
lStructDist = lArmed ? lRunHigh - lTLRef : 0.0
lEffStop    = lArmed ? (not na(tlLongNow) ? math.min(low, tlLongNow) : math.min(low, lRejLevel)) - atr * stopBufATR : na
lStopDist   = not na(lEffStop) ? close - lEffStop : 0.0
lTargetDist = lArmed ? (lRunHigh + lStructDist * mmMult) - close : 0.0
lRROK       = lStopDist > 0 ? (lTargetDist / lStopDist >= minRR) : false
lSizeOK     = not na(atr) ? lStructDist >= atr * minATRmult : true

longTouching  = lArmed and not na(tlLongNow) and low <= tlLongNow + atr * tlTouchATR
longRejecting = longTouching and (strictEntry ? close > high[1] : close > open)
longTrigger   = longRejecting and trendUp and not blockLong and strategy.position_size == 0 and lRROK and lSizeOK

if lArmed and not longTrigger
    invalidLong = not na(tlLongNow) ? close < tlLongNow - atr * 0.5 : close < lRejLevel
    if invalidLong
        lArmed := false

// ============================================================================
// STRATEGY EXECUTION
// ============================================================================
var float entryPrice  = na
var float stopPrice   = na
var float targetPrice = na
var float beTrigger   = na

if shortTrigger
    entryPrice  := close
    stopPrice   := (not na(tlShortNow) ? math.max(high, tlShortNow) : math.max(high, sRejLevel)) + atr * stopBufATR
    targetPrice := sRunLow - sStructDist * mmMult
    beTrigger   := entryPrice - (entryPrice - targetPrice) * 0.5
    sArmed      := false
    strategy.entry('Short', strategy.short, qty = f_qty(stopPrice - close))

if longTrigger
    entryPrice  := close
    stopPrice   := (not na(tlLongNow) ? math.min(low, tlLongNow) : math.min(low, lRejLevel)) - atr * stopBufATR
    targetPrice := lRunHigh + lStructDist * mmMult
    beTrigger   := entryPrice + (targetPrice - entryPrice) * 0.5
    lArmed      := false
    strategy.entry('Long', strategy.long, qty = f_qty(close - stopPrice))

if useBE and strategy.position_size > 0 and not na(beTrigger)
    if high >= beTrigger
        stopPrice := math.max(stopPrice, entryPrice)

if useBE and strategy.position_size < 0 and not na(beTrigger)
    if low <= beTrigger
        stopPrice := math.min(stopPrice, entryPrice)

if strategy.position_size > 0
    if partialAtT
        strategy.exit('L-TP',  'Long', qty_percent = 50, stop = stopPrice, limit = targetPrice)
        strategy.exit('L-Run', 'Long', stop = stopPrice, limit = targetPrice + (targetPrice - entryPrice))
    else
        strategy.exit('L-X', 'Long', stop = stopPrice, limit = targetPrice)

if strategy.position_size < 0
    if partialAtT
        strategy.exit('S-TP',  'Short', qty_percent = 50, stop = stopPrice, limit = targetPrice)
        strategy.exit('S-Run', 'Short', stop = stopPrice, limit = targetPrice - (entryPrice - targetPrice))
    else
        strategy.exit('S-X', 'Short', stop = stopPrice, limit = targetPrice)

if strategy.position_size == 0 and not shortTrigger and not longTrigger
    entryPrice  := na
    stopPrice   := na
    targetPrice := na
    beTrigger   := na

// ============================================================================
// VISUALS
// ============================================================================
plot(showBB ? bbBasis : na, 'BB Basis', color = color.new(color.gray, 0))
pU = plot(showBB ? bbUpper : na, 'BB Upper', color = color.new(color.blue, 60))
pL = plot(showBB ? bbLower : na, 'BB Lower', color = color.new(color.blue, 60))
fill(pU, pL, color = showBB ? color.new(color.blue, 94) : na)

var line tlShort = na
var line tlLong  = na
if showLines and not na(ph1) and not na(ph2) and ph2 < ph1
    line.delete(tlShort)
    tlShort := line.new(ph1b, ph1, ph2b, ph2, color = color.new(color.red, 0), width = 2, extend = extend.right)
if showLines and not na(pl1) and not na(pl2) and pl2 > pl1
    line.delete(tlLong)
    tlLong := line.new(pl1b, pl1, pl2b, pl2, color = color.new(color.green, 0), width = 2, extend = extend.right)

plot(strategy.position_size != 0 ? entryPrice  : na, 'Entry',  color = color.new(color.white, 0), style = plot.style_linebr)
plot(strategy.position_size != 0 ? stopPrice   : na, 'Stop',   color = color.new(color.red,   0), style = plot.style_linebr)
plot(strategy.position_size != 0 ? targetPrice : na, 'Target', color = color.new(color.lime,  0), style = plot.style_linebr)

plotshape(longTrigger,  'Long',  shape.triangleup,   location.belowbar, color = color.new(color.green, 0), size = size.normal, text = 'RZY')
plotshape(shortTrigger, 'Short', shape.triangledown, location.abovebar, color = color.new(color.red,   0), size = size.normal, text = 'RZY')

bgcolor(trendUp ? color.new(color.green, 95) : trendDown ? color.new(color.red, 95) : na)

// ============================================================================
// INFO TABLE
// ============================================================================
var table t = table.new(position.top_right, 2, 6, bgcolor = color.new(color.black, 80), border_width = 1)
if barstate.islast
    table.cell(t, 0, 0, 'Marci Silfrain Strategy',  text_color = color.white,  text_size = size.small)
    table.cell(t, 1, 0, syminfo.ticker, text_color = color.yellow, text_size = size.small)
    table.cell(t, 0, 1, 'Trend',       text_color = color.gray, text_size = size.tiny)
    table.cell(t, 1, 1, trendUp ? 'UP' : trendDown ? 'DOWN' : 'SIDEWAYS',
         text_color = trendUp ? color.green : trendDown ? color.red : color.gray, text_size = size.tiny)
    table.cell(t, 0, 2, 'RZY #',       text_color = color.gray, text_size = size.tiny)
    table.cell(t, 1, 2, str.tostring(rzyCount) + (rzyCount >= exhaustCount ? ' EXHAUSTED' : ''),
         text_color = rzyCount >= exhaustCount ? color.orange : color.white, text_size = size.tiny)
    table.cell(t, 0, 3, 'Armed',       text_color = color.gray, text_size = size.tiny)
    table.cell(t, 1, 3, sArmed ? 'SHORT' : lArmed ? 'LONG' : '-',
         text_color = sArmed ? color.red : lArmed ? color.green : color.gray, text_size = size.tiny)
    table.cell(t, 0, 4, 'In Trade',    text_color = color.gray, text_size = size.tiny)
    table.cell(t, 1, 4, strategy.position_size > 0 ? 'LONG' : strategy.position_size < 0 ? 'SHORT' : 'FLAT',
         text_color = strategy.position_size > 0 ? color.green : strategy.position_size < 0 ? color.red : color.gray, text_size = size.tiny)
    table.cell(t, 0, 5, 'Target',      text_color = color.gray, text_size = size.tiny)
    table.cell(t, 1, 5, na(targetPrice) ? '-' : str.tostring(targetPrice, format.mintick),
         text_color = color.lime, text_size = size.tiny)

// ============================================================================
// ALERTS
// ============================================================================
alertcondition(longTrigger,  'RZY Long',  'Marci Silfrain Strategy Long entry (uptrend continuation)')
alertcondition(shortTrigger, 'RZY Short', 'Marci Silfrain Strategy Short entry (downtrend continuation)')
alertcondition(rzyCount >= exhaustCount and (newTrendUp or newTrendDown or not na(ph) or not na(pl)),
     'RZY Exhaustion', 'RZY count reached exhaustion zone')

Past performance does not guarantee future results. All backtest figures are simulated, use 0% commission, and reflect specific settings on a specific instrument and timeframe. The 1,574% result uses 5% risk per trade with 20× effective leverage — live trading with these settings involves substantial drawdown risk. Always test with paper trading before committing real capital. This post is for educational purposes only and does not constitute financial advice.


Start Automating Your Marci Silfrain Strategy Trades With PickMyTrade

The strategy fires TradingView alerts automatically. Connect those alerts to your live broker account through PickMyTrade and execute every Marci Silfrain Strategy entry and exit without sitting at the screen. Use pickmytrade.trade for Tradovate futures (GC, NQ, ES) and pickmytrade.io for crypto, forex, and all other brokers.

You May Also Like

Frequently Asked Questions

What timeframe works best for Marci Silfrain’s Marci Silfrain Strategy on gold?

The 1,574% backtest used a shorter intraday timeframe that generated 896 trades over three years. For active management, 1H to 4H on XAUUSD balances trade frequency with setup quality. Daily timeframe produces fewer trades — 272 in the same period — but with a higher win rate (37%) and lower drawdown (18.6%). The strategy works on any timeframe without changing settings; the Pivot Strength input scales automatically to the bar size.

Does the Marci Silfrain Strategy work on GC1!, NQ1!, and ES1! futures?

Yes. The f_qty() function reads syminfo.pointvalue to adjust position sizing automatically: $100 per point for GC gold futures, $20 per point for NQ, $50 per point for ES. You must set “Margin for long positions” and “Margin for short positions” to 5% in the TradingView Properties tab. Without this, the backtester rejects all futures trades and shows “This report requires trade data” — a capital-sizing issue, not a strategy issue.

Is a 20% win rate too low to be profitable?

No. Win rate only matters in relation to the average win-to-loss ratio. The Marci Silfrain Strategy’s profit factor of 1.988 means every dollar lost returns $1.99 in winners. The partial exit at the measured-move target banks a confirmed return before the runner plays out — keeping average winner size well above average loss size even during streaks where runners fail to extend. Eight losses in a row at 5% risk each drop equity by ~34%. One runner at 4× risk (not uncommon with MM Multiplier = 2) recovers more than half of that in one trade.

How is the Marci Silfrain Strategy measured move target calculated?

The trendline is projected forward to the bar where price hit its lowest low during the current structure (the “run low”). The distance from the trendline’s value at that bar to the actual low price = the structure size. That same distance is projected below the run low to set the target. At Measured Move Multiplier 2.0, the runner target is set at 2× that distance below the run low. The PineScript calculates this on every bar automatically — you see the green target line on the chart the moment you enter.

What was the maximum drawdown on the 1,574% result?

43.57% ($274,436 from peak equity during the three-year backtest). This is a meaningful number that requires conviction in the system. At 1% risk per trade, the maximum drawdown drops to 18.62% ($23,965) — substantially more manageable. The risk percentage input is the single most important variable for controlling drawdown. Halving risk from 2% to 1% roughly halves the maximum drawdown. Doubling from 5% to 10% would roughly double both the return and the drawdown.


Leave a Comment

Your email address will not be published. Required fields are marked *

error

Follow us for more insights and updates

Scroll to Top
Verified by MonsterInsights