Quant from Scratch by QuantWright

Introduction to Quant Finance · Lesson 7

Returns, three ways

A result means little until you fix its unit. Percent, log return and R: what each one counts, and when to use it.

Know the basics? Read the lesson notes

Who did better?

A trade is one buy and the sell that closes it. Two friends each post the result of one trade. The first made $300. The second made $200. Who did better?

Not from dollars alone. It depends on how much each one put in to make it.
Both made money, but not equally well for what they put in.
Right: a dollar result depends on how much was put in.
The first put $10,000 into the trade, the second $2,000. As a share of what went in: 300 ÷ 10,000 = 0.03, or 3%, and 200 ÷ 2,000 = 0.10, or 10%. The second got more for each dollar. A result as a share of what went in is the percent return. For a price, it's new price ÷ old price − 1 (the − 1 takes away the part you started with): a price going from $50 to $52 is 52 ÷ 50 − 1 = 0.04, or 4%.

+50%, then −50%

Percent fixes the size problem. Now a second problem, about time. An account starts at $10,000, and each trade puts in the whole account. The first trade makes +50%. The second loses 50%. Where does the account end?

Keep your guess in mind. On the next screen you run both trades.

Run the two trades

Press each trade, in either order. The bars show what the account holds after each one.

An account of $10,000 and two trades (made-up numbers)

Each bar is the account after a trade. Dashed: the $10,000 start.

Percents added up0%
Account$10,000
Change from the start0%

+50% and −50% add up to 0%, yet the account ends at $7,500: 25% down.

Each percent applies to what the account holds at that moment. The +50% trade multiplies the account by 1.5, the −50% trade by 0.5, and 1.5 × 0.5 = 0.75, in either order. That multiplier, new ÷ old, is called the growth factor. Percent returns over time multiply; adding them gives the wrong answer.

A unit that adds up: the ln key

It would help to count returns in a unit that simply adds up over time. There is one. Every scientific calculator and spreadsheet has a key called ln, the natural logarithm. You don't need to know how it works inside, only what it does: it turns multiplying into adding. For any two numbers above zero, a and b: ln(a × b) = ln(a) + ln(b).

Growth factors multiply (1.5 × 0.5), and ln turns a product into a sum, so the ln of each factor can simply be added. The log return of a trade is ln of its growth factor. Tap each number to put it in the calculator, then press ln: (the +50% trade), (the −50% trade) and (both together).

    ln(1.5) + ln(0.5) = 0.405 + (−0.693) = −0.288, which is ln(0.75). The two trades' log returns add up to the log return of both together.

    Log returns are written as plain decimals (0.405, not a percent), so they don't get mixed up with percents. To turn one back into a growth factor, use the key that undoes ln, eˣ: type −0.288 and press eˣ, and you get 0.75, which is 25% down.

    Drag the end of a price path

    Here is a made-up price over five days. Each day has a percent return and a log return (ln of that day's price ÷ the day before's). Drag the end of the line, or use the slider: first until the five daily percents add up to 0.0%, then until the five daily logs add up to 0.000.

    A made-up price, five days (simulated)

    Dashed: the $100 start. Drag the orange end point.

    Day 1Day 2Day 3Day 4Day 5
    Percent
    Log
    Daily percents added up–
    Daily logs added up–
    Percents at 0.0%: day 5 price?
    Logs at 0.000: day 5 price?

    The percents added up to 0.0% with the price at $99.30, below the $100 start. The logs added up to 0.000 with the price at $100.00, exactly back at the start. Daily log returns always add up to the log return from start to end; daily percents don't.

    The gap is small here because each day moves only a few percent, and for small moves the two are nearly equal (day 1: −0.0513 as a percent return, −0.0527 as a log return). Big moves, like +50% and −50%, pull them far apart.

    R: a result in units of risk

    Percent says what a trade did to the account. It doesn't say how much the trade put at risk to get there. Many traders decide, before they buy, the price at which they'll sell if the trade goes wrong. That price is the stop. The money lost if the price falls to the stop is the trade's risk.

    R counts a result in units of that risk: result ÷ risk. A trade that risked $400 and made $1,200 made 1,200 ÷ 400 = +3R. One that fell to its stop lost exactly its risk: −1R.

    This trade bought 200 shares (small pieces of a company) at $50 each, the whole $10,000 account, and sold them 8 days later at $56. Drag the stop line and make this same trade worth exactly +2R.

    One made-up trade, 8 days (simulated)

    Dashed: the $50 buy. Orange line: the stop. Shaded: the risk, from the buy down to the stop.

    Result–
    Risk–
    Result in R–

    Stop at $47: the risk is 200 × ($50 − $47) = $600, and $1,200 ÷ $600 = +2R.

    Moving the stop changed only R. The result, $1,200 or +12% of the account ($1,200 ÷ $10,000), stays put, because the trade itself didn't change. R is the one unit of the three that asks how much was at risk. That makes it honest only when the stop was set before the buy: a stop picked afterwards can make any winning trade look like many R.

    Two backtests, two sizes

    A backtest replays a trading rule on past prices to see what it would have made. Two backtests each ran 100 trades. The first risked $50 a trade and made $1,500 in total. The second risked $500 a trade and made $5,000. Which rule did more with what it risked?

    In R: the first made 1,500 ÷ 50 = 30R over 100 trades, 0.3R a trade. The second made 5,000 ÷ 500 = 10R, 0.1R a trade. Its dollars were bigger only because it risked ten times as much on each trade.
    It made more dollars because it risked ten times as much on each trade. In R it made 5,000 ÷ 500 = 10R, against 1,500 ÷ 50 = 30R for the first.
    Making money isn't the test. In R the first made 30R and the second 10R: 0.3R a trade against 0.1R.
    Counted in R, the size each backtest happened to trade drops out, and the two rules can be compared directly.
    Theory

    Simple returns multiply, log returns add

    The percent return has a textbook name: the simple return. Over time, simple returns combine by multiplying their growth factors; log returns combine by adding. The reason: the growth factor from the first price to the last is the product of each period's factor, Pn ÷ P0 = (P1 ÷ P0) × (P2 ÷ P1) × … × (Pn ÷ Pn−1), because the prices in between cancel. ln turns that product into a sum.

    r = P1 ÷ P0 − 1
    ℓ = ln(P1 ÷ P0)
    r = eℓ − 1   (the way back)
    ℓtotal = ℓ1 + ℓ2 + … + ℓn
    Pn ÷ P0 = eℓtotal
    P0, P1
    the price, or the account, at the start and at the end of one period (a day, or a trade)
    P1 ÷ P0
    the growth factor of that period
    r
    the simple return, as a decimal: 0.5 is +50%
    ℓ
    the log return of one period (ℓ is a handwritten l, for log). For small moves ℓ ≈ r: a +1% day (r = 0.01) has ℓ = 0.00995
    ln
    the natural logarithm: the ln key
    ℓ1 … ℓn
    the log returns of n periods in a row
    ℓtotal
    the log return from the first price, P0, to the last, Pn
    ex
    the eˣ key, which undoes ln (e is a fixed number, about 2.718)
    Worked example: your two trades

    Simple returns: r1 = 1.5 − 1 = +0.5 and r2 = 0.5 − 1 = −0.5. They add up to 0, but the growth factors multiply: 1.5 × 0.5 = 0.75.

    Log returns: ℓ1 = ln(1.5) = 0.405 and ℓ2 = ln(0.5) = −0.693, so ℓtotal = 0.405 − 0.693 = −0.288. Back: r = e−0.288 − 1 = 0.75 − 1 = −0.25. The account ended at 0.75 × $10,000 = $7,500, a simple return of −25%.

    Holds when
    • nothing is paid into or taken out of the account between the start and the end (a deposit would look like a gain);
    • prices stay above zero: there is no ln of zero, so a log return can't describe losing everything.
    Breaks when

    Log returns add over time, not across things held side by side: if you split money between two things (say, two stocks), the account's return is the weighted average of their percent returns (the plain average if the split is even), not of their log returns (lesson C11, Diversification). Averages of simple returns over time overstate growth when the returns swing a lot (lesson A14, Compounding and the asymmetry of losses).

    Try it on new numbers, with the ln key below. A price goes from $40 to $50, then to $45. What is its log return from $40 to $45?

      ln(50 ÷ 40) + ln(45 ÷ 50) = ln(1.25) + ln(0.9) = 0.223 + (−0.105) = 0.118, the same as ln(45 ÷ 40) in one go.
      Add the two moves' logs: ln(50 ÷ 40) + ln(45 ÷ 50) = 0.223 + (−0.105) = 0.118, or take ln(45 ÷ 40) in one go. If you got 0.125, that is the simple return, 45 ÷ 40 − 1.
      Theory

      The R-multiple

      A result counted in units of the risk set before the trade is called an R-multiple. For a buy with its stop below the buy price:

      risk = N × (Pbuy − Pstop)
      result in R = result ÷ risk
      result = result in R × risk
      N
      the number of shares bought
      Pbuy
      the buy price
      Pstop
      the stop: the price at which the trade will sell if it goes wrong
      risk
      the dollars lost if the price falls to the stop and the trade sells there
      result
      what the trade made or lost in dollars: what came back minus what went in
      result in R
      the R-multiple: +2R made twice the risk; −1R lost exactly the risk
      Worked example: your trade

      Risk = 200 × ($50 − $47) = $600. Result = 200 × ($56 − $50) = $1,200. Result in R = 1,200 ÷ 600 = +2R. With the stop at $48, the risk is $400 and the same trade is +3R.

      Back to dollars: +2R × $600 = $1,200.

      Holds when
      • the stop is set before the buy and isn't moved afterwards;
      • the trade really sells at the stop price when the price reaches it;
      • risk is counted the same way on every trade.
      Breaks when

      A price can jump past the stop, overnight or on news, and the trade sells lower: a loss bigger than 1R (lesson A13, Orders: market, limit and stop). Trading costs add to every loss (lesson A16, Costs).

      Try it on new numbers. You buy 300 shares at $20 with a stop at $19, and sell at $23.50. What is the result in R?

      Risk = 300 × ($20 − $19) = $300. Result = 300 × ($23.50 − $20) = $1,050. In R: 1,050 ÷ 300 = +3.5R.
      Risk = 300 × ($20 − $19) = $300. Result = 300 × ($23.50 − $20) = $1,050. In R: 1,050 ÷ 300 = +3.5R. The number of shares cancels out: $3.50 gained per share against $1 risked per share.

      What this means for your backtest

      A backtest reports results. Before you compare two of them, check which unit each one is in. Turn over the three units one at a time.

      1. To compare trades of different sizes, use percent of the account.

        $300 is 3% of $10,000 and 10% of $2,000. Dollars only compare when the same amount went in.

      Whichever unit you use, say which one. "+12" means nothing until you know whether it's $12, 12%, a log return of 0.12 or 12R.

      Practice 1 of 3

      "I'm back to even"

      The situationA friend's account made +20% on one trade and −20% on the next. Each trade put in the whole account. They say they're back to even.

      Use the ln key below. What is the account's log return over the two trades? If they were back to even, it would be 0.000.

        Hint: the growth factors are 1.2 (+20%) and 0.8 (−20%). Take ln of each and add them up.

        ln(1.2) + ln(0.8) = 0.182 + (−0.223) = −0.041. Back: e−0.041 − 1 = 0.96 − 1 = −0.04, so the account is 4% down, not even.
        ln(1.2) + ln(0.8) = 0.182 + (−0.223) = −0.041. Back: e−0.041 − 1 = −0.04, so the account is 4% down. Adding the percents (+20 − 20 = 0) is the friend's mistake: the −20% applied to a bigger account than the +20% did.
        Practice 2 of 3

        "+12R last month"

        The situationA made-up seller of trading signals posts: "Last month: +12R." The small print says each trade risked $50, on a $10,000 account.

        By what percent did that account grow last month? Type it in percent.

        Hint: R × the risk per trade gives dollars. Dollars ÷ the account gives the percent.

        12 × $50 = $600, and 600 ÷ 10,000 = 0.06: +6%.
        +12R is not +12%. 12 × $50 = $600, and 600 ÷ 10,000 = 0.06: +6%. The same +12R would be +24% if each trade had risked $200.
        A result in R says nothing about the account until you know the risk per trade.
        Practice 3 of 3

        A year in a spreadsheet

        The situationYour own backtest's spreadsheet adds up a year's 250 daily percent returns and reports the total, +20%, as the year's return.

        Is +20% the year's return?

        Percents don't add over time; the sum is only close when every move is small. +50% then −50% added up to 0% but ended 25% down.
        Multiply the 250 growth factors (each 1 + that day's return) and subtract 1. Adding the 250 daily log returns and pressing eˣ gives the same, and so does last value ÷ first value − 1.
        Log returns add up over time; they don't average to the year's. Their sum is the year's log return; their average is a typical day's.
        ✓

        Lesson done

        A result means little until you fix its unit. Percent of the account compares trades of different sizes. Log returns add up over time, where percents multiply. R measures a result against what the trade risked. Whichever you use, say which.

        Key ideas

        Simple (percent) return
        the change as a share of the start: new ÷ old − 1
        Growth factor
        new ÷ old: what the account is multiplied by (1.5 for +50%)
        Log return
        ln of the growth factor; log returns add up over time
        ln and eˣ
        the natural logarithm, which turns multiplying into adding, and the key that undoes it
        Stop
        the price, set before the buy, at which a trade sells if it goes wrong
        Risk
        the dollars lost if the price falls to the stop
        R (R-multiple)
        a result in units of its risk: result ÷ risk

        Formulas

        r = P1 ÷ P0 − 1  ·  ℓ = ln(P1 ÷ P0)  ·  r = eℓ − 1

        ℓtotal = ℓ1 + … + ℓn  ·  Pn ÷ P0 = eℓtotal

        risk = N × (Pbuy − Pstop)  ·  result in R = result ÷ risk  ·  result = result in R × risk

        Lesson notes

        A result means little until you fix its unit. Percent of the money put in compares trades of different sizes. Log returns add up over time, where percents multiply. R measures a result against what the trade risked. Say which you use.

        Dollars are not enough

        A trade is one buy and the sell that closes it. Two friends each post a trade: the first made $300, the second $200. The first put in $10,000, the second $2,000. As a share of what went in, 300 ÷ 10,000 = 0.03, or 3%, and 200 ÷ 2,000 = 0.10, or 10%. That share is the percent return: the second friend got more per dollar. For a price it is new price ÷ old price − 1, so $50 to $52 is 52 ÷ 50 − 1 = 0.04, or 4%.

        +50%, then −50%

        Take an account of $10,000, where each trade puts in the whole account. A +50% trade then a −50% trade add up to 0%, yet the account ends at $7,500, which is 25% down. Each percent applies to what the account holds then. The first trade multiplies the account by 1.5, the second by 0.5, and 1.5 × 0.5 = 0.75, in either order. That multiplier, new ÷ old, is the growth factor. Percents over time multiply; adding them is wrong.

        A unit that adds: ln

        The ln key, the natural logarithm, turns multiplying into adding: for numbers a and b above zero, ln(a × b) = ln(a) + ln(b). The log return of a trade is ln of its growth factor. So ln(1.5) + ln(0.5) = 0.405 + (−0.693) = −0.288, which is ln(0.75). Log returns are plain decimals. The eˣ key undoes ln: −0.288 becomes 0.75, 25% down.

        Five days of a made-up price

        A made-up price started at $100 and closed days 1 to 4 at $94.87, $91.13, $95.26 and $92.11. With day 5 at $99.30 the five daily percents add up to 0.0%, yet the price ended below its start. With day 5 at $100.00 the five daily logs add up to 0.000, and the price ended exactly at the start. Daily log returns always add up to the start-to-end log return; daily percents do not. The gap is small because each day moved only a few percent, and for small moves they are nearly equal: day 1 was −5.13% (−0.0513) as a percent return and −0.0527 as a log return. Big moves pull them apart.

        R: a result in units of risk

        Percent does not say what a trade put at risk. Many traders decide, before buying, the price at which they will sell if it goes wrong. That price is the stop, and the money lost if the price falls to it is the trade's risk. R is result ÷ risk: a trade that risked $400 and made $1,200 made +3R, and one that fell to its stop lost −1R.

        One trade bought 200 shares at $50, the whole $10,000 account, and sold them 8 days later at $56. It made $1,200, which is +12% of the account. With a stop at $47 the risk was 200 × (50 − 47) = $600, so the trade was 1,200 ÷ 600 = +2R. Moving the stop changes only R, and R is honest only if the stop was set before the buy: a stop picked afterwards can make any winner look like many R.

        Comparing rules in R

        Two backtests (replays of a rule on past prices) each ran 100 trades. The first risked $50 a trade and made $1,500 in total, the second risked $500 and made $5,000. In R the first made 1,500 ÷ 50 = 30R, or 0.3R a trade. The second made 5,000 ÷ 500 = 10R, or 0.1R a trade. Its dollars were bigger because it risked ten times as much.

        Formula: simple returns multiply, log returns add

        The percent return is also called the simple return. The growth factor from the first price to the last is the product of each period's factor, because the prices in between cancel, and ln turns that product into a sum.

        r = P1 ÷ P0 − 1
        ℓ = ln(P1 ÷ P0)
        r = eℓ − 1   (the way back)
        ℓtotal = ℓ1 + ℓ2 + … + ℓn
        Pn ÷ P0 = eℓtotal
        P0, P1
        the price, or the account, at the start and at the end of one period (a day, or a trade)
        P1 ÷ P0
        the growth factor of that period
        r
        the simple return, as a decimal: 0.5 is +50%
        ℓ
        the log return of one period (ℓ is a handwritten l, for log). For small moves ℓ ≈ r: a +1% day (r = 0.01) has ℓ = 0.00995
        ln
        the natural logarithm: the ln key
        ℓ1 … ℓn
        the log returns of n periods in a row
        ℓtotal
        the log return from the first price, P0, to the last, Pn
        ex
        the eˣ key, which undoes ln (e is a fixed number, about 2.718)
        Worked example: the two trades above

        Simple returns: r1 = 1.5 − 1 = +0.5 and r2 = 0.5 − 1 = −0.5. They add up to 0, but the growth factors multiply: 1.5 × 0.5 = 0.75.

        Log returns: ℓ1 = ln(1.5) = 0.405 and ℓ2 = ln(0.5) = −0.693, so ℓtotal = 0.405 − 0.693 = −0.288. Back: r = e−0.288 − 1 = 0.75 − 1 = −0.25. The account ended at 0.75 × $10,000 = $7,500, a simple return of −25%.

        Holds whenBreaks when

        Log returns add over time, not across things held side by side: if you split money between two things (say, two stocks), the account's return is the weighted average of their percent returns (each counted by how much of the money it holds; the plain average if the split is even), not of their log returns (lesson C11, Diversification). Averages of simple returns over time overstate growth when the returns swing a lot (lesson A14, Compounding and the asymmetry of losses).

        Formula: the R-multiple

        risk = N × (Pbuy − Pstop)
        result in R = result ÷ risk
        result = result in R × risk
        N
        the number of shares bought
        Pbuy
        the buy price
        Pstop
        the stop: the price at which the trade will sell if it goes wrong
        risk
        the dollars lost if the price falls to the stop and the trade sells there
        result
        what the trade made or lost in dollars: what came back minus what went in
        result in R
        the R-multiple: +2R made twice the risk; −1R lost exactly the risk
        Worked example: the trade above

        Risk = 200 × ($50 − $47) = $600. Result = 200 × ($56 − $50) = $1,200. Result in R = 1,200 ÷ 600 = +2R. With the stop at $48, the risk is $400 and the same trade is +3R.

        Back to dollars: +2R × $600 = $1,200.

        Holds whenBreaks when

        A price can jump past the stop, overnight or on news, and the trade sells lower: a loss bigger than 1R (lesson A13, Orders: market, limit and stop). Trading costs add to every loss (lesson A16, Costs).

        One more worked example

        Made-up round numbers

        Returns. An account gains +10%, then loses 10%, each trade putting in the whole account.

        Growth factors: 1.1 and 0.9. Together: 1.1 × 0.9 = 0.99, so the account is 1% down, although the percents add up to 0.

        Logs: ln(1.1) = 0.0953 and ln(0.9) = −0.1054. Sum: 0.0953 − 0.1054 = −0.0101. Back: e−0.0101 = 0.99.

        R. 250 shares are bought at $16, the whole $4,000 account, with a stop at $15, and sold at $18.40.

        Risk = 250 × (16 − 15) = $250. Result = 250 × (18.40 − 16) = 250 × 2.40 = $600. In R: 600 ÷ 250 = +2.4R. As a share of the account: 600 ÷ 4,000 = 15%.

        Common mistakes

        Check yourself

        1. One trade made $450 on $5,000 put in, another $120 on $1,000. Which did better?
          Answer

          450 ÷ 5,000 = 0.09, or 9%. 120 ÷ 1,000 = 0.12, or 12%. The second did better.

        2. An account of $10,000 gains 25%, then loses 20%, each trade putting in the whole account. Where does it end?
          Answer

          1.25 × 0.8 = 1, so it ends at 10,000 × 1 = $10,000. The percents add up to +5%, which is the wrong answer.

        3. You buy 100 shares at $30 with a stop at $28.50, and sell at $34.50. What is the result in R?
          Answer

          Risk = 100 × (30 − 28.50) = $150. Result = 100 × (34.50 − 30) = $450. In R: 450 ÷ 150 = +3R.

        4. A seller posts "+8R last month". Each trade risked $25 on a $5,000 account. By what percent did the account grow?
          Answer

          8 × $25 = $200, and 200 ÷ 5,000 = 0.04: 4%.

        Try it yourself

        Run the script. Every price and number in this lesson comes from one Python script with a fixed random seed (below). Change the paths' seed or the trade's stop range and see what moves.

        By hand, in a spreadsheet. Type a few prices down column A. In B2 put =A2/A1-1 (the simple return) and in C2 =LN(A2/A1) (the log return), and copy both down. Add up column C and compare it with =LN(last/first): they match. Then =EXP(sum)-1 gives the simple return of the whole stretch. Add up column B and see how far it is from that.

        The code behind every number (Python, seed 2026110904)
        Loading…

        Going further: when percent and log nearly agree

        For small moves, the simple return and the log return are almost the same number. For big ones they drift apart, and the log return of a fall is always further from zero than the simple return.

        Simple returnAs a decimalLog return

        The reason: for a small simple return r, ln(1 + r) is close to r − r²⁄2. At r = 0.01 the correction, 0.00005, is invisible. At r = 0.5 it is 0.125: 0.5 − 0.125 = 0.375, against the true 0.405. That is why adding up a few small daily percents is nearly harmless, and adding up many, or big ones, is not.

        For the preciseFive-day path: start $100.00; days 1 to 4 multiply the price by (1 + r), r ~ normal(0, 0.04), rounded to cents: $94.87, $91.13, $95.26, $92.11. Their simple returns −0.0513, −0.0394, +0.0453, −0.0331 add up to −0.0785; their log returns −0.0527, −0.0402, +0.0443, −0.0336 add up to −0.0822. The daily simple returns add to exactly 0 at a day-5 price of $99.3379; the slider's nearest point, $99.30, gives a sum that shows as 0.0% and a start-to-end simple return of −0.70% (log −0.0070). The trade: 200 shares at $50.00, a pinned random walk in log price with daily steps ~ normal(0, 0.012), pulled to end at ln(56/50) = 0.1133 on day 8; lowest close $50.22 (day 2), so no stop on the slider ($44.00 to $49.50) is touched. Seed 2026110904.

        Honest notes

        Where this comes from