<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>bwrob blog</title>
<link>https://bwrob.github.io/</link>
<atom:link href="https://bwrob.github.io/index.xml" rel="self" type="application/rss+xml"/>
<description>Personal blog about programming, finance, and physics.</description>
<image>
<url>https://bwrob.github.io/assets/logo/logo_full.png</url>
<title>bwrob blog</title>
<link>https://bwrob.github.io/</link>
<height>15</height>
<width>144</width>
</image>
<generator>quarto-1.10.18</generator>
<lastBuildDate>Thu, 02 Jul 2026 00:00:00 GMT</lastBuildDate>
<item>
  <title>Profiling Python OOMs</title>
  <link>https://bwrob.github.io/posts/26-07-02-oom-python/</link>
  <description><![CDATA[ 






<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/26-07-02-oom-python/image.jpg" class="lightbox" data-gallery="quarto-lightbox-gallery-1"><img src="https://bwrob.github.io/assets/images/posts/26-07-02-oom-python/image.jpg" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:95.0%"></a></p>
</figure>
</div>
<p>Finding memory leaks in Python gets complicated when using compiled extensions like NumPy, PyO3, or pybind11. When the system Out of Memory (OOM) killer runs, it terminates the process with a <code>SIGKILL</code> without leaving a stack trace.</p>
<p>To debug an OOM, you need to find where the allocation occurred: in a Python object or inside a C/C++ backend.</p>
<p><strong>Memray</strong> is a Python memory profiler that can track allocations down to the native level. Note that it only works on UNIX-based operating systems.</p>
<section id="setting-memory-limits" class="level2">
<h2 class="anchored" data-anchor-id="setting-memory-limits">Setting Memory Limits</h2>
<p>If the Linux OOM killer terminates the process, Memray cannot write its profile data to disk, and the capture is lost.</p>
<p>We can avoid this by setting a soft memory limit using Python’s built-in <code>resource</code> module. This forces the interpreter to raise a <code>MemoryError</code> before the OS terminates the process, allowing Memray to save the profile data.</p>
</section>
<section id="a-memory-leak-example" class="level2">
<h2 class="anchored" data-anchor-id="a-memory-leak-example">A Memory Leak Example</h2>
<p>Below is an example script that triggers an OOM using either a Python bytes object or a NumPy array.</p>
<section id="setting-the-limit" class="level3">
<h3 class="anchored" data-anchor-id="setting-the-limit">Setting the Limit</h3>
<p>First, we define a utility function to set the virtual memory limit.</p>
<div id="63d52920" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> os</span>
<span id="annotated-cell-1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> resource</span>
<span id="annotated-cell-1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> secrets</span>
<span id="annotated-cell-1-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="annotated-cell-1-5"></span>
<span id="annotated-cell-1-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> limit_memory(max_bytes: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="annotated-cell-1-7">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Set a virtual memory limit to trigger a Python MemoryError before OS SIGKILL."""</span></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-1" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-1-8" class="code-annotation-target">    resource.setrlimit(resource.RLIMIT_AS, (max_bytes, max_bytes))</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-1" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-1" data-code-lines="8" data-code-annotation="1">The <code>resource.setrlimit</code> function caps the virtual memory (<code>RLIMIT_AS</code>) available to the process. When memory usage exceeds this limit, the OS denies further allocations, raising a <code>MemoryError</code> instead of terminating the process.</span>
</dd>
</dl>
</div>
</div>
</section>
<section id="pure-python-allocation" class="level3">
<h3 class="anchored" data-anchor-id="pure-python-allocation">Pure Python Allocation</h3>
<p>Next, we define a function that allocates memory using Python bytes.</p>
<div id="6c374103" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> leak_python() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="annotated-cell-2-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Trigger an OOM error by allocating progressively larger Python bytes objects."""</span></span>
<span id="annotated-cell-2-3">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Triggering OOM with a single pure Python bytes object..."</span>)</span>
<span id="annotated-cell-2-4">    current_size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Start at 10 MB</span></span>
<span id="annotated-cell-2-5">    data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="annotated-cell-2-6"></span>
<span id="annotated-cell-2-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>:</span>
<span id="annotated-cell-2-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> data <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-2" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-2-9" class="code-annotation-target">            <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">del</span> data  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Explicitly free memory before the next allocation</span></span>
<span id="annotated-cell-2-10"></span>
<span id="annotated-cell-2-11">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Attempting to allocate </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>current_size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> MB bytes object..."</span>)</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-2" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-2-12" class="code-annotation-target">        data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> os.urandom(current_size)</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-2" data-target-annotation="3" onclick="event.preventDefault();">3</a><span id="annotated-cell-2-13" class="code-annotation-target">        current_size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(current_size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-2" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-2" data-code-lines="9" data-code-annotation="1">Freeing the previous allocation ensures the OOM is triggered by a single large allocation failing, rather than gradual accumulation.</span>
</dd>
<dt data-target-cell="annotated-cell-2" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-2" data-code-lines="12" data-code-annotation="2"><code>os.urandom</code> generates uncompressible bytes, preventing OS memory compression from masking the size of the allocation.</span>
</dd>
<dt data-target-cell="annotated-cell-2" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-2" data-code-lines="13" data-code-annotation="3">Grow by 50% each iteration.</span>
</dd>
</dl>
</div>
</div>
</section>
<section id="numpy-allocation" class="level3">
<h3 class="anchored" data-anchor-id="numpy-allocation">NumPy Allocation</h3>
<p>We also define a function that allocates memory via NumPy.</p>
<div id="70691f96" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-3" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> leak_numpy() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="annotated-cell-3-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Trigger an OOM error by allocating progressively larger NumPy float64 arrays."""</span></span>
<span id="annotated-cell-3-3">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Triggering OOM with a single native NumPy array..."</span>)</span>
<span id="annotated-cell-3-4">    current_elements <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 8 bytes per float64</span></span>
<span id="annotated-cell-3-5">    arr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="annotated-cell-3-6"></span>
<span id="annotated-cell-3-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>:</span>
<span id="annotated-cell-3-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> arr <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="annotated-cell-3-9">            <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">del</span> arr  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Explicitly free memory before the next allocation</span></span>
<span id="annotated-cell-3-10"></span>
<span id="annotated-cell-3-11">        mb_size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (current_elements <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="annotated-cell-3-12">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Attempting to allocate </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>mb_size<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> MB float64 array..."</span>)</span>
<span id="annotated-cell-3-13"></span>
<span id="annotated-cell-3-14">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This single C-level malloc will eventually fail and raise MemoryError</span></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-3-15" class="code-annotation-target">        arr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.ones(current_elements, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>np.float64)</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-3-16" class="code-annotation-target">        current_elements <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(current_elements <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-3" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="15" data-code-annotation="1">NumPy arrays are backed by C/C++ allocations. When <code>np.ones</code> is called, it bypasses Python’s memory manager and requests contiguous memory from the system. Without native profiling enabled, Memray would only track the Python wrapper, missing the underlying C allocation.</span>
</dd>
<dt data-target-cell="annotated-cell-3" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="16" data-code-annotation="2">Grow by 50% each iteration.</span>
</dd>
</dl>
</div>
</div>
</section>
<section id="running-the-simulator" class="level3">
<h3 class="anchored" data-anchor-id="running-the-simulator">Running the Simulator</h3>
<p>The entry point sets the memory limit and runs one of the allocation functions.</p>
<div id="6d986e5e" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-4" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-4-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"__main__"</span>:</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-4" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-4-2" class="code-annotation-target">    limit_memory(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="annotated-cell-4-3"></span>
<span id="annotated-cell-4-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="annotated-cell-4-5">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> secrets.choice([<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>]):</span>
<span id="annotated-cell-4-6">            leak_python()</span>
<span id="annotated-cell-4-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="annotated-cell-4-8">            leak_numpy()</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-4" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-4-9" class="code-annotation-target">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">MemoryError</span>:</span>
<span id="annotated-cell-4-10">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">[!] MemoryError caught. Memray can now flush the capture file to disk."</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-4" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-4" data-code-lines="2" data-code-annotation="1">Restricts the process to exactly 1 GB of virtual memory.</span>
</dd>
<dt data-target-cell="annotated-cell-4" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-4" data-code-lines="9" data-code-annotation="2">Catching <code>MemoryError</code> allows the script to exit gracefully. This is required for Memray to flush its buffers and write the profile data to disk.</span>
</dd>
</dl>
</div>
</div>
</section>
</section>
<section id="running-the-profiler" class="level2">
<h2 class="anchored" data-anchor-id="running-the-profiler">Running the Profiler</h2>
<p>To capture native allocations, run the script with the <code>--native</code> flag:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">memray</span> run <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--native</span> oom_simulator.py</span></code></pre></div></div>
<p>This generates a binary capture file (e.g., <code>memray-oom_simulator.py.12345.bin</code>).</p>
</section>
<section id="analyzing-the-results" class="level2">
<h2 class="anchored" data-anchor-id="analyzing-the-results">Analyzing the Results</h2>
<p>Memray provides several formats to analyze the generated binary file.</p>
<section id="html-flamegraph" class="level3">
<h3 class="anchored" data-anchor-id="html-flamegraph">HTML Flamegraph</h3>
<p>You can generate an interactive HTML flamegraph to visualize allocations:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">memray</span> flamegraph memray-oom_simulator.py.12345.bin</span></code></pre></div></div>
<p>This will produce an HTML file that you can open in a browser.</p>
<ul>
<li><strong>Python Allocation:</strong> The graph will show a large block for <code>os.urandom</code>.</li>
<li><strong>NumPy Allocation:</strong> The graph will show the call stack going from Python into <code>numpy.core.multiarray.ones</code> and down to the C allocation function that blew the 1 GB limit.</li>
</ul>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/26-07-02-oom-python/memray-flamegraph.png" class="lightbox" data-glightbox="description: .lightbox-desc-2;title:Memray Flamegraph;" data-gallery="memray" title="Memray Flamegraph"><img src="https://bwrob.github.io/assets/images/posts/26-07-02-oom-python/memray-flamegraph.png" class="img-fluid figure-img" alt="Memray Flamegraph"></a></p>
<figcaption>Memray Flamegraph</figcaption>
</figure>
</div>
</section>
<section id="live-terminal-ui" class="level3">
<h3 class="anchored" data-anchor-id="live-terminal-ui">Live Terminal UI</h3>
<p>Memray includes a terminal UI (similar to <code>htop</code>) to view memory allocations in real time:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">memray</span> run <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--native</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--live</span> oom_simulator.py</span></code></pre></div></div>
<p>This shows real-time memory spikes, top allocating files, and a running plot of heap usage. It is useful for monitoring background services over SSH.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/26-07-02-oom-python/memray-live.png" class="lightbox" data-glightbox="description: .lightbox-desc-3;title:Memray Live TUI;" data-gallery="memray" title="Memray Live TUI"><img src="https://bwrob.github.io/assets/images/posts/26-07-02-oom-python/memray-live.png" class="img-fluid figure-img" alt="Memray Live TUI"></a></p>
<figcaption>Memray Live TUI</figcaption>
</figure>
</div>
</section>
<section id="statistics-summary" class="level3">
<h3 class="anchored" data-anchor-id="statistics-summary">Statistics Summary</h3>
<p>For a quick text summary of allocations, use the <code>stats</code> command:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">memray</span> stats memray-oom_simulator.py.12345.bin</span></code></pre></div></div>
<p>This outputs a summary directly to the terminal, containing:</p>
<ul>
<li>Total memory allocated.</li>
<li>The top allocating functions (both Python and C-level).</li>
<li>A histogram of allocation sizes.</li>
</ul>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/26-07-02-oom-python/memray-stats.png" class="lightbox" data-glightbox="description: .lightbox-desc-4;title:Memray Stats;" data-gallery="memray" title="Memray Stats"><img src="https://bwrob.github.io/assets/images/posts/26-07-02-oom-python/memray-stats.png" class="img-fluid figure-img" alt="Memray Stats"></a></p>
<figcaption>Memray Stats</figcaption>
</figure>
</div>
</section>
<section id="terminal-tree-view" class="level3">
<h3 class="anchored" data-anchor-id="terminal-tree-view">Terminal Tree View</h3>
<p>You can also render an inverted call graph in the terminal using the <code>tree</code> command:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">memray</span> tree memray-oom_simulator.py.12345.bin</span></code></pre></div></div>
<p>This visualizes the call relationships of functions that consumed memory. It helps trace a memory leak straight to the source.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/26-07-02-oom-python/memray-tree.png" class="lightbox" data-glightbox="description: .lightbox-desc-5;title:Memray Tree;" data-gallery="memray" title="Memray Tree"><img src="https://bwrob.github.io/assets/images/posts/26-07-02-oom-python/memray-tree.png" class="img-fluid figure-img" alt="Memray Tree"></a></p>
<figcaption>Memray Tree</figcaption>
</figure>
</div>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Download the companion script <a href="../../assets/python/oom_simulator.py">here</a>.</p>
</div>
</div>



</section>
</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Performance</category>
  <guid>https://bwrob.github.io/posts/26-07-02-oom-python/</guid>
  <pubDate>Thu, 02 Jul 2026 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/assets/images/posts/26-07-02-oom-python/image.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Python Powered Terminal Tools</title>
  <link>https://bwrob.github.io/posts/26-05-06-python-powered-terminal-tools/</link>
  <description><![CDATA[ 






<p>Python-native terminal utilities that can be installed directly via <code>uv</code> or <code>pipx</code>. Useful for either quick and dirty work, or a productivity boost in an environment where you don’t have full privileges to install your favourite toolchain.</p>
<ul>
<li><p><strong><a href="https://github.com/rishubil/textual-code"><code>textual-code</code></a></strong></p>
<p>The best modern TUI code editor. Built on Textual, offering VS Code/Sublime-like features (file explorer, multi-cursor, mouse support) out of the box.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> tool install textual-code <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--python</span> 3.13</span></code></pre></div></div></li>
<li><p><strong><a href="https://github.com/ranger/ranger"><code>ranger-fm</code></a></strong></p>
<p>The classic, highly customizable terminal file manager with Vim bindings and a multi-column preview layout.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> tool install ranger-fm <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--python</span> 3.13</span></code></pre></div></div></li>
<li><p><strong><a href="https://github.com/saulpw/visidata"><code>visidata</code></a></strong></p>
<p>The “Excel of the terminal.” Incredibly fast tabular data explorer for CSV, Excel, SQLite, IPC and JSON files.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> tool install <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--with</span> pyarrow visidata</span></code></pre></div></div></li>
<li><p><strong><a href="https://github.com/nicolargo/glances"><code>glances</code></a></strong></p>
<p>The absolute powerhouse system monitor. Tracks CPU, RAM, Docker, GPUs, temperatures, and network speeds all at once. Works locally or as a web dashboard you can monitor from your network. Useful for checking status of local home server.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> tool install <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"glances[all]"</span></span></code></pre></div></div></li>
<li><p><strong><a href="https://github.com/jeffkaufman/icdiff"><code>icdiff</code></a></strong></p>
<p>Improved colored diffs. Displays side-by-side terminal diffs with word-level color coding.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> tool install icdiff</span></code></pre></div></div></li>
<li><p><strong><a href="https://github.com/davep/hike"><code>hike</code></a></strong></p>
<p>A terminal-based Markdown browser with clickable hyperlinks and beautiful rendering.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> tool install hike</span></code></pre></div></div></li>
<li><p><strong><a href="https://github.com/Textualize/rich-cli"><code>rich-cli</code></a></strong></p>
<p>A massive upgrade to <code>cat</code>. Renders files with full syntax highlighting and proper formatting.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> tool install rich-cli</span></code></pre></div></div></li>
<li><p><strong><a href="https://github.com/SunnyTamang/pygitzen"><code>pygitzen</code></a></strong></p>
<p>A Python-native Git dashboard to stage files, view diffs, and commit without remembering complex commands. Heavily inspired by LazyGit.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> tool install pygitzen</span></code></pre></div></div></li>
<li><p><strong><a href="https://github.com/tconbeer/harlequin"><code>harlequin</code></a></strong></p>
<p>A drop-in terminal IDE replacement for DBeaver/DataGrip. Supports DuckDB, SQLite, PostgreSQL, etc., with a schema sidebar and query editor.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> tool install harlequin</span></code></pre></div></div></li>
</ul>



<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Dev Env</category>
  <guid>https://bwrob.github.io/posts/26-05-06-python-powered-terminal-tools/</guid>
  <pubDate>Wed, 06 May 2026 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/posts/26-05-06-python-powered-terminal-tools/cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Serverless Marimo Dashboard</title>
  <link>https://bwrob.github.io/posts/26-04-24-serverless-marimo-dashboard/</link>
  <description><![CDATA[ 






<p><code>marimo</code> is a fantastic tool for collecting and analyzing data, in many ways more powerful than Jupyter. One of the selling points for me is it’s reactive data flow model. No more worrying about running cells in the right order or dealing with stale data. With <code>marimo</code>, your data is always up to date and your analysis is always accurate. This design, combined with it’s app view (layouts) makes it an efficient vehicle for creating interactive dashboards.</p>
<p>If you’re new to <code>marimo</code>, you can get started with the tutorials shiped with the library. Just run in your shell of choice:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> run marimo tutorial</span></code></pre></div></div>
<p>Setting up a dashboard to convey an important analysis (like convincing your partner to buy new gaming PC) can be a 10x solution. But paying for hosting and maintaining a server for a this can eat up valuable cash resources for those RAM sticks. That’s where <code>webasembly</code> and <code>pyodide</code> come in. You can run fully fledged Python applications directly in the browser. The scope of packages supported is not as wide as a regular Python environment, but it’s still pretty good and growing. You can check out the <a href="https://pyodide.org/en/stable/">pyodide documentation</a> for more details on what’s available.</p>
<p>Here is how you can create a serverless Marimo dashboard:</p>
<ol type="1">
<li><p>Create a simple dashboard using <code>marimo</code>. Set the layout to create an interactive experience. Beware, not all python libraries are supported, but you can still do a lot with the ones that are - <code>pandas</code>, <code>matplotlib</code>, <code>plotly</code>, <code>polars</code> and more.</p></li>
<li><p>Use <code>marimo</code> to export your dashbooard to webassembly. Marimo has built-in support for exporting to webassembly, so you can easily create a standalone dashboard that can be hosted anywhere.</p></li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> run marimo export html-wasm assets/python/serverless_marimo_dashboard_example.py <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--output</span> assets/marimo-dashboard <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--mode</span> run</span></code></pre></div></div>
<ol start="3" type="1">
<li>To check if your dashboard works, you can use a simple HTTP server to serve the files locally. For example, you can use Python’s built-in HTTP server module:</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">python</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-m</span> http.server <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--directory</span> assets/marimo-dashboard</span></code></pre></div></div>
<ol start="4" type="1">
<li><p>Host your dashboard on a static site hosting service like GitHub Pages, Netlify, or Vercel. Since the dashboard is just a static file, you don’t need to worry about server maintenance or costs.</p></li>
<li><p>When you open the dashboard in your browser, it will load the webassembly module and run your Python code to display the data. You can interact with the dashboard just like you would with any other web application. The compute is done locally in the browser using pyodide, the user is paying for it with their CPU cycles.</p></li>
</ol>
<p>You can try the dashboard out <a href="https://bwrob.github.io/assets/marimo-dashboard/index.html">here</a>.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Download the whole code <a href="../../assets/python/serverless_marimo_dashboard_example.py">here</a>.</p>
</div>
</div>



<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Python Recipes</category>
  <category>Data Science</category>
  <guid>https://bwrob.github.io/posts/26-04-24-serverless-marimo-dashboard/</guid>
  <pubDate>Fri, 24 Apr 2026 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/posts/26-04-24-serverless-marimo-dashboard/cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Polars in Finance Cheat Sheet</title>
  <link>https://bwrob.github.io/posts/26-04-05-polars-expressions-cheat-sheet/</link>
  <description><![CDATA[ 






<p>Polars expressions and contexts applied to S&amp;P 500 OHLCV data. If you know Pandas, the patterns here should click fast.</p>
<section id="loading-financial-data" class="level2">
<h2 class="anchored" data-anchor-id="loading-financial-data">1. Loading Financial Data</h2>
<div id="2850e01a" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> polars <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pl</span>
<span id="annotated-cell-1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> polars.selectors <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> cs</span>
<span id="annotated-cell-1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> pathlib <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Path</span>
<span id="annotated-cell-1-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> os</span>
<span id="annotated-cell-1-5"></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-1" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-1-6" class="code-annotation-target">root <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Path(os.path.abspath(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)).parent.parent</span>
<span id="annotated-cell-1-7"></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-1" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-1-8" class="code-annotation-target">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pl.read_ipc(root <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"assets"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ticker_data.arrow"</span>)</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-1" data-target-annotation="3" onclick="event.preventDefault();">3</a><span id="annotated-cell-1-9" class="code-annotation-target">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.sort([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ticker"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"date"</span>])</span>
<span id="annotated-cell-1-10"></span>
<span id="annotated-cell-1-11">df.head(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-1" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-1" data-code-lines="6" data-code-annotation="1">Set root path to project directory.</span>
</dd>
<dt data-target-cell="annotated-cell-1" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-1" data-code-lines="8" data-code-annotation="2">Load ticker data from an Arrow file.</span>
</dd>
<dt data-target-cell="annotated-cell-1" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-1" data-code-lines="9" data-code-annotation="3">Sort by ticker and date — required for shifts and rolling windows.</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-display" data-execution_count="1">
<div><style>
.dataframe > thead > tr,
.dataframe > tbody > tr {
  text-align: right;
  white-space: pre-wrap;
}
</style>
<small>shape: (5, 7)</small>
<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th">date</th>
<th data-quarto-table-cell-role="th">ticker</th>
<th data-quarto-table-cell-role="th">open</th>
<th data-quarto-table-cell-role="th">high</th>
<th data-quarto-table-cell-role="th">low</th>
<th data-quarto-table-cell-role="th">close</th>
<th data-quarto-table-cell-role="th">volume</th>
</tr>
<tr class="even">
<td>date</td>
<td>str</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>2006-01-03</td>
<td>"A"</td>
<td>19.918699</td>
<td>20.025999</td>
<td>19.5728</td>
<td>19.9783</td>
<td>5.307088e6</td>
</tr>
<tr class="even">
<td>2006-01-04</td>
<td>"A"</td>
<td>20.008101</td>
<td>20.1751</td>
<td>19.900801</td>
<td>20.032</td>
<td>4.195817e6</td>
</tr>
<tr class="odd">
<td>2006-01-05</td>
<td>"A"</td>
<td>19.9485</td>
<td>20.556801</td>
<td>19.9485</td>
<td>20.556801</td>
<td>4.835402e6</td>
</tr>
<tr class="even">
<td>2006-01-06</td>
<td>"A"</td>
<td>20.574699</td>
<td>20.747601</td>
<td>20.3302</td>
<td>20.664101</td>
<td>6.146307e6</td>
</tr>
<tr class="odd">
<td>2006-01-09</td>
<td>"A"</td>
<td>20.664101</td>
<td>20.753599</td>
<td>20.527</td>
<td>20.6045</td>
<td>4.082859e6</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
<section id="expressions-the-atomic-units-of-logic" class="level2">
<h2 class="anchored" data-anchor-id="expressions-the-atomic-units-of-logic">2. Expressions: The Atomic Units of Logic</h2>
<p>Expressions are reusable, composable chunks of logic. Define once, apply anywhere.</p>
<div id="2b14f941" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><a class="code-annotation-anchor" data-target-cell="annotated-cell-2" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-2-1" class="code-annotation-target">log_return <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"close"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"close"</span>).shift(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)).log().over(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ticker"</span>)</span>
<span id="annotated-cell-2-2"></span>
<span id="annotated-cell-2-3">realized_vol <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (log_return.rolling_std(window_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">21</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">252</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)).over(</span>
<span id="annotated-cell-2-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ticker"</span></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-2" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-2-5" class="code-annotation-target">)</span>
<span id="annotated-cell-2-6"></span>
<span id="annotated-cell-2-7"></span>
<span id="annotated-cell-2-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> min_max_scale(name: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> pl.Expr:</span>
<span id="annotated-cell-2-9">    col <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pl.col(name)</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-2" data-target-annotation="3" onclick="event.preventDefault();">3</a><span id="annotated-cell-2-10" class="code-annotation-target">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (col <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> col.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>()) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (col.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> col.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>())</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-2" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-2" data-code-lines="1" data-code-annotation="1">Log returns: ln(P_t / P_{t-1}), calculated within each ticker via <code>.over()</code>.</span>
</dd>
<dt data-target-cell="annotated-cell-2" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-2" data-code-lines="5" data-code-annotation="2">Realized volatility: annualized rolling std (21-day window ≈ 1 trading month).</span>
</dd>
<dt data-target-cell="annotated-cell-2" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-2" data-code-lines="10" data-code-annotation="3">Min-max scaling for ML features.</span>
</dd>
</dl>
</div>
</div>
</section>
<section id="context-selection-feature-engineering" class="level2">
<h2 class="anchored" data-anchor-id="context-selection-feature-engineering">3. Context: Selection &amp; Feature Engineering</h2>
<p><code>with_columns</code> adds multiple indicators in a single pass.</p>
<div id="502db6d5" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-3" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-3-1">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.with_columns(</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-3-2" class="code-annotation-target">    ret<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>log_return,</span>
<span id="annotated-cell-3-3">    vol<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>realized_vol,</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-3-4" class="code-annotation-target">    typical_price<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"high"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"low"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"close"</span>)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,</span>
<span id="annotated-cell-3-5">)</span>
<span id="annotated-cell-3-6"></span>
<span id="annotated-cell-3-7">df.tail(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-3" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="2" data-code-annotation="1">Append log returns and realized volatility.</span>
</dd>
<dt data-target-cell="annotated-cell-3" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="4" data-code-annotation="2">Typical price — common input for Money Flow Index.</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-display" data-execution_count="3">
<div><style>
.dataframe > thead > tr,
.dataframe > tbody > tr {
  text-align: right;
  white-space: pre-wrap;
}
</style>
<small>shape: (5, 10)</small>
<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th">date</th>
<th data-quarto-table-cell-role="th">ticker</th>
<th data-quarto-table-cell-role="th">open</th>
<th data-quarto-table-cell-role="th">high</th>
<th data-quarto-table-cell-role="th">low</th>
<th data-quarto-table-cell-role="th">close</th>
<th data-quarto-table-cell-role="th">volume</th>
<th data-quarto-table-cell-role="th">ret</th>
<th data-quarto-table-cell-role="th">vol</th>
<th data-quarto-table-cell-role="th">typical_price</th>
</tr>
<tr class="even">
<td>date</td>
<td>str</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>2026-04-22</td>
<td>"ZTS"</td>
<td>118.949997</td>
<td>119.910004</td>
<td>116.599998</td>
<td>117.519997</td>
<td>3.5146e6</td>
<td>-0.0056</td>
<td>0.272725</td>
<td>118.010002</td>
</tr>
<tr class="even">
<td>2026-04-23</td>
<td>"ZTS"</td>
<td>117.190002</td>
<td>117.599998</td>
<td>114.949997</td>
<td>116.059998</td>
<td>4.5328e6</td>
<td>-0.012501</td>
<td>0.276069</td>
<td>116.203331</td>
</tr>
<tr class="odd">
<td>2026-04-24</td>
<td>"ZTS"</td>
<td>116.010002</td>
<td>117.050003</td>
<td>115.410004</td>
<td>116.870003</td>
<td>4.1851e6</td>
<td>0.006955</td>
<td>0.276144</td>
<td>116.443344</td>
</tr>
<tr class="even">
<td>2026-04-27</td>
<td>"ZTS"</td>
<td>116.620003</td>
<td>119.68</td>
<td>116.599998</td>
<td>117.870003</td>
<td>3.1603e6</td>
<td>0.00852</td>
<td>0.277579</td>
<td>118.050003</td>
</tr>
<tr class="odd">
<td>2026-04-28</td>
<td>"ZTS"</td>
<td>117.230003</td>
<td>118.290001</td>
<td>116.080002</td>
<td>116.650002</td>
<td>2.9725e6</td>
<td>-0.010404</td>
<td>0.260076</td>
<td>117.006668</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
<section id="context-aggregation-group_by" class="level2">
<h2 class="anchored" data-anchor-id="context-aggregation-group_by">4. Context: Aggregation (<code>group_by</code>)</h2>
<div id="4eba742e" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-4" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-4-1">risk_summary <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.group_by(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ticker"</span>).agg(</span>
<span id="annotated-cell-4-2">    annual_return<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ret"</span>).mean() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">252</span>),</span>
<span id="annotated-cell-4-3">    annual_vol<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ret"</span>).std() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">252</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)),</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-4" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-4-4" class="code-annotation-target">    max_drawdown<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>((pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"close"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"close"</span>).cum_max() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>()),</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-4" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-4-5" class="code-annotation-target">    sharpe_ratio<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ret"</span>).mean() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ret"</span>).std()) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">252</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>),</span>
<span id="annotated-cell-4-6">)</span>
<span id="annotated-cell-4-7"></span>
<span id="annotated-cell-4-8">risk_summary.sort(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sharpe_ratio"</span>, descending<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>).head(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-4" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-4" data-code-lines="4" data-code-annotation="1">Max drawdown via cumulative maximum.</span>
</dd>
<dt data-target-cell="annotated-cell-4" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-4" data-code-lines="5" data-code-annotation="2">Sharpe ratio (assuming 0% risk-free rate).</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-display" data-execution_count="4">
<div><style>
.dataframe > thead > tr,
.dataframe > tbody > tr {
  text-align: right;
  white-space: pre-wrap;
}
</style>
<small>shape: (5, 5)</small>
<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th">ticker</th>
<th data-quarto-table-cell-role="th">annual_return</th>
<th data-quarto-table-cell-role="th">annual_vol</th>
<th data-quarto-table-cell-role="th">max_drawdown</th>
<th data-quarto-table-cell-role="th">sharpe_ratio</th>
</tr>
<tr class="even">
<td>str</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>"SNDK"</td>
<td>2.785047</td>
<td>0.98521</td>
<td>-0.475009</td>
<td>2.826855</td>
</tr>
<tr class="even">
<td>"GEV"</td>
<td>1.023233</td>
<td>0.533674</td>
<td>-0.382856</td>
<td>1.917337</td>
</tr>
<tr class="odd">
<td>"Q"</td>
<td>0.743194</td>
<td>0.545531</td>
<td>-0.271231</td>
<td>1.362331</td>
</tr>
<tr class="even">
<td>"CEG"</td>
<td>0.475289</td>
<td>0.490132</td>
<td>-0.507023</td>
<td>0.969717</td>
</tr>
<tr class="odd">
<td>"AVGO"</td>
<td>0.351236</td>
<td>0.378535</td>
<td>-0.483</td>
<td>0.927882</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
<section id="power-selectors-polars.selectors" class="level2">
<h2 class="anchored" data-anchor-id="power-selectors-polars.selectors">5. Power Selectors (<code>polars.selectors</code>)</h2>
<p>Target columns by properties instead of hardcoding names — handy for scenario shocks.</p>
<div id="7cbf00ba" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-5" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><a class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-5-1" class="code-annotation-target">price_shock <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cs.starts_with(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"open"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"high"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"low"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"close"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.01</span></span>
<span id="annotated-cell-5-2"></span>
<span id="annotated-cell-5-3">df.select(</span>
<span id="annotated-cell-5-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"date"</span>,</span>
<span id="annotated-cell-5-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ticker"</span>,</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-5-6" class="code-annotation-target">    price_shock.name.suffix(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_shock"</span>),</span>
<span id="annotated-cell-5-7">).head(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-5" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="1" data-code-annotation="1">Apply a 1% upward shock to all OHLC columns at once.</span>
</dd>
<dt data-target-cell="annotated-cell-5" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="6" data-code-annotation="2">Suffix the new column names to keep originals intact.</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-display" data-execution_count="5">
<div><style>
.dataframe > thead > tr,
.dataframe > tbody > tr {
  text-align: right;
  white-space: pre-wrap;
}
</style>
<small>shape: (3, 6)</small>
<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th">date</th>
<th data-quarto-table-cell-role="th">ticker</th>
<th data-quarto-table-cell-role="th">open_shock</th>
<th data-quarto-table-cell-role="th">high_shock</th>
<th data-quarto-table-cell-role="th">low_shock</th>
<th data-quarto-table-cell-role="th">close_shock</th>
</tr>
<tr class="even">
<td>date</td>
<td>str</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>2006-01-03</td>
<td>"A"</td>
<td>20.117886</td>
<td>20.226259</td>
<td>19.768528</td>
<td>20.178083</td>
</tr>
<tr class="even">
<td>2006-01-04</td>
<td>"A"</td>
<td>20.208181</td>
<td>20.376852</td>
<td>20.099808</td>
<td>20.232319</td>
</tr>
<tr class="odd">
<td>2006-01-05</td>
<td>"A"</td>
<td>20.147984</td>
<td>20.762369</td>
<td>20.147984</td>
<td>20.762369</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
<section id="window-functions-over" class="level2">
<h2 class="anchored" data-anchor-id="window-functions-over">6. Window Functions (<code>over</code>)</h2>
<p>Compute group-level stats and project them back onto individual rows — no merge needed.</p>
<div id="c368f420" class="cell" data-execution_count="6">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-6" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-6-1">df.with_columns(</span>
<span id="annotated-cell-6-2">    vol_z<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"volume"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"volume"</span>).mean().over(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ticker"</span>))</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-6" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-6-3" class="code-annotation-target">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"volume"</span>).std().over(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ticker"</span>),</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-6" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-6-4" class="code-annotation-target">    rel_strength<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"close"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"close"</span>).mean().over(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"date"</span>),</span>
<span id="annotated-cell-6-5">).head(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-6" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-6" data-code-lines="3" data-code-annotation="1">Volume z-score per ticker — flags unusual trading activity.</span>
</dd>
<dt data-target-cell="annotated-cell-6" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-6" data-code-lines="4" data-code-annotation="2">Cross-sectional relative strength: price vs.&nbsp;market average that day.</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-display" data-execution_count="6">
<div><style>
.dataframe > thead > tr,
.dataframe > tbody > tr {
  text-align: right;
  white-space: pre-wrap;
}
</style>
<small>shape: (5, 12)</small>
<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th">date</th>
<th data-quarto-table-cell-role="th">ticker</th>
<th data-quarto-table-cell-role="th">open</th>
<th data-quarto-table-cell-role="th">high</th>
<th data-quarto-table-cell-role="th">low</th>
<th data-quarto-table-cell-role="th">close</th>
<th data-quarto-table-cell-role="th">volume</th>
<th data-quarto-table-cell-role="th">ret</th>
<th data-quarto-table-cell-role="th">vol</th>
<th data-quarto-table-cell-role="th">typical_price</th>
<th data-quarto-table-cell-role="th">vol_z</th>
<th data-quarto-table-cell-role="th">rel_strength</th>
</tr>
<tr class="even">
<td>date</td>
<td>str</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>2006-01-03</td>
<td>"A"</td>
<td>19.918699</td>
<td>20.025999</td>
<td>19.5728</td>
<td>19.9783</td>
<td>5.307088e6</td>
<td>null</td>
<td>null</td>
<td>19.859035</td>
<td>1.077447</td>
<td>0.749611</td>
</tr>
<tr class="even">
<td>2006-01-04</td>
<td>"A"</td>
<td>20.008101</td>
<td>20.1751</td>
<td>19.900801</td>
<td>20.032</td>
<td>4.195817e6</td>
<td>0.002684</td>
<td>null</td>
<td>20.035969</td>
<td>0.542916</td>
<td>0.748959</td>
</tr>
<tr class="odd">
<td>2006-01-05</td>
<td>"A"</td>
<td>19.9485</td>
<td>20.556801</td>
<td>19.9485</td>
<td>20.556801</td>
<td>4.835402e6</td>
<td>0.025861</td>
<td>null</td>
<td>20.354034</td>
<td>0.850562</td>
<td>0.766769</td>
</tr>
<tr class="even">
<td>2006-01-06</td>
<td>"A"</td>
<td>20.574699</td>
<td>20.747601</td>
<td>20.3302</td>
<td>20.664101</td>
<td>6.146307e6</td>
<td>0.005206</td>
<td>null</td>
<td>20.580635</td>
<td>1.481119</td>
<td>0.764833</td>
</tr>
<tr class="odd">
<td>2006-01-09</td>
<td>"A"</td>
<td>20.664101</td>
<td>20.753599</td>
<td>20.527</td>
<td>20.6045</td>
<td>4.082859e6</td>
<td>-0.002888</td>
<td>null</td>
<td>20.628368</td>
<td>0.488583</td>
<td>0.754984</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
<section id="time-series-rolling-metrics-asof-joins" class="level2">
<h2 class="anchored" data-anchor-id="time-series-rolling-metrics-asof-joins">7. Time Series: Rolling Metrics &amp; Asof Joins</h2>
<div id="14c0a895" class="cell" data-execution_count="7">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-7" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-7-1">df.with_columns(</span>
<span id="annotated-cell-7-2">    vwap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"close"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"volume"</span>)).rolling_sum(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-7" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-7-3" class="code-annotation-target">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"volume"</span>).rolling_sum(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="annotated-cell-7-4">).head(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-7" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-7" data-code-lines="3" data-code-annotation="1">20-day rolling VWAP.</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-display" data-execution_count="7">
<div><style>
.dataframe > thead > tr,
.dataframe > tbody > tr {
  text-align: right;
  white-space: pre-wrap;
}
</style>
<small>shape: (5, 11)</small>
<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th">date</th>
<th data-quarto-table-cell-role="th">ticker</th>
<th data-quarto-table-cell-role="th">open</th>
<th data-quarto-table-cell-role="th">high</th>
<th data-quarto-table-cell-role="th">low</th>
<th data-quarto-table-cell-role="th">close</th>
<th data-quarto-table-cell-role="th">volume</th>
<th data-quarto-table-cell-role="th">ret</th>
<th data-quarto-table-cell-role="th">vol</th>
<th data-quarto-table-cell-role="th">typical_price</th>
<th data-quarto-table-cell-role="th">vwap</th>
</tr>
<tr class="even">
<td>date</td>
<td>str</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
<td>f32</td>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>2006-01-03</td>
<td>"A"</td>
<td>19.918699</td>
<td>20.025999</td>
<td>19.5728</td>
<td>19.9783</td>
<td>5.307088e6</td>
<td>null</td>
<td>null</td>
<td>19.859035</td>
<td>null</td>
</tr>
<tr class="even">
<td>2006-01-04</td>
<td>"A"</td>
<td>20.008101</td>
<td>20.1751</td>
<td>19.900801</td>
<td>20.032</td>
<td>4.195817e6</td>
<td>0.002684</td>
<td>null</td>
<td>20.035969</td>
<td>null</td>
</tr>
<tr class="odd">
<td>2006-01-05</td>
<td>"A"</td>
<td>19.9485</td>
<td>20.556801</td>
<td>19.9485</td>
<td>20.556801</td>
<td>4.835402e6</td>
<td>0.025861</td>
<td>null</td>
<td>20.354034</td>
<td>null</td>
</tr>
<tr class="even">
<td>2006-01-06</td>
<td>"A"</td>
<td>20.574699</td>
<td>20.747601</td>
<td>20.3302</td>
<td>20.664101</td>
<td>6.146307e6</td>
<td>0.005206</td>
<td>null</td>
<td>20.580635</td>
<td>null</td>
</tr>
<tr class="odd">
<td>2006-01-09</td>
<td>"A"</td>
<td>20.664101</td>
<td>20.753599</td>
<td>20.527</td>
<td>20.6045</td>
<td>4.082859e6</td>
<td>-0.002888</td>
<td>null</td>
<td>20.628368</td>
<td>null</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
<section id="reshaping-for-correlation-analysis" class="level2">
<h2 class="anchored" data-anchor-id="reshaping-for-correlation-analysis">8. Reshaping for Correlation Analysis</h2>
<p>Pivot from long to wide for correlation / covariance matrices.</p>
<div id="f0be48d5" class="cell" data-execution_count="8">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-8" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-8-1">wide_returns <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.pivot(</span>
<span id="annotated-cell-8-2">    index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"date"</span>,</span>
<span id="annotated-cell-8-3">    on<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ticker"</span>,</span>
<span id="annotated-cell-8-4">    values<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ret"</span>,</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-8" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-8-5" class="code-annotation-target">).drop_nulls()</span>
<span id="annotated-cell-8-6"></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-8" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-8-7" class="code-annotation-target">corr_matrix <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> wide_returns.select(cs.numeric()).corr()</span>
<span id="annotated-cell-8-8">corr_matrix.head(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-8" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-8" data-code-lines="5" data-code-annotation="1">One column per ticker’s returns.</span>
</dd>
<dt data-target-cell="annotated-cell-8" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-8" data-code-lines="7" data-code-annotation="2">Correlation matrix across all assets.</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-display" data-execution_count="8">
<div><style>
.dataframe > thead > tr,
.dataframe > tbody > tr {
  text-align: right;
  white-space: pre-wrap;
}
</style>
<small>shape: (5, 501)</small>
<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th">A</th>
<th data-quarto-table-cell-role="th">AAPL</th>
<th data-quarto-table-cell-role="th">ABBV</th>
<th data-quarto-table-cell-role="th">ABNB</th>
<th data-quarto-table-cell-role="th">ABT</th>
<th data-quarto-table-cell-role="th">ACGL</th>
<th data-quarto-table-cell-role="th">ACN</th>
<th data-quarto-table-cell-role="th">ADBE</th>
<th data-quarto-table-cell-role="th">ADI</th>
<th data-quarto-table-cell-role="th">ADM</th>
<th data-quarto-table-cell-role="th">ADP</th>
<th data-quarto-table-cell-role="th">ADSK</th>
<th data-quarto-table-cell-role="th">AEE</th>
<th data-quarto-table-cell-role="th">AEP</th>
<th data-quarto-table-cell-role="th">AES</th>
<th data-quarto-table-cell-role="th">AFL</th>
<th data-quarto-table-cell-role="th">AIG</th>
<th data-quarto-table-cell-role="th">AIZ</th>
<th data-quarto-table-cell-role="th">AJG</th>
<th data-quarto-table-cell-role="th">AKAM</th>
<th data-quarto-table-cell-role="th">ALB</th>
<th data-quarto-table-cell-role="th">ALGN</th>
<th data-quarto-table-cell-role="th">ALL</th>
<th data-quarto-table-cell-role="th">ALLE</th>
<th data-quarto-table-cell-role="th">AMAT</th>
<th data-quarto-table-cell-role="th">AMCR</th>
<th data-quarto-table-cell-role="th">AMD</th>
<th data-quarto-table-cell-role="th">AME</th>
<th data-quarto-table-cell-role="th">AMGN</th>
<th data-quarto-table-cell-role="th">AMP</th>
<th data-quarto-table-cell-role="th">AMT</th>
<th data-quarto-table-cell-role="th">AMZN</th>
<th data-quarto-table-cell-role="th">ANET</th>
<th data-quarto-table-cell-role="th">AON</th>
<th data-quarto-table-cell-role="th">AOS</th>
<th data-quarto-table-cell-role="th">APA</th>
<th data-quarto-table-cell-role="th">APD</th>
<th data-quarto-table-cell-role="th">…</th>
<th data-quarto-table-cell-role="th">VICI</th>
<th data-quarto-table-cell-role="th">VLO</th>
<th data-quarto-table-cell-role="th">VLTO</th>
<th data-quarto-table-cell-role="th">VMC</th>
<th data-quarto-table-cell-role="th">VRSK</th>
<th data-quarto-table-cell-role="th">VRSN</th>
<th data-quarto-table-cell-role="th">VRT</th>
<th data-quarto-table-cell-role="th">VRTX</th>
<th data-quarto-table-cell-role="th">VST</th>
<th data-quarto-table-cell-role="th">VTR</th>
<th data-quarto-table-cell-role="th">VTRS</th>
<th data-quarto-table-cell-role="th">VZ</th>
<th data-quarto-table-cell-role="th">WAB</th>
<th data-quarto-table-cell-role="th">WAT</th>
<th data-quarto-table-cell-role="th">WBD</th>
<th data-quarto-table-cell-role="th">WDAY</th>
<th data-quarto-table-cell-role="th">WDC</th>
<th data-quarto-table-cell-role="th">WEC</th>
<th data-quarto-table-cell-role="th">WELL</th>
<th data-quarto-table-cell-role="th">WFC</th>
<th data-quarto-table-cell-role="th">WM</th>
<th data-quarto-table-cell-role="th">WMB</th>
<th data-quarto-table-cell-role="th">WMT</th>
<th data-quarto-table-cell-role="th">WRB</th>
<th data-quarto-table-cell-role="th">WSM</th>
<th data-quarto-table-cell-role="th">WST</th>
<th data-quarto-table-cell-role="th">WTW</th>
<th data-quarto-table-cell-role="th">WY</th>
<th data-quarto-table-cell-role="th">WYNN</th>
<th data-quarto-table-cell-role="th">XEL</th>
<th data-quarto-table-cell-role="th">XOM</th>
<th data-quarto-table-cell-role="th">XYL</th>
<th data-quarto-table-cell-role="th">XYZ</th>
<th data-quarto-table-cell-role="th">YUM</th>
<th data-quarto-table-cell-role="th">ZBH</th>
<th data-quarto-table-cell-role="th">ZBRA</th>
<th data-quarto-table-cell-role="th">ZTS</th>
</tr>
<tr class="even">
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>…</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
<td>f64</td>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>1.0</td>
<td>0.252005</td>
<td>0.159886</td>
<td>0.387158</td>
<td>0.291319</td>
<td>0.051918</td>
<td>0.314924</td>
<td>0.220464</td>
<td>0.365594</td>
<td>0.082219</td>
<td>0.250166</td>
<td>0.352096</td>
<td>0.01177</td>
<td>-0.145537</td>
<td>0.20628</td>
<td>0.149047</td>
<td>-0.048577</td>
<td>0.142817</td>
<td>0.096217</td>
<td>0.21591</td>
<td>0.184219</td>
<td>0.467583</td>
<td>0.129767</td>
<td>0.202938</td>
<td>0.322944</td>
<td>0.333373</td>
<td>0.084619</td>
<td>0.375688</td>
<td>0.321947</td>
<td>0.361348</td>
<td>0.011551</td>
<td>0.34124</td>
<td>0.173192</td>
<td>0.162829</td>
<td>0.229952</td>
<td>-0.147347</td>
<td>0.205694</td>
<td>…</td>
<td>0.016885</td>
<td>-0.049898</td>
<td>0.323352</td>
<td>0.333929</td>
<td>0.135326</td>
<td>0.065517</td>
<td>0.177153</td>
<td>0.315086</td>
<td>0.133985</td>
<td>-0.169327</td>
<td>0.253472</td>
<td>-0.07502</td>
<td>0.337305</td>
<td>0.62843</td>
<td>0.056035</td>
<td>0.257507</td>
<td>0.22573</td>
<td>-0.032459</td>
<td>-0.059922</td>
<td>0.214895</td>
<td>0.004414</td>
<td>-0.119114</td>
<td>0.066659</td>
<td>0.013125</td>
<td>0.385525</td>
<td>0.357492</td>
<td>0.103034</td>
<td>0.16268</td>
<td>0.289355</td>
<td>0.007724</td>
<td>-0.119016</td>
<td>0.23687</td>
<td>0.381205</td>
<td>0.216098</td>
<td>0.196699</td>
<td>0.274606</td>
<td>0.362176</td>
</tr>
<tr class="even">
<td>0.252005</td>
<td>1.0</td>
<td>0.032607</td>
<td>0.353655</td>
<td>0.207605</td>
<td>0.10381</td>
<td>0.050583</td>
<td>0.132521</td>
<td>0.365957</td>
<td>-0.057716</td>
<td>0.06369</td>
<td>0.121071</td>
<td>-0.158196</td>
<td>-0.146113</td>
<td>0.018032</td>
<td>0.205258</td>
<td>0.216694</td>
<td>0.115361</td>
<td>0.003543</td>
<td>-0.085321</td>
<td>0.028355</td>
<td>0.376391</td>
<td>0.127262</td>
<td>0.008084</td>
<td>0.178174</td>
<td>0.273976</td>
<td>0.092632</td>
<td>0.342363</td>
<td>0.248612</td>
<td>0.294118</td>
<td>0.025718</td>
<td>0.231091</td>
<td>0.098731</td>
<td>-0.052414</td>
<td>0.18999</td>
<td>-0.127354</td>
<td>0.106166</td>
<td>…</td>
<td>0.109663</td>
<td>-0.125555</td>
<td>0.149918</td>
<td>0.116569</td>
<td>-0.076417</td>
<td>0.007996</td>
<td>0.242075</td>
<td>0.07343</td>
<td>-0.009934</td>
<td>0.081029</td>
<td>0.401407</td>
<td>-0.069197</td>
<td>0.336963</td>
<td>0.267525</td>
<td>0.150331</td>
<td>0.083502</td>
<td>0.115886</td>
<td>-0.190388</td>
<td>0.044669</td>
<td>0.36324</td>
<td>-0.072876</td>
<td>-0.057587</td>
<td>0.033092</td>
<td>0.117635</td>
<td>0.27519</td>
<td>0.175975</td>
<td>0.068427</td>
<td>0.108035</td>
<td>0.365579</td>
<td>-0.149933</td>
<td>-0.108486</td>
<td>0.194755</td>
<td>0.151375</td>
<td>0.146997</td>
<td>0.06224</td>
<td>0.188564</td>
<td>0.252188</td>
</tr>
<tr class="odd">
<td>0.159886</td>
<td>0.032607</td>
<td>1.0</td>
<td>0.025042</td>
<td>0.17823</td>
<td>0.1801</td>
<td>0.051987</td>
<td>0.065414</td>
<td>0.029073</td>
<td>0.030087</td>
<td>-0.049793</td>
<td>0.074998</td>
<td>0.27563</td>
<td>0.201132</td>
<td>0.01249</td>
<td>0.162784</td>
<td>0.032822</td>
<td>0.151542</td>
<td>0.089796</td>
<td>0.13993</td>
<td>0.098696</td>
<td>0.106788</td>
<td>0.131893</td>
<td>0.054494</td>
<td>0.021722</td>
<td>0.108147</td>
<td>0.003968</td>
<td>0.181843</td>
<td>0.389602</td>
<td>-0.032594</td>
<td>0.105185</td>
<td>-0.112818</td>
<td>-0.002974</td>
<td>0.035057</td>
<td>0.120331</td>
<td>-0.133418</td>
<td>0.137989</td>
<td>…</td>
<td>0.028821</td>
<td>-0.092267</td>
<td>0.206458</td>
<td>0.08881</td>
<td>0.081341</td>
<td>-0.101082</td>
<td>0.004792</td>
<td>0.433486</td>
<td>-0.154702</td>
<td>0.184427</td>
<td>0.14594</td>
<td>0.123576</td>
<td>0.107561</td>
<td>0.05267</td>
<td>0.036274</td>
<td>-0.130214</td>
<td>-0.060284</td>
<td>0.194187</td>
<td>0.229703</td>
<td>-0.040875</td>
<td>0.105738</td>
<td>0.055912</td>
<td>0.229642</td>
<td>0.057308</td>
<td>0.04018</td>
<td>0.160114</td>
<td>0.013678</td>
<td>0.040071</td>
<td>-0.121142</td>
<td>0.183901</td>
<td>-0.111634</td>
<td>0.084572</td>
<td>0.053288</td>
<td>0.195927</td>
<td>0.009359</td>
<td>-0.03683</td>
<td>-0.018306</td>
</tr>
<tr class="even">
<td>0.387158</td>
<td>0.353655</td>
<td>0.025042</td>
<td>1.0</td>
<td>0.179758</td>
<td>0.069289</td>
<td>0.408465</td>
<td>0.469951</td>
<td>0.41908</td>
<td>-0.003487</td>
<td>0.454314</td>
<td>0.500417</td>
<td>-0.086092</td>
<td>-0.187378</td>
<td>-0.005041</td>
<td>0.155108</td>
<td>0.131687</td>
<td>0.26926</td>
<td>0.201723</td>
<td>0.092757</td>
<td>0.196378</td>
<td>0.559737</td>
<td>0.112407</td>
<td>0.127923</td>
<td>0.296559</td>
<td>0.276444</td>
<td>0.173123</td>
<td>0.297822</td>
<td>0.195929</td>
<td>0.433715</td>
<td>-0.006856</td>
<td>0.417421</td>
<td>0.322316</td>
<td>0.226075</td>
<td>0.217916</td>
<td>-0.153585</td>
<td>-0.079396</td>
<td>…</td>
<td>0.053546</td>
<td>-0.091131</td>
<td>0.448981</td>
<td>0.12535</td>
<td>0.24754</td>
<td>0.193942</td>
<td>0.155101</td>
<td>0.2933</td>
<td>0.108703</td>
<td>-0.09358</td>
<td>0.293449</td>
<td>-0.223877</td>
<td>0.354082</td>
<td>0.348563</td>
<td>0.159664</td>
<td>0.396202</td>
<td>0.156269</td>
<td>-0.177693</td>
<td>-0.075159</td>
<td>0.368768</td>
<td>0.012266</td>
<td>-0.014705</td>
<td>-0.084896</td>
<td>-0.146465</td>
<td>0.44977</td>
<td>0.284118</td>
<td>0.182924</td>
<td>0.037971</td>
<td>0.439027</td>
<td>-0.130453</td>
<td>-0.272673</td>
<td>0.284202</td>
<td>0.451018</td>
<td>0.021685</td>
<td>0.142714</td>
<td>0.384437</td>
<td>0.45244</td>
</tr>
<tr class="odd">
<td>0.291319</td>
<td>0.207605</td>
<td>0.17823</td>
<td>0.179758</td>
<td>1.0</td>
<td>0.135045</td>
<td>0.082257</td>
<td>-0.01935</td>
<td>0.121082</td>
<td>0.129791</td>
<td>0.053078</td>
<td>-0.057555</td>
<td>0.235583</td>
<td>0.179526</td>
<td>0.038046</td>
<td>0.225051</td>
<td>0.124796</td>
<td>0.100274</td>
<td>0.090429</td>
<td>0.032748</td>
<td>-0.07607</td>
<td>0.23032</td>
<td>0.184531</td>
<td>0.133566</td>
<td>0.092136</td>
<td>0.224374</td>
<td>-0.145982</td>
<td>0.167634</td>
<td>0.177653</td>
<td>0.073567</td>
<td>0.151422</td>
<td>-0.07323</td>
<td>-0.16457</td>
<td>0.005134</td>
<td>0.142195</td>
<td>-0.005853</td>
<td>0.199751</td>
<td>…</td>
<td>0.141295</td>
<td>-0.051328</td>
<td>0.31528</td>
<td>0.121736</td>
<td>0.047432</td>
<td>0.100863</td>
<td>0.08491</td>
<td>0.126726</td>
<td>0.014749</td>
<td>0.292106</td>
<td>0.13791</td>
<td>0.088639</td>
<td>0.223678</td>
<td>0.151275</td>
<td>0.095275</td>
<td>-0.110802</td>
<td>0.028947</td>
<td>0.160011</td>
<td>0.325483</td>
<td>-0.008272</td>
<td>0.135166</td>
<td>-0.005325</td>
<td>0.131658</td>
<td>0.12927</td>
<td>0.217428</td>
<td>0.32369</td>
<td>0.019537</td>
<td>0.198712</td>
<td>0.092924</td>
<td>0.155969</td>
<td>-0.001896</td>
<td>0.056342</td>
<td>-0.007221</td>
<td>0.300103</td>
<td>0.180629</td>
<td>-0.065155</td>
<td>0.275692</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
<section id="performance-categoricals-streaming" class="level2">
<h2 class="anchored" data-anchor-id="performance-categoricals-streaming">9. Performance: Categoricals &amp; Streaming</h2>
<p>Cast string columns to <code>Categorical</code> for memory savings. For datasets that exceed RAM, use <code>LazyFrame</code> + streaming to process in batches.</p>
<div id="e07849ee" class="cell" data-execution_count="9">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-9" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-9-1">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pl.scan_ipc(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"large_dataset.arrow"</span>)</span>
<span id="annotated-cell-9-2">.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">filter</span>(pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vol"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>)</span>
<span id="annotated-cell-9-3">.group_by(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ticker"</span>)</span>
<span id="annotated-cell-9-4">.agg(pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ret"</span>).mean())</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-9" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-9-5" class="code-annotation-target">.with_columns(pl.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ticker"</span>).cast(pl.Categorical))</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-9" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-9-6" class="code-annotation-target">.collect(streaming<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-9" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-9" data-code-lines="5" data-code-annotation="1">Tickers as <code>Categorical</code> — integers under the hood, much less memory.</span>
</dd>
<dt data-target-cell="annotated-cell-9" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-9" data-code-lines="6" data-code-annotation="2">Streaming execution — processes in batches instead of loading everything at once.</span>
</dd>
</dl>
</div>
</div>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Download the companion script <a href="../../assets/python/polars_expressions_and_data_transformations_cheat_sheet.py">here</a>.</p>
</div>
</div>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Data Science</category>
  <guid>https://bwrob.github.io/posts/26-04-05-polars-expressions-cheat-sheet/</guid>
  <pubDate>Sun, 05 Apr 2026 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/assets/images/posts/26-04-05-polars-expressions-cheat-sheet/polars_art.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>Keeping Your Jupyter Notebooks Clean</title>
  <link>https://bwrob.github.io/posts/26-02-20-recipes-jupyter-notebook-quality-checks/</link>
  <description><![CDATA[ 






<p>Jupyter notebooks, can be a real mess for version control systems. They are often full of massive dataframes, messy plots, or printouts. Including outputs in the notebook commited to shared git repo makes the diff and peer reviews quite cumbersome.</p>
<p>There might be some other conventions your team is following (or at least trying to). Nice titles, descriptive expelnations, sectioning etc. Without a cerberus checking those commit after commit it’s hard to muster the discipline ourselves.</p>
<p>Since notebooks are just JSON files under the hood, we can easily prepare a zero-dependency Python script to be our watchdog.</p>
<p>Let’s define a helper class to represent the structure of a notebook cell, and then write some functions to check for common quality issues.</p>
<div id="5320f5d9" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Check Jupyter notebooks for quality criteria."""</span></span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> json</span>
<span id="cb1-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> sys</span>
<span id="cb1-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> pathlib <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Path</span>
<span id="cb1-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> TypedDict, cast</span>
<span id="cb1-7"></span>
<span id="cb1-8"></span>
<span id="cb1-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Cell(TypedDict):</span>
<span id="cb1-10">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""A cell in a Jupyter notebook."""</span></span>
<span id="cb1-11"></span>
<span id="cb1-12">    cell_type: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb1-13">    outputs: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>]</span>
<span id="cb1-14">    execution_count: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span></span>
<span id="cb1-15">    source: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>]</span>
<span id="cb1-16">    metadata: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>]</span></code></pre></div></div>
</details>
</div>
<p>This script will perform a couple of simple checks on each notebook:</p>
<div id="5626bd12" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><a class="code-annotation-anchor" data-target-cell="annotated-cell-2" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-2-1" class="code-annotation-target"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> first_cell_is_markdown(cells: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[Cell]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>:</span>
<span id="annotated-cell-2-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Check if the first cell in the notebook is a markdown cell."""</span></span>
<span id="annotated-cell-2-3">    first <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cells[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="annotated-cell-2-4">    cell_type: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> first.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell_type"</span>)</span>
<span id="annotated-cell-2-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> cell_type <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"markdown"</span></span>
<span id="annotated-cell-2-6"></span>
<span id="annotated-cell-2-7"></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-2" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-2-8" class="code-annotation-target"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> outputs_are_empty(cells: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[Cell]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>:</span>
<span id="annotated-cell-2-9">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Check if all cells in the notebook have empty outputs."""</span></span>
<span id="annotated-cell-2-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> cell <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> cells:</span>
<span id="annotated-cell-2-11">        outputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cell.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"outputs"</span>)</span>
<span id="annotated-cell-2-12">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> outputs:</span>
<span id="annotated-cell-2-13">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span></span>
<span id="annotated-cell-2-14">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span></span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-2" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-2" data-code-lines="1" data-code-annotation="1">Ensures the first cell of the notebook is a Markdown cell. This is useful for making sure every notebook starts with a title or introduction.</span>
</dd>
<dt data-target-cell="annotated-cell-2" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-2" data-code-lines="8" data-code-annotation="2">Iterates through all cells and checks if any have outputs. This helps prevent committing large dataframes, plots, or potentially sensitive information that might be stored in the notebook’s execution results.</span>
</dd>
</dl>
</div>
</div>
<p>Then we need some logic to run these checks on all notebooks in a directory:</p>
<div id="e279a228" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-3" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><a class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-3-1" class="code-annotation-target"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> check_notebook(path: Path) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>:</span>
<span id="annotated-cell-3-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Check if a notebook satisfies the quality criteria."""</span></span>
<span id="annotated-cell-3-3">    json_string <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> path.read_text(encoding<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"utf8"</span>)</span>
<span id="annotated-cell-3-4">    data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> json.loads(json_string)</span>
<span id="annotated-cell-3-5"></span>
<span id="annotated-cell-3-6">    cells <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> data.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cells"</span>)</span>
<span id="annotated-cell-3-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> cells:</span>
<span id="annotated-cell-3-8">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># We shouldn't have empty notebooks in our repo</span></span>
<span id="annotated-cell-3-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span></span>
<span id="annotated-cell-3-10"></span>
<span id="annotated-cell-3-11">    cells <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cast(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"list[Cell]"</span>, cells)</span>
<span id="annotated-cell-3-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span>(</span>
<span id="annotated-cell-3-13">        (</span>
<span id="annotated-cell-3-14">            first_cell_is_markdown(cells),</span>
<span id="annotated-cell-3-15">            outputs_are_empty(cells),</span>
<span id="annotated-cell-3-16">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Potentially more checks could be added here in the future.</span></span>
<span id="annotated-cell-3-17">        )</span>
<span id="annotated-cell-3-18">    )</span>
<span id="annotated-cell-3-19"></span>
<span id="annotated-cell-3-20"></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-3-21" class="code-annotation-target"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> check_directory(path_str: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="annotated-cell-3-22">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Check all notebooks in a directory and its subdirectories."""</span></span>
<span id="annotated-cell-3-23">    all_notebooks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Path(path_str).glob(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"**/*.ipynb"</span>)</span>
<span id="annotated-cell-3-24">    failed <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [path <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> path <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> all_notebooks <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> check_notebook(path)]</span>
<span id="annotated-cell-3-25"></span>
<span id="annotated-cell-3-26">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> failed:</span>
<span id="annotated-cell-3-27">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="annotated-cell-3-28"></span>
<span id="annotated-cell-3-29">    failed_str <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\t</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>.join(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(path) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> path <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> failed)</span>
<span id="annotated-cell-3-30">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Failed check on notebooks:</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\t</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>failed_str<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="annotated-cell-3-31">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="annotated-cell-3-32"></span>
<span id="annotated-cell-3-33"></span>
<span id="annotated-cell-3-34"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"__main__"</span>:</span>
<span id="annotated-cell-3-35">    sys.exit(check_directory(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"."</span>))</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-3" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="21" data-code-annotation="1">Uses <code>Path.glob("**/*.ipynb")</code> to find all Jupyter notebooks in the current directory and all subdirectories. It then runs the <code>check_notebook</code> function on each one. Using the <code>pathlib</code> library makes it easy to handle file paths in a cross-platform way.</span>
</dd>
<dt data-target-cell="annotated-cell-3" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="1" data-code-annotation="2">Iterates through all found notebooks and collects those that fail the checks. If any notebooks fail, it prints their paths and exits with a non-zero status code to indicate failure.</span>
</dd>
</dl>
</div>
</div>
<p>Automating these little chores saves a lot of headache in the long run. It’s a simple base that you can easily tweak or add more rules to as you go.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Download the whole code <a href="../../assets/python/jupyter_notebook_quality_assurance_checks.py">here</a>.</p>
</div>
</div>



<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Python Recipes</category>
  <category>Dev Env</category>
  <guid>https://bwrob.github.io/posts/26-02-20-recipes-jupyter-notebook-quality-checks/</guid>
  <pubDate>Fri, 20 Feb 2026 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/posts/26-02-20-recipes-jupyter-notebook-quality-checks/cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Inheritance, Polymorphism &amp; Protocols</title>
  <link>https://bwrob.github.io/teaching/2025-python-academy/25-12-18-python-academy-oop-basics/</link>
  <description><![CDATA[ 






<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p>We’ve already seen what goes into a single class, but in a real library, objects don’t exist in a vacuum. They need to talk to each other and share common ground. This is where things like <strong>Inheritance</strong> and <strong>Polymorphism</strong> come in.</p>
<p>Think of it this way: a <strong>European Option</strong> <em>is a</em> <strong>Financial Instrument</strong>. A <strong>Nelson-Siegel Model</strong> <em>is a</em> <strong>Yield Curve</strong>. By setting up our code to reflect these relationships, we can write engines that handle any curve we throw at them without needing a massive “if-else” mess.</p>
<p>Today, we’ll build a yield curve hierarchy to see how this works in practice.</p>
</section>
<section id="the-scenario-a-bond-pricer" class="level2">
<h2 class="anchored" data-anchor-id="the-scenario-a-bond-pricer">The Scenario: A Bond Pricer</h2>
<p>Picture this: you’re writing a function to price bonds. You know you need to discount cashflows, so you need a yield curve. But “Yield Curve” is just an abstract idea. In reality, you might be dealing with:</p>
<ul>
<li>A <strong>Flat Curve</strong> (constant interest rate).</li>
<li>A <strong>Zero Curve</strong> (interpolated from market rates).</li>
<li>A <strong>Spline Curve</strong> (some fancy cubic math).</li>
</ul>
<p>Your pricing engine shouldn’t care which one it’s using. It shouldn’t have <code>if type(curve) == FlatCurve</code> logic cluttering it up. It just wants a discount factor.</p>
</section>
<section id="abstract-base-classes-abcs" class="level2">
<h2 class="anchored" data-anchor-id="abstract-base-classes-abcs">Abstract Base Classes (ABCs)</h2>
<p>To keep things sane, we need rules. We need a contract that says: “If you want to be a Yield Curve, you <em>must</em> provide a discount factor.”</p>
<p>Python handles this with <strong>Abstract Base Classes (ABCs)</strong>.</p>
<div id="486a6634" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> abc <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> ABC, abstractmethod</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> math</span>
<span id="cb1-3"></span>
<span id="cb1-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> YieldCurve(ABC):</span>
<span id="cb1-5">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb1-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Abstract base class for all yield curves.</span></span>
<span id="cb1-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb1-8"></span>
<span id="cb1-9">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@abstractmethod</span></span>
<span id="cb1-10">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> discount_factor(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, t: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb1-11">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate discount factor D(t) for time t."""</span></span>
<span id="cb1-12">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">pass</span></span>
<span id="cb1-13"></span>
<span id="cb1-14">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> zero_rate(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, t: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb1-15">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb1-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        Concrete method shared by all curves.</span></span>
<span id="cb1-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        Z(t) = -ln(D(t)) / t</span></span>
<span id="cb1-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb1-19">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-9</span>:</span>
<span id="cb1-20">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span></span>
<span id="cb1-21">        df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.discount_factor(t)</span>
<span id="cb1-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>math.log(df) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> t</span></code></pre></div></div>
</details>
</div>
<p>Inheriting from <code>ABC</code> prevents anyone from creating a “plain” <code>YieldCurve</code>—it’s just a template. The <code>@abstractmethod</code> decorator is the enforcer: if a subclass doesn’t implement <code>discount_factor</code>, Python won’t let you instantiate it.</p>
<p>Notice we included <code>zero_rate</code>. Since the math linking zero rates and discount factors is universal (<img src="https://latex.codecogs.com/png.latex?Z(t)%20=%20-%5Cfrac%7B%5Cln%20D(t)%7D%7Bt%7D">), we write it once here, and every single subclass gets it for free.</p>
</section>
<section id="concrete-implementations" class="level2">
<h2 class="anchored" data-anchor-id="concrete-implementations">Concrete Implementations</h2>
<p>With the ground rules established, let’s build something real. The simplest case is a <strong>Flat Forward Curve</strong>, where the rate is constant forever.</p>
<div id="0992962e" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> FlatForwardCurve(YieldCurve):</span>
<span id="cb2-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, rate: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>):</span>
<span id="cb2-3">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.rate <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rate</span>
<span id="cb2-4"></span>
<span id="cb2-5">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> discount_factor(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, t: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb2-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> math.exp(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.rate <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> t)</span></code></pre></div></div>
</details>
</div>
</section>
<section id="multiple-inheritance-and-layering-behavior" class="level2">
<h2 class="anchored" data-anchor-id="multiple-inheritance-and-layering-behavior">Multiple Inheritance and Layering Behavior</h2>
<p>Before we get to complex curves, let’s talk about one of Python’s superpowers: <strong>Multiple Inheritance</strong>. In many languages, a class can only have one parent. In Python, it can have many.</p>
<p>While this can get messy (the infamous “Diamond Problem”), it’s perfect for <strong>Mixins</strong>. A Mixin is a small class designed to “mix in” specific functionality to other classes.</p>
<p>Suppose we want to take our <code>FlatForwardCurve</code> (or <em>any</em> curve) and add a constant spread to it. Instead of rewriting the curve logic, we create a <code>SpreadMixin</code>.</p>
<div id="1232ccb5" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-3" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> SpreadMixin:</span>
<span id="annotated-cell-3-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, spread: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs):</span>
<span id="annotated-cell-3-3">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.spread <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> spread</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-3-4" class="code-annotation-target">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)</span>
<span id="annotated-cell-3-5"></span>
<span id="annotated-cell-3-6">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> discount_factor(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, t: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-3-7" class="code-annotation-target">        base_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().discount_factor(t)</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="3" onclick="event.preventDefault();">3</a><span id="annotated-cell-3-8" class="code-annotation-target">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> base_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> math.exp(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.spread <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> t)</span>
<span id="annotated-cell-3-9"></span>
<span id="annotated-cell-3-10"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> ShiftedFlatCurve(SpreadMixin, FlatForwardCurve):</span>
<span id="annotated-cell-3-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">pass</span></span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-3" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="4" data-code-annotation="1">Pass remaining arguments to the next class in the chain</span>
</dd>
<dt data-target-cell="annotated-cell-3" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="7" data-code-annotation="2">Get base discount factor from the parent curve</span>
</dd>
<dt data-target-cell="annotated-cell-3" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="8" data-code-annotation="3">Apply spread: D_new(t) = D_old(t) <em>exp(-spread</em> t)</span>
</dd>
</dl>
</div>
</div>
<p>When we create <code>ShiftedFlatCurve</code>, Python’s <strong>Method Resolution Order (MRO)</strong> ensures that <code>SpreadMixin</code> runs first. Its <code>super().discount_factor</code> call then hops over to <code>FlatForwardCurve</code>.</p>
<div id="cfb91eea" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb3-1">shifted <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ShiftedFlatCurve(rate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, spread<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.02</span>)</span>
<span id="cb3-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Total rate effectively 0.07</span></span>
<span id="cb3-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Shifted DF(1.0): </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>shifted<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>discount_factor(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Shifted DF(1.0): 0.9324</code></pre>
</div>
</div>
<p>We just composed a new financial model on the fly without rewriting the flat curve logic.</p>
</section>
<section id="interpolation-a-fork-in-the-road" class="level2">
<h2 class="anchored" data-anchor-id="interpolation-a-fork-in-the-road">Interpolation: A Fork in the Road</h2>
<p>Now, let’s tackle curves built from market data. We have points (tenors and rates), but we need values <em>between</em> those points. We need interpolation.</p>
<p>This presents a classic design choice. Do we bake the interpolation logic into the curve class, or do we keep it separate? Let’s look at both <strong>Composition</strong> and <strong>Inheritance</strong>.</p>
<section id="approach-a-composition-the-strategy-pattern" class="level3">
<h3 class="anchored" data-anchor-id="approach-a-composition-the-strategy-pattern">Approach A: Composition (The Strategy Pattern)</h3>
<p>Here, we treat interpolation as a tool the curve <em>uses</em>. We define an <code>Interpolator</code> protocol and pass a concrete implementation (like <code>LinearInterpolator</code>) to the curve.</p>
<div id="5c634b55" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Protocol</span>
<span id="cb5-2"></span>
<span id="cb5-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Define the Strategy Interface</span></span>
<span id="cb5-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Interpolator(Protocol):</span>
<span id="cb5-5">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> interpolate(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, t: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, x: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>], y: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>: ...</span>
<span id="cb5-6"></span>
<span id="cb5-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Implement Concrete Strategy</span></span>
<span id="cb5-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> LinearInterpolator:</span>
<span id="cb5-9">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> interpolate(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, t: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, x: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>], y: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb5-10">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Simple flat extrapolation for endpoints</span></span>
<span id="cb5-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> x[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]:</span>
<span id="cb5-12">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> y[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb5-13">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> x[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]:</span>
<span id="cb5-14">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> y[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb5-15"></span>
<span id="cb5-16">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Linear search (simplified)</span></span>
<span id="cb5-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(x) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>):</span>
<span id="cb5-18">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> x[i] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> x[i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]:</span>
<span id="cb5-19">                t1, t2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x[i], x[i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb5-20">                y1, y2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y[i], y[i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb5-21">                w <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> t1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (t2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> t1)</span>
<span id="cb5-22">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> w) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> y1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> w <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> y2</span>
<span id="cb5-23">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> y[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb5-24"></span>
<span id="cb5-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 3. Use Composition in the Curve</span></span>
<span id="cb5-26"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> InterpolatedZeroCurve(YieldCurve):</span>
<span id="cb5-27">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(</span>
<span id="cb5-28">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, times: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>], rates: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>], interpolator: Interpolator</span>
<span id="cb5-29">    ):</span>
<span id="cb5-30">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.times <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(times)</span>
<span id="cb5-31">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.rates <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [r <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _, r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(times, rates))]</span>
<span id="cb5-32">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.interpolator <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> interpolator  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Composition</span></span>
<span id="cb5-33"></span>
<span id="cb5-34">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> discount_factor(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, t: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb5-35">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Delegate the math to the strategy</span></span>
<span id="cb5-36">        r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.interpolator.interpolate(t, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.times, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.rates)</span>
<span id="cb5-37">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> math.exp(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> t)</span></code></pre></div></div>
</details>
</div>
<p>This is flexible. Want to switch to Cubic Splines? Just pass a different interpolator. The curve class itself doesn’t need to change.</p>
</section>
<section id="approach-b-inheritance-mixins" class="level3">
<h3 class="anchored" data-anchor-id="approach-b-inheritance-mixins">Approach B: Inheritance (Mixins)</h3>
<p>Alternatively, we can “mix in” the ability to interpolate, just like we mixed in the spread logic.</p>
<div id="110138bf" class="cell" data-execution_count="6">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> LinearInterpolationMixin:</span>
<span id="cb6-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Mixin that provides linear interpolation capability.</span></span>
<span id="cb6-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb6-5">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> interpolate_linear(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, t: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, x: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>], y: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb6-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> x[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]: <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> y[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb6-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> x[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]: <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> y[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb6-8"></span>
<span id="cb6-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(x) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>):</span>
<span id="cb6-10">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> x[i] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> x[i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]:</span>
<span id="cb6-11">                t1, t2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x[i], x[i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb6-12">                y1, y2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y[i], y[i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb6-13">                w <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> t1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (t2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> t1)</span>
<span id="cb6-14">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> w) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> y1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> w <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> y2</span>
<span id="cb6-15">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> y[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb6-16"></span>
<span id="cb6-17"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> MixinZeroCurve(LinearInterpolationMixin, YieldCurve):</span>
<span id="cb6-18">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, times: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>], rates: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>]):</span>
<span id="cb6-19">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.times <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(times)</span>
<span id="cb6-20">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.rates <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [r <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _, r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(times, rates))]</span>
<span id="cb6-21"></span>
<span id="cb6-22">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> discount_factor(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, t: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb6-23">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Use the inherited method</span></span>
<span id="cb6-24">        r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.interpolate_linear(t, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.times, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.rates)</span>
<span id="cb6-25">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> math.exp(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> t)</span></code></pre></div></div>
</details>
</div>
<p>This feels more integrated, but it’s static. You can’t change the interpolation method at runtime as easily as with composition.</p>
</section>
</section>
<section id="the-payoff-polymorphism" class="level2">
<h2 class="anchored" data-anchor-id="the-payoff-polymorphism">The Payoff: Polymorphism</h2>
<p>Because we stuck to the <code>YieldCurve</code> contract, the pricing function doesn’t need to know about any of the complexity above.</p>
<div id="b13aa159" class="cell" data-execution_count="7">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> dataclasses <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dataclass</span>
<span id="cb7-2"></span>
<span id="cb7-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@dataclass</span></span>
<span id="cb7-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> CashFlow:</span>
<span id="cb7-5">    amount: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span></span>
<span id="cb7-6">    time: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span></span>
<span id="cb7-7"></span>
<span id="cb7-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> price_bond(cashflows: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[CashFlow], curve: YieldCurve) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb7-9">    price <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span></span>
<span id="cb7-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> cf <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> cashflows:</span>
<span id="cb7-11">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Polymorphic call: Python decides at runtime which</span></span>
<span id="cb7-12">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># discount_factor method to run!</span></span>
<span id="cb7-13">        price <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> cf.amount <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> curve.discount_factor(cf.time)</span>
<span id="cb7-14">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> price</span></code></pre></div></div>
</details>
</div>
<p>Let’s test it:</p>
<div id="dc2194fc" class="cell" data-execution_count="8">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define a bond: coupon of 5 at t=1, principal 105 at t=2</span></span>
<span id="cb8-2">bond_cfs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [CashFlow(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>), CashFlow(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">105</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.0</span>)]</span>
<span id="cb8-3"></span>
<span id="cb8-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Price with Flat Curve</span></span>
<span id="cb8-5">flat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FlatForwardCurve(rate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb8-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Price (Flat): </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>price_bond(bond_cfs, flat)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb8-7"></span>
<span id="cb8-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Price with Composition (Strategy)</span></span>
<span id="cb8-9">linear_strategy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> LinearInterpolator()</span>
<span id="cb8-10">curve_comp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> InterpolatedZeroCurve([<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.0</span>], [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.04</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.06</span>], linear_strategy)</span>
<span id="cb8-11"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Price (Composition): </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>price_bond(bond_cfs, curve_comp)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb8-12"></span>
<span id="cb8-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 3. Price with Mixin</span></span>
<span id="cb8-14">curve_mixin <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> MixinZeroCurve([<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.0</span>], [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.04</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.06</span>])</span>
<span id="cb8-15"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Price (Mixin): </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>price_bond(bond_cfs, curve_mixin)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Price (Flat): 99.76
Price (Composition): 97.90
Price (Mixin): 97.90</code></pre>
</div>
</div>
<p>We swapped the entire mathematical engine underneath the hood—from flat rates to interpolated curves using different design patterns—and the pricing logic didn’t flinch.</p>
</section>
<section id="protocols-when-inheritance-feels-heavy" class="level2">
<h2 class="anchored" data-anchor-id="protocols-when-inheritance-feels-heavy">Protocols: When Inheritance Feels Heavy</h2>
<p>Inheritance is a commitment. Sometimes you want to use a class from a third-party library that <em>looks</em> like a yield curve but doesn’t inherit from your specific <code>YieldCurve</code> ABC.</p>
<p><strong>Protocols</strong> (structural subtyping) solve this. A Protocol defines a shape: “I don’t care who your parents are, as long as you have a <code>discount_factor</code> method.”</p>
<div id="5a2600b4" class="cell" data-execution_count="9">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> runtime_checkable</span>
<span id="cb10-2"></span>
<span id="cb10-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@runtime_checkable</span></span>
<span id="cb10-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Discountable(Protocol):</span>
<span id="cb10-5">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> discount_factor(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, t: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>: ...</span>
<span id="cb10-6"></span>
<span id="cb10-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> SimpleDiscounter:</span>
<span id="cb10-8">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb10-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    This class does NOT inherit from YieldCurve.</span></span>
<span id="cb10-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    It just happens to have the right method.</span></span>
<span id="cb10-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb10-12">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> discount_factor(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, t: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb10-13">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> t)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Simple capitalization</span></span>
<span id="cb10-14"></span>
<span id="cb10-15"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> price_asset_structural(amount: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, t: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, model: Discountable) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb10-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> amount <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> model.discount_factor(t)</span>
<span id="cb10-17"></span>
<span id="cb10-18">simple <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> SimpleDiscounter()</span>
<span id="cb10-19"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Is compatible? </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(simple, Discountable)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb10-20"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Price: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>price_asset_structural(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>, simple)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Is compatible? True
Price: 95.24</code></pre>
</div>
</div>
<p>This lets you build loosely coupled systems that play nice with code you don’t own.</p>
</section>
<section id="wrapping-up" class="level2">
<h2 class="anchored" data-anchor-id="wrapping-up">Wrapping Up</h2>
<p>OOP gives us some powerful ways to keep our code organized and flexible.</p>
<ul>
<li><strong>ABCs</strong> set the rules for what an object must do.</li>
<li><strong>Mixins</strong> let us stack features on top of each other like Lego blocks.</li>
<li><strong>Polymorphism</strong> lets our models swap in and out seamlessly.</li>
<li><strong>Protocols</strong> let us stay flexible without forcing a rigid hierarchy.</li>
</ul>
<p>These patterns are what turn a collection of scripts into a proper library.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>You can find the complete code for this post here: <a href="../../../assets/python/inheritance_polymorphism_and_protocols_in_python_oop.py">inheritance_polymorphism_and_protocols_in_python_oop.py</a>.</p>
</div>
</div>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Python Academy</category>
  <guid>https://bwrob.github.io/teaching/2025-python-academy/25-12-18-python-academy-oop-basics/</guid>
  <pubDate>Thu, 18 Dec 2025 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/teaching/2025-python-academy/25-12-18-python-academy-oop-basics/cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>The Python Data Model</title>
  <link>https://bwrob.github.io/teaching/2025-python-academy/25-12-12-python-academy-data-model/</link>
  <description><![CDATA[ 






<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p>Python’s built-in types just… work. <code>len()</code> for sizes, <code>[]</code> for lookups, <code>for</code> loops for iteration. It all feels consistent because it is.</p>
<p>That consistency comes from the <strong>Python Data Model</strong>. By implementing a few “special methods” (you might know them as <em>dunder</em> methods, short for <strong>d</strong>ouble <strong>under</strong>score), you can make your own custom classes behave exactly like the built-ins.</p>
<p>In this post, we’re going to build a <code>Portfolio</code> class that feels like a native part of the language. Instead of clunky custom methods, we’ll use the patterns Python already knows and loves.</p>
</section>
<section id="the-goal-a-pythonic-portfolio" class="level2">
<h2 class="anchored" data-anchor-id="the-goal-a-pythonic-portfolio">The Goal: A Pythonic Portfolio</h2>
<p>We want a <code>Portfolio</code> class that stores a list of financial positions. But we don’t want a clunky interface like <code>portfolio.get_position_by_ticker("AAPL")</code>. We want the market-standard syntax:</p>
<ul>
<li><code>len(portfolio)</code> to size up our exposure.</li>
<li><code>portfolio["AAPL"]</code> to get a quote instantly.</li>
<li><code>for position in portfolio</code> to audit our holdings.</li>
</ul>
<p>Let’s start by defining a simple <code>Position</code> container. To keep our balance sheet clean, we’ll track the total USD value rather than quantity and price.</p>
<div id="58d58fff" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> __future__ <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> annotations</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> dataclasses <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dataclass</span>
<span id="cb1-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> collections.abc <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Iterator</span>
<span id="cb1-5"></span>
<span id="cb1-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@dataclass</span></span>
<span id="cb1-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Position:</span>
<span id="cb1-8">    symbol: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb1-9">    value_usd: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span></span></code></pre></div></div>
</details>
</div>
</section>
<section id="the-initial-portfolio-class" class="level2">
<h2 class="anchored" data-anchor-id="the-initial-portfolio-class">The Initial <code>Portfolio</code> Class</h2>
<p>We start with a standard class definition. To index our strategy efficiently, we’ll store the positions in a dictionary keyed by their symbol. We name it <code>_contents</code> to signal it’s an internal implementation detail—a trade secret, if you will—encouraging users to access data through the public interface.</p>
<div id="fbe6628e" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Portfolio:</span>
<span id="cb2-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, name: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, managers: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, ...], contents: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[Position] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>):</span>
<span id="cb2-3">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.name <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> name</span>
<span id="cb2-4">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.managers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> managers</span>
<span id="cb2-5">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Store positions in a dictionary keyed by symbol for fast lookup</span></span>
<span id="cb2-6">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._contents <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {pos.symbol: pos <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> pos <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> contents} <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> contents <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> {}</span>
<span id="cb2-7"></span>
<span id="cb2-8">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__repr__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb2-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Portfolio(name=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!r}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, managers=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>managers<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!r}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, contents=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._contents.values())<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!r}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">)"</span></span>
<span id="cb2-10"></span>
<span id="cb2-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create some data</span></span>
<span id="cb2-12">pos1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Position(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AAPL"</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">15000.0</span>)</span>
<span id="cb2-13">pos2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Position(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GOOG"</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">140000.0</span>)</span>
<span id="cb2-14">p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Portfolio(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tech Fund"</span>, (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Alice"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bob"</span>), [pos1, pos2])</span>
<span id="cb2-15"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(p)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Portfolio(name='Tech Fund', managers=('Alice', 'Bob'), contents=[Position(symbol='AAPL', value_usd=15000.0), Position(symbol='GOOG', value_usd=140000.0)])</code></pre>
</div>
</div>
<p>We included <code>__repr__</code> right away. This dunder method provides the “official” string representation, useful for debugging the object’s state.</p>
</section>
<section id="emulating-a-collection" class="level2">
<h2 class="anchored" data-anchor-id="emulating-a-collection">Emulating a Collection</h2>
<p>Right now, if we try to gauge the size of our portfolio, it raises a <code>TypeError</code>.</p>
<div id="310cc0b4" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb4-2">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(p)</span>
<span id="cb4-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">TypeError</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> e:</span>
<span id="cb4-4">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Error: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>e<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Error: object of type 'Portfolio' has no len()</code></pre>
</div>
</div>
<p>To enable the <code>len()</code> function, we implement <code>__len__</code>.</p>
<section id="len__" class="level3">
<h3 class="anchored" data-anchor-id="len__"><code>__len__</code></h3>
<div id="964c8423" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Portfolio(Portfolio): <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Inheriting to add methods incrementally for this post</span></span>
<span id="cb6-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__len__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb6-3">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._contents)</span>
<span id="cb6-4"></span>
<span id="cb6-5">p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Portfolio(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tech Fund"</span>, (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Alice"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bob"</span>), [pos1, pos2])</span>
<span id="cb6-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Portfolio size: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(p)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Portfolio size: 2</code></pre>
</div>
</div>
<p>Now <code>len(p)</code> delegates to the underlying <code>self._contents</code> dictionary.</p>
</section>
<section id="getitem__" class="level3">
<h3 class="anchored" data-anchor-id="getitem__"><code>__getitem__</code></h3>
<p>We don’t want to scan through a list to find a stock — that’s O(N). The <code>__getitem__</code> method allows us to use the square bracket notation <code>[]</code> to access items directly.</p>
<div id="2c66ae1a" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Portfolio(Portfolio):</span>
<span id="cb8-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__getitem__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, symbol: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Position <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb8-3">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._contents.get(symbol)</span>
<span id="cb8-4"></span>
<span id="cb8-5">p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Portfolio(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tech Fund"</span>, (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Alice"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bob"</span>), [pos1, pos2])</span>
<span id="cb8-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"AAPL position: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>p[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'AAPL'</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb8-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"MSFT position: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>p[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MSFT'</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Returns None</span></span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>AAPL position: Position(symbol='AAPL', value_usd=15000.0)
MSFT position: None</code></pre>
</div>
</div>
<p>With this, our <code>Portfolio</code> behaves like a mapping—an efficient way to access our assets.</p>
</section>
<section id="enabling-iteration-__iter__" class="level3">
<h3 class="anchored" data-anchor-id="enabling-iteration-__iter__">Enabling Iteration: <code>__iter__</code></h3>
<p>Iterating through a collection is fundamental. Since we backed our portfolio with a dictionary, default iteration would just give us the keys (symbols). But when we loop through a portfolio, we usually want the assets themselves. We can dictate this behavior by implementing <code>__iter__</code>.</p>
<div id="d81e813f" class="cell" data-execution_count="6">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Portfolio(Portfolio):</span>
<span id="cb10-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__iter__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Iterator[Position]:</span>
<span id="cb10-3">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._contents.values())</span>
<span id="cb10-4"></span>
<span id="cb10-5">p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Portfolio(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tech Fund"</span>, (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Alice"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bob"</span>), [pos1, pos2])</span>
<span id="cb10-6"></span>
<span id="cb10-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Iterating through portfolio:"</span>)</span>
<span id="cb10-8"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> pos <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> p:</span>
<span id="cb10-9">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f" - </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>pos<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>symbol<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: $</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>pos<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>value_usd<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:,.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Iterating through portfolio:
 - AAPL: $15,000.00
 - GOOG: $140,000.00</code></pre>
</div>
</div>
<p>Now, <code>for pos in p</code> yields the positions directly. We have full control over the traversal.</p>
</section>
</section>
<section id="membership-and-truthiness-__contains__-and-__bool__" class="level2">
<h2 class="anchored" data-anchor-id="membership-and-truthiness-__contains__-and-__bool__">Membership and Truthiness: <code>__contains__</code> and <code>__bool__</code></h2>
<p>We can already check membership via <code>__iter__</code>, but that’s O(N). Since we have a dictionary underneath, <code>__contains__</code> gives us O(1) lookup.</p>
<p>We also want to know if our portfolio is empty. By default, Python checks <code>len()</code>, but implementing <code>__bool__</code> allows us to be explicit about what constitutes a “truthy” portfolio.</p>
<div id="22c90dcb" class="cell" data-execution_count="7">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Portfolio(Portfolio):</span>
<span id="cb12-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__contains__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, item: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> Position) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>:</span>
<span id="cb12-3">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(item, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb12-4">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> item <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._contents</span>
<span id="cb12-5">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(item, Position):</span>
<span id="cb12-6">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> item.symbol <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._contents</span>
<span id="cb12-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span></span>
<span id="cb12-8"></span>
<span id="cb12-9">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__bool__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>:</span>
<span id="cb12-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._contents)</span>
<span id="cb12-11"></span>
<span id="cb12-12">p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Portfolio(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tech Fund"</span>, (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Alice"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bob"</span>), [pos1, pos2])</span>
<span id="cb12-13"></span>
<span id="cb12-14"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Is 'AAPL' in p? </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'AAPL'</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> p<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb12-15"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Is 'MSFT' in p? </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MSFT'</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> p<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb12-16"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Is p truthy? </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>(p)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb12-17"></span>
<span id="cb12-18">empty_p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Portfolio(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Empty"</span>, (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Nobody"</span>,))</span>
<span id="cb12-19"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Is empty_p truthy? </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>(empty_p)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Is 'AAPL' in p? True
Is 'MSFT' in p? False
Is p truthy? True
Is empty_p truthy? False</code></pre>
</div>
</div>
</section>
<section id="operator-overloading-__add__-combining-portfolios" class="level2">
<h2 class="anchored" data-anchor-id="operator-overloading-__add__-combining-portfolios">Operator Overloading: <code>__add__</code> (Combining Portfolios)</h2>
<p>In Python, objects can be combined using operators. If we have two portfolios, it makes intuitive sense to “add” them together using <code>+</code>.</p>
<p>We implement this via <code>__add__</code>. This isn’t just concatenation; it’s a consolidation. We need to combine managers and sum up the value of overlapping positions.</p>
<div id="ce7475fd" class="cell" data-execution_count="8">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb14-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Portfolio(Portfolio):</span>
<span id="cb14-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__add__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, other: Portfolio) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Portfolio:</span>
<span id="cb14-3">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(other, Portfolio):</span>
<span id="cb14-4">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">NotImplemented</span></span>
<span id="cb14-5"></span>
<span id="cb14-6">        new_name <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> + </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>other<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb14-7">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Combine managers, removing duplicates</span></span>
<span id="cb14-8">        new_managers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.managers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> other.managers)))</span>
<span id="cb14-9">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Merge contents</span></span>
<span id="cb14-10">        all_positions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb14-11"></span>
<span id="cb14-12">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Add positions from self</span></span>
<span id="cb14-13">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> pos <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>:</span>
<span id="cb14-14">            all_positions[pos.symbol] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Position(pos.symbol, pos.value_usd)</span>
<span id="cb14-15"></span>
<span id="cb14-16">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Add positions from other</span></span>
<span id="cb14-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> pos <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> other:</span>
<span id="cb14-18">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> pos.symbol <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> all_positions:</span>
<span id="cb14-19">                existing <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> all_positions[pos.symbol]</span>
<span id="cb14-20">                existing.value_usd <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> pos.value_usd</span>
<span id="cb14-21">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb14-22">                all_positions[pos.symbol] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Position(pos.symbol, pos.value_usd)</span>
<span id="cb14-23">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Portfolio(new_name, new_managers, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(all_positions.values()))</span>
<span id="cb14-24"></span>
<span id="cb14-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Example Usage</span></span>
<span id="cb14-26">p1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Portfolio(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tech"</span>, (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Alice"</span>,), [Position(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AAPL"</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">15000.0</span>)])</span>
<span id="cb14-27">p2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Portfolio(</span>
<span id="cb14-28">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Growth"</span>, (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bob"</span>,), [Position(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AAPL"</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">8000.0</span>), Position(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MSFT"</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">30000.0</span>)]</span>
<span id="cb14-29">)</span>
<span id="cb14-30"></span>
<span id="cb14-31">p3 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> p1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> p2</span>
<span id="cb14-32"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Merged Portfolio: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>p3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb14-33"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Merged AAPL: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>p3[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'AAPL'</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Merged Portfolio: Portfolio(name='Tech + Growth', managers=('Alice', 'Bob'), contents=[Position(symbol='AAPL', value_usd=23000.0), Position(symbol='MSFT', value_usd=30000.0)])
Merged AAPL: Position(symbol='AAPL', value_usd=23000.0)</code></pre>
</div>
</div>
</section>
<section id="string-representation-__repr__-vs-__str__" class="level2">
<h2 class="anchored" data-anchor-id="string-representation-__repr__-vs-__str__">String Representation: <code>__repr__</code> vs <code>__str__</code></h2>
<p>Finally, we need to decide how our portfolio presents itself to the world.</p>
<ul>
<li><strong><code>__repr__</code> (The Private Ledger):</strong> Unambiguous, developer-focused. It should ideally allow you to recreate the object.</li>
<li><strong><code>__str__</code> (The Public Face):</strong> Readable, user-focused. “What does this object represent to a human?”</li>
</ul>
<p>If <code>__str__</code> is not defined, Python falls back to <code>__repr__</code>. But we want a nice summary.</p>
<div id="6cb11471" class="cell" data-execution_count="9">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Portfolio(Portfolio):</span>
<span id="cb16-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__str__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb16-3">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Portfolio '</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">' with </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> positions managed by </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', '</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>join(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.managers)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb16-4"></span>
<span id="cb16-5">p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Portfolio(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tech Fund"</span>, (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Alice"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bob"</span>), [pos1, pos2])</span>
<span id="cb16-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Str: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(p)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb16-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Repr: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">repr</span>(p)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Str: Portfolio 'Tech Fund' with 2 positions managed by Alice, Bob
Repr: Portfolio(name='Tech Fund', managers=('Alice', 'Bob'), contents=[Position(symbol='AAPL', value_usd=15000.0), Position(symbol='GOOG', value_usd=140000.0)])</code></pre>
</div>
</div>
</section>
<section id="why-this-matters" class="level2">
<h2 class="anchored" data-anchor-id="why-this-matters">Why This Matters</h2>
<p>By implementing these methods, we’ve turned a basic container into a robust and functional class.</p>
<ul>
<li><strong>Lookup by Symbol:</strong> Instant access with <code>p['AAPL']</code>.</li>
<li><strong>Intuitive Iteration:</strong> Seamless traversal with <code>for pos in p</code>.</li>
<li><strong>Arithmetic:</strong> Combining objects made easy with <code>p1 + p2</code>.</li>
<li><strong>Expressiveness:</strong> The code reads clearly and naturally.</li>
</ul>
</section>
<section id="summary" class="level2">
<h2 class="anchored" data-anchor-id="summary">Summary</h2>
<p>The Python Data Model is what makes Python feel like Python. It lets your custom objects play nice with all the built-in features you’re already using. Here’s the “greatest hits” of dunder methods we covered:</p>
<ul>
<li><code>__init__</code>: For setting things up.</li>
<li><code>__repr__</code>: The “developer view” (detailed and exact).</li>
<li><code>__str__</code>: The “human view” (clean and readable).</li>
<li><code>__len__</code>: So <code>len(your_obj)</code> actually works.</li>
<li><code>__getitem__</code>: For that sweet square-bracket <code>[]</code> access.</li>
<li><code>__iter__</code>: To make your object loopable.</li>
<li><code>__contains__</code>: For fast <code>x in your_obj</code> checks.</li>
<li><code>__bool__</code>: To define what “empty” means for your object.</li>
<li><code>__add__</code>: So you can literally <code>+</code> your objects together.</li>
</ul>
<p>These patterns are what make Python code feel like Python. In the <a href="../25-12-18-python-academy-oop-basics/">next post</a>, we’ll use inheritance and protocols to build a yield curve hierarchy.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Download the whole code <a href="../../../assets/python/python_data_model_portfolio_implementation_example.py">here</a>.</p>
</div>
</div>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Python Academy</category>
  <guid>https://bwrob.github.io/teaching/2025-python-academy/25-12-12-python-academy-data-model/</guid>
  <pubDate>Fri, 12 Dec 2025 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/teaching/2025-python-academy/25-12-12-python-academy-data-model/cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Anatomy of a Python Class</title>
  <link>https://bwrob.github.io/teaching/2025-python-academy/25-12-04-python-academy-class-anatomy/</link>
  <description><![CDATA[ 






<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p>In the quant world, we’re always dealing with things that have both data and behavior. Think about an option: it has properties like a strike price and an expiry date, but it also <em>does</em> stuff, like calculating its own payoff or theoretical price. Object-Oriented Programming (OOP) is just a fancy way of saying we’re going to bundle all that related info and logic into one tidy package called a class.</p>
<p>We’re going to break down exactly what goes into a Python class, starting from a totally empty shell and building it up into a robust financial model. By the end, you’ll see how to turn a messy collection of variables into a clean, reliable tool.</p>
</section>
<section id="starting-simple-the-empty-class" class="level2">
<h2 class="anchored" data-anchor-id="starting-simple-the-empty-class">Starting Simple: The Empty Class</h2>
<p>Python’s dynamic nature allows for flexibility that can be surprising if you are coming from statically typed languages like C++ or Java. The most minimal class definition in Python is simply an empty block.</p>
<div id="83f74317" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Option:</span>
<span id="cb1-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">pass</span></span></code></pre></div></div>
</details>
</div>
<p>This <code>Option</code> class might seem useless, but Python allows us to attach attributes to instances dynamically—a practice sometimes called “monkey patching” in broader contexts.</p>
<div id="3dee8109" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create an instance</span></span>
<span id="cb2-2">my_option <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Option()</span>
<span id="cb2-3"></span>
<span id="cb2-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Attach attributes dynamically</span></span>
<span id="cb2-5">my_option.strike <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span></span>
<span id="cb2-6">my_option.expiry <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2025-12-20"</span></span>
<span id="cb2-7">my_option.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Call"</span></span>
<span id="cb2-8"></span>
<span id="cb2-9"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Option strike: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>my_option<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>strike<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Option strike: 100</code></pre>
</div>
</div>
<p>While flexible, this approach is risky for production systems, especially in finance where data integrity is critical. It offers no guarantee of structure—one <code>Option</code> might have a <code>strike</code>, while another has a <code>strike_price</code>. It also makes debugging difficult, as typos like <code>my_option.stike = 100</code> pass silently until the code crashes later. IDEs and static analysis tools struggle to help you since they don’t know what attributes to expect.</p>
</section>
<section id="enforcing-structure-__init__" class="level2">
<h2 class="anchored" data-anchor-id="enforcing-structure-__init__">Enforcing Structure: <code>__init__</code></h2>
<p>To fix this, we use the <code>__init__</code> method. Think of it as your “initializer” (sometimes called a constructor). It runs the second an object is created, making sure every instance starts off with the right data in the right place.</p>
<p>Here’s how we can define a <code>EuropeanOption</code> class with a proper setup.</p>
<div id="86fc4d11" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> EuropeanOption:</span>
<span id="cb4-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, strike: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, expiry: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, option_type: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb4-3">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.strike <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> strike</span>
<span id="cb4-4">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.expiry <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> expiry</span>
<span id="cb4-5">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.option_type <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> option_type</span>
<span id="cb4-6"></span>
<span id="cb4-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Now, we HAVE to provide these arguments to create an instance</span></span>
<span id="cb4-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># euro_option = EuropeanOption() # This would blow up with a TypeError</span></span>
<span id="cb4-9">euro_option <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> EuropeanOption(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">100.0</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2025-12-20"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Call"</span>)</span></code></pre></div></div>
</details>
</div>
<section id="self-the-secret-sauce" class="level3">
<h3 class="anchored" data-anchor-id="self-the-secret-sauce"><code>self</code>: The Secret Sauce</h3>
<p>If you’ve looked at Python code before, you’ve seen <code>self</code> everywhere. It’s a bit weird at first, but it’s actually pretty straightforward: <code>self</code> is just a reference to the specific object you’re currently working with.</p>
<ul>
<li><strong>What it is:</strong> <code>self</code> represents the “me” of the object. It’s how the object talks to its own data and methods.</li>
<li><strong>The Magic:</strong> When you call a method like <code>my_option.payoff()</code>, Python secretly passes <code>my_option</code> as the first argument. So, <code>my_option.payoff()</code> is really just <code>EuropeanOption.payoff(my_option)</code> under the hood.</li>
<li><strong>Scope:</strong> When you attach a variable to <code>self</code> (like <code>self.strike</code>), it becomes an “instance attribute.” That means it belongs to that specific object and sticks around as long as the object exists. If you just define a variable in a method <em>without</em> <code>self</code>, it’s just a temporary local variable that disappears once the method is done.</li>
</ul>
<p>By adding type hints (<code>: float</code>, <code>: str</code>), we also document exactly what kind of data we expect, serving as a guide for other developers and our future selves.</p>
</section>
</section>
<section id="class-attributes-vs.-instance-attributes" class="level2">
<h2 class="anchored" data-anchor-id="class-attributes-vs.-instance-attributes">Class Attributes vs.&nbsp;Instance Attributes</h2>
<p>The attributes <code>strike</code>, <code>expiry</code>, and <code>option_type</code> are <strong>instance attributes</strong>. They belong to a specific object; one option’s strike does not affect another’s.</p>
<p>Sometimes, however, we need to share data across <em>all</em> instances of a class. These are <strong>class attributes</strong>, defined directly in the class body.</p>
<div id="c0a2095a" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> EuropeanOption:</span>
<span id="cb5-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Class attribute</span></span>
<span id="cb5-3">    CONTRACT_SIZE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Standard lot size</span></span>
<span id="cb5-4">    _DEFAULT_OPTION_TYPE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Call"</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Default for new options</span></span>
<span id="cb5-5"></span>
<span id="cb5-6">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, strike: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, expiry: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, option_type: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb5-7">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.strike <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> strike  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Instance attribute</span></span>
<span id="cb5-8">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.expiry <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> expiry</span>
<span id="cb5-9">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.option_type <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> option_type</span>
<span id="cb5-10"></span>
<span id="cb5-11">op1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> EuropeanOption(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2025-12-20"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Call"</span>)</span>
<span id="cb5-12">op2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> EuropeanOption(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">110</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2025-12-20"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Put"</span>)</span>
<span id="cb5-13"></span>
<span id="cb5-14"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Option 1 contract size: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>op1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>CONTRACT_SIZE<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb5-15"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Option 2 contract size: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>op2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>CONTRACT_SIZE<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Option 1 contract size: 100
Option 2 contract size: 100</code></pre>
</div>
</div>
<p>Changing <code>EuropeanOption.CONTRACT_SIZE</code> updates the value for all instances that haven’t explicitly overridden it.</p>
</section>
<section id="the-three-method-types-an-overview" class="level2">
<h2 class="anchored" data-anchor-id="the-three-method-types-an-overview">The Three Method Types: An Overview</h2>
<p>With <code>self</code> and class attributes covered, here are the three types of methods a class can have.</p>
<table class="caption-top table">
<colgroup>
<col style="width: 5%">
<col style="width: 10%">
<col style="width: 9%">
<col style="width: 75%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">Type</th>
<th style="text-align: left;">Decorator</th>
<th style="text-align: left;">First Argument</th>
<th style="text-align: left;">Purpose</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Instance</td>
<td style="text-align: left;">None</td>
<td style="text-align: left;"><code>self</code></td>
<td style="text-align: left;">Operates on and modifies the object.</td>
</tr>
<tr class="even">
<td style="text-align: left;">Class</td>
<td style="text-align: left;"><code>@classmethod</code></td>
<td style="text-align: left;"><code>cls</code></td>
<td style="text-align: left;">Operates on and modifies the class itself; often used for factory methods.</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Static</td>
<td style="text-align: left;"><code>@staticmethod</code></td>
<td style="text-align: left;">None</td>
<td style="text-align: left;">Isolated utility functions that logically belong to the class but don’t need access to instance or class state.</td>
</tr>
</tbody>
</table>
<hr>
<section id="instance-methods" class="level3">
<h3 class="anchored" data-anchor-id="instance-methods">Instance Methods</h3>
<p><strong>Instance methods</strong> are the default — functions defined inside a class that operate on a specific instance via <code>self</code>.</p>
<div id="bc9065b5" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> EuropeanOption:</span>
<span id="cb7-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, strike: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, option_type: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb7-3">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.strike <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> strike</span>
<span id="cb7-4">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.option_type <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> option_type</span>
<span id="cb7-5"></span>
<span id="cb7-6">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> payoff(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, spot_price: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb7-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.option_type <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Call"</span>:</span>
<span id="cb7-8">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(spot_price <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.strike, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>)</span>
<span id="cb7-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.option_type <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Put"</span>:</span>
<span id="cb7-10">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.strike <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> spot_price, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>)</span>
<span id="cb7-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb7-12">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Unknown option type"</span>)</span>
<span id="cb7-13"></span>
<span id="cb7-14">call <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> EuropeanOption(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Call"</span>)</span>
<span id="cb7-15"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Spot 110, Call Payoff: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>call<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>payoff(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">110</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb7-16"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Spot 90, Call Payoff: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>call<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>payoff(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">90</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Spot 110, Call Payoff: 10
Spot 90, Call Payoff: 0.0</code></pre>
</div>
</div>
</section>
</section>
<section id="class-methods" class="level2">
<h2 class="anchored" data-anchor-id="class-methods">Class Methods</h2>
<p>Sometimes we need a method that operates on the class itself rather than a specific instance. These are <strong>class methods</strong>, receiving the class (<code>cls</code>) as their first argument instead of <code>self</code>. They are marked with the <code>@classmethod</code> decorator.</p>
<p>A common use case for class methods is creating <strong>factory methods</strong>—alternative ways to instantiate the class.</p>
<div id="478e6f03" class="cell" data-execution_count="6">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> EuropeanOption:</span>
<span id="cb9-2">    _DEFAULT_OPTION_TYPE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Call"</span></span>
<span id="cb9-3"></span>
<span id="cb9-4">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, strike: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, option_type: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb9-5">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.strike <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> strike</span>
<span id="cb9-6">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.option_type <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> option_type</span>
<span id="cb9-7"></span>
<span id="cb9-8">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__repr__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb9-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"EuropeanOption(strike=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>strike<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, type='</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>option_type<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">')"</span></span>
<span id="cb9-10"></span>
<span id="cb9-11">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@classmethod</span></span>
<span id="cb9-12">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> from_string(cls, description: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb9-13">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Parses strings like "Call-100" or "Put-150"</span></span>
<span id="cb9-14">        parts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> description.split(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-'</span>)</span>
<span id="cb9-15">        option_type <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> parts[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb9-16">        strike <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>(parts[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb9-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> cls(strike, option_type)</span>
<span id="cb9-18"></span>
<span id="cb9-19">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@classmethod</span></span>
<span id="cb9-20">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> set_default_option_type(cls, new_type: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb9-21">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Sets a new default option type for the class."""</span></span>
<span id="cb9-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> new_type <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Call"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Put"</span>]:</span>
<span id="cb9-23">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Option type must be 'Call' or 'Put'."</span>)</span>
<span id="cb9-24">        cls._DEFAULT_OPTION_TYPE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> new_type</span>
<span id="cb9-25"></span>
<span id="cb9-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create an instance using the factory</span></span>
<span id="cb9-27">option_from_str <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> EuropeanOption.from_string(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Put-120"</span>)</span>
<span id="cb9-28"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Created from string: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>option_from_str<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb9-29"></span>
<span id="cb9-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Demonstrate non-builder class method</span></span>
<span id="cb9-31"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Default option type before change: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>EuropeanOption<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>_DEFAULT_OPTION_TYPE<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb9-32">EuropeanOption.set_default_option_type(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Put"</span>)</span>
<span id="cb9-33"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Default option type after change: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>EuropeanOption<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>_DEFAULT_OPTION_TYPE<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Created from string: EuropeanOption(strike=120.0, type='Put')
Default option type before change: Call
Default option type after change: Put</code></pre>
</div>
</div>
</section>
<section id="static-methods" class="level2">
<h2 class="anchored" data-anchor-id="static-methods">Static Methods</h2>
<p>A <strong>static method</strong> behaves like a regular function but lives within the class’s namespace. It doesn’t receive <code>self</code> or <code>cls</code> automatically. We use the <code>@staticmethod</code> decorator for utility functions that are logically related to the class but don’t need access to the class or instance state.</p>
<p>For an option class, a static method might implement a pricing formula component that is purely mathematical.</p>
<div id="f45eb84e" class="cell" data-execution_count="7">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb11-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> math</span>
<span id="cb11-2"></span>
<span id="cb11-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> EuropeanOption:</span>
<span id="cb11-4">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ... (previous methods) ...</span></span>
<span id="cb11-5"></span>
<span id="cb11-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@staticmethod</span></span>
<span id="cb11-7">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> d1(S, K, T, r, sigma):</span>
<span id="cb11-8">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculates d1 term for Black-Scholes."""</span></span>
<span id="cb11-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (math.log(S <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> K) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> sigma <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> T) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (sigma <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> math.sqrt(T))</span>
<span id="cb11-10"></span>
<span id="cb11-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># We can call it without an instance</span></span>
<span id="cb11-12">d1_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> EuropeanOption.d1(S<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, K<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, T<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, sigma<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>)</span>
<span id="cb11-13"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"d1 value: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>d1_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>d1 value: 0.3500</code></pre>
</div>
</div>
</section>
<section id="the-property-decorator-property" class="level2">
<h2 class="anchored" data-anchor-id="the-property-decorator-property">The Property Decorator: <code>@property</code></h2>
<p>In finance, invalid data can lead to significant errors. A negative strike price or a negative volatility is nonsensical. In languages like Java or C++, you typically implement <code>getStrike()</code> and <code>setStrike()</code> methods to handle validation. Python offers a cleaner alternative: the <code>@property</code> decorator.</p>
<p>This allows us to access a method as if it were an attribute, adding logic like validation seamlessly.</p>
<div id="7652de8a" class="cell" data-execution_count="8">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> EuropeanOption:</span>
<span id="cb13-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, strike: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>):</span>
<span id="cb13-3">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># We assign to the property, triggering the setter validation</span></span>
<span id="cb13-4">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.strike <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> strike</span>
<span id="cb13-5"></span>
<span id="cb13-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@property</span></span>
<span id="cb13-7">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> strike(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb13-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._strike</span>
<span id="cb13-9"></span>
<span id="cb13-10">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@strike.setter</span></span>
<span id="cb13-11">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> strike(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, value):</span>
<span id="cb13-12">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb13-13">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Strike price cannot be negative."</span>)</span>
<span id="cb13-14">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._strike <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> value</span>
<span id="cb13-15"></span>
<span id="cb13-16">opt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> EuropeanOption(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>)</span>
<span id="cb13-17"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Current Strike: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>opt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>strike<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb13-18"></span>
<span id="cb13-19"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb13-20">    opt.strike <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span></span>
<span id="cb13-21"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> e:</span>
<span id="cb13-22">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Error caught: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>e<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Current Strike: 100
Error caught: Strike price cannot be negative.</code></pre>
</div>
</div>
<p>Notice we use <code>self._strike</code> inside the property to store the actual value.</p>
</section>
<section id="access-control-private-vs.-protected" class="level2">
<h2 class="anchored" data-anchor-id="access-control-private-vs.-protected">Access Control: Private vs.&nbsp;Protected</h2>
<p>Python does not enforce strict <code>private</code> or <code>protected</code> keywords. Instead, it relies on naming conventions:</p>
<div id="d1c4d21a" class="cell" data-execution_count="9">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-9" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-9-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> EuropeanOption:</span>
<span id="annotated-cell-9-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, strike: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>):</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-9" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-9-3" class="code-annotation-target">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._strike <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> strike</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-9" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-9-4" class="code-annotation-target">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.__valuation_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BS"</span></span>
<span id="annotated-cell-9-5"></span>
<span id="annotated-cell-9-6">opt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> EuropeanOption(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>)</span>
<span id="annotated-cell-9-7"></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-9" data-target-annotation="3" onclick="event.preventDefault();">3</a><span id="annotated-cell-9-8" class="code-annotation-target"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(opt._strike)</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-9" data-target-annotation="4" onclick="event.preventDefault();">4</a><span id="annotated-cell-9-9" class="code-annotation-target"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># print(opt.__valuation_model)</span></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-9" data-target-annotation="5" onclick="event.preventDefault();">5</a><span id="annotated-cell-9-10" class="code-annotation-target"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(opt._EuropeanOption__valuation_model)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-9" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-9" data-code-lines="3" data-code-annotation="1"><strong>Protected (<code>_variable</code>)</strong>: A single underscore prefix indicates that a variable or method is for internal use only. It’s a signal to other developers: “Don’t touch this unless you know what you are doing.</span>
</dd>
<dt data-target-cell="annotated-cell-9" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-9" data-code-lines="4" data-code-annotation="2"><strong>Private (<code>__variable</code>)</strong>: A double underscore prefix triggers <strong>name mangling</strong>. The interpreter changes the variable name to <code>_ClassName__variable</code> to prevent accidental overwrites in subclasses. It is effectively private, but can still be accessed if you really try.</span>
</dd>
<dt data-target-cell="annotated-cell-9" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-9" data-code-lines="8" data-code-annotation="3">Works, but considered bad practice</span>
</dd>
<dt data-target-cell="annotated-cell-9" data-target-annotation="4">4</dt>
<dd>
<span data-code-cell="annotated-cell-9" data-code-lines="9" data-code-annotation="4">Raises an error because of name mangling</span>
</dd>
<dt data-target-cell="annotated-cell-9" data-target-annotation="5">5</dt>
<dd>
<span data-code-cell="annotated-cell-9" data-code-lines="10" data-code-annotation="5">Still accessible via the mangled name, but this is a hack and should be avoided.</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>100
BS</code></pre>
</div>
</div>
<p>In quantitative libraries, generally use <code>_</code> for internal state that shouldn’t be part of the public API. Reserve <code>__</code> for cases where you specifically need to avoid naming collisions in complex inheritance hierarchies.</p>
</section>
<section id="memory-optimization-__slots__" class="level2">
<h2 class="anchored" data-anchor-id="memory-optimization-__slots__">Memory Optimization: <code>__slots__</code></h2>
<p>Standard Python objects store their attributes in a dictionary (<code>__dict__</code>), which allows for the dynamic behavior we saw earlier. However, dictionaries come with memory overhead.</p>
<p>If you are running a Monte Carlo simulation with millions of paths, this overhead can become a bottleneck. <code>__slots__</code> tells Python to reserve space for <em>only</em> a specific set of attributes, removing the dynamic dictionary and saving memory.</p>
<div id="48c15fe6" class="cell" data-execution_count="10">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> sys</span>
<span id="cb16-2"></span>
<span id="cb16-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> StandardOption:</span>
<span id="cb16-4">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, strike, expiry):</span>
<span id="cb16-5">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.strike <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> strike</span>
<span id="cb16-6">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.expiry <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> expiry</span>
<span id="cb16-7"></span>
<span id="cb16-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> SlottedOption:</span>
<span id="cb16-9">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__slots__</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"strike"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"expiry"</span>]</span>
<span id="cb16-10"></span>
<span id="cb16-11">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, strike, expiry):</span>
<span id="cb16-12">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.strike <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> strike</span>
<span id="cb16-13">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.expiry <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> expiry</span>
<span id="cb16-14"></span>
<span id="cb16-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compare memory usage</span></span>
<span id="cb16-16">std_opt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> StandardOption(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2025-12-20"</span>)</span>
<span id="cb16-17">slot_opt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> SlottedOption(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2025-12-20"</span>)</span>
<span id="cb16-18"></span>
<span id="cb16-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Helper function to estimate size (rough approximation)</span></span>
<span id="cb16-20"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_size(obj):</span>
<span id="cb16-21">    size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sys.getsizeof(obj)</span>
<span id="cb16-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">hasattr</span>(obj, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"__dict__"</span>):</span>
<span id="cb16-23">        size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> sys.getsizeof(obj.__dict__)</span>
<span id="cb16-24">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> size</span>
<span id="cb16-25"></span>
<span id="cb16-26"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Standard Option Size: ~</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>get_size(std_opt)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> bytes"</span>)</span>
<span id="cb16-27"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Slotted Option Size:  ~</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>get_size(slot_opt)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> bytes"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Standard Option Size: ~344 bytes
Slotted Option Size:  ~48 bytes</code></pre>
</div>
</div>
<p>The <code>SlottedOption</code> instance is more rigid—you cannot add new attributes like <code>slot_opt.vega = ...</code>—but it is significantly more memory-efficient.</p>
</section>
<section id="modern-python-data-classes" class="level2">
<h2 class="anchored" data-anchor-id="modern-python-data-classes">Modern Python: Data Classes</h2>
<p>Since Python 3.7, there is an even easier way to create classes that primarily store data. The <code>@dataclass</code> decorator automatically generates <code>__init__</code>, <code>__repr__</code>, <code>__eq__</code>, and other special methods for you, reducing boilerplate.</p>
<div id="fa4e6082" class="cell" data-execution_count="11">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> dataclasses <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dataclass</span>
<span id="cb18-2"></span>
<span id="cb18-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@dataclass</span></span>
<span id="cb18-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> OptionData:</span>
<span id="cb18-5">    strike: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span></span>
<span id="cb18-6">    expiry: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb18-7">    option_type: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Call"</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Default value</span></span>
<span id="cb18-8"></span>
<span id="cb18-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># No need to write __init__ or __repr__ manually!</span></span>
<span id="cb18-10">opt_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> OptionData(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">100.0</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2025-12-20"</span>)</span>
<span id="cb18-11"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(opt_data)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>OptionData(strike=100.0, expiry='2025-12-20', option_type='Call')</code></pre>
</div>
</div>
<p>Data classes are perfect for data transfer objects (DTOs) or when you simply need a structured container for information without complex initialization logic. They play very well with modern type checkers and IDEs.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>We’ve gone from a chaotic, empty class to a structured, efficient unit that’s ready for some serious quant work. Here’s the quick checklist:</p>
<ul>
<li><strong><code>__init__</code></strong> is your safety net—use it to make sure your objects start off right.</li>
<li><strong>Instance vs.&nbsp;Class Attributes:</strong> Know when data belongs to one object and when it’s shared by everyone.</li>
<li><strong>Method Types:</strong> Use Instance methods for most things, Class methods for “factory” setups, and Static methods for pure utility.</li>
<li><strong><code>@property</code></strong> is your best friend for adding validation without making your code ugly.</li>
<li><strong>Access Control:</strong> Use <code>_</code> to signal “internal use only” and <code>__</code> when you really want to avoid naming collisions.</li>
<li><strong><code>__slots__</code></strong> is a great “break in case of emergency” tool for saving memory in massive simulations.</li>
<li><strong>Data Classes</strong> are the modern, low-boilerplate way to build classes that just store info.</li>
</ul>
<p>With these building blocks in place, the <a href="../25-12-12-python-academy-data-model/">next post</a> dives into Python’s data model — the dunder methods that make your classes feel like built-in types.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>The complete Python script with all the examples from this post is available for download and experimentation. You can get it here: <a href="../../../assets/python/python_class_mechanics_and_anatomy_deep_dive.py">python_class_mechanics_and_anatomy_deep_dive.py</a>.</p>
</div>
</div>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Python Academy</category>
  <guid>https://bwrob.github.io/teaching/2025-python-academy/25-12-04-python-academy-class-anatomy/</guid>
  <pubDate>Thu, 04 Dec 2025 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/teaching/2025-python-academy/25-12-04-python-academy-class-anatomy/cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Python Env Management: From venv to uv</title>
  <link>https://bwrob.github.io/teaching/2025-python-academy/25-11-27-python-academy-environment-management/</link>
  <description><![CDATA[ 






<p>In this installment of <a href="https://bwrob.github.io/#category=Python%20Academy">Python Academy</a>, we’re tackling something that trips up almost everyone starting with Python: <strong>Environment Management</strong>.</p>
<p>We’ll kick things off with the bread-and-butter tools—<code>venv</code> and <code>pip</code>—and then look at <code>uv</code>, a modern alternative that’s rewriting the rules (and it’s fast).</p>
<section id="the-classics-venv-and-pip" class="level2">
<h2 class="anchored" data-anchor-id="the-classics-venv-and-pip">The Classics: venv and pip</h2>
<section id="why-bother-with-virtual-environments" class="level3">
<h3 class="anchored" data-anchor-id="why-bother-with-virtual-environments">Why bother with virtual environments?</h3>
<p>When you first install Python, you get one global playground. It sounds convenient until you realize that sharing your toys leads to broken toys.</p>
<ol type="1">
<li><strong>Version Nightmares:</strong> Project A needs <code>pandas</code> version 1.0, but Project B demands version 2.0. You can’t have both installed globally.</li>
<li><strong>Breaking Your System:</strong> On Linux/macOS, your OS uses Python for its own internal tools. If you start messing with global packages, you might accidentally break your terminal or system utilities.</li>
<li><strong>Permission Headaches:</strong> Installing globally often screams for <code>sudo</code>, which is usually a sign you’re doing something risky.</li>
</ol>
<p>Virtual environments are the answer. They let you create isolated sandboxes for every project. Each sandbox gets its own Python executable and its own set of libraries, so they never fight over versions.</p>
</section>
<section id="creating-and-activating" class="level3">
<h3 class="anchored" data-anchor-id="creating-and-activating">Creating and Activating</h3>
<p>The standard way to make a sandbox is with <code>venv</code>.</p>
<p>To create one named <code>.venv</code> (the industry standard name):</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">python</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-m</span> venv .venv</span></code></pre></div></div>
<p>You’ll see a new <code>.venv</code> folder pop up. But it’s just sitting there until you <strong>activate</strong> it.</p>
<p><strong>On macOS/Linux:</strong></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">source</span> .venv/bin/activate</span></code></pre></div></div>
<p><strong>On Windows:</strong></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource powershell number-lines code-with-copy"><code class="sourceCode powershell"><span id="cb3-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">venv</span>\Scripts\Activate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ps1</span></span></code></pre></div></div>
<p>Once you see <code>(.venv)</code> in your prompt, you’re in the sandbox. Anything you install here stays here.</p>
</section>
<section id="managing-packages-with-pip" class="level3">
<h3 class="anchored" data-anchor-id="managing-packages-with-pip">Managing Packages with pip</h3>
<p><code>pip</code> is your tool for grabbing libraries from the internet (PyPI).</p>
<p>To install something:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pip</span> install requests</span></code></pre></div></div>
<p>To see what you’ve got:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pip</span> list</span></code></pre></div></div>
</section>
<section id="requirements.txt" class="level3">
<h3 class="anchored" data-anchor-id="requirements.txt"><code>requirements.txt</code></h3>
<p>So you’ve built a cool app. How do you tell your friend exactly which libraries they need to run it? You hand them a <code>requirements.txt</code>.</p>
<p>You can generate this list from your current environment automatically:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pip</span> freeze <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> requirements.txt</span></code></pre></div></div>
<p>This dumps every installed package and its exact version into a text file.</p>
<p>When your friend grabs your code, they just run:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pip</span> install <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-r</span> requirements.txt</span></code></pre></div></div>
<p>And boom, their environment looks just like yours.</p>
</section>
<section id="generating-requirements-from-code-with-pipreqs" class="level3">
<h3 class="anchored" data-anchor-id="generating-requirements-from-code-with-pipreqs">Generating requirements from code with pipreqs</h3>
<p><code>pip freeze</code> works well if you’ve been disciplined about your environment. But what if you inherit a folder of Python scripts with no documentation and no <code>requirements.txt</code>? Or what if you’ve just been installing packages globally for years?</p>
<p>In these cases, <code>pip freeze</code> will give you a list of <em>everything</em> you’ve ever installed, which is often overkill and messy.</p>
<p>This is where <code>pipreqs</code> shines. It analyzes your source code imports to determine exactly what packages are needed. It’s the perfect tool to bootstrap “good practices” for a project that started without them.</p>
<ol type="1">
<li><p><strong>Install it:</strong></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pip</span> install pipreqs</span></code></pre></div></div></li>
<li><p><strong>Run it:</strong></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pipreqs</span> .</span></code></pre></div></div></li>
</ol>
<p>This scans your <code>.py</code> files and generates a clean, minimal <code>requirements.txt</code> based solely on the libraries you actually import. Now you have a solid foundation to create a fresh virtual environment!</p>
</section>
</section>
<section id="the-modern-era-uv" class="level2">
<h2 class="anchored" data-anchor-id="the-modern-era-uv">The Modern Era: uv</h2>
<p><code>venv</code> and <code>pip</code> are reliable, but let’s be honest—they can be a bit clunky and slow. Enter <code>uv</code>. It’s a Python package and project manager written in Rust, and it is fast. It aims to replace <code>pip</code>, <code>pip-tools</code>, and <code>virtualenv</code> with one single binary.</p>
<section id="setting-up-with-uv" class="level3">
<h3 class="anchored" data-anchor-id="setting-up-with-uv">Setting up with uv</h3>
<p>Instead of manually creating folders and files, <code>uv</code> creates the project skeleton for you:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb10-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> init my-project</span>
<span id="cb10-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span> my-project</span></code></pre></div></div>
<p>This sets up a standard structure, including a <code>pyproject.toml</code>. This file is the modern replacement for <code>requirements.txt</code> and <code>setup.py</code>.</p>
</section>
<section id="managing-dependencies" class="level3">
<h3 class="anchored" data-anchor-id="managing-dependencies">Managing Dependencies</h3>
<p>With <code>uv</code>, the days of <code>pip install</code> followed by remembering to run <code>pip freeze</code> are over. You just tell <code>uv</code> what you want:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> add requests</span></code></pre></div></div>
<p>This one command does all the heavy lifting:</p>
<ol type="1">
<li>Finds the best version of <code>requests</code>.</li>
<li>Installs it (creating a virtual environment automatically if you don’t have one).</li>
<li>Updates your <code>pyproject.toml</code>.</li>
<li>Updates <code>uv.lock</code>, which locks down the exact versions of everything (like <code>package-lock.json</code> in the JS world) so your builds are 100% reproducible.</li>
</ol>
</section>
<section id="development-dependencies" class="level3">
<h3 class="anchored" data-anchor-id="development-dependencies">Development Dependencies</h3>
<p>Sometimes you need tools just for development—like testing frameworks or linters—that shouldn’t be shipped with your actual app. <code>uv</code> handles this cleanly:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb12-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> add <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--dev</span> pytest ruff</span></code></pre></div></div>
<p>Take <code>ruff</code> for example. It’s a fast linter and formatter. You want it while you’re coding to keep things tidy, but your users don’t need it to run your app. Adding it with <code>--dev</code> puts it in a special <code>[tool.uv.dev-dependencies]</code> section, keeping your production environment lean.</p>
</section>
<section id="managing-python-versions" class="level3">
<h3 class="anchored" data-anchor-id="managing-python-versions">Managing Python Versions</h3>
<p>This is where <code>uv</code> really shines. Need to test on Python 3.11 but you only have 3.12 installed? <code>uv</code> can fetch it for you:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb13-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> python install 3.11</span>
<span id="cb13-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> venv <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--python</span> 3.11</span></code></pre></div></div>
<p>Or you can just pin your project to a specific version, and <code>uv</code> will respect that:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb14-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> python pin 3.12</span></code></pre></div></div>
</section>
<section id="packaging-sharing-your-code" class="level3">
<h3 class="anchored" data-anchor-id="packaging-sharing-your-code">Packaging: Sharing Your Code</h3>
<p>So you’ve got a project and you want to share it with your colleagues (or the world). How do you box it up? You build a <strong>Wheel</strong>.</p>
<section id="whats-a-wheel" class="level4">
<h4 class="anchored" data-anchor-id="whats-a-wheel">What’s a Wheel?</h4>
<p>A “Wheel” (file extension <code>.whl</code>) is the standard way to distribute Python packages. Think of it as a zip file that’s ready to go.</p>
<p>In the old days, we often shared “source distributions” (<code>.tar.gz</code>). This meant the user’s computer had to compile any C-extensions or complex code when they installed it. This was slow and error-prone.</p>
<p>Wheels are <strong>built distributions</strong>. They are pre-compiled and ready to unpack. When you <code>pip install pandas</code>, you’re almost certainly downloading a wheel. It’s faster, safer, and easier.</p>
</section>
<section id="the-old-guard-setuptools" class="level4">
<h4 class="anchored" data-anchor-id="the-old-guard-setuptools">The Old Guard: <code>setuptools</code></h4>
<p>Traditionally, building a package meant wrestling with a file called <code>setup.py</code> using a library called <code>setuptools</code>. This little Python script was where you’d declare everything about your package: its name, version, author, a brief description, and most importantly, its dependencies. You’d define which modules to include, any data files, and even entry points for command-line tools.</p>
<p>It was powerful, for sure, but also notoriously tricky to get right. Debugging <code>setup.py</code> was tedious — you’d write code to describe your package, manage included files, and handle dependencies. It worked, but slight changes in Python’s packaging standards would often mean revisiting this script.</p>
<p>Here’s a super basic <code>setup.py</code> example for a package named <code>my_package</code>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="annotated-cell-13" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-13-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># setup.py</span></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-13" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-13-2" class="code-annotation-target"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> setuptools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> setup, find_packages</span>
<span id="annotated-cell-13-3"></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-13" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-13-4" class="code-annotation-target">setup(</span>
<span id="annotated-cell-13-5">    name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'my_package'</span>,</span>
<span id="annotated-cell-13-6">    version<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'0.1.0'</span>,</span>
<span id="annotated-cell-13-7">    packages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>find_packages(),</span>
<span id="annotated-cell-13-8">    install_requires<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="annotated-cell-13-9">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'requests'</span>,</span>
<span id="annotated-cell-13-10">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'numpy'</span>,</span>
<span id="annotated-cell-13-11">    ],</span>
<span id="annotated-cell-13-12">    author<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Your Name'</span>,</span>
<span id="annotated-cell-13-13">    author_email<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'your.email@example.com'</span>,</span>
<span id="annotated-cell-13-14">    description<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'A simple example package.'</span>,</span>
<span id="annotated-cell-13-15">    long_description<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'README.md'</span>).read(),</span>
<span id="annotated-cell-13-16">    long_description_content_type<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'text/markdown'</span>,</span>
<span id="annotated-cell-13-17">    url<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://github.com/yourusername/my_package'</span>,</span>
<span id="annotated-cell-13-18">    classifiers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="annotated-cell-13-19">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Programming Language :: Python :: 3'</span>,</span>
<span id="annotated-cell-13-20">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'License :: OSI Approved :: MIT License'</span>,</span>
<span id="annotated-cell-13-21">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Operating System :: OS Independent'</span>,</span>
<span id="annotated-cell-13-22">    ],</span>
<span id="annotated-cell-13-23">    python_requires<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'&gt;=3.8'</span>,</span>
<span id="annotated-cell-13-24">)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-13" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-13" data-code-lines="2" data-code-annotation="1">Import necessary setuptools utilities.</span>
</dd>
<dt data-target-cell="annotated-cell-13" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-13" data-code-lines="4" data-code-annotation="2">The setup function defines package metadata and requirements.</span>
</dd>
</dl>
<p>And to build your package (both source and wheel distributions) using this file, you’d run:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb15-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">python</span> setup.py sdist bdist_wheel</span></code></pre></div></div>
</section>
<section id="the-new-way-uv-build" class="level4">
<h4 class="anchored" data-anchor-id="the-new-way-uv-build">The New Way: uv build</h4>
<p>Since <code>uv</code> already knows everything about your project from <code>pyproject.toml</code>, building a package is laughably simple. You don’t need a <code>setup.py</code> anymore.</p>
<p>Just run:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb16-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> build</span></code></pre></div></div>
<p>That’s it. <code>uv</code> will look at your <code>pyproject.toml</code>, gather your code, and spit out a shiny <code>.whl</code> file (and a <code>.tar.gz</code> source distribution just in case) into a <code>dist/</code> folder. You can then upload these to PyPI or share them directly.</p>
</section>
</section>
<section id="conclusion" class="level3">
<h3 class="anchored" data-anchor-id="conclusion">Conclusion</h3>
<table class="caption-top table">
<colgroup>
<col style="width: 17%">
<col style="width: 42%">
<col style="width: 39%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">Feature</th>
<th style="text-align: left;">Classic (<code>venv</code> + <code>pip</code>)</th>
<th style="text-align: left;">Modern (<code>uv</code>)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><strong>Creation</strong></td>
<td style="text-align: left;"><code>python -m venv .venv</code></td>
<td style="text-align: left;"><code>uv init</code> / auto-created</td>
</tr>
<tr class="even">
<td style="text-align: left;"><strong>Install</strong></td>
<td style="text-align: left;"><code>pip install pkg</code></td>
<td style="text-align: left;"><code>uv add pkg</code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><strong>Save Deps</strong></td>
<td style="text-align: left;"><code>pip freeze &gt; requirements.txt</code></td>
<td style="text-align: left;">Automatic in <code>pyproject.toml</code></td>
</tr>
<tr class="even">
<td style="text-align: left;"><strong>Dev Deps</strong></td>
<td style="text-align: left;">Manual separation</td>
<td style="text-align: left;"><code>uv add --dev pkg</code></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><strong>Speed</strong></td>
<td style="text-align: left;">Standard</td>
<td style="text-align: left;">Blazing Fast 🚀</td>
</tr>
</tbody>
</table>
<p>Understanding <code>venv</code> and <code>pip</code> is useful background — it’s how we did things for a long time. But once you try <code>uv</code>, you won’t want to go back.</p>


</section>
</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Python Academy</category>
  <guid>https://bwrob.github.io/teaching/2025-python-academy/25-11-27-python-academy-environment-management/</guid>
  <pubDate>Thu, 27 Nov 2025 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/teaching/2025-python-academy/25-11-27-python-academy-environment-management/cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Efficient Iteration</title>
  <link>https://bwrob.github.io/teaching/2025-python-academy/25-11-05-python-academy-iteration/</link>
  <description><![CDATA[ 






<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p>In the finance world, we’re always neck-deep in data. It’s not just about how fast you can process it, but whether your code is going to crash your server by eating up all the memory.</p>
<p>This post is about iterators and generators — the “lazy” way to handle data that saves memory and avoids headaches.</p>
</section>
<section id="lists-vs.-tuples-the-eager-iterables" class="level2">
<h2 class="anchored" data-anchor-id="lists-vs.-tuples-the-eager-iterables">Lists vs.&nbsp;Tuples: The Eager Iterables</h2>
<p>Lists and tuples are the most common sequence types in Python. They are <em>eager</em> in the sense that all their elements are stored in memory at once. When you create a list of a million numbers, Python allocates memory for all of them.</p>
<div id="f08c4a26" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb1-1">my_list <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1_000_000</span>)]</span>
<span id="cb1-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This creates a list with 1,000,000 integers in memory.</span></span></code></pre></div></div>
</details>
</div>
<p>This is fine for small to medium-sized datasets, but for very large datasets, this can lead to <code>MemoryError</code>.</p>
<section id="key-differences" class="level3">
<h3 class="anchored" data-anchor-id="key-differences">Key Differences</h3>
<p>The primary difference between lists and tuples is <strong>mutability</strong>.</p>
<ul>
<li><p><strong>Lists</strong> are mutable, meaning you can change their content. You can add, remove, or change elements. This flexibility comes at a cost: lists typically require more memory to store the same number of elements compared to tuples. This is because Python allocates extra memory to accommodate future additions.</p></li>
<li><p><strong>Tuples</strong> are immutable. Once a tuple is created, you cannot change its content. This immutability makes them slightly more memory-efficient and faster to access than lists.</p></li>
</ul>
<p>From a quant’s perspective, you can think of a tuple as a “frozen” or “read-only” list. Use tuples for data that should not change, like coordinates, configuration settings, or records from a database. If you need a collection that you will modify, a list is the way to go.</p>
</section>
</section>
<section id="iterators-the-lazy-approach" class="level2">
<h2 class="anchored" data-anchor-id="iterators-the-lazy-approach">Iterators: The Lazy Approach</h2>
<p>An iterator is an object that represents a stream of data. It produces one item at a time, only when requested. The iterator protocol consists of two methods:</p>
<ul>
<li><code>__iter__()</code>: Returns the iterator object itself.</li>
<li><code>__next__()</code>: Returns the next item from the stream. When there are no more items, it raises a <code>StopIteration</code> exception.</li>
</ul>
<p>You can get an iterator from any iterable (like a list) using the <code>iter()</code> function.</p>
<div id="7eeb0e85" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb2-1">my_list <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]</span>
<span id="cb2-2">my_iterator <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(my_list)</span>
<span id="cb2-3"></span>
<span id="cb2-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(my_iterator))  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Output: 1</span></span>
<span id="cb2-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(my_iterator))  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Output: 2</span></span>
<span id="cb2-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(my_iterator))  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Output: 3</span></span>
<span id="cb2-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The next call would raise StopIteration</span></span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>1
2
3</code></pre>
</div>
</div>
</section>
<section id="generators-simplified-iterators" class="level2">
<h2 class="anchored" data-anchor-id="generators-simplified-iterators">Generators: Simplified Iterators</h2>
<p>Generators are a simpler way to create iterators. Instead of writing a class with <code>__iter__</code> and <code>__next__</code>, you write a function that uses <code>yield</code>.</p>
<p>Here’s a simple generator that produces a sequence of numbers:</p>
<div id="aa4980b2" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> number_generator(n):</span>
<span id="cb4-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n):</span>
<span id="cb4-3">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> i</span>
<span id="cb4-4"></span>
<span id="cb4-5">gen <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> number_generator(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1_000_000</span>)</span>
<span id="cb4-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># No large list is created in memory here.</span></span>
<span id="cb4-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The generator object 'gen' is created, ready to produce numbers.</span></span></code></pre></div></div>
</details>
</div>
<p>The state of the generator is saved between <code>yield</code> calls. This allows it to resume where it left off.</p>
<section id="example-flattening-a-list-of-lists" class="level3">
<h3 class="anchored" data-anchor-id="example-flattening-a-list-of-lists">Example: Flattening a List of Lists</h3>
<p>A common task is to flatten a list of lists into a single list. A generator is a perfect tool for this, especially when dealing with large datasets, as it avoids creating a new, large list in memory.</p>
<p>Imagine you have a list of trades, where each trade has a list of associated cashflows. You want to process all cashflows from all trades.</p>
<div id="3adf84b0" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb5-1">trades_cashflows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb5-2">    [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>],  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Cashflows for Trade 1</span></span>
<span id="cb5-3">    [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>],  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Cashflows for Trade 2</span></span>
<span id="cb5-4">    [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>],  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Cashflows for Trade 3</span></span>
<span id="cb5-5">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">110</span>,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Simple payment doesn't need to be in a list!</span></span>
<span id="cb5-6">]</span>
<span id="cb5-7"></span>
<span id="cb5-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> flatten(list_of_lists):</span>
<span id="cb5-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> item <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> list_of_lists:</span>
<span id="cb5-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(item, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>):</span>
<span id="cb5-11">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> subitem <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> item:</span>
<span id="cb5-12">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> subitem</span>
<span id="cb5-13">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb5-14">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> item</span>
<span id="cb5-15"></span>
<span id="cb5-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The generator does not hold all cashflows in memory</span></span>
<span id="cb5-17">all_cashflows_generator <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> flatten(trades_cashflows)</span>
<span id="cb5-18"></span>
<span id="cb5-19"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> cf <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> all_cashflows_generator:</span>
<span id="cb5-20">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(cf, end<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" "</span>)</span>
<span id="cb5-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Output: 10 20 30 15 25 100 -10 5 110</span></span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>10 20 30 15 25 100 -10 5 110 </code></pre>
</div>
</div>
<p>The generator only holds one cashflow at a time, regardless of total count.</p>
</section>
</section>
<section id="memory-efficiency-in-action" class="level2">
<h2 class="anchored" data-anchor-id="memory-efficiency-in-action">Memory Efficiency in Action</h2>
<p>To make our memory analysis cleaner, we can define a decorator. This is a more Pythonic way to wrap functions with common boilerplate code, like starting and stopping <code>tracemalloc</code>.</p>
<p>Let’s demonstrate the memory difference using a decorator with the standard library’s <code>tracemalloc</code> module. We’ll compare the memory usage of creating a list versus creating a generator.</p>
<div id="d57fee03" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> tracemalloc</span>
<span id="cb7-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> functools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> wraps</span>
<span id="cb7-3"></span>
<span id="cb7-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> profile_memory(func):</span>
<span id="cb7-5">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""A decorator to profile the memory usage of a function."""</span></span>
<span id="cb7-6"></span>
<span id="cb7-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@wraps</span>(func)</span>
<span id="cb7-8">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> wrapper(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs):</span>
<span id="cb7-9">        tracemalloc.start()</span>
<span id="cb7-10">        result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> func(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)</span>
<span id="cb7-11">        current, peak <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tracemalloc.get_traced_memory()</span>
<span id="cb7-12">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Function: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>func<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb7-13">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(</span>
<span id="cb7-14">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Current memory usage is </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>current <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.6f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">MB; Peak was </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>peak <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.6f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">MB"</span></span>
<span id="cb7-15">        )</span>
<span id="cb7-16">        tracemalloc.stop()</span>
<span id="cb7-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> result</span>
<span id="cb7-18"></span>
<span id="cb7-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> wrapper</span>
<span id="cb7-20"></span>
<span id="cb7-21"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@profile_memory</span></span>
<span id="cb7-22"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> create_list(n):</span>
<span id="cb7-23">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""This function creates a list of n numbers."""</span></span>
<span id="cb7-24">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n)]</span>
<span id="cb7-25"></span>
<span id="cb7-26"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@profile_memory</span></span>
<span id="cb7-27"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> create_generator(n):</span>
<span id="cb7-28">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""This function creates a generator of n numbers."""</span></span>
<span id="cb7-29">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n))</span>
<span id="cb7-30"></span>
<span id="cb7-31">n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1_000_000</span></span>
<span id="cb7-32"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Profiling memory for list creation..."</span>)</span>
<span id="cb7-33">my_list <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> create_list(n)</span>
<span id="cb7-34"></span>
<span id="cb7-35"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Profiling memory for generator creation..."</span>)</span>
<span id="cb7-36">my_generator <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> create_generator(n)</span>
<span id="cb7-37"></span>
<span id="cb7-38"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The generator itself is small. Let's profile consuming it.</span></span>
<span id="cb7-39"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@profile_memory</span></span>
<span id="cb7-40"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> consume_generator(gen):</span>
<span id="cb7-41">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(gen)</span>
<span id="cb7-42"></span>
<span id="cb7-43"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Profiling memory for generator consumption..."</span>)</span>
<span id="cb7-44">consumed_list <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> consume_generator(my_generator)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Profiling memory for list creation...
Function: create_list
Current memory usage is 40.441278MB; Peak was 40.441318MB
Profiling memory for generator creation...
Function: create_generator
Current memory usage is 0.000392MB; Peak was 0.000392MB
Profiling memory for generator consumption...
Function: consume_generator
Current memory usage is 40.441272MB; Peak was 40.441272MB</code></pre>
</div>
</div>
<p>The output speaks for itself: creating the generator uses almost no memory. The cost only shows up when you actually consume it into a list.</p>
</section>
<section id="essential-iteration-tools-zip-sorted-enumerate" class="level2">
<h2 class="anchored" data-anchor-id="essential-iteration-tools-zip-sorted-enumerate">Essential Iteration Tools: <code>zip</code>, <code>sorted</code>, <code>enumerate</code></h2>
<p>A few built-in functions that come up constantly:</p>
<ul>
<li><p><strong><code>enumerate(iterable, start=0)</code></strong>: When processing a series of cashflows, you might need to know the period number for each payment. <code>enumerate</code> is perfect for this.</p>
<p>::: {#a2707624 .cell execution_count=6} <code>{.python .cell-code}   cashflows = [100, 100, 100, 1100] # Coupon payments and principal   for period, cf in enumerate(cashflows, 1):       print(f"Period {period}: Cashflow = {cf}")</code></p>
<p>::: {.cell-output .cell-output-stdout} <code>Period 1: Cashflow = 100   Period 2: Cashflow = 100   Period 3: Cashflow = 100   Period 4: Cashflow = 1100</code> ::: :::</p></li>
<li><p><strong><code>zip(*iterables)</code></strong>: This function is very useful for combining different streams of data. For example, you can pair trade dates with their corresponding notionals.</p>
<p>::: {#bfcf62c9 .cell execution_count=7} <code>{.python .cell-code}   trade_dates = ['2025-11-05', '2025-11-06', '2025-11-07']   notionals = [1_000_000, 2_500_000, 500_000]   for date, notional in zip(trade_dates, notionals):       print(f"On {date}, we traded a notional of {notional:,}")</code></p>
<p>::: {.cell-output .cell-output-stdout} <code>On 2025-11-05, we traded a notional of 1,000,000   On 2025-11-06, we traded a notional of 2,500,000   On 2025-11-07, we traded a notional of 500,000</code> ::: :::</p></li>
<li><p><strong><code>sorted(iterable, key=None, reverse=False)</code></strong>: Sorting is a common task. You might want to sort a list of trades by maturity date or notional.</p>
<p>::: {#5792732b .cell execution_count=8} ``` {.python .cell-code} from dataclasses import dataclass from datetime import date</p>
<p><span class="citation" data-cites="dataclass">@dataclass</span> class Trade: trade_id: str maturity: date notional: float</p>
<p>trades = [ Trade(‘T1’, date(2026, 12, 31), 10_000_000), Trade(‘T2’, date(2025, 12, 31), 5_000_000), Trade(‘T3’, date(2027, 12, 31), 15_000_000), ]</p>
<p># Sort trades by maturity date sorted_by_maturity = sorted(trades, key=lambda t: t.maturity) for trade in sorted_by_maturity: print(trade) ```</p>
<p>::: {.cell-output .cell-output-stdout} <code>Trade(trade_id='T2', maturity=datetime.date(2025, 12, 31), notional=5000000)   Trade(trade_id='T1', maturity=datetime.date(2026, 12, 31), notional=10000000)   Trade(trade_id='T3', maturity=datetime.date(2027, 12, 31), notional=15000000)</code> ::: :::</p></li>
</ul>
</section>
<section id="the-itertools-module-a-treasure-trove-for-financial-iteration" class="level2">
<h2 class="anchored" data-anchor-id="the-itertools-module-a-treasure-trove-for-financial-iteration">The <code>itertools</code> Module: A Treasure Trove for Financial Iteration</h2>
<p>The <code>itertools</code> module is worth knowing well. Here are the ones I reach for most in financial work.</p>
<ul>
<li><p><strong><code>itertools.chain(*iterables)</code> and <code>itertools.chain.from_iterable(iterable)</code></strong>: Often you need to process items from several sequences in a row. <code>chain</code> lets you treat them as a single, continuous stream without merging them in memory. A great example is pricing a fixed-to-float swap leg, where initial coupon payments are fixed, and later ones are floating.</p>
<p><code>chain.from_iterable</code> is a useful variant that takes a single iterable of iterables.</p>
<p>::: {#ba501479 .cell execution_count=9} ``` {.python .cell-code} import itertools import random</p>
<p># First 2 years have fixed coupons fixed_leg = [50, 50, 50, 50]</p>
<p># Next 3 years have floating coupons (calculated for demonstration) floating_leg = [50 + random.uniform(-5, 5) for _ in range(6)]</p>
<p># We have a list of cashflow legs bond_legs = [fixed_leg, floating_leg]</p>
<p># We can use chain.from_iterable to chain them together full_swap_leg = itertools.chain.from_iterable(bond_legs)</p>
<p>print(“Full cashflow stream for the leg:”) for cf in full_swap_leg: print(f”{cf:.2f}“, end=’ ’) ```</p>
<p>::: {.cell-output .cell-output-stdout} <code>Full cashflow stream for the leg:   50.00 50.00 50.00 50.00 54.89 50.04 45.64 54.27 45.16 47.22</code> ::: :::</p></li>
<li><p><strong><code>itertools.accumulate(iterable[, func])</code></strong>: This is ideal for calculating cumulative sums or running products. A common use case is to calculate the cumulative P&amp;L of a trading strategy.</p>
<p>::: {#a2a32f56 .cell execution_count=10} <code>{.python .cell-code}   import itertools   daily_pnl = [150, -200, 50, 300, -100]   cumulative_pnl = itertools.accumulate(daily_pnl)   print(list(cumulative_pnl))   # Output: [150, -50, 0, 300, 200]</code></p>
<p>::: {.cell-output .cell-output-stdout} <code>[150, -50, 0, 300, 200]</code> ::: :::</p>
<p>It can also model more complex recurrence relations, like the amortization of a loan. Let’s calculate the outstanding balance of a fixed-payment annuity until it’s paid off.</p>
<p>::: {#32cffe3d .cell execution_count=11} ``` {.python .cell-code} import itertools</p>
<p>def outstanding_balance(balance, payment, rate): return balance * (1 + rate) - payment</p>
<p>initial_notional = 1_000 interest_rate = 0.01 # Monthly rate (around 12% annually) monthly_payment = 50</p>
<p># Create an infinite stream of payments payments = itertools.repeat(monthly_payment)</p>
<p># The first argument to the lambda is the accumulated value (the balance) # The second argument is the next item from the iterable (the payment) balances = itertools.accumulate( payments, lambda balance, pmt: outstanding_balance(balance, pmt, interest_rate), initial=initial_notional, )</p>
<p># We can use takewhile to iterate until the loan is paid off (balance &gt; 0) # The +1 is to see the final payment that brings the balance to &lt;= 0 amortization_schedule = itertools.takewhile(lambda balance: balance &gt; 0, balances)</p>
<p>for i, balance in enumerate(amortization_schedule): print(f”Month {i+1}: {balance:,.2f}“)</p>
<p># Note: A proper amortization schedule would have a final smaller payment. # This example is to demonstrate the power of itertools. ```</p>
<p>::: {.cell-output .cell-output-stdout} <code>Month          1: 1,000.00   Month          2: 960.00   Month          3: 919.60   Month          4: 878.80   Month          5: 837.58   Month          6: 795.96   Month          7: 753.92   Month          8: 711.46   Month          9: 668.57   Month          10: 625.26   Month          11: 581.51   Month          12: 537.33   Month          13: 492.70   Month          14: 447.63   Month          15: 402.10   Month          16: 356.12   Month          17: 309.69   Month          18: 262.78   Month          19: 215.41   Month          20: 167.56   Month          21: 119.24   Month          22: 70.43   Month          23: 21.14</code> ::: :::</p></li>
<li><p><strong><code>itertools.pairwise(iterable)</code></strong>: As we’ve seen, this is ideal for working with consecutive items in a sequence. Calculating year fractions for a swap leg is a prime example.</p>
<p>::: {#62b2cb03 .cell execution_count=12} ``` {.python .cell-code} import itertools from datetime import date</p>
<p>payment_dates = [date(2025, 1, 15), date(2025, 7, 15), date(2026, 1, 15)] def year_fraction(start, end): return (end - start).days / 365.25</p>
<p>for start, end in itertools.pairwise(payment_dates): yf = year_fraction(start, end) print(f”Period: {start} to {end}, Year Fraction: {yf:.4f}“) ```</p>
<p>::: {.cell-output .cell-output-stdout} <code>Period: 2025-01-15 to 2025-07-15, Year Fraction: 0.4956   Period: 2025-07-15 to 2026-01-15, Year Fraction: 0.5038</code> ::: :::</p></li>
<li><p><strong><code>itertools.cycle(iterable)</code></strong>: Repeats a sequence indefinitely. This can be used to cycle through a set of risk scenarios or apply a repeating pattern of market data shocks.</p>
<p>::: {#9ff90afe .cell execution_count=13} <code>{.python .cell-code}   import itertools   scenarios = itertools.cycle(['Base', 'Rate Up', 'Rate Down'])   for _ in range(5):       print(f"Running scenario: {next(scenarios)}")</code></p>
<p>::: {.cell-output .cell-output-stdout} <code>Running scenario: Base   Running scenario: Rate Up   Running scenario: Rate Down   Running scenario: Base   Running scenario: Rate Up</code> ::: :::</p></li>
</ul>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Understanding the difference between being “eager” (grabbing everything at once) and “lazy” (grabbing only what you need) is one of those leveling-up moments in Python. By leaning on iterators, generators, and the <code>itertools</code> library, you can write code that’s not just more efficient, but also much cleaner and easier to reason about.</p>
<p>The iterator protocol (<code>__iter__</code> and <code>__next__</code>) we covered here is actually our first taste of Python’s data model — a topic we’ll dig into after covering <a href="../25-12-04-python-academy-class-anatomy/">class anatomy</a>.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>The complete Python script with all the examples from this post is available for download and experimentation. You can get it here: <a href="../../../assets/python/efficient_iteration_and_generators_patterns.py">efficient_iteration_and_generators_patterns.py</a>.</p>
</div>
</div>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Python Academy</category>
  <guid>https://bwrob.github.io/teaching/2025-python-academy/25-11-05-python-academy-iteration/</guid>
  <pubDate>Wed, 05 Nov 2025 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/teaching/2025-python-academy/25-11-05-python-academy-iteration/cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Functions, Closures and Decorators</title>
  <link>https://bwrob.github.io/teaching/2025-python-academy/25-10-23-python-academy-functions-closures-decorators/</link>
  <description><![CDATA[ 






<p>In Python, functions are a lot more flexible than you might think. We’re going to dive into what makes them “first-class citizens” and how that lets us do some really cool things with closures and decorators. If you’ve ever wondered how that <code>@something</code> syntax works, you’re in the right place.</p>
<section id="functions" class="level2">
<h2 class="anchored" data-anchor-id="functions">Functions</h2>
<p>In Python, functions are “first-class citizens”. This just means you can treat them like any other variable. You can:</p>
<ul>
<li>assign them to variables,</li>
<li>pass them as arguments to other functions,</li>
<li>return them from functions.</li>
</ul>
<p>This “functional programming” trait of Python is a core for some powerful patterns that wouldn’t work in some other (purely OOP) languages.</p>
<p>Let’s use a function from our previous post on Fibonacci numbers to see this in action.</p>
<div id="7e8485c4" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fibonacci_iterative(n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb1-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using an iterative approach."""</span></span>
<span id="cb1-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb1-4">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fibonacci is not defined for negative numbers."</span>)</span>
<span id="cb1-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="cb1-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n</span>
<span id="cb1-7"></span>
<span id="cb1-8">    a, b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb1-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>):</span>
<span id="cb1-10">        a, b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> b, a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> b</span>
<span id="cb1-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> b</span></code></pre></div></div>
</details>
</div>
<p>Because functions are objects, they come with some handy attributes. For instance, you can get the docstring with <code>__doc__</code> and the function’s name with <code>__name__</code>.</p>
<div id="6aa04a93" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(fibonacci_iterative.__doc__)</span>
<span id="cb2-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(fibonacci_iterative.<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Calculate the nth Fibonacci number using an iterative approach.
fibonacci_iterative</code></pre>
</div>
</div>
<p>And just like other objects, functions inherit from the <code>object</code> base class.</p>
<div id="de81a5f4" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(fibonacci_iterative, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">object</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="3">
<pre><code>True</code></pre>
</div>
</div>
<p>Functions are more than callable blocks of code — and that flexibility is what makes closures and decorators possible.</p>
</section>
<section id="benchmarking-fibonacci-implementations" class="level2">
<h2 class="anchored" data-anchor-id="benchmarking-fibonacci-implementations">Benchmarking Fibonacci Implementations</h2>
<p>To really drive home the point that functions are first-class citizens, let’s put a few of our Fibonacci functions into a list and pass them to a benchmarking function. This function will test each one and see how they perform.</p>
<div id="5d54f3f1" class="cell" data-execution_count="4">
<details class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fibonacci_iterative(n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb6-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using an iterative approach."""</span></span>
<span id="cb6-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb6-4">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fibonacci is not defined for negative numbers."</span>)</span>
<span id="cb6-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="cb6-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n</span>
<span id="cb6-7"></span>
<span id="cb6-8">    a, b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb6-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>):</span>
<span id="cb6-10">        a, b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> b, a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> b</span>
<span id="cb6-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> b</span>
<span id="cb6-12"></span>
<span id="cb6-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fibonacci_recursive(n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb6-14">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using a recursive approach."""</span></span>
<span id="cb6-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb6-16">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fibonacci is not defined for negative numbers."</span>)</span>
<span id="cb6-17">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="cb6-18">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n</span>
<span id="cb6-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> fibonacci_recursive(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> fibonacci_recursive(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb6-20"></span>
<span id="cb6-21">FIBONACCI_CACHE: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb6-22"></span>
<span id="cb6-23"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fibonacci_recursive_cached(n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb6-24">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using recursion with memoization."""</span></span>
<span id="cb6-25">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb6-26">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fibonacci is not defined for negative numbers."</span>)</span>
<span id="cb6-27">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="cb6-28">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n</span>
<span id="cb6-29"></span>
<span id="cb6-30">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> FIBONACCI_CACHE:</span>
<span id="cb6-31">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> FIBONACCI_CACHE[n]</span>
<span id="cb6-32"></span>
<span id="cb6-33">    result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fibonacci_recursive_cached(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> fibonacci_recursive_cached(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb6-34"></span>
<span id="cb6-35">    FIBONACCI_CACHE[n] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> result</span>
<span id="cb6-36">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> result</span></code></pre></div></div>
</details>
</div>
<div id="d9bdf294" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> time</span>
<span id="cb7-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Callable</span>
<span id="cb7-3"></span>
<span id="cb7-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> benchmark(</span>
<span id="cb7-5">    functions: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[Callable[[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>], <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>]],</span>
<span id="cb7-6">    n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span></span>
<span id="cb7-7">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb7-8">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Benchmarks a list of functions."""</span></span>
<span id="cb7-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> func <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> functions:</span>
<span id="cb7-10">        start <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> time.perf_counter()</span>
<span id="cb7-11">        func(n)</span>
<span id="cb7-12">        end <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> time.perf_counter()</span>
<span id="cb7-13">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Function </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>func<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> took </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>end <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> start<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.6f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> seconds."</span>)</span>
<span id="cb7-14"></span>
<span id="cb7-15">fib_functions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [fibonacci_recursive, fibonacci_recursive_cached, fibonacci_iterative]</span>
<span id="cb7-16">benchmark(fib_functions, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Function fibonacci_recursive took 0.133286 seconds.
Function fibonacci_recursive_cached took 0.000015 seconds.
Function fibonacci_iterative took 0.000004 seconds.</code></pre>
</div>
</div>
</section>
<section id="closures" class="level2">
<h2 class="anchored" data-anchor-id="closures">Closures</h2>
<p>A closure is basically a function that remembers the environment in which it was created. Let’s use our <code>get_greeter</code> function to see what that means.</p>
<div id="0d91b7bc" class="cell" data-execution_count="6">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_greeter(greeting: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Callable[[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>],<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>]:</span>
<span id="cb9-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Returns a greeter function."""</span></span>
<span id="cb9-3"></span>
<span id="cb9-4">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> greeter(name: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>:</span>
<span id="cb9-5">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>greeting<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">!"</span></span>
<span id="cb9-6"></span>
<span id="cb9-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> greeter</span>
<span id="cb9-8"></span>
<span id="cb9-9">good_morning_greeter <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_greeter(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Good morning"</span>)</span>
<span id="cb9-10"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(good_morning_greeter(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"World"</span>))</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Good morning, World!</code></pre>
</div>
</div>
<p>When we call <code>get_greeter("Good morning")</code>, we get a new <code>greeter</code> function back. This new function, which we’ve assigned to <code>good_morning_greeter</code>, “remembers” that the <code>greeting</code> variable was “Good morning”.</p>
<p>This is what a closure does: it “closes over” the variables from the scope where it was created. So even though the <code>get_greeter</code> function has finished running, <code>good_morning_greeter</code> still has access to the <code>greeting</code> variable.</p>
<p>We can even peek inside the closure with the <code>__closure__</code> attribute, which shows us the variables it has captured.</p>
<div id="e620f5b0" class="cell" data-execution_count="7">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb11-1">good_morning_greeter.__closure__[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].cell_contents</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre><code>'Good morning'</code></pre>
</div>
</div>
<p>This shows that the value <code>"Good morning"</code> is tucked away in our <code>good_morning_greeter</code> function’s closure.</p>
<p>Closures are a key ingredient for decorators, which we’ll get to next. They also let us create “function factories” that can produce specialized functions.</p>
<p>For a more mathematical example, let’s create a function factory that builds a polynomial function from a tuple of coefficients.</p>
<p>A polynomial is defined as <img src="https://latex.codecogs.com/png.latex?P(x)%20=%20%5Csum_%7Bi=0%7D%5E%7Bn%7D%20a_i%20x%5Ei%20=%20a_n%20x%5En%20+%20a_%7Bn-1%7D%20x%5E%7Bn-1%7D%20+%20%5Cdots%20+%20a_1%20x%20+%20a_0">.</p>
<div id="bd9c6e9b" class="cell" data-execution_count="8">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-8" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-8-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> polynomial_factory(coefficients: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, ...]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Callable:</span>
<span id="annotated-cell-8-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="annotated-cell-8-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    A factory that creates a polynomial function from a tuple of coefficients.</span></span>
<span id="annotated-cell-8-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    The coefficients are ordered from the highest power to the lowest.</span></span>
<span id="annotated-cell-8-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="annotated-cell-8-6">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> polynomial(x: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="annotated-cell-8-7">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="annotated-cell-8-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        Evaluates the polynomial for a given x.</span></span>
<span id="annotated-cell-8-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="annotated-cell-8-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(c <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> i) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, c <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">reversed</span>(coefficients)))</span>
<span id="annotated-cell-8-11"></span>
<span id="annotated-cell-8-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> polynomial</span>
<span id="annotated-cell-8-13"></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-8" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-8-14" class="code-annotation-target">p1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> polynomial_factory((<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span>
<span id="annotated-cell-8-15"></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-8" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-8-16" class="code-annotation-target">p2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> polynomial_factory((<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>))</span>
<span id="annotated-cell-8-17"></span>
<span id="annotated-cell-8-18"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(p1(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span>
<span id="annotated-cell-8-19"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(p2(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-8" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-8" data-code-lines="14" data-code-annotation="1"><img src="https://latex.codecogs.com/png.latex?P(x)%20=%202x%5E2%20+%203x%20+%205"></span>
</dd>
<dt data-target-cell="annotated-cell-8" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-8" data-code-lines="16" data-code-annotation="2"><img src="https://latex.codecogs.com/png.latex?Q(x)%20=%20x%5E3%20-%208"></span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>70
117</code></pre>
</div>
</div>
<p>Here, <code>polynomial_factory</code> returns a new <code>polynomial</code> function. This new function’s closure captures the <code>coefficients</code> tuple. So, <code>p1</code> will always be the polynomial <img src="https://latex.codecogs.com/png.latex?2x%5E2%20+%203x%20+%205">, and <code>p2</code> will always be <img src="https://latex.codecogs.com/png.latex?x%5E3%20-%208">.</p>
</section>
<section id="decorators" class="level2">
<h2 class="anchored" data-anchor-id="decorators">Decorators</h2>
<p>Decorators are a neat way to add functionality to functions or classes without changing their code. Think of it as wrapping a function in another function to give it extra abilities.</p>
<p>In the last post, we used the <code>@cache</code> decorator to speed up our recursive Fibonacci function. Let’s try to build a simple version of that decorator ourselves.</p>
<div id="67222427" class="cell" data-execution_count="9">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-9" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><a class="code-annotation-anchor" data-target-cell="annotated-cell-9" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-9-1" class="code-annotation-target"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> my_cache(func: Callable) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Callable:</span>
<span id="annotated-cell-9-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""A simple cache decorator."""</span></span>
<span id="annotated-cell-9-3">    _cache <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="annotated-cell-9-4"></span>
<span id="annotated-cell-9-5">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> wrapper(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args):</span>
<span id="annotated-cell-9-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> args <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> _cache:</span>
<span id="annotated-cell-9-7">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> _cache[args]</span>
<span id="annotated-cell-9-8"></span>
<span id="annotated-cell-9-9">        result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> func(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args)</span>
<span id="annotated-cell-9-10">        _cache[args] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> result</span>
<span id="annotated-cell-9-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> result</span>
<span id="annotated-cell-9-12"></span>
<span id="annotated-cell-9-13">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> wrapper</span>
<span id="annotated-cell-9-14"></span>
<span id="annotated-cell-9-15"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@my_cache</span></span>
<span id="annotated-cell-9-16"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fibonacci_cached_by_me(n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="annotated-cell-9-17">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using recursion with our own cache decorator."""</span></span>
<span id="annotated-cell-9-18">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="annotated-cell-9-19">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fibonacci is not defined for negative numbers."</span>)</span>
<span id="annotated-cell-9-20">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="annotated-cell-9-21">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n</span>
<span id="annotated-cell-9-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> fibonacci_cached_by_me(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> fibonacci_cached_by_me(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="annotated-cell-9-23"></span>
<span id="annotated-cell-9-24">fibonacci_cached_by_me(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-9" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-9" data-code-lines="1" data-code-annotation="1">This is a cleaner way of writing <code>fibonacci_cached_by_me = my_cache(fibonacci_cached_by_me)</code>. A decorator is just a function that takes another function as input and returns a modified function.</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-display" data-execution_count="9">
<pre><code>832040</code></pre>
</div>
</div>
<p>Decorators can also take arguments. To do this, we create a “decorator factory” - a function that returns a decorator. Here’s one that repeats a function call a few times.</p>
<div id="2d36fa17" class="cell" data-execution_count="10">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-10" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-10-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> repeat(times: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Callable:</span>
<span id="annotated-cell-10-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""A decorator that repeats a function call a given number of times."""</span></span>
<span id="annotated-cell-10-3"></span>
<span id="annotated-cell-10-4">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> decorator(func: Callable) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Callable:</span>
<span id="annotated-cell-10-5">        <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> wrapper(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs):</span>
<span id="annotated-cell-10-6">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(times):</span>
<span id="annotated-cell-10-7">                result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> func(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)</span>
<span id="annotated-cell-10-8">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> result</span>
<span id="annotated-cell-10-9"></span>
<span id="annotated-cell-10-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> wrapper</span>
<span id="annotated-cell-10-11"></span>
<span id="annotated-cell-10-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> decorator</span>
<span id="annotated-cell-10-13"></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-10" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-10-14" class="code-annotation-target"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@repeat</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="annotated-cell-10-15"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> say_hello(name: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="annotated-cell-10-16">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Hello, </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">!"</span>)</span>
<span id="annotated-cell-10-17"></span>
<span id="annotated-cell-10-18">say_hello(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"World"</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-10" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-10" data-code-lines="14" data-code-annotation="1">the same as writing <code>say_hello = repeat(3)(say_hello)</code>.</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>Hello, World!
Hello, World!
Hello, World!</code></pre>
</div>
</div>
<p>Decorators show up everywhere — Flask uses them for routing, <code>pytest</code> for fixtures. In the <a href="../25-11-05-python-academy-iteration/">next post</a>, we’ll use one to profile memory usage of iterators and generators.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Download the whole code <a href="../../../assets/python/python_functions_closures_and_decorators_explained.py">here</a>.</p>
</div>
</div>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Python Academy</category>
  <guid>https://bwrob.github.io/teaching/2025-python-academy/25-10-23-python-academy-functions-closures-decorators/</guid>
  <pubDate>Thu, 23 Oct 2025 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/teaching/2025-python-academy/25-10-23-python-academy-functions-closures-decorators/cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Fibonacci Numbers Case Study</title>
  <link>https://bwrob.github.io/teaching/2025-python-academy/25-10-12-python-academy-fibonacci/</link>
  <description><![CDATA[ 






<p>Fibonacci numbers are a classic interview question and a great way to talk about optimization. In this post, we’re going to see how many different ways there are to solve the same problem in Python—from the “obvious” way that’s painfully slow, to a few clever tricks that make it fast.</p>
<section id="naive-recursive-approach" class="level2">
<h2 class="anchored" data-anchor-id="naive-recursive-approach">Naive Recursive Approach</h2>
<p>The Fibonacci sequence is defined by the recurrence relation: <img src="https://latex.codecogs.com/png.latex?F_n%20=%20F_%7Bn-1%7D%20+%20F_%7Bn-2%7D"> with seed values <img src="https://latex.codecogs.com/png.latex?F_0=0"> and <img src="https://latex.codecogs.com/png.latex?F_1=1">.</p>
<p>A naive implementation of this in Python is a direct translation of the mathematical formula:</p>
<div id="fcb82a6b" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fibonacci_recursive(n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb1-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using a recursive approach."""</span></span>
<span id="cb1-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb1-4">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fibonacci is not defined for negative numbers."</span>)</span>
<span id="cb1-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="cb1-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n</span>
<span id="cb1-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> fibonacci_recursive(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> fibonacci_recursive(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div></div>
</details>
</div>
<p>This approach is very intuitive, but it is also very slow. For <code>n=40</code>, it already takes a noticeable amount of time to compute. The reason for this is that the function calls itself twice for each <code>n</code>, leading to an exponential growth of the call stack.</p>
<div id="d3a1bbbc" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> time <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> perf_counter</span>
<span id="cb2-2"></span>
<span id="cb2-3">start <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> perf_counter()</span>
<span id="cb2-4">_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fibonacci_recursive(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>)</span>
<span id="cb2-5">end <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> perf_counter()</span>
<span id="cb2-6"></span>
<span id="cb2-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Execution taken </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>end <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> start<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> seconds"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Execution taken 15.75 seconds</code></pre>
</div>
</div>
</section>
<section id="visualizing-the-call-stack" class="level2">
<h2 class="anchored" data-anchor-id="visualizing-the-call-stack">Visualizing the Call Stack</h2>
<p>To better understand the problem, let’s visualize the call stack. We can create a “talkative” version of our function that logs every call.</p>
<div id="ba1713b4" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> rich.console <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Console</span>
<span id="cb4-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> rich.tree <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Tree</span>
<span id="cb4-3"></span>
<span id="cb4-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fibonacci_recursive_talkative(n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb4-5">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using a recursive approach."""</span></span>
<span id="cb4-6">    tree <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Tree(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"fibonacci_recursive_talkative(</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">)"</span>)</span>
<span id="cb4-7"></span>
<span id="cb4-8">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> worker(n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, tree: Tree) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb4-9">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using a recursive approach."""</span></span>
<span id="cb4-10">        node <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tree.add(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"fibonacci_recursive(</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">) called"</span>)</span>
<span id="cb4-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb4-12">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fibonacci is not defined for negative numbers."</span>)</span>
<span id="cb4-13">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="cb4-14">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n</span>
<span id="cb4-15">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> worker(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, node) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> worker(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, node)</span>
<span id="cb4-16"></span>
<span id="cb4-17">    result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> worker(n, tree)</span>
<span id="cb4-18">    Console().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(tree)</span>
<span id="cb4-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> result</span></code></pre></div></div>
</details>
</div>
<p>For <code>n=6</code>, the call tree looks like this:</p>
<div id="9f81e22e" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb5-1">_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fibonacci_recursive_talkative(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-display">
<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace">fibonacci_recursive_talkative(6)
└── fibonacci_recursive(6) called
    ├── fibonacci_recursive(5) called
    │   ├── fibonacci_recursive(4) called
    │   │   ├── fibonacci_recursive(3) called
    │   │   │   ├── fibonacci_recursive(2) called
    │   │   │   │   ├── fibonacci_recursive(1) called
    │   │   │   │   └── fibonacci_recursive(0) called
    │   │   │   └── fibonacci_recursive(1) called
    │   │   └── fibonacci_recursive(2) called
    │   │       ├── fibonacci_recursive(1) called
    │   │       └── fibonacci_recursive(0) called
    │   └── fibonacci_recursive(3) called
    │       ├── fibonacci_recursive(2) called
    │       │   ├── fibonacci_recursive(1) called
    │       │   └── fibonacci_recursive(0) called
    │       └── fibonacci_recursive(1) called
    └── fibonacci_recursive(4) called
        ├── fibonacci_recursive(3) called
        │   ├── fibonacci_recursive(2) called
        │   │   ├── fibonacci_recursive(1) called
        │   │   └── fibonacci_recursive(0) called
        │   └── fibonacci_recursive(1) called
        └── fibonacci_recursive(2) called
            ├── fibonacci_recursive(1) called
            └── fibonacci_recursive(0) called
</pre>
</div>
</div>
<p>As you can see, many values are calculated multiple times. For example, <code>fibonacci_recursive(4)</code> is calculated twice, <code>fibonacci_recursive(3)</code> is calculated three times, and so on. This is the reason for the inefficiency.</p>
</section>
<section id="memoization" class="level2">
<h2 class="anchored" data-anchor-id="memoization">Memoization</h2>
<p>We can improve the performance by storing the results of the function calls in a cache (a dictionary). This technique is called memoization.</p>
<div id="1d09262a" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb6-1">FIBONACCI_CACHE: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb6-2"></span>
<span id="cb6-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fibonacci_recursive_cached(n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb6-4">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using recursion with memoization."""</span></span>
<span id="cb6-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb6-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fibonacci is not defined for negative numbers."</span>)</span>
<span id="cb6-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="cb6-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n</span>
<span id="cb6-9"></span>
<span id="cb6-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> FIBONACCI_CACHE:</span>
<span id="cb6-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> FIBONACCI_CACHE[n]</span>
<span id="cb6-12"></span>
<span id="cb6-13">    result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fibonacci_recursive_cached(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> fibonacci_recursive_cached(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb6-14"></span>
<span id="cb6-15">    FIBONACCI_CACHE[n] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> result</span>
<span id="cb6-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> result</span></code></pre></div></div>
</details>
</div>
<p>This version is much faster. However, it will fail for large <code>n</code> (e.g., <code>n=8_000</code>) because of Python’s recursion depth limit.</p>
<div id="232dfd84" class="cell" data-execution_count="6">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb7-2">    fibonacci_recursive_cached(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8_000</span>)</span>
<span id="cb7-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">RecursionError</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> e:</span>
<span id="cb7-4">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(e)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>maximum recursion depth exceeded</code></pre>
</div>
</div>
</section>
<section id="decorators-for-caching" class="level2">
<h2 class="anchored" data-anchor-id="decorators-for-caching">Decorators for Caching</h2>
<p>A more elegant way to implement memoization is by using a decorator. A decorator is a function that takes another function and extends its behavior without explicitly modifying it. Python’s <code>functools</code> module provides a built-in decorator <code>lru_cache</code> that does exactly what we need.</p>
<div id="76342303" class="cell" data-execution_count="7">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> functools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> cache</span>
<span id="cb9-2"></span>
<span id="cb9-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@cache</span></span>
<span id="cb9-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fibonacci_recursive_cached_decorator(n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb9-5">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using recursion with memoization."""</span></span>
<span id="cb9-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb9-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fibonacci is not defined for negative numbers."</span>)</span>
<span id="cb9-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="cb9-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n</span>
<span id="cb9-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> fibonacci_recursive_cached_decorator(</span>
<span id="cb9-11">        n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb9-12">    ) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> fibonacci_recursive_cached_decorator(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div></div>
</details>
</div>
<p>This is the most concise and Pythonic way to write a cached recursive Fibonacci function.</p>
</section>
<section id="iterative-approach" class="level2">
<h2 class="anchored" data-anchor-id="iterative-approach">Iterative Approach</h2>
<p>Another way to solve the problem is to use an iterative approach. This is equivalent to tail recursion optimization.</p>
<div id="f964a19c" class="cell" data-execution_count="8">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fibonacci_iterative(n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb10-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using an iterative approach."""</span></span>
<span id="cb10-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb10-4">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fibonacci is not defined for negative numbers."</span>)</span>
<span id="cb10-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="cb10-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n</span>
<span id="cb10-7"></span>
<span id="cb10-8">    a, b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb10-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>):</span>
<span id="cb10-10">        a, b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> b, a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> b</span>
<span id="cb10-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> b</span></code></pre></div></div>
</details>
</div>
<p>This is the most efficient way (we’ll see) to calculate Fibonacci numbers in Python. It has a linear time complexity and constant space complexity.</p>
</section>
<section id="performance-comparison" class="level2">
<h2 class="anchored" data-anchor-id="performance-comparison">Performance Comparison</h2>
<p>To compare the performance of these implementations, we can use the <code>perfplot</code> library. It allows us to easily benchmark different functions over a range of input sizes.</p>
<div id="6c2bf773" class="cell" data-execution_count="9">
<details class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-9" style="background: #f1f3f5;"><pre class="sourceCode numberSource python code-annotation-code number-lines code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-9-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numba</span>
<span id="annotated-cell-9-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> perfplot</span>
<span id="annotated-cell-9-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="annotated-cell-9-4"></span>
<span id="annotated-cell-9-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fibonacci_internal_cached_decorator(n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="annotated-cell-9-6">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using recursion with memoization.</span></span>
<span id="annotated-cell-9-7"></span>
<span id="annotated-cell-9-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    This version uses an internal helper function decorated with @cache.</span></span>
<span id="annotated-cell-9-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    This forces the cache to be local to this function.</span></span>
<span id="annotated-cell-9-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="annotated-cell-9-11"></span>
<span id="annotated-cell-9-12">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@cache</span></span>
<span id="annotated-cell-9-13">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> helper(n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="annotated-cell-9-14">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using recursion with memoization."""</span></span>
<span id="annotated-cell-9-15">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="annotated-cell-9-16">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fibonacci is not defined for negative numbers."</span>)</span>
<span id="annotated-cell-9-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="annotated-cell-9-18">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> n</span>
<span id="annotated-cell-9-19">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> helper(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> helper(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="annotated-cell-9-20"></span>
<span id="annotated-cell-9-21">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> helper(n)</span>
<span id="annotated-cell-9-22"></span>
<span id="annotated-cell-9-23">fibonacci_iterative_jit <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> numba.njit(fibonacci_iterative)</span>
<span id="annotated-cell-9-24"></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-9" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-9-25" class="code-annotation-target">_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fibonacci_iterative_jit(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)</span>
<span id="annotated-cell-9-26"></span>
<span id="annotated-cell-9-27"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fibonacci_linalg_numpy(n):</span>
<span id="annotated-cell-9-28">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate the nth Fibonacci number using matrix exponentiation with NumPy."""</span></span>
<span id="annotated-cell-9-29"></span>
<span id="annotated-cell-9-30">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="annotated-cell-9-31">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="annotated-cell-9-32">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:</span>
<span id="annotated-cell-9-33">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="annotated-cell-9-34"></span>
<span id="annotated-cell-9-35">    Q <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array([[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]], dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>np.uint64)</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-9" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-9-36" class="code-annotation-target">    result_matrix <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.linalg.matrix_power(Q, n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="annotated-cell-9-37">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> result_matrix[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-9" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-9" data-code-lines="25" data-code-annotation="1">Force compilation</span>
</dd>
<dt data-target-cell="annotated-cell-9" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-9" data-code-lines="36" data-code-annotation="2">This is the line that cannot be compiled by Numba in nopython mode</span>
</dd>
</dl>
</div>
</div>
<div id="cb3425a7" class="cell" data-execution_count="10">
<details class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb11-1">perfplot.show(</span>
<span id="cb11-2">    setup<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> n: n,</span>
<span id="cb11-3">    kernels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb11-4">        fibonacci_recursive,</span>
<span id="cb11-5">        fibonacci_internal_cached_decorator,</span>
<span id="cb11-6">        fibonacci_iterative,</span>
<span id="cb11-7">    ],</span>
<span id="cb11-8">    n_range<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>)],</span>
<span id="cb11-9">    xlabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n"</span>,</span>
<span id="cb11-10">    labels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb11-11">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"recursive"</span>,</span>
<span id="cb11-12">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"recursive cached"</span>,</span>
<span id="cb11-13">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"iterative"</span>,</span>
<span id="cb11-14">    ],</span>
<span id="cb11-15">    title<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Recursive vs cached vs iterative"</span>,</span>
<span id="cb11-16">    show_progress<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>,</span>
<span id="cb11-17">    equality_check<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>,</span>
<span id="cb11-18">    logx<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>,</span>
<span id="cb11-19">    logy<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb11-20">)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-display">
<script type="application/vnd.jupyter.widget-view+json">
{"model_id":"d5310aa937024f9b917c04d2e27908cd","version_major":2,"version_minor":0,"quarto_mimetype":"application/vnd.jupyter.widget-view+json"}
</script>
</div>
<div class="cell-output cell-output-display">
<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><a href="index_files/figure-html/cell-11-output-3.png" class="lightbox" data-gallery="quarto-lightbox-gallery-1"><img src="https://bwrob.github.io/teaching/2025-python-academy/25-10-12-python-academy-fibonacci/index_files/figure-html/cell-11-output-3.png" width="824" height="527" class="figure-img"></a></p>
</figure>
</div>
</div>
</div>
<p>There are more advanced techniques and algorithms to compute Fibonacci numbers, below is a sneak peek for the future at two more efficient methods: using Numba’s JIT compilation and matrix exponentiation with NumPy.</p>
<div id="6e296b78" class="cell" data-execution_count="11">
<details class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb12-1">perfplot.show(</span>
<span id="cb12-2">    setup<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> n: n,</span>
<span id="cb12-3">    kernels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb12-4">        fibonacci_iterative,</span>
<span id="cb12-5">        fibonacci_iterative_jit,</span>
<span id="cb12-6">        fibonacci_linalg_numpy,</span>
<span id="cb12-7">    ],</span>
<span id="cb12-8">    n_range<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)],</span>
<span id="cb12-9">    xlabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n"</span>,</span>
<span id="cb12-10">    labels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb12-11">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"iterative (native)"</span>,</span>
<span id="cb12-12">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"iterative (numba jit)"</span>,</span>
<span id="cb12-13">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"matrix (numpy linalg)"</span>,</span>
<span id="cb12-14">    ],</span>
<span id="cb12-15">    equality_check<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>,</span>
<span id="cb12-16">    show_progress<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>,</span>
<span id="cb12-17">    logx<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>,</span>
<span id="cb12-18">    logy<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb12-19">)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-display">
<script type="application/vnd.jupyter.widget-view+json">
{"model_id":"e1e1de21b9584a7bb8f36ad02a8b86f0","version_major":2,"version_minor":0,"quarto_mimetype":"application/vnd.jupyter.widget-view+json"}
</script>
</div>
<div class="cell-output cell-output-display">
<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><a href="index_files/figure-html/cell-12-output-3.png" class="lightbox" data-gallery="quarto-lightbox-gallery-2"><img src="https://bwrob.github.io/teaching/2025-python-academy/25-10-12-python-academy-fibonacci/index_files/figure-html/cell-12-output-3.png" width="866" height="475" class="figure-img"></a></p>
</figure>
</div>
</div>
</div>
<p>In the <a href="../25-10-23-python-academy-functions-closures-decorators/">next post</a>, we’ll use these Fibonacci implementations to explore first-class functions, closures, and decorators.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Download the whole code <a href="../../../assets/python/fibonacci_optimization_and_memoization_case_study.py">here</a>.</p>
</div>
</div>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Python Academy</category>
  <guid>https://bwrob.github.io/teaching/2025-python-academy/25-10-12-python-academy-fibonacci/</guid>
  <pubDate>Sun, 12 Oct 2025 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/teaching/2025-python-academy/25-10-12-python-academy-fibonacci/cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Python Resources</title>
  <link>https://bwrob.github.io/posts/25-07-06-python-resources/</link>
  <description><![CDATA[ 






<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/logo/python_mug.png" class="lightbox" data-gallery="quarto-lightbox-gallery-1"><img src="https://bwrob.github.io/assets/logo/python_mug.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:95.0%"></a></p>
</figure>
</div>
<p>A constantly updated list of resources to improve your Python skills.</p>
<section id="books" class="level2">
<h2 class="anchored" data-anchor-id="books">Books</h2>
<ul>
<li><a href="https://www.oreilly.com/library/view/fluent-python-2nd/9781492056348/">Fluent Python</a> by Luciano Ramalho</li>
<li><a href="https://www.oreilly.com/library/view/high-performance-python/9781098165956/">High Performance Python</a> by Micha Gorelick and Ian Ozsvald</li>
<li><a href="https://realpython.com/products/cpython-internals-book/">CPython Internals</a> by Anthony Shaw</li>
</ul>
</section>
<section id="youtube" class="level2">
<h2 class="anchored" data-anchor-id="youtube">YouTube</h2>
<section id="channels" class="level3">
<h3 class="anchored" data-anchor-id="channels">Channels</h3>
<ul>
<li><a href="https://www.youtube.com/@mCoding">mCoding</a></li>
<li><a href="https://www.youtube.com/arjancodes">ArjanCodes</a></li>
</ul>
</section>
<section id="videos" class="level3">
<h3 class="anchored" data-anchor-id="videos">Videos</h3>
<ul>
<li><a href="https://www.youtube.com/watch?v=Qhkskqxe4Wk">Why Numpy Is Better Than ALL Your Code</a></li>
</ul>
</section>
</section>
<section id="blogs-and-websites" class="level2">
<h2 class="anchored" data-anchor-id="blogs-and-websites">Blogs and Websites</h2>
<ul>
<li><a href="https://realpython.com/">Real Python</a></li>
<li><a href="https://www.ntietz.com/blog/">nietz</a></li>
<li><a href="https://blog.glyph.im/">Deciphering Glyph</a></li>
<li><a href="https://www.pythonweekly.com/">Python Weekly</a></li>
</ul>
</section>
<section id="articles" class="level2">
<h2 class="anchored" data-anchor-id="articles">Articles</h2>
<section id="design-patterns" class="level3">
<h3 class="anchored" data-anchor-id="design-patterns">Design Patterns</h3>
<ul>
<li><a href="https://blog.glyph.im/2025/04/stop-writing-init-methods.html">Stop Writing <strong>init</strong> Methods</a></li>
<li><a href="https://blog.glyph.im/2025/01/active-enum.html">The “Active Enum” Pattern</a></li>
</ul>
</section>
<section id="python-internals" class="level3">
<h3 class="anchored" data-anchor-id="python-internals">Python Internals</h3>
<ul>
<li><a href="https://savannah.dev/posts/how-your-code-runs-in-a-jit-build/">How JIT builds of CPython actually work</a></li>
</ul>


</section>
</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Pythonic Distractions</category>
  <guid>https://bwrob.github.io/posts/25-07-06-python-resources/</guid>
  <pubDate>Sun, 06 Jul 2025 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/assets/logo/python_mug.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>Risk Management of Merger Arbitrage Portfolios</title>
  <link>https://bwrob.github.io/posts/25-07-04-merger-arb-risk-management/</link>
  <description><![CDATA[ 






<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/25-07-04-merger-arb-risk-management/merger_arb.webp" class="lightbox" data-gallery="quarto-lightbox-gallery-1"><img src="https://bwrob.github.io/assets/images/posts/25-07-04-merger-arb-risk-management/merger_arb.webp" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:95.0%"></a></p>
</figure>
</div>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>This post is a reprint of my graduate thesis for postgraduate studies in Investment Banking at the Warsaw School of Economics.</p>
</div>
</div>
<section id="merger-arbitrage" class="level2">
<h2 class="anchored" data-anchor-id="merger-arbitrage">Merger Arbitrage</h2>
<p>Financial markets are where different participants interact through trading. The two primary things being traded are capital and risk. Capital is the money exchanged for the expectation of a future return, while risk is the uncertainty associated with that return.</p>
<section id="arbitrageurs-in-financial-markets" class="level3">
<h3 class="anchored" data-anchor-id="arbitrageurs-in-financial-markets">Arbitrageurs in Financial Markets</h3>
<p>Market participants can be categorized based on their motivations for engaging in markets:</p>
<ul>
<li><p><em>Speculators</em> – They are willing to assume risk with the goal of generating a profit. They adopt a positional view on the assets and instruments they acquire or sell. This category includes everyone from specialized investment funds to individual investors saving for retirement.</p></li>
<li><p><em>Hedgers</em> – Their aim is to mitigate their existing risk exposure. They may be consumers or producers of the underlying asset, or speculators seeking to adjust their risk profile.</p></li>
<li><p><em>Market makers</em> – They provide liquidity, profiting from the bid-ask spread, deal premiums, fees, and commissions.</p></li>
<li><p><em>Arbitrageurs</em> – They aim to capitalize on price discrepancies between different markets or instruments. They do not have a positional view on the market but try to identify and exploit inefficiencies in the market.</p></li>
</ul>
<p>Among these four groups, arbitrageurs are arguably the most sophisticated market participants. The <em>efficient market hypothesis</em> assumes that market prices reflect all available information. However, markets are not always perfectly efficient. Temporary inefficiencies can occur due to things like information asymmetry, transaction costs, or behavioral biases. Arbitrageurs seek to exploit these inefficiencies to generate a profit. This is typically achieved by simultaneously buying and selling related assets in different markets or instruments, to profit from the price differences.</p>
</section>
<section id="mergers-and-acquisitions" class="level3">
<h3 class="anchored" data-anchor-id="mergers-and-acquisitions">Mergers and Acquisitions</h3>
<p>Mergers and acquisitions (M&amp;A) is a general term that refers to the consolidation of companies or assets through various types of financial transactions. A merger is a term used to describe the combination of two companies into a single entity, while an acquisition refers to the purchase of one company by another. The motive for both is that consolidation would create synergies, which would lead to increased efficiency and profitability. This includes:</p>
<ul>
<li><p><strong>Increased market share</strong> – Companies increase their market share and gain a competitive advantage.</p></li>
<li><p><strong>Economies of scale</strong> – Larger companies can achieve economies of scale, reducing costs and increasing profitability.</p></li>
<li><p><strong>Diversification</strong> – Companies can diversify their product lines and reduce risk by entering new markets.</p></li>
<li><p><strong>Horizontal integration</strong> – Companies acquire players upstream or downstream in the supply chain, increasing their control over the production process.</p></li>
<li><p><strong>Access to new technology</strong> – Companies can acquire new technology or intellectual property, enhancing their competitive position.</p></li>
</ul>
</section>
<section id="sec:merger_arbitrage" class="level3">
<h3 class="anchored" data-anchor-id="sec:merger_arbitrage">Merger Arbitrage</h3>
<p>Merger arbitrage is an investment strategy that involves trading in the stocks of companies involved in mergers and acquisitions (M&amp;A). There are two main types of M&amp;A transactions – <em>cash offers</em> and <em>stock (or share-for-share) offers</em>. The basic investment premise of an arbitrageur in each of those can follow these hypothetical scenarios:</p>
<ul>
<li><p><strong>Cash offer</strong> – Company <img src="https://latex.codecogs.com/png.latex?A">, the <em>buyer</em>, announces an acquisition of company <img src="https://latex.codecogs.com/png.latex?B">, the <em>target</em>, for a cash payment of <img src="https://latex.codecogs.com/png.latex?30$%20per%0Ashare.%20The%20last%20trading%20price%20of%20company%20$B$%20was%20">20$. After the announcement, the price of company <img src="https://latex.codecogs.com/png.latex?B"> rises to <img src="https://latex.codecogs.com/png.latex?28$.%20There%20is%0Astill%20a%20">2$ <em>spread</em> between the current price and the acquisition price. This represents the risk that the acquisition may not be completed. Merger-arbitrage traders will buy shares of company <img src="https://latex.codecogs.com/png.latex?B"> at <img src="https://latex.codecogs.com/png.latex?28$%20and%20wait%20for%20the%20acquisition%20to%20be%20completed.%20They%20would%0Apocket%20the%20">2$ spread if the acquisition is successful.</p></li>
<li><p><strong>Stock offer</strong> – Company <img src="https://latex.codecogs.com/png.latex?A"> announces an acquisition of company <img src="https://latex.codecogs.com/png.latex?B"> for a share-for-share exchange with a ratio of <img src="https://latex.codecogs.com/png.latex?0.25">. This means that <img src="https://latex.codecogs.com/png.latex?A"> is offering to exchange one of its shares for four shares of company <img src="https://latex.codecogs.com/png.latex?B">. The last trading price of company <img src="https://latex.codecogs.com/png.latex?B"> was <img src="https://latex.codecogs.com/png.latex?15%25"> of the price of company <img src="https://latex.codecogs.com/png.latex?A">. After the announcement, the price of company <img src="https://latex.codecogs.com/png.latex?B"> rises to <img src="https://latex.codecogs.com/png.latex?22%25"> of the price of company <img src="https://latex.codecogs.com/png.latex?A">. Merger-arbitrage traders will buy shares of company <img src="https://latex.codecogs.com/png.latex?B"> at <img src="https://latex.codecogs.com/png.latex?22%25"> of the price of company <img src="https://latex.codecogs.com/png.latex?A"> and at the same time short a quarter of the equivalent amount of shares of company <img src="https://latex.codecogs.com/png.latex?A">. They would pocket the <img src="https://latex.codecogs.com/png.latex?3%25"> spread if the acquisition is successful.</p></li>
</ul>
<p>Merger arbitrage is a popular strategy among hedge funds and institutional investors, as it can provide attractive risk-adjusted returns. It hinges on the investor’s ability to accurately assess the likelihood of a merger or acquisition being completed successfully. This requires a deep understanding of the regulatory environment, the motivations of the companies involved, and the potential impact on their stock prices. Institutional arbitrageurs, like hedge funds, are often present in the courtroom during the merger process. They analyze the legal documents, financial statements, attend hearings, and compare the particular merger with similar transactions in the past. F</p>
</section>
<section id="sec:merger_arbitrage_risk_and_return" class="level3">
<h3 class="anchored" data-anchor-id="sec:merger_arbitrage_risk_and_return">Risk and Return</h3>
<p>The main components crucial for evaluating an investment are:</p>
<ul>
<li><p><strong>Expected return</strong> – The expected return is the average return that an investor can expect to earn from an investment over a specific period of time.</p></li>
<li><p><strong>Time horizon</strong> – The time horizon is the period of time over which an investor expects to hold an investment before selling it.</p></li>
<li><p><strong>Risk</strong> – Risk is the uncertainty associated with the expected return of an investment, often measured by the standard deviation of the returns.</p></li>
</ul>
<p>After a merger announcement, the volatility of the target company decreases after the initial spike. Another way to think about it is that the portfolio of the arbitrageur is not a portfolio of stocks but a portfolio of merger spreads. The decreased risk and market neutrality make even a more modest return attractive.</p>
<p>The arbitrageur needs to be wary of the time horizon of the investment, as the merger may take a long time to be completed. In such a case, the spread they managed to capture may underperform the risk-free rate over that period. Historically, the average merger arbitrage spread has been around <img src="https://latex.codecogs.com/png.latex?5%25"> to <img src="https://latex.codecogs.com/png.latex?10%25"> per year, depending on market conditions and the specific deals involved. The source of this surplus return is explained by other sources of risk, as we’ll see in the next post.</p>
</section>
</section>
<section id="ch:risk_management" class="level2">
<h2 class="anchored" data-anchor-id="ch:risk_management">Risk Management</h2>
<p>Modern finance is built on the principle that risk can be quantified, analyzed, managed, and traded. The primary concepts employed in risk quantification are volatility and correlation. However, for merger arbitrage, these concepts and their related metrics from modern portfolio theory aren’t very useful. This is largely due to the relatively uncorrelated nature of the merger arbitrage strategy. The goal of pursuing such strategies is to generate alpha, which exhibits low correlation with broader market movements. While this can be a big advantage, especially when the market is unstable, it also creates unique risk management challenges.</p>
<section id="general-risk-management-metrics" class="level3">
<h3 class="anchored" data-anchor-id="general-risk-management-metrics">General Risk Management Metrics</h3>
<p>When a risk officer assesses a portfolio’s risk, they use a range of metrics. A key consideration is the portfolio’s target return, which directly influences the risk appetite, i.e., the amount of risk the portfolio manager is willing to assume. The most common risk metrics used in the industry include:</p>
<ul>
<li><p><strong>Sensitivities</strong> – These metrics measure how the value of a portfolio changes in response to changes in underlying factors. The most common sensitivities are the Greeks, which quantify the sensitivity of the portfolio value to changes in underlying asset prices, interest rates, and volatility. There are also more structured measures that involve multi-dimensional market objects, like DV01 (1 basis point parallel change in the yield curve) or CS01 (1 basis point parallel change in the credit spread curve).</p></li>
<li><p><strong>Variance-based measures</strong> – These metrics assess the risk of a portfolio by examining the statistics of its returns. Common variance-based measures include standard deviation and beta. Beta is a measure of correlation between the portfolio and the general market, typically materialized as a benchmark index such as the S&amp;P 500. Another important measure is the Sharpe ratio, which evaluates the risk-adjusted return of a portfolio. It is calculated as the excess return of the portfolio over the risk-free rate, divided by the standard deviation of the portfolio returns.</p></li>
<li><p><strong>Quantile-based measures</strong> – These metrics gauge the risk of a portfolio by analyzing the distribution of its returns. The most common quantile-based measures are Value at Risk (VaR) and Expected Shortfall (ES). VaR represents the maximum potential loss on a portfolio over a given time horizon with a specified confidence level. ES, also known as Conditional VaR, represents the expected loss conditional on the loss exceeding the VaR.</p></li>
<li><p><strong>Exposure limits</strong> – These constraints define the maximum amount of risk that can be assumed for a single position or within a particular market segment. Adhering to these limits is crucial for maintaining a diversified portfolio and preventing excessive concentration in any single position. This is typically expressed as the maximum potential loss that can be incurred.</p></li>
<li><p><strong>Liquidity measures</strong> – These metrics quantify the speed and ease with which a position can be entered or exited. Even the best investment prospects are worthless if they cannot be executed at a scale justifying research and infrastructure costs. On the other hand, if conditions turn unfavorable, a swift exit is crucial to limit losses. Examples of liquidity measures include trade volume and the time required to liquidate a position.</p></li>
<li><p><strong>Stress testing</strong> – This technique evaluates the risk of a portfolio by assessing its performance under extreme market conditions. The scenarios applied to the portfolio can be either synthetic (e.g., a <img src="https://latex.codecogs.com/png.latex?10%25"> drop in the S&amp;P 500, considering asset correlations) or historical (e.g., the 2008 financial crisis). Stress testing exercises are important for determining capital requirements and are often mandated by regulators. It involves analyzing not only the portfolio’s performance under the prescribed scenario but also the behavior of other risk metrics.</p></li>
</ul>
<p>Risk management for a portfolio depends heavily on its characteristics; there’s no one-size-fits-all approach. The selection of appropriate risk metrics depends on the portfolio manager’s risk appetite and the specific investment strategy. Strategies that are highly specialized, like arbitrage, may require a different set of risk metrics and special considerations to be taken into account.</p>
</section>
<section id="the-case-of-merger-arbitrage" class="level3">
<h3 class="anchored" data-anchor-id="the-case-of-merger-arbitrage">The Case of Merger Arbitrage</h3>
<p>Let’s look at the specifics of risk management for merger arbitrage portfolios.</p>
<p><em>Sensitivities</em> can be particularly important, especially when derivatives are used to leverage positions. However, standard derivative valuation models may not be suitable for stocks involved in M&amp;A transactions. This is evident in cash mergers, where the stock price is bounded by the cash offer price. Consequently, the Black-Scholes model’s assumption of a log-normal distribution of the stock price is violated. We will examine an alternative option pricing model better suited for stocks involved in M&amp;A in later sections.</p>
<p><em>Variance-based and quantile-based measures</em> have limited utility for merger arbitrage portfolios. A fundamental assumption underlying these metrics, which rely on statistical analysis of returns time series, is stationarity—the invariance of the statistical properties of the returns process. This assumption is crucial for historical approaches to estimating distribution-based metrics. However, a stock’s price dynamics change dramatically following a merger announcement, making it unreasonable to assume that its past behavior is predictive of future performance. This means that historically observed standard deviation, beta, and VaR are not reliable measures of risk for merger arbitrage portfolios.</p>
<p>A rigorous approach to <em>position limits</em> is essential for the successful execution of a merger arbitrage strategy. Taking on a large position in a single stock can be very risky, given the non-negligible probability of a deal’s failure. Therefore, portfolios should be diversified across a range of stocks and sectors. We discuss this in more detail in the next section.</p>
<p><em>Liquidity</em> and order book depth are crucial for merger arbitrage portfolios, as they can significantly impact the execution of trades. Usually, a merger offer includes a significant premium to the last trading price, which causes the stock price to jump up close to the offer price. This incentivizes long-term investors to sell their shares, as from their perspective, there is little upside in holding the stock. The arbitrageur, on the other hand, is interested in the spread between the offer price and the stock price – they provide liquidity to the sellers. Overall liquidity, trading volume, and bid-ask spread need to be monitored closely by the arbitrageur from this point onwards. If an event that endangers the merger occurs, there might not be enough buyers, and the arbitrageur may be unable to exit their position without incurring significant losses.</p>
<p>Special attention should be given to <em>stress testing</em> of merger arbitrage portfolios. The prices of stocks under merger offer revert to their historical correlation with the market during periods of market distress. This presents a unique modeling challenge, and merger arbitrage portfolios need to be treated separately from other portfolios.</p>
<p>Let’s get into some of the specific considerations and unique aspects of risk management for merger arbitrage portfolios.</p>
</section>
</section>
<section id="exposure-limits-and-expected-losses" class="level2">
<h2 class="anchored" data-anchor-id="exposure-limits-and-expected-losses">Exposure Limits and Expected Losses</h2>
<p>Exposure limits are a critical part of risk management for merger arbitrage portfolios. A key aspect of managing a merger arbitrage strategy is determining the maximum amount of risk that can be taken in a single position or a particular market segment. Limiting exposure reduces the probability of incurring significant losses from a single deal break.</p>
<p>This obviously means that a pure merger arbitrage portfolio needs to invest in multiple deals at once. The portfolio managers target a specific number of deals to be included in their strategy. Arbitrageurs can be “concentrated” (few deals, in-depth analysis) or “diversified” (many deals, spreading risk). According to a survey of risk management practices, merger arbitrageurs held an average of 36 positions, with a minimum of 25 and a maximum of 40. The maximum viable position size for each holding should be determined based on the specific investment goals.</p>
<p>The most straightforward approach to position limits is to cap the size of a single merger position within a portfolio, such as a 5% limit. These limits can be strict, meaning they are never exceeded, or flexible, allowing them to be exceeded if the arbitrageur has a strong belief in a deal’s success. In the latter case, there are usually two types of limits: a hard limit, which is the absolute maximum position size (red light), and a soft limit, which is the maximum position size that can be exceeded with justification (yellow light).</p>
<p>A more advanced approach to position limits is to set them based on the expected loss from a position and limit that to a certain percentage of the portfolio. We present a simplified procedure for calculating these limits, in the next sections.</p>
<p>There are other dimensions to consider when setting exposure limits. For example, the portfolio manager may want to limit the maximum exposure to a single sector or industry, which can help mitigate the risk of sector-specific events affecting multiple positions. This is, however, an easier task in theory than in practice, as the merger arbitrage universe is relatively small, and many deals are concentrated in a few sectors. As different industries go through cycles semi-independently, mergers might be concentrated in a few sectors at a time, making diversification difficult.</p>
<p>Limits can also be set on the types of transactions, such as restricting exposure to leveraged buyouts (LBOs), stock-for-stock transactions, etc., depending on the views and goals of the portfolio manager or the firm.</p>
<p>Another important risk management concept that is closely related to our calculation of exposure limits is the expected loss from a position. In the context of merger arbitrage, expected loss is the probability-weighted loss that an arbitrageur may incur if a merger deal fails to close. This is akin to the expected loss in the case of counterparty credit risk, where the expected loss is calculated as the product of the probability of default and the loss given default.</p>
<section id="estimation-of-probabilities-of-closing" class="level3">
<h3 class="anchored" data-anchor-id="estimation-of-probabilities-of-closing">Estimation of Probabilities of Closing</h3>
<p>Determining the probability of a merger closing is a crucial and often the most difficult step in the merger arbitrage process. Even for experienced arbitrageurs, estimating the probability of a merger closing involves a lot of guesswork and subjective judgment. The arbitrageur assumes the merger will close and will profit only if it does. They need to determine the influence of various factors that may cause a deal break. This includes:</p>
<ul>
<li><p><strong>Financing risks</strong> – The financial health of the acquirer and their ability to raise capital is crucial for the success of the merger. This is especially important for leveraged buyouts (LBOs), where the acquirer relies heavily on debt financing.</p></li>
<li><p><strong>Changes in market conditions</strong> – Even though merger arbitrage is primarily an event-driven, market-neutral strategy, the overall market or specific industry conditions can have a significant impact on the success of a merger. A significant decline in the business environment is called <em>material adverse change</em> in legal terms. The merger agreement may include provisions that allow the acquirer to back out of the deal if a material adverse change occurs.</p></li>
<li><p><strong>Regulatory risks</strong> – Regulatory approval is often a significant hurdle for mergers and acquisitions, especially in industries with high levels of competition or where the merger may create a monopoly. In some instances, for example, cross-border deals, the merger of big entities can be politicized and lead to significant delays or even cancellation of the deal.</p></li>
<li><p><strong>Market cap sizes of the acquirer and target</strong> – A merger is more likely to succeed if the acquirer is significantly larger than the target. According to historical data, the probability of a merger closing is higher when the acquirer is included in large-cap indices such as the S&amp;P 500 or the Russell 1000.</p></li>
<li><p><strong>Shareholder and management sentiment</strong> – Long-term holders on either side of the deal may oppose the merger, especially if they believe it will not be beneficial for the company. Successful shareholder opposition campaigns are, however, rarely successful, especially if the merger premium over the trading price is significant.</p></li>
</ul>
<p>The arbitrageur needs to consider all of these factors and assign a probability of closing to each deal. They may also use historical data regarding the proceedings of similar deals and statistical models to help estimate the probability of a merger closing. Another source of information could be overall market sentiment, which can be gauged from the media coverage of the deal and market pricing, for example, option prices.</p>
</section>
<section id="estimating-severity-of-loss" class="level3">
<h3 class="anchored" data-anchor-id="estimating-severity-of-loss">Estimating severity of loss</h3>
<p>The severity of loss from a merger arbitrage position is the loss that the arbitrageur incurs if the merger fails to close. Severity is analogous to the loss given default (LGD) in credit risk management. The equation for calculating the severity is deceptively simple:</p>
<p><img src="https://latex.codecogs.com/png.latex?L%20=P%5C_%7B%5C%5Cmathrm%7Bp%7D%7D%20-%20P%5C_%7B%5C%5Cmathrm%7Bs%7D%7D"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?P%5C_%7B%5C%5Cmathrm%7Bp%7D%7D"> is the arbitrageur’s purchase price, and <img src="https://latex.codecogs.com/png.latex?P%5C_%7B%5C%5Cmathrm%7Bs%7D%7D"> is the estimated price of the stock at the time of the merger failure. The hard part is estimating <img src="https://latex.codecogs.com/png.latex?P%5C_%7B%5C%5Cmathrm%7Bs%7D%7D">, which might involve even more guesswork than estimating the probability of closing. The purchase price for the arbitrageur has already included the merger premium, but there might have already been some rumors about the possible merger before the announcement, and the stock price might have already reflected some of the merger premium. Or the merger proceedings might unearth some negative information about the target company that was not public previously and affect the outlook on the target. The arbitrageur needs to be conservative and apply punitive estimates of <img src="https://latex.codecogs.com/png.latex?P%5C_%7B%5C%5Cmathrm%7Bs%7D%7D"> to avoid underestimating the severity of loss.</p>
</section>
<section id="calculating-exposure-limits-and-expected-losses" class="level3">
<h3 class="anchored" data-anchor-id="calculating-exposure-limits-and-expected-losses">Calculating Exposure Limits and Expected Losses</h3>
<p>Following the above considerations, the next step is straightforward. The estimate of the <em>expected loss</em> from a position is calculated as follows: <img src="https://latex.codecogs.com/png.latex?%5C%5Cmathbf%7BE%7D%5BL%5D%20=%20(%201%20-%20%5C%5Cmathbf%7BP%7D_%7B%5C%5Cmathrm%7Bsuccess%7D%7D%20)%20%5C%5Ccdot%20L"> where <img src="https://latex.codecogs.com/png.latex?%5C%5Cmathbf%7BP%7D_%7B%5C%5Cmathrm%7Bsuccess%7D%7D"> is the probability of the merger closing, and <img src="https://latex.codecogs.com/png.latex?L"> is the loss incurred if the merger fails.</p>
<p>The <em>severity-based position limit</em> is calculated as a percentage of the portfolio’s value and is set such that the severity of loss does not exceed a certain threshold.</p>
</section>
</section>
<section id="stress-testing" class="level2">
<h2 class="anchored" data-anchor-id="stress-testing">Stress Testing</h2>
<p>As emphasized in previous chapters, merger arbitrage portfolios exhibit low sensitivity to broader market movements. It is useful to conceptualize a merger announcement as a phase transition wherein the target company’s stock price loses its historical correlation with the general market and its industry.</p>
<p>However, certain events can cause the stock price to revert from this phase transition and resume behaving like a typical stock. The most obvious example is the failure of the merger. Other events can also trigger this shift. For instance, during periods of market distress, risk arbitrage returns tend to become positively correlated with the market. This dual effect – uncorrelated returns in normal times and positive correlation with the market during distress – needs to be addressed in the context of stress testing. The whole goal is to assess the risk of a portfolio in extreme market conditions, so the modeling approach should take into account any non-linearities and regime-switching phenomena the portfolio may exhibit.</p>
<section id="merger-arbitrage-as-a-short-put-option" class="level3">
<h3 class="anchored" data-anchor-id="merger-arbitrage-as-a-short-put-option">Merger Arbitrage as a Short Put Option</h3>
<p>The described behavior of arbitrage strategies resembles that of a short position in an out-of-the-money (OTM) put option on a market index. This regime-switching phenomenon was initially observed by Mitchell and Pulvino, who noted that merger arbitrage performs poorly in sharply declining markets. They propose to model the merger arbitrage returns using a <em>piecewise-linear CAPM-type model</em> (broken-stick regression), i.e.,</p>
<p><img src="https://latex.codecogs.com/png.latex?%5C%5Cbegin%7Baligned%7D%0AR%5C_%7B%5C%5Cmathrm%7BRisk%20Arb%7D%7D%20-%20R_f%20&amp;=%20(1%20-%20%5C%5Cdelta)%5B%5C%5Calpha%5C_%7B%5C%5Cmathrm%7BMkt%20Low%7D%7D%20+%20%5C%5Cbeta%5C_%7B%5C%5Cmathrm%7BMkt%20Low%7D%7D(R%5C_%7B%5C%5Cmathrm%7BMkt%7D%7D%20-%20R_f)%5D%20%5C%5C%0A&amp;+%20%5C%5Cdelta%5B%5C%5Calpha%5C_%7B%5C%5Cmathrm%7BMkt%20High%7D%7D%20+%20%5C%5Cbeta%5C_%7B%5C%5Cmathrm%7BMkt%20High%7D%7D(R%5C_%7B%5C%5Cmathrm%7BMkt%7D%7D%20-%20R_f)%5D,%0A%5C%5Cend%7Baligned%7D"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?%5C%5Cdelta"> is an indicator function – equal to one if the excess return is above a threshold level and zero otherwise. To ensure model continuity, it needs to be imposed that the two linear functions are equal at the threshold level, which translates into the following equation:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5C%5Calpha%5C_%7B%5C%5Cmathrm%7BMkt%20Low%7D%7D%20+%20%5C%5Cbeta%5C_%7B%5C%5Cmathrm%7BMkt%20Low%7D%7D(%5C%5Cmathrm%7BThreshold%7D)%20=%20%5C%5Calpha%5C_%7B%5C%5Cmathrm%7BMkt%20High%7D%7D%20+%20%5C%5Cbeta%5C_%7B%5C%5Cmathrm%7BMkt%20High%7D%7D(%5C%5Cmathrm%7BThreshold%7D)%20."></p>
<p>According to their study, in instances where the market index drops by more than <img src="https://latex.codecogs.com/png.latex?4%25"> in a month, the average merger arbitrage portfolio suffers a decline as well, with an average beta value of around <img src="https://latex.codecogs.com/png.latex?0.5">. In a bullish market, the average beta is essentially zero, so the strategy misses the market upside. This means the merger arbitrage alpha is partly compensation for taking on downside market risk without getting the upside. This is analogous to the arbitrageur underwriting uncovered market index put options.</p>
<p>A simple strategy to mitigate merger arbitrage losses involves buying out-of-the-money index put options. While these options usually expire worthless (resulting in the loss of the option premium), they can offset losses from collapsing deals during market downturns. This strategy improves the risk profile but slightly lowers returns in most market conditions due to the cost of the options.</p>
<p>Managing downside risk with equity put options may be insufficient, as this method often overhedges but underhedges when the hedge is most needed. More sophisticated models were developed to model arbitrage strategy returns during market downturns. For instance, Tashman proposes an approach using finite mixtures that includes multiple explanatory variables. Despite the complexity of the model, the main conclusion remains the same: the merger arbitrage strategy exhibits a regime-switching behavior, with a beta of around <img src="https://latex.codecogs.com/png.latex?0.39"> during market downturns and a beta of around <img src="https://latex.codecogs.com/png.latex?0.01"> during normal times.</p>
</section>
<section id="the-practice-of-stress-testing" class="level3">
<h3 class="anchored" data-anchor-id="the-practice-of-stress-testing">The Practice of Stress Testing</h3>
<p>The above findings suggest a proper way to stress test a merger arbitrage portfolio. The arbitrageur can mimic the regime-switching behavior of the portfolio by substituting the arbitrage spread positions with a short put option on the market index for certain risk-management calculations. More specifically, the position should be represented as:</p>
<ul>
<li><p><em>A merger spread</em>, i.e., itself, for purposes of calculating market sensitivities, standard deviation, Sharpe ratio, position limits, and normal quantile-level VaR.</p></li>
<li><p><em>A short put index option</em> for purposes of calculating stress test scenarios, extreme quantile-level VaR, and Stress VaR (i.e., VaR under a stressed historical scenario). The chosen index should be the one that best represents the portfolio’s risk profile, typically the S&amp;P 500, but it can also be a sector index or a custom index.</p></li>
</ul>
<p>This approach is referred to as <em>position proxying</em> and is a common practice in the industry. It is simple (if not crude) but effective in properly assessing arbitrage portfolio performance under stress. Without the proxying, the losses would be underestimated, resulting in a false sense of security and inadequate capital reserves to cover the drawdowns.</p>
</section>
</section>
<section id="option-pricing" class="level2">
<h2 class="anchored" data-anchor-id="option-pricing">Option Pricing</h2>
<p>Merger arbitrage is comparatively a low-volatility strategy, being a market-neutral investment. To amplify the returns, arbitrageurs often employ leverage. Two main vectors of leverage are available: borrowing cash (through margin or loans) to increase the size of the position, or using derivatives to increase the exposure to the underlying stock.</p>
<section id="options-on-ma-targets" class="level3">
<h3 class="anchored" data-anchor-id="options-on-ma-targets">Options on M&amp;A Targets</h3>
<p>Often, purchasing derivatives is the more efficient way to achieve the desired exposure. Derivative instruments are priced based on risk-free interest rates; hence, the associated costs can be lower than borrowing cash. They also allow for more precise engineering of the exposure, as they can be sold or bought depending on the turning market conditions. Purchasing calls on the target stock can be a cost-effective way of obtaining leverage. The option premia are typically low after the announcement of a merger, as the volatility of the stock price drops.</p>
<p>There are other ways that options on M&amp;A targets can be utilized. One is to purchase puts to limit the downside risk of a merger failure. This incurs a premium cost, as mostly the options would expire worthless, but it can allow for a more aggressive overall position size. Finally, option prices can convey information about the market’s expectations regarding the merger outcome. Just as in the general case, option quotes can be used to infer the market’s expectations of the future volatility of the underlying stock; for M&amp;A targets, this can be used to gauge the market’s expectations of the merger outcome. All three of the aforementioned uses require a proper pricing model for the options.</p>
</section>
<section id="option-pricing-on-stocks-involved-in-ma" class="level3">
<h3 class="anchored" data-anchor-id="option-pricing-on-stocks-involved-in-ma">Option Pricing on Stocks Involved in M&amp;A</h3>
<p>As signaled, the standard Black-Scholes model is not suitable for valuation in the context of stocks under a merger process. More complex mathematical models are needed to account for their unique characteristics. This complexity arises from the fact that, unlike typical stocks, the stock price in an M&amp;A scenario does not follow a continuous process. Instead, it is characterized by discrete price movements, or “jumps.” For a stock undergoing a merger, the price would undergo a sudden, instantaneous drop if the merger were to fall through.</p>
<p>Ajay Subramanian made an early attempt to model this, proposing a framework for pricing options on stocks under M&amp;A. His work models option prices of two stocks undergoing a merger, one of which is the target and the other is the acquirer. The pricing model is based on the assumption that the stock price dynamics are governed by the following stochastic differential equations (SDEs):</p>
<p><img src="https://latex.codecogs.com/png.latex?%5C%5Cbegin%7Baligned%7D%0AdS_1(t)%7C_%7BN(t)=0%7D%20&amp;=%201_%7BN(t)=0%7D%20%5C%5B(%5C%5Cmu_1(t)%20-%20d_1)S_1(t-)dt%20+%20%5C%5Csigma'_1%20S_1(t-)dW_1(t)%5C%5D%20%5C%5C%0AdS_2(t)%7C_%7BN(t)=0%7D%20&amp;=%201%5C_%7BN(t)=0%7D%20%5B(%5C%5Cmu_2(t)%20-%20d_2)S_2(t-)dt%20+%20%5C%5Csigma'%5C_2%20S_2(t-)dW_2(t)%5D%0A%5C%5Cend%7Baligned%7D"> where</p>
<ul>
<li><p><img src="https://latex.codecogs.com/png.latex?S_1,%20S_2"> are the prices of the stocks.</p></li>
<li><p><img src="https://latex.codecogs.com/png.latex?%5C%5Cmu_1,%20%5C%5Cmu_2"> are the drifts of the diffusion processes.</p></li>
<li><p><img src="https://latex.codecogs.com/png.latex?%5C%5Csigma'%5C_1,%20%5C%5Csigma'%5C_2"> are the respective volatilities before the jump.</p></li>
<li><p><img src="https://latex.codecogs.com/png.latex?1%5C_%7BN(t)=0%7D"> is 1 before the jump, <img src="https://latex.codecogs.com/png.latex?1%5C_%7BN(t)=1%7D"> is 1 after a jump, if any.</p></li>
<li><p><img src="https://latex.codecogs.com/png.latex?t-"> is a notation for the time just prior to <img src="https://latex.codecogs.com/png.latex?t">.</p></li>
<li><p><img src="https://latex.codecogs.com/png.latex?d_1,%20d_2"> are the respective dividend yields.</p></li>
<li><p><img src="https://latex.codecogs.com/png.latex?W_1,%20W_2"> are Brownian motions.</p></li>
</ul>
<p>If the merger fails, the stocks would revert to a standard Black-Scholes process:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5C%5Cbegin%7Baligned%7D%0AdS_1(t)%7C_%7BN(t)=1%7D%20&amp;=%201_%7BN(t)=1%7D%20%5B(%5C%5Cmu_1(t)%20-%20d_1)S_1(t-)dt%20+%20%5C%5Csigma_1%20S_1(t-)dW_3(t)%5D%20%5C%5C%0AdS_2(t)%7C_%7BN(t)=1%7D%20&amp;=%201_%7BN(t)=1%7D%20%5B(%5C%5Cmu_2(t)%20-%20d_2)S_2(t-)dt%20+%20%5C%5Csigma_2%20S_2(t-)dW_4(t)%5D%0A%5C%5Cend%7Baligned%7D"> where</p>
<ul>
<li><p><img src="https://latex.codecogs.com/png.latex?%5C%5Csigma_1,%20%5C%5Csigma_2"> are the respective volatilities after the jump.</p></li>
<li><p><img src="https://latex.codecogs.com/png.latex?W_3,%20W_4"> are Brownian motions.</p></li>
</ul>
<p>The study also provides a closed-form solution for the option price, which is given by the following formula:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5C%5Cbegin%7Baligned%7D%0AP_1(0,%20T_0,%20K)%20&amp;=%20e%5E%7B-%5C%5Clambda%20T_0%7D%20%5C%5Cleft%7B%20S_1(0)%20e%5E%7B-d_1%20T_0%7D%20%5C%5Cfrac%7Be%5E%7Bi%20T_0%7D%20+%20A_1%7D%7B1%20+%20A_1%7D%20N(%5C%5Calpha'_1)%20-%20K%20e%5E%7B-r%20T_0%7D%20N(%5C%5Calpha'_2)%20%5C%5Cright%7D%20%5C%5C%0A&amp;+%20%5C%5Cfrac%7B%5C%5Clambda%20S_1(0)%20e%5E%7B-d_1%20T_0%7D%20e%5E%7B%5C%5Cfrac%7B%5C%5Clambda%20%5C%5Csigma%5E2%20T_0%7D%7B2%7D%7D%7D%7B%20(1%20+%20A_1)(%5C%5Csigma'%5E2%20-%20%5C%5Csigma%5E2)%7D%20A_1%20%5C%5Cint_%7B2T_0%7D%5E%7B%5C%5Csigma%5E2%202T_0%7D%20dt%20e%5E%7B%5C%5Cfrac%7B%5C%5Clambda%20t%7D%7B%5C%5Csigma'%5E2%20-%20%5C%5Csigma%5E2%7D%7D%20N%5C%5Cleft(%20%5C%5Cfrac%7Bx%20+%200.5t%7D%7B%5C%5Csqrt%7Bt%7D%7D%20%5C%5Cright)%20%5C%5C%0A&amp;-%20%5C%5Cfrac%7B%5C%5Clambda%20K%20e%5E%7B-r%20T_0%7D%20e%5E%7B%5C%5Cfrac%7B%5C%5Clambda%20%5C%5Csigma%5E2%20T_0%7D%7B2%7D%7D%7D%7B(%5C%5Csigma'%5E2%20-%20%5C%5Csigma%5E2)%7D%20%5C%5Cint_%7B2T_0%7D%5E%7B%5C%5Csigma%5E2%202T_0%7D%20dt%20e%5E%7B-%5C%5Cfrac%7B%5C%5Clambda%20t%7D%7B%5C%5Csigma'%5E2%20-%20%5C%5Csigma%5E2%7D%7D%20N%5C%5Cleft(%20%5C%5Cfrac%7Bx%20-%200.5t%7D%7B%5C%5Csqrt%7Bt%7D%7D%20%5C%5Cright)%0A%5C%5Cend%7Baligned%7D"> where:</p>
<ul>
<li><p><img src="https://latex.codecogs.com/png.latex?x%20=%20%5C%5Clog%20%5C%5Cleft%5B%20%5C%5Cfrac%7BS_1(0)%7D%7BK(1+A_1)%7D%20%5C%5Cright%5D%20+%20(r%20-%20d_1)T_0."></p></li>
<li><p><img src="https://latex.codecogs.com/png.latex?A_1,%20A_2"> are chosen so that the stock jumps by a factor<br>
<img src="https://latex.codecogs.com/png.latex?%5C%5Cbeta_i(t)%20=%20A_i%20%5C%5Cexp(t(-%5C%5Clambda))/(1%20+%20A_i%20%5C%5Cexp(-%5C%5Clambda%20t))"> if the deal breaks.</p></li>
<li><p><img src="https://latex.codecogs.com/png.latex?%5C%5Clambda"> is the risk-neutral probability density of the deal breaking.</p></li>
</ul>
<p>The formula is quite complex, and the derivation of the closed-form solution is beyond the scope of this post. An important aspect is that the model has some practical utility and can be used to extract information about the market’s expectations of the merger outcome. It is used to derive the implied probability of the merger closing, similar to the implied volatility in the standard Black-Scholes model.</p>
<p>The empirical results of the study show that the market option prices, combined with the model, are suitable predictors of the merger outcome. The model-implied closing probabilities are derived for a set of merger deals. For the merger deals that closed, the model-implied closing probabilities were significantly higher than for the deals that failed to close. The probability implied by this model could be a useful input for the arbitrageur’s decision-making process and be taken into account when estimating the expected loss from a position.</p>
</section>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Risk management for merger arbitrage portfolios is complex and requires a careful look at their unique characteristics. The main feature of merger arbitrage is its low correlation with the broader market under normal market conditions, which provides an attractive risk-return profile. However, this low correlation can shift to a positive correlation during periods of market distress, which can lead to significant losses for arbitrageurs. Even during flat or bullish markets, the arbitrageur is exposed to the risk of the merger failing, which can result in a substantial drawdown. This requires unique expertise and constant monitoring of the merger proceedings, as well as the overall market outlook on the merger target and acquirer. Merger arbitrage is a good example of why risk management needs to be flexible. It challenges traditional techniques and requires a custom approach to handle its specific risks.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<section id="books" class="level3">
<h3 class="anchored" data-anchor-id="books">Books</h3>
<ul>
<li><strong>McNeil, Alexander J; Frey, Rüdiger; Embrechts, Paul.</strong> (2015). <em>Quantitative Risk Management: Concepts, Techniques, and Tools</em> (Revised Edition). Princeton University Press, Princeton Series in Finance. ISBN: 978-0-691-16679-3</li>
<li><strong>Kirchner, Thomas.</strong> (2016). <em>Merger arbitrage: How to profit from global event-driven arbitrage</em> (Second ed.). John Wiley &amp; Sons.</li>
<li><strong>Moore, Keith M.</strong> (2018). <em>Risk arbitrage: An investor’s guide</em> (Second ed.). John Wiley &amp; Sons.</li>
<li><strong>Boyle, Patrick &amp; McDougall, Jesse.</strong> (2018). <em>Trading and Pricing Financial Derivatives: A Guide to Futures, Options, and Swaps</em>. De Gruyter Press. ISBN: 9781547417308</li>
<li><strong>Welling, Kate &amp; Gabelli, Mario J.</strong> (2018). <em>Merger Masters: Tales of Arbitrage</em>. Columbia University Press. ISBN: 9780231190428</li>
<li><strong>Hull, John C.</strong> (2018). <em>Risk Management and Financial Institutions</em> (Fifth Edition). John Wiley &amp; Sons. ISBN: 978-1-119-42468-5</li>
</ul>
</section>
<section id="articles" class="level3">
<h3 class="anchored" data-anchor-id="articles">Articles</h3>
<ul>
<li><strong>Fung, William &amp; Hsieh, David A.</strong> (1997). “Empirical characteristics of dynamic trading strategies: the case of hedge funds.” <em>Rev.&nbsp;Finan. Stud.</em>, 10, 275–302.</li>
<li><strong>Mitchell, Mark &amp; Pulvino, Todd.</strong> (2001). “Characteristics of risk and return in risk arbitrage.” <em>The Journal of Finance</em>, 56(6), 2135–2175. Wiley for the American Finance Association.</li>
<li><strong>Cont, Rama.</strong> (2001). “Empirical properties of asset returns: stylized facts and statistical issues.” <em>Quantitative Finance</em>, 1(3), 223–236. Taylor &amp; Francis.</li>
<li><strong>Baker, Malcolm &amp; Savaşoğlu, Serkan.</strong> (2002). “Limited arbitrage in mergers and acquisitions.” <em>Journal of Financial Economics</em>, 64(1), 91–115. Elsevier.</li>
<li><strong>Subramanian, Ajay.</strong> (2004). “Option pricing on stocks in mergers and acquisitions.” <em>The Journal of Finance</em>, 59(2), 633–671. Wiley for the American Finance Association.</li>
<li><strong>Moore, Keith; Lai, Gene; Oppenheimer, Henry.</strong> (2006). “The Behavior of Risk Arbitrageurs in Mergers and Acquisitions.” <em>Journal of Alternative Investments</em>, 9, 19–29.</li>
<li><strong>Branch, Ben &amp; Wang, Jia.</strong> (2008). “Risk-Arbitrage Spreads and Performance of Risk Arbitrage.” <em>The Journal of Alternative Investments</em>, 11(1), 9–22. Institutional Investor.</li>
<li><strong>Tashman, Adam &amp; Frey, Robert J.</strong> (2009). “Modeling risk in arbitrage strategies using finite mixtures.” <em>Quantitative Finance</em>, 9(5), 495–503. Taylor &amp; Francis.</li>
<li><strong>Hall, Jason; Pinnuck, Matthew; Thorne, Matthew.</strong> (2012). “Market risk exposure of merger arbitrage in Australia.” <em>Accounting &amp; Finance</em>, aop(aop). Wiley Online Library.</li>
<li><strong>Wall, Douglas Erik Leonard &amp; Theodorsen, Olav Henrik Klingenberg.</strong> (2022). “Risk and return of the merger arbitrage strategy in the European market.” Handelshøyskolen BI.</li>
</ul>


</section>
</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Financial Markets</category>
  <guid>https://bwrob.github.io/posts/25-07-04-merger-arb-risk-management/</guid>
  <pubDate>Fri, 04 Jul 2025 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/assets/images/posts/25-07-04-merger-arb-risk-management/merger_arb.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>A Collection of Iterator Utilities</title>
  <link>https://bwrob.github.io/posts/25-05-02-recipes-iterator-recipes/</link>
  <description><![CDATA[ 






<p>We’re always looping through something in Python. Whether it’s processing lines in a file or streaming data from an API, iterables are everywhere.</p>
<p>Python’s built-in <code>itertools</code> is great, but every now and then you hit a problem that it doesn’t quite cover out of the box. Over time, I’ve put together a small collection of helper functions to handle those “I wish <code>itertools</code> had this” moments. Here are a few of my favorites, complete with some type-safe implementations you can drop into your own projects.</p>
<section id="batched" class="level2">
<h2 class="anchored" data-anchor-id="batched">batched</h2>
<p>This one’s a classic: you have a long list and you want to slice it up into chunks. Maybe you’re feeding data into a neural network or just trying not to hit a rate limit on an API.</p>
<p>Python 3.12 actually added this to <code>itertools</code>, but if you’re stuck on an older version or just want a standalone version, here’s how you can do it:</p>
<div id="28dce9ec" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> __future__ <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> annotations</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> collections.abc <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Iterable</span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> itertools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> islice</span>
<span id="cb1-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sys <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> maxsize</span>
<span id="cb1-5"></span>
<span id="cb1-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> batched[T](</span>
<span id="cb1-7">    iterable: Iterable[T],</span>
<span id="cb1-8">    n: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>,</span>
<span id="cb1-9">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>,</span>
<span id="cb1-10">    strict: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>,</span>
<span id="cb1-11">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Iterable[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>[T, ...]]:</span>
<span id="cb1-12">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Split an iterable into batches of size n."""</span></span>
<span id="cb1-13">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> maxsize:</span>
<span id="cb1-14">        msg <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Batch size n must be at least one and at most sys.maxsize."</span></span>
<span id="cb1-15">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(msg)</span>
<span id="cb1-16"></span>
<span id="cb1-17">    iterator <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(iterable)</span>
<span id="cb1-18">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> batch <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>(islice(iterator, n)):</span>
<span id="cb1-19">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> strict <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(batch) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> n:</span>
<span id="cb1-20">            msg <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Incomplete batch for strict batching."</span></span>
<span id="cb1-21">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(msg)</span>
<span id="cb1-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> batch</span></code></pre></div></div>
</details>
</div>
<section id="example" class="level3">
<h3 class="anchored" data-anchor-id="example">Example</h3>
<div id="46daac15" class="cell" data-execution_count="2">
<details class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"batched(range(10), 3): </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(batched(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>batched(range(10), 3): [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9,)]</code></pre>
</div>
</div>
</section>
</section>
<section id="unbox" class="level2">
<h2 class="anchored" data-anchor-id="unbox">unbox</h2>
<p>Ever have a list that <em>should</em> only have one thing in it? Maybe it’s a filtered database result or a unique ID. Instead of doing <code>results[0]</code> and hoping for the best, <code>unbox</code> makes sure your assumption is actually right.</p>
<p>It grabs that one item and throws a <code>ValueError</code> if it finds more than one (or zero). It’s a great way to catch bugs early.</p>
<div id="e35ad031" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> unbox[T](iterable: Iterable[T]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> T:</span>
<span id="cb4-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Unbox an iterable if it contains a single element."""</span></span>
<span id="cb4-3">    iterator <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(iterable)</span>
<span id="cb4-4">    first_value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(iterator)</span>
<span id="cb4-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb4-6">        _ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(iterator)</span>
<span id="cb4-7">        msg <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Iterable contains more than one element."</span></span>
<span id="cb4-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(msg)</span>
<span id="cb4-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">StopIteration</span>:</span>
<span id="cb4-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> first_value</span></code></pre></div></div>
</details>
</div>
<section id="example-1" class="level3">
<h3 class="anchored" data-anchor-id="example-1">Example</h3>
<div id="9f022c01" class="cell" data-execution_count="4">
<details class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"unbox([42]): </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>unbox([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>])<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb5-2"></span>
<span id="cb5-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb5-4">    _ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> unbox([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>])</span>
<span id="cb5-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> e:</span>
<span id="cb5-6">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"unbox([1, 2]): </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>e<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>unbox([42]): 42
unbox([1, 2]): Iterable contains more than one element.</code></pre>
</div>
</div>
</section>
</section>
<section id="unzip" class="level2">
<h2 class="anchored" data-anchor-id="unzip">unzip</h2>
<p>If you’ve ever used Python’s <code>zip</code> function, you know it’s a lifesaver for pairing up data. But what about the other way around? If you have a list of pairs and you want two separate lists, <code>unzip</code> is the tool for the job.</p>
<div id="f4343ca0" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> unzip[T](iterable: Iterable[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>[T, ...]]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>[Iterable[T], ...]:</span>
<span id="cb7-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Unzip an iterable of tuples."""</span></span>
<span id="cb7-3">    zipped <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>iterable, strict<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb7-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>(zipped)</span></code></pre></div></div>
</details>
</div>
<section id="example-2" class="level3">
<h3 class="anchored" data-anchor-id="example-2">Example</h3>
<div id="facfbf02" class="cell" data-execution_count="6">
<details class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb8-1">zipped_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"a"</span>), (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"b"</span>), (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"c"</span>)]</span>
<span id="cb8-2">unzipped_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> unzip(zipped_data)</span>
<span id="cb8-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"unzip(</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>zipped_data<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">): </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(it) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> it <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> unzipped_data]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>unzip([(1, 'a'), (2, 'b'), (3, 'c')]): [[1, 2, 3], ['a', 'b', 'c']]</code></pre>
</div>
</div>
</section>
</section>
<section id="flatten_iterable" class="level2">
<h2 class="anchored" data-anchor-id="flatten_iterable">flatten_iterable</h2>
<p>Nested lists are a headache. <code>flatten_iterable</code> lets you turn a messy, deeply nested structure into a single, clean list. It’s smart enough to leave strings and bytes alone, so you don’t end up with a list of individual characters when you didn’t mean to.</p>
<div id="eaf549be" class="cell" data-execution_count="7">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> collections.abc <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Generator</span>
<span id="cb10-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> cast</span>
<span id="cb10-3"></span>
<span id="cb10-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span> NestedIterable[T] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Iterable[NestedIterable[T] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> T]</span>
<span id="cb10-5"></span>
<span id="cb10-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> flatten_iterable[T](iterable: NestedIterable[T]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[T]:</span>
<span id="cb10-7">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Flatten an iterable of iterables."""</span></span>
<span id="cb10-8"></span>
<span id="cb10-9">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> _helper(lst: NestedIterable[T]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Generator[T]:</span>
<span id="cb10-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> item <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> lst:</span>
<span id="cb10-11">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(item, Iterable) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(item, (<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bytes</span>)):</span>
<span id="cb10-12">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> _helper(cast(NestedIterable[T], item))</span>
<span id="cb10-13">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb10-14">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> cast(T, item)</span>
<span id="cb10-15"></span>
<span id="cb10-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(_helper(iterable))</span></code></pre></div></div>
</details>
</div>
<section id="example-3" class="level3">
<h3 class="anchored" data-anchor-id="example-3">Example</h3>
<div id="01e16ca1" class="cell" data-execution_count="8">
<details class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb11-1">nested_list <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"a"</span>, [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"b"</span>]</span>
<span id="cb11-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"flatten_iterable(</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>nested_list<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">): </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>flatten_iterable(nested_list)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>flatten_iterable([1, [2, 'a', [3]], 'b']): [1, 2, 'a', 3, 'b']</code></pre>
</div>
</div>
</section>
</section>
<section id="flatten_string_key_dict" class="level2">
<h2 class="anchored" data-anchor-id="flatten_string_key_dict">flatten_string_key_dict</h2>
<p>Nested dictionaries are great for structure, but they can be a pain to access. This function flattens them into a single level, using dots to join the keys (like <code>parent.child.grandchild</code>). It’s perfect for turning complex config files into something much easier to work with.</p>
<div id="daeaa09e" class="cell" data-execution_count="9">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> collections.abc <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Mapping</span>
<span id="cb13-2"></span>
<span id="cb13-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span> NestedDict[T] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Mapping[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, NestedDict[T] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> T]</span>
<span id="cb13-4"></span>
<span id="cb13-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> flatten_string_key_dict[T](dictionary: NestedDict[T]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, T]:</span>
<span id="cb13-6">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Flatten a nested string-keyed dictionary."""</span></span>
<span id="cb13-7"></span>
<span id="cb13-8">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> _generate_items(</span>
<span id="cb13-9">        d: NestedDict[T] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> T, prefix: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span></span>
<span id="cb13-10">    ) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Generator[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, T]]:</span>
<span id="cb13-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(d, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>):</span>
<span id="cb13-12">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> key, value <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> d.items():</span>
<span id="cb13-13">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> _generate_items(value, prefix <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> key <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"."</span>)</span>
<span id="cb13-14">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb13-15">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> prefix[:<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], cast(T, d)</span>
<span id="cb13-16"></span>
<span id="cb13-17">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(_generate_items(dictionary))</span></code></pre></div></div>
</details>
</div>
<section id="example-4" class="level3">
<h3 class="anchored" data-anchor-id="example-4">Example</h3>
<div id="4837356b" class="cell" data-execution_count="10">
<details class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb14-1">nested_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"a"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"b"</span>: {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"c"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"d"</span>: {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"e"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>}}, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>}</span>
<span id="cb14-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(</span>
<span id="cb14-3">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"flatten_string_key_dict(</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>nested_dict<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">): "</span></span>
<span id="cb14-4">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>flatten_string_key_dict(nested_dict)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb14-5">)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>flatten_string_key_dict({'a': 1, 'b': {'c': 2, 'd': {'e': 3}}, 'f': 4}): {'a': 1, 'b.c': 2, 'b.d.e': 3, 'f': 4}</code></pre>
</div>
</div>
</section>
</section>
<section id="group_by_non_consecutive" class="level2">
<h2 class="anchored" data-anchor-id="group_by_non_consecutive">group_by_non_consecutive</h2>
<p>If you’ve ever used <code>itertools.groupby</code>, you know the catch: your data <em>must</em> be sorted first, or it won’t work as expected. This helper function takes care of that for you by sorting the data before grouping it. It’s a bit more memory-heavy because it has to hold the whole list in memory to sort it, but for most everyday tasks, it’s a huge convenience.</p>
<div id="f9c43975" class="cell" data-execution_count="11">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> itertools</span>
<span id="cb16-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> collections.abc <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Callable, Iterator</span>
<span id="cb16-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Any, Protocol, Self</span>
<span id="cb16-4"></span>
<span id="cb16-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> _SupportsLessThan(Protocol):</span>
<span id="cb16-6">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__lt__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, other: Self) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>: ...</span>
<span id="cb16-7"></span>
<span id="cb16-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> group_by_non_consecutive[T, SLT: _SupportsLessThan](</span>
<span id="cb16-9">    iterable: Iterable[T],</span>
<span id="cb16-10">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>,</span>
<span id="cb16-11">    key: Callable[[T], SLT] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb16-12">    reverse: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>,</span>
<span id="cb16-13">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Iterator[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>[SLT, Iterator[T]]]:</span>
<span id="cb16-14">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Sort and group an iterable by a key function.</span></span>
<span id="cb16-15"></span>
<span id="cb16-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Unlike itertools.groupby, this function does not require the iterable</span></span>
<span id="cb16-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    to be pre-sorted. It first sorts the entire iterable and then applies</span></span>
<span id="cb16-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    the grouping.</span></span>
<span id="cb16-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb16-20">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> key <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb16-21"></span>
<span id="cb16-22">        <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> default_key(x: T) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> SLT:</span>
<span id="cb16-23">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> cast(SLT, x)</span>
<span id="cb16-24"></span>
<span id="cb16-25">        key <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> default_key</span>
<span id="cb16-26">    sorted_iterable <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(iterable, key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>key, reverse<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>reverse)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># type: ignore[arg-type]</span></span>
<span id="cb16-27">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> itertools.groupby(sorted_iterable, key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>key)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># type: ignore[arg-type]</span></span></code></pre></div></div>
</details>
</div>
<section id="example-5" class="level3">
<h3 class="anchored" data-anchor-id="example-5">Example</h3>
<div id="c8707200" class="cell" data-execution_count="12">
<details class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb17-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># With key function</span></span>
<span id="cb17-2">data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"apple"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"banana"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ant"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bear"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"apricot"</span>]</span>
<span id="cb17-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"group_by_non_consecutive(</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>data<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, key=lambda x: x[0])"</span>)</span>
<span id="cb17-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> key, group <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> group_by_non_consecutive(data, key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x: x[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]):</span>
<span id="cb17-5">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>key<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(group)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb17-6"></span>
<span id="cb17-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Without key function</span></span>
<span id="cb17-8">data_nums <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb17-9"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"group_by_non_consecutive(</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>data_nums<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">)"</span>)</span>
<span id="cb17-10"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> key, group <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> group_by_non_consecutive(data_nums):</span>
<span id="cb17-11">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>key<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(group)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>group_by_non_consecutive(['apple', 'banana', 'ant', 'bear', 'apricot'], key=lambda x: x[0])
  a: ['apple', 'ant', 'apricot']
  b: ['banana', 'bear']
group_by_non_consecutive([1, 2, 1, 3, 2, 1])
  1: [1, 1, 1]
  2: [2, 2]
  3: [3]</code></pre>
</div>
</div>
<p>These are some of the helpers I find myself reaching for time and again. Hopefully, they’ll save you some time and keep your code a bit cleaner. You can grab the full script with all these functions and examples below.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Download the whole code <a href="../../assets/python/reusable_python_iterator_utilities_and_recipes.py">here</a>.</p>
</div>
</div>


</section>
</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Python Recipes</category>
  <guid>https://bwrob.github.io/posts/25-05-02-recipes-iterator-recipes/</guid>
  <pubDate>Fri, 02 May 2025 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/posts/25-05-02-recipes-iterator-recipes/cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Mathematician in the Financial Markets</title>
  <link>https://bwrob.github.io/posts/25-03-22-mathematician-in-finance/</link>
  <description><![CDATA[ 






<div class="lang-switcher">
<p><a href="../../posts/25-03-22-mathematician-in-finance/index.html" class="lang-btn active">English 🇬🇧</a> <a href="../../posts/25-03-22-mathematician-in-finance/index-pl.html" class="lang-btn">Polski 🇵🇱</a></p>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/25-03-22-mathematician-in-finance/financial_whirlpool.webp" class="lightbox" data-gallery="quarto-lightbox-gallery-1"><img src="https://bwrob.github.io/assets/images/posts/25-03-22-mathematician-in-finance/financial_whirlpool.webp" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:95.0%"></a></p>
</figure>
</div>
<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p>In this post, we’ll look at what it’s actually like for a mathematician to work in financial markets. We’ll go over the different roles you can land, the skills you actually need (beyond just knowing your way around a mathematical proof), and how to navigate the industry.</p>
</section>
<section id="the-financial-ecosystem" class="level2">
<h2 class="anchored" data-anchor-id="the-financial-ecosystem">The Financial Ecosystem</h2>
<p>When you first look at teh financial markets, they can seem like a chaotic mess of numbers, shouting (well, maybe less shouting now that everything is electronic), and complex jargon. But at their core, markets are just ecosystems where capital and risk are being exchanged. It’s a place where people who have money but no projects meet people who have projects but no money.</p>
<p>The characters you meet on the trading floor generally fall into a few buckets.</p>
<p>You have the <strong>Speculators</strong>, who are the ones taking on risk because they think they can predict where the price is going. They provide the liquidity that makes the market move. Regular people investing their retirement funds into stock exchenge indecies are also speculators. They are making a bet that the long term performance of the ecomomy outperforms inflation until they retire. This is historically a safe assuption, but still burdened with uncertainty.</p>
<p>Then you have <strong>Hedgers</strong>—these are the “insurance seekers” who already have a risk (like a farmer worried about wheat prices) and want to get rid of it.</p>
<p>In between them, you find the <strong>Arbitrageurs</strong>. These are the “market cleaners” who look for tiny inconsistencies in prices between different places. If gold is cheaper in London than in New York, they’ll buy in one and sell in the other until the prices align.</p>
<p>Finally, you have the <strong>Intermediaries</strong> (like brokers and market makers) who just want to make the trade happen and pocket a small fee for the service.</p>
<p>For a mathematician, this is a playground. Why? Because every single one of these types interactions with the market involves uncertainty, and if there’s one thing applied mathematicians are good at, it’s quantifying the unknown.</p>
</section>
<section id="why-do-they-need-us" class="level2">
<h2 class="anchored" data-anchor-id="why-do-they-need-us">Why Do They Need Us?</h2>
<p>You might wonder why a bank would hire someone who spent five years studying geometric bundles, clopen sets, branching processes or non-local unbounded operators. The reason is that modern finance is built on models that are essentially massive math problems. Catch-phrase here is “quantitative finance” but truly, nowadays all finance is quantitative.</p>
<p>Take <strong>pricing</strong>, for example. If you want to sell someone an option – the right to buy a stock at a certain price in six months – you need to know what that right is worth today. That involves stochastic calculus, partial differential equations, and a lot of numerical methods. It’s not just “guessing”; it’s solving a more complex Heat Equation in a financial context.</p>
<p>Then there’s <strong>Risk Management</strong>. After the 2008 crisis, “winging it” stopped being an option. Banks need to know, with a high degree of mathematical certainty, how much they could lose if the market takes a dive. This requires sophisticated probability theory and statistics to model “fat tails”—those rare but catastrophic events that standard models often miss.</p>
<p>Beyond pricing and risk, mathematicians heavily involved in <strong>Algorithmic Trading</strong>, where we use optimization and signal processing to execute trades in milliseconds, and <strong>Portfolio Optimization</strong>, where we use linear algebra to find the best possible balance between return and risk.</p>
</section>
<section id="the-many-flavors-of-quants" class="level2">
<h2 class="anchored" data-anchor-id="the-many-flavors-of-quants">The Many Flavors of Quants</h2>
<p>Not all “Quants” do the same thing. Depending on your interests, you might find yourself in very different environments. Some roles are all about the “hard math” of derivatives, while others are more about being a software engineer who happens to know what a Yield Curve is.</p>
<div id="566f3c99" class="cell" data-collapse="true" data-execution_count="1">
<div class="tabset-margin-container"></div><div class="panel-tabset">
<ul class="nav nav-tabs"><li class="nav-item"><a class="nav-link active" id="tabset-1-1-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-1" aria-controls="tabset-1-1" aria-selected="true" href="">Front Office Quant</a></li><li class="nav-item"><a class="nav-link" id="tabset-1-2-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-2" aria-controls="tabset-1-2" aria-selected="false" href="">Market Risk Quant</a></li><li class="nav-item"><a class="nav-link" id="tabset-1-3-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-3" aria-controls="tabset-1-3" aria-selected="false" href="">Credit Risk Quant</a></li><li class="nav-item"><a class="nav-link" id="tabset-1-4-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-4" aria-controls="tabset-1-4" aria-selected="false" href="">Validation Quant</a></li><li class="nav-item"><a class="nav-link" id="tabset-1-5-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-5" aria-controls="tabset-1-5" aria-selected="false" href="">Quant Researcher</a></li><li class="nav-item"><a class="nav-link" id="tabset-1-6-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-6" aria-controls="tabset-1-6" aria-selected="false" href="">Algorithmic Trader</a></li><li class="nav-item"><a class="nav-link" id="tabset-1-7-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-7" aria-controls="tabset-1-7" aria-selected="false" href="">Quant Developer</a></li></ul>
<div class="tab-content">
<div id="tabset-1-1" class="tab-pane active" aria-labelledby="tabset-1-1-tab">
<p>Develops and applies quantitative models for pricing, risk management, and trading strategies directly on the trading desk.</p>
<div style="height:525px; width:600px;">            <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-svg.min.js"></script><script>if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: "STIX-Web"}});}</script>                <script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
        <script charset="utf-8" src="https://cdn.plot.ly/plotly-4.1.1.min.js" integrity="sha256-O24V1F27f8pb0glCkelh3cVHLNiHAJ5gCaVtq2aNch8=" crossorigin="anonymous"></script>                <div id="6f1084d9-ae16-4332-8b63-35e1e968c25e" class="plotly-graph-div" style="height:100%; width:100%;"></div>            <script>                window.PLOTLYENV=window.PLOTLYENV || {};                                if (document.getElementById("6f1084d9-ae16-4332-8b63-35e1e968c25e")) {                    Plotly.newPlot(                        "6f1084d9-ae16-4332-8b63-35e1e968c25e",                        [{"orientation":"h","x":[0,1,0,1,3,0,0,0,3,3,0,0,1],"y":["Statistical Learning","Software Engineering","Risk Modeling","Regulatory Knowledge","Programming","Numerical Methods","Model Validation","Market Microstructure","Financial Math","Finance Knowledge","Data Mining","Data Management","Data Analysis"],"type":"bar"}],                        {"template":{"data":{"histogram2dcontour":[{"type":"histogram2dcontour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"choropleth":[{"type":"choropleth","colorbar":{"outlinewidth":0,"ticks":""}}],"histogram2d":[{"type":"histogram2d","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"heatmap":[{"type":"heatmap","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"contourcarpet":[{"type":"contourcarpet","colorbar":{"outlinewidth":0,"ticks":""}}],"contour":[{"type":"contour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"surface":[{"type":"surface","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"mesh3d":[{"type":"mesh3d","colorbar":{"outlinewidth":0,"ticks":""}}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"parcoords":[{"type":"parcoords","line":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolargl":[{"type":"scatterpolargl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"scattergeo":[{"type":"scattergeo","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolar":[{"type":"scatterpolar","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"scattergl":[{"type":"scattergl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatter3d":[{"type":"scatter3d","line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermap":[{"type":"scattermap","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterternary":[{"type":"scatterternary","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattercarpet":[{"type":"scattercarpet","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"type":"carpet"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}],"barpolar":[{"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"pie":[{"automargin":true,"type":"pie"}]},"layout":{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"white","plot_bgcolor":"#E5ECF6","polar":{"bgcolor":"#E5ECF6","angularaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"radialaxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"ternary":{"bgcolor":"#E5ECF6","aaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"baxis":{"gridcolor":"white","linecolor":"white","ticks":""},"caxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"yaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"zaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"white","landcolor":"#E5ECF6","subunitcolor":"white","showland":true,"showlakes":true,"lakecolor":"white"},"title":{"x":0.05},"margin":{"b":0,"l":0,"r":0,"t":30}}},"xaxis":{"showgrid":false,"tickmode":"linear","tick0":0,"dtick":1},"title":{"text":"Skill Levels - Front Office Quant"},"width":600},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('6f1084d9-ae16-4332-8b63-35e1e968c25e');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };            </script>        </div>
</div>
<div id="tabset-1-2" class="tab-pane" aria-labelledby="tabset-1-2-tab">
<p>Develops and validates models to measure and manage market risk, ensuring the bank stays within its limits and regulatory requirements.</p>
<div style="height:525px; width:600px;">            <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-svg.min.js"></script><script>if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: "STIX-Web"}});}</script>                <script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
        <script charset="utf-8" src="https://cdn.plot.ly/plotly-4.1.1.min.js" integrity="sha256-O24V1F27f8pb0glCkelh3cVHLNiHAJ5gCaVtq2aNch8=" crossorigin="anonymous"></script>                <div id="a9bc4ceb-205a-4df1-b779-94ed9db83948" class="plotly-graph-div" style="height:100%; width:100%;"></div>            <script>                window.PLOTLYENV=window.PLOTLYENV || {};                                if (document.getElementById("a9bc4ceb-205a-4df1-b779-94ed9db83948")) {                    Plotly.newPlot(                        "a9bc4ceb-205a-4df1-b779-94ed9db83948",                        [{"orientation":"h","x":[0,0,3,2,1,0,0,0,2,2,0,0,2],"y":["Statistical Learning","Software Engineering","Risk Modeling","Regulatory Knowledge","Programming","Numerical Methods","Model Validation","Market Microstructure","Financial Math","Finance Knowledge","Data Mining","Data Management","Data Analysis"],"type":"bar"}],                        {"template":{"data":{"histogram2dcontour":[{"type":"histogram2dcontour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"choropleth":[{"type":"choropleth","colorbar":{"outlinewidth":0,"ticks":""}}],"histogram2d":[{"type":"histogram2d","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"heatmap":[{"type":"heatmap","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"contourcarpet":[{"type":"contourcarpet","colorbar":{"outlinewidth":0,"ticks":""}}],"contour":[{"type":"contour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"surface":[{"type":"surface","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"mesh3d":[{"type":"mesh3d","colorbar":{"outlinewidth":0,"ticks":""}}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"parcoords":[{"type":"parcoords","line":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolargl":[{"type":"scatterpolargl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"scattergeo":[{"type":"scattergeo","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolar":[{"type":"scatterpolar","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"scattergl":[{"type":"scattergl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatter3d":[{"type":"scatter3d","line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermap":[{"type":"scattermap","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterternary":[{"type":"scatterternary","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattercarpet":[{"type":"scattercarpet","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"type":"carpet"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}],"barpolar":[{"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"pie":[{"automargin":true,"type":"pie"}]},"layout":{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"white","plot_bgcolor":"#E5ECF6","polar":{"bgcolor":"#E5ECF6","angularaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"radialaxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"ternary":{"bgcolor":"#E5ECF6","aaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"baxis":{"gridcolor":"white","linecolor":"white","ticks":""},"caxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"yaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"zaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"white","landcolor":"#E5ECF6","subunitcolor":"white","showland":true,"showlakes":true,"lakecolor":"white"},"title":{"x":0.05},"margin":{"b":0,"l":0,"r":0,"t":30}}},"xaxis":{"showgrid":false,"tickmode":"linear","tick0":0,"dtick":1},"title":{"text":"Skill Levels - Market Risk Quant"},"width":600},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('a9bc4ceb-205a-4df1-b779-94ed9db83948');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };            </script>        </div>
</div>
<div id="tabset-1-3" class="tab-pane" aria-labelledby="tabset-1-3-tab">
<p>Focuses on the risk of people or companies defaulting on their debts. Heavy on probability and statistical modeling.</p>
<div style="height:525px; width:600px;">            <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-svg.min.js"></script><script>if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: "STIX-Web"}});}</script>                <script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
        <script charset="utf-8" src="https://cdn.plot.ly/plotly-4.1.1.min.js" integrity="sha256-O24V1F27f8pb0glCkelh3cVHLNiHAJ5gCaVtq2aNch8=" crossorigin="anonymous"></script>                <div id="8cc053d9-c256-4e4c-9fb4-afcddd21d344" class="plotly-graph-div" style="height:100%; width:100%;"></div>            <script>                window.PLOTLYENV=window.PLOTLYENV || {};                                if (document.getElementById("8cc053d9-c256-4e4c-9fb4-afcddd21d344")) {                    Plotly.newPlot(                        "8cc053d9-c256-4e4c-9fb4-afcddd21d344",                        [{"orientation":"h","x":[0,1,3,2,2,1,0,0,3,2,0,0,2],"y":["Statistical Learning","Software Engineering","Risk Modeling","Regulatory Knowledge","Programming","Numerical Methods","Model Validation","Market Microstructure","Financial Math","Finance Knowledge","Data Mining","Data Management","Data Analysis"],"type":"bar"}],                        {"template":{"data":{"histogram2dcontour":[{"type":"histogram2dcontour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"choropleth":[{"type":"choropleth","colorbar":{"outlinewidth":0,"ticks":""}}],"histogram2d":[{"type":"histogram2d","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"heatmap":[{"type":"heatmap","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"contourcarpet":[{"type":"contourcarpet","colorbar":{"outlinewidth":0,"ticks":""}}],"contour":[{"type":"contour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"surface":[{"type":"surface","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"mesh3d":[{"type":"mesh3d","colorbar":{"outlinewidth":0,"ticks":""}}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"parcoords":[{"type":"parcoords","line":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolargl":[{"type":"scatterpolargl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"scattergeo":[{"type":"scattergeo","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolar":[{"type":"scatterpolar","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"scattergl":[{"type":"scattergl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatter3d":[{"type":"scatter3d","line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermap":[{"type":"scattermap","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterternary":[{"type":"scatterternary","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattercarpet":[{"type":"scattercarpet","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"type":"carpet"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}],"barpolar":[{"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"pie":[{"automargin":true,"type":"pie"}]},"layout":{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"white","plot_bgcolor":"#E5ECF6","polar":{"bgcolor":"#E5ECF6","angularaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"radialaxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"ternary":{"bgcolor":"#E5ECF6","aaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"baxis":{"gridcolor":"white","linecolor":"white","ticks":""},"caxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"yaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"zaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"white","landcolor":"#E5ECF6","subunitcolor":"white","showland":true,"showlakes":true,"lakecolor":"white"},"title":{"x":0.05},"margin":{"b":0,"l":0,"r":0,"t":30}}},"xaxis":{"showgrid":false,"tickmode":"linear","tick0":0,"dtick":1},"title":{"text":"Skill Levels - Credit Risk Quant"},"width":600},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('8cc053d9-c256-4e4c-9fb4-afcddd21d344');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };            </script>        </div>
</div>
<div id="tabset-1-4" class="tab-pane" aria-labelledby="tabset-1-4-tab">
<p>The ‘internal police.’ They independently check the models built by other quants to make sure they aren’t broken or dangerous.</p>
<div style="height:525px; width:600px;">            <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-svg.min.js"></script><script>if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: "STIX-Web"}});}</script>                <script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
        <script charset="utf-8" src="https://cdn.plot.ly/plotly-4.1.1.min.js" integrity="sha256-O24V1F27f8pb0glCkelh3cVHLNiHAJ5gCaVtq2aNch8=" crossorigin="anonymous"></script>                <div id="a3b98efd-bfc8-4471-a73d-cff82b6400b4" class="plotly-graph-div" style="height:100%; width:100%;"></div>            <script>                window.PLOTLYENV=window.PLOTLYENV || {};                                if (document.getElementById("a3b98efd-bfc8-4471-a73d-cff82b6400b4")) {                    Plotly.newPlot(                        "a3b98efd-bfc8-4471-a73d-cff82b6400b4",                        [{"orientation":"h","x":[0,0,0,3,1,0,3,0,3,0,0,0,1],"y":["Statistical Learning","Software Engineering","Risk Modeling","Regulatory Knowledge","Programming","Numerical Methods","Model Validation","Market Microstructure","Financial Math","Finance Knowledge","Data Mining","Data Management","Data Analysis"],"type":"bar"}],                        {"template":{"data":{"histogram2dcontour":[{"type":"histogram2dcontour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"choropleth":[{"type":"choropleth","colorbar":{"outlinewidth":0,"ticks":""}}],"histogram2d":[{"type":"histogram2d","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"heatmap":[{"type":"heatmap","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"contourcarpet":[{"type":"contourcarpet","colorbar":{"outlinewidth":0,"ticks":""}}],"contour":[{"type":"contour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"surface":[{"type":"surface","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"mesh3d":[{"type":"mesh3d","colorbar":{"outlinewidth":0,"ticks":""}}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"parcoords":[{"type":"parcoords","line":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolargl":[{"type":"scatterpolargl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"scattergeo":[{"type":"scattergeo","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolar":[{"type":"scatterpolar","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"scattergl":[{"type":"scattergl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatter3d":[{"type":"scatter3d","line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermap":[{"type":"scattermap","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterternary":[{"type":"scatterternary","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattercarpet":[{"type":"scattercarpet","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"type":"carpet"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}],"barpolar":[{"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"pie":[{"automargin":true,"type":"pie"}]},"layout":{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"white","plot_bgcolor":"#E5ECF6","polar":{"bgcolor":"#E5ECF6","angularaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"radialaxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"ternary":{"bgcolor":"#E5ECF6","aaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"baxis":{"gridcolor":"white","linecolor":"white","ticks":""},"caxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"yaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"zaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"white","landcolor":"#E5ECF6","subunitcolor":"white","showland":true,"showlakes":true,"lakecolor":"white"},"title":{"x":0.05},"margin":{"b":0,"l":0,"r":0,"t":30}}},"xaxis":{"showgrid":false,"tickmode":"linear","tick0":0,"dtick":1},"title":{"text":"Skill Levels - Validation Quant"},"width":600},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('a3b98efd-bfc8-4471-a73d-cff82b6400b4');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };            </script>        </div>
</div>
<div id="tabset-1-5" class="tab-pane" aria-labelledby="tabset-1-5-tab">
<p>The ‘think tank’ role. Conducts cutting-edge research to find new trading signals or better ways to price assets.</p>
<div style="height:525px; width:600px;">            <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-svg.min.js"></script><script>if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: "STIX-Web"}});}</script>                <script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
        <script charset="utf-8" src="https://cdn.plot.ly/plotly-4.1.1.min.js" integrity="sha256-O24V1F27f8pb0glCkelh3cVHLNiHAJ5gCaVtq2aNch8=" crossorigin="anonymous"></script>                <div id="5660c3a9-3691-4566-b376-3b6ac04f8ebf" class="plotly-graph-div" style="height:100%; width:100%;"></div>            <script>                window.PLOTLYENV=window.PLOTLYENV || {};                                if (document.getElementById("5660c3a9-3691-4566-b376-3b6ac04f8ebf")) {                    Plotly.newPlot(                        "5660c3a9-3691-4566-b376-3b6ac04f8ebf",                        [{"orientation":"h","x":[3,0,0,0,2,0,0,0,3,3,2,0,0],"y":["Statistical Learning","Software Engineering","Risk Modeling","Regulatory Knowledge","Programming","Numerical Methods","Model Validation","Market Microstructure","Financial Math","Finance Knowledge","Data Mining","Data Management","Data Analysis"],"type":"bar"}],                        {"template":{"data":{"histogram2dcontour":[{"type":"histogram2dcontour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"choropleth":[{"type":"choropleth","colorbar":{"outlinewidth":0,"ticks":""}}],"histogram2d":[{"type":"histogram2d","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"heatmap":[{"type":"heatmap","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"contourcarpet":[{"type":"contourcarpet","colorbar":{"outlinewidth":0,"ticks":""}}],"contour":[{"type":"contour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"surface":[{"type":"surface","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"mesh3d":[{"type":"mesh3d","colorbar":{"outlinewidth":0,"ticks":""}}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"parcoords":[{"type":"parcoords","line":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolargl":[{"type":"scatterpolargl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"scattergeo":[{"type":"scattergeo","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolar":[{"type":"scatterpolar","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"scattergl":[{"type":"scattergl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatter3d":[{"type":"scatter3d","line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermap":[{"type":"scattermap","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterternary":[{"type":"scatterternary","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattercarpet":[{"type":"scattercarpet","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"type":"carpet"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}],"barpolar":[{"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"pie":[{"automargin":true,"type":"pie"}]},"layout":{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"white","plot_bgcolor":"#E5ECF6","polar":{"bgcolor":"#E5ECF6","angularaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"radialaxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"ternary":{"bgcolor":"#E5ECF6","aaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"baxis":{"gridcolor":"white","linecolor":"white","ticks":""},"caxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"yaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"zaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"white","landcolor":"#E5ECF6","subunitcolor":"white","showland":true,"showlakes":true,"lakecolor":"white"},"title":{"x":0.05},"margin":{"b":0,"l":0,"r":0,"t":30}}},"xaxis":{"showgrid":false,"tickmode":"linear","tick0":0,"dtick":1},"title":{"text":"Skill Levels - Quant Researcher"},"width":600},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('5660c3a9-3691-4566-b376-3b6ac04f8ebf');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };            </script>        </div>
</div>
<div id="tabset-1-6" class="tab-pane" aria-labelledby="tabset-1-6-tab">
<p>Writes the code that actually executes trades. Needs to understand how markets move on a second-by-second basis.</p>
<div style="height:525px; width:600px;">            <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-svg.min.js"></script><script>if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: "STIX-Web"}});}</script>                <script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
        <script charset="utf-8" src="https://cdn.plot.ly/plotly-4.1.1.min.js" integrity="sha256-O24V1F27f8pb0glCkelh3cVHLNiHAJ5gCaVtq2aNch8=" crossorigin="anonymous"></script>                <div id="4e84ef22-bad8-4a38-a6db-02b2f1eb80f9" class="plotly-graph-div" style="height:100%; width:100%;"></div>            <script>                window.PLOTLYENV=window.PLOTLYENV || {};                                if (document.getElementById("4e84ef22-bad8-4a38-a6db-02b2f1eb80f9")) {                    Plotly.newPlot(                        "4e84ef22-bad8-4a38-a6db-02b2f1eb80f9",                        [{"orientation":"h","x":[3,2,0,0,3,0,0,3,0,3,2,2,0],"y":["Statistical Learning","Software Engineering","Risk Modeling","Regulatory Knowledge","Programming","Numerical Methods","Model Validation","Market Microstructure","Financial Math","Finance Knowledge","Data Mining","Data Management","Data Analysis"],"type":"bar"}],                        {"template":{"data":{"histogram2dcontour":[{"type":"histogram2dcontour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"choropleth":[{"type":"choropleth","colorbar":{"outlinewidth":0,"ticks":""}}],"histogram2d":[{"type":"histogram2d","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"heatmap":[{"type":"heatmap","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"contourcarpet":[{"type":"contourcarpet","colorbar":{"outlinewidth":0,"ticks":""}}],"contour":[{"type":"contour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"surface":[{"type":"surface","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"mesh3d":[{"type":"mesh3d","colorbar":{"outlinewidth":0,"ticks":""}}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"parcoords":[{"type":"parcoords","line":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolargl":[{"type":"scatterpolargl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"scattergeo":[{"type":"scattergeo","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolar":[{"type":"scatterpolar","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"scattergl":[{"type":"scattergl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatter3d":[{"type":"scatter3d","line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermap":[{"type":"scattermap","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterternary":[{"type":"scatterternary","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattercarpet":[{"type":"scattercarpet","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"type":"carpet"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}],"barpolar":[{"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"pie":[{"automargin":true,"type":"pie"}]},"layout":{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"white","plot_bgcolor":"#E5ECF6","polar":{"bgcolor":"#E5ECF6","angularaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"radialaxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"ternary":{"bgcolor":"#E5ECF6","aaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"baxis":{"gridcolor":"white","linecolor":"white","ticks":""},"caxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"yaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"zaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"white","landcolor":"#E5ECF6","subunitcolor":"white","showland":true,"showlakes":true,"lakecolor":"white"},"title":{"x":0.05},"margin":{"b":0,"l":0,"r":0,"t":30}}},"xaxis":{"showgrid":false,"tickmode":"linear","tick0":0,"dtick":1},"title":{"text":"Skill Levels - Algorithmic Trader"},"width":600},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('4e84ef22-bad8-4a38-a6db-02b2f1eb80f9');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };            </script>        </div>
</div>
<div id="tabset-1-7" class="tab-pane" aria-labelledby="tabset-1-7-tab">
<p>The backbone of the operation. They build the high-performance systems that the math runs on.</p>
<div style="height:525px; width:600px;">            <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-svg.min.js"></script><script>if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: "STIX-Web"}});}</script>                <script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
        <script charset="utf-8" src="https://cdn.plot.ly/plotly-4.1.1.min.js" integrity="sha256-O24V1F27f8pb0glCkelh3cVHLNiHAJ5gCaVtq2aNch8=" crossorigin="anonymous"></script>                <div id="f82ae577-7b38-4135-a8e1-71170a3d2c4f" class="plotly-graph-div" style="height:100%; width:100%;"></div>            <script>                window.PLOTLYENV=window.PLOTLYENV || {};                                if (document.getElementById("f82ae577-7b38-4135-a8e1-71170a3d2c4f")) {                    Plotly.newPlot(                        "f82ae577-7b38-4135-a8e1-71170a3d2c4f",                        [{"orientation":"h","x":[0,3,0,1,3,3,0,0,1,2,0,2,0],"y":["Statistical Learning","Software Engineering","Risk Modeling","Regulatory Knowledge","Programming","Numerical Methods","Model Validation","Market Microstructure","Financial Math","Finance Knowledge","Data Mining","Data Management","Data Analysis"],"type":"bar"}],                        {"template":{"data":{"histogram2dcontour":[{"type":"histogram2dcontour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"choropleth":[{"type":"choropleth","colorbar":{"outlinewidth":0,"ticks":""}}],"histogram2d":[{"type":"histogram2d","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"heatmap":[{"type":"heatmap","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"contourcarpet":[{"type":"contourcarpet","colorbar":{"outlinewidth":0,"ticks":""}}],"contour":[{"type":"contour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"surface":[{"type":"surface","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"mesh3d":[{"type":"mesh3d","colorbar":{"outlinewidth":0,"ticks":""}}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"parcoords":[{"type":"parcoords","line":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolargl":[{"type":"scatterpolargl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"scattergeo":[{"type":"scattergeo","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolar":[{"type":"scatterpolar","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"scattergl":[{"type":"scattergl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatter3d":[{"type":"scatter3d","line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermap":[{"type":"scattermap","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterternary":[{"type":"scatterternary","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattercarpet":[{"type":"scattercarpet","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"type":"carpet"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}],"barpolar":[{"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"pie":[{"automargin":true,"type":"pie"}]},"layout":{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"white","plot_bgcolor":"#E5ECF6","polar":{"bgcolor":"#E5ECF6","angularaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"radialaxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"ternary":{"bgcolor":"#E5ECF6","aaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"baxis":{"gridcolor":"white","linecolor":"white","ticks":""},"caxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"yaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"zaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"white","landcolor":"#E5ECF6","subunitcolor":"white","showland":true,"showlakes":true,"lakecolor":"white"},"title":{"x":0.05},"margin":{"b":0,"l":0,"r":0,"t":30}}},"xaxis":{"showgrid":false,"tickmode":"linear","tick0":0,"dtick":1},"title":{"text":"Skill Levels - Quant Developer"},"width":600},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('f82ae577-7b38-4135-a8e1-71170a3d2c4f');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };            </script>        </div>
</div>
</div>
</div>
</div>
</section>
<section id="case-study-from-jupyter-notebook-to-production" class="level2">
<h2 class="anchored" data-anchor-id="case-study-from-jupyter-notebook-to-production">Case Study: From Jupyter Notebook to Production</h2>
<p>To see the difference between the various Quant Analyst and Quant Developer roles in practice, let’s look at a concrete project: <strong>extracting implied probability distributions from option prices</strong>.</p>
<p>This is one of the quantitative finance standards. By looking at option prices across different strikes for a given expiry, we can extract the market’s consensus on the probability of the underlying asset reaching a certain price in the future. Mathematically, this is based on the Breeden-Litzenberger theorem, which states that the risk-neutral probability density function is proportional to the second derivative of the option price with respect to the strike price.</p>
<p>Imagine you have a basic implementation of this math in a Python script or Jupyter Notebook. It fits a smooth curve (like a cubic spline) to option prices and takes the numerical second derivative. It’s a neat math exercise, but in a professional setting, this script is just the starting point.</p>
<p>Here is how the paths of the Quant Analyst and the Quant Developer diverge:</p>
<section id="the-quant-analysts-path" class="level3">
<h3 class="anchored" data-anchor-id="the-quant-analysts-path">The Quant Analyst’s Path</h3>
<p>A Quant Analyst (QA) is primarily focused on the math, the models, and the financial implications of the output:</p>
<ul>
<li><strong>Valuation Quant:</strong> Will worry about the mathematical assumptions. Does the interpolation scheme guarantee that there is no static arbitrage (e.g., ensuring the probability density is never negative and integrates to 1)? How can we use this constructed distribution to price more complex, illiquid, or exotic derivatives?</li>
<li><strong>Risk Quant:</strong> Will look at the output from a risk mitigation perspective. Can we use this implied distribution to identify tail risks in our portfolio and find the cheapest way to hedge them using out-of-the-money (OTM) options?</li>
<li><strong>Quant Researcher:</strong> Will look for trading signals. They might generate these distributions across different expiries, compare them against historical data, and search for statistical inefficiencies or mispricings to exploit.</li>
<li><strong>Quant Trader:</strong> Will focus on the execution. How can we use the distribution’s insights to buy or sell the required options in the market at the best possible price with minimal transaction costs?</li>
</ul>
</section>
<section id="the-quant-developers-path" class="level3">
<h3 class="anchored" data-anchor-id="the-quant-developers-path">The Quant Developer’s Path</h3>
<p>A Quant Developer (QD) is focused on turning this mathematical prototype into a robust, scalable, and production-grade software system:</p>
<ul>
<li><strong>Productionalizing the Code:</strong> The QD takes the (possibly messy) Jupyter notebook and refactors it into clean, structured, and reusable code. This means introducing classes, static typing, proper linting, docstrings, and a comprehensive suite of unit and regression tests.</li>
<li><strong>Data Integration &amp; Design Patterns:</strong> The system needs to work with live market data from various feeds (e.g., Bloomberg, Reuters, or internal databases). The QD uses software design patterns like Dependency Injection and the Adapter Pattern to ensure that swapping data vendors doesn’t require rewriting the core mathematical model.</li>
<li><strong>Performance Optimization:</strong> Solving the math (interpolation, root-finding for implied volatilities) is CPU-heavy. The QD analyzes the performance. Sometimes Python’s <code>scipy</code> is fast enough; other times, they need to implement highly optimized, domain-specific algorithms (like Jaeckel’s method). For ultra-low latency, they might offload the calculations to a compiled language like C++ or Rust (binding it back to Python using <code>nanobind</code> or <code>PyO3</code>).</li>
<li><strong>Concurrency &amp; API Limits:</strong> If fetching data is the bottleneck, the QD implements asynchronous programming (<code>asyncio</code>). They must handle blocking vendor APIs safely (using <code>asyncio.to_thread</code>) and design rate-limiters or semaphores to avoid getting blocked by external data providers.</li>
<li><strong>Batch Processing &amp; Scheduling:</strong> If the risk team only needs end-of-day (EOD) metrics, there is no need for real-time streaming. The QD sets up an orchestrator (like Airflow) to run the model as a batch job overnight, writing results to a database.</li>
<li><strong>User Interface &amp; Dashboards:</strong> If a trader needs to monitor these distributions live on one of their six screens, the QD builds a dashboard. They must decide on the architecture: is a lightweight framework like Streamlit or Dash sufficient, or do they need to split it into a robust backend API (e.g., FastAPI) and a modern frontend (e.g., React)?</li>
</ul>
<p>While in smaller teams or specific projects, a senior quant might write both the model and the production code themselves, these distinct areas of concern—the math and the engineering—remain the core pillars of quant finance.</p>
</section>
</section>
<section id="the-reality-of-the-daily-grind" class="level2">
<h2 class="anchored" data-anchor-id="the-reality-of-the-daily-grind">The Reality of the Daily Grind</h2>
<p>Life as a quant isn’t just solving theorems on a whiteboard. A huge chunk of your day is actually spent <strong>coding and testing</strong>. You might have a great idea for a model, but if you can’t implement it efficiently or prove that it works on historical data, it’s useless. You need to be comfortable with “messy” data—the kind that has holes, errors, and outliers that would make a pure mathematician cry.</p>
<p>There’s also a big <strong>communication</strong> aspect. You’ll often work with traders or managers who are brilliant at their jobs but don’t know a Taylor series from a Taylor Swift song. Being able to explain why a model is giving a certain result, without using Greek letters, is a superpower.</p>
<p>Finally, you have to deal with <strong>pressure and regulations</strong>. In some roles, if your code has a bug, you could lose millions of dollars in minutes. In others, you might spend weeks writing documentation for regulators to prove that your model isn’t going to blow up the economy. It’s a job that requires extreme attention to detail and a thick skin.</p>
</section>
<section id="where-to-look-for-work" class="level2">
<h2 class="anchored" data-anchor-id="where-to-look-for-work">Where to Look for Work?</h2>
<p>If you’re starting out, you have a few options depending on where you want to live.</p>
<p>In <strong>Poland</strong>, we have a surprisingly strong quant scene, with global institutions established in major cities (including UBS, BNY Mellon, Santander, Goldman Sachs, HSBC, and Revolut). Of course, the global hubs remain London, New York, and Hong Kong, but the barrier to entry has lowered significantly with the rise of remote and hybrid work.</p>
</section>
<section id="qa" class="level2">
<h2 class="anchored" data-anchor-id="qa">Q&amp;A</h2>
<p>In my discussions with students and aspiring professionals, several questions tend to come up repeatedly. Here they are, along with my answers, to help shed more light on the realities of this job:</p>
<section id="what-does-a-typical-day-look-like-in-this-job" class="level3">
<h3 class="anchored" data-anchor-id="what-does-a-typical-day-look-like-in-this-job">1. What does a typical day look like in this job?</h3>
<p>It really depends on the role you hold. There are many different “sub-species” of quants—ranging from those who work mostly with ready-made data from risk systems and Excel, to typical software developers who understand finance. I currently work in a role closer to the latter end of the spectrum (as a Quant Developer), though I also have more analytical experience.</p>
<p>My typical day looks something like this:</p>
<ul>
<li><strong>Starting the day (approx. 1h):</strong> I begin with code reviews. I am responsible for the technical quality and design consistency of the code written by quants and less experienced developers.</li>
<li><strong>Daily meeting (15 min):</strong> A brief status update for the team—what everyone did the day before, if anyone is blocked, and if they need to meet up with anyone. This usually leads to 1-on-1 meetings to sort out technical details or business requirements.</li>
<li><strong>Focused engineering work (approx. 4h):</strong> Time spent coding, which is often interrupted by various ad-hoc requests from the above.</li>
<li><strong>Afternoon (meetings):</strong> Meetings with managers or other teams from New York (NYC). These involve reporting weekly progress, cross-team alignment, resolving dependencies, etc.</li>
</ul>
</section>
<section id="is-this-job-stressful-or-exhausting" class="level3">
<h3 class="anchored" data-anchor-id="is-this-job-stressful-or-exhausting">2. Is this job stressful or exhausting?</h3>
<p>A lot depends on the work culture, the team and its management style, and the specific project.</p>
<p>Generally, the closer you are to the “money” (direct trading), the more stress there is. The most stressful environments are on the <em>buy-side</em> (trading, investment funds, hedge funds) or in <em>front-office</em> teams at <em>sell-side</em> institutions (investment banks). On the risk management side, things tend to be calmer, though there are still critical regulatory deadlines that impose pressure.</p>
<p>Even when everything goes smoothly, it is still an exhausting job because it is highly intellectual. For me, it is rewarding, but it does mean that I mostly have energy and time for private projects on weekends. Evenings after work are usually reserved for winding down—gaming, movies, or physical activity.</p>
</section>
<section id="what-are-the-biggest-challenges-when-working-as-a-quant" class="level3">
<h3 class="anchored" data-anchor-id="what-are-the-biggest-challenges-when-working-as-a-quant">3. What are the biggest challenges when working as a Quant?</h3>
<p>The biggest challenge is <strong>combining three worlds: mathematics, technology, and finance</strong>. That is a lot of knowledge to acquire and keep in your head. It is rare to find someone who is a top-tier expert in all three. You have to specialize, make trade-offs, and constantly study—which is sometimes exciting and other times exhausting.</p>
<p>The second challenge is <strong>communication</strong>. This juggling act doesn’t just happen inside your own head. You have to communicate with people who might be at a completely different spot on the Venn diagram of these three fields. Explaining mathematical complexities to a developer or technical limitations to a trader requires a lot of cognitive flexibility.</p>
</section>
<section id="what-gives-you-the-most-satisfaction" class="level3">
<h3 class="anchored" data-anchor-id="what-gives-you-the-most-satisfaction">4. What gives you the most satisfaction?</h3>
<p>This is a very personal question. In the projects I participate in, I try to push the philosophy of <em>“Make It Work, Make It Right, Make It Fast”</em> (dividing the work into three distinct stages).</p>
<p>For me, the most satisfying stage is <strong>“Make It Fast”</strong> (optimization). It is somewhat paradoxical since I currently specialize mainly in Python. Python’s strengths lie in its rich ecosystem of libraries and speed of development, not execution performance. But this introduces an interesting puzzle of optimization and balancing trade-offs, which I find highly rewarding.</p>
</section>
<section id="is-it-possible-to-stay-focused-all-day-when-i-code-i-can-focus-for-about-2-hours-and-then-it-gets-harder" class="level3">
<h3 class="anchored" data-anchor-id="is-it-possible-to-stay-focused-all-day-when-i-code-i-can-focus-for-about-2-hours-and-then-it-gets-harder">5. Is it possible to stay focused all day? When I code, I can focus for about 2 hours, and then it gets harder</h3>
<p>This is completely normal. I don’t think anyone can stay fully focused for 8 hours straight. On a good, productive day, I get maybe 6 hours of actual engineering work done, and sometimes it’s only 4 hours.</p>
<p>Furthermore, I never work on just a single task. Changes have to be reviewed by others from a technical and business perspective, so I usually juggle 3–4 tasks at once:</p>
<ul>
<li>one task is at the very end of the lifecycle (in code review),</li>
<li>one requires deeper design decisions and active coding,</li>
<li>one (more routine/technical) is running in the background, handled by an LLM agent.</li>
</ul>
<p>This kind of context switching actually helps me maintain focus, as long as the frequency of jumps is not too high. For someone in a more junior position, it’s typically 1–2 tasks at a time.</p>
</section>
</section>
<section id="final-thoughts" class="level2">
<h2 class="anchored" data-anchor-id="final-thoughts">Final Thoughts</h2>
<p>The transition from academia to finance can be jarring, but it’s incredibly rewarding if you like seeing your math have a direct, tangible impact on the world. If you’re interested in pursuing this path, my best advice is to get comfortable with Python or C++, learn the basics of probability, and start reading up on the “classics” of the field.</p>
<p><a href="../../resume/index.html">My Resume</a></p>
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further Reading</h2>
<section id="popular-books" class="level3">
<h3 class="anchored" data-anchor-id="popular-books">Popular Books</h3>
<ul>
<li><a href="https://www.amazon.com/Quants-Whizzes-Conquered-Street-Destroyed/dp/0307453383">The Quants: How a New Breed of Math Whizzes Conquered Wall Street and Nearly Destroyed It – Scott Patterson</a></li>
<li><a href="https://www.amazon.com/Random-Walk-Down-Wall-Street/dp/0393358380">A Random Walk Down Wall Street – Burton G. Malkiel</a></li>
<li><a href="https://www.amazon.com/Money-Formula-Finance-Science-Mathematicians/dp/1119358612">The Money Formula – Paul Wilmott, David Orrell</a></li>
</ul>
</section>
<section id="biographies" class="level3">
<h3 class="anchored" data-anchor-id="biographies">Biographies</h3>
<ul>
<li><a href="https://www.amazon.com/Man-All-Markets-Street-Dealer/dp/0812979907">A Man for All Markets – Edward O. Thorp</a></li>
<li><a href="https://www.amazon.com/Man-Who-Solved-Market-Revolution/dp/0593086317">The Man Who Solved the Market – Gregory Zuckerman</a></li>
<li><a href="https://www.amazon.com/My-Life-Quant-Reflections-Physics/dp/0470192739">My Life as a Quant – Emanuel Derman</a></li>
</ul>
</section>
<section id="technical-foundations" class="level3">
<h3 class="anchored" data-anchor-id="technical-foundations">Technical Foundations</h3>
<ul>
<li><a href="https://www.amazon.com/Financial-Calculus-Introduction-Derivative-Pricing/dp/0521552893">Financial Calculus: An Introduction to Derivative Pricing – Martin Baxter, Andrew Rennie</a></li>
<li><a href="https://www.amazon.com/Paul-Wilmott-Introduces-Quantitative-Finance/dp/0470319585">Paul Wilmott Introduces Quantitative Finance – Paul Wilmott</a></li>
<li><a href="https://www.amazon.com/Stochastic-Calculus-Finance-Binomial-Pricing/dp/0387401008">Stochastic Calculus for Finance I: The Binomial Asset Pricing Model – Steven Shreve</a></li>
<li><a href="https://www.amazon.com/Mathematical-Modeling-Computation-Finance-Exercises/dp/1786348055">Mathematical Modeling and Computation in Finance – Cornelis W Oosterlee &amp; Lech A Grzelak</a></li>
</ul>
</section>
<section id="interview-prep" class="level3">
<h3 class="anchored" data-anchor-id="interview-prep">Interview Prep</h3>
<ul>
<li><a href="https://www.amazon.com/Frequently-Asked-Questions-Quantitative-Finance/dp/0470748753">Frequently Asked Questions in Quantitative Finance – Paul Wilmott</a></li>
<li><a href="https://www.amazon.com/Joshi-Interview-Questions-Answers-Second/dp/B00NBE74RY">Quant Job Interview Questions and Answers – Mark Joshi</a></li>
<li><a href="https://www.amazon.com/Frequently-Asked-Questions-Quant-Interviews/dp/173453124X">150 Most Frequently Asked Questions on Quant Interviews – Dan Stefanica et al.</a></li>
</ul>
</section>
<section id="youtube-channels" class="level3">
<h3 class="anchored" data-anchor-id="youtube-channels">YouTube Channels</h3>
<ul>
<li><a href="https://www.youtube.com/computationsinfinance">Computations in Finance</a></li>
<li><a href="https://www.youtube.com/@DimitriBianco">Dimitri Bianco</a></li>
</ul>


</section>
</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Career</category>
  <category>Financial Markets</category>
  <guid>https://bwrob.github.io/posts/25-03-22-mathematician-in-finance/</guid>
  <pubDate>Sat, 22 Mar 2025 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/assets/images/posts/25-03-22-mathematician-in-finance/financial_whirlpool.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>Case Insensitive Enum</title>
  <link>https://bwrob.github.io/posts/25-10-10-recipes-case-insensitive-enum/</link>
  <description><![CDATA[ 






<p>When working with enums in Python, you might want to create an enum that is case-insensitive. This can be particularly useful when you want to allow users to input values without worrying about the case. Here’s how you can achieve this by subclassing <code>StrEnum</code>. To enforce that all enum members are defined in lowercase, we can use a hook <code>__init_subclass__</code>.</p>
<section id="implementation" class="level2">
<h2 class="anchored" data-anchor-id="implementation">Implementation</h2>
<div id="e9860b3b" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> __future__ <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> annotations</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> sys</span>
<span id="cb1-4"></span>
<span id="cb1-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> sys.version_info <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>):</span>
<span id="cb1-6">    <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> enum <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> StrEnum</span>
<span id="cb1-7">    <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Self, override</span>
<span id="cb1-8"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb1-9">    <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> backports.strenum <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> StrEnum</span>
<span id="cb1-10">    <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing_extensions <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Self, override</span>
<span id="cb1-11"></span>
<span id="cb1-12"></span>
<span id="cb1-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> CaseInsensitiveStrEnum(StrEnum):</span>
<span id="cb1-14">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""A case-insensitive string enum.</span></span>
<span id="cb1-15"></span>
<span id="cb1-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    This class extends the `StrEnum` class to provide case-insensitive member lookup.</span></span>
<span id="cb1-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    It also provides a custom `_generate_next_value_` method that returns the</span></span>
<span id="cb1-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    lowercase version of the member name for use with `auto()`.</span></span>
<span id="cb1-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb1-20"></span>
<span id="cb1-21">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@classmethod</span></span>
<span id="cb1-22">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init_subclass__</span>(cls, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, Any]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb1-23">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Implement the special hook that is called when a class is subclassed.</span></span>
<span id="cb1-24"></span>
<span id="cb1-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        It allows us to customize the class creation process without using metaclasses.</span></span>
<span id="cb1-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb1-27">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init_subclass__</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)</span>
<span id="cb1-28"></span>
<span id="cb1-29">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> member <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> cls:</span>
<span id="cb1-30">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> member.islower() <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> member.value.islower():</span>
<span id="cb1-31">                msg <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Member '</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>member<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">' and value </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>member<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>value<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> must be lowercase."</span></span>
<span id="cb1-32">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">TypeError</span>(msg)</span>
<span id="cb1-33"></span>
<span id="cb1-34">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@override</span></span>
<span id="cb1-35">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@staticmethod</span></span>
<span id="cb1-36">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> _generate_next_value_(</span>
<span id="cb1-37">        name: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, start: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, count: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, last_values: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>]</span>
<span id="cb1-38">    ) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>:</span>
<span id="cb1-39">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Return the lower-cased version of the member name.</span></span>
<span id="cb1-40"></span>
<span id="cb1-41"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        This method is overridden to ensure that when `auto()` is used to create</span></span>
<span id="cb1-42"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        enum members, their values are the lowercase version of their names.</span></span>
<span id="cb1-43"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb1-44">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> name.lower()</span>
<span id="cb1-45"></span>
<span id="cb1-46">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@override</span></span>
<span id="cb1-47">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@classmethod</span></span>
<span id="cb1-48">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> _missing_(cls, value: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">object</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Self <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb1-49">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Provide case-insensitive member lookup.</span></span>
<span id="cb1-50"></span>
<span id="cb1-51"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        This method is called when a value is not found in the enum.</span></span>
<span id="cb1-52"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        It is overridden to perform a case-insensitive search for the member.</span></span>
<span id="cb1-53"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb1-54">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(value, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb1-55">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb1-56"></span>
<span id="cb1-57">        value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> value.lower()</span>
<span id="cb1-58">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> member <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> cls:</span>
<span id="cb1-59">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> member.name.lower() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> value:</span>
<span id="cb1-60">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> member</span>
<span id="cb1-61"></span>
<span id="cb1-62">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span></code></pre></div></div>
</details>
</div>
</section>
<section id="example-usage" class="level2">
<h2 class="anchored" data-anchor-id="example-usage">Example Usage</h2>
<p>Here is an example of how to use the <code>CaseInsensitiveStrEnum</code> class:</p>
<div id="5b612a6f" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> enum <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> auto</span>
<span id="cb2-2"></span>
<span id="cb2-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> TestEnum(CaseInsensitiveStrEnum):</span>
<span id="cb2-4">    test <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> auto()</span>
<span id="cb2-5">    enumz <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> auto()</span>
<span id="cb2-6"></span>
<span id="cb2-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"List of members: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>[member.name <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> member <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> TestEnum]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb2-8"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"List of values: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>[member.value <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> member <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> TestEnum]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb2-9"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'Accessing "Test": </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>TestEnum(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Test"</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span>
<span id="cb2-10"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'Accessing "test": </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>TestEnum(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"test"</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span>
<span id="cb2-11"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'Accessing "ENUMZ": </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>TestEnum(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ENUMZ"</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span>
<span id="cb2-12"></span>
<span id="cb2-13"></span>
<span id="cb2-14"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb2-15">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> TestEnum(CaseInsensitiveStrEnum):</span>
<span id="cb2-16">        TEST <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TEST"</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This will raise a TypeError</span></span>
<span id="cb2-17"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">TypeError</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> e:</span>
<span id="cb2-18">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(e)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>List of members: ['test', 'enumz']
List of values: ['test', 'enumz']
Accessing "Test": test
Accessing "test": test
Accessing "ENUMZ": enumz
Member 'TEST' and value TEST must be lowercase.</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Download the whole code <a href="../../assets/python/case_insensitive_str_enum_implementation.py">here</a>.</p>
</div>
</div>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Python Recipes</category>
  <guid>https://bwrob.github.io/posts/25-10-10-recipes-case-insensitive-enum/</guid>
  <pubDate>Wed, 04 Dec 2024 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/posts/25-10-10-recipes-case-insensitive-enum/cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Visualizing Pydantic Models</title>
  <link>https://bwrob.github.io/posts/24-10-11-recipes-pydantic-tree-walker/</link>
  <description><![CDATA[ 






<p>If you’ve ever worked with complex Pydantic models, you know it can be tough to see how they’re structured. This post shows you a Python script that can help by displaying your models as a tree in the console.</p>
<section id="the-script" class="level2">
<h2 class="anchored" data-anchor-id="the-script">The Script</h2>
<p>The script uses the <code>rich</code> library to make the output colorful and easy to read.</p>
<div id="692dd1f9" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ruff: noqa: ANN401</span></span>
<span id="cb1-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># pyright: reportAny=false, reportExplicitAny=false</span></span>
<span id="cb1-3"></span>
<span id="cb1-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> collections.abc <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Generator</span>
<span id="cb1-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Any, TypeVar, get_args, get_origin</span>
<span id="cb1-6"></span>
<span id="cb1-7"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> pydantic <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> BaseModel</span>
<span id="cb1-8"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> rich.console <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Console</span>
<span id="cb1-9"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> rich.markup <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> escape</span>
<span id="cb1-10"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> rich.tree <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Tree</span>
<span id="cb1-11"></span>
<span id="cb1-12">console <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Console()</span>
<span id="cb1-13">COLORS <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cyan"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"green"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"yellow"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"orange"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"red"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"magenta"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"blue"</span>]</span>
<span id="cb1-14">TYPE_COLOR <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bright_black"</span></span>
<span id="cb1-15"></span>
<span id="cb1-16">Model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> TypeVar(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Model"</span>, bound<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>BaseModel)</span>
<span id="cb1-17"></span>
<span id="cb1-18"></span>
<span id="cb1-19"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> create_label(name: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, color: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, type_str: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>:</span>
<span id="cb1-20">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Create a formatted label for the tree."""</span></span>
<span id="cb1-21">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> type_str:</span>
<span id="cb1-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"[</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>color<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">]</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">[/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>color<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">]: [</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>TYPE_COLOR<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">]</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>type_str<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">[/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>TYPE_COLOR<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">]"</span></span>
<span id="cb1-23">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"[</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>color<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">]</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">[/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>color<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">]"</span></span>
<span id="cb1-24"></span>
<span id="cb1-25"></span>
<span id="cb1-26"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> is_pydantic_model(type_: Any) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>:</span>
<span id="cb1-27">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Check if a type is a Pydantic model.</span></span>
<span id="cb1-28"></span>
<span id="cb1-29"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    This is useful for introspection and for handling Pydantic models</span></span>
<span id="cb1-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    differently from other types.</span></span>
<span id="cb1-31"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb1-32">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb1-33">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">issubclass</span>(type_, BaseModel)</span>
<span id="cb1-34">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">TypeError</span>:</span>
<span id="cb1-35">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span></span>
<span id="cb1-36"></span>
<span id="cb1-37"></span>
<span id="cb1-38"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_model_fields(type_: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>[Any]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Generator[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, Any]]:</span>
<span id="cb1-39">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Yield the fields and their types for a given model.</span></span>
<span id="cb1-40"></span>
<span id="cb1-41"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    This function supports Pydantic models, making it a</span></span>
<span id="cb1-42"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    key part of the model introspection process.</span></span>
<span id="cb1-43"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb1-44">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> is_pydantic_model(type_):</span>
<span id="cb1-45">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> name, info <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> type_.model_fields.items():</span>
<span id="cb1-46">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> name, info.annotation</span>
<span id="cb1-47"></span>
<span id="cb1-48"></span>
<span id="cb1-49"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_type_name(type_: Any) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>:</span>
<span id="cb1-50">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Get the name of a type, or its string representation if it has no name."""</span></span>
<span id="cb1-51">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb1-52">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> type_.<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span></span>
<span id="cb1-53">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttributeError</span>:</span>
<span id="cb1-54">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(type_)</span>
<span id="cb1-55"></span>
<span id="cb1-56"></span>
<span id="cb1-57"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> type_to_string(type_: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>:</span>
<span id="cb1-58">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Convert a type to a string representation.</span></span>
<span id="cb1-59"></span>
<span id="cb1-60"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    This function can handle generic types like `list[int]` and `Union[str, int]`,</span></span>
<span id="cb1-61"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    which is essential for displaying complex type hints in a readable format.</span></span>
<span id="cb1-62"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb1-63">    origin <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_origin(type_)</span>
<span id="cb1-64">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> origin <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb1-65">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> get_type_name(type_)</span>
<span id="cb1-66"></span>
<span id="cb1-67">    args_str <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">", "</span>.join(type_to_string(t) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> t <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> get_args(type_))</span>
<span id="cb1-68">    base_type <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_type_name(origin)</span>
<span id="cb1-69">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>base_type<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">[</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>args_str<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">]"</span></span>
<span id="cb1-70"></span>
<span id="cb1-71"></span>
<span id="cb1-72"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> extract_model_types(type_: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Generator[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>[Any]]:</span>
<span id="cb1-73">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Recursively extract model types from a composite type.</span></span>
<span id="cb1-74"></span>
<span id="cb1-75"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    For example, from `list[Union[ModelA, str, ModelB]]`, it will yield</span></span>
<span id="cb1-76"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    `ModelA` and `ModelB`. This is crucial for traversing nested models</span></span>
<span id="cb1-77"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    within generic containers.</span></span>
<span id="cb1-78"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb1-79">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> is_pydantic_model(type_):</span>
<span id="cb1-80">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> type_</span>
<span id="cb1-81"></span>
<span id="cb1-82">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> arg <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> get_args(type_):</span>
<span id="cb1-83">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> extract_model_types(arg)</span>
<span id="cb1-84"></span>
<span id="cb1-85"></span>
<span id="cb1-86"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> build_tree(model: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>[Any], tree: Tree, level: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb1-87">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Recursively build a tree representation of a model.</span></span>
<span id="cb1-88"></span>
<span id="cb1-89"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    This function traverses the model's fields, adding each field and its type</span></span>
<span id="cb1-90"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    to the tree. It handles nested models and generic types, ensuring a comprehensive</span></span>
<span id="cb1-91"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    representation of the model's structure.</span></span>
<span id="cb1-92"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb1-93">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> name, field_type <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> get_model_fields(model):</span>
<span id="cb1-94">        color <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> COLORS[level <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(COLORS)]</span>
<span id="cb1-95">        type_str <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> escape(type_to_string(field_type))</span>
<span id="cb1-96">        label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> create_label(name, color, type_str)</span>
<span id="cb1-97">        child_tree <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tree.add(label)</span>
<span id="cb1-98">        model_types <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(extract_model_types(field_type))</span>
<span id="cb1-99"></span>
<span id="cb1-100">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(model_types) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> model_types[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> field_type:</span>
<span id="cb1-101">            build_tree(model_types[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], child_tree, level <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb1-102">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">continue</span></span>
<span id="cb1-103"></span>
<span id="cb1-104">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> model_type <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> model_types:</span>
<span id="cb1-105">            sub_tree_label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> create_label(model_type.<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span>, COLORS[level <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb1-106">            sub_tree <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> child_tree.add(sub_tree_label)</span>
<span id="cb1-107">            build_tree(model_type, sub_tree, level <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb1-108"></span>
<span id="cb1-109"></span>
<span id="cb1-110"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> display_tree(model: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>[Any]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb1-111">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Print a colorful, tree-like representation of a model to the console.</span></span>
<span id="cb1-112"></span>
<span id="cb1-113"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    The indentation of each line indicates its depth in the model structure,</span></span>
<span id="cb1-114"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    making it easy to visualize the model's composition.</span></span>
<span id="cb1-115"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb1-116">    tree <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Tree(create_label(model.<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span>, COLORS[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]))</span>
<span id="cb1-117">    build_tree(model, tree)</span>
<span id="cb1-118">    console.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(tree)</span></code></pre></div></div>
</details>
</div>
</section>
<section id="example-usage" class="level2">
<h2 class="anchored" data-anchor-id="example-usage">Example Usage</h2>
<p>When you run the script, it will display the structure of the <code>Root</code> model as a tree:</p>
<div id="b4920f5f" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> InnerNode(BaseModel):</span>
<span id="cb2-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Inner node model for testing."""</span></span>
<span id="cb2-3"></span>
<span id="cb2-4">    name: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb2-5">    id_number: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span></span>
<span id="cb2-6"></span>
<span id="cb2-7"></span>
<span id="cb2-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> AnotherInnerNode(BaseModel):</span>
<span id="cb2-9">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Another inner node model for testing."""</span></span>
<span id="cb2-10"></span>
<span id="cb2-11">    age: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span></span>
<span id="cb2-12">    weight: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span></span>
<span id="cb2-13"></span>
<span id="cb2-14"></span>
<span id="cb2-15"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Node(BaseModel):</span>
<span id="cb2-16">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Node model for testing."""</span></span>
<span id="cb2-17"></span>
<span id="cb2-18">    name: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb2-19">    inner: InnerNode</span>
<span id="cb2-20">    many_inner: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[InnerNode]</span>
<span id="cb2-21">    many_union_inner: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[InnerNode <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> AnotherInnerNode]</span>
<span id="cb2-22">    dict_union_inner: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, AnotherInnerNode]</span>
<span id="cb2-23"></span>
<span id="cb2-24"></span>
<span id="cb2-25"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Root(BaseModel):</span>
<span id="cb2-26">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Root model for testing."""</span></span>
<span id="cb2-27"></span>
<span id="cb2-28">    name: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb2-29">    child: Node</span>
<span id="cb2-30"></span>
<span id="cb2-31"></span>
<span id="cb2-32">display_tree(Root)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-display">
<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="color: #008080; text-decoration-color: #008080">Root</span>
├── <span style="color: #008080; text-decoration-color: #008080">name</span>: <span style="color: #808080; text-decoration-color: #808080">str</span>
└── <span style="color: #008080; text-decoration-color: #008080">child</span>: <span style="color: #808080; text-decoration-color: #808080">Node</span>
    ├── <span style="color: #008000; text-decoration-color: #008000">name</span>: <span style="color: #808080; text-decoration-color: #808080">str</span>
    ├── <span style="color: #008000; text-decoration-color: #008000">inner</span>: <span style="color: #808080; text-decoration-color: #808080">InnerNode</span>
    │   ├── <span style="color: #808000; text-decoration-color: #808000">name</span>: <span style="color: #808080; text-decoration-color: #808080">str</span>
    │   └── <span style="color: #808000; text-decoration-color: #808000">id_number</span>: <span style="color: #808080; text-decoration-color: #808080">int</span>
    ├── <span style="color: #008000; text-decoration-color: #008000">many_inner</span>: <span style="color: #808080; text-decoration-color: #808080">list[InnerNode]</span>
    │   └── <span style="color: #808000; text-decoration-color: #808000">InnerNode</span>
    │       ├── name: <span style="color: #808080; text-decoration-color: #808080">str</span>
    │       └── id_number: <span style="color: #808080; text-decoration-color: #808080">int</span>
    ├── <span style="color: #008000; text-decoration-color: #008000">many_union_inner</span>: <span style="color: #808080; text-decoration-color: #808080">list[UnionType[InnerNode, AnotherInnerNode]]</span>
    │   ├── <span style="color: #808000; text-decoration-color: #808000">InnerNode</span>
    │   │   ├── name: <span style="color: #808080; text-decoration-color: #808080">str</span>
    │   │   └── id_number: <span style="color: #808080; text-decoration-color: #808080">int</span>
    │   └── <span style="color: #808000; text-decoration-color: #808000">AnotherInnerNode</span>
    │       ├── age: <span style="color: #808080; text-decoration-color: #808080">int</span>
    │       └── weight: <span style="color: #808080; text-decoration-color: #808080">float</span>
    └── <span style="color: #008000; text-decoration-color: #008000">dict_union_inner</span>: <span style="color: #808080; text-decoration-color: #808080">dict[str, AnotherInnerNode]</span>
        └── <span style="color: #808000; text-decoration-color: #808000">AnotherInnerNode</span>
            ├── age: <span style="color: #808080; text-decoration-color: #808080">int</span>
            └── weight: <span style="color: #808080; text-decoration-color: #808080">float</span>
</pre>
</div>
</div>
</section>
<section id="code-explanation" class="level2">
<h2 class="anchored" data-anchor-id="code-explanation">Code Explanation</h2>
<p>Let’s look at the main parts of the script.</p>
<section id="display_tree-and-build_tree" class="level3">
<h3 class="anchored" data-anchor-id="display_tree-and-build_tree">display_tree and build_tree</h3>
<p><code>display_tree</code> is where it all starts. It creates a <code>rich.tree.Tree</code> and then calls <code>build_tree</code> to fill it up. <code>build_tree</code> goes through the model’s fields, makes a label for each one, and then calls itself if it finds any nested models.</p>
</section>
<section id="type_to_string" class="level3">
<h3 class="anchored" data-anchor-id="type_to_string">type_to_string</h3>
<p>This function turns a type hint into a string. It can handle generic types like <code>list</code>, <code>dict</code>, and <code>Union</code> by using <code>get_origin</code> and <code>get_args</code> from the <code>typing</code> module. It also escapes any square brackets in the type string so <code>rich</code> can render it correctly.</p>
</section>
<section id="extract_model_types" class="level3">
<h3 class="anchored" data-anchor-id="extract_model_types">extract_model_types</h3>
<p>This function pulls out Pydantic model types from a composite type. For example, if you have <code>list[Union[ModelA, str, ModelB]]</code>, it will give you <code>ModelA</code> and <code>ModelB</code>. This is how the script explores nested models inside other types.</p>
</section>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>This script is a simple way to see what your Pydantic models look like. The <code>rich</code> library helps make the output clear and colorful, which is a big help when you’re dealing with complex data.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Download the whole code <a href="../../assets/python/pydantic_recursive_model_tree_walker_utility.py">here</a>.</p>
</div>
</div>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Python Recipes</category>
  <guid>https://bwrob.github.io/posts/24-10-11-recipes-pydantic-tree-walker/</guid>
  <pubDate>Fri, 11 Oct 2024 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/posts/24-10-11-recipes-pydantic-tree-walker/cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Prettify Dev Terminal Setup</title>
  <link>https://bwrob.github.io/posts/24-08-18-linux-shell-setup/</link>
  <description><![CDATA[ 






<section id="oh-my-posh" class="level2">
<h2 class="anchored" data-anchor-id="oh-my-posh">Oh my posh</h2>
<p>Oh My Posh is a prompt theme engine for any shell, including Zsh. It allows you to customize your terminal prompt with themes and segments.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb1-1">brew install jandedobbeleer/oh-my-posh/oh-my-posh</span>
<span id="cb1-2">echo 'eval "$(oh-my-posh init zsh)"' &gt;&gt; .zshrc</span>
<span id="cb1-3">echo 'OH_MY_POSH_THEME="kali"' &gt;&gt; .zshrc</span></code></pre></div></div>
</section>
<section id="autosuggestions" class="level2">
<h2 class="anchored" data-anchor-id="autosuggestions">autosuggestions</h2>
<p>Zsh autosuggestions provide command suggestions based on your history and current input, enhancing your command line experience.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb2-1">brew install zsh-autosuggestions</span>
<span id="cb2-2"># To activate the autosuggestions, add the following at the end of your .zshrc:</span>
<span id="cb2-3">source $(brew --prefix)/share/zsh-autosuggestions/zsh-autosuggestions.zsh</span></code></pre></div></div>
</section>
<section id="aliases" class="level2">
<h2 class="anchored" data-anchor-id="aliases">Aliases</h2>
<p>Create a file <code>~/.bash_aliases</code> and add your aliases there, or directly in <code>.zshrc</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb3-1"># Alias definitions.</span>
<span id="cb3-2"># You may want to put all your additions into a separate file like</span>
<span id="cb3-3"># ~/.bash_aliases, instead of adding them here directly.</span>
<span id="cb3-4"># See /usr/share/doc/bash-doc/examples in the bash-doc package.</span>
<span id="cb3-5"></span>
<span id="cb3-6">if [ -f ~/.bash_aliases ]; then</span>
<span id="cb3-7">    . ~/.bash_aliases</span>
<span id="cb3-8">fi</span>
<span id="cb3-9"></span>
<span id="cb3-10">alias zshconfig='nano ~/.zshrc'</span>
<span id="cb3-11">alias ls='eza -la --group-directories-first --icons'</span></code></pre></div></div>
</section>
<section id="minor-packages" class="level2">
<h2 class="anchored" data-anchor-id="minor-packages">Minor packages</h2>
<section id="fzf" class="level3">
<h3 class="anchored" data-anchor-id="fzf">fzf</h3>
<p>Fuzzy finder for command line, useful for searching files, history, etc.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb4-1">brew install fzf</span>
<span id="cb4-2"># Set up fzf key bindings and fuzzy completion</span>
<span id="cb4-3">echo 'source &lt;(fzf --zsh)' &gt;&gt; .zshrc</span></code></pre></div></div>
</section>
<section id="eza" class="level3">
<h3 class="anchored" data-anchor-id="eza">eza</h3>
<p>Better alternative to <code>ls</code> with icons and better defaults.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb5-1">brew install eza</span>
<span id="cb5-2">echo 'alias ls='eza -la --group-directories-first --icons'' &gt;&gt; .zshrc</span></code></pre></div></div>
</section>
<section id="thefuck" class="level3">
<h3 class="anchored" data-anchor-id="thefuck">thefuck</h3>
<p>A tool to correct mistyped commands in the terminal.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb6-1">brew install thefuck</span>
<span id="cb6-2">echo 'eval $(thefuck --alias)' &gt;&gt; .zshrc</span></code></pre></div></div>
</section>
<section id="tmux" class="level3">
<h3 class="anchored" data-anchor-id="tmux">tmux</h3>
<p>A terminal multiplexer that allows you to manage multiple terminal sessions from a single window.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb7-1">brew install tmux</span>
<span id="cb7-2">echo 'alias tmux="tmux -2"' &gt;&gt; .zshrc</span></code></pre></div></div>
</section>
<section id="fastfetch" class="level3">
<h3 class="anchored" data-anchor-id="fastfetch">fastfetch</h3>
<p>A tool to display system information in the terminal, similar to neofetch but faster.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb8-1">brew install fastfetch</span>
<span id="cb8-2">echo 'alias ff="fastfetch"' &gt;&gt; .zshrc</span>
<span id="cb8-3">echo 'ff' &gt;&gt; .zshrc</span></code></pre></div></div>


</section>
</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Dev Env</category>
  <guid>https://bwrob.github.io/posts/24-08-18-linux-shell-setup/</guid>
  <pubDate>Sun, 18 Aug 2024 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/assets/images/posts/24-08-18-linux-shell-setup/terminal.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>Linux in Windows via WSL</title>
  <link>https://bwrob.github.io/posts/24-08-11-linux-in-windows/</link>
  <description><![CDATA[ 






<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/24-08-11-linux-in-windows/image.jpg" class="lightbox" data-gallery="quarto-lightbox-gallery-1"><img src="https://bwrob.github.io/assets/images/posts/24-08-11-linux-in-windows/image.jpg" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:95.0%"></a></p>
</figure>
</div>
<section id="windows-linux-and-you-ménage-à-trois" class="level2">
<h2 class="anchored" data-anchor-id="windows-linux-and-you-ménage-à-trois">Windows, Linux, and You: Ménage à trois</h2>
<p>Tired of the same old Windows vs.&nbsp;Linux beef among PC superusers? Well, get ready to become a mediator in this feud. I’ll show you how to get the best of both worlds.</p>
<section id="pros-and-cons" class="level3">
<h3 class="anchored" data-anchor-id="pros-and-cons">Pros and cons</h3>
<p>Windows OS has long been the dominant platform for mainstream consumers and businesses. It offers good hardware compatibility, de facto <em>the</em> PC gaming experience and is friendly to the casual user. However, Windows has significant limitations in terms of system control and software development tools.</p>
<p>Linux, on the other hand, is an operating system created by developers and for developers (and system administrators). It provides infinite flexibility and a deep pool of open-source tools. But the learning curve is steep, the open-source projects often get abandoned and with great power (<code>sudo</code>) comes great responsibility (and sometimes system reinstall).</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Actually, to publish this post in the most convenient and elegant <a href="https://quarto.org/docs/publishing/github-pages.html#publish-command">way</a>, I needed to switch to Linux. The Windows <code>quarto</code> CLI fails with some certification errors, coming from <code>deno</code>, that I can’t be bothered to clean up. Discovered this while writing these words as <a href="https://quarto.org/docs/publishing/github-pages.html#render-to-docs">my previous approach</a> was much messier. Irony is the ambrosia of life (for me at least).</p>
</div>
</div>
</section>
<section id="bridging-the-gap" class="level3">
<h3 class="anchored" data-anchor-id="bridging-the-gap">Bridging the gap</h3>
<p>At this point even Microsoft — a strong contrarian to Linux in the past — embraced the usefulness of Linux shell at your fingertips. Imagine having the familiar interface of Windows for your everyday tasks. Combine it with a the raw power and controllability of Linux for when you need to dive deep into development or system administration. And limited stakes once you (inevitably) remove half of your file system with a bash script. Enter Windows Subsystem for Linux (WSL): a ticket to 10x-ing your software development on Windows.</p>
</section>
<section id="wsl-vs.-virtual-machines-whats-the-difference" class="level3">
<h3 class="anchored" data-anchor-id="wsl-vs.-virtual-machines-whats-the-difference">WSL vs.&nbsp;Virtual Machines: What’s the Difference?</h3>
<p>You might be wondering how WSL differs from a traditional virtual machine (VM). While both provide a way to run Linux on Windows, they operate in different ways. A VM emulates a virtual computer within your computer, complete with its own operating system and make-belive hardware resources. This makes VMs resource-intensive and can impact overall system performance. They are also hard to set up and maintain.</p>
<p>WSL, on the other hand, is a more lightweight approach. It integrates Linux directly into the Windows kernel, allowing for faster boot times, better performance, and seamless file sharing between Windows and Linux environments.</p>
</section>
</section>
<section id="installing-and-setting-up-wsl" class="level2">
<h2 class="anchored" data-anchor-id="installing-and-setting-up-wsl">Installing and setting up WSL</h2>
<p>First, we need to set up the WSL and install a chosen Linux distribution. Fortunately, this is “super easy, barely an inconvenience”. You can choose from a list of distros pre-packaged by Microsoft or download and build an image from scratch. You can even build Arch and be legally allowed to say <code>BTW, I use Arch (on Windows)</code>. For this guide, we’ll take a more conventional approach and opt for the long-term support (LTS) version of Ubuntu. Now, open the Powershell with administrative privileges and run:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource {shell} number-lines code-with-copy"><code class="sourceCode"><span id="cb1-1">wsl --update</span>
<span id="cb1-2">wsl --version</span></code></pre></div></div>
<p>These commands ensure that WSL is up-to-date and displays the installed WSL version.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/24-08-11-linux-in-windows/1.png" class="lightbox" data-gallery="quarto-lightbox-gallery-2"><img src="https://bwrob.github.io/assets/images/posts/24-08-11-linux-in-windows/1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:90.0%"></a></p>
</figure>
</div>
<p>Our next command will be:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource {shell} number-lines code-with-copy"><code class="sourceCode"><span id="cb2-1">wsl -l -o</span></code></pre></div></div>
<p>This yields a curated list of pre-packaged Linux distributions that Microsoft provides, making the process almost effortless.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/24-08-11-linux-in-windows/2.png" class="lightbox" data-gallery="quarto-lightbox-gallery-3"><img src="https://bwrob.github.io/assets/images/posts/24-08-11-linux-in-windows/2.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:90.0%"></a></p>
</figure>
</div>
<p>For the installation itself:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource {shell} number-lines code-with-copy"><code class="sourceCode"><span id="cb3-1">wsl --install -d 'Ubuntu-24.04'</span></code></pre></div></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/24-08-11-linux-in-windows/3.png" class="lightbox" data-gallery="quarto-lightbox-gallery-4"><img src="https://bwrob.github.io/assets/images/posts/24-08-11-linux-in-windows/3.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:90.0%"></a></p>
</figure>
</div>
<p>Reboot the Windows system and you’ll see `Ubuntu’ among your applications.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/24-08-11-linux-in-windows/4.png" class="lightbox" data-gallery="quarto-lightbox-gallery-5"><img src="https://bwrob.github.io/assets/images/posts/24-08-11-linux-in-windows/4.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:90.0%"></a></p>
</figure>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/24-08-11-linux-in-windows/5.png" class="lightbox" data-gallery="quarto-lightbox-gallery-6"><img src="https://bwrob.github.io/assets/images/posts/24-08-11-linux-in-windows/5.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:90.0%"></a></p>
</figure>
</div>
</section>
<section id="base-setup-new-shell-and-package-manager" class="level2">
<h2 class="anchored" data-anchor-id="base-setup-new-shell-and-package-manager">Base setup — new shell and package manager</h2>
<p>There is an additional benefit we can reap with just a bit of more work — a fully system-agnostic setup. By having Linux kernel run on Windows, we unified 2 out of 3 giants. The only pillar that is missing is the Mac OS. But wait, it’s based on Unix as well! It just uses different default shell and lacks a package manager, as Apple doesn’t trust its clients. <code>zsh</code> offers a more interactive and customizable shell experience compared to the default bash. Homebrew, often referred to as the “missing package manager for macOS”, provides a convenient way to install additional software on Linux systems. Let’s change the terminal shell to <code>zsh</code> in our Ubuntu installation and compile a secondary (to <code>apt-get</code>) package manager – <code>brew</code>.</p>
<section id="brewing-starts" class="level3">
<h3 class="anchored" data-anchor-id="brewing-starts">Brewing starts</h3>
<p>Before we dive into installing Homebrew, we need to equip our system with the essential tools. The build-essential package provides a collection of compilers and libraries necessary for building software from the source code. Git is a version control system used for managing code projects.</p>
<p>Let’s install these prerequisites using the following command:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb4-1">sudo apt-get upgrade -y</span>
<span id="cb4-2">sudo apt-get install build-essential git -y</span></code></pre></div></div>
<p>Execute the installation script for Homebrew:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb5-1">INSTALL_PATH="https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh"</span>
<span id="cb5-2">/bin/bash -c "$(curl -fsSL $INSTALL_PATH)"</span></code></pre></div></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/24-08-11-linux-in-windows/6.png" class="lightbox" data-gallery="quarto-lightbox-gallery-7"><img src="https://bwrob.github.io/assets/images/posts/24-08-11-linux-in-windows/6.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:90.0%"></a></p>
</figure>
</div>
<p>To make Homebrew accessible from your shell, you need to load its environment variables. The following command achieves this and subsequently runs a diagnostic check:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb6-1">eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"</span>
<span id="cb6-2">brew doctor</span></code></pre></div></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/24-08-11-linux-in-windows/7.png" class="lightbox" data-gallery="quarto-lightbox-gallery-8"><img src="https://bwrob.github.io/assets/images/posts/24-08-11-linux-in-windows/7.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:90.0%"></a></p>
</figure>
</div>
<p>Doctor’s orders to append brew to some set of paths! Let’s do this then:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb7-1">echo 'export XDG_DATA_DIRS="/home/linuxbrew/.linuxbrew/share:$XDG_DATA_DIRS"' &gt;&gt; ~/.profile</span></code></pre></div></div>
</section>
</section>
<section id="z-shell-sea-shell" class="level2">
<h2 class="anchored" data-anchor-id="z-shell-sea-shell">Z-shell — sea-shell</h2>
<p>Homebrew makes package management a breeze. Let’s install <code>zsh</code>, a powerful and customizable shell.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb8-1">brew install zsh</span>
<span id="cb8-2">zsh --version</span>
<span id="cb8-3">zsh</span></code></pre></div></div>
<p>This will take you to interactive <code>.zshrc</code> file setup. The file contains commands that are run each time a shell is spawned. You can either generate empty file with <code>0</code> or go through the interactive setup with <code>1</code>.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/24-08-11-linux-in-windows/8.png" class="lightbox" data-gallery="quarto-lightbox-gallery-9"><img src="https://bwrob.github.io/assets/images/posts/24-08-11-linux-in-windows/8.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:90.0%"></a></p>
</figure>
</div>
<p>Add the brew initialization to <code>.zshrc</code> file as well. This way <code>brew</code> will always be by your side!</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb9-1">(echo; echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"') &gt;&gt; /home/bwrob/.zshrc</span></code></pre></div></div>
<p>Check the default shell and set it to <code>zsh</code>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb10-1">echo $SHELL</span>
<span id="cb10-2">sudo chsh -s $(which zsh)</span>
<span id="cb10-3">echo $SHELL</span></code></pre></div></div>
</section>
<section id="github-command-line-tool" class="level2">
<h2 class="anchored" data-anchor-id="github-command-line-tool">GitHub command line tool</h2>
<p>Remember <code>git != GitHub</code>, we need a way to authenticate and use Github from CLI. There’s a tool for that!</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb11-1">brew install gh</span>
<span id="cb11-2">gh auth login</span></code></pre></div></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/24-08-11-linux-in-windows/9.png" class="lightbox" data-gallery="quarto-lightbox-gallery-10"><img src="https://bwrob.github.io/assets/images/posts/24-08-11-linux-in-windows/9.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:90.0%"></a></p>
</figure>
</div>
<p>Now create a convenient directory and copy your favourite <code>GitHub</code> repo:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb12-1">mkdir repos &amp;&amp; cd repos</span>
<span id="cb12-2">gh repo clone python_playground</span></code></pre></div></div>
</section>
<section id="connect-to-visual-studio-code" class="level2">
<h2 class="anchored" data-anchor-id="connect-to-visual-studio-code">Connect to Visual Studio Code</h2>
<p>While WSL grants us the power of Linux, let’s not forget the user-friendly interface of Windows. When it comes to software development, we can achieve the perfect blend by integrating Visual Studio Code (VSC) with our WSL environment.</p>
<p>Here’s how:</p>
<ul>
<li><p><strong>Install the WSL Extension in VSC</strong>: Fire up VSC on your Windows machine and head over to the Extensions tab. Search for “WSL” and install the official extension by Microsoft: <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl">WSL extension</a>.</p></li>
<li><p><strong>Launching VSC from WSL</strong>: Within your WSL terminal, you can directly invoke VSC as if it were running natively on Windows. Use the following command:</p></li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode numberSource {bash} number-lines code-with-copy"><code class="sourceCode"><span id="cb13-1">code ~\repos\python_playground</span></code></pre></div></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="../../assets/images/posts/24-08-11-linux-in-windows/10.png" class="lightbox" data-gallery="quarto-lightbox-gallery-11"><img src="https://bwrob.github.io/assets/images/posts/24-08-11-linux-in-windows/10.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:90.0%"></a></p>
</figure>
</div>
<p>In the <a href="../../posts/24-08-11-linux-python-dev-env/index.html">next post</a> I will show you how to set up Python environment in Linux. Stay tuned :) .</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Download the Ubuntu shell script <a href="wsl_setup.sh">here</a>.</p>
</div>
</div>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Dev Env</category>
  <guid>https://bwrob.github.io/posts/24-08-11-linux-in-windows/</guid>
  <pubDate>Sun, 11 Aug 2024 00:00:00 GMT</pubDate>
  <media:content url="https://bwrob.github.io/assets/images/posts/24-08-11-linux-in-windows/image.jpg" medium="image" type="image/jpeg"/>
</item>
</channel>
</rss>
