<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>Quants Quest</title>
  <subtitle>Essays and research notes on quantitative finance, deep learning, and time series by Balthazar Courvoisier. Theory, intuition, and practical Python implementations.</subtitle>
  <link href="https://quants.quest/feed.xml" rel="self" type="application/atom+xml" />
  <link href="https://quants.quest/" rel="alternate" type="text/html" />
  <id>https://quants.quest/</id>
  <updated>2026-10-04T14:01:45+00:00</updated>
  <author><name>Balthazar Courvoisier</name><uri>https://quants.quest/about_me/</uri></author>
  
  
  <entry>
    <title type="html">Signed Dual Attention Explained</title>
    <link href="https://quants.quest/SignedDualAttention/" rel="alternate" type="text/html" />
    <id>https://quants.quest/SignedDualAttention</id>
    <published>2026-10-04T00:00:00+00:00</published>
    <updated>2026-10-04T00:00:00+00:00</updated>
    <summary type="html">Discover Signed Dual Attention: an approach to model both positive and negative relationships in deep learning</summary>
    <content type="html" xml:base="https://quants.quest/SignedDualAttention/">&lt;p&gt;In this post I will try my best to explain my latest work, the Signed Dual Attention (SDA) mechanism, developed with Tristan Cazenave as part of my PhD and presented at the AI4TS workshop (AAAI 2026).&lt;/p&gt;

&lt;h2 id=&quot;table-of-content&quot;&gt;Table of Content&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;#why-sda&quot;&gt;How Rethinking Attention Led Me to SDA&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#how-sda-works&quot;&gt;How Signed Dual Attention Works&lt;/a&gt;&lt;br /&gt;
2.1 &lt;a href=&quot;#mathematical-formulation&quot;&gt;Mathematical Formulation&lt;/a&gt;&lt;br /&gt;
2.2 &lt;a href=&quot;#link-with-two-head-attention&quot;&gt;Link with Two-Head Attention&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#future-directions&quot;&gt;Future Directions&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;why-sda&quot;&gt;How Rethinking Attention Led Me to SDA&lt;/h2&gt;

&lt;p&gt;This work began with a critical reflection on the Transformer architecture, inspired by my ongoing research on Graph Neural Networks. Attention can, in fact, be viewed as a fully connected graph. From this perspective, the attention matrix can be interpreted as a learned adjacency matrix.&lt;/p&gt;

&lt;p&gt;Given my background in statistics and classical time series analysis, one of the most intuitive adjacency matrices that came to mind was the correlation matrix. Indeed, in terms of raw formulation, the similarity matrix corresponds to the correlation matrix when variables are centered and standardized. However, attention does not operate directly on a similarity matrix—it applies a softmax transformation to it.&lt;/p&gt;

&lt;p&gt;This distinction leads to a crucial behavioral difference. A correlation matrix used as an adjacency matrix can represent signed relationships, allowing information to propagate with both positive and negative influences depending on the sign of the correlation. In contrast, a standard attention mechanism only permits positive influence. Why does attention still work despite this limitation? Because multi-head attention allows the model to learn multiple types of relationships.&lt;/p&gt;

&lt;p&gt;However, this observation motivated me to explore the modeling of signed relationships within a single attention head. Why bother? Because relying on multiple heads to circumvent this theoretical limitation introduces inefficiencies. When two attention heads are used to learn opposite relationships, the corresponding keys and queries governing the same interaction must be learned twice. Furthermore, in conventional architectures, the feature dimension is divided by the number of heads, resulting in more parameters but less expressive capacity per head. It is from this inefficiency that the idea emerged—to design a mechanism that models both aspects of a relationship within a single attention head, using shared parameters.&lt;/p&gt;

&lt;div class=&quot;newsletter-card&quot;&gt;
  &lt;!-- Beehiiv native embed --&gt;
  &lt;script async=&quot;&quot; src=&quot;https://subscribe-forms.beehiiv.com/embed.js&quot;&gt;&lt;/script&gt;
  &lt;iframe src=&quot;https://subscribe-forms.beehiiv.com/25db4bd3-5665-4879-8dbb-8b5d2e826fb6&quot; title=&quot;Subscribe to the Quants Quest newsletter&quot; loading=&quot;lazy&quot; class=&quot;beehiiv-embed&quot; data-test-id=&quot;beehiiv-embed&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; style=&quot;width: 317px; height: 142px; margin: 0; border-radius: 0px 0px 0px 0px !important; background-color: transparent; box-shadow: 0 0 #0000; max-width: 100%;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;style&gt;
.beehiiv-embed {
  height: 142px;
}

@media (max-width: 768px) {
  .beehiiv-embed {
    height: 220px;
  }
}
&lt;/style&gt;

&lt;h2 id=&quot;how-sda-works&quot;&gt;How Signed Dual Attention Works&lt;/h2&gt;

&lt;p&gt;To model signed relationships, both positive and negative weights in the attention matrix are required. Previous works have addressed this by applying a $\tanh$ transformation to the similarity scores. However, I believe that the softmax function plays an essential role in ensuring stability and effective focus during attention computation.&lt;/p&gt;

&lt;p&gt;The solution I adopted was therefore not to replace the softmax, but to extend it: by applying two softmax functions and constructing an odd function of the similarity matrix, the model can naturally encode both positive and negative affinities while retaining the desirable normalization properties of softmax-based attention.&lt;/p&gt;

&lt;h3 id=&quot;mathematical-formulation&quot;&gt;Mathematical Formulation&lt;/h3&gt;

&lt;p&gt;SDA extends standard scaled dot-product attention by &lt;strong&gt;computing positive and negative attention matrices&lt;/strong&gt; with shared keys and queries matrices:&lt;/p&gt;

\[\begin{align}
A^+ &amp;amp;= \text{softmax}\left(\frac{QK^\top}{\sqrt{d_k}}\right) \\
A^- &amp;amp;= \text{softmax}\left(-\frac{QK^\top}{\sqrt{d_k}}\right) \\
\end{align}\]

\[\text{SDA}(Q,K,V) = (A^+ - A^-) V\]

&lt;ul&gt;
  &lt;li&gt;$A^+$ propagates &lt;strong&gt;positive signals&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;$A^-$ propagates &lt;strong&gt;negative signals&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The subtraction ensures &lt;strong&gt;antagonistic relationships invert the message&lt;/strong&gt;.&lt;/p&gt;

&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/images/sda_architecture.png&quot; alt=&quot;Drift ?&quot; style=&quot;max-height: 350px; width: auto; max-width: 100%;&quot; /&gt;
&lt;/div&gt;
&lt;h3 id=&quot;link-with-two-head-attention&quot;&gt;Link with Two-Head Attention&lt;/h3&gt;

&lt;p&gt;The Signed Dual Attention (SDA) block can be seen as a constrained form of a two-head self-attention mechanism. Imagine a standard two-head attention layer with parameters defined as&lt;/p&gt;

\[(W_1^K, W_1^Q, W_1^V) = (W^K, W^Q, W^V),
\qquad
(W_2^K, W_2^Q, W_2^V) = (-W^K,\, W^Q,\, -W^V).\]

&lt;p&gt;Let $H_1, H_2 \in \mathbb{R}^{T \times d}$ be the outputs of the two heads. In conventional multi-head attention, their concatenation $H_{\text{cat}} \in \mathbb{R}^{T \times 2d}$ is projected through an output matrix $W^O$ to obtain the final representation $H$ :&lt;/p&gt;

\[H = H_{\text{cat}} W^O.\]

&lt;p&gt;If we choose&lt;/p&gt;

\[W^O =
\begin{bmatrix}
I_d \\
I_d
\end{bmatrix}
\in \mathbb{R}^{2d \times d},\]

&lt;p&gt;the projection simply performs an additive fusion, leading to $H = H_1 + H_2$. Under this configuration, the output of the two-head mechanism aligns exactly with the SDA formulation.&lt;/p&gt;

&lt;p&gt;This perspective highlights SDA as a compact and efficient alternative to multi-head attention—able to capture both supportive and antagonistic interactions while using half the parameter count and maintaining the computational footprint of a single-head layer.&lt;/p&gt;

&lt;h2 id=&quot;future-directions&quot;&gt;Future Directions&lt;/h2&gt;

&lt;p&gt;Preliminary experiments suggest that SDA behaves differently across datasets depending on the underlying &lt;strong&gt;autocorrelation structure&lt;/strong&gt;, particularly when both positive and negative dependencies coexist. This makes sense since by $W^O$ inforce both aspect of the relationship to have an equal influence, when it can depending of the data not be the case. I see potential in learning adaptive weighting between the positive and negative attention components $A^{+}$ and $A^{-}$ instead of assigning them equal importance. This enhancement could improve performance in settings where negative interactions are weak or primarily noisy.&lt;/p&gt;

&lt;p&gt;If you would like to go further, you can read our paper, &lt;a href=&quot;https://arxiv.org/abs/2606.04833&quot;&gt;Signed Dual Attention: Capturing Signed Dependencies in Time Series Forecasting&lt;/a&gt;, on arXiv. It presents the mathematical formulation and experiments behind SDA, exploring how attention can capture both positive and negative dependencies in time series without adding parameters.&lt;/p&gt;

</content>
    <category term="Research" /><category term="Computer Science" />
  </entry>
  
  <entry>
    <title type="html">Estimating Pi (π) with Monte Carlo Simulation in Python</title>
    <link href="https://quants.quest/PiEstimation/" rel="alternate" type="text/html" />
    <id>https://quants.quest/PiEstimation</id>
    <published>2026-01-03T08:00:00+00:00</published>
    <updated>2026-01-03T08:00:00+00:00</updated>
    <summary type="html">Learn how to estimate the value of π using Monte Carlo simulation in Python. A step-by-step guide with math, code, and visualization.</summary>
    <content type="html" xml:base="https://quants.quest/PiEstimation/">&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of Contents&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#montecarlo&quot;&gt;Monte Carlo Simulation Basics&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#probabilities&quot;&gt;Using Random Sampling to Estimate Pi&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#implementation&quot;&gt;A Python Implementation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#references-and-further-reading&quot;&gt;References and Further Reading&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#monte-carlo-interview-questions&quot;&gt;Monte Carlo Interview Questions&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;How can we estimate the value of $\pi$? While we know $\pi$ is irrational and cannot be expressed as a finite closed formula, approximations like $3.14$ or $22/7$ are widely used. But what if we want a systematic, simulation-based method to approximate $\pi$ with arbitrary precision?&lt;/p&gt;

&lt;p&gt;Monte Carlo methods provide exactly this. By exploiting randomness and statistical principles, we can approximate $\pi$ in a surprisingly elegant way. This tutorial walks step by step through the mathematics and Python code.&lt;/p&gt;

&lt;h2 id=&quot;montecarlo&quot;&gt;Monte Carlo Simulation Basics&lt;/h2&gt;

&lt;p&gt;Monte Carlo methods rely on random sampling and the central limit theorem (CLT) to estimate expectations. Indeed the CLT states that for $(X_i)_{i=1}^n$ $n$ independent and identically distributed random variables :&lt;/p&gt;

\[\frac{1}{\sqrt{n}}\sum_{i=1}^{n}(X_i - \mu) \xrightarrow[]{d} N(0, \sigma^2)\]

&lt;p&gt;If we can find a random variable $X$ such that $\mathbb{E}[X] = \pi$, then simulating $X$ repeatedly and averaging would us an estimate of $\pi$ ! The more samples we take, the closer we get to the true value, with the rate of convergence governed by the variance of $X$.&lt;/p&gt;

&lt;p&gt;But this here is a quant blog. Suppose we want the absolute error to be less than $\varepsilon &amp;gt; 0$ with probability at least $1 - \alpha$. Can we solve this problem ? Answer is yes, but with some maths.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/here_we_go_again.png&quot; alt=&quot;funny math meme&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Let’s consider $\text{Var}(X) = \sigma^2$, then by the Central Limit Theorem, the sample mean&lt;/p&gt;

\[\hat{\pi}_n = \frac{1}{n} \sum_{i=1}^n X_i\]

&lt;p&gt;satisfies&lt;/p&gt;

\[\sqrt{n}\,(\hat{\pi}_n - \pi) \xrightarrow[]{d} N(0, \sigma^2).\]

&lt;p&gt;This means that for large $n$, the estimation error is approximately normal with variance $\frac{\sigma^2}{n}$. Hence, the standard error of our estimator is&lt;/p&gt;

\[\text{SE}(\hat{\pi}_n) = \frac{\sigma}{\sqrt{n}}.\]

&lt;p&gt;Using the normal approximation, we require&lt;/p&gt;

\[\mathbb{P}\big( |\hat{\pi}_n - \pi| &amp;lt; \varepsilon \big) \approx 1 - \alpha.\]

&lt;p&gt;This leads to the condition&lt;/p&gt;

\[\frac{\sigma}{\sqrt{n}} z_{1-\alpha/2} \leq \varepsilon,\]

&lt;p&gt;where $z_{1-\alpha/2}$ is the $(1 - \alpha/2)$ quantile of the standard normal distribution (for example, $z_{0.975} \approx 1.96$ for a $95\%$ confidence level).&lt;/p&gt;

&lt;p&gt;Rearranging gives the required number of runs:&lt;/p&gt;

\[n \geq \left( \frac{z_{1-\alpha/2} \cdot \sigma}{\varepsilon} \right)^2.\]

&lt;p&gt;This formula provides a practical guideline: once we know or estimate the variance $\sigma^2$ of the Monte Carlo variable, we can determine how many simulations are needed to achieve a desired accuracy $\varepsilon$ with a given confidence level $1 - \alpha$.&lt;/p&gt;

&lt;div class=&quot;newsletter-container&quot;&gt;
  &lt;div class=&quot;newsletter-card&quot;&gt;
  &lt;!-- Beehiiv native embed --&gt;
  &lt;script async=&quot;&quot; src=&quot;https://subscribe-forms.beehiiv.com/embed.js&quot;&gt;&lt;/script&gt;
  &lt;iframe src=&quot;https://subscribe-forms.beehiiv.com/25db4bd3-5665-4879-8dbb-8b5d2e826fb6&quot; title=&quot;Subscribe to the Quants Quest newsletter&quot; loading=&quot;lazy&quot; class=&quot;beehiiv-embed&quot; data-test-id=&quot;beehiiv-embed&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; style=&quot;width: 317px; height: 142px; margin: 0; border-radius: 0px 0px 0px 0px !important; background-color: transparent; box-shadow: 0 0 #0000; max-width: 100%;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;style&gt;
.beehiiv-embed {
  height: 142px;
}

@media (max-width: 768px) {
  .beehiiv-embed {
    height: 220px;
  }
}
&lt;/style&gt;

&lt;/div&gt;

&lt;h2 id=&quot;probabilities&quot;&gt;Using Random Sampling to Estimate $\pi$&lt;/h2&gt;

&lt;p&gt;In practice, random number generation typically begins with pseudo-random draws from a uniform distribution, which can be transformed into other distributions.   In Python, numpy provides a straightforward way to simulate such values.&lt;/p&gt;

&lt;p&gt;Here is the key idea: let $X_1$ and $X_2$ be two i.i.d. uniform random variables on $[-1, 1]$. The probability that the point $(X_1, X_2)$ falls inside the unit circle is proportional to the ratio between the area of the circle and the area of the square:&lt;/p&gt;

\[\mathbb{P}(X_1^2 + X_2^2 \leq 1) = \frac{\text{Area of Circle}}{\text{Area of Square}} = \frac{\pi r^2}{(2r)^2} = \frac{\pi}{4}.\]

&lt;p&gt;Thus, if we simulate many points uniformly in the square $[-1, 1]^2$ and check the fraction that lies within the unit circle, multiplying this fraction by 4 yields an approximation of $\pi$.&lt;/p&gt;

&lt;p&gt;We can for sure also ask ourself : what is the value of $\sigma_X$?&lt;/p&gt;

&lt;p&gt;By definition, &lt;br /&gt;
\(\sigma_X = \sqrt{\mathbb{E}[X^2] - \mathbb{E}[X]^2}\)&lt;/p&gt;

&lt;p&gt;Here, $X$ is the indicator function of the event ${(X_1, X_2) \in \text{Unit Circle}}$. Since $X$ is an indicator, we have $X^2 = X$, thus :&lt;/p&gt;

\[\mathbb{E}[X^2] = \mathbb{E}[X] = \frac{\pi}{4}\]

&lt;p&gt;And so we find :&lt;/p&gt;

\[\sigma_X = \sqrt{\frac{\pi}{4} - \left(\frac{\pi}{4}\right)^2}
= \sqrt{\frac{\pi}{4} \cdot \frac{4 - \pi}{4}}
= \sqrt{\frac{\pi (4 - \pi)}{16}}.\]

&lt;p&gt;Thus,&lt;/p&gt;

\[\sigma_X  &amp;lt; \frac{1}{2}.\]

&lt;h2 id=&quot;implementation&quot;&gt;A Python Implementation&lt;/h2&gt;

&lt;p&gt;The implementation is straightforward:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1e6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# number of simulations
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uniform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uniform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Check which points fall inside the unit circle
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inside_circle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Estimate of pi
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pi_estimate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inside_circle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pi_estimate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Running this code with one million points gives a fairly good approximation of $\pi$. Increasing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; will further improve accuracy.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/PiEstimation_figure_1.png&quot; alt=&quot;Monte Carlo Simulation Pi Estimation&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Estimating $\pi$ with Monte Carlo is a beautiful demonstration of how probability and geometry intersect. It shows that if we can identify a random variable with an expectation equal to the quantity of interest, then repeated sampling gives us a practical way to approximate it.&lt;/p&gt;

&lt;h2 id=&quot;references-and-further-reading&quot;&gt;References and Further Reading&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Monte_Carlo_method&quot;&gt;Monte Carlo Method — Wikipedia&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Central_limit_theorem&quot;&gt;Central Limit Theorem — Wikipedia&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Gentle, J. E. (2003). &lt;em&gt;Random Number Generation and Monte Carlo Methods&lt;/em&gt;. Springer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;monte-carlo-interview-questions&quot;&gt;Monte Carlo Interview Questions&lt;/h2&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;strong&gt;1. What is a Monte Carlo simulation, and why is it useful in quantitative finance?&lt;/strong&gt;&lt;/summary&gt;
  &lt;p&gt;
    Monte Carlo simulation uses random sampling to approximate complex probabilistic outcomes. In finance, it&apos;s used for option pricing, risk management, portfolio optimization, and evaluating scenarios where closed-form solutions are difficult.
  &lt;/p&gt;
&lt;/details&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;strong&gt;2. How does Monte Carlo simulation leverage randomness to approximate deterministic quantities like π?&lt;/strong&gt;&lt;/summary&gt;
  &lt;p&gt;
    By generating many random points in a known geometric space (e.g., a square), we can estimate the probability of events (e.g., falling inside a circle). Multiplying this probability by the appropriate factor gives an approximation of π.
  &lt;/p&gt;
&lt;/details&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;strong&gt;3. What role does the Central Limit Theorem play in Monte Carlo methods?&lt;/strong&gt;&lt;/summary&gt;
  &lt;p&gt;
    The Central Limit Theorem justifies that the sample mean of independent simulations approximates a normal distribution for large samples, allowing us to compute confidence intervals and error bounds for estimates.
  &lt;/p&gt;
&lt;/details&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;strong&gt;4. How do you determine the number of Monte Carlo simulations needed to achieve a desired accuracy?&lt;/strong&gt;&lt;/summary&gt;
  &lt;p&gt;
    Using the standard error formula: \( SE = \sigma / \sqrt{n} \), and desired error \(\varepsilon\) at confidence level \(1-\alpha\), the required simulations are \( n \ge (z_{1-\alpha/2} \cdot \sigma / \varepsilon)^2 \).
  &lt;/p&gt;
&lt;/details&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;strong&gt;5. How can π be estimated using random sampling in a unit square?&lt;/strong&gt;&lt;/summary&gt;
  &lt;p&gt;
    Generate uniform random points in $[-1,1]^2$. Count the fraction inside the unit circle. Multiply this fraction by 4 to estimate π: 
    $$
    \pi \approx 4 \times frac{\text{points inside circle}}{\text{total points}}
    $$
  &lt;/p&gt;
&lt;/details&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;strong&gt;6. What is the variance of the Monte Carlo estimator when estimating π?&lt;/strong&gt;&lt;/summary&gt;
  &lt;p&gt;
    Using the indicator variable for a point inside the circle: \( \sigma^2 = \frac{\pi}{4}\left(1 - \frac{\pi}{4}\right) \). The standard error of the mean decreases with \(1/\sqrt{n}\).
  &lt;/p&gt;
&lt;/details&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;strong&gt;7. How would you implement a Monte Carlo simulation to estimate π in Python efficiently?&lt;/strong&gt;&lt;/summary&gt;
  &lt;p&gt;
    Use vectorized operations in NumPy to generate random points and compute the fraction inside the unit circle. Example: 
    &lt;pre&gt;&lt;code&gt;
import numpy as np
n = 1_000_000
x, y = np.random.uniform(-1, 1, n), np.random.uniform(-1, 1, n)
pi_estimate = 4 * ((x**2 + y**2) &amp;lt;= 1).mean()
print(pi_estimate)
    &lt;/code&gt;&lt;/pre&gt;
  &lt;/p&gt;
&lt;/details&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;strong&gt;8. How can variance reduction techniques improve Monte Carlo estimation?&lt;/strong&gt;&lt;/summary&gt;
  &lt;p&gt;
    Techniques like antithetic variates, control variates, and quasi-random sequences reduce estimator variance, improving accuracy without increasing the number of simulations—a critical tool in hedge fund risk modeling.
  &lt;/p&gt;
&lt;/details&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;strong&gt;9. Why is understanding the standard error important in quantitative simulations?&lt;/strong&gt;&lt;/summary&gt;
  &lt;p&gt;
    The standard error quantifies the expected fluctuation of the estimate around the true value, allowing quants to construct confidence intervals and assess the reliability of Monte Carlo results.
  &lt;/p&gt;
&lt;/details&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;strong&gt;10. Where are Monte Carlo methods commonly applied in quantitative finance?&lt;/strong&gt;&lt;/summary&gt;
  &lt;p&gt;
    Applications include derivative pricing (e.g., options), Value-at-Risk (VaR) calculation, stress testing portfolios, scenario analysis, and simulating complex stochastic processes like interest rates or asset paths.
  &lt;/p&gt;
&lt;/details&gt;
</content>
    <category term="Statistics" /><category term="Python" />
  </entry>
  
  <entry>
    <title type="html">Is a Random Walk with Drift a Martingale ?</title>
    <link href="https://quants.quest/RandomWalkwithDrift/" rel="alternate" type="text/html" />
    <id>https://quants.quest/RandomWalkwithDrift</id>
    <published>2025-11-12T00:00:00+00:00</published>
    <updated>2025-11-12T00:00:00+00:00</updated>
    <summary type="html">Learn how the risk-neutral measure mathematically transforms a random walk with drift into a martingale by removing its drift, with clear step-by-step explanations.</summary>
    <content type="html" xml:base="https://quants.quest/RandomWalkwithDrift/">&lt;p&gt;As discussed in our previous &lt;a href=&quot;/RandomWalkvsMartingale/&quot;&gt;blog post on martingales and random walks&lt;/a&gt;, both concepts are fundamental in financial mathematics and quantitative finance. In financial modelling, however, the most relevant case is the random walk with drift. While it may seem at first that a random walk with drift has little in common with a martingale, the relationship between them is deeper than it appears. In this article, we explore the connection between random walks with drift, martingales, and the &lt;a href=&quot;/FactorModelSDFLink/&quot;&gt;stochastic discount factor&lt;/a&gt;, to build a clearer understanding of what they truly are.&lt;/p&gt;

&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of Contents&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;#RandomWalkDrift_Definition&quot;&gt;Martingales, Random Walks and Drifts&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#RandomWalkDrift_Martingale&quot;&gt;From Drift to Martingale&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ConnectionSDF&quot;&gt;Link with the Stochastic Discount Factor&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#Conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#FurtherReading&quot;&gt;Further Reading&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;RandomWalkDrift_Definition&quot;&gt;Martingales, Random Walks and Drifts&lt;/h2&gt;

&lt;p&gt;Let’s make some definitions here to ensure we all speak the same language (thank God mathematics is universal).&lt;/p&gt;

&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/images/what_do_you_mean_drift.jpg&quot; alt=&quot;Drift ?&quot; style=&quot;max-height: 350px; width: auto; max-width: 100%;&quot; /&gt;
&lt;/div&gt;

&lt;h3 id=&quot;martingale&quot;&gt;Martingale&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;martingale&lt;/strong&gt; $W_t$ with respect to a filtration $\mathcal{F}_t$ satisfies :&lt;/p&gt;

\[\mathbb{E}\left[W_{t+1} \mid \mathcal{F}_t \right] = w_t \quad \forall t \ge 0\]

&lt;p&gt;Intuitively, the best forecast of tomorrow’s value, given all information today, is simply today’s value.&lt;/p&gt;

&lt;h3 id=&quot;random-walk&quot;&gt;Random Walk&lt;/h3&gt;

&lt;p&gt;A random walk $W_t$ is a discrete-time stochastic process defined by :&lt;/p&gt;

\[W_t = \sum_{i=1}^{t} \varepsilon_i,\]

&lt;p&gt;where ${\varepsilon_i}_{i \ge 1}$ is a sequence of i.i.d. random variables and where in many cases :&lt;/p&gt;

\[\mathbb{E}[\varepsilon_i] = 0, \quad \text{and} \quad \text{Var}(\varepsilon_i) = \sigma^2.\]

&lt;p&gt;In these settings, the process satisfies :&lt;/p&gt;

\[\mathbb{E}[W_{t+1} \mid \mathcal{F}_t] = W_t,\]

&lt;p&gt;which and the random walk $(W_t)$ is a &lt;strong&gt;martingale&lt;/strong&gt;.&lt;/p&gt;

&lt;div class=&quot;newsletter-container&quot;&gt;
  &lt;div class=&quot;newsletter-card&quot;&gt;
  &lt;!-- Beehiiv native embed --&gt;
  &lt;script async=&quot;&quot; src=&quot;https://subscribe-forms.beehiiv.com/embed.js&quot;&gt;&lt;/script&gt;
  &lt;iframe src=&quot;https://subscribe-forms.beehiiv.com/25db4bd3-5665-4879-8dbb-8b5d2e826fb6&quot; title=&quot;Subscribe to the Quants Quest newsletter&quot; loading=&quot;lazy&quot; class=&quot;beehiiv-embed&quot; data-test-id=&quot;beehiiv-embed&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; style=&quot;width: 317px; height: 142px; margin: 0; border-radius: 0px 0px 0px 0px !important; background-color: transparent; box-shadow: 0 0 #0000; max-width: 100%;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;style&gt;
.beehiiv-embed {
  height: 142px;
}

@media (max-width: 768px) {
  .beehiiv-embed {
    height: 220px;
  }
}
&lt;/style&gt;

&lt;/div&gt;

&lt;h3 id=&quot;random-walk-with-drift&quot;&gt;Random Walk with Drift&lt;/h3&gt;

&lt;p&gt;However, financial modelling requires more often than not to have $\mathbb{E}[\varepsilon_i] = r$, with $r$ a non null constant. To adjust, we can use $\tilde{\varepsilon_i} = \varepsilon_i - r$ to define a new random walk with increments $\tilde{\varepsilon_i}$ that we will note $\tilde{W_t}$. From the relationship we can say that $\tilde{W_t} = W_t - r \times t$ or equivalently $W_t = \tilde{W_t} + r \times t$.&lt;/p&gt;

&lt;p&gt;Thus introducing a non zero constant for $\mathbb{E}[\varepsilon_i]$ creates a &lt;strong&gt;random walk with drift&lt;/strong&gt;  and modifies the process into :
\(X_t = \mu t + W_t.\)
This can be interpreted as a &lt;strong&gt;deterministic linear trend&lt;/strong&gt; $\mu t$ plus a &lt;strong&gt;centered random walk&lt;/strong&gt; $W_t$.&lt;/p&gt;

&lt;p&gt;Quantitatively:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The &lt;strong&gt;expected value&lt;/strong&gt; evolves as $\mathbb{E}[X_t] = \mu t$ showing the systematic accumulation of the drift.&lt;/li&gt;
  &lt;li&gt;The &lt;strong&gt;variance&lt;/strong&gt; remains stochastic due to the random component : $\text{Var}(X_t) = t \sigma^2$&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hence, a random walk with drift is simply a martingale tilted by a linear deterministic trend $\mu t$.&lt;br /&gt;
In financial modeling, removing the drift by working under a &lt;em&gt;risk-neutral measure&lt;/em&gt; recovers the martingale property crucial for pricing and arbitrage-free valuation.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;N&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;# number of sample paths
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2520&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# number of time steps
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mu&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.05&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;# drift
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sigma&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;# volatility
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;eps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sigma&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cumsum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# random walk
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;expected_drift&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mu&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subplots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.75&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expected_drift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;red&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linestyle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;--&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linewidth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Expected Drift&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Random Walk with Drift Simulations&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Time Steps&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Value&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tight_layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/RWwithD_fig_1.png&quot; alt=&quot;Random Walk with Drift simulation example with Python&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;RandomWalkDrift_Martingale&quot;&gt;From Drift to Martingale&lt;/h2&gt;

&lt;p&gt;So far, we have described our random walks dynamics under a &lt;strong&gt;real-world measure&lt;/strong&gt;, denoted by $\mathbb{P}$. Under $\mathbb{P}$, a random walk can exhibit a &lt;strong&gt;drift&lt;/strong&gt;. When modelling financial instruments, this drift reflects required expected return for bearing risk. However it is far more convenient to work with martingales when computing expectations, the probability of a given event, … And that why mathematicals tools have been searched to transform random walk with drift into random walk : the change of measure, and more speciafically the &lt;strong&gt;risk-neutral measure&lt;/strong&gt; in finance.&lt;/p&gt;

&lt;p&gt;What is the key idea here ? Many real word applications require simply to compute an expectation. For a deriviative for instance, however the model used to describe the behavior of the underlying, &lt;a href=&quot;https://en.wikipedia.org/wiki/Black%E2%80%93Scholes_model&quot;&gt;Black Scholes&lt;/a&gt; for instance, we end up computed to expectation of the final payoff.&lt;/p&gt;

&lt;p&gt;For any random real variable $X$, we can express it’s expectation as :&lt;/p&gt;

\[\mathbb{E}[X] = \int_{-\infty}^{\infty} f(x)x \mathrm{d}x\]

&lt;p&gt;Changing the measure simply means finding a new density function $f’$ for $X$ such that it becomes a martingale. How is this done rigorously ? That is where the Radon Nikodym Bridge comes by.&lt;/p&gt;

&lt;h3 id=&quot;the-radonnikodym-bridge&quot;&gt;The Radon–Nikodym Bridge&lt;/h3&gt;

&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Radon%E2%80%93Nikodym_theorem&quot;&gt;&lt;strong&gt;Radon–Nikodym Theorem&lt;/strong&gt;&lt;/a&gt; is the key demonstration behind everything that will follow. Using the Radon Nikodyn variable &lt;br /&gt;
\(\Lambda_t = \frac{d\mathbb{Q}}{d\mathbb{P}}\Big|_{\mathcal{F}_t}.\)
sometimes called the &lt;strong&gt;change-of-measure density&lt;/strong&gt;, reweights probabilities such that expectations under $\mathbb{P}$ are transformed into expectations under $\mathbb{Q}$:&lt;/p&gt;

\[\mathbb{E}_{\mathbb{Q}}[X_t] = \mathbb{E}_{\mathbb{P}}[\Lambda_t X_t].\]

&lt;p&gt;Let’s give an intuition for what will happend if use it to transform our random walk with a positive drift into a martingale. $\Lambda_t$ will downweight states of the world that are good and upweights those that are bad, effectively neutralizing the drift. A detailed exposition of this concept can be found in &lt;a href=&quot;/RandomWalkvsMartingale/&quot;&gt;this post&lt;/a&gt;, which connects the Radon–Nikodym transformation with random walk intuition.&lt;/p&gt;

&lt;p&gt;Ok, great, but you are now probability asking : Is that usefull maths or just some weird theory that will always be pointless ? Well, despite being nice and clever theorem, it does have it moment. Let’s look at a classic application.&lt;/p&gt;

&lt;h3 id=&quot;a-practical-application&quot;&gt;A Practical Application&lt;/h3&gt;

\[W_0 = 0, \quad W_{t+1} = W_t + \mu + \varepsilon_{t+1}, \quad \varepsilon_t \sim \text{i.i.d. } N(0,\sigma^2),\]

&lt;p&gt;Let’s denote $\tau_a$ the hitting time of level $a &amp;gt; 0$ : $\inf{t \ge 0 : W_t \ge a}$.&lt;br /&gt;
We must compute the probability $p = \mathbb{P}(\tau_a &amp;lt; \infty)$ that the drifted random walk eventually reaches level $a$.&lt;/p&gt;

&lt;p&gt;Consider
\(M_t = e^{-\theta W_t}\)&lt;/p&gt;

&lt;p&gt;where $\theta &amp;gt; 0$ is chosen such that :&lt;/p&gt;

\[\mathbb{E}[e^{-\theta (\mu + \varepsilon_t)}] = 1.\]

&lt;p&gt;For $\varepsilon_t \sim N(0,\sigma^2)$:&lt;/p&gt;

\[\mathbb{E}[e^{-\theta (\mu + \varepsilon_t)}] = e^{-\theta \mu + \frac{1}{2}\sigma^2 \theta^2} = 1
\quad\Longrightarrow\quad
\theta = \frac{2\mu}{\sigma^2}.\]

&lt;p&gt;Then $(M_t)_{t=0}^{+\infty}$ is a positive martingale with $M_0 = 1$.&lt;/p&gt;

&lt;p&gt;We can define a new probability measure $Q$ on $\mathcal{F}_n$ via&lt;/p&gt;

\[\frac{dQ}{dP}\Big|_{\mathcal{F}_n} = M_n\]

&lt;p&gt;This is an &lt;strong&gt;exponential change of measure&lt;/strong&gt; (&lt;a href=&quot;https://en.wikipedia.org/wiki/Esscher_transform&quot;&gt;Esscher transform&lt;/a&gt;). Under $Q$, the increments of the random walk become&lt;/p&gt;

\[\varepsilon_t^Q \sim N(-\sigma^2 \theta, \sigma^2),\]

&lt;p&gt;so that the drift under $Q$ is&lt;/p&gt;

\[\mu - \sigma^2 \theta = \mu - 2\mu = -\mu &amp;lt; 0.\]

&lt;p&gt;By the Radon–Nikodym formula:&lt;/p&gt;

\[P(\tau_a &amp;lt; \infty) = \mathbb{E}_P[\mathbf{1}_{\{\tau_a &amp;lt; \infty\}}] 
= \mathbb{E}_Q\Big[ \frac{dP}{dQ} \mathbf{1}_{\{\tau_a &amp;lt; \infty\}} \Big]
= \mathbb{E}_Q\Big[ e^{\theta W_{\tau_a}} \mathbf{1}_{\{\tau_a &amp;lt; \infty\}} \Big].\]

&lt;p&gt;Moreover, $W_{\tau_a} = a$, so&lt;/p&gt;

\[P(\tau_a &amp;lt; \infty) = e^{-\theta a}.\]

&lt;p&gt;And finally :&lt;/p&gt;

\[P(\tau_a &amp;lt; \infty) = \exp\Big(-\frac{2\mu}{\sigma^2} a\Big)\]

&lt;h2 id=&quot;ConnectionSDF&quot;&gt;Link with the Stochastic Discount Factor&lt;/h2&gt;

&lt;p&gt;In finance, the &lt;strong&gt;Stochastic Discount Factor&lt;/strong&gt; (SDF), usually denoted $M_t$, plays exactly the same conceptual role. It is the core of assets pricing and the magic behind factors models &lt;a href=&quot;/FactorModelSDFLink/&quot;&gt;(go see the post)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The SDF discounts risky future payoffs back to today’s value, adjusting for both time and risk, ensuring that random walks with drift become martingales. To gain more insight, check out our &lt;a href=&quot;/RandomWalkvsMartingale/&quot;&gt;previous post about random walks&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;Conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;When a stochastic process exhibits drift, its future values are partially predictable, and it is no longer a martingale. However, there exist systematic ways to transform a drifted process into a martingale, allowing us to restore the powerful martingale property for analysis and computation.&lt;/p&gt;

&lt;p&gt;In the context of random walks, introducing a constant drift creates a random walk with drift, but through techniques such as the exponential martingale transform or a change of measure, we can construct a new process that removes the drift while preserving the essential probabilistic structure.&lt;/p&gt;

&lt;p&gt;This transformation is not only a theoretical tool: in finance, it underpins the risk-neutral measure and the SDF, where discounted asset prices become martingales. By reweighting probabilities via the Radon–Nikodym derivative, we can consistently price assets without having to explicitly account for the real-world drift of returns.&lt;/p&gt;

&lt;h2 id=&quot;FurtherReading&quot;&gt;Further Reading&lt;/h2&gt;

&lt;p&gt;If you’d like to explore these ideas more deeply, the following resources provide both mathematical rigor and economic intuition:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;/RandomWalkvsMartingale/&quot;&gt;&lt;em&gt;Random Walk vs Martingale&lt;/em&gt;&lt;/a&gt; — an accessible explanation of how measure changes reshape stochastic dynamics.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Bjork, T. (2009).&lt;/strong&gt; &lt;em&gt;Arbitrage Theory in Continuous Time.&lt;/em&gt; Oxford University Press.&lt;br /&gt;
A comprehensive reference on measure changes, martingales, and the Radon–Nikodym derivative in continuous-time finance.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Cochrane, J. H. (2005).&lt;/strong&gt; &lt;em&gt;Asset Pricing.&lt;/em&gt; Princeton University Press.&lt;br /&gt;
Chapters on the stochastic discount factor offer a deep economic interpretation of the risk-neutral transformation.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Shreve, S. (2004).&lt;/strong&gt; &lt;em&gt;Stochastic Calculus for Finance II: Continuous-Time Models.&lt;/em&gt; Springer.&lt;br /&gt;
A mathematically precise introduction to the link between real-world and risk-neutral measures.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Together, these texts bridge intuition and mathematics, reinforcing how &lt;strong&gt;changing measures&lt;/strong&gt; connects probability theory, pricing, and the economics of risk.&lt;/p&gt;

</content>
    <category term="Statistics" /><category term="Quantitative Finance" />
  </entry>
  
  <entry>
    <title type="html">The SDF Explained: Why Factor Models Actually Work</title>
    <link href="https://quants.quest/FactorModelSDFLink/" rel="alternate" type="text/html" />
    <id>https://quants.quest/FactorModelSDFLink</id>
    <published>2025-09-27T00:00:00+00:00</published>
    <updated>2025-09-27T00:00:00+00:00</updated>
    <summary type="html">Learn why factor models work in finance. Beneath their growing complexity in the number of factors lies a deeper unifying idea: factor models are, at their core, a way to approximate the Stochastic Discount Factor (SDF).</summary>
    <content type="html" xml:base="https://quants.quest/FactorModelSDFLink/">&lt;p&gt;Asset pricing has evolved dramatically over the past several decades, shifting from simple models based on a single market factor to an expansive &lt;a href=&quot;https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4605976&quot;&gt;zoo&lt;/a&gt; of multifactor frameworks. But beneath the growing complexity lies a deeper unifying idea: factor models are, at their core, a way to approximate the Stochastic Discount Factor (SDF). This post is not about which factors “work” or how to pick them, it’s about why factor models work at all. Drawing on insights from &lt;a href=&quot;https://www.johnhcochrane.com/asset-pricing&quot;&gt;Cochrane (2005)&lt;/a&gt;, we’ll explore how the empirical world of factor investing is fundamentally tied to the SDF.&lt;/p&gt;

&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of Contents&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;#Context&quot;&gt;A Historical Perspective&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#SDF&quot;&gt;The True Concept Behind Asset Prices&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#FactorModelsAreSDF&quot;&gt;Factor Models as SDFs in Disguise&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#Conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;Context&quot;&gt;A Historical Perspective&lt;/h2&gt;

&lt;p&gt;In the beginning, investors created the Market. The Market was one, with a clear form and simple measure. And the investors said: Let risk be priced. And risk was priced. And they called this the &lt;a href=&quot;https://doi.org/10.2307/2977928&quot;&gt;Capital Asset Pricing Model&lt;/a&gt;, born in 1964, the first of its kind.&lt;/p&gt;

&lt;p&gt;But investors said: Let there be more than one risk, for markets are many and varied. And so in 1992 arose the &lt;a href=&quot;https://en.wikipedia.org/wiki/Fama%E2%80%93French_three-factor_model&quot;&gt;Fama–French Three-Factor Model&lt;/a&gt;. And they called it the Threefold Model, for it spanned size, value, and the market itself. Thus were born factors, and with them the first risk portfolios.&lt;/p&gt;

&lt;div style=&quot;max-width: 600px; margin: 0 auto;&quot;&gt;
&lt;svg width=&quot;100%&quot; height=&quot;auto&quot; viewBox=&quot;0 0 900 220&quot; preserveAspectRatio=&quot;xMidYMid meet&quot; role=&quot;img&quot; aria-labelledby=&quot;title desc&quot;&gt;
  &lt;title id=&quot;title&quot;&gt;Timeline: CAPM → Factor Zoo → IPCA / ML&lt;/title&gt;
  &lt;desc id=&quot;desc&quot;&gt;A simple horizontal timeline with three labeled nodes: CAPM (parsimonious), Factor Zoo (many candidate factors), and IPCA / ML (high-dimensional SDF learning).&lt;/desc&gt;

  &lt;defs&gt;
    &lt;!-- Arrow head for the timeline --&gt;
    &lt;marker id=&quot;arrow&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;9&quot; refY=&quot;5&quot; markerWidth=&quot;6&quot; markerHeight=&quot;6&quot; orient=&quot;auto-start-reverse&quot;&gt;
      &lt;path d=&quot;M 0 0 L 10 5 L 0 10 z&quot; fill=&quot;#2b2b2b&quot; /&gt;
    &lt;/marker&gt;

    &lt;!-- Soft drop shadow for nodes --&gt;
    &lt;filter id=&quot;softShadow&quot; x=&quot;-50%&quot; y=&quot;-50%&quot; width=&quot;200%&quot; height=&quot;200%&quot;&gt;
      &lt;feGaussianBlur stdDeviation=&quot;3&quot; result=&quot;blur&quot; /&gt;
      &lt;feOffset in=&quot;blur&quot; dx=&quot;0&quot; dy=&quot;2&quot; result=&quot;offsetBlur&quot; /&gt;
      &lt;feMerge&gt;
        &lt;feMergeNode in=&quot;offsetBlur&quot; /&gt;
        &lt;feMergeNode in=&quot;SourceGraphic&quot; /&gt;
      &lt;/feMerge&gt;
    &lt;/filter&gt;

    &lt;!-- Common styles --&gt;
    &lt;style type=&quot;text/css&quot;&gt;&lt;![CDATA[
      .timeline-line { stroke: #2b2b2b; stroke-width: 3; fill: none; marker-end: url(#arrow); }
      .node-circle { fill: #ffffff; stroke: #1f77b4; stroke-width: 2.5; }
      .node-label { font-family: Inter, &quot;Helvetica Neue&quot;, Arial, sans-serif; font-size: 14px; fill: #111111; font-weight: 600; }
      .node-sub { font-family: Inter, &quot;Helvetica Neue&quot;, Arial, sans-serif; font-size: 12px; fill: #333333; }
      .year { font-family: Inter, &quot;Helvetica Neue&quot;, Arial, sans-serif; font-size: 11px; fill: #666666; }
    ]]&gt;&lt;/style&gt;
  &lt;/defs&gt;

  &lt;!-- Background --&gt;
  &lt;rect width=&quot;100%&quot; height=&quot;100%&quot; fill=&quot;transparent&quot; /&gt;

  &lt;!-- Timeline baseline --&gt;
  &lt;line x1=&quot;70&quot; y1=&quot;110&quot; x2=&quot;830&quot; y2=&quot;110&quot; class=&quot;timeline-line&quot; /&gt;

  &lt;!-- CAPM node --&gt;
  &lt;g transform=&quot;translate(150,110)&quot; filter=&quot;url(#softShadow)&quot;&gt;
    &lt;circle r=&quot;28&quot; class=&quot;node-circle&quot; /&gt;
    &lt;!-- Icon: simple market glyph --&gt;
    &lt;g transform=&quot;translate(-10,-10) scale(0.8)&quot; fill=&quot;#1f77b4&quot; aria-hidden=&quot;true&quot;&gt;
      &lt;rect x=&quot;0&quot; y=&quot;6&quot; width=&quot;6&quot; height=&quot;18&quot; rx=&quot;1&quot;&gt;&lt;/rect&gt;
      &lt;rect x=&quot;8&quot; y=&quot;0&quot; width=&quot;6&quot; height=&quot;24&quot; rx=&quot;1&quot;&gt;&lt;/rect&gt;
      &lt;rect x=&quot;16&quot; y=&quot;3&quot; width=&quot;6&quot; height=&quot;21&quot; rx=&quot;1&quot;&gt;&lt;/rect&gt;
    &lt;/g&gt;
  &lt;/g&gt;
  &lt;text x=&quot;150&quot; y=&quot;160&quot; text-anchor=&quot;middle&quot; class=&quot;node-label&quot;&gt;CAPM&lt;/text&gt;
  &lt;text x=&quot;150&quot; y=&quot;178&quot; text-anchor=&quot;middle&quot; class=&quot;node-sub&quot;&gt; Sharpe, Single factor&lt;/text&gt;
  &lt;text x=&quot;150&quot; y=&quot;196&quot; text-anchor=&quot;middle&quot; class=&quot;year&quot;&gt;(1960 — 1990s)&lt;/text&gt;

  &lt;!-- Factor Zoo node --&gt;
  &lt;g transform=&quot;translate(430,110)&quot; filter=&quot;url(#softShadow)&quot;&gt;
    &lt;circle r=&quot;28&quot; class=&quot;node-circle&quot; /&gt;
    &lt;!-- Icon: multiple small bars --&gt;
    &lt;g transform=&quot;translate(-18,-12)&quot; aria-hidden=&quot;true&quot;&gt;
      &lt;rect x=&quot;0&quot; y=&quot;10&quot; width=&quot;4&quot; height=&quot;14&quot; rx=&quot;1&quot; fill=&quot;#2ca02c&quot;&gt;&lt;/rect&gt;
      &lt;rect x=&quot;6&quot; y=&quot;4&quot; width=&quot;4&quot; height=&quot;20&quot; rx=&quot;1&quot; fill=&quot;#2ca02c&quot;&gt;&lt;/rect&gt;
      &lt;rect x=&quot;12&quot; y=&quot;0&quot; width=&quot;4&quot; height=&quot;24&quot; rx=&quot;1&quot; fill=&quot;#2ca02c&quot;&gt;&lt;/rect&gt;
      &lt;rect x=&quot;18&quot; y=&quot;7&quot; width=&quot;4&quot; height=&quot;17&quot; rx=&quot;1&quot; fill=&quot;#2ca02c&quot;&gt;&lt;/rect&gt;
    &lt;/g&gt;
  &lt;/g&gt;
  &lt;text x=&quot;430&quot; y=&quot;160&quot; text-anchor=&quot;middle&quot; class=&quot;node-label&quot;&gt;Multi Factors Models&lt;/text&gt;
  &lt;text x=&quot;430&quot; y=&quot;178&quot; text-anchor=&quot;middle&quot; class=&quot;node-sub&quot;&gt; Fama French, small number of factors &lt;/text&gt;
  &lt;text x=&quot;430&quot; y=&quot;196&quot; text-anchor=&quot;middle&quot; class=&quot;year&quot;&gt;(1990s — 2010s)&lt;/text&gt;

  &lt;!-- IPCA / ML node --&gt;
  &lt;g transform=&quot;translate(710,110)&quot; filter=&quot;url(#softShadow)&quot;&gt;
    &lt;circle r=&quot;28&quot; class=&quot;node-circle&quot; /&gt;
    &lt;!-- Icon: neural/pc glyph --&gt;
    &lt;g transform=&quot;translate(-10,-14)&quot; aria-hidden=&quot;true&quot;&gt;
      &lt;circle cx=&quot;0&quot; cy=&quot;8&quot; r=&quot;3&quot; fill=&quot;#d62728&quot;&gt;&lt;/circle&gt;
      &lt;circle cx=&quot;12&quot; cy=&quot;0&quot; r=&quot;3&quot; fill=&quot;#d62728&quot;&gt;&lt;/circle&gt;
      &lt;circle cx=&quot;24&quot; cy=&quot;8&quot; r=&quot;3&quot; fill=&quot;#d62728&quot;&gt;&lt;/circle&gt;
      &lt;path d=&quot;M0 8 L12 0 L24 8&quot; fill=&quot;none&quot; stroke=&quot;#d62728&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;
    &lt;/g&gt;
  &lt;/g&gt;
  &lt;text x=&quot;710&quot; y=&quot;160&quot; text-anchor=&quot;middle&quot; class=&quot;node-label&quot;&gt;Factor Zoo&lt;/text&gt;
  &lt;text x=&quot;710&quot; y=&quot;178&quot; text-anchor=&quot;middle&quot; class=&quot;node-sub&quot;&gt;Many proposed factors&lt;/text&gt;
  &lt;text x=&quot;710&quot; y=&quot;196&quot; text-anchor=&quot;middle&quot; class=&quot;year&quot;&gt;(2010 → present)&lt;/text&gt;

  &lt;!-- Optional connecting dots (timeline progression) --&gt;
  &lt;g fill=&quot;#2b2b2b&quot; opacity=&quot;0.12&quot;&gt;
    &lt;circle cx=&quot;280&quot; cy=&quot;110&quot; r=&quot;4&quot;&gt;&lt;/circle&gt;
    &lt;circle cx=&quot;340&quot; cy=&quot;110&quot; r=&quot;4&quot;&gt;&lt;/circle&gt;
    &lt;circle cx=&quot;520&quot; cy=&quot;110&quot; r=&quot;4&quot;&gt;&lt;/circle&gt;
    &lt;circle cx=&quot;610&quot; cy=&quot;110&quot; r=&quot;4&quot;&gt;&lt;/circle&gt;
  &lt;/g&gt;
&lt;/svg&gt;
&lt;/div&gt;

&lt;p&gt;And again the investors spoke: Let us make factors in our own image, many and diverse, to capture the world as we see it. And so began the great multiplication. From momentum in the 1990s, to profitability and investment in the 2010s, factors spread and multiplied, until there was a vast &lt;a href=&quot;https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4605976&quot;&gt;zoo&lt;/a&gt; of them, each claiming to price risk and explain return.&lt;/p&gt;

&lt;p&gt;But despite the proliferation of models that price the market and explain the cross-section of returns, one central question remains: Where does all this actually come from? After all, divine metaphors aside, no one created the market from thin air with well structured properties and linear pricing properties. In this post, I want to explore one possible line of reasoning that helps explain why factor models work, not just how. My thinking here is largely influenced by the reading of &lt;a href=&quot;https://www.johnhcochrane.com/asset-pricing&quot;&gt;Cochrane (2005)&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;newsletter-container&quot;&gt;
  &lt;div class=&quot;newsletter-card&quot;&gt;
  &lt;!-- Beehiiv native embed --&gt;
  &lt;script async=&quot;&quot; src=&quot;https://subscribe-forms.beehiiv.com/embed.js&quot;&gt;&lt;/script&gt;
  &lt;iframe src=&quot;https://subscribe-forms.beehiiv.com/25db4bd3-5665-4879-8dbb-8b5d2e826fb6&quot; title=&quot;Subscribe to the Quants Quest newsletter&quot; loading=&quot;lazy&quot; class=&quot;beehiiv-embed&quot; data-test-id=&quot;beehiiv-embed&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; style=&quot;width: 317px; height: 142px; margin: 0; border-radius: 0px 0px 0px 0px !important; background-color: transparent; box-shadow: 0 0 #0000; max-width: 100%;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;style&gt;
.beehiiv-embed {
  height: 142px;
}

@media (max-width: 768px) {
  .beehiiv-embed {
    height: 220px;
  }
}
&lt;/style&gt;

&lt;/div&gt;

&lt;h2 id=&quot;SDF&quot;&gt;SDF: The True Concept Behind Asset Prices&lt;/h2&gt;

&lt;p&gt;When first encountering factors, OLS estimators, shrinkage, and $t$-tests, it can feel rather abstract—especially if the end goal is making an investment decision. Yet one principle is more intuitive and foundational: the &lt;strong&gt;law of one price&lt;/strong&gt;, which underlies most modern asset pricing theory.&lt;/p&gt;

&lt;h3 id=&quot;the-law-of-one-price&quot;&gt;The Law of One Price&lt;/h3&gt;

&lt;p&gt;The Law of One Price states that in an arbitrage-free market, two assets with identical cash flows must have the same price (&lt;a href=&quot;https://doi.org/10.2307/2223329&quot;&gt;G. Cassel (1918)&lt;/a&gt;). In practice, of course, there are frictions such as limited accessibility, bid-ask spreads, or information asymmetries. Nevertheless, it forms the backbone of asset pricing: two portfolios delivering the same payoffs should have the same price, and two bonds with identical cash flows and risk characteristics should offer the same yield.&lt;/p&gt;

&lt;h3 id=&quot;from-the-law-of-one-price-to-the-sdf&quot;&gt;From the Law of One Price to the SDF&lt;/h3&gt;

&lt;p&gt;This idea can be formalized mathematically through the &lt;strong&gt;stochastic discount factor (SDF)&lt;/strong&gt;, also called the pricing kernel &lt;a href=&quot;https://www.johnhcochrane.com/asset-pricing&quot;&gt;Cochrane (2005)&lt;/a&gt;. The SDF is a random variable $m_{t+1}$ that links future payoffs $X_{t+1}$ to current prices $P_t$:&lt;/p&gt;

\[P_t = \mathbb{E}_t \left[ m_{t+1} \, X_{t+1} \right]\]

&lt;p&gt;Equivalently, for excess returns $r_{t+1}$ (returns over the risk-free rate), the SDF satisfies:&lt;/p&gt;

\[\mathbb{E}_t \left[ m_{t+1} \, r_{t+1} \right] = 0\]

&lt;p&gt;Intuitively, this states that &lt;strong&gt;all assets are “fairly priced”&lt;/strong&gt; given the SDF. The SDF is closely related to risk-neutral probabilities and can be thought of as a weighting factor that adjusts future payoffs to their present value while accounting for risk preferences. Go check &lt;a href=&quot;/RandomWalkvsMartingale/&quot;&gt;this previous post&lt;/a&gt; if you want info on that.&lt;/p&gt;

&lt;h3 id=&quot;the-sdf-in-practice&quot;&gt;The SDF in Practice&lt;/h3&gt;

&lt;p&gt;In theory, if we knew the distribution of $m_{t+1}$, pricing would be straightforward. This leads to the “everything is factored into the price,” which you can see on &lt;a href=&quot;https://www.youtube.com/@benjjjaamiinn&quot;&gt;Benjamin Channel&lt;/a&gt;. But in reality, the SDF is unobservable, so we must approximate it. One approach could be Bayesian: treat the SDF as a latent random variable and update a prior distribution with market realizations over time.&lt;/p&gt;

&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/images/thats_my_quant.jpeg&quot; alt=&quot;That&apos;s my Quant&quot; style=&quot;max-height: 350px; width: auto; max-width: 100%;&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;In practice, however, finance has favored &lt;strong&gt;simpler approximations&lt;/strong&gt;. Factor models, estimated via OLS regressions, can be interpreted as &lt;strong&gt;linear projections of the SDF onto observed returns&lt;/strong&gt;. This is why factor models—CAPM, Fama–French, and beyond—capture so much pricing information: they approximate the true, unobservable stochastic discount factor. To known more about the Stochastic Discount Factor and what it’s implies in terms of risk neutral mesures and martingales, go check &lt;a href=&quot;/RandomWalkvsMartingale/&quot;&gt;this previous post&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;FactorModelsAreSDF&quot;&gt;Factor Models as SDFs in Disguise&lt;/h2&gt;

&lt;p&gt;At this point, you might be thinking: &lt;em&gt;“What’s the link between factor models and the SDF?”&lt;/em&gt; If you already know where this is going, congratulations mate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Estimating a factor model&lt;/strong&gt;, whether it is CAPM, the &lt;a href=&quot;https://doi.org/10.1016/j.jfineco.2014.10.010&quot;&gt;Fama–French Five-Factor Model&lt;/a&gt;, or a custom model with hundreds of factors selected via LASSO, is, at its core, &lt;strong&gt;an SDF estimation problem&lt;/strong&gt;. This was a revelation for me while reading John Cochrane’s &lt;em&gt;Asset Pricing&lt;/em&gt; (Chapter 6).&lt;/p&gt;

&lt;h3 id=&quot;from-factor-models-to-the-sdf&quot;&gt;From Factor Models to the SDF&lt;/h3&gt;

&lt;p&gt;Suppose we have a factor model:&lt;/p&gt;

\[r_{i,t+1} = \sum_{k=1}^K \beta_{ik} F_{k,t+1} + \epsilon_{i,t+1}, \quad i = 1, \dots, N\]

&lt;p&gt;with factors $F_k$ and factor loadings $\beta_{ik}$. We want an &lt;strong&gt;implied SDF&lt;/strong&gt; $m_{t+1}^{\text{impl}}$ that satisfies the SDF condition for all assets:&lt;/p&gt;

\[\mathbb{E}_t \left[ m_{t+1}^{\text{impl}} \, r_{i,t+1} \right] = 0 \quad \forall i.\]

&lt;p&gt;Cochrane shows that we can construct it as a &lt;strong&gt;linear combination of the factors&lt;/strong&gt;:&lt;/p&gt;

\[m_{t+1}^{\text{impl}} = 1 - \sum_{k=1}^K \lambda_k F_{k,t+1},\]

&lt;p&gt;where the weights $\lambda_k$ solve the system:&lt;/p&gt;

\[\mathbb{E}_t \Big[ (1 - \sum_{k=1}^K \lambda_k F_{k,t+1}) \, r_{i,t+1} \Big] = 0, \quad i = 1, \dots, N.\]

&lt;p&gt;In matrix notation, let $R$ be the $N \times 1$ vector of excess returns and $F$ the $N \times K$ factor matrix:&lt;/p&gt;

\[\mathbb{E}_t[R] = F \lambda \quad \implies \quad \lambda = (F^\top F)^{-1} F^\top \mathbb{E}_t[R].\]

&lt;p&gt;This provides an &lt;strong&gt;explicit SDF estimate&lt;/strong&gt; from any factor model. Every factor captures a dimension of risk, and the combination of factors approximates the true, unobservable SDF $M_t = 1-\lambda^\top F_t$. This is why factor models are powerful : they encode the pricing kernel in a tractable, estimable form.&lt;/p&gt;

&lt;h3 id=&quot;why-use-factor-models-instead-of-directly-approximating-the-stochastic-discount-factor&quot;&gt;Why Use Factor Models Instead of Directly Approximating the Stochastic Discount Factor?&lt;/h3&gt;

&lt;p&gt;If the true power of a factor model lies in its deep connection to the stochastic discount factor (SDF), why not bypass the factors entirely and approximate the SDF directly to predict future prices?&lt;/p&gt;

&lt;p&gt;The idea might be to approximate the SDF $ M $ and then use the fundamental pricing equation $ P_t = \mathbb{E}[M_{t+1} \times P_{t+1}] $ to compute fair prices and identify whether an asset is over or undervalued. However, this approach isn’t as straightforward or as informative as it might seem.&lt;/p&gt;

&lt;p&gt;For example, suppose $ M = 1 $ almost surely. Then you’re left with $ P_t = \mathbb{E}[P_{t+1}] $, which offers no new insight. This illustrates that simply knowing the distribution of the SDF is not enough.&lt;/p&gt;

&lt;p&gt;What really matters when working with $\mathbb{E}[M_{t+1} R_{t+1}] = 0$ is understanding the joint distribution of $ (M_t, R_t) $ the stochastic discount factor and the asset returns together. This joint distribution is difficult to characterize directly.&lt;/p&gt;

&lt;p&gt;Factor models offer a practical solution by capturing the sensitivity of returns to underlying risk factors. This sensitivity gives us a tractable way to understand how returns co-move with the SDF, essentially providing a handle on their joint behavior.&lt;/p&gt;

&lt;p&gt;In other words, the key mathematical value of factor models is that they let us approximate the joint dynamics between $ M_t $ and $ R_t $ through the factors $ F $. Let’s see that with some equations :&lt;/p&gt;

\[\mathbb{E}_t[R_{t+1} \times M_{t+1}] = 0\]

&lt;p&gt;Which implies&lt;/p&gt;

\[\mathbb{E}_t\big[R_{t+1} \times (1 - \lambda^\top F_{t+1})\big] = 0\]

&lt;p&gt;And thus&lt;/p&gt;

\[\mathbb{E}_t[R_{t+1}] = \mathbb{E}_t[R_{t+1} F_{t+1}^\top] \lambda\]

&lt;p&gt;When using the OLS estimator, the betas of the stock (an $ N \times K $ matrix) are defined as&lt;/p&gt;

\[B_{t+1} = R_{t+1} F_{t+1}^\top (F_{t+1} F_{t+1}^\top)^{-1}\]

&lt;p&gt;Since&lt;/p&gt;

\[R_{t+1} F_{t+1}^\top = R_{t+1} F_{t+1}^\top (F_{t+1} F_{t+1}^\top)^{-1} (F_{t+1} F_{t+1}^\top),\]

&lt;p&gt;We get :&lt;/p&gt;

\[R_{t+1} F_{t+1}^\top = B_{t+1} F_{t+1} F_{t+1}^\top\]

&lt;p&gt;Noting :&lt;/p&gt;

\[\Sigma_{FF}^{t+1} = \mathbb{E}_t[F_{t+1} F_{t+1}^\top]\]

&lt;p&gt;We end up with :&lt;/p&gt;

\[\mathbb{E}_t[R_{t+1}] = B_{t+1} \Sigma_{FF}^{t+1} \lambda\]

&lt;p&gt;By starting with basic properties of the stochastic discount factor, we ultimately arrive at a pricing formula that depends only on our factor model. This is powerful because it allows us to shift the focus from estimating relationships across all $ N $ assets to working with a much smaller set of $ K $ factors.&lt;/p&gt;

&lt;p&gt;Plenty of work must be then done on estimating $B_{t+1}$, $\Sigma_{FF}^{t+1}$ and $\lambda_{t+1}$. When $ K \ll N $, and assuming the factors are not highly correlated, the factor covariance matrix $\Sigma_{FF}^{t+1}$ is easier to estimate, invert, and work with in general.&lt;/p&gt;

&lt;p&gt;This dimensionality reduction offers several practical benefits, including more stable estimates, reduced computational complexity, and better interpretability of risk-return trade-offs.&lt;/p&gt;

&lt;h2 id=&quot;Conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;At first glance, factor models may look like clever statistical tools thrown at return data to extract patterns. But a deeper look reveals something more fundamental: they are not just predictive regressions, they are structured approximations of the Stochastic Discount Factor, the very object at the heart of modern asset pricing. This tells us &lt;em&gt;why&lt;/em&gt; factor models work.&lt;/p&gt;

&lt;p&gt;So next time you’re running a factor regression, remember: you’re not just crunching numbers, you’re approximating the invisible hand that prices all possible states of the economy.&lt;/p&gt;

&lt;p&gt;Got thoughts, questions, or counterpoints? Drop a comment below. I’d love to hear your take.&lt;/p&gt;

</content>
    <category term="Quantitative Finance" />
  </entry>
  
  <entry>
    <title type="html">Merger Arbitrage Explained</title>
    <link href="https://quants.quest/WarnerBrosMerger/" rel="alternate" type="text/html" />
    <id>https://quants.quest/WarnerBrosMerger</id>
    <published>2025-09-21T00:00:00+00:00</published>
    <updated>2025-09-21T00:00:00+00:00</updated>
    <summary type="html">Learn how to analyze merger arbitrage opportunities using the Warner Bros Discovery and Paramount deal rumors. Break down market-implied probabilities, downside risk, and expected value like a quant.</summary>
    <content type="html" xml:base="https://quants.quest/WarnerBrosMerger/">&lt;h2 id=&quot;disclaimer&quot;&gt;Disclaimer&lt;/h2&gt;

&lt;p&gt;This post is for informational and educational purposes only. It does not constitute financial, investment, or trading advice. The author currently holds a position in Warner Bros Discovery (WBD) at the time of writing.&lt;/p&gt;

&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of Contents&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;#what-is-merger-arbitrage&quot;&gt;What Is Merger Arbitrage?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#understanding-implied-probability-from-market-prices&quot;&gt;Market Prices and Implied Probabilities&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#merger-arbitrage-methodology&quot;&gt;A Simple Merger Arbitrage Methodology&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#case-study-warner-bros-discovery-paramountskydance&quot;&gt;Case Study: Warner Bros &amp;amp; Paramount Merger&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;4.1 &lt;a href=&quot;#deal-overview&quot;&gt;Deal Overview&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;4.2 &lt;a href=&quot;#price-based-probability-estimation&quot;&gt;Price-Based Probability Estimation&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;4.3 &lt;a href=&quot;#sensitivity-analysis&quot;&gt;Sensitivity Analysis&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#risks-and-considerations&quot;&gt;Risks and Considerations&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#building-an-arbitrage-framework&quot;&gt;Building an Arbitrage Framework&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;what-is-merger-arbitrage&quot;&gt;What Is Merger Arbitrage&lt;/h2&gt;

&lt;p&gt;I’ve held a large position in Warner Bros Discovery (WBD) since 2023, so when news broke of a potential takeover by Paramount/Skydance, it naturally caught my attention. This post is partly motivated by that position, and more broadly by the opportunity to walk through how merger arbitrage can be evaluated when a real-world event unfolds.&lt;/p&gt;

&lt;p&gt;Let’s walk through it.&lt;/p&gt;

&lt;p&gt;Merger arbitrage is an event-driven investment strategy built around one simple idea: when a company announces it’s acquiring another, there’s a temporary pricing inefficiency and that create an opportunity. Here’s how it works.&lt;/p&gt;

&lt;p&gt;When an acquisition is announced, the acquirer offers to buy the target company, &lt;strong&gt;usually at a premium&lt;/strong&gt;. For example, they might offer 24\$ per share for a company that was trading at 15\$. The target’s stock typically jumps on the news… but not all the way to 24$. Why not? Because there’s still risk: the deal might fall through, get delayed, or be blocked by regulators. So the market applies a discount, pricing in the possibility of failure.&lt;/p&gt;

&lt;p&gt;This gap between the current market price of the target and the deal price is called the &lt;strong&gt;spread&lt;/strong&gt;. Merger arbitrageurs make bets on it to make an arbitrage.&lt;/p&gt;

&lt;p&gt;In a pure &lt;strong&gt;cash deal&lt;/strong&gt;, the arbitrage setup is straightforward: you buy the target company’s shares after the deal is announced and wait. If the deal closes, the acquirer pays cash, and you pocket the difference. If the deal breaks, the stock usually drops, sometimes sharply, and you lose money. So the whole game is about &lt;strong&gt;probabilities&lt;/strong&gt; and &lt;strong&gt;payoffs&lt;/strong&gt;. In this post I will only talk about this kind of deal.&lt;/p&gt;

&lt;p&gt;The wider the spread, the more the market is signaling uncertainty. A narrow spread? The market sees a high chance of the deal going through. A wide spread? More risk or at least, more perceived risk.&lt;/p&gt;

&lt;p&gt;In some cases, the spread can even go negative, the stock trades above the offer price. That usually means investors are betting on a bidding war or a sweetened deal.&lt;/p&gt;

&lt;p&gt;Merger arbitrage isn’t about guessing whether a stock will go up or down. It’s about &lt;strong&gt;evaluating a specific corporate event&lt;/strong&gt;, estimating the probability of success, and judging whether the potential return justifies the risk. It’s closer to probabilistic thinking than traditional investing.&lt;/p&gt;

&lt;p&gt;It’s not glamorous. It’s not momentum-driven. But when done systematically with proper sizing, scenario modeling, and discipline it can be a effective strategy (here a &lt;a href=&quot;https://www.aima.org/asset/676DA5D6-8CE4-42D7-A2C6171EAC6382DC/&quot;&gt;first article&lt;/a&gt; and a &lt;a href=&quot;https://papers.ssrn.com/sol3/papers.cfm?abstract_id=315639&quot;&gt;second one&lt;/a&gt; documenting this assertion).&lt;/p&gt;

&lt;div class=&quot;newsletter-container&quot;&gt;
  &lt;div class=&quot;newsletter-card&quot;&gt;
  &lt;!-- Beehiiv native embed --&gt;
  &lt;script async=&quot;&quot; src=&quot;https://subscribe-forms.beehiiv.com/embed.js&quot;&gt;&lt;/script&gt;
  &lt;iframe src=&quot;https://subscribe-forms.beehiiv.com/25db4bd3-5665-4879-8dbb-8b5d2e826fb6&quot; title=&quot;Subscribe to the Quants Quest newsletter&quot; loading=&quot;lazy&quot; class=&quot;beehiiv-embed&quot; data-test-id=&quot;beehiiv-embed&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; style=&quot;width: 317px; height: 142px; margin: 0; border-radius: 0px 0px 0px 0px !important; background-color: transparent; box-shadow: 0 0 #0000; max-width: 100%;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;style&gt;
.beehiiv-embed {
  height: 142px;
}

@media (max-width: 768px) {
  .beehiiv-embed {
    height: 220px;
  }
}
&lt;/style&gt;

&lt;/div&gt;

&lt;h2 id=&quot;understanding-implied-probability-from-market-prices&quot;&gt;Market Prices and Implied Probabilities&lt;/h2&gt;

&lt;p&gt;When a public company announces it’s being acquired, the offer is almost always above the last trading price, often significantly. That premium is what makes merger arbitrage possible.&lt;/p&gt;

&lt;p&gt;Let’s work on a simple example. Imagine a small public company : let’s call it Banana. It is trading at 10\$ per share. One morning, Apple announces it wants to acquire that company for 20\$ a share, in cash. That’s a 100% premium.&lt;/p&gt;

&lt;p&gt;What happens to the stock? It jumps, but not to 20$. Maybe it shoots up to 18\$ or 19\$. That difference between the offer price 20\$ and the new trading price (say, 18\$) is called the &lt;strong&gt;spread&lt;/strong&gt;. And it contains valuable information.&lt;/p&gt;

&lt;h3 id=&quot;the-spreak-is-the-market-priced-deal-risk&quot;&gt;The Spreak is the Market-Priced Deal Risk&lt;/h3&gt;

&lt;p&gt;If the market believed with 100% certainty that the deal would close exactly as proposed, the stock would immediately trade at 20\$. But that almost never happens. There’s always &lt;em&gt;some&lt;/em&gt; risk : antitrust issues, financing problems, board pushback, political pressure, or just the chance that the acquirer changes its mind.&lt;/p&gt;

&lt;p&gt;So the market prices in that uncertainty. In our example, the 2\$ gap between 18\$ and 20\$ is how the market &lt;em&gt;discounts&lt;/em&gt; the possibility that the deal might not happenn or might happen later, or on worse terms.&lt;/p&gt;

&lt;p&gt;From that spread, we can actually &lt;strong&gt;estimate the implied probability&lt;/strong&gt; of the deal closing.&lt;/p&gt;

&lt;h3 id=&quot;a-simple-formula&quot;&gt;A Simple Formula&lt;/h3&gt;

&lt;p&gt;We can model the current price as a weighted average of two outcomes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The deal closes, and the target gets 20\$&lt;/li&gt;
  &lt;li&gt;The deal fails, and the target falls back to its pre-deal price (say, 10\$)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can write this as:&lt;/p&gt;

\[\text{Market Price} = p \times \text{Deal Price} + (1 - p) \times \text{Fallback Price}\]

&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;$p$ is the &lt;strong&gt;implied probability&lt;/strong&gt; of deal success&lt;/li&gt;
  &lt;li&gt;Deal Price is the offer amount (e.g. 20\$)&lt;/li&gt;
  &lt;li&gt;Fallback Price is the estimated value if the deal fails (e.g. 10\$)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Solving for $p$:&lt;/p&gt;

\[p = \frac{\text{Market Price} - \text{Fallback Price}}{\text{Deal Price} - \text{Fallback Price}}\]

&lt;p&gt;Plug in the numbers from our example:&lt;/p&gt;

\[p = \frac{18 - 10}{20 - 10} = \frac{8}{10} = 0.80\]

&lt;p&gt;So, in this case, the market is pricing in &lt;strong&gt;an 80% chance&lt;/strong&gt; that the deal will close as announced.&lt;/p&gt;

&lt;h2 id=&quot;merger-arbitrage-methodology&quot;&gt;Merger Arbitrage Methodology&lt;/h2&gt;

&lt;p&gt;The implied probability isn’t just academic : it’s your decision-making compass.&lt;/p&gt;

&lt;p&gt;If you’re looking at a potential merger arbitrage setup, here’s the process in plain terms:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Step 1: Understand what the market is pricing in.&lt;/strong&gt;&lt;br /&gt;
The current spread between the offer price and the trading price reflects the market’s best guess at the probability the deal will close. Not with certainty, but under prevailing assumptions: risk, timing, regulatory pressure, etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Step 2: Decide whether you agree.&lt;/strong&gt;&lt;br /&gt;
This is the core of the strategy. You’re not predicting prices — you’re evaluating scenarios. Is the market underestimating the chance of success? Are people missing a regulatory blocker? Has the risk already been overstated?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Step 3: Think in outcomes, not absolutes.&lt;/strong&gt;&lt;br /&gt;
There are usually two (or more) outcomes: the deal closes, or it doesn’t. Each comes with a probability, a timeline, and a payoff. Your goal is to model the expected value (EV) of the trade, given those inputs.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;the-expected-value-framework&quot;&gt;The Expected Value Framework&lt;/h3&gt;

&lt;p&gt;Let’s break it into a simple two-outcome model:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Deal Price (D):&lt;/strong&gt; The price paid if the acquisition closes&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Current Price (C):&lt;/strong&gt; What the target trades at now&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Fallback Price (F):&lt;/strong&gt; Estimated value if the deal fails&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Probability of Success (p):&lt;/strong&gt; Your estimate (or market’s implied)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then your &lt;strong&gt;expected value (EV)&lt;/strong&gt; per share is:&lt;/p&gt;

\[\text{EV} = p \times D + (1 - p) \times F\]

&lt;p&gt;If EV is meaningfully above the current price (after adjusting for time and risk), it’s potentially a good trade. If not, you pass.&lt;/p&gt;

&lt;h3 id=&quot;a-quick-example&quot;&gt;A Quick Example&lt;/h3&gt;

&lt;p&gt;Suppose:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Deal price = 24\$&lt;/li&gt;
  &lt;li&gt;Current stock price = 19\$&lt;/li&gt;
  &lt;li&gt;Fallback (if deal fails) = 12\$&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using the formula to back out the &lt;strong&gt;implied probability&lt;/strong&gt;:&lt;/p&gt;

\[p = \frac{19 - 12}{24 - 12} = \frac{7}{12} \approx 58\%\]

&lt;p&gt;Now suppose you think, because you are an expert in the industry for example, that the chance of success is more like 70%. Plug it in:&lt;/p&gt;

\[\text{EV} = 0.70 \times 24 + 0.30 \times 12 = 16.8 + 3.6 = 20.4\]

&lt;p&gt;The expected value under your assumptions is 20.40\$, which is above the current price 19\$. That suggests a potential edge &lt;em&gt;if&lt;/em&gt; your assumptions are more accurate than the market’s. When making a are more complex model, you should take into account also the time required for the deal to go trough, and think more into target and fallback distributions than fixed parameters.&lt;/p&gt;

&lt;h2 id=&quot;case-study-warner-bros-discovery-paramountskydance&quot;&gt;Warner Bros &amp;amp; Paramount Merger&lt;/h2&gt;

&lt;h3 id=&quot;deal-overview&quot;&gt;Deal Overview&lt;/h3&gt;

&lt;p&gt;According to a &lt;a href=&quot;https://nypost.com/2025/09/19/media/paramount-skydance-eyes-takeover-bid-for-warner-bros-discovery-report/&quot;&gt;New York Post report (Sep 19, 2025)&lt;/a&gt;, Skydance Media, which recently acquired control of Paramount Global, is now exploring a bid to acquire Warner Bros Discovery at a price in the range of &lt;strong&gt;22\$–24\$ per share&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This isn’t a formal offer (yet), but it’s enough to move the market. Want to see it ? Here the Warner Bros stock price over the last days (and bonus the Python code to do it at home) :&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;yfinance&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yf&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;datetime&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Fetch WBD price data
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ticker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Ticker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;WBD&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025-06-01&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025-09-21&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ticker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Plot
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Close&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;WBD Close Price&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;navy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axvline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2025&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;red&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linestyle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;--&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Deal Rumor (Sep 19)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;WBD Stock Price – June to September 2025&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Date&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Price ($)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;grid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tight_layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/WarnerBros_fig_1.png&quot; alt=&quot;Warner Bros Stock Evolution&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Analyst reactions have been mixed: analysts from TD Cowen have downgraded WBD from Buy to Hold, arguing that without a deal, the stock could fall back to &lt;strong&gt;11\$–12\$&lt;/strong&gt;, based on fundamentals. (&lt;a href=&quot;https://www.marketwatch.com/story/buying-wbds-stock-ahead-of-a-possible-paramount-deal-this-analyst-is-cautious-0b4fa36c&quot;&gt;MarketWatch, Sep 20, 2025&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;How to get info like that easily at home ? Here again python is your friend. Here a small code enabling you to get recent headlines on any ticker :&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;yfinance&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yf&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;datetime&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Fetch the lastest news article for Warner Bros Discovery (WBD)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ticker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Ticker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;WBD&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;news_items&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ticker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_news&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Format and print the news like an RSS reader
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;news_item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;content&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;published&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;displayTime&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;canonicalUrl&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;url&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;summary&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;summary&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;📌 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🔗 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;📌 Wells Fargo Raises Warner Bros. Discovery &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;WBD&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Price Target, Sees M&amp;amp;A Potential
Warner Bros. Discovery Inc. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;NASDAQ:WBD&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; ranks among the best communication services stocks to buy now.
Wells Fargo boosted its price target &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;Warner Bros. Discovery Inc. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;NASDAQ:WBD&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; to 14&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;from 13&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;on
September 11, retaining an Equal Weight rating on the company’s shares. The revision reflects
Wells Fargo’s belief that Warner Brothers Discovery’s Studios and &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;…]
🔗 https://finance.yahoo.com/news/wells-fargo-raises-warner-bros-075936106.html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So what is the market currently pricing in? Let’s quantify it.&lt;/p&gt;

&lt;h3 id=&quot;price-based-probability-estimation&quot;&gt;Price-Based Probability Estimation&lt;/h3&gt;

&lt;p&gt;Let’s plug in some numbers based on the reporting and price action:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Deal price (X)&lt;/strong&gt;: We will use 24\$&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Current price (Y)&lt;/strong&gt;: 19\$ (WBD has traded between 18\$–20\$ since the rumor broke)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Fallback price (B)&lt;/strong&gt;: 11\$ (where analysts estimate WBD would trade without a deal)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using the implied probability formula:&lt;/p&gt;

\[p = \frac{Y - B}{X - B} = \frac{19 - 11}{24 - 11} = \frac{8}{13} \approx 61.5\%\]

&lt;p&gt;So based on this spread, the market is implying roughly a &lt;strong&gt;61–62% chance&lt;/strong&gt; that the deal goes through &lt;em&gt;as rumored&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Again using &lt;em&gt;yfinance&lt;/em&gt; and &lt;em&gt;Python&lt;/em&gt; you can easily look at the evolution of the merger probability (under this parameters of deal price and fallback of course) :&lt;/p&gt;

&lt;p&gt;import yfinance as yf
import matplotlib.pyplot as plt&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Fetch WBD price data
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ticker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Ticker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;WBD&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025-06-01&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025-09-21&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ticker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;deal_price&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Assumed acquisition price
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fallback_price&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Assumed fallback price
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Implied_Probability&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Close&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fallback_price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deal_price&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fallback_price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Implied_Probability&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Implied Deal Probability&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;purple&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axhline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;gray&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linestyle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;--&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Market-Implied Probability of WBD Acquisition&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Date&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Probability&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;grid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tight_layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/WarnerBros_fig_2.png&quot; alt=&quot;Market-Implied Probability of WBD Acquisition&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Let’s break down the potential payoff structure:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Upside if deal closes&lt;/strong&gt;: 5\$ per share → about &lt;strong&gt;+26.3%&lt;/strong&gt; return from 19\$ to 24\$&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Downside if deal fails&lt;/strong&gt;: Loss of 8\$ per share → about &lt;strong&gt;–42.1%&lt;/strong&gt; from 19\$ to 11\$&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the deal closes in &lt;strong&gt;6 months&lt;/strong&gt;, that’s a 26% return in half a year, or over &lt;strong&gt;50% annualized&lt;/strong&gt; (not adjusting for taxes or compounding). But &lt;strong&gt;this return is priced in&lt;/strong&gt;. Meaning the risk of dowside exist and is priced. The question you must ask yourself in this situation is more : is the market probability near the truth ? ie is the market efficient ?&lt;/p&gt;

&lt;h3 id=&quot;sensitivity-analysis&quot;&gt;Sensitivity Analysis&lt;/h3&gt;

&lt;p&gt;The final step to fully understand our model is asking : &lt;strong&gt;how sensitive are we to changes in assumptions ?&lt;/strong&gt; Let’s run a few scenarios.&lt;/p&gt;

&lt;h4 id=&quot;what-if-the-fallback-increase-&quot;&gt;What if the fallback increase ?&lt;/h4&gt;

&lt;p&gt;Suppose the market is wrong about the downside, and the true fallback price is 14\$, not 11\$. Then:&lt;/p&gt;

\[p = \frac{19 - 14}{24 - 14} = \frac{5}{10} = 50\%\]

&lt;p&gt;So in this more optimistic view, the &lt;strong&gt;implied probability drops to 50%&lt;/strong&gt;, because the downside isn’t as severe.&lt;/p&gt;

&lt;h4 id=&quot;what-if-the-deal-price-decrease-&quot;&gt;What if the deal price decrease ?&lt;/h4&gt;

&lt;p&gt;What if the deal gets negotiated down to 22\$ ? Then:&lt;/p&gt;

\[p = \frac{19 - 11}{22 - 11} = \frac{8}{11} \approx 72.7\%\]

&lt;p&gt;Ironically, a &lt;strong&gt;lower offer price&lt;/strong&gt; results in a &lt;em&gt;higher implied probability&lt;/em&gt; — because the spread narrows.&lt;/p&gt;

&lt;p&gt;This shows that the probability estimate is sensitive to both inputs: the upside and the fallback. What if we want to look at it in more scalable fashion ?&lt;/p&gt;

&lt;h4 id=&quot;getting-the-full-picture&quot;&gt;Getting the full picture&lt;/h4&gt;

&lt;p&gt;The 24\$ dollars per share is maybe a good payoff guess, but what about the fallback price ? Warner Bros Stock has move from 8 to 14\$ regularly over the last 2 years. Again (and for the last time) we can use Python to study the sensitivity to this fallback price. What we want to see is the &lt;em&gt;implied probability&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;seaborn&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sns&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Set deal price
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deal_price&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Define fallback and market price ranges
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fallbacks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;12.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# $8 to $12
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;23.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# $11 to $24
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Create a matrix to store implied probabilities
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spread_matrix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zeros&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fallbacks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Compute implied probabilities
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fallbacks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;    
        &lt;span class=&quot;n&quot;&gt;spread_matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deal_price&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
&lt;span class=&quot;c1&quot;&gt;# Clip to range [0, 1] for clarity
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spread_matrix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spread_matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;spread_matrix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spread_matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Plot heatmap
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heatmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spread_matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;annot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.2f&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;YlGnBu&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;xticklabels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yticklabels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fallbacks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cbar_kws&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;label&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;Implied Probability&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Market Price ($)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Fallback Price ($)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Implied Probability Sensitivity — WBD Deal at 24$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xticks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rotation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;45&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tight_layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/WarnerBros_fig_3.png&quot; alt=&quot;Implied Probability Sensitivity — WBD Deal at 24&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;what-makes-this-deal-tricky&quot;&gt;What Makes This Deal Tricky?&lt;/h3&gt;

&lt;p&gt;Beyond price modeling, this deal carries &lt;strong&gt;significant regulatory risk&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;According to a &lt;a href=&quot;https://journals.library.columbia.edu/index.php/lawandarts/announcement/view/826&quot;&gt;Columbia Journal of Law &amp;amp; the Arts article&lt;/a&gt;, a Paramount–WBD merger would likely trigger scrutiny under the 2023 DOJ/FTC Merger Guidelines. The combined entity would have substantial market share in theatrical distribution, streaming, and television possibly pushing it into “highly concentrated” territory by antitrust standards.&lt;/p&gt;

&lt;p&gt;Key regulatory concerns:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Horizontal overlap&lt;/strong&gt; in film studios and content production&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Vertical integration&lt;/strong&gt; risks (content + distribution)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Media plurality&lt;/strong&gt; concerns (CNN + CBS News under one roof)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Public interest tests&lt;/strong&gt; from the FCC (because of news media and licenses)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So even if Skydance makes a formal offer, the path to closing could be long and far from guaranteed.&lt;/p&gt;

&lt;h3 id=&quot;where-we-are-now&quot;&gt;Where We Are Now&lt;/h3&gt;

&lt;p&gt;To sum up:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The market is pricing in &lt;strong&gt;~60% chance&lt;/strong&gt; of a 24\$ share deal based on current prices and downside estimates&lt;/li&gt;
  &lt;li&gt;Regulatory headwinds are real and potentially deal-breaking&lt;/li&gt;
  &lt;li&gt;If you think the market is &lt;strong&gt;too cautious&lt;/strong&gt;, there may be opportunity&lt;/li&gt;
  &lt;li&gt;If you think the market is &lt;strong&gt;too optimistic&lt;/strong&gt;, it might be time to hedge or trim&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest depends on how you model risk and whether you trust your estimates more than the market.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The Warner Bros Discovery–Paramount/Skydance case offers a real-time example of how markets digest deal rumors, price in uncertainty, and reflect a collective estimate of risk, all through a single number: the stock price.&lt;/p&gt;

&lt;p&gt;This case illustrates a few key points:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Markets imply probabilities&lt;/strong&gt; through price — not opinion. While analysts debate whether WBD is worth 11\$ or 14\$ without a deal, the stock price incorporates not just that debate, but the &lt;em&gt;likelihood&lt;/em&gt; of various outcomes.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Implied probability is not truth&lt;/strong&gt; : it’s just what the current prices suggest. If you have a differentiated view on the deal’s odds or timing, that’s where alpha can live.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;A simple framework goes a long way&lt;/strong&gt;. By mapping out:
    &lt;ul&gt;
      &lt;li&gt;the potential deal price (upside)&lt;/li&gt;
      &lt;li&gt;the fallback value (downside)&lt;/li&gt;
      &lt;li&gt;the timeline to closing&lt;/li&gt;
      &lt;li&gt;the regulatory and strategic context
…you can structure a probabilistic view of the trade, rather than just a gut feeling.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn’t forecasting. It’s scenario modeling and it forces clarity of thought.&lt;/p&gt;

&lt;p&gt;What we’ve walked through here is a first-principles framework: pricing, spreads, probabilities, payoffs.&lt;/p&gt;

&lt;p&gt;But more complex models are absolutely possible:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Multi-scenario trees&lt;/strong&gt;, with branching outcomes (e.g. competing bids, revised terms, partial deals)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Bayesian updates&lt;/strong&gt; as new information arrives (regulatory signals, earnings calls, leaks)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Monte Carlo simulations&lt;/strong&gt; to model a range of regulatory, political, or timing variables&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Option-based models&lt;/strong&gt; to account for volatility in both upside and fallback prices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don’t &lt;em&gt;need&lt;/em&gt; these tools to start — but as the stakes grow, or as you allocate more capital to merger arbitrage, adding depth to your modeling can help improve risk management and return profile.&lt;/p&gt;

&lt;p&gt;What’s your take ? Is the market underestimating the regulatory risk here ? Or is this a misunderstood opportunity ? Let’s talk bellow !&lt;/p&gt;

</content>
    <category term="Quantitative Finance" /><category term="Python" />
  </entry>
  
  <entry>
    <title type="html">Anaconda to Create a Clean Python Environment</title>
    <link href="https://quants.quest/PythonInstallation/" rel="alternate" type="text/html" />
    <id>https://quants.quest/PythonInstallation</id>
    <published>2025-09-20T00:00:00+00:00</published>
    <updated>2025-09-20T00:00:00+00:00</updated>
    <summary type="html">Learn how to use Anaconda for your Python setup, allowing you to run .py files and jupiter notebooks.</summary>
    <content type="html" xml:base="https://quants.quest/PythonInstallation/">&lt;p&gt;Setting up a clean and stable Python environment is essential for learning and working on projects. This guide will show you how to use &lt;strong&gt;Anaconda&lt;/strong&gt; to do just that.&lt;/p&gt;

&lt;h2 id=&quot;-what-is-anaconda&quot;&gt;🐍 What is Anaconda?&lt;/h2&gt;

&lt;p&gt;Anaconda is a free Python distribution that includes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Python interpreter&lt;/li&gt;
  &lt;li&gt;Popular libraries like NumPy, pandas, matplotlib&lt;/li&gt;
  &lt;li&gt;Jupyter Notebook&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conda&lt;/code&gt; environment manager&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s ideal for students and beginners because it simplifies installation and avoids conflicts between projects. It is compatible with &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VS CODE&lt;/a&gt; ide. An official tutorial exist &lt;a href=&quot;https://test-jupyter.readthedocs.io/en/latest/install.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;-step-1-install-anaconda&quot;&gt;🔧 Step 1: Install Anaconda&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Download Anaconda:&lt;br /&gt;
👉 &lt;a href=&quot;https://www.anaconda.com/download&quot;&gt;https://www.anaconda.com/download&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Choose your OS and download the &lt;strong&gt;Python 3.x (64-bit)&lt;/strong&gt; version.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Run the installer and follow the prompts:&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;(Optional) On Windows, check “Add Anaconda to my PATH”&lt;/li&gt;
      &lt;li&gt;Select “Just Me” and complete installation.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;-step-2-create-a-new-conda-environment&quot;&gt;🧪 Step 2: Create a New Conda Environment&lt;/h2&gt;

&lt;p&gt;Open &lt;strong&gt;Anaconda Prompt&lt;/strong&gt; (Windows) or Terminal (macOS/Linux):&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;conda create &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; myproject &lt;span class=&quot;nv&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;3.10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;-step-3-activate-your-environment&quot;&gt;📂 Step 3: Activate Your Environment&lt;/h2&gt;

&lt;p&gt;After creating the environment, you need to activate it:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;conda activate myproject
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;-step-4-install-packages&quot;&gt;📚 Step 4: Install Packages&lt;/h2&gt;

&lt;p&gt;Use conda install to install packages:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;conda &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;numpy pandas matplotlib jupyter
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;If a package isn’t available in the default conda channel, you can try conda-forge:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;conda &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; conda-forge scikit-learn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Or even use pip inside the environment:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;seaborn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now any Python packages you install will be isolated from your base installation.&lt;/p&gt;

&lt;h2 id=&quot;-step-5-use-the-environment-in-vs-code&quot;&gt;💻 Step 5: Use the Environment in VS Code&lt;/h2&gt;

&lt;p&gt;Anaconda integrates smoothly with VS Code. Once your environment is created, you can use it for both Jupyter notebooks and Python scripts.&lt;/p&gt;

&lt;h3 id=&quot;-for-notebooks-ipynb&quot;&gt;📝 For Notebooks (.ipynb)&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Open VS Code.&lt;/li&gt;
  &lt;li&gt;Install the extensions:&lt;/li&gt;
  &lt;li&gt;Python (by Microsoft)&lt;/li&gt;
  &lt;li&gt;Jupyter (by Microsoft)&lt;/li&gt;
  &lt;li&gt;Open a .ipynb file or create a new notebook.&lt;/li&gt;
  &lt;li&gt;In the top-right corner, select the kernel → choose your conda environment (myproject).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, your notebook cells will run inside the clean conda environment.&lt;/p&gt;

&lt;h3 id=&quot;-for-python-scripts-py&quot;&gt;📄 For Python Scripts (.py)&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Open a .py file in VS Code.&lt;/li&gt;
  &lt;li&gt;Look at the bottom-right corner of VS Code → click on the interpreter selector.&lt;/li&gt;
  &lt;li&gt;Choose the interpreter from your environment (it should appear as something like Python 3.10 (‘myproject’)).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once selected, running scripts (Run → Run Without Debugging or the green button) will execute in your conda environment.&lt;/p&gt;

&lt;div class=&quot;newsletter-container&quot;&gt;
  &lt;div class=&quot;newsletter-card&quot;&gt;
  &lt;!-- Beehiiv native embed --&gt;
  &lt;script async=&quot;&quot; src=&quot;https://subscribe-forms.beehiiv.com/embed.js&quot;&gt;&lt;/script&gt;
  &lt;iframe src=&quot;https://subscribe-forms.beehiiv.com/25db4bd3-5665-4879-8dbb-8b5d2e826fb6&quot; title=&quot;Subscribe to the Quants Quest newsletter&quot; loading=&quot;lazy&quot; class=&quot;beehiiv-embed&quot; data-test-id=&quot;beehiiv-embed&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; style=&quot;width: 317px; height: 142px; margin: 0; border-radius: 0px 0px 0px 0px !important; background-color: transparent; box-shadow: 0 0 #0000; max-width: 100%;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;style&gt;
.beehiiv-embed {
  height: 142px;
}

@media (max-width: 768px) {
  .beehiiv-embed {
    height: 220px;
  }
}
&lt;/style&gt;

&lt;/div&gt;

</content>
    <category term="Python" />
  </entry>
  
  <entry>
    <title type="html">Random Walk vs Martingale: What’s the Difference</title>
    <link href="https://quants.quest/RandomWalkvsMartingale/" rel="alternate" type="text/html" />
    <id>https://quants.quest/RandomWalkvsMartingale</id>
    <published>2025-09-12T00:00:00+00:00</published>
    <updated>2025-09-12T00:00:00+00:00</updated>
    <summary type="html">Learn the key differences between martingales and random walks in finance. Includes intuitive examples, asset pricing theory, and Python code.</summary>
    <content type="html" xml:base="https://quants.quest/RandomWalkvsMartingale/">&lt;p&gt;Finance students often encounter both &lt;a href=&quot;https://en.wikipedia.org/wiki/Random_walk&quot;&gt;&lt;em&gt;random walks&lt;/em&gt;&lt;/a&gt; and &lt;a href=&quot;https://fr.wikipedia.org/wiki/Martingale_(calcul_stochastique)&quot;&gt;&lt;em&gt;martingales&lt;/em&gt;&lt;/a&gt; in their studies. At first sight, the two concepts look almost the same : both can be applied to describe the process, that “do not drift on average”. But both concepts are not identical. Understanding the distinction is crucial.&lt;/p&gt;

&lt;p&gt;In this article, we’ll clarify the concepts, illustrate them with Python simulations, and explain why the distinction matters in finance.&lt;/p&gt;

&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of Contents&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;#Random-Walk&quot;&gt;Random Walk: A Simple Model of Prices&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#Martingale&quot;&gt;Martingale: A Broader Mathematical Concept&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#KeyDifferences&quot;&gt;Random Walk vs Martingale: Key Differences&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#Conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#Further_Reading&quot;&gt;Further Reading&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;Random-Walk&quot;&gt;What is a Random Walk in Finance?&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;random walk&lt;/strong&gt; is one of the simplest &lt;a href=&quot;https://en.wikipedia.org/wiki/Stochastic_process&quot;&gt;stochastic processes&lt;/a&gt;. In discrete time, it is defined as:&lt;/p&gt;

\[X_{t+1} = X_t + \epsilon_{t+1}\]

&lt;p&gt;where $\epsilon_{t+1}$ are independent and identically distributed (i.i.d.) shocks, often assumed to be Gaussian with mean zero and variance $\sigma^2$. The noise distribution can however take different for, including distribution with heavy tails.&lt;/p&gt;

&lt;h3 id=&quot;intuition&quot;&gt;Intuition&lt;/h3&gt;

&lt;p&gt;At each step, the process moves up or down randomly, with no predictable trend. The past brings no information to the future.&lt;/p&gt;

&lt;div class=&quot;newsletter-container&quot;&gt;
  &lt;div class=&quot;newsletter-card&quot;&gt;
  &lt;!-- Beehiiv native embed --&gt;
  &lt;script async=&quot;&quot; src=&quot;https://subscribe-forms.beehiiv.com/embed.js&quot;&gt;&lt;/script&gt;
  &lt;iframe src=&quot;https://subscribe-forms.beehiiv.com/25db4bd3-5665-4879-8dbb-8b5d2e826fb6&quot; title=&quot;Subscribe to the Quants Quest newsletter&quot; loading=&quot;lazy&quot; class=&quot;beehiiv-embed&quot; data-test-id=&quot;beehiiv-embed&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; style=&quot;width: 317px; height: 142px; margin: 0; border-radius: 0px 0px 0px 0px !important; background-color: transparent; box-shadow: 0 0 #0000; max-width: 100%;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;style&gt;
.beehiiv-embed {
  height: 142px;
}

@media (max-width: 768px) {
  .beehiiv-embed {
    height: 220px;
  }
}
&lt;/style&gt;

&lt;/div&gt;

&lt;h3 id=&quot;financial-interpretation&quot;&gt;Financial interpretation&lt;/h3&gt;

&lt;p&gt;If stock prices followed a random walk, tomorrow’s price would equal today’s price plus a random shock. This aligns with the &lt;strong&gt;Efficient Market Hypothesis&lt;/strong&gt; : if markets are efficient, new information arrives randomly, and so do price changes.&lt;/p&gt;

&lt;h3 id=&quot;python-example&quot;&gt;Python example&lt;/h3&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;252&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;eps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cumsum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# random walk
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Random Walk Simulations&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/RWvsM_fig_1.png&quot; alt=&quot;Python simulation of random walk in finance&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;Martingale&quot;&gt;What is a Random Walk in Stock Prices?&lt;/h2&gt;

&lt;p&gt;A martingale is defined in probability theory as a process $X_t$ such that:&lt;/p&gt;

\[\mathbb{E}[X_{t+1} \mid \mathcal{F}_t] = X_t\]

&lt;p&gt;where $\mathcal{F}_t$ is the information available up to time $t$.&lt;/p&gt;

&lt;h3 id=&quot;intuition-1&quot;&gt;Intuition&lt;/h3&gt;

&lt;p&gt;The conditional expectation of tomorrow’s value, given today’s information, is just today’s value. In other words, knowing the past gives you no edge in predicting the future.&lt;/p&gt;

&lt;h3 id=&quot;key-difference-from-random-walk&quot;&gt;Key difference from random walk&lt;/h3&gt;

&lt;p&gt;A martingale is defined by a conditional expectation property under a probability measure, when a random walk is model of the behavior of $X_t$. This makes the martingale a far more general concept.&lt;/p&gt;

&lt;h3 id=&quot;financial-interpretation-the-role-of-the-sdf-and-change-of-measure&quot;&gt;Financial Interpretation: The Role of the SDF and Change of Measure&lt;/h3&gt;

&lt;p&gt;Under the &lt;strong&gt;real-world probability measure&lt;/strong&gt; $\mathbb{P}$, a stock price is generally &lt;strong&gt;not&lt;/strong&gt; a martingale due to the presence of risk premia—investors demand compensation for bearing risk. However, in &lt;strong&gt;risk-neutral pricing&lt;/strong&gt;, we use a different probability measure, called the &lt;strong&gt;risk-neutral measure&lt;/strong&gt; $\mathbb{Q}$, under which &lt;strong&gt;discounted asset prices become martingales&lt;/strong&gt;. This makes the concept universal.&lt;/p&gt;

&lt;h4 id=&quot;what-is-the-risk-neutral-probability&quot;&gt;What is the risk neutral probability&lt;/h4&gt;

&lt;p&gt;This probability transformation is made possible by the &lt;strong&gt;Stochastic Discount Factor (SDF)&lt;/strong&gt;, also known as the &lt;strong&gt;pricing kernel&lt;/strong&gt;. The SDF captures how investors value future payoffs relative to today, adjusting for both &lt;strong&gt;time value&lt;/strong&gt; and &lt;strong&gt;risk preferences&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If we consider no dividends from $t$ to $t+1$ the connection is formalized as:&lt;/p&gt;

\[\forall i \in \Omega : P_t^i  = \mathbb{E}^{\mathbb{P}}_t \left[ m_{t+1} \cdot P_{t+1}^i \right]\]

&lt;p&gt;Here, $m_{t+1}$ acts as a &lt;strong&gt;weighting function&lt;/strong&gt; that adjusts future payoffs based on states of the world, giving less weight to “good” states (where marginal utility is low) and more to “bad” states (where it’s high).&lt;/p&gt;

&lt;p&gt;But how is this possible ? Let’s define the &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Radon%E2%80%93Nikodym_theorem&quot;&gt;Radon-Nikodym&lt;/a&gt; derivative&lt;/strong&gt;:&lt;/p&gt;

\[\begin{equation}
\frac{d\mathbb{Q}}{d\mathbb{P}} = \frac{m_{t+1}}{\mathbb{E}^{\mathbb{P}}[m_{t+1}]}
\tag{1}
\end{equation}\]

&lt;p&gt;using this ratio we can &lt;strong&gt;shift from the real-world measure to the risk-neutral measure&lt;/strong&gt;:&lt;/p&gt;

\[\begin{aligned}
\mathbb{E}^{\mathbb{P}}_t \!\left[ m_{t+1}\, P_{t+1}^i \right] 
&amp;amp;= \mathbb{E}^{\mathbb{P}}_t \!\left[ \frac{d\mathbb{Q}}{d\mathbb{P}} \; \mathbb{E}^{\mathbb{P}}[m_{t+1}] \; P_{t+1}^i \right] \\[1em]
&amp;amp;= \mathbb{E}^{\mathbb{P}}_t \!\left[ \frac{d\mathbb{Q}}{d\mathbb{P}} \, P_{t+1}^i \right] \, \mathbb{E}^{\mathbb{P}}[m_{t+1}] \\[1em]
&amp;amp;= \mathbb{E}^{\mathbb{Q}}_t \!\left[ P_{t+1}^i \right] \, \mathbb{E}^{\mathbb{P}}[m_{t+1}].
\end{aligned}\]

&lt;p&gt;Using equation (1) we can apply it to the risk free asset such that wih return $e^{r}$:&lt;/p&gt;

\[\mathbb{E}^{\mathbb{P}}[m_{t+1}] = e^{-r}\]

&lt;p&gt;We end up with :&lt;/p&gt;

\[P_t = e^{-r} \mathbb{E}^{\mathbb{Q}}_t \left[ P_{t+1}^i \right]\]

&lt;p&gt;If we use $e^{rt} P_t$ as the discounted price, we get&lt;/p&gt;

\[e^{-rt} P_t^i = e^{-r(t+1)} \mathbb{E}^{\mathbb{Q}}_t \left[ P_{t+1}^i \right]\]

\[e^{-rt} P_t^i = \mathbb{E}^{\mathbb{Q}}_t \left[ e^{-r(t+1)} P_{t+1}^i \right]\]

&lt;p&gt;Thus if we note $\tilde{P}_t^i = e^{rt} P_t^i$ we have :&lt;/p&gt;

\[\mathbb{E}^{\mathbb{Q}}_t[ \tilde{P}_{t+1}^i] = \tilde{P}_t^i\]

&lt;p&gt;In this new measure $ \mathbb{Q} $, the discounted price of any asset is a &lt;strong&gt;martingale&lt;/strong&gt;, meaning its expected future value (adjusted for time) equals its current price.&lt;/p&gt;

&lt;p&gt;This is the mathematical foundation of modern asset pricing and derivatives valuation: we &lt;strong&gt;price assets as if investors are risk-neutral&lt;/strong&gt;, using a change of measure justified by the SDF, even though in reality they are not.&lt;/p&gt;

&lt;h2 id=&quot;KeyDifferences&quot;&gt;Random Walk vs Martingale: Key Differences&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Feature&lt;/th&gt;
      &lt;th&gt;Random Walk&lt;/th&gt;
      &lt;th&gt;Martingale&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Definition&lt;/td&gt;
      &lt;td&gt;$X_{t+1} = X_t + \epsilon_{t+1}$, iid shocks&lt;/td&gt;
      &lt;td&gt;$\mathbb{E}[X_{t+1} \mid \mathcal{F}_t] = X_t$&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Distribution&lt;/td&gt;
      &lt;td&gt;Specific (often Gaussian)&lt;/td&gt;
      &lt;td&gt;Any distribution, as long as conditional expectation holds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Predictability&lt;/td&gt;
      &lt;td&gt;No trend, but variance accumulates&lt;/td&gt;
      &lt;td&gt;No conditional drift; more general&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Finance usage&lt;/td&gt;
      &lt;td&gt;Descriptive model of price series&lt;/td&gt;
      &lt;td&gt;Mathematical framework for pricing, based on no-arbitrage arguments&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;when-is-martingale-not-a-random-walk-&quot;&gt;When is Martingale not a Random Walk ?&lt;/h2&gt;

&lt;p&gt;The key difference between a random walk and a martingale process lies in the distributional assumptions. A random walk assumes i.i.d. (independent and identically distributed) increments, while a martingale only requires that the conditional expectation of tomorrow’s value equals today’s value.&lt;/p&gt;

&lt;p&gt;To see this distinction, consider the following stochastic process:&lt;/p&gt;

\[X_{t+1} = X_t + X_t\epsilon_{t+1}\]

&lt;p&gt;where $\epsilon_{t+1}$ is a zero-mean random shock.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;This process is a &lt;strong&gt;martingale&lt;/strong&gt;, because&lt;br /&gt;
\(\mathbb{E}[X_{t+1} \mid \mathcal{F}_t] = X_t.\)&lt;/li&gt;
  &lt;li&gt;But it is &lt;strong&gt;not a random walk&lt;/strong&gt;, since the increments depend on the current level $X_t$ rather than being i.i.d.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This example also highlights why &lt;strong&gt;log prices&lt;/strong&gt; are often modeled instead of raw prices. Taking logs, we get:&lt;/p&gt;

\[\log(X_{t+1}) = \log\!\big(X_t(1+\epsilon_{t+1})\big) 
= \log(X_t) + \log(1+\epsilon_{t+1}).\]

&lt;p&gt;Now the process $\log(X_t)$ evolves as a &lt;strong&gt;random walk with innovations $\log(1+\epsilon_{t+1})$&lt;/strong&gt;, which are i.i.d. under suitable conditions.&lt;/p&gt;

&lt;h3 id=&quot;python-illustration&quot;&gt;Python illustration&lt;/h3&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Simple martingale simulation
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# start at 0
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;252&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# steps are fair, zero expected change
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;choice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;  

&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Martingale-like Process&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Martingale Simulation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/RWvsM_fig_2.png&quot; alt=&quot;Martingale simulation example with Python&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;Conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Random walks and martingales may seem similar at first glance, but the distinction is subtle and important. Random walks describe how prices move step by step, while martingales capture a broader property of &lt;strong&gt;fair game&lt;/strong&gt; conditional expectations. Understanding both is fundamental to quantitative finance, stochastic modeling, and financial mathematics. To see a pratical use of random walk models and martingales properties to forecast volatility, check this &lt;a href=&quot;/BitcoinVolatility-2/&quot;&gt;previous post&lt;/a&gt; !&lt;/p&gt;

&lt;h2 id=&quot;FurtherReading&quot;&gt;Further Reading&lt;/h2&gt;

&lt;p&gt;To deepen your understanding of martingales, stochastic discount factors, and their role in asset pricing, consider exploring the following resources:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;John H. Cochrane – Asset Pricing&lt;/strong&gt;&lt;br /&gt;
A comprehensive and rigorous treatment of asset pricing using stochastic discount factors, risk-neutral valuation, and the martingale approach. Some free content is available on &lt;a href=&quot;https://www.johnhcochrane.com/&quot;&gt;Cochrane’s website&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Darrell Duffie – Dynamic Asset Pricing Theory&lt;/strong&gt;&lt;br /&gt;
A mathematically advanced reference focusing on continuous-time models and martingale techniques in finance.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Steven Shreve – Stochastic Calculus for Finance I &amp;amp; II&lt;/strong&gt;&lt;br /&gt;
Volume I introduces discrete-time models; Volume II covers continuous-time finance using Brownian motion and martingales. Great for building intuition and formal understanding.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Martin Baxter &amp;amp; Andrew Rennie – Financial Calculus&lt;/strong&gt;&lt;br /&gt;
A practical introduction to arbitrage pricing and martingale methods in continuous time.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Wikipedia articles&lt;/strong&gt;:&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Martingale_(probability_theory)&quot;&gt;Martingale (probability theory)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Stochastic_discount_factor&quot;&gt;Stochastic discount factor&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Radon%E2%80%93Nikodym_theorem&quot;&gt;Radon–Nikodym theorem&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These readings offer both the theoretical foundation and practical insights needed for modern quantitative finance.&lt;/p&gt;

</content>
    <category term="Statistics" /><category term="Quantitative Finance" />
  </entry>
  
  <entry>
    <title type="html">Bitcoin Volatility Estimation with the Parkinson Estimator in Python</title>
    <link href="https://quants.quest/BitcoinVolatility-3/" rel="alternate" type="text/html" />
    <id>https://quants.quest/BitcoinVolatility-3</id>
    <published>2024-09-27T00:00:00+00:00</published>
    <updated>2024-09-27T00:00:00+00:00</updated>
    <summary type="html">Learn how to estimate Bitcoin&apos;s volatility using the Parkinson estimator in Python with Binance data. Includes theory, implementation, and comparisons to classic volatility measures.</summary>
    <content type="html" xml:base="https://quants.quest/BitcoinVolatility-3/">&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of Contents&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#parkinson-range-method&quot;&gt;The Parkinson’s Range-Based Method&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#parkinson-volitility-on-bitcoin&quot;&gt;Implementation on Bitcoin’s Data&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#challenge-when-estimating-volatility&quot;&gt;Considerations for Practical Use&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#references-and-further-reading&quot;&gt;References and Further Reading&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;introduction&quot;&gt;The Parkinson Estimator for Bitcoin Volatility&lt;/h2&gt;

&lt;p&gt;In this third installment of our series on Bitcoin volatility, we delve into a new volatility estimator, this time based on High and Low data points. This approach not only leverages high and low price points but also offer more precise volatility estimations. To fetch the data, check out this &lt;a href=&quot;/DataBaseCreation/&quot;&gt;previous post&lt;/a&gt;, where we explored how to use the Binance API.&lt;/p&gt;

&lt;p&gt;Small recap of the previous articles of this serie :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/BitcoinVolatility-1/&quot;&gt;&lt;strong&gt;Part 1 article&lt;/strong&gt;&lt;/a&gt; introduced the basic concepts of volatility, focusing on historical volatility calculations using closing prices from Binance data and the EWMA estimator.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/BitcoinVolatility-2/&quot;&gt;&lt;strong&gt;Part 2 article&lt;/strong&gt;&lt;/a&gt; expanded on these concepts by examining the use of econometric model (GARCH) to modelize complex behaviours (ARCH effect).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These analyses provided a groundwork for understanding the complexities of Bitcoin’s price dynamics and set the stage for integrating more sophisticated statistical techniques.&lt;/p&gt;

&lt;p&gt;Building on our previous discussions, this article aims to &lt;strong&gt;Explore Alternative Data:&lt;/strong&gt; and &lt;strong&gt;Alternative Volatility Estimators&lt;/strong&gt; that utilize not the close (C) prices but the high (H), low (L).&lt;/p&gt;

&lt;p&gt;The estimator we’ll discuss is not my original creation; its roots trace back to Parkinson, who first introduced it to the community in 1980. Since the formal proof has been established over four decades ago, my aim here isn’t to rehash the theory but rather to provide a clear, step-by-step guide to its construction. This tutorial will walk you through the essential concepts, ensuring you gain a practical understanding of how this estimator works and how it can be implemented effectively.&lt;/p&gt;

&lt;p&gt;By the end of this post, you’ll gain a deeper understanding of how a volatility estimator can be constructed, making it a valuable guide for quantitative researchers.&lt;/p&gt;

&lt;h2 id=&quot;parkinson-range-method&quot;&gt;The Parkinson’s Range-Based Method&lt;/h2&gt;

&lt;p&gt;What steps should a quant researcher follow when searching for an estimator ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Objective:&lt;/strong&gt; Construct a volatility estimator based on High and Low observations&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modelling:&lt;/strong&gt; For this post, we will assume the &lt;strong&gt;asset price&lt;/strong&gt; ( P_t ) follows a geometric Brownian motion (I will conceive not being original here).&lt;/p&gt;

\[dP_t = \mu P_t \, dt + \sigma P_t \, dW_t\]

&lt;p&gt;where $ \mu $ is the drift, $ \sigma $ is the constant volatility, and $ W_t $ is a Wiener process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Intuition:&lt;/strong&gt; Our key assumption here is that the expected logarithmic range ($R$) of the asset should be proportional to its standard deviation.&lt;/p&gt;

\[R = \ln \left( \frac{\max_{0 \leq t \leq T} \ln P_t}{\min_{0 \leq t \leq T} \ln P_t}\right) = \ln \left( \frac{M_T}{m_T} \right)\]

&lt;p&gt;&lt;strong&gt;Methodology:&lt;/strong&gt; The standard approach to constructing an estimator typically involves identifying a random variable whose expected value is connected to the theoretical quantity we want to estimate. From there, we leverage the &lt;a href=&quot;https://en.wikipedia.org/wiki/Central_limit_theorem&quot;&gt;Central Limit Theorem&lt;/a&gt;:&lt;/p&gt;

\[\frac{1}{\sqrt{n}}\sum_{i=1}^{n}(X_i - \mu) \xrightarrow[]{d} N(0, \sigma^2)\]

&lt;p&gt;Where $ X_i $ are independent and identically distributed (i.i.d.) random variables, with $ E[X_i] = \mu $ and $ \text{Var}(X_i) = \sigma^2 $, and $ n $ is the sample size.&lt;/p&gt;

&lt;p&gt;The central limit theorem ensures that as $ n \to \infty $, the sum of the random variables converges in distribution to a normal distribution.&lt;/p&gt;

&lt;p&gt;Now that we have the variable $R$, whose expected value should be related to $ \sigma $, the next step is to formally prove this through some mathematical derivations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Chicken and the Knife:&lt;/strong&gt; As a former physics teacher of mine used to say about thermodynamics equations: now you have the knife in your hand, and the chicken is right in front of you. Time to get to work! There’s no simple trick to computing $ E\left[ R \right] $ in this case.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/chicken_and_the_knife.webp&quot; alt=&quot;figure 0&quot; width=&quot;500px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here, we’re working with an expectation, and as probabilists, we naturally express this as an integral. To move forward, we need the probability distribution of the range, which, luckily, can be derived from the joint distribution of the minimum and maximum values along the paths.&lt;/p&gt;

&lt;p&gt;In his 1951 paper, Feller outlines the necessary steps to compute this joint probability distribution. The key steps are as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Step 1: Express the joint distribution in terms of simpler events.&lt;/strong&gt;
The first idea is to express the probability that $ M_t $ and $ m_t $ are below certain levels, say $ M_t \leq a $ and $ m_t \geq b $. This is the probability that the process stays between $ b $ and $ a $ over time $ t $.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Step 2: Use reflection symmetry.&lt;/strong&gt;
A Wiener process has a useful symmetry property: If we reflect the path at any point (like a mirror), the reflected path is also a valid Wiener process. This symmetry can simplify the analysis of the maximum and minimum because what happens above zero is mirrored below.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Step 3: Break the problem into manageable parts.&lt;/strong&gt;
The joint probability of reaching a maximum $ M_t $ and a minimum $ m_t $ can be viewed as a combination of two probabilities:
    &lt;ol&gt;
      &lt;li&gt;The probability that the process doesn’t cross a certain boundary.&lt;/li&gt;
      &lt;li&gt;The probability that the process reaches a given level for the first time (like hitting a particular maximum or minimum).&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Step 4: Utilize known distributions.&lt;/strong&gt;
The distribution of the maximum $ M_t $ is known to follow a specific distribution (related to the normal distribution of the Wiener process). Similarly, the minimum can be handled by symmetry.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We then get the folowing cumulative probability distribution, taking the same notations as 1980 Parkinson’s article :&lt;/p&gt;

\[P(R \leq x) = \sum_{n=1}^{\infty} (-1)^{n+1} n \left\{ \text{Erfc} \left( \frac{(n+1)x}{\sqrt{2\sigma}} \right) - 2 \, \text{Erfc} \left( \frac{nx}{\sqrt{2\sigma}} \right) + \text{Erfc} \left( \frac{(n-1)x}{\sqrt{2\sigma}} \right) \right\}\]

&lt;p&gt;For clarity sake, we have here consider $ T = 1 $. Using this, Parkinson (1980) calculates (for $ p \geq 1 $):&lt;/p&gt;

&lt;p&gt;\(E(R^p) = \frac{4}{\sqrt{\pi}} \Gamma \left( \frac{p + 1}{2} \right) \left( 1 - \frac{4}{2^p} \right) \zeta (p - 1) 2\sigma^2
\tag{10}\)
where $ \Gamma(x) $ is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Gamma_function&quot;&gt;gamma function&lt;/a&gt; and $ \zeta(x) $ is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Riemann_zeta_function&quot;&gt;Riemann zeta function&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Particularly, for $ p = 2 $:&lt;/p&gt;

\[E(R^2) = 4 \ln(2) \sigma^2\]

&lt;p&gt;&lt;strong&gt;Creating the Estimator:&lt;/strong&gt; We have finally established the desired relationship, linking $ R $ and $ \sigma $. The final step is to apply the central limit theorem to create an estimator for $ \sigma $, considering we have multiple observations.&lt;/p&gt;

&lt;p&gt;Suppose we have $ n $ independent observations of the range, denoted by $ R_1, R_2, \dots, R_n $. Using the fact that $ E(R^2) = 4 \ln(2) \sigma^2 $, we can derive an unbiased estimator for $ \sigma^2 $ based on these observations.&lt;/p&gt;

&lt;p&gt;The estimator for $ \sigma^2 $ is:&lt;/p&gt;

\[\hat{\sigma}^2 = \frac{1}{n} \sum_{i=1}^{n} \frac{R_i^2}{4 \ln(2)} = \frac{1}{4 n \ln(2)} \sum_{i=1}^{n} \ln \left(\frac{H_i}{L_i}\right)\]

&lt;p&gt;By the central limit theorem, as the sample size $ n $ increases, the estimator $ \hat{\sigma}^2 $ converges to the true variance $ \sigma^2 $, and its distribution approaches normality. Let’s get moving now on a pratical implemention on Bitcoin data.&lt;/p&gt;

&lt;h2 id=&quot;parkinson-volitility-on-bitcoin&quot;&gt;Parkinson Volatility Estimator&lt;/h2&gt;

&lt;h3 id=&quot;binance-bitcoin-data-preparation&quot;&gt;Binance Bitcoin Data Preparation&lt;/h3&gt;

&lt;p&gt;As we’ve done in previous articles, we’ll follow a similar data preparation process here. For those needing a refresher, we previously explained how to fetch and store Binance data in an HDF5 file in &lt;a href=&quot;/DataBaseCreation/&quot;&gt;this post&lt;/a&gt;. It’s this dataset we will exploit here.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pandas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt; 
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt; 
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt; 

&lt;span class=&quot;n&quot;&gt;database_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data/crypto_database.h5&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_hdf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;database_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;BTCUSDT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Convert &apos;Open_Time&apos; to datetime if not already done
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reset_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_datetime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Set &apos;Open_Time&apos; as the index
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;close-to-close-volatility-estimator-for-bitcoin&quot;&gt;Close-to-Close Volatility Estimator for Bitcoin&lt;/h3&gt;

&lt;p&gt;To provide a meaningful comparison, we’ll calculate the &lt;strong&gt;Close-to-Close volatility estimator&lt;/strong&gt; over the same time frame as the Parkinson estimator (1 hour, or 60 data points).&lt;/p&gt;

&lt;p&gt;In line with Collin Bennett’s recommendations, we assume a zero-mean model for the returns. Therefore, instead of relying on Python’s built-in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.std()&lt;/code&gt; function, we’ll manually compute the volatility, excluding any mean adjustment. This approach provides a more accurate representation of volatility under the assumption that returns have a zero mean.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# We will compute returns with the last hour data 
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;classic_std&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;log_returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rolling&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;python-implementation-of-the-parkinson-volatility-estimator&quot;&gt;Python Implementation of the Parkinson Volatility Estimator&lt;/h3&gt;

&lt;p&gt;We then implement the &lt;strong&gt;Parkinson Volatility Estimator&lt;/strong&gt;, which uses the high-low range of prices to capture intraday volatility more effectively.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Compute the log range 
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;log_range&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;High&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Low&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Define a python function for the parkinson volatility 
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parkinson_std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sigma&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;R&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sigma&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Compute the parkinson standard deviation
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;parkinson_std&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;log_range&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parkinson_std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rolling&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;parkinson-vs-classic-volatility-in-bitcoin&quot;&gt;Parkinson vs Classic Volatility in Bitcoin&lt;/h3&gt;

&lt;p&gt;Now that we’ve computed the Parkinson volatility, let’s visually compare it with our classic close to close volatility estimator to better understand how they behave across different time periods.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Create a figure with a 1x2 grid layout
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subplots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Add main title and subtitle to the entire figure
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;suptitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&apos;Volatility Analysis&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;fontweight&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;bold&apos;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;s&quot;&gt;&apos;Comparison of the Parkinson Volatility and the Classic Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;center&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;italic&apos;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Adjust spacing between plots for better layout
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subplots_adjust&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.85&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wspace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Plot 1: Bitcoin price and Parkinson volatility on the left side
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;parkinson_std&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Parkinson Volatility (Rolling 60)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;#17becf&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Teal for Parkinson Volatility
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Parkinson Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Parkinson Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;upper left&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Plot 2: Classic standard deviation and percentage difference on the right side
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;classic_std&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Classic Volatility (Rolling 60)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;#ff7f0e&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Orange for Classic Volatility
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Classic Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Classic Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;upper left&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Rotate x-axis labels for both subplots for better readability
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;axes&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_xticklabels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rotation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;45&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;right&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Adjust layout to prevent overlap and enhance readability
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tight_layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Leave space at the top for titles
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Show the plot
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/BitcoinVolatility-3-figure-1.png&quot; alt=&quot;figure 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Great! It appears that both estimators show fairly similar behavior, which makes sense given that both are designed to be consistent measures of volatility. However, there are bound to be some differences between them. To better understand these variations, let’s calculate the percentage difference between the two estimators:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Calculate percentage difference between Parkinson and realized volatility
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;volatility_diff&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;parkinson_std&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;close_close_std&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;close_close_std&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s focus on specific time periods to examine the differences between the two estimators more closely, as visualizing all the data at once would likely result in a cluttered and unclear display.&lt;/p&gt;

&lt;h4 id=&quot;parkinson-volatility-during-bitcoins-2020-covid-19-crash&quot;&gt;Parkinson Volatility During Bitcoin’s 2020 COVID-19 Crash&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Background:&lt;/strong&gt; In March 2020, Bitcoin’s price plummeted by over 50% within a week amidst the global financial turmoil caused by the COVID-19 pandemic.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Define the time range for the 2020 COVID-19 crash
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;2020-02-01&apos;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;2020-05-01&apos;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Slice the DataFrame for this time period
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df_2020_crash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Create a figure with a 2x2 grid layout
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subplots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Add main title and subtitle to the entire figure
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;suptitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Bitcoin Price and Volatility Analysis during 2020 COVID-19 Crash&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontweight&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;bold&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.93&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;Comparison of Parkinson Volatility, Classic Volatility, and Price Evolution&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
         &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;center&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;italic&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Adjust spacing between plots for better layout
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subplots_adjust&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.85&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wspace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hspace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Plot 1: Bitcoin price (close) evolution during 2020 COVID-19 crash
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df_2020_crash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Close&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;BTC Price&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;#1f77b4&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Deep Blue
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Bitcoin Price (2020 COVID-19 Crash)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;BTC Price (USD)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Plot 2: Parkinson volatility during 2020 COVID-19 crash
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df_2020_crash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;parkinson_std&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Parkinson Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;#17becf&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Teal
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Bitcoin Parkinson Volatility (2020 COVID-19 Crash)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Parkinson Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Plot 3: Classic standard deviation during 2020 COVID-19 crash
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df_2020_crash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;classic_std&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Classic Std (Rolling 120)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;#ff7f0e&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Orange
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Bitcoin Classic Volatility (Rolling Std, 2020 COVID-19 Crash)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Classic Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Plot 4: Percentage difference between Parkinson and Classic volatility
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df_2020_crash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;volatility_diff&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;% Difference&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;#2ca02c&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Green
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df_2020_crash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;volatility_diff&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rolling&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;7-Day Rolling Avg&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linestyle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;--&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;#d62728&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Red
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Percentage Difference Between Parkinson and Classic Volatility (2020 COVID-19 Crash)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;% Difference&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Adjust layout to prevent overlap and enhance readability
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tight_layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Leave space at the top for titles
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Show the plot
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/BitcoinVolatility-3-figure-2.png&quot; alt=&quot;figure 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;From the visual analysis of Bitcoin’s price and volatility during the 2020 COVID-19 crash, a few key observations emerge:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Price Trend&lt;/strong&gt;: The Bitcoin price experienced significant fluctuations, with a steep decline in early March followed by a rapid recovery in April. This reflects the general market instability during the early phases of the pandemic.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Parkinson Volatility&lt;/strong&gt;: The Parkinson volatility spikes in March, correlating with the sharp price drop, indicating heightened intraday volatility during that period. This volatility seems to stabilize but remains elevated as the price recovers.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Classic Volatility&lt;/strong&gt;: The classic standard deviation, representing the close-to-close volatility, mirrors the pattern seen in the Parkinson volatility, with spikes during March’s market turbulence. However, it smooths out more in the later periods.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Percentage Difference&lt;/strong&gt;: The percentage difference between Parkinson and classic volatility shows consistent fluctuations. A notable feature is the elevated percentage difference in mid-March, suggesting that the intraday high-low ranges (Parkinson) captured more volatility compared to the closing prices during the market’s most turbulent moments.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Overall, this period reflects heightened volatility due to the COVID-19 market shock, with significant short-term fluctuations and a high divergence between intraday and closing-price volatility.&lt;/p&gt;

&lt;h4 id=&quot;parkinson-volatility-during-bitcoins-2024-ath&quot;&gt;Parkinson Volatility During Bitcoin’s 2024 ATH&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Background:&lt;/strong&gt; In 2024, Bitcoin surged to a new all-time high, driven by increasing institutional adoption, macroeconomic instability, and growing recognition of Bitcoin as a hedge against inflation. The price rise was fueled by heightened demand for alternative assets, pushing Bitcoin beyond previous record levels set in 2021.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Define the time range for the 2024 ATH
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;2024-01-01&apos;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;2024-04-01&apos;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Slice the DataFrame for this time period
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df_2024_ath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Create a figure with a 2x2 grid layout
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subplots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Add main title and subtitle to the entire figure
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;suptitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Bitcoin Price and Volatility Analysis during 2024 ATH&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontweight&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;bold&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.93&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;Comparison of Parkinson Volatility, Classic Volatility, and Price Evolution&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
         &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;center&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;italic&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Adjust spacing between plots for better layout
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subplots_adjust&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.85&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wspace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hspace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Plot 1: Bitcoin price (close) evolution during 2024 ATH
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df_2024_ath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Close&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;BTC Price&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;#1f77b4&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Deep Blue
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Bitcoin Price (2024 ATH)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;BTC Price (USD)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Plot 2: Parkinson volatility during 2024 ATH
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df_2024_ath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;parkinson_std&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Parkinson Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;#17becf&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Teal
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Bitcoin Parkinson Volatility (2024 ATH)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Parkinson Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Plot 3: Classic standard deviation during 2024 ATH
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df_2024_ath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;classic_std&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Classic Std (Rolling 120)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;#ff7f0e&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Orange
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Bitcoin Classic Volatility (Rolling Std, 2024 ATH)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Classic Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Plot 4: Percentage difference between Parkinson and Classic volatility
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df_2024_ath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;volatility_diff&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;% Difference&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;#2ca02c&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Green
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df_2024_ath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;volatility_diff&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rolling&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;7-Day Rolling Avg&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linestyle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;--&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;#d62728&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Red
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Percentage Difference Between Parkinson and Classic Volatility (2024 ATH)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fontsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;% Difference&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Adjust layout to prevent overlap and enhance readability
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tight_layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Leave space at the top for titles
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Show the plot
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/BitcoinVolatility-3-figure-3.png&quot; alt=&quot;figure 3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In the analysis of Bitcoin’s price and volatility during its 2024 All-Time High (ATH), several insights can be observed:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Price Trend&lt;/strong&gt;: Bitcoin’s price experienced a significant upward trend leading to its new all-time high, surpassing $70,000 in March 2024. This rally was marked by steady growth throughout January and February, followed by higher volatility as the price approached its peak. The price stabilized but remained elevated after the peak.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Parkinson Volatility&lt;/strong&gt;: The Parkinson volatility, which measures intraday high-low fluctuations, spiked during moments of rapid price movement, particularly as Bitcoin approached its ATH in mid-March 2024. This indicates increased intraday volatility during periods of strong upward price momentum.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Classic Volatility&lt;/strong&gt;: The classic volatility (rolling standard deviation of closing prices) follows a similar pattern to Parkinson volatility but appears smoother. It shows volatility peaks aligned with the rapid price increases but captures less extreme intraday swings.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Percentage Difference&lt;/strong&gt;: The percentage difference between Parkinson and classic volatility fluctuates throughout the period, with notable spikes in volatility divergence as Bitcoin approaches its ATH. The rolling average of the percentage difference shows that intraday volatility (Parkinson) tended to outpace close-to-close volatility (classic) during periods of intense price movement, with the difference narrowing slightly after the ATH.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Overall, this analysis highlights the heightened volatility in both intraday and closing price movements as Bitcoin surged to its 2024 ATH, with Parkinson volatility capturing sharper intraday price changes compared to the classic volatility measure.&lt;/p&gt;

&lt;h2 id=&quot;challenge-when-estimating-volatility&quot;&gt;Practical Considerations when working on Volatility&lt;/h2&gt;

&lt;p&gt;A critical decision when implementing a volatility model is selecting the appropriate rolling window length for historical volatility estimation. As Collin Bennett discusses in &lt;em&gt;Trading Volatility&lt;/em&gt;, this choice is far from trivial and carries important implications for the accuracy of the model. Specifically, the number of data points used in the rolling window directly impacts the variance of the estimator: a longer window reduces variance but assumes that the underlying market conditions, particularly volatility, remain constant over a longer period.&lt;/p&gt;

&lt;p&gt;This assumption can be problematic in practice. In our case, for example, using a rolling window that spans several days or weeks assumes that volatility is relatively stable over that period. However, in fast-moving or highly volatile markets, such an assumption may be hazardous. Short-term market shocks or trends may significantly affect volatility, making a longer window less responsive to sudden changes.&lt;/p&gt;

&lt;p&gt;Collin Bennett emphasizes this challenge when he states:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Choosing the historical volatility number of days is not a trivial choice… while an identical duration historical volatility is useful to arrive at a realistic minimum and maximum value over a long period of time, it is not always the best period of time to determine the fair level of long-dated implieds… volatility mean reverts over a period of c8 months” (&lt;em&gt;Trading Volatility&lt;/em&gt;, Bennett).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In essence, while using longer windows may reduce estimator variance, it risks incorporating outdated volatility caused by past events, diminishing the relevance of the estimate for current market conditions. As Bennett suggests, aligning the historical window with implied volatility durations (e.g., 21 trading days for one-month implied volatility) can be a practical approach but should be adjusted to account for events that may no longer impact market conditions.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In this post, we explored the Parkinson estimator as an alternative method for estimating Bitcoin’s volatility, leveraging high and low data points to capture more precise intraday fluctuations. We compared it with the classic close-to-close estimator and observed how the Parkinson estimator provides a better representation of volatility during sharp market movements, such as Bitcoin’s 2020 COVID-19 crash and its 2024 all-time high. While both methods have their merits, the choice of estimator ultimately depends on the nature of the data and the specific trading strategy.&lt;/p&gt;

&lt;p&gt;Stay tuned for the next post, where we continue our journey into volatility modeling, exploring more advanced estimators and their practical applications in trading!&lt;/p&gt;

&lt;p&gt;I’d love to hear your thoughts! Share your feedback, questions, or suggestions for future topics in the comments below.&lt;/p&gt;

&lt;h2 id=&quot;references-and-further-reading&quot;&gt;References and Further Reading&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Parkinson, M. (1980), &lt;a href=&quot;https://www.researchgate.net/publication/24102749_The_Extreme_Value_Method_for_Estimating_the_Variance_of_the_Rate_of_Return&quot;&gt;Estimating the Variance of the Rate of Return for a Security&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Feller, W. (1951), &lt;a href=&quot;https://www.semanticscholar.org/paper/The-Asymptotic-Distribution-of-the-Range-of-Sums-of-Feller/55b997d9033e8a601965102c012705588e9eb421&quot;&gt;The Asymptotic Distribution of the Range of Sums of Independent Random Variables&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mmquant.net/wp-content/uploads/2016/09/range_based_estimators.pdf&quot;&gt;Great article&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Binance API Documentation: &lt;a href=&quot;https://github.com/binance/binance-spot-api-docs&quot;&gt;Binance API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to explore these resources to deepen your understanding.&lt;/p&gt;

</content>
    <category term="Statistics" /><category term="Quantitative Finance" /><category term="Algo Trading" /><category term="Python" />
  </entry>
  
  <entry>
    <title type="html">Estimating Bitcoin&apos;s Volatility using a GARCH Model</title>
    <link href="https://quants.quest/BitcoinVolatility-2/" rel="alternate" type="text/html" />
    <id>https://quants.quest/BitcoinVolatility-2</id>
    <published>2024-09-23T00:00:00+00:00</published>
    <updated>2024-09-23T00:00:00+00:00</updated>
    <summary type="html">Learn how to estimate and forecast Bitcoin volatility using GARCH models in Python with Binance data.</summary>
    <content type="html" xml:base="https://quants.quest/BitcoinVolatility-2/">&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of Contents&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#motivations&quot;&gt;Motivations&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-garch-model&quot;&gt;The GARCH Model&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#preparing-the-data&quot;&gt;Preparing Binance Bitcoin Data for GARCH in Python&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#testing-for-arch-effects&quot;&gt;Testing Bitcoin Returns for ARCH Effects&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#model-selection&quot;&gt;Selecting a GARCH Model for Bitcoin&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#interpreting-the-garch-parameters&quot;&gt;Interpreting the GARCH Parameters&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#goodness-of-fit-check&quot;&gt;Goodness-of-fit Check&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#estimating-and-forecasting-volatility&quot;&gt;Estimating and Forecasting Volatility&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;In our &lt;a href=&quot;/BitcoinVolatility-1/&quot;&gt;last post&lt;/a&gt;, we discussed the Exponentially Weighted Moving Average (EWMA) method for estimating Bitcoin’s volatility. We used historical data from Binance and implemented the EWMA model to track volatility. To fetch the data, check out this &lt;a href=&quot;/DataBaseCreation/&quot;&gt;previous post&lt;/a&gt;, where we explored how to use the Binance API. This time we’ll take it a step further by introducing the &lt;strong&gt;GARCH&lt;/strong&gt; model, a more sophisticated method used to estimate but also forecast volatility. Let’s dive in!&lt;/p&gt;

&lt;h2 id=&quot;motivations&quot;&gt;Motivations&lt;/h2&gt;

&lt;p&gt;When modeling financial volatility, it’s crucial to choose a model that captures the unique characteristics of asset price returns without unnecessary complexity. While simple models like the random walk with gaussian increments might seem sufficient for short-term forecasts, they miss important features of financial time series.&lt;/p&gt;

&lt;p&gt;Let’s consider the random walk model :&lt;/p&gt;

\[p_{t+1} = p_t + \epsilon_t, \quad \epsilon_t \sim \mathcal{N}(0, \sigma^2)\]

&lt;p&gt;Then the following empirical properties cannot be modelized :&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Volatility Clustering&lt;/strong&gt; : One of the most well-documented phenomena in financial markets. This refers to the empirical observation that large price changes tend to be followed by large price changes, and small changes tend to be followed by small changes, regardless of the direction of the price movement.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Heavy-Tailed Distributions&lt;/strong&gt; : Another well-known stylized fact about financial returns. Extreme events (large price changes) happen more often than a normal distribution would predict. Simple volatility models that assume normality tend to underestimate the likelihood of these extreme events.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From a mathematical standpoint:&lt;/p&gt;

\[\text{Cov}(\epsilon_t^2, \epsilon_{t+k}^2) &amp;gt; 0 \quad \text{for small } k\]

\[\text{Kurt}(\epsilon_t) = \frac{\mathbb{E}[(\epsilon_t - \mu)^4]}{\sigma^4} &amp;gt; 3\]

&lt;p&gt;For any financial time series exhibiting these characteristics (volatility clustering and heavy tails) using a more sophisticated model becomes necessary. Fortunately, we can identify these properties through rigorous statistical tests :&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Autocorrelation Tests&lt;/strong&gt;: We can apply tests like the &lt;a href=&quot;https://en.wikipedia.org/wiki/Ljung%E2%80%93Box_test&quot;&gt;&lt;strong&gt;Ljung-Box Q-test&lt;/strong&gt;&lt;/a&gt; on the squared residuals $\epsilon_t^2$ to detect volatility clustering.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Kurtosis Test&lt;/strong&gt;: We can perform a &lt;a href=&quot;https://en.wikipedia.org/wiki/Jarque%E2%80%93Bera_test&quot;&gt;&lt;strong&gt;Jarque-Bera test&lt;/strong&gt;&lt;/a&gt; to check whether the distribution of the residuals significantly deviates from normality.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Moreover we also have the GARCH model, which is specifically designed to capture and replicate such behaviors. When applied, the GARCH model accounts for these empirical features, allowing the time series to exhibit the volatility clustering and non-normal distributions that are often observed in financial markets. But enough teasing and let’s explain it !&lt;/p&gt;

&lt;h2 id=&quot;the-garch-model&quot;&gt;The GARCH Model&lt;/h2&gt;

&lt;h3 id=&quot;what-is-a-garch-model&quot;&gt;What is a GARCH Model?&lt;/h3&gt;

&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Autoregressive_conditional_heteroskedasticity&quot;&gt;&lt;strong&gt;GARCH&lt;/strong&gt;&lt;/a&gt; (Generalized Autoregressive Conditional Heteroskedasticity) model was developped by &lt;a href=&quot;https://public.econ.duke.edu/~boller/Published_Papers/joe_86.pdf&quot;&gt;Tim Bollerslev&lt;/a&gt; and is a popular choice for financial volatility modeling, especially in markets where volatility tends to cluster over time. Let’s dive in.&lt;/p&gt;

&lt;p&gt;We modelize the log returns with :&lt;/p&gt;

\[r_t = \log(p_t) - \log(p_{t-1}) \quad \text{where} \quad r_t \sim \mathcal{N}(0, \sigma_t^2)\]

&lt;p&gt;Here, $\sigma_t^2$ is the time-varying volatility, which is gonna be modeled by the GARCH model. A &lt;strong&gt;GARCH&lt;/strong&gt; model need two parameters for it’s definition : p and q. It considers a combination of &lt;strong&gt;p&lt;/strong&gt; lagged variances (past periods’ volatility) and &lt;strong&gt;q&lt;/strong&gt; lagged squared returns (recent price changes), giving it the flexibility to model volatility with a deeper memory. The general form of the &lt;strong&gt;GARCH(p, q)&lt;/strong&gt; model is given by:&lt;/p&gt;

\[\sigma_t^2 = \omega + \sum_{i=1}^{q} \alpha_i \cdot r_{t-i}^2 + \sum_{j=1}^{p} \beta_j \cdot \sigma_{t-j}^2\]

&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;$\sigma_t^2$ is the current variance estimate (volatility squared),&lt;/li&gt;
  &lt;li&gt;$\omega$ represents the long-term variance (baseline level of volatility),&lt;/li&gt;
  &lt;li&gt;$\alpha_i$ weights the impact of past squared returns $(r_{t-i}^2)$, capturing how recent market shocks influence volatility,&lt;/li&gt;
  &lt;li&gt;$\beta_j$ weights the impact of past variances $(\sigma_{t-j}^2)$, reflecting how long-term volatility persists over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By adjusting the &lt;strong&gt;p&lt;/strong&gt; and &lt;strong&gt;q&lt;/strong&gt; parameters, the &lt;strong&gt;GARCH(p, q)&lt;/strong&gt; model becomes highly versatile. It can capture both &lt;strong&gt;volatility clustering&lt;/strong&gt; (the tendency for large changes to follow large changes) and &lt;strong&gt;mean reversion&lt;/strong&gt; (volatility eventually returning to a long-term average), which are essential characteristics in financial markets, especially in assets with erratic price movements like cryptocurrencies.&lt;/p&gt;

&lt;h3 id=&quot;why-use-a-garch-model-here&quot;&gt;Why Use a GARCH Model Here?&lt;/h3&gt;

&lt;p&gt;The decision to make a blog post about using &lt;strong&gt;GARCH model&lt;/strong&gt; for estimating Bitcoin’s volatility stems from both academic motivations and empirical necessities. Fitting a GARCH model is not just an exercise in financial theory, but is also one let’s be honnest here.&lt;/p&gt;

&lt;p&gt;But the model’s ability to incorporate past variances and shocks into future volatility estimates makes it a compelling choice for researchers and practitioners alike. Academically, it’s exciting to explore how well the GARCH model fits different time series data, especially in markets as volatile as cryptocurrencies, where price swings happen frequently.&lt;/p&gt;

&lt;p&gt;In financial time series like Bitcoin’s returns, there are well-documented &lt;strong&gt;ARCH effects&lt;/strong&gt;. Volatility changes over time and exhibits clustering. This means simple models that assume constant volatility will fail to adequately describe the data. Moreover, it seems legit to assume Bitcoin’s return distribution exhibits &lt;strong&gt;fat tails&lt;/strong&gt;, meaning extreme price changes occur more frequently than predicted by a normal distribution. This heavy-tailed behavior is another reason to use a GARCH model.&lt;/p&gt;

&lt;h2 id=&quot;preparing-the-data&quot;&gt;Preparing the Data&lt;/h2&gt;

&lt;p&gt;Before we fit a GARCH model, let’s load and clean our data, just like we did in the &lt;a href=&quot;/BitcoinVolatility-1/&quot;&gt;previous post&lt;/a&gt; with EWMA. We’ll again use the Bitcoin data we stored in HDF5 format and ensure the dataset is free of missing values. Because we are gonna use plenty of statistical test, we are gonna have to tackle some hardware limitations. For this modelling we will work with 3 months historic and keep one months for out of sample testing.&lt;/p&gt;

&lt;h3 id=&quot;loading-data-from-hdf5&quot;&gt;Loading Data from HDF5&lt;/h3&gt;

&lt;p&gt;First, let’s load the Bitcoin data we previously stored in our HDF5 file.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pandas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Define the date range 
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;2019-01-01&apos;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;2019-05-01&apos;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Load the data from the HDF5 file
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_hdf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;data/crypto_database.h5&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;BTCUSDT&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;index &amp;gt;= &apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos; and index &amp;lt;= &apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will give us access to the Bitcoin candlestick data with 1-minute granularity.&lt;/p&gt;

&lt;h3 id=&quot;data-cleaning-and-preprocessing&quot;&gt;Data Cleaning and Preprocessing&lt;/h3&gt;

&lt;p&gt;Ensuring data quality is paramount. We’ll check for missing values and ensure that the data types are appropriate.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Check for missing values
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isnull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Convert &apos;Open_Time&apos; to datetime if not already done
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reset_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_datetime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Set &apos;Open_Time&apos; as the index
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;taking-a-look-at-the-data&quot;&gt;Taking a look at the data&lt;/h3&gt;

&lt;p&gt;Let’s ensure we have good quality data by plotting the evolution of the Bitcoin Price.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Plot the log returns
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Close&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Bitcoin Price&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;BTC USDT&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/BitcoinVolatility-2-figure-1.png&quot; alt=&quot;Bitcoin price chart in Python&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;calculating-log-returns&quot;&gt;Calculating Log Returns&lt;/h3&gt;

&lt;p&gt;Let’s calculate here again the log returns using the ‘Close’ price.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Calculate log returns
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;log_returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Close&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Close&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Drop the NaN value created by the shift
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dropna&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;log_returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, let’s visualize the log returns to get a sense of their behavior.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Plot the log returns
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;log_returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Bitcoin Log Returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Log Return&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/BitcoinVolatility-2-figure-2.png&quot; alt=&quot;Bitcoin log price chart in Python&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;testing-for-arch-effects&quot;&gt;Testing for ARCH Effects&lt;/h2&gt;

&lt;p&gt;In financial time series, it’s crucial to test for &lt;strong&gt;ARCH effects&lt;/strong&gt; (Autoregressive Conditional Heteroskedasticity), which means that the volatility of the series changes over time and is not constant. If ARCH effects are present, we can use models like &lt;strong&gt;GARCH&lt;/strong&gt; to capture the volatility dynamics. For the folowing statistical tests, we will as an example a 3 months period, keeping the last month as an out of sample dataset.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;split_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_datetime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2019-04-01&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;training_data_mask&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;split_date&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;training_data_mask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;log_returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;stationarity-test&quot;&gt;Stationarity Test&lt;/h3&gt;

&lt;p&gt;Before testing for ARCH effects, we must first check if the series is &lt;strong&gt;stationary&lt;/strong&gt;. This is indeed a required features to fit a GARCH model on the serie. We typically can use the &lt;a href=&quot;https://en.wikipedia.org/wiki/Augmented_Dickey%E2%80%93Fuller_test&quot;&gt;&lt;strong&gt;Augmented Dickey-Fuller (ADF) test&lt;/strong&gt;&lt;/a&gt;. The null hypothesis of the ADF test is that the series has a unit root, i.e., it is non-stationary.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pandas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;statsmodels.tsa.stattools&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adfuller&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Assuming &apos;returns&apos; is a Pandas Series of your financial returns
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adfuller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;ADF Statistic: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;p-value: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ADF Statistic: &lt;span class=&quot;nt&quot;&gt;-53&lt;/span&gt;.002111501058444
p-value: 0.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;p-value&lt;/strong&gt; is below 0.05, we reject the null hypothesis, implying that the series is stationary.&lt;/p&gt;

&lt;h3 id=&quot;autocorrelation-test&quot;&gt;Autocorrelation Test&lt;/h3&gt;

&lt;p&gt;Once stationarity is confirmed, we check for autocorrelation in the &lt;strong&gt;squared returns&lt;/strong&gt;. The presence of autocorrelation in squared returns indicates volatility clustering, a key sign of ARCH effects.&lt;/p&gt;

&lt;p&gt;To test for autocorrelation, we can use the &lt;strong&gt;Ljung-Box Q-test&lt;/strong&gt;. This test checks for autocorrelation at multiple lags.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;statsmodels.stats.diagnostic&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;acorr_ljungbox&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Check autocorrelation in squared returns
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ljung_box_test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;acorr_ljungbox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;return_df&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ljung_box_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;         lb_stat  lb_pvalue
10  34331.948673        0.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A significant p-value (below 0.05) for the Ljung-Box test means that there is significant autocorrelation in the squared returns, suggesting the presence of ARCH effects.&lt;/p&gt;

&lt;h3 id=&quot;normality-test&quot;&gt;Normality Test&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Jarque-Bera test&lt;/strong&gt; assesses whether the skewness and kurtosis of the series significantly deviate from those of a normal distribution. The null hypothesis is that the data follows a normal distribution.&lt;/p&gt;

&lt;p&gt;The test checks both &lt;strong&gt;skewness&lt;/strong&gt; and &lt;strong&gt;kurtosis&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Skewness&lt;/strong&gt; indicates asymmetry in the distribution.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Kurtosis&lt;/strong&gt; measures the tail heaviness of the distribution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A high Jarque-Bera test statistic suggests that the series is not normally distributed, which is often the case with financial returns, where we observe fat tails and non-symmetric behavior.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scipy.stats&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jarque_bera&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Perform Jarque-Bera test on returns
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jb_test_stat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jb_p_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jarque_bera&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Jarque-Bera Test Statistic: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jb_test_stat&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;P-value: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jb_p_value&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Jarque-Bera Test Statistic: 85728124.76566969
P-value: 0.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A &lt;strong&gt;p-value&lt;/strong&gt; lower than 0.05 indicates that we reject the null hypothesis, implying that the returns do not follow a normal distribution. This further strengthens the case for using models like GARCH, which can handle non-normal characteristics such as fat tails and volatility clustering.&lt;/p&gt;

&lt;h2 id=&quot;model-selection&quot;&gt;Model Selection&lt;/h2&gt;

&lt;p&gt;We now have to select the p (the lag of past volatilities) and q (the lag of past squared returns) orders of our GARCH model. Goal here is thus to find the configuration that best fits the data. To do this, we’ll estimate multiple models by varying the parameters p and q in the GARCH model, ranging from simple to more complex configurations, and compare their AIC and BIC values. The model with the &lt;strong&gt;lowest &lt;a href=&quot;https://en.wikipedia.org/wiki/Akaike_information_criterion&quot;&gt;Akaike Information Criterion&lt;/a&gt; (AIC)&lt;/strong&gt; is generally favored when focusing on model fit, while the &lt;strong&gt;lowest &lt;a href=&quot;https://en.wikipedia.org/wiki/Bayesian_information_criterion&quot;&gt;Bayesian Information Criterion&lt;/a&gt; (BIC)&lt;/strong&gt; is preferred when penalizing more complex models to avoid overfitting.&lt;/p&gt;

&lt;p&gt;Some pratical considerations now :&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;We’ll use Python’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arch&lt;/code&gt; package to fit the GARCH model.&lt;/li&gt;
  &lt;li&gt;We’ll apply a &lt;strong&gt;scaling factor&lt;/strong&gt; of 1440 to the log returns.&lt;/li&gt;
  &lt;li&gt;We’ll we used a &lt;strong&gt;zero mean&lt;/strong&gt; assumption for the log returns.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;why-scale-the-data-&quot;&gt;Why scale the data ?&lt;/h3&gt;

&lt;p&gt;This is necessary because GARCH models tend to perform better when the input data is scaled to more manageable levels, especially with high-frequency data like minute-by-minute returns. Without scaling, the small magnitude of log returns can lead to numerical instability in the estimation process. Scaling helps to improve the model’s convergence and interpretability of the parameter estimates. Here we choose to multiply the returns by the number of minutes in the day : 1440.&lt;/p&gt;

&lt;h3 id=&quot;why-assume-a-zero-drift-&quot;&gt;Why assume a zero drift ?&lt;/h3&gt;

&lt;p&gt;The argument I will give here was presented by Collin Bennett in his book &lt;em&gt;Trading Volatility&lt;/em&gt;. Bennett explains that when calculating volatility, it is often &lt;strong&gt;best to assume zero drift&lt;/strong&gt;. The calculation for standard deviation measures the deviation from the average log return (drift), which must be estimated from the sample. This estimation can lead to misleading volatility calculations if the sample period includes unusually high or negative returns.&lt;/p&gt;

&lt;p&gt;For example, if a stock rises by 10% every day for ten days, the standard deviation would be zero because there is no deviation from the 10% average return. However, such trends are unrealistic over the long term, and using the sample log return as the expected future return can distort the volatility estimate. By assuming a &lt;strong&gt;zero mean&lt;/strong&gt; or drift, we prevent the volatility calculation from being influenced by extreme sample returns. In theory, over the long term, the expected return should be close to zero, as the forward price of an asset should reflect this assumption. This is why volatility calculations are typically more accurate when assuming &lt;strong&gt;zero drift&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;results&quot;&gt;Results&lt;/h3&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;arch&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arch_model&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;scaling_factor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# We get daily returns
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min_bic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1e10&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;selected_orders&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# GARCH(p,q) model
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arch_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;log_returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scaling_factor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
            &lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Zero&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
            &lt;span class=&quot;n&quot;&gt;vol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;GARCH&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
            &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;off&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last_obs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;GARCH(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;) AIC: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aic&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;, BIC: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bic&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;min_bic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;min_bic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bic&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;selected_orders&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;selected_orders&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Selected model with BIC : p=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; and q=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GARCH&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1,0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; AIC: 269793.01931055624, BIC: 269812.558147921
GARCH&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1,1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; AIC: 245265.1323021801, BIC: 245294.44055822722
GARCH&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1,2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; AIC: 244480.07736779848, BIC: 244519.15504252794
GARCH&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1,3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; AIC: 244168.23045229167, BIC: 244217.0775457035
GARCH&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2,0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; AIC: 260475.38690308636, BIC: 260504.69515913347
GARCH&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2,1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; AIC: 245268.00954894855, BIC: 245307.087223678
GARCH&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2,2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; AIC: 244482.07737045927, BIC: 244530.9244638711
GARCH&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2,3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; AIC: 244170.230456519, BIC: 244228.8469686132
GARCH&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3,0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; AIC: 255222.99234444185, BIC: 255262.0700191713
GARCH&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3,1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; AIC: 245269.1326656593, BIC: 245317.97975907114
GARCH&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3,2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; AIC: 244484.07805419483, BIC: 244542.69456628902
GARCH&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3,3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; AIC: 244172.23049541027, BIC: 244240.61642618684
Selected model with BIC : &lt;span class=&quot;nv&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 and &lt;span class=&quot;nv&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After evaluating multiple GARCH(p, q) models, we first select the &lt;strong&gt;GARCH(1, 3)&lt;/strong&gt; model based on both information criterions. Let’s take a look at the estimated parameters then :&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# GARCH(1, 3) model
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arch_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;log_returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scaling_factor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Zero&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;GARCH&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last_obs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;off&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                       Zero Mean - GARCH Model Results                        
&lt;span class=&quot;o&quot;&gt;==============================================================================&lt;/span&gt;
Dep. Variable:            log_returns   R-squared:                       0.000
Mean Model:                 Zero Mean   Adj. R-squared:                  0.000
Vol Model:                      GARCH   Log-Likelihood:               &lt;span class=&quot;nt&quot;&gt;-122079&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
Distribution:                  Normal   AIC:                           244168.
Method:            Maximum Likelihood   BIC:                           244217.
                                        No. Observations:               129239
Date:                Thu, Sep 26 2024   Df Residuals:                   129239
Time:                        10:34:30   Df Model:                            0
                              Volatility Model                              
&lt;span class=&quot;o&quot;&gt;============================================================================&lt;/span&gt;
                 coef    std err          t      P&amp;gt;|t|      95.0% Conf. Int.
&lt;span class=&quot;nt&quot;&gt;----------------------------------------------------------------------------&lt;/span&gt;
omega          0.0180  3.464e-03      5.200  1.991e-07 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1.122e-02,2.480e-02]
alpha[1]       0.1996  1.736e-02     11.497  1.362e-30     &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;  0.166,  0.234]
beta[1]        0.3958      0.103      3.859  1.140e-04     &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;  0.195,  0.597]
beta[2]        0.1163      0.127      0.919      0.358     &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-0&lt;/span&gt;.132,  0.364]
beta[3]        0.2756  3.697e-02      7.455  9.010e-14     &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;  0.203,  0.348]
&lt;span class=&quot;o&quot;&gt;============================================================================&lt;/span&gt;

Covariance estimator: robust
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This provides us with the key parameters of our model, that we can analyze now !&lt;/p&gt;

&lt;h2 id=&quot;interpreting-the-garch-parameters&quot;&gt;Interpreting the GARCH Parameters&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;GARCH(1, 3)&lt;/strong&gt; model provides several important parameters that give insight into Bitcoin’s volatility. Below is a breakdown of each key parameter and its interpretation:&lt;/p&gt;

&lt;table style=&quot;width:100%; border-collapse:collapse;&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align:center; vertical-align:middle;&quot;&gt;&lt;strong&gt;Parameter&lt;/strong&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align:center; vertical-align:middle;&quot;&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align:center; vertical-align:middle;&quot;&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align:center; vertical-align:middle;&quot;&gt;&lt;strong&gt;Interpretation&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;$\omega$&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;0.0180&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;Represents the &lt;strong&gt;long-term or baseline variance&lt;/strong&gt;.&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;A small, positive, and significant $\omega$ indicates a constant underlying volatility in the returns. Spikes in volatility are largely driven by recent shocks and historical persistence.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;$\alpha_1$&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;0.1996&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;Captures the impact of &lt;strong&gt;recent squared returns&lt;/strong&gt; ($r_{t-1}^2$) on current volatility.&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;About 20% of recent price movements influence current volatility. This suggests that large, sudden price changes significantly impact volatility.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;$\beta_1$&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;0.3958&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;Reflects the &lt;strong&gt;persistence of past volatility&lt;/strong&gt; on current volatility.&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;Around 40% of previous volatility persists into the current period. This explains the &lt;strong&gt;volatility clustering&lt;/strong&gt; phenomenon, where high volatility tends to follow high volatility.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;$\beta_2$&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;0.1163&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;Represents the influence of the &lt;strong&gt;second lag of volatility&lt;/strong&gt; on current volatility.&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;$\beta_2$ is &lt;strong&gt;not statistically significant&lt;/strong&gt; (p-value = 0.358), suggesting the second lag has a minimal effect on current volatility.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;$\beta_3$&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;0.2756&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;Measures the impact of the &lt;strong&gt;third lag of volatility&lt;/strong&gt; on current volatility.&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;The third lag is statistically significant with a &lt;strong&gt;t-statistic&lt;/strong&gt; of &lt;strong&gt;7.455&lt;/strong&gt;. This reinforces the idea that Bitcoin volatility has a &lt;strong&gt;long memory&lt;/strong&gt;.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;key-insights&quot;&gt;Key Insights:&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Long-term volatility ($\omega$)&lt;/strong&gt; is relatively low, suggesting that Bitcoin’s baseline volatility is not extreme but driven by recent market shocks.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Recent shocks ($\alpha_1$)&lt;/strong&gt; have a notable effect, with around 20% of volatility attributed to recent returns.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Volatility persistence ($\beta_1$)&lt;/strong&gt; is high, reinforcing the &lt;strong&gt;clustering of volatility&lt;/strong&gt; that is often observed in financial markets.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Second lag ($\beta_2$)&lt;/strong&gt; is not significant, indicating that further-back periods do not heavily influence the current volatility.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Third lag ($\beta_3$)&lt;/strong&gt; is significant, meaning that some past volatility still impacts the current market, showcasing Bitcoin’s long volatility memory.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;goodness-of-fit-check&quot;&gt;Goodness-of-fit Check&lt;/h2&gt;

&lt;p&gt;After fitting our selected GARCH model, it is however highly recommended to perform a &lt;strong&gt;goodness-of-fit check&lt;/strong&gt; on the residuals to ensure that the model adequately captures the dynamics of your time series. The main goal of such checks is to assess whether the model residuals behave as expected—ideally, they should resemble white noise, meaning they have no autocorrelation and constant variance (homoscedasticity). We will work on the standardized residuals&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Standardized residuals from the GARCH model
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std_residuals&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conditional_volatility&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Because of the last obs arguments we have NaNs
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std_residuals&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std_residuals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dropna&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s vizualize those residuals :&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Plot the standardized residuals from the GARCH model
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;std_residuals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Standardized residuals from the GARCH model&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Standardized residuals&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/BitcoinVolatility-2-figure-3.png&quot; alt=&quot;Bitcoin chart using GARCH in Python&quot; /&gt;&lt;/p&gt;

&lt;p&gt;At first glance, the situation looks concerning: we observe clear volatility clustering, with high volatility in the initial months, and numerous extreme values, suggesting the residuals may deviate from normality.&lt;/p&gt;

&lt;div style=&quot;text-align: center;&quot;&gt;
We now need to realize some &lt;strong&gt;rigorous statistical testing&lt;/strong&gt; to confirm that.
&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/here_we_go_again.png&quot; alt=&quot;Bitcoin volatility chart using GARCH in Python&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;autocorrelation-of-residuals&quot;&gt;Autocorrelation of Residuals&lt;/h3&gt;

&lt;p&gt;The standardized residuals (the residuals divided by their estimated volatility) should no longer show any significant autocorrelation. We can here again use the &lt;strong&gt;Ljung-Box Q-test&lt;/strong&gt; to test whether there is any remaining autocorrelation in the residuals or squared residuals.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Ljung-Box test for residuals (no autocorrelation should be present)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ljung_box_res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;acorr_ljungbox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std_residuals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;return_df&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Ljung-Box test for residuals&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ljung_box_res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Ljung-Box test for squared residuals (no remaining ARCH effects should be present)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ljung_box_sq_res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;acorr_ljungbox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std_residuals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;return_df&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Ljung-Box test for squared residuals&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ljung_box_sq_res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Ljung-Box &lt;span class=&quot;nb&quot;&gt;test &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;residuals
       lb_stat     lb_pvalue
10  163.434818  6.326210e-30

Ljung-Box &lt;span class=&quot;nb&quot;&gt;test &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;squared residuals
      lb_stat  lb_pvalue
10  19.082143   0.039232
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;p-values&lt;/strong&gt; are bellow 0.05, this indicates that there is statistically significant autocorrelation in the residuals or squared residuals, suggesting that the GARCH model has not effectively captured all the volatility structure.&lt;/p&gt;

&lt;h3 id=&quot;normality-of-residuals&quot;&gt;Normality of Residuals&lt;/h3&gt;

&lt;p&gt;The standardized residuals should follow a normal distribution. The &lt;strong&gt;Jarque-Bera test&lt;/strong&gt; can be used for this:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scipy.stats&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jarque_bera&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Perform Jarque-Bera test on standardized residuals
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jb_stat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jb_p_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jarque_bera&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std_residuals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Jarque-Bera Test Statistic: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jb_stat&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;P-value: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jb_p_value&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Jarque-Bera Test Statistic: 5551677.823833454
P-value: 0.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;p-value&lt;/strong&gt; bellow 0.05 indicates that the residuals do significantly deviate from normality.&lt;/p&gt;

&lt;p&gt;After running both test, the results indicate that &lt;strong&gt;the model’s residuals have issues&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;what-might-actually-improve-the-model&quot;&gt;What Might Actually Improve the Model?&lt;/h3&gt;

&lt;p&gt;To improve the fit of the GARCH model, we could consider several adjustments. The following table outlines possible strategies for improving the model:&lt;/p&gt;

&lt;table style=&quot;width:100%; border-collapse:collapse;&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align:center; vertical-align:middle;&quot;&gt;&lt;strong&gt;Adjustment&lt;/strong&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align:center; vertical-align:middle;&quot;&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align:center; vertical-align:middle;&quot;&gt;&lt;strong&gt;Benefit&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;&lt;strong&gt;Use a higher-order GARCH&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;Increase the number of lags in the GARCH terms, such as moving to &lt;strong&gt;GARCH(2, 3)&lt;/strong&gt;. This adjustment could better capture the autocorrelation if volatility has a longer memory, thereby modeling both short-term and long-term volatility effects more effectively.&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;Provides more flexibility in capturing extended memory in the volatility series, which could improve the model’s fit in markets with persistent volatility patterns.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;&lt;strong&gt;Use an EGARCH or GJR-GARCH model&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;A &lt;strong&gt;GARCH variant&lt;/strong&gt; like &lt;strong&gt;EGARCH&lt;/strong&gt; or &lt;strong&gt;GJR-GARCH&lt;/strong&gt; can account for &lt;strong&gt;asymmetric volatility&lt;/strong&gt; (where negative returns have a greater effect on volatility than positive returns).&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;Improves performance in modeling volatility clustering in assets with skewed returns, like Bitcoin.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;&lt;strong&gt;Change the residual distribution&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;If the residuals deviate from normality (as indicated by the &lt;strong&gt;Jarque-Bera test&lt;/strong&gt;), switch from a normal distribution to a &lt;strong&gt;Student’s t-distribution&lt;/strong&gt; or &lt;strong&gt;Generalized Error Distribution (GED)&lt;/strong&gt; for the residuals.&lt;/td&gt;
      &lt;td style=&quot;text-align:center; vertical-align:middle;&quot;&gt;Better reflects the &lt;strong&gt;non-normal&lt;/strong&gt; characteristics of financial time series, particularly fat tails, improving the model&apos;s ability to handle extreme events and outliers.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;But should we really bother ?&lt;/p&gt;

&lt;h3 id=&quot;should-we-discard-the-current-garch-model&quot;&gt;Should We Discard the Current GARCH Model?&lt;/h3&gt;

&lt;p&gt;Although the Ljung-Box tests for residuals and squared residuals show statistically significant autocorrelation, and the Jarque-Bera test indicates that the residuals deviate from normality, these results do not necessarily invalidate the use of the GARCH model. This indeed does not imply that the model is entirely ineffective. GARCH models are specifically designed to capture &lt;strong&gt;conditional heteroskedasticity&lt;/strong&gt;—volatility that changes over time based on past returns and variances. While the remaining autocorrelation suggests there are still some dynamics unexplained by the model, the GARCH framework remains usefull to capture volatility clustering.&lt;/p&gt;

&lt;p&gt;Even though the residuals do not follow a perfect normal distribution, the GARCH model can still provide valuable insights by capturing time-varying volatility. If we expect fat-tailed distributions, we could enhance the model by specifying a &lt;strong&gt;non-normal distribution&lt;/strong&gt; (e.g., Student’s t-distribution) for the residuals, which might better reflect the empirical properties of the data.&lt;/p&gt;

&lt;p&gt;Financial time series are notoriously difficult to model, and violations of normality or remaining autocorrelation are expected in complex markets like cryptocurrencies. GARCH remains a valuable tool in capturing the essential dynamics of volatility, and with potential enhancements—such as using a different distribution for the residuals or exploring higher-order GARCH models—we can further refine the model for better performance.&lt;/p&gt;

&lt;p&gt;In summary, while the current model may not be perfect, it provides a solid foundation for understanding volatility patterns. Refining the model rather than discarding it will likely lead to more accurate and insightful results. Thus, we will keep it that way for the moment, and probably improve it in a latter post.&lt;/p&gt;

&lt;h2 id=&quot;estimating-and-forecasting-volatility&quot;&gt;Estimating and Forecasting Volatility&lt;/h2&gt;

&lt;p&gt;Once we have select and fit one model, we can use it both to estimate realized volatility and for forecast.&lt;/p&gt;

&lt;h3 id=&quot;estimating-realized-volatility&quot;&gt;Estimating Realized Volatility&lt;/h3&gt;

&lt;p&gt;In this subsection, we’ll estimate &lt;strong&gt;realized volatility&lt;/strong&gt; using our &lt;strong&gt;GARCH model&lt;/strong&gt; and compare it to an alternative method like the &lt;strong&gt;EWMA&lt;/strong&gt; estimator. This comparison will give us a clearer picture of how well the GARCH model captures the dynamics of Bitcoin’s volatility compared to simpler approaches.&lt;/p&gt;

&lt;p&gt;Using the following code, we extract and plot the &lt;strong&gt;conditional volatility&lt;/strong&gt; from our GARCH model:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Get conditional volatility
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cond_vol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conditional_volatility&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cond_vol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dropna&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Plot the conditional volatility
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cond_vol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Conditional Volatility from GARCH(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;) Model&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/BitcoinVolatility-2-figure-4.png&quot; alt=&quot;Bitcoin volatility chart using GARCH in Python 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The plot shows how volatility fluctuates over time, capturing periods of heightened risk (volatility clustering) and more stable periods.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Exponentially Weighted Moving Average (EWMA)&lt;/strong&gt; model is another method often used to estimate realized volatility, giving more weight to recent observations. To compute and compare the EWMA volatility, we can use the following code:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Compute EWMA volatility
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lambda_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.94&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Decay factor as used in RiskMetrics
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ewma_vol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scaling_factor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ewm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lambda_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adjust&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Create a figure with two subplots (2 rows, 1 column)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;axs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subplots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# First subplot: GARCH vs EWMA Volatility
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cond_vol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;GARCH Conditional Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;blue&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;axs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ewma_vol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;EWMA Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;orange&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;axs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;GARCH vs. EWMA Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;axs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;axs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;axs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Second subplot: GARCH vs EWMA Volatility Ratio
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cond_vol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ewma_vol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ewma_vol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;GARCH Conditional Volatility vs EWMA Volatility Ratio&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;blue&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;axs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cond_vol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ewma_vol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ewma_vol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rolling&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Rolling Mean&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;red&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;axs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;GARCH vs. EWMA Volatility Ratio&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;axs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;axs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Volatility Ratio&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;axs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Adjust layout to prevent overlap
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tight_layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Display the figure
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/BitcoinVolatility-2-figure-5.png&quot; alt=&quot;figure 6&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Observation&lt;/strong&gt;: The GARCH model consistently shows higher volatility estimates compared to the EWMA model.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Explanation&lt;/strong&gt;: This is a typical feature of the GARCH model, which captures both the recent volatility and its persistence over time. Unlike EWMA, which gives more weight to recent data while smoothing out fluctuations, GARCH is designed to account for longer-term volatility clustering, making it more responsive to periods of heightened market stress.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Observation&lt;/strong&gt;: The EWMA model displays smoother, more stable volatility estimates over time.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Explanation&lt;/strong&gt;: EWMA assigns exponentially decreasing weights to past data, which dampens the impact of older, more volatile periods. This explains why EWMA produces lower volatility values, as it focuses more on recent changes without accounting for the persistent volatility that the GARCH model captures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;forecasting-volatility&quot;&gt;Forecasting Volatility&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;GARCH(1,3)&lt;/strong&gt; model allows us to generate conditional forecasts over future periods. Let’s expirement forecasting the volatility on unseen data.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;forecasts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;forecast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;horizon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;forecasted_variance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forecasts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;variance&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;forecasted_volatility&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;forecasted_variance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;    

&lt;span class=&quot;c1&quot;&gt;# Plot the conditional volatility
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;forecasted_volatility&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;h.60&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Forecast Volatility from GARCH(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;) Model&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/BitcoinVolatility-2-figure-6.png&quot; alt=&quot;Bitcoin volatility chart using GARCH in Python 3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The plot shows how volatility is expected to behave over the next 60 minutes. Spikes in forecasted volatility would indicate heightened market risk, while a more stable line would suggest a calmer market.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In this post, we explored the use of the &lt;strong&gt;GARCH model&lt;/strong&gt; for estimating and forecasting Bitcoin’s volatility. Compared to simpler models like &lt;strong&gt;EWMA&lt;/strong&gt;, GARCH provides a more robust framework for capturing the dynamic nature of financial markets, particularly in handling &lt;strong&gt;volatility clustering&lt;/strong&gt; and &lt;strong&gt;fat tails&lt;/strong&gt;—two key characteristics often present in cryptocurrency markets.&lt;/p&gt;

&lt;p&gt;We began by discussing the motivations for moving beyond simple models, then delved into the mechanics of the &lt;strong&gt;GARCH(1, 3)&lt;/strong&gt; model, explaining how it captures both recent volatility shocks and their persistence. We demonstrated how to fit the GARCH model, perform essential &lt;strong&gt;goodness-of-fit tests&lt;/strong&gt;, and interpret the resulting parameters. We encountered some issues with the residuals, but despite these imperfections our GARCH model still provides valuable insights into Bitcoin’s volatility structure and that potential improvements, like changing the residual distribution or testing higher-order models, could further refine the model.&lt;/p&gt;

&lt;p&gt;We showed how the GARCH model can be used both to estimate &lt;strong&gt;realized volatility&lt;/strong&gt; and to generate &lt;strong&gt;volatility forecasts&lt;/strong&gt; for the next hour. This ability to project future volatility is incredibly useful for traders, risk managers, and anyone involved in high-frequency trading environments where knowing short-term risk is critical.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;/BitcoinVolatility-3/&quot;&gt;the next post&lt;/a&gt;, we will dive deeper into volatility forecasting by exploring alternative data points like Low and High. Stay tuned for the final part of our series as we continue to explore the fascinating world of volatility modeling for Bitcoin !&lt;/p&gt;

&lt;h2 id=&quot;additional-resources&quot;&gt;Additional Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Code Repository&lt;/strong&gt;: &lt;a href=&quot;https://github.com/Zaltarba/BitcoinVolatilityEstimation/tree/main&quot;&gt;GitHub Link&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Adviced Reading&lt;/strong&gt;: John Hull’s &lt;em&gt;Options, Futures, and Other Derivatives&lt;/em&gt; and Collin Bennet’s &lt;em&gt;Trading Volatility&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to check out the GitHub repository for the complete code and try experimenting with different parameters to see how they affect volatility estimates.&lt;/p&gt;

&lt;p&gt;I’d love to hear your thoughts! Share your feedback, questions, or suggestions for future topics in the comments below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy analyzing&lt;/strong&gt;, and as always, may your trading strategies be &lt;strong&gt;well-informed&lt;/strong&gt;!&lt;/p&gt;
</content>
    <category term="Statistics" /><category term="Quantitative Finance" /><category term="Algo Trading" /><category term="Python" />
  </entry>
  
  <entry>
    <title type="html">Bitcoin Volatility Estimation with EWMA in Python</title>
    <link href="https://quants.quest/BitcoinVolatility-1/" rel="alternate" type="text/html" />
    <id>https://quants.quest/BitcoinVolatility-1</id>
    <published>2024-09-20T00:00:00+00:00</published>
    <updated>2024-09-20T00:00:00+00:00</updated>
    <summary type="html">Learn how to estimate Bitcoin&apos;s realized volatility using the EWMA method in Python with Binance data.</summary>
    <content type="html" xml:base="https://quants.quest/BitcoinVolatility-1/">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;In our &lt;a href=&quot;/DataBaseCreation/&quot;&gt;previous post&lt;/a&gt;, we explored how to fetch and store Binance candlestick data using HDF5, laying the groundwork for efficient data management in cryptocurrency research. Efficient data handling is crucial when dealing with large datasets, especially in the fast-paced world of crypto trading.&lt;/p&gt;

&lt;p&gt;Now, we’re taking the next step in our journey by delving into the analysis of this data. This is the first part of a three-part series where we’ll dive deep into estimating Bitcoin’s volatility using different methods.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminology Alert&lt;/strong&gt; : Volatility measures how much and how quickly the value of an asset changes.&lt;/p&gt;

&lt;p&gt;It’s important to note that volatility is not directly observable. It’s a &lt;strong&gt;hidden variable&lt;/strong&gt; that must be estimated from market data. Its value can vary depending on the estimation model used, making it a crucial yet complex component in financial analysis.&lt;/p&gt;

&lt;p&gt;There are two main types of volatility:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Realized Volatility&lt;/strong&gt;: Calculated from past market prices, it reflects the asset’s actual price movements over a specified period.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Implied Volatility&lt;/strong&gt;: Derived from the market price of a traded derivative, especially options. It represents the market’s expectation of future volatility.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why this difference ? Well, it happens volatility is far easier to predict than returns themselves. For options or other financial products, the future value of the volatility (meaning the future behaviour of the asset) is more usefull. Thus, the market will use the volatility expectancy for those products. In this post, &lt;strong&gt;we will focus on the realized volatility&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;why-analyze-bitcoins-realized-volatility-&quot;&gt;Why Analyze Bitcoin’s Realized Volatility ?&lt;/h2&gt;

&lt;p&gt;Understanding realized volatility is crucial, especially when dealing with highly volatile assets like Bitcoin. Realized volatility measures the degree of variation in an asset’s past price movements over a specific period. Studying it provides valuable insights into the asset’s risk profile and helps in making informed decisions. Here’s why analyzing realized volatility is essential:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Risk Assessment and Management&lt;/strong&gt;: Realized volatility is a key indicator of the risk associated with an asset. By analyzing how much Bitcoin’s price has fluctuated in the past, traders and investors can gauge the potential risk of future price movements.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Strategic Trading Decisions&lt;/strong&gt;: Studying realized volatility can help traders develop effective trading strategies by recognizing periods of high or low volatility to choose appropriate trading approaches (e.g., trend following in high volatility, mean reversion in low volatility).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Option Pricing and Derivative Valuation&lt;/strong&gt;: Since volatility is a hidden variable and not directly observable, realized volatility serves as an essential estimate.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Getting Risk-Adjusted Returns&lt;/strong&gt;: Evaluating whether the potential returns justify the risks based on realized volatility.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In essence, studying realized volatility is &lt;strong&gt;not just an academic&lt;/strong&gt; exercise—it’s a practical necessity. It equips traders and investors with the knowledge to navigate the complexities of the financial markets, particularly the dynamic and often unpredictable cryptocurrency landscape. By acknowledging that volatility is a hidden variable dependent on estimation models, we can appreciate the importance of selecting appropriate methods to measure and interpret it. This understanding ultimately leads to better risk management, more effective trading strategies, and informed decision-making in the pursuit of financial goals.&lt;/p&gt;

&lt;h2 id=&quot;preparing-binance-bitcoin-data-for-ewma-in-python&quot;&gt;Preparing Binance Bitcoin Data for EWMA in Python&lt;/h2&gt;

&lt;p&gt;Before we can estimate volatility, we need to prepare our data. The database we will use is the one we created in &lt;a href=&quot;/DataBaseCreation/&quot;&gt;this post&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;loading-data-from-hdf5&quot;&gt;Loading Data from HDF5&lt;/h3&gt;

&lt;p&gt;First, let’s load the Bitcoin data we previously stored in our HDF5 file.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pandas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt; 

&lt;span class=&quot;c1&quot;&gt;# Load the data from the HDF5 file
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_hdf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;data/crypto_database.h5&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;BTCUSDT&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This will give us access to the Bitcoin candlestick data with 1-minute granularity.&lt;/p&gt;

&lt;h3 id=&quot;data-cleaning-and-preprocessing&quot;&gt;Data Cleaning and Preprocessing&lt;/h3&gt;

&lt;p&gt;Ensuring data quality is paramount. We’ll check for missing values and ensure that the data types are appropriate.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Check for missing values
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isnull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Convert &apos;Open_Time&apos; to datetime if not already done
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reset_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_datetime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Set &apos;Open_Time&apos; as the index
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;taking-a-look-at-the-data&quot;&gt;Taking a look at the data&lt;/h3&gt;

&lt;p&gt;Let’s ensure we have good quality data by plotting the evolution of the Bitcoin Price.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Plot the log returns
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Close&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Bitcoin Price&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;BTC USDT&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/BitcoinVolatility-1-figure-1.png&quot; alt=&quot;figure 1&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;calculating-bitcoin-log-returns-in-python&quot;&gt;Calculating Bitcoin Log Returns in Python&lt;/h3&gt;

&lt;p&gt;Logarithmic returns, or log returns, can be preferred over simple returns for several reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Time Additivity&lt;/strong&gt;: Log returns are additive over time, which simplifies calculations.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Normality&lt;/strong&gt;: They often better approximate a normal distribution, which is a common assumption in financial models.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Symmetry&lt;/strong&gt;: Log returns treat upward and downward movements symmetrically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The formula for log returns is:&lt;/p&gt;

\[r_t = \ln\left(\frac{P_t}{P_{t-1}}\right)\]

&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$ r_t $ is the log return at time $ t $.&lt;/li&gt;
  &lt;li&gt;$ P_t $ is the price at time $ t $.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s calculate the log returns using the ‘Close’ price. While this approach is common, it’s important to note that volatility estimation doesn’t have to rely solely on the ‘Close’ price; other data points like the ‘Open’, ‘High’, and ‘Low’ during a time interval are also meaningful and can provide additional insights. However, for simplicity in this post, we’ll only use the ‘Close’ price.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Calculate log returns
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;log_returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Close&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Close&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Drop the NaN value created by the shift
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dropna&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;log_returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, let’s visualize the log returns to get a sense of their behavior.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Plot the log returns
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;log_returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Bitcoin Log Returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Log Return&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/BitcoinVolatility-1-figure-2.png&quot; alt=&quot;figure 2&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;estimating-bitcoin-volatility-with-ewma&quot;&gt;Estimating Bitcoin Volatility with EWMA&lt;/h2&gt;

&lt;h3 id=&quot;introducing-the-ewma-method&quot;&gt;Introducing the EWMA Method&lt;/h3&gt;

&lt;p&gt;The Exponentially Weighted Moving Average (EWMA) is a powerful statistical technique that assigns exponentially decreasing weights to past observations, giving more significance to recent data points. This responsiveness to the latest market information makes EWMA particularly valuable in volatile markets like cryptocurrency, where conditions can change rapidly.&lt;/p&gt;

&lt;p&gt;EWMA was popularized by &lt;strong&gt;J.P. Morgan&lt;/strong&gt; in the early 1990s through their development of the &lt;a href=&quot;https://www.phy.pmf.unizg.hr/~bp/TD4ePt_2.pdf&quot;&gt;&lt;strong&gt;RiskMetrics&lt;/strong&gt;&lt;/a&gt; system. RiskMetrics provided a standardized framework for measuring and managing market risk, introducing EWMA as an effective method for estimating volatility. John Hull’s book &lt;a href=&quot;https://archive.org/details/options-futures-et-autres-actifs-derives&quot;&gt;&lt;em&gt;“Options, Futures, and Other Derivatives”&lt;/em&gt;&lt;/a&gt; discusses EWMA as an effective method for volatility estimation. By emphasizing recent price movements without entirely discarding older data, EWMA captures the persistence and clustering of volatility often observed in financial time series.&lt;/p&gt;

&lt;p&gt;The EWMA volatility is calculated using the formula:&lt;/p&gt;

\[\sigma_t^2 = \lambda \sigma_{t-1}^2 + (1 - \lambda) r_t^2\]

&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$ \sigma_t^2 $ is the variance at time $ t $.&lt;/li&gt;
  &lt;li&gt;$ \lambda $ is the decay factor (0 &amp;lt; $ \lambda $ &amp;lt; 1).&lt;/li&gt;
  &lt;li&gt;$ r_t $ is the return at time $ t $.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;setting-the-decay-factor-lambda&quot;&gt;Setting the Decay Factor (Lambda)&lt;/h3&gt;

&lt;p&gt;The choice of the decay factor $ \lambda $ determines how quickly the weights decrease. A commonly used value is $ \lambda = 0.94 $, as suggested by RiskMetrics. A higher $ \lambda $ gives more weight to older observations, while a lower $ \lambda $ emphasizes recent returns more heavily.&lt;/p&gt;

&lt;h3 id=&quot;step-by-step-calculation&quot;&gt;Step-by-Step Calculation&lt;/h3&gt;

&lt;p&gt;Using pandas, we can implement the EWMA volatility estimation easily.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Set the decay factor
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lambda_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.94&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lambda_&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Calculate the EWMA variance
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;ewma_variance&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;log_returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ewm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adjust&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Calculate the EWMA volatility
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;ewma_volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;ewma_variance&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;visualization&quot;&gt;Visualization&lt;/h3&gt;

&lt;p&gt;Let’s plot the EWMA volatility to visualize how it changes over time.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Plot the EWMA volatility
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;ewma_volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;EWMA Volatility of Bitcoin Returns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Volatility&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/BitcoinVolatility-1-figure-3.png&quot; alt=&quot;figure 3&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;analyzing-the-results&quot;&gt;Analyzing the Results&lt;/h3&gt;

&lt;p&gt;By analyzing the plot, we can identify periods of sharp volatility spikes, which signal higher risk and potentially greater reward opportunities. These spikes are often triggered by significant market events or news impacting Bitcoin. This behavior is known as &lt;strong&gt;volatility clustering&lt;/strong&gt;, where high-volatility periods are followed by similarly turbulent periods, while low-volatility phases exhibit smaller, more stable fluctuations.&lt;/p&gt;

&lt;h3 id=&quot;ewma-volatility-advantages-and-limitations&quot;&gt;EWMA Volatility: Advantages and Limitations&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Responsiveness&lt;/strong&gt;: EWMA adjusts quickly to changes, making it suitable for volatile markets.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Simplicity&lt;/strong&gt;: It’s straightforward to implement and doesn’t require complex modeling.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Weighted Data&lt;/strong&gt;: By giving more importance to recent data, EWMA provides a more current view of market volatility.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Easy Online Learning&lt;/strong&gt;: EWMA is well-suited for real-time or online learning, where data is processed sequentially. In production environments, where data arrives continuously, this feature ensures the system can easily adapt without reprocessing the entire dataset each time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These characteristics make EWMA a highly practical tool for production applications, especially in environments where real-time data processing is critical. Yet it has some important limitations that should be considered, especially when thinking about future predictions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;No Predictive Power for Future Volatility&lt;/strong&gt;: The EWMA estimator is not suitable for predicting &lt;strong&gt;future volatility&lt;/strong&gt;. When simulating future values of the model, the expectation $ E[\sigma_{t+h}] $ tends to 0 as $ h $ increases, meaning the model effectively predicts no future volatility (assuming $ E[ r_t] = 0 $ ). This limitation arises because EWMA only reacts to past data without incorporating any forward-looking information or structural changes in the market.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Constant Decay Factor&lt;/strong&gt;: The choice of the decay factor $ \lambda $ is critical to the model’s performance. However, EWMA uses a constant $ \lambda $, which assumes that the rate at which past data becomes less relevant is fixed over time. This might not be realistic during periods of sudden market regime shifts, where volatility patterns change dramatically.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Sensitivity to Large Shocks&lt;/strong&gt;: While EWMA adapts to volatility changes, it might still &lt;strong&gt;overreact to short-term shocks&lt;/strong&gt;. Large price movements (like flash crashes) can disproportionately affect the estimated volatility in the short term, without accounting for whether these movements represent structural shifts or noise.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lastly, as explained by Collin Bennet in his book &lt;a href=&quot;https://www.trading-volatility.com/Trading-Volatility.pdf&quot;&gt;Trading Volatility&lt;/a&gt; Exponentially weighted volatility models struggle to account for recurring volatility-inducing events like earnings reports. Just before an earnings announcement—when future volatility is expected to rise—the model places the least weight on previous earnings-related volatility spikes. Conversely, right after the earnings event—when future volatility is likely to decrease—the model assigns the most weight to these prior events. However, these models may still have some applicability when analyzing indices.&lt;/p&gt;

&lt;p&gt;Due to these limitations, the EWMA method is suitable only for &lt;strong&gt;historical analysis&lt;/strong&gt; and not for forecasting future volatility. More advanced models, like GARCH, are better suited for predicting future volatility because they account for the persistence and reversion tendencies in volatility over time.&lt;/p&gt;

&lt;h2 id=&quot;conclusion-and-next-steps&quot;&gt;Conclusion and Next Steps&lt;/h2&gt;

&lt;p&gt;In this post, we’ve introduced the concept of volatility and its importance in financial markets, particularly for Bitcoin. We’ve shown how to estimate volatility using the EWMA method, which provides a responsive and practical approach for traders and analysts.&lt;/p&gt;

&lt;p&gt;This is just the beginning. In the &lt;a href=&quot;/BitcoinVolatility-2/&quot;&gt;next posts&lt;/a&gt; of this series, we’ll explore more sophisticated methods like GARCH models for volatility estimation.&lt;/p&gt;

&lt;p&gt;Stay tuned for deeper insights into the fascinating world of financial volatility analysis!&lt;/p&gt;

&lt;h2 id=&quot;additional-resources&quot;&gt;Additional Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Code Repository&lt;/strong&gt;: &lt;a href=&quot;https://github.com/Zaltarba/BitcoinVolatilityEstimation/tree/main&quot;&gt;GitHub Link&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Adviced Reading&lt;/strong&gt;: John Hull’s &lt;em&gt;Options, Futures, and Other Derivatives&lt;/em&gt; and Collin Bennet’s &lt;em&gt;Trading Volatility&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to share your thoughts or ask questions in the comments below. I encourage you to experiment with the code, try different decay factors, and see how it affects the volatility estimates.&lt;/p&gt;

&lt;p&gt;I’d love to hear your thoughts! Share your feedback, questions, or suggestions for future topics in the comments below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy analyzing&lt;/strong&gt;, and as always, may your trading strategies be &lt;strong&gt;well-informed&lt;/strong&gt;!&lt;/p&gt;

</content>
    <category term="Statistics" /><category term="Quantitative Finance" /><category term="Algo Trading" /><category term="Python" />
  </entry>
  
  <entry>
    <title type="html">How to Fetch and Store Binance Data Efficiently Using HDF5 in Python</title>
    <link href="https://quants.quest/DataBaseCreation/" rel="alternate" type="text/html" />
    <id>https://quants.quest/DataBaseCreation</id>
    <published>2024-08-18T00:00:00+00:00</published>
    <updated>2024-08-18T00:00:00+00:00</updated>
    <summary type="html">Learn how to fetch Binance candlestick data and store it efficiently using HDF5 in Python. Discover the Binance API and how to keep your data process scalable.</summary>
    <content type="html" xml:base="https://quants.quest/DataBaseCreation/">&lt;h2 id=&quot;why-hdf5-is-ideal-for-storing-cryptocurrency-data&quot;&gt;Why HDF5 is Ideal for Storing Cryptocurrency Data&lt;/h2&gt;

&lt;p&gt;When handling large datasets, especially in research, the choice of file format is crucial. &lt;a href=&quot;https://fr.wikipedia.org/wiki/Hierarchical_Data_Format&quot;&gt;HDF5&lt;/a&gt; (Hierarchical Data Format version 5) is a powerful data model that is ideal for managing and storing enormous amounts of data efficiently. It’s designed to store data in a hierarchical structure, making it a perfect choice for large, complex datasets—like cryptocurrency trading data. Let’s dive into how you can leverage HDF5 to store crypto data fetched from &lt;a href=&quot;https://www.binance.com/en&quot;&gt;Binance&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before jumping into the code, let’s discuss why HDF5 is so beneficial:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Efficiency&lt;/strong&gt;: HDF5 is built for writing and reading speed. It can handle massive datasets much more efficiently than traditional file formats like CSV.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: It’s designed to store and organize large amounts of data across multiple datasets.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;: HDF5 files can be easily sliced and diced for different analyses without needing to load the entire dataset into memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These characteristics make HDF5 a valuable tool for research, especially when working with high-frequency trading data, which can accumulate quickly.&lt;/p&gt;

&lt;p&gt;Want some proof ? Here is an comparaison between .csv and .h5 files for a small dataset.&lt;/p&gt;

&lt;p&gt;For the &lt;strong&gt;writing speed&lt;/strong&gt; :&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_csv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;data/speed_test.csv&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CPU &lt;span class=&quot;nb&quot;&gt;times&lt;/span&gt;: total: 93.8 ms
Wall &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;: 123 ms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_hdf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;data/speed_test.h5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;w&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CPU &lt;span class=&quot;nb&quot;&gt;times&lt;/span&gt;: total: 0 ns
Wall &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;: 14.7 ms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For the &lt;strong&gt;reading speed&lt;/strong&gt; :&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_csv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;data/speed_test.csv&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CPU &lt;span class=&quot;nb&quot;&gt;times&lt;/span&gt;: total: 15.6 ms
Wall &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;: 32 ms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_hdf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;data/speed_test.h5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CPU &lt;span class=&quot;nb&quot;&gt;times&lt;/span&gt;: total: 15.6 ns
Wall &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;: 11.7 ms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the csv format can’t compete.&lt;/p&gt;

&lt;h2 id=&quot;getting-started-with-python-imports&quot;&gt;Getting Started with Python Imports&lt;/h2&gt;

&lt;p&gt;First, let’s set up our environment by importing the necessary libraries:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;requests&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pandas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;datetime&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timedelta&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;These libraries are fundamental for fetching, processing, and storing cryptocurrency data. requests will help us interact with Binance’s API, while pandas is crucial for data manipulation. datetime and time will manage our data fetching timeframes.&lt;/p&gt;

&lt;h2 id=&quot;fetching-and-storing-binance-data-in-hdf5&quot;&gt;Fetching and Storing Binance Data in HDF5&lt;/h2&gt;

&lt;p&gt;Next, we’ll create a function to fetch candlestick data from Binance and store it in an HDF5 file. The HDF5 file acts as a database, storing our data in a structured and efficient manner.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fetch_candlestick_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdf5_file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;data/crypto_database.h5&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;candlestick_data&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://api.binance.com/api/v3/klines&quot;&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Convert dates to timestamps in milliseconds
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;start_ts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strptime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;%Y-%m-%d %H:%M:%S&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;end_ts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strptime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;%Y-%m-%d %H:%M:%S&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Calculate the total number of steps
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;total_steps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end_ts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_ts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Initialize step counter
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;step_counter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_ts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end_ts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;symbol&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;interval&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;startTime&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_ts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;endTime&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_ts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end_ts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&apos;limit&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status_code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&apos;Open_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;s&quot;&gt;&apos;Open&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;s&quot;&gt;&apos;High&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;s&quot;&gt;&apos;Low&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;s&quot;&gt;&apos;Close&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;s&quot;&gt;&apos;Volume&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;s&quot;&gt;&apos;Close_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;s&quot;&gt;&apos;Quote_Asset_Volume&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;s&quot;&gt;&apos;Number_of_Trades&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;s&quot;&gt;&apos;Taker_Buy_Base_Asset_Volume&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;s&quot;&gt;&apos;Taker_Buy_Quote_Asset_Volume&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;s&quot;&gt;&apos;Ignore&apos;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
            
            &lt;span class=&quot;c1&quot;&gt;# Convert timestamps to datetime
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_datetime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;ns&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Close_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Convert numeric columns to appropriate types
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_numeric&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;High&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_numeric&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;High&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Low&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_numeric&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Low&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Close&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_numeric&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Close&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Volume&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_numeric&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Volume&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Quote_Asset_Volume&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_numeric&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Quote_Asset_Volume&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Taker_Buy_Base_Asset_Volume&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_numeric&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Taker_Buy_Base_Asset_Volume&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Taker_Buy_Quote_Asset_Volume&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_numeric&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Taker_Buy_Quote_Asset_Volume&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;# Set &apos;Open Time&apos; as index
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Open_Time&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;# Store DataFrame in HDF5 file
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_hdf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;hdf5_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;a&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;table&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;n&quot;&gt;data_columns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            
            &lt;span class=&quot;c1&quot;&gt;# Update step counter
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;step_counter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            
            &lt;span class=&quot;c1&quot;&gt;# Print progress
&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Step &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step_counter&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total_steps&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; completed.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            
            &lt;span class=&quot;n&quot;&gt;start_ts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Move to the next timestamp
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Error: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status_code&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Wait a minute before retrying
&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# To avoid hitting rate limits
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Breaking Down the Function :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;API Request: The function sends a request to Binance’s API for candlestick data. We loop through time intervals using the start_ts and end_ts timestamps to ensure we gather data over a specified period.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Data Processing: The JSON response is converted into a pandas DataFrame, making it easier to work with. We format the data by converting timestamps and changing numeric columns to their appropriate types.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;HDF5 Storage: Finally, we store the DataFrame in an HDF5 file. This allows us to append new data over time, making it an efficient method for long-term storage.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;running-the-data-collection&quot;&gt;Running the Data Collection&lt;/h2&gt;

&lt;p&gt;Now, let’s tie it all together with a main function that initiates the data fetching process:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;symbol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;BTCUSDT&apos;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;interval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;1m&apos;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 1-minute granularity
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;2020-01-01 00:00:00&apos;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;2020-02-01 00:00:00&apos;&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Fetch the data and store it in HDF5
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;fetch_candlestick_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;start_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end_date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;hdf5_file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;data/crypto_database.h5&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;By using HDF5, you gain a powerful tool for managing large datasets, ensuring that your research is both scalable and efficient. Whether you’re analyzing historical price data or developing trading strategies, this approach provides a robust foundation for your work.&lt;/p&gt;

&lt;p&gt;Moreover, you can expand your database by storing additional cryptocurrency pairs in the same HDF5 file. Accessing them is straightforward—simply use pd.read_hdf() with the desired key, allowing you to seamlessly retrieve and analyze data across multiple assets.&lt;/p&gt;

&lt;h2 id=&quot;additional-resources&quot;&gt;Additional Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Code Repository&lt;/strong&gt;: &lt;a href=&quot;https://github.com/Zaltarba/BitcoinVolatilityEstimation/tree/main&quot;&gt;GitHub Link&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Adviced Reading&lt;/strong&gt;: Yves Hilpish &lt;a href=&quot;https://www.oreilly.com/library/view/python-for-algorithmic/9781492053347/&quot;&gt;&lt;em&gt;Python for Algorithmic Trading&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’d love to hear your thoughts! Share your feedback, questions, or suggestions for future topics in the comments below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy coding&lt;/strong&gt;, and may your data always be &lt;strong&gt;manageable&lt;/strong&gt;!&lt;/p&gt;
</content>
    <category term="Quantitative Finance" /><category term="Algo Trading" /><category term="Data Engineering" /><category term="Python" />
  </entry>
  
  <entry>
    <title type="html">Leveraging Options Data for Stock Sentiment Analysis</title>
    <link href="https://quants.quest/AboutMarketSentiment/" rel="alternate" type="text/html" />
    <id>https://quants.quest/AboutMarketSentiment</id>
    <published>2024-07-14T00:00:00+00:00</published>
    <updated>2024-07-14T00:00:00+00:00</updated>
    <summary type="html">Learn how Open Interest, Put/Call Ratio, and the Sizzle Index can enhance your understanding of market sentiment and stock trends</summary>
    <content type="html" xml:base="https://quants.quest/AboutMarketSentiment/">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Options data, often overlooked by those who don’t directly trade options, can be a goldmine for assessing market sentiment and gauging potential stock movements. Here, we explore three key options metrics that can serve as a sentiment barometer for any stock trader:&lt;/p&gt;

&lt;h3 id=&quot;key-metrics-to-watch&quot;&gt;Key Metrics to Watch&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Open Interest&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Put/Call Ratio&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;IV Skewness&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These metrics provide valuable insights into market dynamics and potential trend shifts in stock prices. If you want to use them easily, feel free to check my app &lt;a href=&quot;https://is-it-time-to-buy.streamlit.app/&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practical Tip&lt;/strong&gt; : Option data can easily be access for major stock with yfinance for free&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;yfinance&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yf&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pandas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_options_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ticker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Load the ticker data
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;stock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Ticker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ticker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Get available options expirations
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;expirations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Initialize an empty DataFrame to hold all options data
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;all_options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Loop through all available expiration dates and get the options data
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expirations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Fetch the call and put data for the current expiration date
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;option_chain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Combine the call and put data
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;current_options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;current_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Expiration&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Add the expiration date to the DataFrame
&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# Append the current options data to the all_options DataFrame
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;all_options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Clearly Identify Call and Puts 
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;all_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;contractSymbol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;all_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ticker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;all_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all_options&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;C&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Call&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;P&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Put&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all_options&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;understanding-open-interest&quot;&gt;Understanding Open Interest&lt;/h2&gt;

&lt;p&gt;Open interest represents the total number of outstanding options contracts that have not been settled. For each new option contract that is opened, open interest increases by one; it decreases by one for every contract that is closed. This number gives traders an idea of the liquidity and size of the market for a particular option.&lt;/p&gt;

&lt;p&gt;Some traders use the highest open interest strike price as a marker for potential support or resistance levels in the underlying stock. This concept is tied to the “max pain theory,” which posits that the stock price might gravitate towards the strike price at expiration where the most options (both calls and puts) would expire worthlessly, causing the maximum financial loss to option holders.&lt;/p&gt;

&lt;h2 id=&quot;analyzing-the-putcall-ratio&quot;&gt;Analyzing the Put/Call Ratio&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Terminology Alert&lt;/strong&gt; : The put/call ratio measures the volume of trading in puts versus calls.&lt;/p&gt;

\[\text{Put/Call Ratio} = \frac{\text{Volume of Puts Traded}}{\text{Volume of Calls Traded}}\]

&lt;p&gt;This ratio is calculated by dividing the total volume of puts traded by the total volume of calls traded over a specific period, typically one trading day. In practice, the put/call ratio can be derived from options across all strikes and maturities, not just those with the same strike price or expiration date. This comprehensive approach provides a broader view of market sentiment, capturing the general trading behavior towards puts versus calls across the entire options market. Traders use this ratio to gauge overall market sentiment, identifying whether there’s a prevailing bearish or bullish inclination among participants.&lt;/p&gt;

&lt;p&gt;A higher ratio indicates more put buying (commonly seen as bearish sentiment), whereas a lower ratio suggests more call buying (typically viewed as bullish sentiment). This ratio can act as a contrarian indicator, hinting at possible reversals if predominantly one type of option outweighs the other significantly.&lt;/p&gt;

&lt;p&gt;Traders often look for extremes in this ratio on their trading platforms to assess whether the market sentiment is overly pessimistic or optimistic, which might indicate a potential reversal in the stock’s price movement.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;While not everyone may trade options, the data derived from options markets can offer crucial insights into broader market sentiments and potential shifts in stock trajectories. By integrating open interest and put/call ratios into your analysis, you can gain a more nuanced understanding of market dynamics and better prepare for future movements. Remember, these tools should provide additional layers of insight and are not standalone decision-makers.&lt;/p&gt;
</content>
    <category term="Quantitative Finance" /><category term="Algo Trading" />
  </entry>
  
  <entry>
    <title type="html">An Introduction to Pair Trading and Market Neutral Strategies</title>
    <link href="https://quants.quest/PairsTrading-1/" rel="alternate" type="text/html" />
    <id>https://quants.quest/PairsTrading-1</id>
    <published>2024-06-22T00:00:00+00:00</published>
    <updated>2024-06-22T00:00:00+00:00</updated>
    <summary type="html">This post is the first of a serie about pair trading and market neutral strategies ...</summary>
    <content type="html" xml:base="https://quants.quest/PairsTrading-1/">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;I have started working on pairs trading and market-neutral trading strategies in the US equity market over the last few months. Here, I will try to give a clear and concise introduction to the topic and introduce the frameworks I will be delving into more deeply in the next posts.&lt;/p&gt;

&lt;h2 id=&quot;general-overview&quot;&gt;General Overview&lt;/h2&gt;

&lt;p&gt;Before speaking of pairs trading, let’s first define market-neutral strategies. A market-neutral strategy aims to provide uncorrelated sources of returns from the market. The Capital Asset Pricing Model (CAPM), even if now outdated, provides a nice framework to explain the intuition:&lt;/p&gt;

&lt;p&gt;The return of an asset can be expressed as $r_t - r_f = \alpha + (\beta \times (r_m - r_f)) + \epsilon_t$, with:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;$r_f$ the risk-free return&lt;/li&gt;
  &lt;li&gt;$r_m$ the market return&lt;/li&gt;
  &lt;li&gt;$\alpha$ the expected excess return&lt;/li&gt;
  &lt;li&gt;$\beta$ the sensitivity of the asset’s returns to the market returns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this framework, if you manage to construct a portfolio with a null beta (i.e., the linear combination of the assets within is such that the sum of their betas is null), you then get a portfolio whose returns are uncorrelated from those of the market! The quant researcher’s role is thus to reduce its strategy’s beta as much as possible and to maximize its alpha (i.e., its expected outperformance). Bear and bull markets don’t matter anymore! But what’s the point?&lt;/p&gt;

&lt;h2 id=&quot;why-do-market-neutral-startegies&quot;&gt;Why do market neutral startegies&lt;/h2&gt;

&lt;p&gt;Why not just buy OTM calls with one week until expiration and pray to get rich? Joke aside, why not just be a bullish investors and be directional ? Warrent Buffet for sure isn’t a market neutral player.&lt;/p&gt;

&lt;p&gt;This is I believe a legitimate question for any investors (motivations from the Quants side are mostly about the challenge, the maths behind and the elegance of it). Well first all, this allows you to perform consistent return (doesn’t mean you will suceed). Market can indeed go upside but also downside. Their is also the diversification play : since Markowitz’s work and modern portfolio theory adoption investor are looking for uncorrelated strategies in order to improve their sharpe or sortino ratio.&lt;/p&gt;

&lt;h2 id=&quot;about-pairs-trading&quot;&gt;About Pairs Trading&lt;/h2&gt;

&lt;p&gt;Pairs trading is a specific framework with the purpose of creating market-neutral strategies. The way to do this, used by hedge fund quants, is as follows: use a linear combination of two stocks to remove the beta from the market. Let’s consider two stocks: stock A and stock B.&lt;/p&gt;

&lt;p&gt;Under the CAPM model (again, this approach is outdated and if you are looking for practical advice, you should work with a multi-factor model at least) you get:&lt;/p&gt;

\[\beta_B \times r_t^A - \beta_A \times r_t^B = \beta_B \times \alpha_A - \beta_A \times \alpha_B + \epsilon_t^A + \epsilon_t^B\]

&lt;p&gt;with&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$\beta_A$, $\alpha_A$, $r_t^A$, and $\epsilon_t^A$ being the CAPM components for stock A&lt;/li&gt;
  &lt;li&gt;$\beta_B$, $\alpha_B$, $r_t^B$, and $\epsilon_t^B$ being the CAPM components for stock B&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, the market part has disappeared. Theoretically, buying $\beta_B$ stock A and shorting $\beta_A$ stock B should give you a market-neutral portfolio for any stock. Where’s the hitch? Well, a warning here: an assumption of the CAPM model is that $\epsilon_t$ is an idiosyncratic risk, meaning the correlation between $\epsilon_t^A$ and $\epsilon_t^B$ is null. That’s a big assumption and why I have been warning so much about this framework. We will see more useful frameworks in the next posts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminology Alert&lt;/strong&gt;: In practice, strategies tend to go long on stock A and short $\frac{\beta_A}{\beta_B}$. Thus, we introduce the hedge ratio $\rho = \frac{\beta_A}{\beta_B}$.&lt;/p&gt;

&lt;p&gt;Pair trading is all about working on spreads between the two assets and to construct getting positive returns from it (modern pair trading can of course be involving 3, 4, 5, or even more stock but we will keep simple for now).&lt;/p&gt;

&lt;p&gt;Now that we are clear on what market neutral means, let’s get into some of the basic tools.&lt;/p&gt;

&lt;h2 id=&quot;some-technical-aspects&quot;&gt;Some Technical Aspects&lt;/h2&gt;

&lt;p&gt;Let’s dive into some technical aspects. I will stop using the CAPM model from now on. Despite it being great for gaining some common sense and intuitions, it’s not so good for modeling today’s market.&lt;/p&gt;

&lt;p&gt;A common framework for years has been &lt;strong&gt;cointegration&lt;/strong&gt;. Basically, you consider stocks A and B being cointegrated if and only if you can get a stationnary series from a linear combinaison of their log prices (which are not stationnary):&lt;/p&gt;

\[\log(P_t^A) = \text{const} + \rho \times \log(P_t^B) + \epsilon_t\]

&lt;p&gt;with $(\epsilon_t)$ being stationary.&lt;/p&gt;

&lt;p&gt;In this case, you are able to compute the hedge ratio from a simple regression. Moreover, you can get a confidence interval and p-value to ensure it is significantly non-null. Great! I have to say that linking cointegration with achieving a market-neutral strategy is not straightforward. It indeed requires at least some modeling or further assumptions/requirements. But for now, let’s admit it gets us closer.&lt;/p&gt;

&lt;p&gt;But the devil hides in the details. I won’t delve into all the linear regression temporal aspects and its application for sequential data (refer to a handbook on time series prediction for more knowledge), but one has to be very careful. We are indeed working on non-stationary variables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminology Alert&lt;/strong&gt;: A spurious regression is a regression where the p-value indicates a statistically significant relationship between variables, but this relationship is actually meaningless or random, often due to underlying trends in the data rather than a true correlation.&lt;/p&gt;

&lt;p&gt;Let’s consider two stock prices, $(P_t^A)$ and $(P_t^B)$. Let’s model both stock prices logarithm by a random walk and with uncorrelated noise. So we get:&lt;/p&gt;

&lt;p&gt;\(\log(P_t^A) = \log(P_0^A) + \sum_{i=1}^{t} \epsilon_i^A\)
\(\log(P_t^B) = \log(P_0^B) + \sum_{i=1}^{t} \epsilon_i^B\)&lt;/p&gt;

&lt;p&gt;with:&lt;/p&gt;

&lt;p&gt;\(\epsilon_t^A \sim \text{WN}(0, \sigma_A^2)\)
and
\(\epsilon_t^B \sim \text{WN}(0, \sigma_B^2)\)&lt;/p&gt;

&lt;p&gt;The issue here is $Var(P_t^A) = t \times \sigma_A^2$, which means we have a non-stationary variable. Thus, the linear regression requirements are not met. If you attempt to do one, the issue is that the usual test statistics (like t-statistics) do not follow their standard distributions under the null hypothesis. P-values will not be interpretable since they need to follow a uniform distribution between 0 and 1 under the null hypothesis.&lt;/p&gt;

&lt;p&gt;Doing some simulation with the folowing code :&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pandas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;statsmodels.api&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sm&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simulate_random_walk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot; Generate a random walk series. &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Random walk starts at zero
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;walk&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zeros&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Generate random steps, add to previous
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;walk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;walk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;walk&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;perform_regression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot; Perform linear regression and return the p-value. &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_constant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Adding a constant for the intercept
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OLS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pvalues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# p-value for the slope
&lt;/span&gt;    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;num_simulations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;num_points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Number of points in each random walk
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;p_values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_simulations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Generate two independent random walks
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;simulate_random_walk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_points&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;simulate_random_walk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_points&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            
            &lt;span class=&quot;c1&quot;&gt;# Perform regression and get the p-value
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;p_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perform_regression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;p_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
        &lt;span class=&quot;c1&quot;&gt;# Plotting the distribution of p-values
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bins&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;edgecolor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;black&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;P-value&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Frequency&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Distribution of P-values for 100 Regressions of Independent Random Walks&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    
        &lt;span class=&quot;c1&quot;&gt;# Optionally, return or print p_values or any other statistics
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p_values&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Call the main function to execute the simulation
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;p_values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You get the folowing graph :&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/IPT_spurious_pvalues.png&quot; alt=&quot;Figure 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As you can see, despite having two unrelated random walks, we get a significant relationship most of the time.&lt;/p&gt;

&lt;p&gt;To summarize, cointegration could be a great tool, allowing us to compute the hedge ratio. However, one must ensure the hypothesis of cointegration is met, meaning hypothesis testing on the stationarity of the residuals is required in order to use it. That’s where cointegration’s best friend comes into play: the &lt;strong&gt;stationarity test&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Several stationarity tests exist. They can be used in tandem or on their own. The two main ones are the KPSS and the ADF tests. They allow us to test if a series is likely to be stationary or not. I would advise again to read &lt;a href=&quot;https://civil.colorado.edu/~balajir/CVEN6833/lectures/wwts-book.pdf&quot;&gt;Time series Analysis&lt;/a&gt; if you are looking to go into the maths.&lt;/p&gt;

&lt;p&gt;If say you suceed to find two stock which cointegrated prices, you are then able to construct a stationanry portfolio longing one share of stock A and shorting \rhau share of stock B. You can then can exploid the mean reversion properties of a stationnary process. Meaning, you will short this portfolio when it is bellow its long term mean and short it when its above its long term mean (you actually can greatly improve from this but again, we keep it simple for now).&lt;/p&gt;

&lt;p&gt;When people use these two tools, the process is typically as follows:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Compute the linear regression&lt;/li&gt;
  &lt;li&gt;Perform a stationarity test on the residuals&lt;/li&gt;
  &lt;li&gt;If the residuals are stationary, use the linear regression coefficients to get the hedge ratio&lt;/li&gt;
  &lt;li&gt;Obtain your market-neutral portfolio&lt;/li&gt;
  &lt;li&gt;Create entry and exit thresholds to trade on low/mid-frequency&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach is explained by Gatev et al. in &lt;a href=&quot;https://papers.ssrn.com/sol3/papers.cfm?abstract_id=141615&quot;&gt;Pairs Trading: Performance of a Relative Value Arbitrage Rule&lt;/a&gt;. Trading the spreads is not something I will explain here but known it can be approach with stochastic calculus (OU model,  …).&lt;/p&gt;

&lt;h2 id=&quot;the-pratical-challenges&quot;&gt;The pratical challenges&lt;/h2&gt;

&lt;p&gt;So far, we have a well-documented approach, complete with specified mathematics and models, that should enable us to consistently make money. So, what’s the catch? To generate consistent profits, you need to identify several pairs and trade them. I believe the identification phase is one of the most challenging aspects. If one opts for a brute force approach and applies the Augmented Dickey-Fuller (ADF) test to all possible pairs, the number of false positives will likely skyrocket.&lt;/p&gt;

&lt;p&gt;The hedge against other players is created in this phase. The question then becomes: How will you define your universe? There are many existing stock universes that involve methods such as clustering, setting thresholds on the Hurst exponents of the spreads, and multiple stationarity tests, among others.&lt;/p&gt;

&lt;p&gt;Additionally, there is a second challenge: you should aim to trade pairs with the fastest mean reversion speed. This is also be difficult to achieve and I will leave it an open question for now.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In conclusion, while the theory behind pair trading and market-neutral strategies appears robust, implementing these strategies effectively requires navigating a complex landscape of challenges. Identifying viable pairs, maintaining a truly market-neutral position, and capitalizing on mean reversion speed are just the tip of the iceberg. Each phase, from defining your universe to executing trades, demands rigorous analysis and a critical approach to data. The true test lies not only in the selection and application of models but also in our ability to adapt and refine these strategies in response to evolving market conditions. As we move forward, the subsequent posts will explore more advanced tools and techniques, aiming to enhance our understanding and execution of these sophisticated trading strategies. Stay tuned for a deeper dive into the nuances that can make or break the success of pair trading.&lt;/p&gt;

</content>
    <category term="Personal project" /><category term="Algo Trading" />
  </entry>
  
  <entry>
    <title type="html">A closed-form filter for binary time series</title>
    <link href="https://quants.quest/HiddenMarkovModel/" rel="alternate" type="text/html" />
    <id>https://quants.quest/HiddenMarkovModel</id>
    <published>2023-07-09T00:00:00+00:00</published>
    <updated>2023-07-09T00:00:00+00:00</updated>
    <summary type="html">The aim of this project is to study and benchmark the performance of the &quot;Optimal Particle Filter&quot; introduced by Fanaso and al. in 2021, with the well-known Bootstrap Filter algorithm.</summary>
    <content type="html" xml:base="https://quants.quest/HiddenMarkovModel/">&lt;p&gt;This project is a common work with Raphael Thabut and Eric Vong. It’s a pratical implementation of &lt;a href=&quot;https://www.researchgate.net/publication/352384574_A_closed-form_filter_for_binary_time_series&quot;&gt;A closed-form filter for binary time series&lt;/a&gt; by Fanaso and al.&lt;/p&gt;

&lt;h2 id=&quot;article-presentation&quot;&gt;Article presentation&lt;/h2&gt;

&lt;p&gt;Denoising data is always relevant to perform, as in reality, a lot of observations can be noised due to external effects. Most filtering methods to predict and smooth distributions relies on the assumption of the Gaussian nature of the state-space models. This is because we have closed form filters available. Even for a binary state-space model, we require Monte-Carlo strategies for prediction.&lt;/p&gt;

&lt;p&gt;This article claims that they have found a closed form filter for the dynamic probit models with a gaussian state variable. To do so, they showed that they belong to a class of distribution, the Skew Unified Normal (SUN), whose parameters can be updated with closed expression.&lt;/p&gt;

&lt;p&gt;They then show how the algorithm performs in practice, and how using, the properties of the SUN distribution, allows for online inference for high dimensions.&lt;/p&gt;

&lt;h2 id=&quot;zoom-on-the-financial-application&quot;&gt;Zoom on the financial application&lt;/h2&gt;

&lt;p&gt;The articles gave an application example, using financial time series. Indeed, it focus on the analysis of two times series, the Nikkei 225 (Japanase Stock Index) and the CAC 40 (French Stock Index).&lt;/p&gt;

&lt;p&gt;As the latter opens after the former, one can try to use the cointegration effect between the two time series to obtain relevant predictions. Our data will be composed of :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$x_t$ where $x_t = 1$ if the Nikkei 225 opening has increased between the close value and opening value and $x_t = 0$ otherwise&lt;/li&gt;
  &lt;li&gt;$y_t$ where $y_t = 1$ if the CAC 40 opening has increased between the close value and opening value and $y_t = 0$ otherwise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One important objective for a financial application would be to evaluate $Pr(y_t = 1 \mid x_t)$.&lt;/p&gt;

&lt;p&gt;This can be done using a probit model. We try to infer a binary value given two parameters, the trend of the CAC 40 when the Nikkei 225 opening is negative and the shift in the trend if the Nikkei 225 opening is positive. Mathematically, this means :&lt;/p&gt;

\[P(y_t = 1 \mid x_t) = \Phi[F_t \theta, 1]\]

&lt;p&gt;with the following notations :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$F_t = (1, x_t)$&lt;/li&gt;
  &lt;li&gt;$\theta = (\theta_1, \theta_2)$, $\theta_1$ being the trend and $\theta_2$ the shift&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the case of such an application, the purpose of the methods we describe in this report is to estimate the $\theta$ parameter effectively.&lt;/p&gt;

&lt;h2 id=&quot;the-sun-distribution&quot;&gt;The SUN distribution&lt;/h2&gt;

&lt;p&gt;Gaussian models are omnipresent in mathematical models. They have very strong properties and make models simpler. Although, one important drawback is that real life distribution tends to have some sort of asymetry.&lt;/p&gt;

&lt;p&gt;A first extension of the gaussian models, Skew Normals, has been proposed by Arellano-Valle and Azzalini (1996). Due to the fertility of this formulation, a unifying representation, the Skewed Unifyed Normals, has been proposed by them since 2006.&lt;/p&gt;

&lt;p&gt;Given $\theta \in R^q$, we say that $\theta$ has a unified skew-normal distribution, noted $\theta \sim {SUN}_{q, h}{(\xi, \Omega, \Delta, \gamma, \Gamma)}$, if its density function $\rho{(\theta)}$ is of form:&lt;/p&gt;

\[\phi_q{(\theta - \xi ; \Omega)} \frac{\Phi_{h}{(\gamma + \Delta^T \overline{\Omega}^{-1} \omega^{-1} ({\theta - \xi}); \Gamma - \Delta^T \overline{\Omega}^{-1} \Delta})}{\Phi_h{(\gamma ; \Gamma)}}\]

&lt;p&gt;With:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$\phi_q{(\theta ; \Omega)}$ where $\phi_h$ is the centered gaussian density with covariance $\Omega$ matrix&lt;/li&gt;
  &lt;li&gt;$\Phi_{h}{(\gamma ; \Gamma)}$ where $\Phi_h$ is the centered gaussian cumulative distribution function with covariance $\Gamma$&lt;/li&gt;
  &lt;li&gt;$\Omega = \omega \overline{\Omega} \omega$ and $\overline{\Omega}$ is the correlation matrix&lt;/li&gt;
  &lt;li&gt;$\xi$ controls the location&lt;/li&gt;
  &lt;li&gt;$\omega$ controls the scale&lt;/li&gt;
  &lt;li&gt;$\Delta$ defines the dependance between the covariance matrixes $\Gamma, \overline{\Omega}$&lt;/li&gt;
  &lt;li&gt;$\gamma$ controls the truncature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The term:&lt;/p&gt;

\[\frac{\Phi_{h}(\gamma + \Delta^T \overline{\Omega}^{-1} \omega^{-1} (\theta - \xi) ; \Gamma - \Delta^T \overline{\Omega}^{-1} \Delta)}{\Phi_{h}(\gamma ; \Gamma)}\]

&lt;p&gt;induces the skewness as it is rescaled by the term $\Phi_{h}(\gamma ; \Gamma)$&lt;/p&gt;

&lt;p&gt;We have also the following distribution equality $\theta \overset{(d)} = \xi + \omega (U_0 + \Delta \Gamma^{-1} U_1)$ with $U_0$ independant of $U_1$ and $U_0 \sim N_q{(0, \overline{\Omega} - \Delta \Gamma^{-1} \Delta^T)}, U_1 \sim TN_h{(0, \Gamma, -\gamma)}$ truncated normal law below $-\gamma$. This representation allows for efficient computing, but we can also apply it to a probit model.&lt;/p&gt;

&lt;p&gt;Given $y_t = (y_{1t}, \ldots, y_{mt})^T \in {(0, 1)}^m$ a binary vector and $\theta_t = (\theta_{1t}, \ldots, \theta_{pt})^T \in R^p$ the vectors of parameters. The dynamic probit model is then defined as:  `&lt;/p&gt;

&lt;p&gt;\(p{(y_t \mid \theta_t)} = \Phi_m{(B_t F_t \theta_t ; B_t V_t B_t)}\)
\(\theta_t = G_t \theta_{t-1} + \varepsilon_t, \varepsilon_t \sim N_p{(0, W_t)}\)&lt;/p&gt;

&lt;p&gt;With $\theta_0 \sim N_{p}{(a_0, P_0)}$ with $B_t = \mathrm{diag}{(2y_{1t} - 1, \ldots, 2y_{mt} - 1)}$&lt;/p&gt;

&lt;p&gt;This representation is equivalent to another formulation (Albert and Chib 1993) as followed:&lt;/p&gt;

&lt;p&gt;\(p{(z_t \vert \theta_t)} = \phi_m{(z_t - F_t \theta_t; V_t)}\)
\(\theta_t = G_t \theta_{t-1} + \varepsilon_t, \varepsilon_t \sim N_{p}(0, W_t)\)&lt;/p&gt;

&lt;p&gt;With $y_{it} = 1&lt;em&gt;{z&lt;/em&gt;{it} &amp;gt; 0}$&lt;/p&gt;

&lt;p&gt;Then, under such a dynamic, the first step filtering distribution is:&lt;/p&gt;

\[(\theta_1 \mid y_1) \sim SUN_{p,m}{(\xi_{1 \mid 1}, \Omega_{1 \mid 1}, \Delta_{1 \mid 1}, \gamma_{1 \mid 1}, \Gamma_{1 \mid 1})}\]

&lt;p&gt;With the following parameters:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$\xi_{1 \mid 1} = G_1 a_0$&lt;/li&gt;
  &lt;li&gt;$\Omega_{1 \mid 1} = G_1 P_0 G_1^T + W_1$&lt;/li&gt;
  &lt;li&gt;$\Delta_{1 \mid 1} = \overline{\Omega_{1 \mid 1}} \omega_{1 \mid 1} F_1^T B_1 s_1^{-1}$&lt;/li&gt;
  &lt;li&gt;$\gamma_{1 \mid 1} = s_1^{-1} B_1 F_1 \xi_{1 \mid 1}$&lt;/li&gt;
  &lt;li&gt;$\Gamma_{1 \mid 1} = s_1^{-1} B_1 \times {F_1 \Omega_{1 \mid 1} F_1^T + V_1}B_1 s_1^{-1}$&lt;/li&gt;
  &lt;li&gt;$s_1 = (\mathrm{diag}{(F_1 \Omega_{1 \mid 1}F_1^T + V_1)})^{1/2}$&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More generally, if $(\theta_t \mid y_{1:t-1}) \sim SUN_{p,m(t-1)}(\xi_{t-1 \mid t-1}, \Omega_{t-1 \mid t-1}, \Delta_{t-1 \mid t-1}, \gamma_{t-1 \mid t-1}, \Gamma_{t-1 \mid t-1})$ is the filtering distribution at $t-1$, then the predictive distribution at $t$ is $(\theta_t \mid y_{1:t-1}) \sim SUN_{p,m(t-1)}(\xi_{t \mid t-1}, \Omega_{t \mid t-1}, \Delta_{t \mid t-1}, \gamma_{t \mid t-1}, \Gamma_{t \mid t-1})$ with the following parameters:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$\xi_{t \mid t-1} = G_t \xi_{t-1 \mid t-1}$&lt;/li&gt;
  &lt;li&gt;$\Omega_{t \mid t-1} = G_t \Omega_{t-1 \mid t-1}G_t^T + W_t$&lt;/li&gt;
  &lt;li&gt;$\Delta_{t \mid t-1} = w_{t-1 \mid t-1}^{-1} G_t w_{t -1 \mid t-1} \Delta_{t-1 \mid t-1}$&lt;/li&gt;
  &lt;li&gt;$\gamma_{t \mid t-1} = \gamma_{t-1 \mid t-1}$&lt;/li&gt;
  &lt;li&gt;$\Gamma_{t \mid t-1} = \gamma_{t-1 \mid t-1}$&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And at time $t$, the filtering distribution are defined as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$\xi_{t \mid t} = \xi_{t \mid t-1}$&lt;/li&gt;
  &lt;li&gt;$\Omega_{t \mid t} = \Omega_{t \mid t-1}$&lt;/li&gt;
  &lt;li&gt;$\Delta_{t \mid t} = [\Delta_{t \mid t-1}, \overline{\Omega_{t \mid t}} \omega_{t \mid t} F_t^T B_t s_t^{-1}]$&lt;/li&gt;
  &lt;li&gt;$\gamma_{t \mid t} = [\gamma_{t \mid t-1}^T, \xi_{t \mid t}^T F_t^T B_t s_t^{-T}]$&lt;/li&gt;
  &lt;li&gt;$\Gamma_{t \mid t} = [[A, B], [B, C]]$&lt;/li&gt;
  &lt;li&gt;$A = \Gamma_{t \mid t-1}$&lt;/li&gt;
  &lt;li&gt;$B = s_t^{-1} B_t F_t \omega_{t \mid t} \Delta_{t \mid t-1}$&lt;/li&gt;
  &lt;li&gt;$C = s_t^{-1} B_t(F_t \Omega_{t \mid t} F_t^T + V_t) B_t s_t^{-1}$&lt;/li&gt;
  &lt;li&gt;$s_t = (\mathrm{diag}{F_t \Omega_{t \mid t} F_t^T + V_t})^{1/2}$&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the smoothing, it is available with similar forms of equations.&lt;/p&gt;

&lt;h2 id=&quot;particles-algorithms&quot;&gt;Particles algorithms&lt;/h2&gt;

&lt;p&gt;Particle filters are a mathematical tool used to estimate the state of a system that is described by a set of uncertain variables. It is a type of recursive Bayesian filter that estimates the state of a system by sampling a large number of “particles,” each of which represents a possible state of the system. The particles are weighted according to their likelihood of being the true state of the system, and the weighted average of the particles is used as an estimate of the state. In this section we describe two particles algorithms we used to estimate the parameters of the targeted SUN distribution : the bootstrap filter, and an optimal filter proposed by the researchers.&lt;/p&gt;

&lt;p&gt;To obtain similar results, detailed in the fourth part of the report, we started with the same parameters and used the previously seen properties.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$a_0 = [0, 0]$&lt;/li&gt;
  &lt;li&gt;$P_0 = 3I_2$&lt;/li&gt;
  &lt;li&gt;$V_t = 1$&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;bootstrap-filter&quot;&gt;Bootstrap filter&lt;/h3&gt;

&lt;p&gt;In a bootstrap filter, the state estimates are generated using a bootstrapping process, which involves sampling from the previous estimate of the state distribution with replacement. This means that each sample is drawn from the previous estimate, and the same sample may be drawn multiple times. The new estimate of the state is then obtained by weighting the samples according to their likelihood of being the true state.&lt;/p&gt;

&lt;p&gt;In the specific case of our study, using the properties and the assumptions of the model, we implemented the bootstrap filter by following this pseudo code :&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/HMM_Fig1.png&quot; alt=&quot;Fig 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Where $W_0$ is taken as $W_0 = 0.01 I_2$ (suggested by a graphical search of the maximum for the marginal likelihood computed under different combinations via the analytical formula)&lt;/p&gt;

&lt;h3 id=&quot;independent-and-identically-distributed-sampling&quot;&gt;Independent and identically distributed sampling&lt;/h3&gt;

&lt;p&gt;A first filter is proposed by the researchers in the article. It uses the main properties of the SUN distribution in order to get independent and identically distributed sampling. This algorithm can be described by the following pseudo code :&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/HMM_Fig7.png&quot; alt=&quot;Fig 7&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;optimal-filter&quot;&gt;Optimal filter&lt;/h3&gt;

&lt;p&gt;The optimal filter introduced by the researchers can be described by the following pseudo code, using the equations of the SUN distribution and filtering, we perform the steps :&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/HMM_Fig2.png&quot; alt=&quot;Fig 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Where $G_t = \Gamma = \overline{\Omega} = I_2$ and $\omega = 0.1$, this filter leverages the SUN distribution properties detailed above. With the starting values, we have:&lt;/p&gt;

\[\Gamma = I_2\]

&lt;h2 id=&quot;results-and-conclusion&quot;&gt;Results and Conclusion&lt;/h2&gt;

&lt;p&gt;We decided to focus on the convergence of the algorithms. Plotting the convergence of the models parameter $\theta_1$ and $\theta_2$.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/HMM_Fig3.png&quot; alt=&quot;Fig 3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We observe similar results as the one in the paper :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$\theta_1$ seems to tend towards -0.5&lt;/li&gt;
  &lt;li&gt;$\theta_2$ seems to tend towards 1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One may find the same plot but for the boostrap algorithm in the Appendix. We can see the same convergence results : $\theta_1$ seems to tend towards -0.5, $\theta_2$ seems to tend towards 1.&lt;/p&gt;

&lt;p&gt;In order to compare the accuracy of the algorithms, Fasano et al used the following procedure :&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Compute the corresponding SUN density on a 2000*2000 sized grid of equally spaced values of $\theta_{1t}$ and $\theta_{2t}$ for each $t$ in $1,2,…,97$&lt;/li&gt;
  &lt;li&gt;Compute the marginal distributions of $\theta_{1t}$ (resp. $\theta_{2t}$) by summing over the values of $\theta_{2t}$ (resp. $\theta_{1t}$) and multiplying by the grid step size (this corresponds to approaching the integral of the joint density on one of the two variables by a rectangle method)&lt;/li&gt;
  &lt;li&gt;Run each algorithm 100 with respectively $10^3, 10^4,$ and $ 10^5$ particles&lt;/li&gt;
  &lt;li&gt;Compute the Wasserstein distance between the empirical distribution given by each algorithm and the discretized exact density&lt;/li&gt;
  &lt;li&gt;for each algorithm, take the median of the 100 Wasserstein distance computed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We also used this method, however due to the extensive computing time the methods required. We restrained ourselves to grids of size $100 \times 100$ and only went up to $t=50$. We ended up with the following table :&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Algorithm&lt;/th&gt;
      &lt;th&gt;$\theta_1 \quad (R=10^3)$&lt;/th&gt;
      &lt;th&gt;$\theta_1 \quad (R=10^4)$&lt;/th&gt;
      &lt;th&gt;$\theta_1 \quad (R=10^5)$&lt;/th&gt;
      &lt;th&gt;$\theta_2 \quad (R=10^3)$&lt;/th&gt;
      &lt;th&gt;$\theta_2 \quad (R=10^4)$&lt;/th&gt;
      &lt;th&gt;$\theta_2 \quad (R=10^5)$&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Boostrap&lt;/td&gt;
      &lt;td&gt;0.086&lt;/td&gt;
      &lt;td&gt;0.036&lt;/td&gt;
      &lt;td&gt;0.025&lt;/td&gt;
      &lt;td&gt;0.124&lt;/td&gt;
      &lt;td&gt;0.069&lt;/td&gt;
      &lt;td&gt;0.062&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Optimal&lt;/td&gt;
      &lt;td&gt;0.082&lt;/td&gt;
      &lt;td&gt;0.034&lt;/td&gt;
      &lt;td&gt;0.024&lt;/td&gt;
      &lt;td&gt;0.117&lt;/td&gt;
      &lt;td&gt;0.067&lt;/td&gt;
      &lt;td&gt;0.061&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;We can see that our results are similar to the article’s results, and the conclusions drawn out are the same : although mild, we benefit from a better accuracy with the proposed “optimal” filter than the one we observe when using the classic bootstrap filter.&lt;br /&gt;
“
We also reproduced a bar plot which shows the frequency at which each algorithm dominates the other accross time.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/HMM_Fig4.png&quot; alt=&quot;Fig 4&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can see the “optimal” filter has ranks above the bootstrap filter most of the time: it overperforms the bootstrap filter at frequency 0.59 for $R=10^3$, 0.84 for $R=10^4$, and 0.66 for $R=10^5$.&lt;/p&gt;

&lt;p&gt;We also compared the performance of the algorithms throughout the time window by averaging the wasserstein distance over each of the 100 experiments for each algorithm at each time $t$, the graph below shows the results:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/HMM_Fig5.png&quot; alt=&quot;Fig 5&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can see that the accuracy of both algorithms decreases with time (let it be noted that here a good accuracy is a low accuracy, although this can sound confusing). Of course, we also notice throughout the study that more particles implies better results.&lt;/p&gt;

&lt;p&gt;Finally, and because we are using Monte Carlo methods, we decided to take a look at the variance of our algrithms. We expected a smaller variance for the “optimal” algorithm. To look at the variance of the results, we simulated 100 runs with each algorithm and $10^3$ samples. We then assessed the median variance. We obtained the  following results :&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Algorithm&lt;/th&gt;
      &lt;th&gt;Variance of $\theta_1$&lt;/th&gt;
      &lt;th&gt;Variance of $\theta_2$&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Boostrap&lt;/td&gt;
      &lt;td&gt;0.00525312&lt;/td&gt;
      &lt;td&gt;0.00937037&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Optimal&lt;/td&gt;
      &lt;td&gt;0.00380095&lt;/td&gt;
      &lt;td&gt;0.00727529&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;As expected we have lower variance with the optimal algorithm than the boostrap algorithm. Moreover, we have a relatively small variance : $10^{-3}$ for all coefficients.&lt;/p&gt;

&lt;h2 id=&quot;appendix&quot;&gt;Appendix&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/images/HMM_Fig6.png&quot; alt=&quot;Fig 6&quot; /&gt;&lt;/p&gt;

</content>
    <category term="Quantitative Finance" />
  </entry>
  
  <entry>
    <title type="html">How to cluster time series within a bayesian framework</title>
    <link href="https://quants.quest/BayesianArticle/" rel="alternate" type="text/html" />
    <id>https://quants.quest/BayesianArticle</id>
    <published>2023-07-08T00:00:00+00:00</published>
    <updated>2023-07-08T00:00:00+00:00</updated>
    <summary type="html">Let&apos;s explore a Bayesian framework enhanced by Monte Carlo simulation methods and hidden Markov chains for time series clustering.</summary>
    <content type="html" xml:base="https://quants.quest/BayesianArticle/">&lt;h2 id=&quot;a-model-based-clustering-of-multiple-time-series-algorithm&quot;&gt;A model-based clustering of multiple time-series algorithm&lt;/h2&gt;

&lt;p&gt;This project is a common work with Gabriel Guaquiere. It is a pratical implementation of the methods from &lt;a href=&quot;https://www.researchgate.net/publication/4756297_Model-Based_Clustering_of_Multiple_Time_Series&quot;&gt;Model-Based Clustering of Multiple Time Series&lt;/a&gt; by Frühwirth-Schnatter, and S. Kaufmann.&lt;br /&gt;
You can check the python implementation on my &lt;a href=&quot;https://github.com/Zaltarba/Bayesian_statistics_project.git&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;The purpose of this project is to group a set of time series into different clusters and, in doing so, estimate the statistical model describing the time series of each cluster. To conduct our estimations, we adopt a Bayesian framework and utilize Monte Carlo simulation methods and hidden Markov chains.&lt;/p&gt;

&lt;p&gt;Let $(y_{i,t})$, with $t=1,…,T$, be a multiple time series among N other time series $i=1,…,N$. We assume that these series belong to K different clusters, and that all time series belonging to cluster $k$ are described by the same statistical model with a group-specific parameter, $\theta_k$. The membership to group $k$ for each time series $i$ is initially unknown and is estimated simultaneously with the parameters $\theta_k$. Additionally, we assume that the parameters $\theta_k$ are specific to each cluster.&lt;/p&gt;

&lt;p&gt;We introduce :&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the vector $S = (S_1,S_2,…,S_N)$ where $\forall i \in 1,..,N$ $S_i$ $\in 1,…,K$ indicates the group to which time series $i$ belongs&lt;/li&gt;
  &lt;li&gt;the vector $\phi = (\eta_1, …, \eta_K)$ where $\eta_k$ indicates the proportion of time series belonging to cluster $k$.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using an MCMC algorithm, we will iteratively estimate the vector $S$, followed by the vectors $\theta$ and $\phi$.&lt;/p&gt;

&lt;h2 id=&quot;the-model&quot;&gt;The Model&lt;/h2&gt;

&lt;h3 id=&quot;theoretical-perspective&quot;&gt;Theoretical Perspective&lt;/h3&gt;

&lt;p&gt;For $i = 1,..,N$, the conditional density of $y_i$ given $\theta_{S_i}$ is written as:&lt;/p&gt;

\[p(y_i \mid \theta_{S_i}) = \prod_{t=1,...,T} p(y_{i,t} \mid y_{i,t-1},..,y_{i,0},\theta_{S_i})~~~~~~~~~~~~~~~~~~~~~~(1)\]

&lt;p&gt;Where $p(y_i \mid y_{i,t-1},..,y_{i,0},\theta_{S_i})$ is a known density that depends on the chosen model.&lt;/p&gt;

&lt;p&gt;Therefore,&lt;/p&gt;

\[p(y_i \mid S_i, \theta_1,...,\theta_K) = p(y_i \mid \theta_{S_i})~~~~~~~~~~~~~~~~~~~~~~(2)\]

&lt;p&gt;Next, we establish a probabilistic model for the variable $S = (S_1,..,S_N)$. We assume that $S_1, S_2,..,S_N$ are pairwise independent a priori, and for all $i = 1,..,N$, we define the prior probability $Pr(S_i = k)$, the probability that time series $i$ belongs to cluster $k$. We assume that for each series $i$, we have no prior knowledge of which cluster it belongs to. Hence,&lt;/p&gt;

\[Pr(S_i = k \mid \eta_1,..,\eta_K) = \eta_k~~~~~~~~~~~~~~~~~~~~~~(3)\]

&lt;p&gt;The sizes of the groups $(\eta_1,..,\eta_K)$ are initially unknown and are estimated using the data.&lt;/p&gt;

&lt;h3 id=&quot;the-mcmc-algorithm&quot;&gt;The MCMC Algorithm&lt;/h3&gt;

&lt;p&gt;The estimation of the parameter vector $\psi = (\theta_1,..,\theta_k,\phi,S)$ using MCMC is done in two steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We fix the parameters $(\theta_1,..,\theta_K,\phi)$ and estimate $S$.&lt;/p&gt;

&lt;p&gt;In this step, we will assign a group $k$ to each time series $i$ using the posterior $p(S_i \mid y,\theta_1,..,\theta_K,\phi)$.&lt;/p&gt;

&lt;p&gt;Based on Bayes’ theorem and the above, we know that:&lt;/p&gt;

\[p(S_i = k \mid y,\theta_1,..,\theta_K,\phi) \propto p(y_i \mid \theta_k)Pr(S_i = k \mid \phi)~~~~~~~~~~~~~~~~~~~~~~(4)\]

&lt;p&gt;Using equations (1) and (3), we will calculate this posterior for $k = 1,..,K$, and using Python, we will simulate a draw of $S_i$ and assign it to a group $k$.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We fix the classification $S$ and estimate the parameter vector $(\theta_1,..,\theta_K,\phi)$.&lt;/p&gt;

&lt;p&gt;Conditioned on $S$, the variables $\theta$ and $\phi$ are independent. Since the parameter $\theta_k$ is specific to cluster $k$, we group all time series belonging to group $k$.&lt;/p&gt;

&lt;p&gt;Thus, $\theta_k$ is estimated using the posterior (5) and a Metropolis-Hastings algorithm:&lt;/p&gt;

\[p(\theta_k \mid y,S_1,..,S_N) = \prod_{i : S_i = k} p(\theta_k \mid y_i) = \prod_{i : S_i = k} p(y_i \mid \theta_k)p(\theta_k)~~~~~~~~~~~~~~~~~~~~~~(5)\]

&lt;p&gt;Where the prior $p(\theta_k)$ depends on the chosen model.&lt;/p&gt;

&lt;p&gt;Finally, we estimate $\phi = (\eta_1,..,\eta_k)$ using the posterior (6) and a Metropolis-Hastings algorithm:&lt;/p&gt;

&lt;p&gt;$p(\phi \mid S,y) = p(y \mid S,\phi,\theta_1,..,\theta_K)$&lt;br /&gt;
$= p(y \mid S,\phi,\theta_1,..,\theta_K) \times p(S \mid \phi) \times p(\phi)~~~~~~~~~~~~~~~~~~~~~~(6)$&lt;br /&gt;
$= \prod_{k=1,…,K} \prod_{i : S_i = k} p(y_i \mid \theta_k) \prod_{j = 1,…,N}Pr(S_j \mid \phi)p(\phi)$&lt;/p&gt;

&lt;p&gt;Where the prior distribution of $\phi$ is a Dirichlet distribution (4,..,4).&lt;/p&gt;

&lt;p&gt;We will estimate $\psi = (\theta_1,..,\theta_k,\phi,S)$ by repeating these two steps P times, after initializing $\psi^{0} = (\theta_1^{0},..,\theta_k^{0},\phi^{0},S^{0})$.&lt;/p&gt;

&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;

&lt;p&gt;From a practical point of view, the likelihood of the estimated ARIMAX(p, 0, d) models was calculated using the statsmodels library.&lt;/p&gt;

&lt;p&gt;To avoid a final classification with zero time series in a cluster, we decided to randomly select about ten series in such cases to update the cluster parameters. Otherwise, if the size of a cluster is reduced to zero in the early iterations, the coefficients associated with the model would not be updated.&lt;/p&gt;

&lt;p&gt;The two steps described in the previous section were used for a Gibbs sampling algorithm. For each step, a Metropolis-Hastings algorithm was implemented. A random walk was performed to find the model coefficients, with ten successive iterations for each step. We selected this number based on the results we obtained and taking into account the complexity of the final algorithm.&lt;/p&gt;

&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;

&lt;h3 id=&quot;model-1&quot;&gt;Model 1&lt;/h3&gt;

&lt;p&gt;The first model is an ARMA(1,1) model of the form:&lt;/p&gt;

&lt;p&gt;$y_{i,t} = \alpha_{S_i}y_{i,t-1} + \beta_{S_i}\epsilon_{t-1} + \epsilon_t$&lt;/p&gt;

&lt;p&gt;Here, $\theta_k$ = $(\alpha_k,\beta_k)$, where $\alpha_k$ and $\beta_k$ are the AR(1) and MA(1) parameters, respectively, of the time series belonging to cluster $k$.&lt;/p&gt;

&lt;p&gt;We set $K = 2$ and $N = 100$, and use the following priors:&lt;/p&gt;

&lt;p&gt;$\forall k \in 1,2 : \alpha,\beta \sim \mathcal{N}(0,,\frac{1}{3})\phi \sim \mathcal{D}(4,4)\Pr(S_i = k \mid \eta_1,..,\eta_K) = \eta_k$&lt;/p&gt;

&lt;p&gt;Since $\epsilon_t \sim \mathcal{N}(0,\sigma^2)$, we have:&lt;/p&gt;

&lt;p&gt;$y_{i,t} \mid y_{i,t-1},..,y_{i,0},\theta_{S_i} \sim \mathcal{N}(\alpha_{S_i}y_{i,t-1} + \beta_{S_i}\epsilon_{t-1}, \sigma^2)$&lt;/p&gt;

&lt;p&gt;We are able to calculate the posteriors (4), (5), and (6) and estimate the parameters using the method described in Section 2.&lt;/p&gt;

&lt;p&gt;The results obtained after 5000 iterations are as follows:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Coefficients&lt;/th&gt;
      &lt;th&gt;$\alpha$&lt;/th&gt;
      &lt;th&gt;$\beta$&lt;/th&gt;
      &lt;th&gt;$\sigma^2$&lt;/th&gt;
      &lt;th&gt;Cluster Sizes&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;True Value&lt;/td&gt;
      &lt;td&gt;1 and -0.8&lt;/td&gt;
      &lt;td&gt;0.1 and 0.1&lt;/td&gt;
      &lt;td&gt;0.1 and 0.1&lt;/td&gt;
      &lt;td&gt;80 and 20&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Estimated Value&lt;/td&gt;
      &lt;td&gt;1.00 and 0.81&lt;/td&gt;
      &lt;td&gt;0.08 and 0.11&lt;/td&gt;
      &lt;td&gt;0.09 and 0.10&lt;/td&gt;
      &lt;td&gt;80 and 20&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Error (%)&lt;/td&gt;
      &lt;td&gt;0.03% and 0.91%&lt;/td&gt;
      &lt;td&gt;17.3% and 12.6%&lt;/td&gt;
      &lt;td&gt;0.19% and 0.95%&lt;/td&gt;
      &lt;td&gt;0% and 0%&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Our model successfully assigned each series to its cluster and accurately estimated the $\alpha$ parameter for each cluster. However, it performed less well in estimating the $\beta$ (MA(1)) parameter. Perhaps with a more appropriate prior, the error could have been reduced. The variance of the residuals was estimated with high precision.&lt;/p&gt;

&lt;p&gt;The graphs below illustrate the convergence of the $\alpha$, $\beta$, $\phi$, $\sigma^2$, $S$, and $\phi$ parameters over the iterations for each cluster.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/model1_graph-1.png&quot; alt=&quot;Results for the first model&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It can be observed that the parameters converge to their true values around the 1000th iteration.&lt;/p&gt;

&lt;h2 id=&quot;model-2&quot;&gt;Model 2&lt;/h2&gt;

&lt;p&gt;The second model is an ARMAX(1,1) model of the form:&lt;/p&gt;

&lt;p&gt;$y_{i,t} = \alpha_{S_i}y_{i,t-1} + \beta_{S_i}\epsilon_{t-1} + \gamma_{S_i}x_t + \epsilon_t$&lt;/p&gt;

&lt;p&gt;Here, $\theta_k$ = $(\alpha_k,\beta_k,\gamma_k)$, where $\alpha_k$, $\beta_k$, and $\gamma_k$ are the AR(1), MA(1), and the coefficient for the exogenous variable, respectively, of the time series belonging to cluster $k$. The process $x_t$ is a random walk and is observed.&lt;/p&gt;

&lt;p&gt;We set K = 3 and N = 100, and use the same priors as in Model 1.&lt;/p&gt;

&lt;p&gt;Since $\epsilon_t \sim \mathcal{N}(0,\sigma^2)$, with $\sigma^2$ known, we have:&lt;/p&gt;

&lt;p&gt;$y_{i,t} \mid y_{i,t-1},..,y_{i,0},\theta_{S_i} \sim \mathcal{N}(\alpha_{S_i}y_{i,t-1} + \beta_{S_i}\epsilon_{t-1} + \gamma_{S_i}x_t, \sigma^2)$&lt;/p&gt;

&lt;p&gt;We are able to calculate the posteriors (4), (5), and (6) and estimate the parameters using the method described in Section 2.&lt;/p&gt;

&lt;p&gt;The results obtained after 5000 iterations are as follows:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Coefficients&lt;/th&gt;
      &lt;th&gt;$\alpha$&lt;/th&gt;
      &lt;th&gt;$\beta$&lt;/th&gt;
      &lt;th&gt;$\gamma$&lt;/th&gt;
      &lt;th&gt;$\sigma^2$&lt;/th&gt;
      &lt;th&gt;Cluster Sizes&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;True Value&lt;/td&gt;
      &lt;td&gt;1, -0.8, 0.5&lt;/td&gt;
      &lt;td&gt;0.1, 0.1, 0.5&lt;/td&gt;
      &lt;td&gt;0.1, 0.5, 0.9&lt;/td&gt;
      &lt;td&gt;0.1 0.1 0.1&lt;/td&gt;
      &lt;td&gt;60, 20, 20&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Estimated Value&lt;/td&gt;
      &lt;td&gt;0.99 -0.75 -0.50&lt;/td&gt;
      &lt;td&gt;0.11, 0.03 0.55&lt;/td&gt;
      &lt;td&gt;0.091, 0.497, 0.886&lt;/td&gt;
      &lt;td&gt;0.099 0.097 0.098&lt;/td&gt;
      &lt;td&gt;60, 20, 20&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Error (%)&lt;/td&gt;
      &lt;td&gt;0.07% 6.88% 0.56%&lt;/td&gt;
      &lt;td&gt;14.29% 70.58% 9.35%&lt;/td&gt;
      &lt;td&gt;9.4%, 0.57%, 1.54%&lt;/td&gt;
      &lt;td&gt;0.46% 2.03% 1.32%&lt;/td&gt;
      &lt;td&gt;0%, 0%, 0%&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Our model successfully assigned each series to its cluster, and it accurately estimated the $\alpha$ and $\gamma$ parameters within each cluster. However, it performed less well in estimating the $\beta$ (MA(1)) parameter. Perhaps with a more appropriate prior, the error could have been reduced.&lt;/p&gt;

&lt;p&gt;The graphs below illustrate the convergence of the $\alpha$, $\beta$, $\gamma$, $\phi$, $\sigma^2$, $S$, and $\phi$ parameters over the iterations for each cluster.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/model2_graph-1.png&quot; alt=&quot;Results for the second model&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It can be observed that the parameters converge to their true values around the 1000th iteration.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;By using a Bayesian approach and Monte Carlo methods, we successfully grouped time series into different clusters. We observed that the estimations of the AR parameters were very close to the true values, and our algorithms made no classification errors. However, the estimations of the MA parameters were often less accurate. This difficulty arises from the challenges involved in estimating the parameters specific to ARIMA models. Additionally, we assumed that all parameters follow the same prior distribution&lt;/p&gt;

&lt;h2 id=&quot;bibliography&quot;&gt;Bibliography&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Frühwirth-Schnatter, and S. Kaufmann, (2008). Model-based clustering of multiple time-series, Journal of Business and Economic Statistics, 26, 78 – 89&lt;/li&gt;
&lt;/ol&gt;
</content>
    <category term="Statistics" />
  </entry>
  
</feed>
