TradingView Backtesting

Simple vs Log Returns in Pine Script and Backtest Analysis

A log return is the natural logarithm of a positive growth factor: r = ln(P₁ / P₀) = ln(1 + R), where R is the simple return. Convert back with R = exp(r) - 1. Log returns add across consecutive periods for the same investment. Across assets in one period, combine simple returns using beginning-of-period portfolio weights, then take the log of the portfolio growth factor.

See the decision guide

Convert a single period without mixing units

Use the natural logarithm, not base 10. For this price-only calculation, assume positive prices, no distributions and no trading costs. R = P₁ / P₀ - 1; r = ln(1 + R). A percentage label means 100 times the decimal value. These identities follow the return definitions in Eric Zivot's textbook linked below.

  • Calculate ln(1 + 0.10) for a 10% simple gain. Feeding 10 into that formula means a 1,000% gain.
  • For small changes, ln(1 + R) is close to R. At a 1% simple return, the log return is 0.9950%; at a 50% simple return, it is 40.5465%. Use the exact conversion when reconciling results.
  • Log returns are a representation of growth. Calling a return continuously compounded does not establish that a trading strategy reinvested every profit.
Hypothetical price moveSimple return RLog return rReverse conversion
100 to 1100.10 = 10.0000%0.095310 = 9.5310%exp(0.0953101798) - 1 = 0.10
100 to 90-0.10 = -10.0000%-0.105361 = -10.5361%exp(-0.1053605157) - 1 = -0.10
100 to 1000 = 0%0 = 0%exp(0) - 1 = 0

Across time: multiply growth factors or add log returns

Consider one hypothetical investment with values 100, 150 and 75 at three consecutive boundaries. There are no external cash flows, income payments or costs. The full-period simple return is the product of the two growth factors minus one; the full-period log return is the sum of the two logs.

  • Adding the simple returns gives 0%, which misses the loss. Reporting the log total as a -28.7682% account loss is also wrong: the account lost 25%.
  • Use consecutive, non-overlapping periods from the same value series. Adding rolling 20-bar log returns double-counts overlapping intervals.
  • Deposits and withdrawals break a raw account-value ratio. Segment at external flows before linking performance returns; a log transformation cannot distinguish funding from investment gains.
IntervalGrowth factorSimple returnLog return, decimal
100 to 1501.50+50%ln(1.50) = 0.405465
150 to 750.50-50%ln(0.50) = -0.693147
100 to 751.50 × 0.50 = 0.75-25%ln(0.75) = -0.287682
Reproduce the hypothetical two-period result with full precisiontext
Simple total = (1 + 0.50) * (1 - 0.50) - 1 = -0.25
Log total = ln(1.50) + ln(0.50) = -0.2876820725
Convert log total = exp(-0.2876820725) - 1 = -0.25

Mean log return = -0.2876820725 / 2 = -0.1438410362
Geometric mean simple return = exp(-0.1438410362) - 1
                            = -0.1339745962 per period

Across assets: calculate the portfolio return first

Now put $500 in asset A and $500 in asset B at the same starting time. Over one period, A gains 50% and B loses 50%. Hold both positions through the period, with no flows, trading costs or distributions. A ends at $750 and B at $250, so the $1,000 portfolio is unchanged.

  • For a fully invested portfolio over one holding interval, Rₚ = Σ(wᵢRᵢ), with weights measured at the start. Then rₚ = ln(1 + Rₚ). If inputs are asset log returns, convert each with exp(rᵢ) - 1 before weighting.
  • These are fractions of invested value, not share counts. After this example, the buy-and-hold weights are 75% and 25%. Keeping 50% and 50% for the next period assumes rebalancing.
  • Align asset timestamps, currency and income treatment. Include cash and financing where applicable. Intraperiod trades require an equity ledger or smaller holding intervals; stale opening weights cannot describe arbitrary trading.
CalculationResultMeaning
0.5 × 50% + 0.5 × (-50%)0%Portfolio simple return using starting value weights
ln(1 + 0)0Portfolio log return
0.5 × ln(1.50) + 0.5 × ln(0.50)-0.143841Weighted asset logs; not the portfolio log return
exp(-0.1438410362) - 1-13.3975%Incorrect portfolio result if weighted logs are used

Plot confirmed simple and log returns in Pine Script

This Pine Script v6 indicator compares adjacent chart closes. It waits for the current bar to close and returns na unless both prices are present and strictly positive. The shared positive-price filter makes the two plotted series comparable. This is a chart-price calculation, not a strategy equity return or a trading signal.

  • On the first available bar, close[1] is missing, so both outputs remain na. The open realtime bar is also blank until confirmed. The script does not replace missing returns with zero.
  • A closed bar with prior close 100 and current close 110 should display 10.0000 and 9.5310. Use the Data Window to inspect both series on the same bar.
  • The logarithm difference equals ln(close / close[1]) for positive prices. A log chart setting changes the axis; it does not turn close into a log return.
  • Use standard price bars and record the symbol, timeframe, session and adjustment settings. Heikin Ashi or other synthetic closes measure a constructed series rather than executable market prices.
Pine Script v6: percentage display, confirmed bars and explicit missing valuespine
//@version=6
indicator("Simple and log returns", overlay = false, precision = 4)

bool hasPositivePair = not na(close) and not na(close[1]) and close > 0 and close[1] > 0
bool canCalculate = hasPositivePair and barstate.isconfirmed
float simpleReturn = canCalculate ? close / close[1] - 1.0 : na
float logReturn = canCalculate ? math.log(close) - math.log(close[1]) : na

plot(100.0 * simpleReturn, "Simple return (%)", color = color.blue, style = plot.style_linebr)
plot(100.0 * logReturn, "Log return (100 x decimal)", color = color.orange, style = plot.style_linebr)
hline(0.0, "Zero", color = color.gray)

Reject invalid prices and preserve missing intervals

A conventional price-based log return needs two strictly positive prices. A positive price falling to zero has a valid -100% simple return, but no finite log return. The example script deliberately leaves both series blank for that pair; record the total loss separately instead of treating the blank as no change.

  • If a feed omits a bar entirely, close[1] means the previous available bar. A price change from 100 on Monday to 110 on Wednesday spans the gap; it is not an observed one-day Tuesday return.
  • Scheduled weekends and exchange closures differ from missing observations. Define the sampling calendar before comparing daily statistics across markets.
  • Summing only the available log returns can omit an unknown interval. Do not label that sum a complete return for the original window. Two valid endpoints can support an endpoint return, but cannot reconstruct missing intraperiod volatility.
Input conditionMathematical issueHandling
Previous price is zeroThe price ratio divides by zero.Return is undefined; do not substitute a small denominator.
Current price is zero; prior price positiveln(0) has no finite value.Report a total loss separately; exclude it from finite log statistics.
Either price is negativeA sign change has no real log ratio; two negative prices can give a positive ratio without a valid positive-wealth interpretation.Use contract P&L and a defined capital base; do not take absolute prices or add a constant.
A required observation is missingThe intended adjacent-period return is unknown.Keep na and investigate the data gap before aggregating.

Use a consistent split and dividend adjustment basis

An unadjusted two-for-one split can move a quote from 100 to 50 while doubling the number of shares. A raw price ratio would show -50% simple return and ln(0.5) log return even though the holding value is unchanged. Use a consistently split-adjusted series or an account ledger that tracks the share change.

  • Price return and total return answer different questions. If a hypothetical share starts at 100, ends at 98 and pays a cash dividend of 2 at the end of the interval, its price return is -2% while its pre-tax holding-period total return is (98 + 2) / 100 - 1 = 0%.
  • TradingView describes its dividend-adjusted chart as a total-return view. Confirm that adjustment is available and enabled for the chosen symbol, and record the setting when exporting or comparing data.
  • Do not add the dividend again to an already dividend-adjusted return series. A multi-period total-return calculation also needs a consistent reinvestment convention.
  • The Pine example uses the closes supplied by the chart and does not request a separate adjustment basis. Changing chart data settings can change historical return values.

Reconcile return statistics before comparing backtests

Keep the return type, period and capital denominator beside each result. A trade percentage refers to its position; a bar-by-bar account return refers to total account equity. Overlapping positions, idle cash and changing position sizes prevent a list of trade percentages from acting as consecutive whole-account returns.

  • Backtest Deep Report accepts TradingView List of Trades CSV exports and calculates supported results such as net profit, profit factor and drawdown. Check the imported trades and initial capital before comparing them with TradingView.
  • The trade report does not supply the complete adjusted price series used above. Keep log-return calculations separate unless you have verified the exact statistic and its inputs; do not assume a return-distribution chart is plotting log returns.
  • For custom Pine statistics, ask Pine Script AI Coding Agent to use an explicit value series and missing-data rule. Reproduce a few bars manually, then check the full period against the endpoint growth factor.
  • A log transformation does not remove commissions, slippage or financing. Calculate the appropriate net account values first. Return representation alone says nothing about future profitability.
Where Pineify fits

Backtest Deep Report

Inspect supported profit and risk metrics from your TradingView trade CSV. Reconcile the capital basis and trade records, and calculate price-series log returns separately.

Also useful: Pine Script AI Coding Agent. Draft a custom return calculation with explicit inputs and invalid-value handling, then compare its output with an independent calculation.

Review exported trades

Frequently asked questions

Educational information, not investment advice. All numerical examples are hypothetical arithmetic examples, not observed trading performance. The Pine indicator measures chart-price changes and does not place orders or predict returns.

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.