TradingView Backtesting

Equity-Curve Filters: Strategy Returns as a Tradable State

Equity curve trading uses the performance of a fixed reference strategy to permit or block later entries. A moving-average filter takes the next eligible trade only when previously observed reference equity is above its average. Keep the unfiltered strategy running in simulation during every pause; otherwise the filtered account can stop producing the observations needed to restart. Lower drawdown can come with lower profit because the filter also misses recoveries.

See the decision guide

Freeze the strategy before adding the switch

The research question is whether one predeclared participation rule improves an unchanged strategy. Save the strategy version, parameters, symbol, timeframe, session, test dates, initial capital, position sizing, pyramiding, commission and slippage. Run that reference continuously. Changing its entry logic or size while selecting the equity-average length makes it impossible to attribute a difference to the filter alone.

  • Define the observation clock: the example below advances after each reference trade closes. A 20-trade average spans a variable amount of calendar time; it is not a 20-day average.
  • Choose closed-trade equity or regularly sampled mark-to-market equity. Closed-trade equity waits for exits and does not show losses accumulating in open positions.
  • Keep the reference sizing independent of filtered equity. This example uses fixed cash P&L amounts with no compounding, external cash flows, leverage constraint or interaction between trades.
  • The ten-trade ledger below is a frozen hypothetical input for testing the controller. It is not a historical result for a price-entry strategy or evidence that the filter improves trading performance.

A causal three-trade moving-average rule

Let S(t) be shadow equity after reference trade t closes, and p(t) its net cash P&L. S(t) = S(t-1) + p(t), whether or not the filtered account took that trade. With three completed reference trades, M(t) = [S(t) + S(t-1) + S(t-2)] / 3. Before trade t+1 enters, set its gate to 1 only if S(t) > M(t). Filtered equity then changes by gate × p(t+1) at that trade's exit.

  • Warm-up policy: take the first three reference trades. The initial $10,000 balance is not one of the three closing-equity observations used by the average.
  • Equality policy: S(t) = M(t) means pause. This matters on flat histories and at trade 10 below. Changing > to >= is a different rule.
  • Timing assumption: each reference trade fully exits, its result becomes available, and only then does the next entry decision occur. Equal timestamps require an explicit event order; do not assume a close result was available to an earlier order.
  • The gate controls new entries. A pause does not liquidate an existing position or cancel its protective exit. Forced liquidation would need a different simulation with its own fills and costs.

Follow every trade through the pause and restart

Start both accounts at $10,000. The fixed reference gross P&L sequence is +220, +120, -180, -280, -80, +420, +220, -180, +120, +220 dollars. Each executed trade has a $20 total round-trip cost, including the assumed commission and slippage allowance. Shadow P&L deducts that same hypothetical cost on every reference trade; the filtered account pays it only for trades it takes. The gate and average in each row are known before that row's trade enters. Displayed averages are rounded; decisions use full precision.

  • The first pause covers trades 4 through 6. It avoids $400 of net losses but also misses the $400 rebound in trade 6. Only after that rebound closes does the shadow state permit trade 7.
  • The second pause covers trades 9 and 10, skipping another $300 of net profit. The equality rule blocks trade 10. After trade 10 closes, shadow equity is above its average again, so trade 11 would be permitted if a new reference entry occurred.
  • The filtered balance stays at $10,100 during the first pause, but shadow equity moves through $9,800, $9,700 and $10,100. Using only the frozen filtered balance would discard the recovery evidence.
TradeReference net P&LShadow before entryPrior 3-close averageGateShadow after exitFiltered after exit
1+$200$10,000Warm-upTake$10,200$10,200
2+$100$10,200Warm-upTake$10,300$10,300
3-$200$10,300Warm-upTake$10,100$10,100
4-$300$10,100$10,200.00Pause$9,800$10,100
5-$100$9,800$10,066.67Pause$9,700$10,100
6+$400$9,700$9,866.67Pause$10,100$10,100
7+$200$10,100$9,866.67Take$10,300$10,300
8-$200$10,300$10,033.33Take$10,100$10,100
9+$100$10,100$10,166.67Pause$10,200$10,100
10+$200$10,200$10,200.00Pause$10,400$10,100

Lower drawdown does not imply a better outcome

Evaluate both accounts over the same ten reference opportunities, including the five skipped opportunities in the filtered history. For each path, the running peak is the maximum of initial capital and all observed balances so far. Drawdown is peak minus current balance; percentage drawdown divides that shortfall by its contemporaneous peak. These are closed-trade observations, not intratrade risk measurements.

  • The reference falls from $10,300 after trade 2 to $9,700 after trade 5: 600 / 10,300 = 5.83%. The filtered path falls from the same peak to $10,100: 200 / 10,300 = 1.94%.
  • Five skipped opportunities mean 50% participation by trade count. They do not establish 50% time in market, because this example has no holding timestamps or calendar duration.
  • The filter loses $300 of net profit relative to the reference despite its smaller drawdown. No Sharpe ratio, CAGR or statistical significance is inferred from this short, undated example.
MeasureUnfiltered referenceFiltered account
Trades taken10 of 105 of 10
Gross cash P&L+$600+$200
Round-trip costs paid$200$100
Net profit / ending equity+$400 / $10,400+$100 / $10,100
Return on initial capital4.00%1.00%
Maximum observed drawdown$600 / 5.83%$200 / 1.94%
New-entry pause episodesNoneTrades 4-6 and 9-10

Reproduce the controller outside the report

This standalone Python calculation reproduces the ledger. It accepts one net cash P&L value per completed, non-overlapping reference trade in chronological order. Supply net values once: do not deduct exported commissions twice. Its input contract requires each result to be available before the next entry; an arbitrary list sorted by exit time does not establish that condition.

Python 3, no packages required. Fixed-size ledger replay, not a broker emulator or a TradingView order script.python
from math import isfinite


def equity_filter(net_pnl, window=3, initial=10000):
    if not isinstance(window, int) or isinstance(window, bool) or window < 2:
        raise ValueError("window must be an integer >= 2")
    if not isfinite(initial) or initial <= 0:
        raise ValueError("initial equity must be positive and finite")
    if any(not isfinite(p) for p in net_pnl):
        raise ValueError("missing or nonfinite P&L")
    shadow = filtered = initial
    closes = []
    rows = []
    for number, pnl in enumerate(net_pnl, 1):
        average = sum(closes[-window:]) / window if len(closes) >= window else None
        take = average is None or shadow > average
        before = shadow
        shadow += pnl  # Update even while the filtered account is paused.
        filtered += pnl if take else 0
        if shadow <= 0 or filtered <= 0:
            raise ValueError("equity depleted; model funding and margin separately")
        rows.append((number, pnl, before, average, take, shadow, filtered))
        closes.append(shadow)
    return rows


gross = [220, 120, -180, -280, -80, 420, 220, -180, 120, 220]
rows = equity_filter([p - 20 for p in gross])
for row in rows:
    print(row)
assert [r[4] for r in rows] == [True, True, True, False, False, False,
                                      True, True, False, False]
assert rows[-1][5:] == (10400, 10100)

Execution and accounting can invalidate a simple replay

Deleting losing-looking rows from an export is not a causal backtest. At each candidate entry, the controller may use only the reference state already observable at that timestamp. When positions overlap, a trade with an earlier entry can close after several later entries; its final P&L was unavailable to those decisions.

  • For overlapping positions, replay entries, exits and valuations in time order with separate reference and filtered position books. Maintain the reference positions while paused. Use only completed exits or the explicitly chosen mark-to-market observations at each decision.
  • If skipped trades change available margin, percent-of-equity sizing, pyramiding, reversal behavior or later strategy signals, copying fixed baseline P&L into the filtered ledger is insufficient. Re-simulate those dependencies and state them in the baseline specification.
  • A close-based permission check cannot guarantee an execution at that same closing price. TradingView normally fills a newly created market order on the next available tick. Model the chosen calculation settings, order timing and any operational delay.
  • A slower average can prolong a pause; a faster average can repeatedly switch around the threshold. A minimum pause or separate restart threshold adds another rule to validate, not a free improvement.
  • Include the costs of actual permitted trades. If the overlay forcibly exits or re-enters positions, add those extra fills, spreads and slippage. Cash yield during pauses is zero here; model it separately if relevant.

Use TradingView exports and Pineify for their supported roles

TradingView exports Strategy Report tabs separately. Obtain the List of Trades CSV for trade records, retain the settings, and reconcile the number of completed trades and summed net cash P&L against the source report. Pineify Backtest Deep Report parses entry and exit times, prices, quantity, net P&L and excursion data. It calculates net profit and an equity path from trade P&L, with drawdown measurements. Those fields support a baseline audit; they do not establish an equity-filter backtest.

  • Keep one completed trade result per reference opportunity. Check entry/exit pairing, partial exits, open trades, timezone and missing rows before replay. Inspect the actual CSV headers and parsed values rather than assuming every export format is interchangeable.
  • The report currently has no dedicated shadow-equity gate, pause-interval or restart simulation field. Compute this page's filter and comparison independently using the code or a worksheet; do not describe a plotted equity curve as the filter implementation.
  • A trade export does not contain the complete mark-to-market path of all open positions at every decision time. Obtain the necessary observations separately if that is your selected equity definition.
  • For an in-chart implementation, the Pine Script AI Coding Agent can help draft custom code. Specify two independent books, known-time decisions and unchanged exits, then review and test the result. Using filtered strategy.equity as the sole reference does not satisfy this page's shadow-ledger rule.

Test the extra rule on unseen history

An equity trend predicts later strategy outcomes only if there is useful dependence that persists into the evaluation period. A historical run of losses followed by more losses is not sufficient evidence by itself. An independent return sequence offers no predictive information from its past; a mean-reverting sequence can make pausing after losses particularly costly.

  • Choose the equity definition, window, warm-up, equality policy and execution lag on development data, then freeze them before the holdout. Keep the baseline fixed too.
  • At the holdout boundary, carry only state that would have been known then, including prior shadow observations and open reference positions. Do not reset a paused controller to active just to begin the evaluation.
  • Report both profit and risk, trade participation, calendar exposure where timestamps exist, every pause start and end, restart delay and net P&L missed while paused. Include unresolved pauses at the end of the sample.
  • Disclose all tried window lengths and rule variants. Compare nearby settings and additional chronological periods; selecting the best historical switch after many trials increases selection bias.
Where Pineify fits

Backtest Deep Report

Review a compatible TradingView trade CSV and reconcile baseline P&L and drawdown. Calculate the shadow-equity filter independently; it is not a built-in report method.

Also useful: Pine Script AI Coding Agent. Draft custom strategy logic from a specification that separates the reference book from the filtered book, then verify its timing and accounting.

Explore Backtest Deep Report

Frequently asked questions

Educational information, not investment advice. The ledger is hypothetical and illustrates a research method. It is not measured market performance, a live execution result or a promise of lower future losses.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.