{"schemaVersion":2,"courseId":"financial","module":{"id":"returns","title":"1 · Returns, compounding, and factor data","summary":"Align price changes, dividends, frequency, and factor units.","stages":[{"type":"read","id":"financial-returns-guide","skillIds":["financial.returns","financial.factor-models"],"estimatedMinutes":7,"difficulty":"core","title":"Returns, compounding, and factor data: research guide","html":"<h2>Returns, compounding, and factor data</h2><p class=\"lead\">Align price changes, dividends, frequency, and factor units.</p><p>Simple and log returns serve different aggregation operations; factor regressions also require excess returns and synchronized dates.</p><div class=\"callout\"><b>Workflow.</b> Use a return definition aligned with compounding, horizon, and portfolio operations.</div><p><b>Diagnostic:</b> Inspect prices, dividends, frequency, and simple-versus-log conversion. The main failure to avoid is mixing return conventions or ignoring corporate actions.</p>","prerequisiteStageIds":[]},{"type":"interactive","id":"financial-returns-lab","skillIds":["financial.returns"],"estimatedMinutes":6,"difficulty":"core","title":"Return measurement intuition lab","note":"Raise the daily volatility σ and watch the summed log returns stay exactly equal to total log growth, while the summed simple returns drift away from the true holding-period return.","params":[{"name":"sigma","label":"Daily volatility σ","min":0.005,"max":0.06,"step":0.005,"value":0.02}],"template":"import numpy as np, matplotlib.pyplot as plt\nrng = np.random.default_rng(0)\nn = 252; mu = 0.0004\nr_log = mu + {{sigma}} * rng.normal(0, 1, n)      # daily LOG returns\nprice = 100 * np.exp(np.cumsum(r_log))             # price path\nr_simple = np.exp(r_log) - 1                        # matching SIMPLE returns\nsum_log = r_log.sum()                              # additive aggregation\ntrue_log = np.log(price[-1] / 100)                 # true cumulative log growth\nsum_simple = r_simple.sum()                        # naive additive (biased)\ntrue_hold = price[-1] / 100 - 1                     # true holding-period return\nfig, ax = plt.subplots(1, 2, figsize=(7.6, 3.6))\nax[0].plot(price, color=\"#da9100\", lw=1.5); ax[0].set_title(\"Price path\")\nax[0].set_xlabel(\"day\"); ax[0].set_ylabel(\"P\")\nvals = [sum_log, true_log, sum_simple, true_hold]\nax[1].bar([\"Σ log r\", \"true log\", \"Σ simple r\", \"true simple\"], vals,\n          color=[\"#da9100\", \"#c9c6ac\", \"#da9100\", \"#c9c6ac\"])\nax[1].axhline(0, color=\"k\", lw=.6); ax[1].set_title(\"Aggregating returns\")\nax[1].set_ylabel(\"cumulative return\")\nplt.tight_layout()\nprint(f\"sigma={{sigma}}:  sum(log r)={sum_log:.4f}  ==  true log growth {true_log:.4f}\")\nprint(f\"sum(simple r)={sum_simple:.4f}  vs  true holding return {true_hold:.4f}  (gap widens with variance)\")\n","prerequisiteStageIds":["financial-returns-guide"]},{"type":"code","id":"financial-returns-worked","skillIds":["financial.returns"],"estimatedMinutes":10,"difficulty":"core","title":"Returns, compounding, and factor data: worked Python model","note":"Run the reproducible example, then change one assumption and compare the output.","code":"import numpy as np\nrng = np.random.default_rng(11)\nfactor = rng.normal(0.006, 0.04, 240)\nasset = 0.001 + 1.25*factor + rng.normal(0, 0.025, 240)\nX = np.column_stack([np.ones(len(factor)), factor])\nalpha, beta = np.linalg.lstsq(X, asset, rcond=None)[0]\nprint(f\"Monthly alpha: {alpha:.4f}\")\nprint(f\"Factor beta:   {beta:.3f}\")","prerequisiteStageIds":["financial-returns-lab"]},{"type":"codechallenge","id":"financial-returns-challenge","skillIds":["financial.returns"],"estimatedMinutes":12,"difficulty":"core","title":"Return measurement code challenge","note":"Estimate alpha and beta in the one-factor model using least squares.","starter":"import numpy as np\nfactor = np.array([-0.03, 0.01, 0.04, -0.01, 0.02, 0.05])\nasset = np.array([-0.02, 0.02, 0.06, -0.01, 0.04, 0.07])\nX = np.column_stack([np.ones(len(factor)), factor])\nalpha, beta = ...","tests":"expected = np.linalg.lstsq(X, asset, rcond=None)[0]\nassert np.allclose([alpha, beta], expected)\nprint(\"grader: factor alpha and beta are correct\")","hints":["Use np.linalg.lstsq with X and asset.","The returned coefficient vector contains alpha, then beta."],"success":"The numerical result and the return measurement workflow both pass the grader.","prerequisiteStageIds":["financial-returns-worked"],"variantId":"financial-returns-challenge-core"},{"type":"case","id":"financial-returns-case","skillIds":["financial.factor-models"],"estimatedMinutes":8,"difficulty":"core","title":"Factor regressions: model decision","note":"A team is about to report results without checking factor definitions, excess-return construction, and residual diagnostics.","steps":[{"prompt":"What is the best next action?","choices":["Estimate exposures and alpha with returns and factors aligned in frequency and units.","Increase decimal precision and report immediately.","Drop observations until the preferred coefficient appears."],"answer":0,"explain":"The defensible workflow is to estimate exposures and alpha with returns and factors aligned in frequency and units."},{"prompt":"Which risk should the final report address explicitly?","choices":["Only whether the sample mean is positive.","apparent alpha caused by omitted factors or unit mismatch","Whether every coefficient has the same sign."],"answer":1,"explain":"The relevant failure mode is apparent alpha caused by omitted factors or unit mismatch."}],"prerequisiteStageIds":["financial-returns-challenge"],"variantId":"financial-returns-case-core"},{"type":"match","id":"financial-returns-match","skillIds":["financial.factor-models"],"estimatedMinutes":7,"difficulty":"core","title":"Factor regressions: evidence map","note":"Match each research role to the course-specific evidence.","pairs":[{"left":"Good practice","right":"Estimate exposures and alpha with returns and factors aligned in frequency and units."},{"left":"Diagnostic evidence","right":"factor definitions, excess-return construction, and residual diagnostics"},{"left":"Failure to guard against","right":"apparent alpha caused by omitted factors or unit mismatch"}],"prerequisiteStageIds":["financial-returns-case"],"variantId":"financial-returns-match-core"}]}}
