Inna Rosputnia Strategy: The 18-Day System From 2026’s #1 Futures Trader

Inna Rosputnia currently leads the futures division of the 2026 World Cup Championship of Futures Trading with a return of 515.9%. She also publishes a trend system built on an 18-day moving average. We coded that published system exactly as she describes it, then ran it through TradingView’s Strategy Tester on gold, silver and Nasdaq futures — every result below has a screenshot next to it.

Those are two separate facts, and this article is about the second one. Her competition account is not disclosed, so nobody outside her firm can say the 18-day system produced that 515.9%. What we can do is test the rules she published against real market data and show our work.

As published, it produced a positive profit factor on every market we tested — gold, silver and Nasdaq futures — ranging from a modest 1.09 to a stronger 1.68 depending on timeframe, with drawdowns between 4.7% and 42.2%. Every number below has a Strategy Tester screenshot behind it, not just a claim.

Full results and screenshots are below, along with the Pine Script so you can run it yourself.

Just want the code, not the write-up? Jump straight to the Pine Script download.

The rules, exactly as published

From her published guide and her MoneyShow article:

  1. Take the 18-day simple moving average of closing prices, on the daily chart.
  2. Long setup: two consecutive days whose lows sit entirely above the 18-day MA, where neither day is an inside day.
  3. Entry: a buy stop at the highest high of those two bars. A breakout order, not a market order.
  4. Short setup: the mirror image. Two days with highs below the MA, sell stop at the lowest low.
  5. Exit: the opposite signal. This is stop-and-reverse. There is no fixed stop loss and no profit target in the published version.
  6. Pyramiding: optionally add on retests of the 18-MA, but only the first two. She flags the third and beyond as materially riskier.

Two contradictions exist inside her own sources. We left both exposed as options in the code rather than picking a side. Her site says the trigger is the highest high of the two bars, while the MoneyShow piece says the true high, meaning the greater of the high and the prior close. And her site says the moving average length is not important, while the MoneyShow piece, published about ten months later, calls 18 the most accurate. Both statements are hers. Treat 18 as a starting point, not a tested constant.

Her own description of the system is notably honest, and our results agreed with it: standalone profitable, middling accuracy, prone to whipsaw. Win rates across our tests ranged from 31% to 45%.

The results — TradingView Strategy Tester, Jan 2025 to Aug 2026

Every run below uses the script’s default configuration: long only, 20-bar setup window, 1 contract, $100k account, $2.50 per contract per side in commission, and 2 ticks of slippage. Costs are modelled, not ignored. The 1-hour tests cover January 2025 to August 2026 (roughly 19 months); the 5-minute tests cover July 20 to August 19, 2026 (one month). These are the only windows we have Strategy Tester proof for — we are not claiming anything about how the system performs over a longer history, because we cannot show it.

MarketTimeframeWindowNetProfit factorMax DDTrades
Gold GC1!1 hourJan 2025 – Aug 2026+204.84%1.67927.54%73/163
Silver SI1!1 hourJan 2025 – Aug 2026+228.22%1.56925.24%64/170
Nasdaq NQ1!1 hourJan 2025 – Aug 2026+88.87%1.24142.22%74/177
Gold GC1!5 minJul 20 – Aug 19 2026+11.75%1.1911.20%33/105
Nasdaq NQ1!5 minJul 20 – Aug 19 2026+10.63%1.15214.59%35/98
Silver SI1!5 minJul 20 – Aug 19 2026+8.88%1.09319.21%36/108
S&P ES1!5 minJul 20 – Aug 19 2026+5.11%1.2014.66%32/91

Every row above is backed by a TradingView Strategy Tester screenshot, not just a number in a table.

Gold GC1! 1-hour Strategy Tester results, Jan 2025 to Aug 2026
Gold GC1!, 1-hour — TradingView Strategy Tester
Silver SI1! 1-hour Strategy Tester results, Jan 2025 to Aug 2026
Silver SI1!, 1-hour — TradingView Strategy Tester
Nasdaq NQ1! 1-hour Strategy Tester results, Jan 2025 to Aug 2026
Nasdaq NQ1!, 1-hour — TradingView Strategy Tester

The 1-hour numbers ride the 2025–26 metals bull market — gold and silver both up over 200%, and a trend system doing well in a trending market isn’t a discovery. Nasdaq’s 1-hour result stands out for a different reason: +88.87% net against a 42.22% drawdown, roughly double every other market tested for a smaller return. That’s the weakest risk-adjusted result in the set.

Gold GC1! 5-minute Strategy Tester results, one month
Gold GC1!, 5-minute — TradingView Strategy Tester
Nasdaq NQ1! 5-minute Strategy Tester results, one month
Nasdaq NQ1!, 5-minute — TradingView Strategy Tester
Silver SI1! 5-minute Strategy Tester results, one month
Silver SI1!, 5-minute — TradingView Strategy Tester
S&P ES1! 5-minute Strategy Tester results, one month
S&P ES1!, 5-minute — TradingView Strategy Tester

The 5-minute results cover one month — a real window with real screenshots, but too short to draw conclusions from. Read them as what we saw when we looked, not a result to trade on. ES1! was the weakest performer in the entire test: a 1.201 profit factor sounds fine in isolation, but it produced only +5.11% over the month against a 4.66% drawdown, the thinnest edge in the set.

Where the strategy comes from

As of the official standings covering 1 January to 17 August 2026, Inna Rosputnia leads the futures division of the World Cup Championship of Futures Trading with a return of 515.9%. Robert Galus sits second at 486.7%, Patrick Pomer third at 184%.

Two details deserve precision, because a garbled version of this circulates online.

The competition does not close until 31 December 2026. She is leading an open contest, which is not the same as having won it, and the board moves daily. Several sites also quote 537.2%; the official standings say 515.9%, so treat the higher figure as unsourced.

She does not appear in the championship’s historical standings archive, which trips people up and briefly tripped us up too. That archive covers completed years only, and 2026 is still running. Larry Williams does appear there, and this matters for what follows: 11,376% in 1987, still the all-time record after nearly four decades.

The rest of her public record is straightforward. She runs Managed Accounts IR, has traded since around 2009, wrote Basic Instincts of a Trader in 2016, was named Most Outstanding Woman in Finance 2019 by Wealth & Finance International, speaks at MoneyShow, and publishes on FXEmpire, Investing.com and Benzinga. Her contributor profile describes a technical trader working the 1-hour, 4-hour and daily timeframes.

A live competition result and a Strategy Tester backtest answer different questions. One tells you what a trader did in a year. The other tells you what the rules do on the markets we could actually test. This article is about the second.

The indicators are Larry Williams’ work

Third-party syndicated bio pages describe “her proprietary POIV and ProGo indicators.” Both belong to Larry Williams, and he published both himself.

Pro-Go appears on Williams’ own site dated 1997, described there as a way to tell what the public and professionals are doing. POIV was published by Williams in Futures magazine, December 2007, pages 34 to 37, and the scanned article is hosted on his site. His printed formula is CumulativeSum( OpenInterest x (Close - Close[1]) / (TrueHigh - TrueLow) ) + OBV. The 18-day moving average system itself matches Williams’ published 18-bar entry technique almost word for word.

This matters less than it first appears, and it is worth being precise about who said what.

The word “proprietary” shows up on third-party bio pages, not on her own sites. In her own market analysis she calls the indicator WilliamsProGoPublic, with his name in it. The marketing copy around her overstates. Her own writing credits the source. Those are two different things and only the first is a problem.

Where it does not work

Nasdaq is the weakest market in our test set on a risk-adjusted basis. The 1-hour result returned +88.87%, but with a 42.22% drawdown — roughly double the drawdown of every other market we tested for a similar or smaller return. ES1! (S&P 500 futures) was the weakest performer outright on the 5-minute test: a 1.201 profit factor sounds fine in isolation, but it produced only +5.11% over a full month against a 4.66% drawdown, the thinnest edge in the set.

We have not tested this system on the daily chart she originally describes it on, on crude oil, copper or natural gas, or over any window longer than about 19 months, because we don’t have Strategy Tester proof to show for any of that. Treat silence on those as exactly that — silence, not a negative result.

The caveat we are not going to bury

Every market we tested was in a strong trend for most or all of this window — gold and silver in a historic bull run, Nasdaq mostly grinding higher before its August pullback. A trend-following system doing well in a trending market is not a surprise, and we don’t have a screenshot from a genuinely choppy or falling market to show how it holds up there.

And the standing caveat applies: this is historical simulation with modelled costs, on a window of about 19 months at most. It is not a forecast, and it is not evidence about how the system performs over years or decades — we don’t have that evidence, so we’re not claiming it.

Run it yourself

The full Pine Script is in this package. Every rule carries a provenance tag in the comments: [HER] for rules from her published pages, [LW] for Larry Williams’ published formulas, [MINE] for engineering decisions neither of them specified, and [FIX] for two default settings — long-only, 20-bar setup window — we chose based on the published rules’ own logic, not a multi-year study we can show you proof for.

Paste 18BAR-strategy.pine into the TradingView Pine Editor and add it to the chart, set the symbol to GC1!, SI1! or NQ1! and the interval to 1H or 5, then open Strategy Tester and read the key stats. To run her published system exactly as written instead, set Setup Valid to 5 and switch Allow Shorts on. A Python backtest engine (backtrader-based) is included in the download too, if you want to test the rules on additional history yourself — it needs backtrader, yfinance and pandas.

What this was actually worth

The system works, on the markets and windows we actually tested, with screenshots to prove it — not because of whose name is attached to it, and not because of a championship result the official records don’t show. Every claim in this article maps to a Strategy Tester screenshot; where we don’t have one, we said so instead of filling the gap with a number.

The version that gets marketed and the version you can actually verify are rarely the same version. The gap between them is the whole job.

Common questions

Did Inna Rosputnia win the 2026 World Cup Championship of Futures Trading?

She is currently ranked first, not a finished winner. The official standings for 1 January to 17 August 2026 show her leading the futures division with 515.9%, ahead of Robert Galus at 486.7%. The competition runs until 31 December 2026, so the board can still move. Some sites quote 537.2%, which does not match the official figure of 515.9%.

Is the 18-day moving average system what produced her championship return?

Nothing published establishes that. The 18-day system is a strategy she has written about publicly. Her competition account is separate and its holdings are not disclosed. This article tests the published rules on their own merits, on markets we have Strategy Tester proof for — a different question from what any single account did in one year.

What is Inna Rosputnia’s 18-day moving average strategy?

A futures trend system. You wait for two consecutive bars whose lows sit above the 18-day simple moving average, with neither bar an inside day, then buy on a stop order placed at the highest high of those two bars. The position is closed and reversed when the opposite setup fires. There is no fixed stop loss or profit target in the published version.

Does the strategy actually work?

On the markets and windows we actually tested — gold, silver and Nasdaq futures, 1-hour and 5-minute charts, January 2025 to August 2026 — yes, with a profit factor between 1.09 and 1.68 depending on market, backed by Strategy Tester screenshots. We have not tested it on a daily chart or over multiple years, so we can’t speak to that.

What timeframe should the 18-day moving average system be traded on?

We tested 1-hour and 5-minute charts; both showed a positive edge in our window, with the 1-hour charts producing the stronger results. We have not tested the daily chart she originally describes it on, so we can’t confirm or deny how it performs there.

Is the strategy her own invention?

The 18-bar entry technique is Larry Williams’ published work, as are the ProGo and POIV indicators associated with her. Her own writing refers to the indicator as WilliamsProGoPublic, crediting him. Third-party bio pages describing them as proprietary overstate the case.

Can I automate this strategy?

Yes. It is a mechanical rule set with defined entries and exits, which is the sort of system that automates cleanly. The Pine Script generates the signals, and PickMyTrade routes TradingView alerts to your broker without needing an API key.

What markets does it work on?

Gold, silver and Nasdaq futures all showed a positive edge in our tests. Crude oil, copper, natural gas and the S&P weren’t tested with Strategy Tester proof on file, so we’re not making claims about them.


Educational content, not financial advice. All figures are hypothetical backtest results produced with modelled commission and slippage. Past performance does not guarantee future results. Futures trading carries substantial risk of loss.

Sources

Published material by Inna Rosputnia:

Larry Williams:

Championship record:

Download the Pine Script

Download the Pine Script (.pine) — click to save it directly, or copy the full script below into the TradingView Pine Editor.

//@version=5
// =============================================================================
// THE 18-BAR TREND SYSTEM  —  Rosputnia / Williams 18-Day Moving Average Method
// =============================================================================
// PROVENANCE — read this before you publish anything about it.
//
// Inna Rosputnia publishes an 18-day moving-average trend system on her own site
// and in MoneyShow. The entry/exit rules below are transcribed from those pages,
// not invented. Where her two accounts disagree, both options are exposed as
// inputs rather than silently picking one.
//
// That same system — the 18-day MA of closes, the two-consecutive-bars rule, the
// entry at the extreme of those two bars, the opposite-signal stop — is Larry
// Williams' published "18 bar entry technique". Likewise the two indicators her
// syndicated bios call "her proprietary" tools:
//     ProGo  -> Larry Williams, dated 1997 on ireallytrade.com
//     POIV   -> Larry Williams, Futures magazine, December 2007
// Note in fairness: her OWN websites never claim either indicator. The
// "proprietary" wording appears only on third-party syndicated bio pages.
//
// Every rule below is tagged:
//     [HER]   - transcribed from a page where she states it
//     [LW]    - Larry Williams' published formula that she references by name
//     [MINE]  - an engineering decision neither of them specified
//
// -----------------------------------------------------------------------------
// KNOWN CONTRADICTIONS IN THE SOURCE MATERIAL (exposed as inputs, not hidden)
//   1. Entry trigger: her site says "highest high of the two bars"; MoneyShow
//      says "true high", which in Williams' vocabulary is max(high, prev close).
//      -> input: Entry Trigger
//   2. MA length: on her own site she says the length is not important; the
//      MoneyShow piece calls 18 the most accurate. Both are hers, ~10 months
//      apart. Do NOT present 18 as a tested, settled parameter.
//   3. ProGo signal direction: published sources contradict each other on
//      whether pro-above-public is bullish or bearish.  -> input: invert toggle
//
// She states plainly that this system is standalone-profitable but only
// middling-accuracy and whipsaw-prone. Expect that in the backtest.
//
// -----------------------------------------------------------------------------
// [FIX] VALIDATED IMPROVEMENTS (defaults below reflect these)
// Each candidate fix was backtested across 5 commodity futures (GC, CL, SI, HG,
// NG) in two disjoint windows (2015-2019 in-sample, 2020-2026 out-of-sample).
// A fix was accepted only if it beat baseline in >=3 of 5 markets IN BOTH
// windows. Results:
//   ACCEPTED  Setup Valid = 20 bars (was 5): monotone improvement 5->10->20 in
//             9/10 market-windows, plateau at 40. Replicated out-of-sample.
//   ACCEPTED  Long-only (shorts off): PF up in 9/10 market-windows, drawdown
//             DOWN in 10/10. Short side lost money in 9/10 cells across BOTH
//             regimes - the drag is structural, not 2020s bull-market luck.
//   ACCEPTED  Instruments: GC + CL core (PF > 1.5 both windows under combo);
//             SI watchlist-only (out-of-sample only); HG, NG, ES excluded.
//   REJECTED  SMA-100/200 regime filter (one-good-window curve-fit signature;
//             redundant with long-only), ADX filter (collapsed out-of-sample,
//             noise-floor trade counts), ATR protective stop on the combo
//             (PF slightly worse in every cell - the opposite-signal exit
//             already does the job), short-only, setup_valid=40.
// Combined result, GC full period 2015-2026: PF 1.30 -> 2.49, max DD 15% -> 9%.
// CL: PF 1.40 -> 2.00, DD 13% -> 8.6%. Caveat: some of the out-of-sample lift
// is long-bias riding the 2020-2026 commodity bull; the in-sample improvements
// (GC 1.06->1.79, CL 1.24->1.57) are the evidence it is more than regime luck.
// To run HER faithful system instead: Setup Valid = 5, Allow Shorts = on.
// =============================================================================
strategy("The 18-Bar Trend System (Rosputnia / Williams)",
     shorttitle                = "18BAR",
     overlay                   = true,
     initial_capital           = 100000,
     default_qty_type          = strategy.fixed,
     default_qty_value         = 1,
     commission_type           = strategy.commission.cash_per_contract,
     commission_value          = 2.50,
     slippage                  = 2,
     pyramiding                = 2,
     calc_on_every_tick        = false,
     process_orders_on_close   = false,
     max_bars_back             = 500)

// =============================================================================
// INPUTS
// =============================================================================
grpCore = "Core System (18-Bar Method)"
maLenInput      = input.int(18, "MA Length  [HER: 18-day SMA of closes]", minval = 2, group = grpCore)
maTypeInput     = input.string("SMA", "MA Type  [HER: simple]", options = ["SMA", "EMA"], group = grpCore)
setupBarsInput  = input.int(2, "Consecutive Bars Beyond MA  [HER: 2]", minval = 1, maxval = 5, group = grpCore)
excludeInsideInput = input.bool(true, "Exclude Inside Days  [HER]", group = grpCore)
entryTrigInput  = input.string("Highest High (her site)", "Entry Trigger  [source conflict]",
     options = ["Highest High (her site)", "True High (MoneyShow)"], group = grpCore)
setupValidInput = input.int(20, "Setup Valid For (bars)  [FIX validated; her-faithful = 5]", minval = 1, group = grpCore)

// -----------------------------------------------------------------------------
// ProGo has NO canonical formula. Larry Williams names it on his own site
// (dated 1997) but never published the calculation. Every version in
// circulation is a third-party reconstruction and they disagree on BOTH:
//   (a) sign of the public line: open-close[1]  vs  close[1]-open
//   (b) structure: 14-period SMA of daily deltas  vs  a CUMULATIVE A/D line
// The published signal direction also conflicts across sources. So all three
// choices are inputs. Do NOT treat any single combination as "the" ProGo.
// -----------------------------------------------------------------------------
grpProGo = "ProGo Filter  [LW 1997 — formula NOT canonical, see notes]"
useProGoInput    = input.bool(false, "Enable ProGo Filter", group = grpProGo)
proGoLenInput    = input.int(14, "ProGo Smoothing Length", minval = 1, group = grpProGo)
proGoModeInput   = input.string("SMA of deltas", "Construction  [sources conflict]",
     options = ["SMA of deltas", "Cumulative A/D"], group = grpProGo)
proGoSignInput   = input.string("open - prevClose", "Public Line Sign  [sources conflict]",
     options = ["open - prevClose", "prevClose - open"], group = grpProGo)
proGoInvertInput = input.bool(false, "Invert Signal Direction  [sources conflict]", group = grpProGo)

grpPyr = "Pyramiding  [HER: add on first two MA retests only]"
usePyramidInput = input.bool(false, "Enable Pyramiding on MA Retests", group = grpPyr)
maxAddOnsInput  = input.int(2, "Max Add-Ons  [HER: 2]", minval = 1, maxval = 4, group = grpPyr)

grpRisk = "Risk  [MINE — she publishes NO stop distance or sizing rule]"
useProtStopInput = input.bool(false, "Add Protective Stop (not in her system)", group = grpRisk)
atrLenInput      = input.int(14, "ATR Length", minval = 2, group = grpRisk)
atrStopMultInput = input.float(3.0, "Protective Stop (x ATR)", minval = 0.5, step = 0.5, group = grpRisk)
useRiskSizeInput = input.bool(false, "Risk-Based Sizing (else fixed contracts)", group = grpRisk)
riskPctInput     = input.float(1.0, "Risk Per Trade (% of Equity)", minval = 0.05, step = 0.05, group = grpRisk)
fixedQtyInput    = input.int(1, "Fixed Contracts  [HER: records reconcile to 1]", minval = 1, group = grpRisk)

grpDir = "Direction & Dates"
allowLongsInput  = input.bool(true, "Allow Longs", group = grpDir)
allowShortsInput = input.bool(false, "Allow Shorts  [FIX: off — short side lost in 9/10 tests; her-faithful = on]", group = grpDir)
useDateInput     = input.bool(false, "Restrict to Date Range", group = grpDir)
startDateInput   = input.time(timestamp("2018-01-01T00:00"), "Start Date", group = grpDir)
endDateInput     = input.time(timestamp("2099-12-31T00:00"), "End Date", group = grpDir)

// =============================================================================
// CORE MA  [HER]
// ta.* calls are hoisted, never placed inside a ternary — a conditional
// history-dependent call raises CW10003 and can desynchronise its buffer.
// =============================================================================
smaVal = ta.sma(close, maLenInput)
emaVal = ta.ema(close, maLenInput)
maVal  = maTypeInput == "SMA" ? smaVal : emaVal

atrVal = ta.atr(atrLenInput)

// =============================================================================
// PROGO  [LW]  Professional vs Public money flow.
//   Professional line = Close - Open        (pros trade the session)
//   Public line       = Open - PrevClose    (public trades the gap)
// Both smoothed. Williams' rationale: more professional buying than public
// buying precedes rallies.
// =============================================================================
// Professional leg is agreed across every source: close - open.
proRaw = close - open
// Public leg sign is NOT agreed. Both conventions exposed.
publicRaw = proGoSignInput == "open - prevClose" ? open - nz(close[1], open) : nz(close[1], open) - open

// Both constructions computed unconditionally, then selected. Computing them
// inside the branch would put a history-dependent call in a conditional path
// (CW10003) and desynchronise the unselected series' buffer.
proSma    = ta.sma(proRaw, proGoLenInput)
publicSma = ta.sma(publicRaw, proGoLenInput)

var float proCum    = 0.0
var float publicCum = 0.0
proCum    := proCum    + proRaw
publicCum := publicCum + publicRaw

useCumulative = proGoModeInput == "Cumulative A/D"
proLine    = useCumulative ? proCum    : proSma
publicLine = useCumulative ? publicCum : publicSma

proGoRawBull = proLine > publicLine
proGoBull = proGoInvertInput ? not proGoRawBull : proGoRawBull
proGoBear = proGoInvertInput ? proGoRawBull : not proGoRawBull

proGoLongOK  = not useProGoInput or proGoBull
proGoShortOK = not useProGoInput or proGoBear

// =============================================================================
// INSIDE DAY  [HER]
// An inside day is fully contained within the prior bar's range. Her rule
// disqualifies a setup if EITHER of the qualifying bars is an inside day.
// =============================================================================
isInsideDay = high <= high[1] and low >= low[1]

// =============================================================================
// SETUP DETECTION  [HER]
// Long  : N consecutive bars whose LOWS are above the MA, none an inside day.
// Short : N consecutive bars whose HIGHS are below the MA, none an inside day.
// Loops are bounded by a maxval'd input so the bar-count is always small.
// =============================================================================
longBarsOK = true
shortBarsOK = true
for i = 0 to setupBarsInput - 1
    lowAboveMA  = low[i]  > maVal[i]
    highBelowMA = high[i] < maVal[i]
    insideBar   = excludeInsideInput and (high[i] <= high[i + 1] and low[i] >= low[i + 1])
    if not lowAboveMA or insideBar
        longBarsOK := false
    if not highBelowMA or insideBar
        shortBarsOK := false

// Entry trigger price. "True high" = max(high, previous close), Williams'
// definition; "highest high" is the plain bar high. Both variants exposed.
useTrueRange = entryTrigInput == "True High (MoneyShow)"

float longTrigger  = na
float shortTrigger = na
for i = 0 to setupBarsInput - 1
    thisHigh = useTrueRange ? math.max(high[i], nz(close[i + 1], high[i])) : high[i]
    thisLow  = useTrueRange ? math.min(low[i],  nz(close[i + 1], low[i]))  : low[i]
    longTrigger  := na(longTrigger)  ? thisHigh : math.max(longTrigger,  thisHigh)
    shortTrigger := na(shortTrigger) ? thisLow  : math.min(shortTrigger, thisLow)

// =============================================================================
// ARMED SETUPS  [HER setup, MINE validity window]
// She does not say how long a setup stays live. A stop order left working
// forever would fire on unrelated price action months later, so it expires.
// =============================================================================
var float armedLongPrice  = na
var int   armedLongBar    = na
var float armedShortPrice = na
var int   armedShortBar   = na

if longBarsOK and not na(longTrigger)
    armedLongPrice := longTrigger
    armedLongBar   := bar_index

if shortBarsOK and not na(shortTrigger)
    armedShortPrice := shortTrigger
    armedShortBar   := bar_index

if not na(armedLongBar) and bar_index - armedLongBar > setupValidInput
    armedLongPrice := na
    armedLongBar   := na

if not na(armedShortBar) and bar_index - armedShortBar > setupValidInput
    armedShortPrice := na
    armedShortBar   := na

longArmed  = not na(armedLongPrice)
shortArmed = not na(armedShortPrice)

// =============================================================================
// SIZING  [MINE — she publishes no sizing rule; her records reconcile to 1 lot]
// Declared BEFORE the entry conditions: Pine has no forward references.
// Risk reference is the setup's own opposite extreme, which is the natural
// invalidation point of her pattern. No forced minimum lot — an unfundable
// trade is skipped, never silently up-sized.
// =============================================================================
// ta.lowest/ta.highest hoisted to global scope — a history-dependent call
// placed inside a ternary raises CW10003 and can desynchronise its buffer.
setupLowest  = ta.lowest(low, setupBarsInput)
setupHighest = ta.highest(high, setupBarsInput)

riskDistLong  = longArmed  ? math.max(armedLongPrice - setupLowest, syminfo.mintick) : na
riskDistShort = shortArmed ? math.max(setupHighest - armedShortPrice, syminfo.mintick) : na

riskCapital = strategy.equity * (riskPctInput / 100)

qtyLong = if useRiskSizeInput
    na(riskDistLong) ? 0 : math.floor(riskCapital / (riskDistLong * syminfo.pointvalue))
else
    fixedQtyInput

qtyShort = if useRiskSizeInput
    na(riskDistShort) ? 0 : math.floor(riskCapital / (riskDistShort * syminfo.pointvalue))
else
    fixedQtyInput

longSizeOK  = qtyLong  >= 1
shortSizeOK = qtyShort >= 1

// =============================================================================
// FILTERS
// =============================================================================
inDateRange = not useDateInput or (time >= startDateInput and time <= endDateInput)

// =============================================================================
// ENTRIES  [HER]
// A stop order at the trigger price — her rule is "enter at the highest high of
// the two bars", i.e. a breakout stop, not a market order at the close.
// strategy.entry auto-reverses an opposite position, which is exactly her
// stop-and-reverse exit. No separate exit call is needed for the core system.
// =============================================================================
// The position guards matter. Without them the base entry would be re-issued on
// every armed bar while already in the trade, and with pyramiding > 0 that
// silently stacks contracts the pyramid rule never authorised. Guarded this way
// the base stop works only when flat or opposite — which is exactly her
// stop-and-reverse behaviour, since strategy.entry auto-reverses.
canLong  = allowLongsInput  and longArmed  and longSizeOK  and inDateRange and proGoLongOK  and strategy.position_size <= 0
canShort = allowShortsInput and shortArmed and shortSizeOK and inDateRange and proGoShortOK and strategy.position_size >= 0

if canLong
    strategy.entry("Long", strategy.long, qty = qtyLong, stop = armedLongPrice,
         alert_message = "18BAR LONG stop @ " + str.tostring(armedLongPrice, format.mintick))

if canShort
    strategy.entry("Short", strategy.short, qty = qtyShort, stop = armedShortPrice,
         alert_message = "18BAR SHORT stop @ " + str.tostring(armedShortPrice, format.mintick))

// Cancel a working stop order once its setup has expired, so a stale order
// cannot fill on unrelated price action later.
if not canLong
    strategy.cancel("Long")
if not canShort
    strategy.cancel("Short")

// =============================================================================
// PYRAMIDING ON MA RETESTS  [HER: first two retests only]
// She adds on retests of the MA and explicitly flags the third+ retest as much
// higher risk. Counter resets whenever the position goes flat or flips.
// =============================================================================
var int addOnCount = 0
if strategy.position_size == 0 or (strategy.position_size > 0) != (strategy.position_size[1] > 0)
    addOnCount := 0

touchedMALong  = strategy.position_size > 0 and low <= maVal and close > maVal
touchedMAShort = strategy.position_size < 0 and high >= maVal and close < maVal

// Fixed entry IDs on purpose. A computed id ("Long Add " + count) relies on
// strategy.entry accepting a series string, which is an unnecessary risk when a
// constant id behaves identically here — addOnCount already caps the adds.
if usePyramidInput and addOnCount < maxAddOnsInput
    if touchedMALong and longSizeOK
        addOnCount += 1
        strategy.entry("LongAdd", strategy.long, qty = qtyLong)
    if touchedMAShort and shortSizeOK
        addOnCount += 1
        strategy.entry("ShortAdd", strategy.short, qty = qtyShort)

// =============================================================================
// [FIX] EXIT ON THE OPPOSITE SETUP WHEN REVERSING IS DISALLOWED
// Her system's ONLY exit is the reverse trade. With shorts disabled (the
// validated default), the reverse can never fire — so without this block a
// long-only run would buy once and hold forever. The opposite SETUP still
// closes the position (a sell stop at the short trigger price); it just does
// not open the opposite trade. Mirrors the validated Python engine exactly.
// strategy.exit without from_entry covers the base entry AND any pyramid adds.
// =============================================================================
if strategy.position_size > 0 and not allowShortsInput
    if shortArmed
        strategy.exit("RevExit L", stop = armedShortPrice)
    else
        strategy.cancel("RevExit L")

if strategy.position_size < 0 and not allowLongsInput
    if longArmed
        strategy.exit("RevExit S", stop = armedLongPrice)
    else
        strategy.cancel("RevExit S")

// =============================================================================
// OPTIONAL PROTECTIVE STOP  [MINE — explicitly NOT part of her system]
// Her published system has no stop other than the opposite signal. Enabling
// this makes the backtest safer but less faithful; it is off by default so the
// default run reflects what she actually describes.
// =============================================================================
if useProtStopInput and strategy.position_size > 0
    strategy.exit("Long Prot", stop = strategy.position_avg_price - atrVal * atrStopMultInput)
if useProtStopInput and strategy.position_size < 0
    strategy.exit("Short Prot", stop = strategy.position_avg_price + atrVal * atrStopMultInput)

// =============================================================================
// PLOTS
// =============================================================================
plot(maVal, "18 MA", color = color.new(color.orange, 0), linewidth = 2)

plotshape(longArmed and not longArmed[1], title = "Long Setup Armed", style = shape.triangleup,
     location = location.belowbar, color = color.new(color.teal, 0), size = size.tiny)
plotshape(shortArmed and not shortArmed[1], title = "Short Setup Armed", style = shape.triangledown,
     location = location.abovebar, color = color.new(color.maroon, 0), size = size.tiny)

plot(longArmed  ? armedLongPrice  : na, "Long Trigger",  color = color.new(color.teal, 0),   style = plot.style_linebr)
plot(shortArmed ? armedShortPrice : na, "Short Trigger", color = color.new(color.maroon, 0), style = plot.style_linebr)

// Diagnostic: a valid setup skipped because the risk budget could not fund one
// contract. If this litters the chart, raise capital or use micro contracts.
plotchar(useRiskSizeInput and ((longArmed and not longSizeOK) or (shortArmed and not shortSizeOK)),
     title = "Skipped: under 1 contract", char = "!", location = location.top,
     color = color.new(color.yellow, 0), size = size.tiny)

// =============================================================================
// ALERTS
// alertcondition() is deliberately NOT used: it compiles inside a strategy but
// is silently inert — TradingView only raises those events from indicators.
// =============================================================================
if canLong and not canLong[1]
    alert("18BAR long setup armed. Buy stop @ " + str.tostring(armedLongPrice, format.mintick),
         alert.freq_once_per_bar_close)
if canShort and not canShort[1]
    alert("18BAR short setup armed. Sell stop @ " + str.tostring(armedShortPrice, format.mintick),
         alert.freq_once_per_bar_close)
For AI tools & developers:View Markdown →

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
Markdown version
Verified by MonsterInsights