[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6HARAQ9JY42JC52VCYF82C9":3,"skill-same:01M6HARAQ9JY42JC52VCYF82C9":71},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":38,"linkOnly":39,"markdownContent":40,"markdownBody":41,"frontMatter":42,"refName":49,"commitSha":50,"skillDirectory":51,"forksCount":14,"repositoryHtmlUrl":52,"repositoryHomepageUrl":6,"ownerHtmlUrl":53,"ownerBlogUrl":54,"ownerDescription":55,"updatedAt":56,"install":57,"resources":70},"01M6HARAQ9JY42JC52VCYF82C9","stochastic-processes",null,"Expert guidance on random processes, Markov chains, Brownian motion, and stochastic calculus.  Use for: modeling random systems, Markov chain analysis, Poisson processes, Brownian motion,  Ito calculus, stochastic differential equations, martingale theory, and financial mathematics.","NeuralBlitz\u002FMito","NeuralBlitz","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F79354388?v=4","01M6H8T2TFH477HRS0KTSTKR2E","David Riggs","01M6H8T2YQQDXPYM092P670Z21",0,"MIT","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fstochastic-processes\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,5,28,29,30,31,32,33,34,35,36,37],"stochastic processes","processes","differential equations","financial mathematics","for","random","chain","systems","modeling","data","probability","calculus","mathematics","expert","guidance","motion","opencode","use","analysis","2026-11-10 10:12:30",false,"---\nname: stochastic-processes\ndescription: >\n  Expert guidance on random processes, Markov chains, Brownian motion, and stochastic calculus. \n  Use for: modeling random systems, Markov chain analysis, Poisson processes, Brownian motion, \n  Ito calculus, stochastic differential equations, martingale theory, and financial mathematics.\nlicense: MIT\ncompatibility: opencode\nmetadata:\n  audience: mathematicians, data-scientists, financial-analysts\n  category: mathematics\n  tags: [stochastic-processes, markov-chains, brownian-motion, probability]\n---\n\n# Stochastic Processes — Theory and Applications\n\nCovers: **Probability Foundations · Markov Chains · Poisson Processes · Brownian Motion · Stochastic Calculus · Applications**\n\n-----\n\n## Probability Foundations\n\n### Probability Spaces and Random Variables\n\nA probability space consists of three components: the sample space Omega representing all possible outcomes, a sigma-algebra F containing all measurable events, and a probability measure P assigning probabilities to events. Understanding this foundation is essential for rigorously defining stochastic processes.\n\nA random variable is a measurable function X: Omega -> R that assigns a real number to each outcome. The distribution of X is characterized by its cumulative distribution function F(x) = P(X \u003C= x), or by its probability density function f(x) for continuous variables.\n\n**Key Distributions:**\n\n| Distribution | Parameters | Mean | Variance |\n|--------------|-----------|------|----------|\n| Normal | mu, sigma^2 | mu | sigma^2 |\n| Exponential | lambda | 1\u002Flambda | 1\u002Flambda^2 |\n| Poisson | lambda | lambda | lambda |\n| Uniform | a, b | (a+b)\u002F2 | (b-a)^2\u002F12 |\n| Bernoulli | p | p | p(1-p) |\n\n### Expectations and Moments\n\n```python\nimport numpy as np\nfrom scipy import stats\n\n# Calculate expectations\ndef expectation(distribution, func=lambda x: x):\n    \"\"\"Calculate E[g(X)] for distribution\"\"\"\n    if hasattr(distribution, 'expect'):\n        return distribution.expect(func)\n    # Monte Carlo approximation\n    samples = distribution.rvs(100000)\n    return np.mean(func(samples))\n\n# Normal distribution example\nnormal = stats.norm(loc=5, scale=2)\nE_x = normal.mean()  # 5\nVar_x = normal.var()  # 4\nE_x2 = normal.moment(2)  # E[X^2] = Var + E[X]^2 = 4 + 25 = 29\n\n# Conditional expectation\n# E[X|Y=y] - expectation of X given Y=y\ndef conditional_expectation(joint_samples, x_idx, y_idx, y_value):\n    \"\"\"Calculate E[X|Y=y] from samples\"\"\"\n    mask = joint_samples[:, y_idx] == y_value\n    return np.mean(joint_samples[mask, x_idx])\n\n# Moment generating function\ndef mgf_normal(t, mu, sigma):\n    \"\"\"MGF of normal distribution\"\"\"\n    return np.exp(mu * t + 0.5 * sigma**2 * t**2)\n\n# Characteristic function\ndef cf_normal(t, mu, sigma):\n    \"\"\"Characteristic function of normal\"\"\"\n    return np.exp(1j * mu * t - 0.5 * sigma**2 * t**2)\n```\n\n-----\n\n## Markov Chains\n\n### Definition and Properties\n\nA stochastic process {X_n} is a Markov chain if it satisfies the Markov property: given the present, the future is independent of the past. Formally, P(X_{n+1} = j | X_n = i, X_{n-1} = i_{n-1}, ..., X_0 = i_0) = P(X_{n+1} = j | X_n = i).\n\nThe transition matrix P with entries P_{ij} = P(X_{n+1} = j | X_n = i) characterizes the chain. A Markov chain is homogeneous if these transition probabilities are independent of n.\n\n**Key Properties:**\n\n- **Irreducible** — Every state can be reached from every other state\n- **Recurrent** — Expected return time to any state is finite\n- **Transient** — Some states may never be revisited\n- **Periodic** — Returns to states occur at regular intervals\n- **Aperiodic** — No regular return pattern\n\n### Markov Chain Implementation\n\n```python\nimport numpy as np\nfrom dataclasses import dataclass\nfrom typing import Dict, List, Optional\nimport matplotlib.pyplot as plt\n\n@dataclass\nclass MarkovChain:\n    \"\"\"Homogeneous Markov chain\"\"\"\n    states: List[str]\n    transition_matrix: np.ndarray\n    initial_distribution: Optional[np.ndarray] = None\n    \n    def __post_init__(self):\n        n = len(self.states)\n        if self.initial_distribution is None:\n            self.initial_distribution = np.ones(n) \u002F n\n        \n        # Validate\n        assert np.allclose(self.transition_matrix.sum(axis=1), 1)\n        assert len(self.states) == self.transition_matrix.shape[0]\n    \n    def simulate(self, n_steps: int, seed: int = None) -> List[str]:\n        \"\"\"Simulate chain for n_steps\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        path = []\n        current = np.random.choice(len(self.states), p=self.initial_distribution)\n        path.append(self.states[current])\n        \n        for _ in range(n_steps - 1):\n            current = np.random.choice(\n                len(self.states),\n                p=self.transition_matrix[current]\n            )\n            path.append(self.states[current])\n        \n        return path\n    \n    def transition_prob(self, from_state: str, to_state: str, steps: int = 1) -> float:\n        \"\"\"Probability of transitioning from one state to another in n steps\"\"\"\n        i = self.states.index(from_state)\n        j = self.states.index(to_state)\n        \n        if steps == 1:\n            return self.transition_matrix[i, j]\n        \n        return (self.transition_matrix ** steps)[i, j]\n    \n    def stationary_distribution(self) -> np.ndarray:\n        \"\"\"Find stationary distribution pi such that pi = pi * P\"\"\"\n        eigenvalues, eigenvectors = np.linalg.eig(\n            self.transition_matrix.T\n        )\n        \n        # Find eigenvector with eigenvalue closest to 1\n        idx = np.argmin(np.abs(eigenvalues - 1))\n        stationary = np.real(eigenvectors[:, idx])\n        return stationary \u002F stationary.sum()\n    \n    def verify_ergodicity(self) -> Dict:\n        \"\"\"Check if chain is ergodic\"\"\"\n        n = len(self.states)\n        \n        # Check irreducibility\n        reachable = np.linalg.matrix_power(\n            self.transition_matrix + np.eye(n), n - 1\n        ) > 0\n        irreducible = np.all(reachable)\n        \n        # Check aperiodicity\n        eigenvalues = np.linalg.eigvals(self.transition_matrix)\n        eigenvalues = np.round(eigenvalues, 10)\n        eigenvalues = eigenvalues[np.abs(eigenvalues) > 0.01]\n        is_aperiodic = not any(\n            np.isclose(np.abs(e), 1) and \n            np.isclose(np.abs(e ** n - 1), 0)\n            for n in range(2, n + 1)\n            for e in eigenvalues\n        )\n        \n        stationary = self.stationary_distribution()\n        \n        return {\n            \"irreducible\": irreducible,\n            \"aperiodic\": is_aperiodic,\n            \"has_stationary\": True,\n            \"stationary_distribution\": dict(zip(self.states, stationary))\n        }\n\n# Example: Weather model\nweather_states = [\"sunny\", \"cloudy\", \"rainy\"]\nweather_transitions = np.array([\n    [0.7, 0.2, 0.1],  # Sunny -> sunny, cloudy, rainy\n    [0.3, 0.4, 0.3],  # Cloudy -> sunny, cloudy, rainy\n    [0.2, 0.3, 0.5]   # Rainy -> sunny, cloudy, rainy\n])\n\nweather_chain = MarkovChain(weather_states, weather_transitions)\n\n# Simulate\npath = weather_chain.simulate(30)\nprint(\"Weather sequence:\", \" -> \".join(path[:10]))\n\n# Stationary distribution\nstationary = weather_chain.stationary_distribution()\nprint(\"\\nStationary distribution:\")\nfor state, prob in zip(weather_states, stationary):\n    print(f\"  {state}: {prob:.3f}\")\n\n# Verify ergodicity\nprint(\"\\nErgodicity:\", weather_chain.verify_ergodicity())\n```\n\n### Continuous-Time Markov Chains\n\n```python\nclass ContinuousTimeMarkovChain:\n    \"\"\"Continuous-time Markov chain with rate matrix Q\"\"\"\n    \n    def __init__(self, states: List[str], rate_matrix: np.ndarray):\n        self.states = states\n        self.rate_matrix = rate_matrix\n        \n        # Verify row sums to 0\n        assert np.allclose(rate_matrix.sum(axis=1), 0)\n        \n        # Transition matrix for embedded chain\n        n = len(states)\n        self.embedded_matrix = np.zeros((n, n))\n        for i in range(n):\n            if rate_matrix[i].sum() > 0:\n                self.embedded_matrix[i] = rate_matrix[i] \u002F -rate_matrix[i, i]\n    \n    def simulate_jump_times(self, n_jumps: int, initial_state: int = 0, seed: int = None):\n        \"\"\"Simulate path with jump times\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        path = [initial_state]\n        times = [0.0]\n        current = initial_state\n        \n        for _ in range(n_jumps):\n            # Time to next jump (exponential)\n            rate = -self.rate_matrix[current, current]\n            dt = np.random.exponential(1 \u002F rate)\n            times.append(times[-1] + dt)\n            \n            # Next state (embedded chain)\n            current = np.random.choice(\n                len(self.states),\n                p=self.embedded_matrix[current]\n            )\n            path.append(current)\n        \n        return {\n            \"states\": [self.states[s] for s in path],\n            \"times\": times,\n            \"path\": path\n        }\n```\n\n-----\n\n## Poisson Processes\n\n### Definition and Properties\n\nA Poisson process with rate lambda counts events occurring randomly in time. It satisfies: the number of events in any interval follows a Poisson distribution, events occur independently of past events, and the process has stationary increments.\n\nThe interarrival times (times between consecutive events) are independently and exponentially distributed with mean 1\u002Flambda. This property allows simple simulation of Poisson processes.\n\n```python\nclass PoissonProcess:\n    \"\"\"Poisson process with rate lambda\"\"\"\n    \n    def __init__(self, lambda_rate: float):\n        self.lambda_rate = lambda_rate\n    \n    def simulate(self, T: float, seed: int = None) -> Dict:\n        \"\"\"Simulate Poisson process up to time T\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        # Generate interarrival times\n        interarrivals = []\n        t = 0\n        while True:\n            dt = np.random.exponential(1 \u002F self.lambda_rate)\n            t += dt\n            if t > T:\n                break\n            interarrivals.append(dt)\n        \n        # Arrival times\n        arrival_times = np.cumsum(interarrivals)\n        counts = np.arange(1, len(arrival_times) + 1)\n        \n        return {\n            \"arrival_times\": arrival_times,\n            \"counts\": counts,\n            \"n_events\": len(arrival_times)\n        }\n    \n    def probability_k_events(self, k: int, T: float) -> float:\n        \"\"\"P(N(T) = k)\"\"\"\n        from scipy.special import gammainc\n        mu = self.lambda_rate * T\n        return np.exp(-mu) * (mu ** k) \u002F np.math.factorial(k)\n    \n    def arrival_time_distribution(self, n: int) -> np.ndarray:\n        \"\"\"Distribution of arrival times given N(T) = n\"\"\"\n        # Order statistics of uniform\n        return np.sort(np.random.uniform(0, 1, n))\n\n# Compound Poisson process\nclass CompoundPoissonProcess:\n    \"\"\"Compound Poisson process: N(t) with i.i.d. jump sizes\"\"\"\n    \n    def __init__(self, lambda_rate: float, jump_distribution):\n        self.lambda_rate = lambda_rate\n        self.jump_distribution = jump_distribution\n    \n    def simulate(self, T: float, seed: int = None) -> Dict:\n        \"\"\"Simulate compound Poisson process\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        # Generate Poisson arrivals\n        poisson = PoissonProcess(self.lambda_rate)\n        arrivals = poisson.simulate(T)\n        \n        # Generate jump sizes\n        n = arrivals[\"n_events\"]\n        jump_sizes = self.jump_distribution.rvs(n)\n        \n        # Compound process values\n        values = np.cumsum(jump_sizes)\n        times = arrivals[\"arrival_times\"]\n        \n        return {\n            \"times\": times,\n            \"values\": values,\n            \"jump_sizes\": jump_sizes,\n            \"final_value\": values[-1] if n > 0 else 0\n        }\n```\n\n-----\n\n## Brownian Motion\n\n### Definition and Properties\n\nStandard Brownian motion B(t) is a stochastic process with: B(0) = 0, stationary increments, independent increments, and continuous paths almost surely. The increments B(t) - B(s) ~ N(0, t-s).\n\nBrownian motion is a martingale, has infinite variation, is nowhere differentiable, and exhibits fractal behavior. These properties make it both mathematically interesting and practically useful for modeling random fluctuations.\n\n```python\nclass BrownianMotion:\n    \"\"\"Standard Brownian motion\"\"\"\n    \n    def __init__(self, drift: float = 0, diffusion: float = 1):\n        self.drift = drift\n        self.diffusion = diffusion\n    \n    def simulate(self, T: float, n_steps: int, seed: int = None) -> Dict:\n        \"\"\"Simulate Brownian motion\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        dt = T \u002F n_steps\n        t = np.linspace(0, T, n_steps + 1)\n        \n        # Increments\n        dW = np.random.normal(0, np.sqrt(dt), n_steps)\n        \n        # Path\n        W = np.zeros(n_steps + 1)\n        W[1:] = np.cumsum(dW)\n        \n        # Add drift and diffusion\n        if self.drift != 0 or self.diffusion != 1:\n            W = self.drift * t + self.diffusion * W\n        \n        return {\n            \"time\": t,\n            \"values\": W,\n            \"final_value\": W[-1]\n        }\n    \n    def simulate_bridge(self, T: float, n_steps: int, start: float, end: float, seed: int = None):\n        \"\"\"Brownian bridge from start to end\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        dt = T \u002F n_steps\n        t = np.linspace(0, T, n_steps + 1)\n        \n        # Standard Brownian bridge\n        W = self.simulate(T, n_steps).values\n        \n        # Transform to bridge\n        # B_bridge(t) = B(t) - t\u002FT * B(T) + (t\u002FT)*start + (1-t\u002FT)*end\n        bridge = W - t \u002F T * W[-1]\n        bridge = bridge + (t \u002F T) * start + (1 - t \u002F T) * end\n        \n        return {\"time\": t, \"values\": bridge}\n    \n    def hitting_time(self, a: float, max_T: float = 100) -> float:\n        \"\"\"First passage time to level a\"\"\"\n        # For standard BM, hitting time has inverse Gaussian distribution\n        if a \u003C= 0:\n            return np.inf\n        \n        # Monte Carlo simulation\n        samples = []\n        for _ in range(1000):\n            path = self.simulate(max_T, 10000)\n            hits = np.where(path[\"values\"] >= a)[0]\n            if len(hits) > 0:\n                samples.append(path[\"time\"][hits[0]])\n        \n        return np.mean(samples) if samples else np.inf\n\n# Geometric Brownian motion\nclass GeometricBrownianMotion:\n    \"\"\"Geometric Brownian motion: S(t) = S(0) * exp((mu - sigma^2\u002F2)t + sigma W(t))\"\"\"\n    \n    def __init__(self, mu: float, sigma: float):\n        self.mu = mu  # drift\n        self.sigma = sigma  # volatility\n    \n    def simulate(self, S0: float, T: float, n_steps: int, seed: int = None) -> Dict:\n        \"\"\"Simulate GBM path\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        dt = T \u002F n_steps\n        t = np.linspace(0, T, n_steps + 1)\n        \n        # Increments\n        dW = np.random.normal(0, np.sqrt(dt), n_steps)\n        \n        # GBM formula\n        drift = (self.mu - 0.5 * self.sigma**2) * dt\n        diffusion = self.sigma * dW\n        \n        log_returns = np.cumsum(drift + diffusion)\n        prices = S0 * np.exp(log_returns)\n        \n        return {\n            \"time\": t,\n            \"prices\": prices,\n            \"log_returns\": log_returns\n        }\n```\n\n-----\n\n## Stochastic Calculus\n\n### Ito Integrals\n\nThe Ito integral extends the concept of integration to stochastic processes. For an Ito process dX = a(t)dt + b(t)dW, the Ito integral integral_0^t b(s)dW(s) captures the martingale part.\n\n**Ito's Lemma:** If X is an Ito process and f is twice-differentiable, then f(X) is also an Ito process:\n\ndf(X) = f'(X)dX + (1\u002F2)f''(X)(dX)^2\n\nwhere (dt)^2 = 0, (dW)^2 = dt, and dW dt = 0.\n\n```python\nclass ItoProcess:\n    \"\"\"Ito process dX = mu(t, X)dt + sigma(t, X)dW\"\"\"\n    \n    def __init__(self, mu_func, sigma_func):\n        self.mu_func = mu_func  # drift function\n        self.sigma_func = sigma_func  # diffusion function\n    \n    def simulate(self, x0: float, T: float, n_steps: int, seed: int = None) -> Dict:\n        \"\"\"Euler-Maruyama discretization\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        dt = T \u002F n_steps\n        sqrt_dt = np.sqrt(dt)\n        \n        t = np.linspace(0, T, n_steps + 1)\n        x = np.zeros(n_steps + 1)\n        x[0] = x0\n        \n        for i in range(n_steps):\n            mu = self.mu_func(t[i], x[i])\n            sigma = self.sigma_func(t[i], x[i])\n            \n            dW = np.random.normal(0, sqrt_dt)\n            x[i + 1] = x[i] + mu * dt + sigma * dW\n        \n        return {\"time\": t, \"values\": x}\n\n# Example: Ornstein-Uhlenbeck process\ndef ou_drift(t, x):\n    return -0.5 * x  # mean-reverting\n\ndef ou_diffusion(t, x):\n    return 0.3  # constant volatility\n\nou_process = ItoProcess(ou_drift, ou_diffusion)\npath = ou_process.simulate(x0=2.0, T=10, n_steps=1000)\n\n# Verify mean reversion\nprint(f\"Initial: {path['values'][0]:.3f}\")\nprint(f\"Final: {path['values'][-1]:.3f}\")\nprint(f\"Mean: {np.mean(path['values']):.3f}\")  # Should be near 0\n```\n\n### Stochastic Differential Equations\n\n```python\nclass SDESolver:\n    \"\"\"Solve stochastic differential equations\"\"\"\n    \n    @staticmethod\n    def euler_maruyama(x0: float, T: float, n_steps: int, \n                      mu, sigma, seed: int = None):\n        \"\"\"Euler-Maruyama method\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        dt = T \u002F n_steps\n        sqrt_dt = np.sqrt(dt)\n        \n        x = np.zeros(n_steps + 1)\n        x[0] = x0\n        \n        for i in range(n_steps):\n            dW = np.random.normal(0, sqrt_dt)\n            x[i + 1] = x[i] + mu(x[i], i * dt) * dt + sigma(x[i], i * dt) * dW\n        \n        return x\n    \n    @staticmethod\n    def milstein(x0: float, T: float, n_steps: int,\n                mu, sigma, dsigma, seed: int = None):\n        \"\"\"Milstein method (includes second-order terms)\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        dt = T \u002F n_steps\n        sqrt_dt = np.sqrt(dt)\n        \n        x = np.zeros(n_steps + 1)\n        x[0] = x0\n        \n        for i in range(n_steps):\n            dW = np.random.normal(0, sqrt_dt)\n            xi = x[i]\n            t = i * dt\n            \n            # Milstein correction\n            correction = 0.5 * sigma(xi, t) * dsigma(xi, t) * ((dW**2) - dt)\n            \n            x[i + 1] = xi + mu(xi, t) * dt + sigma(xi, t) * dW + correction\n        \n        return x\n\n# Black-Scholes SDE: dS = mu*S dt + sigma*S dW\ndef bs_drift(S, t):\n    return 0.05 * S  # mu = 5%\n\ndef bs_diffusion(S, t):\n    return 0.2 * S  # sigma = 20%\n\ndef bs_dsigma(S):\n    return 0.2  # derivative of sigma*S wrt S\n\n# Simulate stock price\nsde = SDESolver()\nS0 = 100\nprices = sde.euler_maruyama(S0, 1, 252, bs_drift, bs_diffusion)\nprint(f\"Initial: ${S0:.2f}, Final: ${prices[-1]:.2f}\")\n```\n\n-----\n\n## Martingales\n\n### Definition and Properties\n\nA stochastic process M(t) is a martingale with respect to filtration F_t if: E|M(t)| \u003C infinity for all t, M(t) is adapted to F_t, and E[M(t) | F_s] = M(s) for all s \u003C t.\n\nMartingales generalize the notion of fair games. They have many useful properties: they oscillate around their starting value, they have constant expectation, and various convergence theorems apply.\n\n```python\nclass MartingaleTest:\n    \"\"\"Test if a process is a martingale\"\"\"\n    \n    @staticmethod\n    def check_martingale(samples: np.ndarray, dt: float) -> Dict:\n        \"\"\"Check martingale properties empirically\"\"\"\n        n_steps = samples.shape[1]\n        \n        # Check expectation is constant\n        means = np.mean(samples, axis=0)\n        mean_changes = np.diff(means)\n        \n        # Check increments are uncorrelated with past\n        correlations = []\n        for lag in range(1, 5):\n            corr = np.corrcoef(\n                samples[:, lag:],\n                samples[:, :-lag]\n            )[0, 1]\n            correlations.append(corr)\n        \n        return {\n            \"means\": means,\n            \"mean_drift\": np.mean(mean_changes),\n            \"increments_correlations\": correlations,\n            \"is_martingale\": all(abs(c) \u003C 0.1 for c in correlations)\n        }\n\n# Example: Brownian motion is a martingale\nbm = BrownianMotion()\nsamples = np.array([bm.simulate(1, 1000).values for _ in range(100)])\nresult = MartingaleTest.check_martingale(samples, 0.001)\nprint(f\"Brownian motion is martingale: {result['is_martingale']}\")\n```\n\n-----\n\n## Applications\n\n### Financial Mathematics\n\n```python\nclass BlackScholes:\n    \"\"\"Black-Scholes option pricing\"\"\"\n    \n    @staticmethod\n    def call_price(S: float, K: float, T: float, r: float, sigma: float) -> float:\n        \"\"\"Black-Scholes call price\"\"\"\n        from scipy.stats import norm\n        \n        d1 = (np.log(S \u002F K) + (r + 0.5 * sigma**2) * T) \u002F (sigma * np.sqrt(T))\n        d2 = d1 - sigma * np.sqrt(T)\n        \n        return S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)\n    \n    @staticmethod\n    def put_price(S: float, K: float, T: float, r: float, sigma: float) -> float:\n        \"\"\"Black-Scholes put price\"\"\"\n        from scipy.stats import norm\n        \n        d1 = (np.log(S \u002F K) + (r + 0.5 * sigma**2) * T) \u002F (sigma * np.sqrt(T))\n        d2 = d1 - sigma * np.sqrt(T)\n        \n        return K * np.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)\n    \n    @staticmethod\n    def greeks(S: float, K: float, T: float, r: float, sigma: float) -> Dict:\n        \"\"\"Calculate Greeks\"\"\"\n        from scipy.stats import norm\n        \n        d1 = (np.log(S \u002F K) + (r + 0.5 * sigma**2) * T) \u002F (sigma * np.sqrt(T))\n        d2 = d1 - sigma * np.sqrt(T)\n        \n        return {\n            \"delta\": norm.cdf(d1),\n            \"gamma\": norm.pdf(d1) \u002F (S * sigma * np.sqrt(T)),\n            \"vega\": S * norm.pdf(d1) * np.sqrt(T) \u002F 100,\n            \"theta\": (-S * norm.pdf(d1) * sigma \u002F (2 * np.sqrt(T)) \n                     - r * K * np.exp(-r * T) * norm.cdf(d2)) \u002F 365,\n            \"rho\": K * T * np.exp(-r * T) * norm.cdf(d2) \u002F 100\n        }\n\n# Example\nbs = BlackScholes()\ncall = bs.call_price(100, 100, 1, 0.05, 0.2)\ngreeks = bs.greeks(100, 100, 1, 0.05, 0.2)\nprint(f\"Call price: ${call:.2f}\")\nprint(f\"Delta: {greeks['delta']:.3f}, Gamma: {greeks['gamma']:.4f}\")\n```\n\n-----\n\n## Best Practices\n\n1. **Start with foundations** — Master probability theory before stochastic processes.\n\n2. **Simulate extensively** — Use simulation to build intuition about process behavior.\n\n3. **Verify assumptions** — Check Markov property, stationarity, and other assumptions.\n\n4. **Use appropriate discretizations** — Choose step sizes carefully for numerical methods.\n\n5. **Consider numerical stability** — Implement variance reduction when possible.\n\n6. **Understand limitations** — Know when models break down and why.\n","# Stochastic Processes — Theory and Applications\n\nCovers: **Probability Foundations · Markov Chains · Poisson Processes · Brownian Motion · Stochastic Calculus · Applications**\n\n-----\n\n## Probability Foundations\n\n### Probability Spaces and Random Variables\n\nA probability space consists of three components: the sample space Omega representing all possible outcomes, a sigma-algebra F containing all measurable events, and a probability measure P assigning probabilities to events. Understanding this foundation is essential for rigorously defining stochastic processes.\n\nA random variable is a measurable function X: Omega -> R that assigns a real number to each outcome. The distribution of X is characterized by its cumulative distribution function F(x) = P(X \u003C= x), or by its probability density function f(x) for continuous variables.\n\n**Key Distributions:**\n\n| Distribution | Parameters | Mean | Variance |\n|--------------|-----------|------|----------|\n| Normal | mu, sigma^2 | mu | sigma^2 |\n| Exponential | lambda | 1\u002Flambda | 1\u002Flambda^2 |\n| Poisson | lambda | lambda | lambda |\n| Uniform | a, b | (a+b)\u002F2 | (b-a)^2\u002F12 |\n| Bernoulli | p | p | p(1-p) |\n\n### Expectations and Moments\n\n```python\nimport numpy as np\nfrom scipy import stats\n\n# Calculate expectations\ndef expectation(distribution, func=lambda x: x):\n    \"\"\"Calculate E[g(X)] for distribution\"\"\"\n    if hasattr(distribution, 'expect'):\n        return distribution.expect(func)\n    # Monte Carlo approximation\n    samples = distribution.rvs(100000)\n    return np.mean(func(samples))\n\n# Normal distribution example\nnormal = stats.norm(loc=5, scale=2)\nE_x = normal.mean()  # 5\nVar_x = normal.var()  # 4\nE_x2 = normal.moment(2)  # E[X^2] = Var + E[X]^2 = 4 + 25 = 29\n\n# Conditional expectation\n# E[X|Y=y] - expectation of X given Y=y\ndef conditional_expectation(joint_samples, x_idx, y_idx, y_value):\n    \"\"\"Calculate E[X|Y=y] from samples\"\"\"\n    mask = joint_samples[:, y_idx] == y_value\n    return np.mean(joint_samples[mask, x_idx])\n\n# Moment generating function\ndef mgf_normal(t, mu, sigma):\n    \"\"\"MGF of normal distribution\"\"\"\n    return np.exp(mu * t + 0.5 * sigma**2 * t**2)\n\n# Characteristic function\ndef cf_normal(t, mu, sigma):\n    \"\"\"Characteristic function of normal\"\"\"\n    return np.exp(1j * mu * t - 0.5 * sigma**2 * t**2)\n```\n\n-----\n\n## Markov Chains\n\n### Definition and Properties\n\nA stochastic process {X_n} is a Markov chain if it satisfies the Markov property: given the present, the future is independent of the past. Formally, P(X_{n+1} = j | X_n = i, X_{n-1} = i_{n-1}, ..., X_0 = i_0) = P(X_{n+1} = j | X_n = i).\n\nThe transition matrix P with entries P_{ij} = P(X_{n+1} = j | X_n = i) characterizes the chain. A Markov chain is homogeneous if these transition probabilities are independent of n.\n\n**Key Properties:**\n\n- **Irreducible** — Every state can be reached from every other state\n- **Recurrent** — Expected return time to any state is finite\n- **Transient** — Some states may never be revisited\n- **Periodic** — Returns to states occur at regular intervals\n- **Aperiodic** — No regular return pattern\n\n### Markov Chain Implementation\n\n```python\nimport numpy as np\nfrom dataclasses import dataclass\nfrom typing import Dict, List, Optional\nimport matplotlib.pyplot as plt\n\n@dataclass\nclass MarkovChain:\n    \"\"\"Homogeneous Markov chain\"\"\"\n    states: List[str]\n    transition_matrix: np.ndarray\n    initial_distribution: Optional[np.ndarray] = None\n    \n    def __post_init__(self):\n        n = len(self.states)\n        if self.initial_distribution is None:\n            self.initial_distribution = np.ones(n) \u002F n\n        \n        # Validate\n        assert np.allclose(self.transition_matrix.sum(axis=1), 1)\n        assert len(self.states) == self.transition_matrix.shape[0]\n    \n    def simulate(self, n_steps: int, seed: int = None) -> List[str]:\n        \"\"\"Simulate chain for n_steps\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        path = []\n        current = np.random.choice(len(self.states), p=self.initial_distribution)\n        path.append(self.states[current])\n        \n        for _ in range(n_steps - 1):\n            current = np.random.choice(\n                len(self.states),\n                p=self.transition_matrix[current]\n            )\n            path.append(self.states[current])\n        \n        return path\n    \n    def transition_prob(self, from_state: str, to_state: str, steps: int = 1) -> float:\n        \"\"\"Probability of transitioning from one state to another in n steps\"\"\"\n        i = self.states.index(from_state)\n        j = self.states.index(to_state)\n        \n        if steps == 1:\n            return self.transition_matrix[i, j]\n        \n        return (self.transition_matrix ** steps)[i, j]\n    \n    def stationary_distribution(self) -> np.ndarray:\n        \"\"\"Find stationary distribution pi such that pi = pi * P\"\"\"\n        eigenvalues, eigenvectors = np.linalg.eig(\n            self.transition_matrix.T\n        )\n        \n        # Find eigenvector with eigenvalue closest to 1\n        idx = np.argmin(np.abs(eigenvalues - 1))\n        stationary = np.real(eigenvectors[:, idx])\n        return stationary \u002F stationary.sum()\n    \n    def verify_ergodicity(self) -> Dict:\n        \"\"\"Check if chain is ergodic\"\"\"\n        n = len(self.states)\n        \n        # Check irreducibility\n        reachable = np.linalg.matrix_power(\n            self.transition_matrix + np.eye(n), n - 1\n        ) > 0\n        irreducible = np.all(reachable)\n        \n        # Check aperiodicity\n        eigenvalues = np.linalg.eigvals(self.transition_matrix)\n        eigenvalues = np.round(eigenvalues, 10)\n        eigenvalues = eigenvalues[np.abs(eigenvalues) > 0.01]\n        is_aperiodic = not any(\n            np.isclose(np.abs(e), 1) and \n            np.isclose(np.abs(e ** n - 1), 0)\n            for n in range(2, n + 1)\n            for e in eigenvalues\n        )\n        \n        stationary = self.stationary_distribution()\n        \n        return {\n            \"irreducible\": irreducible,\n            \"aperiodic\": is_aperiodic,\n            \"has_stationary\": True,\n            \"stationary_distribution\": dict(zip(self.states, stationary))\n        }\n\n# Example: Weather model\nweather_states = [\"sunny\", \"cloudy\", \"rainy\"]\nweather_transitions = np.array([\n    [0.7, 0.2, 0.1],  # Sunny -> sunny, cloudy, rainy\n    [0.3, 0.4, 0.3],  # Cloudy -> sunny, cloudy, rainy\n    [0.2, 0.3, 0.5]   # Rainy -> sunny, cloudy, rainy\n])\n\nweather_chain = MarkovChain(weather_states, weather_transitions)\n\n# Simulate\npath = weather_chain.simulate(30)\nprint(\"Weather sequence:\", \" -> \".join(path[:10]))\n\n# Stationary distribution\nstationary = weather_chain.stationary_distribution()\nprint(\"\\nStationary distribution:\")\nfor state, prob in zip(weather_states, stationary):\n    print(f\"  {state}: {prob:.3f}\")\n\n# Verify ergodicity\nprint(\"\\nErgodicity:\", weather_chain.verify_ergodicity())\n```\n\n### Continuous-Time Markov Chains\n\n```python\nclass ContinuousTimeMarkovChain:\n    \"\"\"Continuous-time Markov chain with rate matrix Q\"\"\"\n    \n    def __init__(self, states: List[str], rate_matrix: np.ndarray):\n        self.states = states\n        self.rate_matrix = rate_matrix\n        \n        # Verify row sums to 0\n        assert np.allclose(rate_matrix.sum(axis=1), 0)\n        \n        # Transition matrix for embedded chain\n        n = len(states)\n        self.embedded_matrix = np.zeros((n, n))\n        for i in range(n):\n            if rate_matrix[i].sum() > 0:\n                self.embedded_matrix[i] = rate_matrix[i] \u002F -rate_matrix[i, i]\n    \n    def simulate_jump_times(self, n_jumps: int, initial_state: int = 0, seed: int = None):\n        \"\"\"Simulate path with jump times\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        path = [initial_state]\n        times = [0.0]\n        current = initial_state\n        \n        for _ in range(n_jumps):\n            # Time to next jump (exponential)\n            rate = -self.rate_matrix[current, current]\n            dt = np.random.exponential(1 \u002F rate)\n            times.append(times[-1] + dt)\n            \n            # Next state (embedded chain)\n            current = np.random.choice(\n                len(self.states),\n                p=self.embedded_matrix[current]\n            )\n            path.append(current)\n        \n        return {\n            \"states\": [self.states[s] for s in path],\n            \"times\": times,\n            \"path\": path\n        }\n```\n\n-----\n\n## Poisson Processes\n\n### Definition and Properties\n\nA Poisson process with rate lambda counts events occurring randomly in time. It satisfies: the number of events in any interval follows a Poisson distribution, events occur independently of past events, and the process has stationary increments.\n\nThe interarrival times (times between consecutive events) are independently and exponentially distributed with mean 1\u002Flambda. This property allows simple simulation of Poisson processes.\n\n```python\nclass PoissonProcess:\n    \"\"\"Poisson process with rate lambda\"\"\"\n    \n    def __init__(self, lambda_rate: float):\n        self.lambda_rate = lambda_rate\n    \n    def simulate(self, T: float, seed: int = None) -> Dict:\n        \"\"\"Simulate Poisson process up to time T\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        # Generate interarrival times\n        interarrivals = []\n        t = 0\n        while True:\n            dt = np.random.exponential(1 \u002F self.lambda_rate)\n            t += dt\n            if t > T:\n                break\n            interarrivals.append(dt)\n        \n        # Arrival times\n        arrival_times = np.cumsum(interarrivals)\n        counts = np.arange(1, len(arrival_times) + 1)\n        \n        return {\n            \"arrival_times\": arrival_times,\n            \"counts\": counts,\n            \"n_events\": len(arrival_times)\n        }\n    \n    def probability_k_events(self, k: int, T: float) -> float:\n        \"\"\"P(N(T) = k)\"\"\"\n        from scipy.special import gammainc\n        mu = self.lambda_rate * T\n        return np.exp(-mu) * (mu ** k) \u002F np.math.factorial(k)\n    \n    def arrival_time_distribution(self, n: int) -> np.ndarray:\n        \"\"\"Distribution of arrival times given N(T) = n\"\"\"\n        # Order statistics of uniform\n        return np.sort(np.random.uniform(0, 1, n))\n\n# Compound Poisson process\nclass CompoundPoissonProcess:\n    \"\"\"Compound Poisson process: N(t) with i.i.d. jump sizes\"\"\"\n    \n    def __init__(self, lambda_rate: float, jump_distribution):\n        self.lambda_rate = lambda_rate\n        self.jump_distribution = jump_distribution\n    \n    def simulate(self, T: float, seed: int = None) -> Dict:\n        \"\"\"Simulate compound Poisson process\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        # Generate Poisson arrivals\n        poisson = PoissonProcess(self.lambda_rate)\n        arrivals = poisson.simulate(T)\n        \n        # Generate jump sizes\n        n = arrivals[\"n_events\"]\n        jump_sizes = self.jump_distribution.rvs(n)\n        \n        # Compound process values\n        values = np.cumsum(jump_sizes)\n        times = arrivals[\"arrival_times\"]\n        \n        return {\n            \"times\": times,\n            \"values\": values,\n            \"jump_sizes\": jump_sizes,\n            \"final_value\": values[-1] if n > 0 else 0\n        }\n```\n\n-----\n\n## Brownian Motion\n\n### Definition and Properties\n\nStandard Brownian motion B(t) is a stochastic process with: B(0) = 0, stationary increments, independent increments, and continuous paths almost surely. The increments B(t) - B(s) ~ N(0, t-s).\n\nBrownian motion is a martingale, has infinite variation, is nowhere differentiable, and exhibits fractal behavior. These properties make it both mathematically interesting and practically useful for modeling random fluctuations.\n\n```python\nclass BrownianMotion:\n    \"\"\"Standard Brownian motion\"\"\"\n    \n    def __init__(self, drift: float = 0, diffusion: float = 1):\n        self.drift = drift\n        self.diffusion = diffusion\n    \n    def simulate(self, T: float, n_steps: int, seed: int = None) -> Dict:\n        \"\"\"Simulate Brownian motion\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        dt = T \u002F n_steps\n        t = np.linspace(0, T, n_steps + 1)\n        \n        # Increments\n        dW = np.random.normal(0, np.sqrt(dt), n_steps)\n        \n        # Path\n        W = np.zeros(n_steps + 1)\n        W[1:] = np.cumsum(dW)\n        \n        # Add drift and diffusion\n        if self.drift != 0 or self.diffusion != 1:\n            W = self.drift * t + self.diffusion * W\n        \n        return {\n            \"time\": t,\n            \"values\": W,\n            \"final_value\": W[-1]\n        }\n    \n    def simulate_bridge(self, T: float, n_steps: int, start: float, end: float, seed: int = None):\n        \"\"\"Brownian bridge from start to end\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        dt = T \u002F n_steps\n        t = np.linspace(0, T, n_steps + 1)\n        \n        # Standard Brownian bridge\n        W = self.simulate(T, n_steps).values\n        \n        # Transform to bridge\n        # B_bridge(t) = B(t) - t\u002FT * B(T) + (t\u002FT)*start + (1-t\u002FT)*end\n        bridge = W - t \u002F T * W[-1]\n        bridge = bridge + (t \u002F T) * start + (1 - t \u002F T) * end\n        \n        return {\"time\": t, \"values\": bridge}\n    \n    def hitting_time(self, a: float, max_T: float = 100) -> float:\n        \"\"\"First passage time to level a\"\"\"\n        # For standard BM, hitting time has inverse Gaussian distribution\n        if a \u003C= 0:\n            return np.inf\n        \n        # Monte Carlo simulation\n        samples = []\n        for _ in range(1000):\n            path = self.simulate(max_T, 10000)\n            hits = np.where(path[\"values\"] >= a)[0]\n            if len(hits) > 0:\n                samples.append(path[\"time\"][hits[0]])\n        \n        return np.mean(samples) if samples else np.inf\n\n# Geometric Brownian motion\nclass GeometricBrownianMotion:\n    \"\"\"Geometric Brownian motion: S(t) = S(0) * exp((mu - sigma^2\u002F2)t + sigma W(t))\"\"\"\n    \n    def __init__(self, mu: float, sigma: float):\n        self.mu = mu  # drift\n        self.sigma = sigma  # volatility\n    \n    def simulate(self, S0: float, T: float, n_steps: int, seed: int = None) -> Dict:\n        \"\"\"Simulate GBM path\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        dt = T \u002F n_steps\n        t = np.linspace(0, T, n_steps + 1)\n        \n        # Increments\n        dW = np.random.normal(0, np.sqrt(dt), n_steps)\n        \n        # GBM formula\n        drift = (self.mu - 0.5 * self.sigma**2) * dt\n        diffusion = self.sigma * dW\n        \n        log_returns = np.cumsum(drift + diffusion)\n        prices = S0 * np.exp(log_returns)\n        \n        return {\n            \"time\": t,\n            \"prices\": prices,\n            \"log_returns\": log_returns\n        }\n```\n\n-----\n\n## Stochastic Calculus\n\n### Ito Integrals\n\nThe Ito integral extends the concept of integration to stochastic processes. For an Ito process dX = a(t)dt + b(t)dW, the Ito integral integral_0^t b(s)dW(s) captures the martingale part.\n\n**Ito's Lemma:** If X is an Ito process and f is twice-differentiable, then f(X) is also an Ito process:\n\ndf(X) = f'(X)dX + (1\u002F2)f''(X)(dX)^2\n\nwhere (dt)^2 = 0, (dW)^2 = dt, and dW dt = 0.\n\n```python\nclass ItoProcess:\n    \"\"\"Ito process dX = mu(t, X)dt + sigma(t, X)dW\"\"\"\n    \n    def __init__(self, mu_func, sigma_func):\n        self.mu_func = mu_func  # drift function\n        self.sigma_func = sigma_func  # diffusion function\n    \n    def simulate(self, x0: float, T: float, n_steps: int, seed: int = None) -> Dict:\n        \"\"\"Euler-Maruyama discretization\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        dt = T \u002F n_steps\n        sqrt_dt = np.sqrt(dt)\n        \n        t = np.linspace(0, T, n_steps + 1)\n        x = np.zeros(n_steps + 1)\n        x[0] = x0\n        \n        for i in range(n_steps):\n            mu = self.mu_func(t[i], x[i])\n            sigma = self.sigma_func(t[i], x[i])\n            \n            dW = np.random.normal(0, sqrt_dt)\n            x[i + 1] = x[i] + mu * dt + sigma * dW\n        \n        return {\"time\": t, \"values\": x}\n\n# Example: Ornstein-Uhlenbeck process\ndef ou_drift(t, x):\n    return -0.5 * x  # mean-reverting\n\ndef ou_diffusion(t, x):\n    return 0.3  # constant volatility\n\nou_process = ItoProcess(ou_drift, ou_diffusion)\npath = ou_process.simulate(x0=2.0, T=10, n_steps=1000)\n\n# Verify mean reversion\nprint(f\"Initial: {path['values'][0]:.3f}\")\nprint(f\"Final: {path['values'][-1]:.3f}\")\nprint(f\"Mean: {np.mean(path['values']):.3f}\")  # Should be near 0\n```\n\n### Stochastic Differential Equations\n\n```python\nclass SDESolver:\n    \"\"\"Solve stochastic differential equations\"\"\"\n    \n    @staticmethod\n    def euler_maruyama(x0: float, T: float, n_steps: int, \n                      mu, sigma, seed: int = None):\n        \"\"\"Euler-Maruyama method\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        dt = T \u002F n_steps\n        sqrt_dt = np.sqrt(dt)\n        \n        x = np.zeros(n_steps + 1)\n        x[0] = x0\n        \n        for i in range(n_steps):\n            dW = np.random.normal(0, sqrt_dt)\n            x[i + 1] = x[i] + mu(x[i], i * dt) * dt + sigma(x[i], i * dt) * dW\n        \n        return x\n    \n    @staticmethod\n    def milstein(x0: float, T: float, n_steps: int,\n                mu, sigma, dsigma, seed: int = None):\n        \"\"\"Milstein method (includes second-order terms)\"\"\"\n        if seed is not None:\n            np.random.seed(seed)\n        \n        dt = T \u002F n_steps\n        sqrt_dt = np.sqrt(dt)\n        \n        x = np.zeros(n_steps + 1)\n        x[0] = x0\n        \n        for i in range(n_steps):\n            dW = np.random.normal(0, sqrt_dt)\n            xi = x[i]\n            t = i * dt\n            \n            # Milstein correction\n            correction = 0.5 * sigma(xi, t) * dsigma(xi, t) * ((dW**2) - dt)\n            \n            x[i + 1] = xi + mu(xi, t) * dt + sigma(xi, t) * dW + correction\n        \n        return x\n\n# Black-Scholes SDE: dS = mu*S dt + sigma*S dW\ndef bs_drift(S, t):\n    return 0.05 * S  # mu = 5%\n\ndef bs_diffusion(S, t):\n    return 0.2 * S  # sigma = 20%\n\ndef bs_dsigma(S):\n    return 0.2  # derivative of sigma*S wrt S\n\n# Simulate stock price\nsde = SDESolver()\nS0 = 100\nprices = sde.euler_maruyama(S0, 1, 252, bs_drift, bs_diffusion)\nprint(f\"Initial: ${S0:.2f}, Final: ${prices[-1]:.2f}\")\n```\n\n-----\n\n## Martingales\n\n### Definition and Properties\n\nA stochastic process M(t) is a martingale with respect to filtration F_t if: E|M(t)| \u003C infinity for all t, M(t) is adapted to F_t, and E[M(t) | F_s] = M(s) for all s \u003C t.\n\nMartingales generalize the notion of fair games. They have many useful properties: they oscillate around their starting value, they have constant expectation, and various convergence theorems apply.\n\n```python\nclass MartingaleTest:\n    \"\"\"Test if a process is a martingale\"\"\"\n    \n    @staticmethod\n    def check_martingale(samples: np.ndarray, dt: float) -> Dict:\n        \"\"\"Check martingale properties empirically\"\"\"\n        n_steps = samples.shape[1]\n        \n        # Check expectation is constant\n        means = np.mean(samples, axis=0)\n        mean_changes = np.diff(means)\n        \n        # Check increments are uncorrelated with past\n        correlations = []\n        for lag in range(1, 5):\n            corr = np.corrcoef(\n                samples[:, lag:],\n                samples[:, :-lag]\n            )[0, 1]\n            correlations.append(corr)\n        \n        return {\n            \"means\": means,\n            \"mean_drift\": np.mean(mean_changes),\n            \"increments_correlations\": correlations,\n            \"is_martingale\": all(abs(c) \u003C 0.1 for c in correlations)\n        }\n\n# Example: Brownian motion is a martingale\nbm = BrownianMotion()\nsamples = np.array([bm.simulate(1, 1000).values for _ in range(100)])\nresult = MartingaleTest.check_martingale(samples, 0.001)\nprint(f\"Brownian motion is martingale: {result['is_martingale']}\")\n```\n\n-----\n\n## Applications\n\n### Financial Mathematics\n\n```python\nclass BlackScholes:\n    \"\"\"Black-Scholes option pricing\"\"\"\n    \n    @staticmethod\n    def call_price(S: float, K: float, T: float, r: float, sigma: float) -> float:\n        \"\"\"Black-Scholes call price\"\"\"\n        from scipy.stats import norm\n        \n        d1 = (np.log(S \u002F K) + (r + 0.5 * sigma**2) * T) \u002F (sigma * np.sqrt(T))\n        d2 = d1 - sigma * np.sqrt(T)\n        \n        return S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)\n    \n    @staticmethod\n    def put_price(S: float, K: float, T: float, r: float, sigma: float) -> float:\n        \"\"\"Black-Scholes put price\"\"\"\n        from scipy.stats import norm\n        \n        d1 = (np.log(S \u002F K) + (r + 0.5 * sigma**2) * T) \u002F (sigma * np.sqrt(T))\n        d2 = d1 - sigma * np.sqrt(T)\n        \n        return K * np.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)\n    \n    @staticmethod\n    def greeks(S: float, K: float, T: float, r: float, sigma: float) -> Dict:\n        \"\"\"Calculate Greeks\"\"\"\n        from scipy.stats import norm\n        \n        d1 = (np.log(S \u002F K) + (r + 0.5 * sigma**2) * T) \u002F (sigma * np.sqrt(T))\n        d2 = d1 - sigma * np.sqrt(T)\n        \n        return {\n            \"delta\": norm.cdf(d1),\n            \"gamma\": norm.pdf(d1) \u002F (S * sigma * np.sqrt(T)),\n            \"vega\": S * norm.pdf(d1) * np.sqrt(T) \u002F 100,\n            \"theta\": (-S * norm.pdf(d1) * sigma \u002F (2 * np.sqrt(T)) \n                     - r * K * np.exp(-r * T) * norm.cdf(d2)) \u002F 365,\n            \"rho\": K * T * np.exp(-r * T) * norm.cdf(d2) \u002F 100\n        }\n\n# Example\nbs = BlackScholes()\ncall = bs.call_price(100, 100, 1, 0.05, 0.2)\ngreeks = bs.greeks(100, 100, 1, 0.05, 0.2)\nprint(f\"Call price: ${call:.2f}\")\nprint(f\"Delta: {greeks['delta']:.3f}, Gamma: {greeks['gamma']:.4f}\")\n```\n\n-----\n\n## Best Practices\n\n1. **Start with foundations** — Master probability theory before stochastic processes.\n\n2. **Simulate extensively** — Use simulation to build intuition about process behavior.\n\n3. **Verify assumptions** — Check Markov property, stationarity, and other assumptions.\n\n4. **Use appropriate discretizations** — Choose step sizes carefully for numerical methods.\n\n5. **Consider numerical stability** — Implement variance reduction when possible.\n\n6. **Understand limitations** — Know when models break down and why.\n",{"name":5,"license":15,"metadata":43,"description":48,"compatibility":35},{"tags":44,"audience":47,"category":31},[5,45,46,29],"markov-chains","brownian-motion","mathematicians, data-scientists, financial-analysts","Expert guidance on random processes, Markov chains, Brownian motion, and stochastic calculus.  Use for: modeling random systems, Markov chain analysis, Poisson processes, Brownian motion,  Ito calculus, stochastic differential equations, martingale theory, and financial mathematics.\n","main","2ea764e153842704d24a2e9aa4170441a7f03081",".opencode\u002Fskills\u002Fstochastic-processes","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito","https:\u002F\u002Fgithub.com\u002FNeuralBlitz","nuralnexus.org","Independent Multidisciplinary Researcher, Creative Producer, and AI Systems Architect\r\nAn independent creator and research-driven systems designer.","2026-11-12 03:13:05",{"source":8,"skillName":5,"commands":58,"prompt":68,"zipAvailable":69},[59,62,65],{"tool":60,"command":61},"npx","npx skills add NeuralBlitz\u002FMito --skill stochastic-processes",{"tool":63,"command":64},"bunx","bunx skills add NeuralBlitz\u002FMito --skill stochastic-processes",{"tool":66,"command":67},"pnpm","pnpm dlx skills add NeuralBlitz\u002FMito --skill stochastic-processes","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fstochastic-processes\u002FSKILL.md",true,[],[72,87,100,113,121,146],{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":78,"publishedAt":38},"01M6HAZSAQK1S27CEZYAYJTQDX","wireless-communications","Wireless systems, mobile networks, and 5G\u002F6G","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fwireless-communications\u002FSKILL.md",[],[79,80,81,26,82,83,84,85,35,86],"communications","wireless communications","wireless","engineering","networks","5G","students","mobile",{"skillNo":88,"name":89,"nameZh":6,"description":90,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":91,"categories":92,"keywords":93,"publishedAt":38},"01M6HAZFX6E8NK3WZWDX5YCKYY","websockets","WebSocket implementation and best practices","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fwebassembly\u002Fwebsockets\u002FSKILL.md",[],[89,94,95,96,35,97,98,99],"websocket implementation","time","implementation","real-time","websocket","best practices",{"skillNo":101,"name":102,"nameZh":6,"description":103,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":106,"publishedAt":38},"01M6HAZ6DAXBQ7QHXXM1EM7715","vulnerability-auditing","Vulnerability assessment and auditing","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fvulnerability-auditing\u002FSKILL.md",[],[107,108,109,110,35,111,112],"vulnerability","vulnerability auditing","security","vulnerability assessment","cybersecurity","assessment",{"skillNo":114,"name":115,"nameZh":6,"description":116,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":117,"categories":118,"keywords":119,"publishedAt":38},"01M6HAZ3FKF3CS9Z3J96RVE2ZE","vulnerability-assessment","Finding and assessing security vulnerabilities","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fvue\u002Fvulnerability-assessment\u002FSKILL.md",[],[110,107,112,109,120,35],"vulnerabilities",{"skillNo":122,"name":123,"nameZh":6,"description":124,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":125,"categories":126,"keywords":137,"publishedAt":38},"01M6HAYSHM6HKRKEHFP0SGZQX7","vlsi-design","Very-Large-Scale Integration circuit design and semiconductor engineering","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fvlsi-design\u002FSKILL.md",[127,132],{"categoryNo":128,"categoryName":129,"taxonomyType":130,"taxonomyTypeDesc":131},"01JBSEEDCAT000000000000015","视觉设计","SCENARIO","使用场景",{"categoryNo":133,"categoryName":134,"taxonomyType":135,"taxonomyTypeDesc":136},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[138,139,140,141,142,82,143,35,144,85,145],"vlsi design","VLSI","design","hardware","integration","computer","scale","circuit",{"skillNo":147,"name":148,"nameZh":6,"description":149,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":150,"categories":151,"keywords":152,"publishedAt":38},"01M6HAYPQ30FFE2JXD7WQJ8R6C","unsupervised","Unsupervised learning concepts","https:\u002F\u002Fgithub.com\u002FNeuralBlitz\u002FMito\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fvisualization\u002Funsupervised\u002FSKILL.md",[],[148,153,35,154,155,156,157,158],"learning","intelligence","unsupervised learning","machine","concepts","machine-learning"]