Module 6 · Probability and Random Variables Lesson 58 of 120
Variance, Moments, and Moment-Generating Intuition
Measuring uncertainty around an expected claim count.
Transcript
19 sentences · select one to jump thereCheck your understanding
Is E[X²] generally equal to E[X]²?
Code lab
Run it yourself
The lesson source in 7 languages. Edit it, run TypeScript and Python right here, and compare with the expected output.
/**
* Fintech Math Bootcamp · Lesson 058 of 120
* Variance, Moments, and Moment-Generating Intuition
* Module 06: Probability and Random Variables
*
* Scenario: Measuring uncertainty around an expected claim count
* Rule: Var(X) = E[X²] − E[X]²
*
* Try it: Is E[X²] generally equal to E[X]²?
*
* Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/probability-and-random-variables/variance-moments-and-moment-generating-intuition/
* Free course: https://courses.thefintechbuilder.com
* Synthetic teaching example, not financial advice or a production library.
*/
export function lesson058() {
const x=[0,1,2], p=[.2,.5,.3];
const moment=(k:number)=>x.reduce((s,v,i)=>s+p[i]*v**k,0);
const mean=moment(1), second=moment(2);
const mgf=(t:number)=>x.reduce((s,v,i)=>s+p[i]*Math.exp(t*v),0);
const result={mean,second,variance:second-mean**2,mgfAtZero:mgf(0)};
return result;
}
export const checkedResult = {"mean":1.1,"second":1.7,"variance":0.48999999999999977,"mgfAtZero":1};
// Run this file directly: npx tsx lessons/06-probability-and-random-variables/058-variance-moments-and-moment-generating-intuition.ts
if (process.argv[1] && import.meta.url.endsWith(process.argv[1].replace(/\\/g, "/").split("/").pop()!)) {
console.log(JSON.stringify(lesson058(), null, 2));
}
Your output
Press Run to execute the code in your browser.
Expected output
{
"mean": 1.1,
"second": 1.7,
"variance": 0.48999999999999977,
"mgfAtZero": 1
}# Fintech Math Bootcamp · Lesson 058 of 120
# Variance, Moments, and Moment-Generating Intuition
# Module 06: Probability and Random Variables
#
# Scenario: Measuring uncertainty around an expected claim count
# Rule: Var(X) = E[X²] − E[X]²
#
# Try it: Is E[X²] generally equal to E[X]²?
#
# Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/probability-and-random-variables/variance-moments-and-moment-generating-intuition/
# Free course: https://courses.thefintechbuilder.com
# Synthetic teaching example, not financial advice or a production library.
import json
import math
def lesson058() -> dict:
x, p = [0, 1, 2], [0.2, 0.5, 0.3]
def moment(k: int) -> float: # raw moment E[X^k]
return sum(pi * v**k for v, pi in zip(x, p))
def mgf(t: float) -> float: # moment-generating function E[e^(tX)]
return sum(pi * math.exp(t * v) for v, pi in zip(x, p))
mean, second = moment(1), moment(2)
return {"mean": mean, "second": second, "variance": second - mean**2, "mgfAtZero": mgf(0)}
if __name__ == "__main__":
print(json.dumps(lesson058(), indent=2))
Your output
Press Run to execute the code in your browser.
Expected output
{
"mean": 1.1,
"second": 1.7,
"variance": 0.48999999999999977,
"mgfAtZero": 1
}/**
* Fintech Math Bootcamp · Lesson 058 of 120
* Variance, Moments, and Moment-Generating Intuition
* Module 06: Probability and Random Variables
*
* Scenario: Measuring uncertainty around an expected claim count
* Rule: Var(X) = E[X²] − E[X]²
*
* Try it: Is E[X²] generally equal to E[X]²?
*
* Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/probability-and-random-variables/variance-moments-and-moment-generating-intuition/
* Free course: https://courses.thefintechbuilder.com
* Synthetic teaching example, not financial advice or a production library.
*/
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class Main {
static final double[] X = {0, 1, 2};
static final double[] P = {0.2, 0.5, 0.3};
// Raw moment E[X^k].
static double moment(int k) {
double s = 0;
for (int i = 0; i < X.length; i++) s += P[i] * Math.pow(X[i], k);
return s;
}
// Moment-generating function E[e^(tX)].
static double mgf(double t) {
double s = 0;
for (int i = 0; i < X.length; i++) s += P[i] * Math.exp(t * X[i]);
return s;
}
static Map<String, Object> lesson058() {
double mean = moment(1), second = moment(2);
Map<String, Object> result = new LinkedHashMap<String, Object>();
result.put("mean", mean);
result.put("second", second);
result.put("variance", second - mean * mean);
result.put("mgfAtZero", mgf(0));
return result;
}
public static void main(String[] args) {
System.out.println(toJson(lesson058(), ""));
}
// --- Minimal JSON printer: maps keep insertion order, 2-space indent. ---
static String toJson(Object value, String indent) {
if (value == null) return "null";
if (value instanceof String) return "\"" + value + "\"";
if (value instanceof Double) return formatNumber((Double) value);
if (value instanceof Number) return value.toString();
if (value instanceof double[]) {
List<Object> items = new ArrayList<Object>();
for (double v : (double[]) value) items.add(v);
return toJson(items, indent);
}
String inner = indent + " ";
StringBuilder sb = new StringBuilder();
if (value instanceof Map) {
Map<?, ?> map = (Map<?, ?>) value;
if (map.isEmpty()) return "{}";
sb.append("{\n");
int i = 0;
for (Map.Entry<?, ?> entry : map.entrySet()) {
sb.append(inner).append('"').append(entry.getKey()).append("\": ")
.append(toJson(entry.getValue(), inner))
.append(++i < map.size() ? ",\n" : "\n");
}
return sb.append(indent).append('}').toString();
}
List<?> list = (List<?>) value;
if (list.isEmpty()) return "[]";
sb.append("[\n");
for (int i = 0; i < list.size(); i++) {
sb.append(inner).append(toJson(list.get(i), inner))
.append(i + 1 < list.size() ? ",\n" : "\n");
}
return sb.append(indent).append(']').toString();
}
static String formatNumber(double v) {
if (Double.isNaN(v) || Double.isInfinite(v)) return "null";
if (v == Math.rint(v) && Math.abs(v) < 1e15) return Long.toString((long) v);
return Double.toString(v);
}
}
No browser runner for Java yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"mean": 1.1,
"second": 1.7,
"variance": 0.48999999999999977,
"mgfAtZero": 1
}// Fintech Math Bootcamp · Lesson 058 of 120
// Variance, Moments, and Moment-Generating Intuition
// Module 06: Probability and Random Variables
//
// Scenario: Measuring uncertainty around an expected claim count
// Rule: Var(X) = E[X²] − E[X]²
//
// Try it: Is E[X²] generally equal to E[X]²?
//
// Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/probability-and-random-variables/variance-moments-and-moment-generating-intuition/
// Free course: https://courses.thefintechbuilder.com
// Synthetic teaching example, not financial advice or a production library.
package main
import (
"encoding/json"
"fmt"
"math"
)
// Moments holds the first two raw moments, the variance, and the MGF at t = 0.
type Moments struct {
Mean float64 `json:"mean"`
Second float64 `json:"second"`
Variance float64 `json:"variance"`
MgfAtZero float64 `json:"mgfAtZero"`
}
func lesson058() Moments {
x, p := []float64{0, 1, 2}, []float64{0.2, 0.5, 0.3}
// moment returns the raw moment E[X^k].
moment := func(k float64) float64 {
s := 0.0
for i, v := range x {
s += p[i] * math.Pow(v, k)
}
return s
}
// mgf returns the moment-generating function E[e^(tX)].
mgf := func(t float64) float64 {
s := 0.0
for i, v := range x {
s += p[i] * math.Exp(t*v)
}
return s
}
mean, second := moment(1), moment(2)
return Moments{Mean: mean, Second: second, Variance: second - mean*mean, MgfAtZero: mgf(0)}
}
func main() {
out, _ := json.MarshalIndent(lesson058(), "", " ")
fmt.Println(string(out))
}
No browser runner for Go yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"mean": 1.1,
"second": 1.7,
"variance": 0.48999999999999977,
"mgfAtZero": 1
}/**
* Fintech Math Bootcamp · Lesson 058 of 120
* Variance, Moments, and Moment-Generating Intuition
* Module 06: Probability and Random Variables
*
* Scenario: Measuring uncertainty around an expected claim count
* Rule: Var(X) = E[X²] − E[X]²
*
* Try it: Is E[X²] generally equal to E[X]²?
*
* Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/probability-and-random-variables/variance-moments-and-moment-generating-intuition/
* Free course: https://courses.thefintechbuilder.com
* Synthetic teaching example, not financial advice or a production library.
*/
#include <charconv>
#include <cmath>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
// --- Minimal JSON value and printer: objects keep insertion order, 2-space indent. ---
struct Json {
enum class Kind { Null, Number, Text, Array, Object };
Kind kind = Kind::Null;
double number = 0;
std::string text;
std::vector<std::string> keys; // object keys, parallel to items
std::vector<Json> items; // array elements or object values
};
Json num(double v) { Json j; j.kind = Json::Kind::Number; j.number = v; return j; }
Json str(const std::string& s) { Json j; j.kind = Json::Kind::Text; j.text = s; return j; }
Json arr(const std::vector<Json>& values) { Json j; j.kind = Json::Kind::Array; j.items = values; return j; }
Json arr(const std::vector<double>& values) {
std::vector<Json> items;
for (double v : values) items.push_back(num(v));
return arr(items);
}
Json obj(const std::vector<std::pair<std::string, Json>>& fields) {
Json j;
j.kind = Json::Kind::Object;
for (const auto& [key, value] : fields) { j.keys.push_back(key); j.items.push_back(value); }
return j;
}
std::string formatNumber(double v) {
if (!std::isfinite(v)) return "null";
char buf[64];
auto end = std::to_chars(buf, buf + sizeof buf, v).ptr; // shortest round-trip form
return std::string(buf, end);
}
void writeJson(std::ostream& out, const Json& j, const std::string& indent) {
switch (j.kind) {
case Json::Kind::Null: out << "null"; return;
case Json::Kind::Number: out << formatNumber(j.number); return;
case Json::Kind::Text: out << '"' << j.text << '"'; return;
default: break;
}
bool isObject = j.kind == Json::Kind::Object;
if (j.items.empty()) { out << (isObject ? "{}" : "[]"); return; }
std::string inner = indent + " ";
out << (isObject ? "{\n" : "[\n");
for (size_t i = 0; i < j.items.size(); ++i) {
out << inner;
if (isObject) out << '"' << j.keys[i] << "\": ";
writeJson(out, j.items[i], inner);
out << (i + 1 < j.items.size() ? ",\n" : "\n");
}
out << indent << (isObject ? '}' : ']');
}
// --- Lesson ---
Json lesson058() {
const std::vector<double> x = {0, 1, 2}, p = {0.2, 0.5, 0.3};
auto moment = [&](int k) { // raw moment E[X^k]
double s = 0;
for (size_t i = 0; i < x.size(); ++i) s += p[i] * std::pow(x[i], k);
return s;
};
auto mgf = [&](double t) { // moment-generating function E[e^(tX)]
double s = 0;
for (size_t i = 0; i < x.size(); ++i) s += p[i] * std::exp(t * x[i]);
return s;
};
double mean = moment(1), second = moment(2);
return obj({
{"mean", num(mean)},
{"second", num(second)},
{"variance", num(second - mean * mean)},
{"mgfAtZero", num(mgf(0))},
});
}
int main() {
writeJson(std::cout, lesson058(), "");
std::cout << '\n';
}
No browser runner for C++ yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"mean": 1.1,
"second": 1.7,
"variance": 0.48999999999999977,
"mgfAtZero": 1
}// Fintech Math Bootcamp · Lesson 058 of 120
// Variance, Moments, and Moment-Generating Intuition
// Module 06: Probability and Random Variables
//
// Scenario: Measuring uncertainty around an expected claim count
// Rule: Var(X) = E[X²] − E[X]²
//
// Try it: Is E[X²] generally equal to E[X]²?
//
// Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/probability-and-random-variables/variance-moments-and-moment-generating-intuition/
// Free course: https://courses.thefintechbuilder.com
// Synthetic teaching example, not financial advice or a production library.
// --- Minimal JSON value and printer: objects keep insertion order, 2-space indent. ---
#[allow(dead_code)]
enum Json {
Null,
Num(f64),
Str(String),
Arr(Vec<Json>),
Obj(Vec<(String, Json)>),
}
#[allow(dead_code)]
fn nums(values: &[f64]) -> Json {
Json::Arr(values.iter().map(|&v| Json::Num(v)).collect())
}
#[allow(dead_code)]
fn obj(fields: Vec<(&str, Json)>) -> Json {
Json::Obj(fields.into_iter().map(|(k, v)| (k.to_string(), v)).collect())
}
fn format_number(v: f64) -> String {
if !v.is_finite() {
return "null".to_string();
}
if v.fract() == 0.0 && v.abs() < 1e15 {
return format!("{}", v as i64);
}
format!("{:?}", v) // shortest round-trip form
}
impl Json {
fn render(&self, indent: &str) -> String {
let inner = format!("{} ", indent);
match self {
Json::Null => "null".to_string(),
Json::Num(v) => format_number(*v),
Json::Str(s) => format!("\"{}\"", s),
Json::Arr(items) if items.is_empty() => "[]".to_string(),
Json::Obj(fields) if fields.is_empty() => "{}".to_string(),
Json::Arr(items) => {
let lines: Vec<String> = items.iter().map(|v| format!("{}{}", inner, v.render(&inner))).collect();
format!("[\n{}\n{}]", lines.join(",\n"), indent)
}
Json::Obj(fields) => {
let lines: Vec<String> = fields
.iter()
.map(|(k, v)| format!("{}\"{}\": {}", inner, k, v.render(&inner)))
.collect();
format!("{{\n{}\n{}}}", lines.join(",\n"), indent)
}
}
}
}
// --- Lesson ---
fn lesson058() -> Json {
let x: [f64; 3] = [0.0, 1.0, 2.0];
let p: [f64; 3] = [0.2, 0.5, 0.3];
// Raw moment E[X^k].
let moment = |k: i32| -> f64 { x.iter().zip(p.iter()).map(|(v, pi)| pi * v.powi(k)).sum() };
// Moment-generating function E[e^(tX)].
let mgf = |t: f64| -> f64 { x.iter().zip(p.iter()).map(|(v, pi)| pi * (t * v).exp()).sum() };
let (mean, second) = (moment(1), moment(2));
obj(vec![
("mean", Json::Num(mean)),
("second", Json::Num(second)),
("variance", Json::Num(second - mean.powi(2))),
("mgfAtZero", Json::Num(mgf(0.0))),
])
}
fn main() {
println!("{}", lesson058().render(""));
}
No browser runner for Rust yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"mean": 1.1,
"second": 1.7,
"variance": 0.48999999999999977,
"mgfAtZero": 1
}/**
* Fintech Math Bootcamp · Lesson 058 of 120
* Variance, Moments, and Moment-Generating Intuition
* Module 06: Probability and Random Variables
*
* Scenario: Measuring uncertainty around an expected claim count
* Rule: Var(X) = E[X²] − E[X]²
*
* Try it: Is E[X²] generally equal to E[X]²?
*
* Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/probability-and-random-variables/variance-moments-and-moment-generating-intuition/
* Free course: https://courses.thefintechbuilder.com
* Synthetic teaching example, not financial advice or a production library.
*/
using System;
using System.Linq;
using System.Text.Json;
var options = new JsonSerializerOptions { WriteIndented = true };
Console.WriteLine(JsonSerializer.Serialize(Lesson058(), options));
static object Lesson058()
{
double[] x = { 0, 1, 2 };
double[] p = { 0.2, 0.5, 0.3 };
double Moment(int k) => x.Select((v, i) => p[i] * Math.Pow(v, k)).Sum(); // raw moment E[X^k]
double Mgf(double t) => x.Select((v, i) => p[i] * Math.Exp(t * v)).Sum(); // E[e^(tX)]
double mean = Moment(1), second = Moment(2);
return new { mean, second, variance = second - mean * mean, mgfAtZero = Mgf(0) };
}
No browser runner for C# yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"mean": 1.1,
"second": 1.7,
"variance": 0.48999999999999977,
"mgfAtZero": 1
}Prefer your own machine? Every file is in the course repository · open it in Codespaces.
Lesson notes
The rule
Var(X) = E[X²] − E[X]²