<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Brent-WTI Spread | Leon Shpaner</title>
    <link>https://www.leonshpaner.com/tag/brent-wti-spread/</link>
      <atom:link href="https://www.leonshpaner.com/tag/brent-wti-spread/index.xml" rel="self" type="application/rss+xml" />
    <description>Brent-WTI Spread</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>en-us</language><copyright>© Leon Shpaner 2026</copyright><lastBuildDate>Sat, 03 Oct 2026 00:00:00 +0000</lastBuildDate>
    <image>
      <url>https://www.leonshpaner.com/images/icon_hu7311a5e5f4afeb70854f035fe2a04133_865498_512x512_fill_lanczos_center_2.png</url>
      <title>Brent-WTI Spread</title>
      <link>https://www.leonshpaner.com/tag/brent-wti-spread/</link>
    </image>
    
    <item>
      <title>The Relationship Between Market Space and Profit Distribution in Arbitrage</title>
      <link>https://www.leonshpaner.com/concept_papers/marketspace_dynamics/</link>
      <pubDate>Sat, 03 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://www.leonshpaner.com/concept_papers/marketspace_dynamics/</guid>
      <description>

&lt;div id=&#34;TOC&#34;&gt;

&lt;/div&gt;

&lt;script id=&#34;MathJax-script&#34; async src=&#34;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js&#34;&gt;&lt;/script&gt;
&lt;style&gt;
.pdf-link {
  display: inline-flex; align-items: center; padding: 5px 10px;
  border: 1px solid blue; text-decoration: none; color: blue;
  font-family: Arial, sans-serif; font-size: 16px; font-weight: bold;
  transition: background-color 0.3s, color 0.3s;
}
.pdf-link:hover { background-color: blue; color: white; }
.pdf-link svg { margin-right: 5px; fill: blue; transition: fill 0.3s; }
.pdf-link:hover svg { fill: white; }
&lt;/style&gt;
&lt;p&gt;&lt;a href=&#34;../market_space_and_profit_distribution_in_arbitrage.pdf&#34; class=&#34;pdf-link&#34;&gt;
&lt;svg width=&#34;16&#34; height=&#34;16&#34; viewBox=&#34;0 0 24 24&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;
&lt;path d=&#34;M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6zm2 12H8v-2h8v2zm0-4H8v-2h8v2zm-3-5v3h3l-3-3z&#34;/&gt;
&lt;/svg&gt;
PDF
&lt;/a&gt;&lt;/p&gt;
&lt;div id=&#34;table-of-contents&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Table of Contents&lt;/h2&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;a href=&#34;#abstract&#34;&gt;Abstract&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#hypothesis-and-theoretical-framework&#34;&gt;Hypothesis and Theoretical Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#mathematical-framework&#34;&gt;Mathematical Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#market-space-dynamics-in-commodity-trading&#34;&gt;Market Space Dynamics in Commodity Trading&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#practical-implications&#34;&gt;Practical Implications&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#profit-distribution&#34;&gt;Profit Distribution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#arbitrage-opportunities&#34;&gt;Arbitrage Opportunities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#market-efficiency&#34;&gt;Market Efficiency&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#literature-review&#34;&gt;Literature Review&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#geometric-arbitrage-theory&#34;&gt;Geometric Arbitrage Theory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#spatial-price-equilibrium-and-limits-of-arbitrage&#34;&gt;Spatial Price Equilibrium and Limits of Arbitrage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-brent-wti-spread&#34;&gt;The Brent-WTI Spread&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#methods&#34;&gt;Methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#results&#34;&gt;Results&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#limitations&#34;&gt;Limitations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#references&#34;&gt;References&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Appendix
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#appendix-market-space-dynamics-algorithm&#34;&gt;Market Space Dynamics Algorithm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#appendix-marketspacedynamics-class-implementation-in-python&#34;&gt;MarketSpaceDynamics Class Implementation in Python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;abstract&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;Abstract&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;This concept paper proposes that the area of a marketplace, modeled as a non-equilateral triangle, is related to the profit distribution between unequal-sized firms in arbitrage situations. Arbitrage, the practice of exploiting price differences across markets, is a fundamental concept in finance and economics, and most treatments focus on the price discrepancy itself. We introduce a geometric framework, using integral calculus, in which the partition of a triangular market space determines how a profit density is divided among market segments. Under a constant profit density, each segment’s share of profit equals its share of the area, which gives the hypothesis a testable form. As an exploratory illustration, we compare price-volume curves and ARIMA forecasts for NYMEX WTI and ICE Brent crude oil futures from January 2022 to January 2024. The comparison recovers the familiar Brent-WTI price differential, which reflects differences in crude grade and delivery location and therefore carries basis risk. The paper does not yet test the hypothesis formally; we outline the data on firm size and segment-level profits that such a test would require.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Arbitrage, the practice of exploiting price differences in different markets, is central to financial theory. This paper explores the hypothesis that the area of the marketplace, modeled as a non-equilateral triangle, is related to the profit distribution between unequal-sized firms in arbitrage situations. We propose a geometric framework, using integral calculus, to describe how market structure could shape economic interactions and arbitrage opportunities.&lt;/p&gt;
&lt;p&gt;Crude oil illustrates the setting well. The same commodity trades on several exchanges (for example, WTI on NYMEX and Brent on ICE), and the persistent price differential between the two benchmarks has a large literature of its own. We use these two contracts as an exploratory case.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;hypothesis-and-theoretical-framework&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;Hypothesis and Theoretical Framework&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span class=&#34;math inline&#34;&gt;\(H_0\)&lt;/span&gt;: The area of the marketplace, represented as a non-equilateral triangle, has no significant effect on the profit distribution between unequal-sized firms in an arbitrage situation.&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math inline&#34;&gt;\(H_1\)&lt;/span&gt;: The area of the marketplace, represented as a non-equilateral triangle, is significantly related to the profit distribution between unequal-sized firms in an arbitrage situation.&lt;/p&gt;
&lt;p&gt;The theoretical framework draws on geometric modeling and integral calculus, and is motivated by geometric arbitrage theory. The marketplace is modeled as a non-equilateral triangle in a Cartesian coordinate system, where the area of the triangle represents the market space. This representation lets us state how the partition of that space among market segments translates into a partition of profits.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;mathematical-framework&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;Mathematical Framework&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Let the marketplace be represented by a non-equilateral triangle &lt;span class=&#34;math inline&#34;&gt;\(\triangle ABC\)&lt;/span&gt; in a Cartesian plane. Points &lt;span class=&#34;math inline&#34;&gt;\(A\)&lt;/span&gt;, &lt;span class=&#34;math inline&#34;&gt;\(B\)&lt;/span&gt;, and &lt;span class=&#34;math inline&#34;&gt;\(C\)&lt;/span&gt; denote the vertices of the market space, with each side representing a different market boundary.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Figure 1:&lt;/em&gt;&lt;/strong&gt; &lt;span class=&#34;math inline&#34;&gt;\(\triangle ACD\)&lt;/span&gt; represents Market A, and &lt;span class=&#34;math inline&#34;&gt;\(\triangle ADB\)&lt;/span&gt; represents Market B&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;fig1.svg&#34; alt=&#34;&#34; width=&#34;600px&#34; height=&#34;600px&#34; style=&#34;display: block; margin: auto;&#34; /&gt;&lt;/p&gt;
&lt;p&gt;A line segment &lt;span class=&#34;math inline&#34;&gt;\(AD\)&lt;/span&gt;, where &lt;span class=&#34;math inline&#34;&gt;\(D\)&lt;/span&gt; lies on &lt;span class=&#34;math inline&#34;&gt;\(BC\)&lt;/span&gt;, divides the triangle into two segments: Market A (&lt;span class=&#34;math inline&#34;&gt;\(\triangle ACD\)&lt;/span&gt;) and Market B (&lt;span class=&#34;math inline&#34;&gt;\(\triangle ADB\)&lt;/span&gt;). The triangle is positioned on a Cartesian coordinate plane to facilitate the analysis of vertical integration and spatial relationships.&lt;/p&gt;
&lt;p&gt;To quantify the total trade potential within the marketplace, we use the geometric area of &lt;span class=&#34;math inline&#34;&gt;\(\triangle ABC\)&lt;/span&gt;, which represents the market space bounded by firms or segments. A larger area reflects a broader scope for arbitrage activity and profit realization. For a triangle with vertices &lt;span class=&#34;math inline&#34;&gt;\(A = (x_A, y_A)\)&lt;/span&gt;, &lt;span class=&#34;math inline&#34;&gt;\(B = (x_B, y_B)\)&lt;/span&gt;, and &lt;span class=&#34;math inline&#34;&gt;\(C = (x_C, y_C)\)&lt;/span&gt;, the area follows from the determinant (shoelace) formula:&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
    \text{Area}(\triangle ABC) = \frac{1}{2}\left|x_A(y_B-y_C) + x_B(y_C-y_A) + x_C(y_A-y_B)\right|
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Assume the profit in each segment is proportional to its area. Let &lt;span class=&#34;math inline&#34;&gt;\(P_A\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(P_B\)&lt;/span&gt; denote the profits in Market A and Market B:&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
P_A = k \cdot \text{Area}(\triangle ACD)
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
P_B = k \cdot \text{Area}(\triangle ADB)
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;where &lt;span class=&#34;math inline&#34;&gt;\(k\)&lt;/span&gt; is a constant reflecting market conditions and efficiency. It follows that each market’s profit share equals its area share, &lt;span class=&#34;math inline&#34;&gt;\(P_A / (P_A + P_B) = \text{Area}(\triangle ACD) / \text{Area}(\triangle ABC)\)&lt;/span&gt;, independent of &lt;span class=&#34;math inline&#34;&gt;\(k\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;The dividing segment &lt;span class=&#34;math inline&#34;&gt;\(AD\)&lt;/span&gt;, with &lt;span class=&#34;math inline&#34;&gt;\(A = (x_A, y_A)\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(D = (x_D, y_D)\)&lt;/span&gt;, lies on the line&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
    y - y_A = m(x - x_A), \qquad m = \frac{y_D - y_A}{x_D - x_A}
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;provided &lt;span class=&#34;math inline&#34;&gt;\(x_D \neq x_A\)&lt;/span&gt; (if &lt;span class=&#34;math inline&#34;&gt;\(AD\)&lt;/span&gt; is vertical, the line is simply &lt;span class=&#34;math inline&#34;&gt;\(x = x_A\)&lt;/span&gt;). The segment areas follow from the same determinant formula, for example&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
    \text{Area}(\triangle ADB) = \frac{1}{2}\left|x_A(y_D-y_B) + x_D(y_B-y_A) + x_B(y_A-y_D)\right|
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;and, because &lt;span class=&#34;math inline&#34;&gt;\(D\)&lt;/span&gt; lies on &lt;span class=&#34;math inline&#34;&gt;\(BC\)&lt;/span&gt;, the two segments exhaust the market:&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
    \text{Area}(\triangle ABC) = \text{Area}(\triangle ACD) + \text{Area}(\triangle ADB)
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The area can equivalently be written as an iterated integral. Orient the triangle so that &lt;span class=&#34;math inline&#34;&gt;\(BC\)&lt;/span&gt; is the base; then&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
    \text{Area}(\triangle ABC) = \int_{x_C}^{x_B}\left(\int_{y_{\text{bottom}}(x)}^{y_{\text{top}}(x)}dy\right)dx
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;where &lt;span class=&#34;math inline&#34;&gt;\(y_{\text{bottom}}(x)\)&lt;/span&gt; is the line through &lt;span class=&#34;math inline&#34;&gt;\(B\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(C\)&lt;/span&gt;, and &lt;span class=&#34;math inline&#34;&gt;\(y_{\text{top}}(x)\)&lt;/span&gt; is the line through &lt;span class=&#34;math inline&#34;&gt;\(C\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(A\)&lt;/span&gt; for &lt;span class=&#34;math inline&#34;&gt;\(x \le x_A\)&lt;/span&gt; and the line through &lt;span class=&#34;math inline&#34;&gt;\(A\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(B\)&lt;/span&gt; for &lt;span class=&#34;math inline&#34;&gt;\(x \ge x_A\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Now let a profit density &lt;span class=&#34;math inline&#34;&gt;\(p(x,y)\)&lt;/span&gt; be defined over the market space. With the dividing point &lt;span class=&#34;math inline&#34;&gt;\(D\)&lt;/span&gt; directly below &lt;span class=&#34;math inline&#34;&gt;\(A\)&lt;/span&gt; (&lt;span class=&#34;math inline&#34;&gt;\(x_D = x_A\)&lt;/span&gt;), the profits in each market are&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
P_A = \iint_{\triangle ACD} p(x,y)\,dA = \int_{x_C}^{x_D}\int_{y_{\text{bottom}}(x)}^{y_{\text{top}}(x)} p(x,y)\,dy\,dx
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
P_B = \iint_{\triangle ADB} p(x,y)\,dA = \int_{x_D}^{x_B}\int_{y_{\text{bottom}}(x)}^{y_{\text{top}}(x)} p(x,y)\,dy\,dx
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;When &lt;span class=&#34;math inline&#34;&gt;\(p(x,y) = k\)&lt;/span&gt; is constant, these reduce to equations (2) and (3). A non-constant density lets profit concentrate in part of the market space, so area share and profit share can diverge; measuring that divergence is one way to test &lt;span class=&#34;math inline&#34;&gt;\(H_1\)&lt;/span&gt; against data.&lt;/p&gt;
&lt;p&gt;The boundary between the two markets can be parameterized as&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
    \mathbf{r}(t) = (1-t)\mathbf{A} + t\mathbf{D}, \qquad 0 \le t \le 1
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;and the profit density accumulated along that boundary is the line integral&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
    \int_{AD} p(x,y)\,ds = \int_{0}^{1} p(\mathbf{r}(t))\,\lVert\mathbf{r}&amp;#39;(t)\rVert\,dt, \qquad \lVert\mathbf{r}&amp;#39;(t)\rVert = \lVert \mathbf{D} - \mathbf{A} \rVert
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;div id=&#34;when-does-profit-net-to-zero&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;strong&gt;When does profit net to zero?&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Consider a linear profit potential &lt;span class=&#34;math inline&#34;&gt;\(\pi(x,y) = -x + y\)&lt;/span&gt;, in which price (along &lt;span class=&#34;math inline&#34;&gt;\(x\)&lt;/span&gt;) reduces profit and access or demand (along &lt;span class=&#34;math inline&#34;&gt;\(y\)&lt;/span&gt;) increases it. For a linear function over any region, the integral equals the area times the function’s value at the centroid &lt;span class=&#34;math inline&#34;&gt;\((\bar{x}, \bar{y})\)&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
    \iint_{\triangle ABC} (-x + y)\,dA = \text{Area}(\triangle ABC)\,(\bar{y} - \bar{x}), \qquad (\bar{x}, \bar{y}) = \left(\tfrac{x_A + x_B + x_C}{3}, \tfrac{y_A + y_B + y_C}{3}\right)
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The total is zero only when the centroid lies on the line &lt;span class=&#34;math inline&#34;&gt;\(y = x\)&lt;/span&gt;. For the triangle in Figure 2 below, with &lt;span class=&#34;math inline&#34;&gt;\(A=(0,3)\)&lt;/span&gt;, &lt;span class=&#34;math inline&#34;&gt;\(B=(6,0)\)&lt;/span&gt;, &lt;span class=&#34;math inline&#34;&gt;\(C=(-2,0)\)&lt;/span&gt;, the area is 12 and the centroid is &lt;span class=&#34;math inline&#34;&gt;\((4/3, 1)\)&lt;/span&gt;, so the integral equals &lt;span class=&#34;math inline&#34;&gt;\(12 \times (1 - 4/3) = -4\)&lt;/span&gt;. Geometry alone therefore does not force profits to balance. A system-wide balance has to come from an economic assumption, such as no-arbitrage, which constrains the profit density itself. This distinction matters for the empirical section: if a market is efficient in the no-arbitrage sense, persistent price differences between segments should reflect costs and risks (transport, quality, financing) and should not yield riskless profit.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;market-space-dynamics-in-commodity-trading&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;Market Space Dynamics in Commodity Trading&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Consider a simplified commodity market represented as a non-equilateral triangle, where the x-axis represents price and the y-axis represents quantity traded. The triangular market space is bounded by the price limits and the maximum quantity that can be traded.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Figure 2&lt;/em&gt;&lt;/strong&gt;: &lt;span class=&#34;math inline&#34;&gt;\(\triangle ACD\)&lt;/span&gt; represents Market A, and &lt;span class=&#34;math inline&#34;&gt;\(\triangle ADB\)&lt;/span&gt; represents Market B&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;fig2.svg&#34; alt=&#34;&#34; width=&#34;600px&#34; height=&#34;600px&#34; style=&#34;display: block; margin: auto;&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The area of &lt;span class=&#34;math inline&#34;&gt;\(\triangle ADB\)&lt;/span&gt;, with &lt;span class=&#34;math inline&#34;&gt;\(A=(0,3)\)&lt;/span&gt;, &lt;span class=&#34;math inline&#34;&gt;\(D=(0,0)\)&lt;/span&gt;, and &lt;span class=&#34;math inline&#34;&gt;\(B=(6,0)\)&lt;/span&gt;, is&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
    \text{Area}(\triangle ADB) = \frac{1}{2}\times \text{base}\times \text{height} = \frac{1}{2}\times6\times3=9
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The same value follows from integration. The upper edge &lt;span class=&#34;math inline&#34;&gt;\(AB\)&lt;/span&gt; runs from &lt;span class=&#34;math inline&#34;&gt;\((0,3)\)&lt;/span&gt; to &lt;span class=&#34;math inline&#34;&gt;\((6,0)\)&lt;/span&gt;, so its slope is &lt;span class=&#34;math inline&#34;&gt;\(-\tfrac{1}{2}\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(y_{\text{top}}(x) = -\tfrac{1}{2}x + 3\)&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
    \int_{0}^{6} \left(-\frac{1}{2}x+3\right) dx = \left[-\frac{x^2}{4} + 3x\right]_{0}^{6} = -9 + 18 = 9
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For Market A, the edge &lt;span class=&#34;math inline&#34;&gt;\(CA\)&lt;/span&gt; runs from &lt;span class=&#34;math inline&#34;&gt;\((-2,0)\)&lt;/span&gt; to &lt;span class=&#34;math inline&#34;&gt;\((0,3)\)&lt;/span&gt;, so &lt;span class=&#34;math inline&#34;&gt;\(y_{\text{top}}(x) = \tfrac{3}{2}x + 3\)&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
    \text{Area}(\triangle ACD) = \int_{-2}^{0} \left(\frac{3}{2}x+3\right) dx = \left[\frac{3x^2}{4} + 3x\right]_{-2}^{0} = 0 - (3 - 6) = 3
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The total market space is &lt;span class=&#34;math inline&#34;&gt;\(3 + 9 = 12\)&lt;/span&gt;, matching &lt;span class=&#34;math inline&#34;&gt;\(\tfrac{1}{2} \times 8 \times 3\)&lt;/span&gt; for base &lt;span class=&#34;math inline&#34;&gt;\(CB\)&lt;/span&gt;. Under a constant profit density, Market A earns &lt;span class=&#34;math inline&#34;&gt;\(3/12 = 25\%\)&lt;/span&gt; of total profit and Market B earns &lt;span class=&#34;math inline&#34;&gt;\(75\%\)&lt;/span&gt;. This is the quantity &lt;span class=&#34;math inline&#34;&gt;\(H_1\)&lt;/span&gt; concerns: if Market B corresponds to the larger firm, the model predicts a 3:1 profit split driven entirely by the geometry of market access.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;practical-implications&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;Practical Implications&lt;/strong&gt;&lt;/h2&gt;
&lt;div id=&#34;profit-distribution&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;strong&gt;Profit Distribution&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;In the illustration above, profit shares follow directly from area shares. Moving the dividing point &lt;span class=&#34;math inline&#34;&gt;\(D\)&lt;/span&gt; along &lt;span class=&#34;math inline&#34;&gt;\(BC\)&lt;/span&gt; changes the split continuously, which gives a simple way to describe how changes in market access (a new pipeline, an exchange listing, a regulatory change) would redistribute profit between segments. With a non-constant density &lt;span class=&#34;math inline&#34;&gt;\(p(x,y)\)&lt;/span&gt;, the same calculation shows where in price-quantity space the profit is concentrated.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;arbitrage-opportunities&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;strong&gt;Arbitrage Opportunities&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Within this framework, an arbitrage opportunity is a region where realized prices depart from the equilibrium relationship implied by the market space. If observed prices at a given quantity sit persistently above or below that relationship in one segment relative to another, the gap is a candidate opportunity. Whether it is a true arbitrage depends on whether the gap exceeds the cost of moving the commodity or position between segments.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;market-efficiency&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;strong&gt;Market Efficiency&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Under efficiency, those gaps should be no larger than transaction, transport, and risk costs, so the expected excess profit across segments is zero. Section 4 shows this balance is an economic restriction on &lt;span class=&#34;math inline&#34;&gt;\(p(x,y)\)&lt;/span&gt; and does not follow from the triangle’s geometry. The empirical question is therefore whether observed differences between segments exceed what costs and risks can explain.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;literature-review&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;Literature Review&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The relationship between market structure and arbitrage opportunities has a long history in financial and agricultural economics. Much of the arbitrage literature focuses on price discrepancies; geometric and spatial approaches add structure to where those discrepancies arise and who captures them.&lt;/p&gt;
&lt;div id=&#34;geometric-arbitrage-theory&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;strong&gt;Geometric Arbitrage Theory&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Farinelli and Takada (2021) develop Geometric Arbitrage Theory (GAT), which restates classical stochastic finance in the language of differential geometry. Markets are modeled as principal fibre bundles, and the curvature of the bundle’s connection measures instantaneous arbitrage capability. Arbitrage conditions such as No-Free-Lunch-with-Vanishing-Risk (NFLVR) and No-Unbounded-Profit-with-Bounded-Risk (NUPBR) are characterized in geometric terms, and the zero eigenspace of the connection Laplacian parameterizes the risk-neutral measures equivalent to the statistical one. This extends asset bubble theory to markets that do not satisfy NFLVR. The present paper borrows GAT’s motivation, that market geometry carries information about arbitrage, while working with far simpler planar geometry.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;spatial-price-equilibrium-and-limits-of-arbitrage&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;strong&gt;Spatial Price Equilibrium and Limits of Arbitrage&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Samuelson (1952) showed that equilibrium prices across spatially separated markets can be found by solving a linear programming problem, with price differences between connected markets equal to transport costs. This spatial price equilibrium idea is the natural benchmark for the triangle model: segments that are geometrically separated should sustain price gaps up to the cost of crossing between them. Shleifer and Vishny (1997) explain why gaps can persist even beyond those costs, since real arbitrage requires capital and carries risk, and specialized arbitrageurs with limited capital may be unable to close mispricings fully. Both ideas bear on the hypothesis: the size and access of a firm determine how much of a cross-segment gap it can actually capture.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-brent-wti-spread&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;strong&gt;The Brent-WTI Spread&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;The crude oil case connects to a substantial literature on benchmark price differentials. Fattouh (2010) studies the dynamics of crude oil price differentials and finds that differentials between crudes of different quality are generally stationary, consistent with linked markets. Büyükşahin et al. (2013) examine the widening of the WTI-Brent spread after 2010 and relate it to physical market conditions, including inventory build-ups at Cushing, alongside the role of financial traders. Both studies indicate that a nonzero Brent-WTI spread is a normal feature of the market, which shapes how the results below should be read.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;methods&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;Methods&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Daily closing prices and volumes for the front-month NYMEX WTI (CL=F) and ICE Brent (BZ=F) continuous futures were downloaded from Yahoo Finance for January 2022 through December 2023. Series were set to a business-day frequency, missing values were forward filled, and zero-volume days were dropped.&lt;/p&gt;
&lt;p&gt;WTI and Brent volumes differ in scale, and in the raw data their volume ranges overlap on only a handful of days. Each contract’s daily volume was therefore converted to its own percentile rank &lt;span class=&#34;math inline&#34;&gt;\(v \in (0, 1]\)&lt;/span&gt;. For each contract, a price-volume curve was built by sorting observations by volume percentile (averaging prices for tied ranks) and interpolating linearly between them. The area under each curve was computed exactly over the volume-percentile range &lt;span class=&#34;math inline&#34;&gt;\([v_{\min}, v_{\max}]\)&lt;/span&gt; shared by both contracts, then divided by the width of that range:&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[\begin{equation}
    \bar{P} = \frac{1}{v_{\max} - v_{\min}} \int_{v_{\min}}^{v_{\max}} f(v)\,dv
\end{equation}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The normalized area &lt;span class=&#34;math inline&#34;&gt;\(\bar{P}\)&lt;/span&gt; is the average height of the price-volume curve, expressed in dollars per barrel. Because volume percentiles are evenly spaced, each trading day carries equal weight, and &lt;span class=&#34;math inline&#34;&gt;\(\bar{P}\)&lt;/span&gt; is close to the contract’s mean price over the sample. The area representation adds a view of how price varies across low- and high-activity days (Figure 3), while the comparison of &lt;span class=&#34;math inline&#34;&gt;\(\bar{P}\)&lt;/span&gt; across contracts is in effect a comparison of average price levels.&lt;/p&gt;
&lt;p&gt;To extend the comparison forward, a non-seasonal ARIMA model was fit to each closing-price series using a stepwise search over orders up to &lt;span class=&#34;math inline&#34;&gt;\((3, d, 3)\)&lt;/span&gt;, selected by AIC. A seasonal component was not used, since business-day data give no basis for a fixed seasonal period. Each model produced a 60-business-day forecast. Volume is not forecast, so the forecasted comparison uses the mean forecast price for each contract.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;results&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;Results&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Table 1 summarizes the comparison. WTI (CL=F) sits below Brent (BZ=F) on both measures. Across all 518 trading days, Brent averaged $4.68 per barrel above WTI, and the gap stood at $5.39 at the end of 2023.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Table 1:&lt;/em&gt;&lt;/strong&gt; Normalized price-volume areas and mean 60-day forecasts (USD per barrel)&lt;/p&gt;
&lt;style type=&#34;text/css&#34;&gt;
.tg  {border-collapse:collapse;border-spacing:0;margin:0px auto;}
.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
  overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
  font-weight:bold;overflow:hidden;padding:10px 5px;word-break:normal;text-align:left;}
.tg td{text-align:left;vertical-align:top}
.tg-wrap {width: fit-content; margin: 0 auto;}
@media screen and (max-width: 767px) {.tg {width: auto !important;}.tg-wrap {overflow-x: auto;-webkit-overflow-scrolling: touch;margin: auto 0px;}}&lt;/style&gt;
&lt;div class=&#34;tg-wrap&#34;&gt;
&lt;table class=&#34;tg&#34;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;
Measure
&lt;/th&gt;
&lt;th&gt;
WTI (CL=F)
&lt;/th&gt;
&lt;th&gt;
Brent (BZ=F)
&lt;/th&gt;
&lt;th&gt;
Brent minus WTI
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
Normalized area, Jan 2022 to Dec 2023
&lt;/td&gt;
&lt;td&gt;
85.95
&lt;/td&gt;
&lt;td&gt;
90.63
&lt;/td&gt;
&lt;td&gt;
4.68
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
Mean 60-day ARIMA forecast
&lt;/td&gt;
&lt;td&gt;
71.65
&lt;/td&gt;
&lt;td&gt;
77.04
&lt;/td&gt;
&lt;td&gt;
5.39
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Figure 3 shows mean price within 20 equal-width volume-percentile bins for each contract, with dashed lines at the normalized areas reported in Table 1. Brent sits above WTI in all but a few bins, and neither contract shows a consistent relationship between price and relative trading activity, so the area comparison mainly reflects the level difference between the two benchmarks. Figure 4 shows closing prices from January 2022 to January 2024.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Figure 3:&lt;/em&gt;&lt;/strong&gt; Mean Price by Volume Percentile for NYMEX WTI and ICE Brent (January 2022 to January 2024)&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;price_volume_curves.svg&#34; /&gt;&lt;!-- --&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Figure 4:&lt;/em&gt;&lt;/strong&gt; NYMEX WTI and ICE Brent Crude Oil Closing Prices Over Time&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;closing_prices.svg&#34; /&gt;&lt;!-- --&gt;&lt;/p&gt;
&lt;p&gt;The stepwise search selected ARIMA(0,1,0) for both WTI (AIC = 2,373.36) and Brent (AIC = 2,382.71). This is a random walk, so the best forecast of each price is its last observed close, and the 60-day forecasts in Figure 5 are flat at $71.65 for WTI and $77.04 for Brent. The forecast spread of $5.39 is therefore the Brent-WTI spread at the end of 2023. The random-walk result is consistent with weak-form efficiency in both futures markets: past prices alone carried no usable information about the direction of the next move.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Figure 5:&lt;/em&gt;&lt;/strong&gt; NYMEX WTI and ICE Brent Crude Oil 60-Day ARIMA Forecast&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;market_analysis_forecast.svg&#34; /&gt;&lt;!-- --&gt;&lt;/p&gt;
&lt;p&gt;The difference between the two normalized areas is the average Brent-WTI differential across comparable levels of relative trading activity. A long WTI, short Brent position based on this ordering is a spread trade. WTI is a lighter, sweeter crude priced for delivery at Cushing, Oklahoma, while Brent is a waterborne North Sea benchmark, so the spread compensates for quality, location, and transport differences and moves with conditions at both delivery points. Profiting from it requires the spread to narrow, and the position carries basis risk. In the language of the framework, the two contracts occupy different segments of the market space, and the differential is the price of crossing between them. A test of &lt;span class=&#34;math inline&#34;&gt;\(H_1\)&lt;/span&gt; would ask whether firms with greater access to both segments (for example, integrated producers or traders with shipping capacity) capture a larger share of that differential than smaller firms.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;Limitations&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Several limitations apply. The triangle model simplifies market dynamics, and the assumption that market space is well represented by a non-equilateral triangle may not hold. The hypothesis concerns unequal-sized firms, but this paper uses only exchange-level price and volume data and does not measure firm size or firm-level profits, so &lt;span class=&#34;math inline&#34;&gt;\(H_0\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(H_1\)&lt;/span&gt; are not formally tested here.&lt;/p&gt;
&lt;p&gt;The empirical illustration has its own constraints. Continuous front-month futures series contain roll effects in both price and volume. Converting volume to percentiles makes the two contracts comparable but discards information about absolute trading activity, so the analysis cannot speak to how the size of a market affects pricing. The price-volume curve treats volume as an ordering variable and ignores time, so it does not capture how the price-volume relationship shifts over the sample. The ARIMA forecasts reduce to random walks and were not evaluated out of sample, so they serve only as a forward extension of the end-of-sample spread. Finally, the comparison ignores transaction, financing, and transport costs, which determine whether any observed differential is exploitable.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;This paper represents market space as a non-equilateral triangle and shows that, under a constant profit density, each segment’s profit share equals its area share. The worked example yields a 3:1 split from geometry alone, and the framework makes clear that system-wide profit balance must come from an economic assumption such as no-arbitrage, which constrains the profit density beyond what the geometry provides.&lt;/p&gt;
&lt;p&gt;The crude oil illustration recovers the Brent-WTI differential, which the literature attributes to quality, location, and physical market conditions. The natural next step is a formal test of &lt;span class=&#34;math inline&#34;&gt;\(H_1\)&lt;/span&gt; using firm-level data, for example comparing how integrated and non-integrated firms capture cross-market differentials. Further extensions include estimating non-constant profit densities from transaction data, accounting for transport and financing costs, and evaluating forecasts out of sample.&lt;/p&gt;
&lt;hr /&gt;
&lt;/div&gt;
&lt;div id=&#34;references&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Büyükşahin, B., Lee, T. K., Moser, J. T., &amp;amp; Robe, M. A. (2013). Physical markets, paper markets and the WTI-Brent spread. &lt;em&gt;The Energy Journal, 34&lt;/em&gt;(3), 129–151.&lt;/p&gt;
&lt;p&gt;Farinelli, S., &amp;amp; Takada, H. (2021). Can you hear the shape of a market? Geometric arbitrage and spectral theory. &lt;em&gt;Axioms, 10&lt;/em&gt;(4), 242. &lt;a href=&#34;https://doi.org/10.3390/axioms10040242&#34; class=&#34;uri&#34;&gt;https://doi.org/10.3390/axioms10040242&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Fattouh, B. (2010). The dynamics of crude oil price differentials. &lt;em&gt;Energy Economics, 32&lt;/em&gt;(2), 334–342.&lt;/p&gt;
&lt;p&gt;Samuelson, P. A. (1952). Spatial price equilibrium and linear programming. &lt;em&gt;The American Economic Review, 42&lt;/em&gt;(3), 283–303.&lt;/p&gt;
&lt;p&gt;Shleifer, A., &amp;amp; Vishny, R. W. (1997). The limits of arbitrage. &lt;em&gt;The Journal of Finance, 52&lt;/em&gt;(1), 35–55.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix-market-space-dynamics-algorithm&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;Appendix: Market Space Dynamics Algorithm&lt;/strong&gt;&lt;/h2&gt;
&lt;style&gt;
.algorithm { font-family: monospace; margin: 0; padding: 0; line-height: 1.4; font-size: 12px;}
.algorithm b { font-weight: bold; }
.algorithm i { font-style: italic; }
.algorithm .top-border{ border-top: 2px solid black; padding: 0; }
&lt;/style&gt;
&lt;div class=&#34;algorithm&#34;&gt;
&lt;div class=&#34;top-border&#34;&gt;
&lt;b&gt;Algorithm 1&lt;/b&gt; Market Space Dynamics Analysis
&lt;div class=&#34;top-border&#34;&gt;

&lt;/div&gt;
&lt;pre&gt;
 &lt;b&gt;1:&lt;/b&gt;  &lt;b&gt;Input:&lt;/b&gt; Historical price and volume data for each security
 &lt;b&gt;2:&lt;/b&gt;  &lt;b&gt;Output:&lt;/b&gt; Normalized areas, forecasts, and price-differential summary

 &lt;b&gt;3:&lt;/b&gt;  &lt;b&gt;Step 1:&lt;/b&gt; Data Collection and Cleaning
 &lt;b&gt;4:&lt;/b&gt;      Download daily close and volume; set business-day frequency
 &lt;b&gt;5:&lt;/b&gt;      Forward fill missing values; drop zero-volume days
 &lt;b&gt;5a:&lt;/b&gt;     Convert each security&#39;s volume to its own percentile rank

 &lt;b&gt;6:&lt;/b&gt;  &lt;b&gt;Step 2:&lt;/b&gt; Build Price-Volume Curves
 &lt;b&gt;7:&lt;/b&gt;      &lt;b&gt;for&lt;/b&gt; each security &lt;b&gt;do&lt;/b&gt;
 &lt;b&gt;8:&lt;/b&gt;          Sort observations by volume percentile; average prices at tied ranks
 &lt;b&gt;9:&lt;/b&gt;          &lt;i&gt;f&lt;sub&gt;security&lt;/sub&gt;(v)&lt;/i&gt; = linear interpolation of price on volume percentile
 &lt;b&gt;10:&lt;/b&gt;     &lt;b&gt;end for&lt;/b&gt;

 &lt;b&gt;11:&lt;/b&gt;  &lt;b&gt;Step 3:&lt;/b&gt; Normalized Areas
 &lt;b&gt;12:&lt;/b&gt;      [&lt;i&gt;v&lt;sub&gt;min&lt;/sub&gt;&lt;/i&gt;, &lt;i&gt;v&lt;sub&gt;max&lt;/sub&gt;&lt;/i&gt;] = volume-percentile range shared by every security
 &lt;b&gt;13:&lt;/b&gt;      &lt;b&gt;for&lt;/b&gt; each security &lt;b&gt;do&lt;/b&gt;
 &lt;b&gt;14:&lt;/b&gt;          &lt;i&gt;area&lt;/i&gt; = ∫&lt;sub&gt;v&lt;sub&gt;min&lt;/sub&gt;&lt;/sub&gt;&lt;sup&gt;v&lt;sub&gt;max&lt;/sub&gt;&lt;/sup&gt; &lt;i&gt;f&lt;sub&gt;security&lt;/sub&gt;(v)&lt;/i&gt; dv   (exact trapezoid over knots)
 &lt;b&gt;15:&lt;/b&gt;          &lt;i&gt;P̄&lt;sub&gt;security&lt;/sub&gt;&lt;/i&gt; = &lt;i&gt;area&lt;/i&gt; / (&lt;i&gt;v&lt;sub&gt;max&lt;/sub&gt;&lt;/i&gt; − &lt;i&gt;v&lt;sub&gt;min&lt;/sub&gt;&lt;/i&gt;)
 &lt;b&gt;16:&lt;/b&gt;      &lt;b&gt;end for&lt;/b&gt;

 &lt;b&gt;17:&lt;/b&gt;  &lt;b&gt;Step 4:&lt;/b&gt; Forecast
 &lt;b&gt;18:&lt;/b&gt;      &lt;b&gt;for&lt;/b&gt; each security &lt;b&gt;do&lt;/b&gt;
 &lt;b&gt;19:&lt;/b&gt;          Fit non-seasonal ARIMA by stepwise AIC search
 &lt;b&gt;20:&lt;/b&gt;          Forecast &lt;i&gt;h&lt;/i&gt; business days; record mean forecast price
 &lt;b&gt;21:&lt;/b&gt;      &lt;b&gt;end for&lt;/b&gt;

 &lt;b&gt;22:&lt;/b&gt;  &lt;b&gt;Step 5:&lt;/b&gt; Compare
 &lt;b&gt;23:&lt;/b&gt;      Identify lowest and highest &lt;i&gt;P̄&lt;/i&gt; and the spread between them
 &lt;b&gt;24:&lt;/b&gt;      Repeat using mean forecast prices

 &lt;b&gt;25:&lt;/b&gt;  &lt;b&gt;Step 6:&lt;/b&gt; Plot binned price by volume percentile, closing prices, and forecasts
 &lt;b&gt;26:&lt;/b&gt;  &lt;b&gt;End Algorithm&lt;/b&gt;
&lt;div class=&#39;top-border&#39;&gt;&lt;/div&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix-marketspacedynamics-class-implementation-in-python&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;strong&gt;Appendix: MarketSpaceDynamics Class Implementation in Python&lt;/strong&gt;&lt;/h2&gt;
&lt;!-- HTML generated using hilite.me --&gt;
&lt;div style=&#34;background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;&#34;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style=&#34;margin: 0; line-height: 125%&#34;&gt;  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&#34;margin: 0; line-height: 125%&#34;&gt;&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;&#34;&#34;MarketSpaceDynamics: price-volume area comparison and ARIMA forecast.&lt;/span&gt;

&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;Run as a script to regenerate the figures and Table 1 values for the paper:&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;    python market_space_dynamics.py&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;&#34;&#34;&lt;/span&gt;

&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color: #0E84B5; font-weight: bold&#34;&gt;numpy&lt;/span&gt; &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color: #0E84B5; font-weight: bold&#34;&gt;np&lt;/span&gt;
&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color: #0E84B5; font-weight: bold&#34;&gt;pandas&lt;/span&gt; &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color: #0E84B5; font-weight: bold&#34;&gt;pd&lt;/span&gt;
&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color: #0E84B5; font-weight: bold&#34;&gt;matplotlib&lt;/span&gt;

matplotlib&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;use(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Agg&#34;&lt;/span&gt;)
&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color: #0E84B5; font-weight: bold&#34;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color: #0E84B5; font-weight: bold&#34;&gt;plt&lt;/span&gt;
&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color: #0E84B5; font-weight: bold&#34;&gt;yfinance&lt;/span&gt; &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color: #0E84B5; font-weight: bold&#34;&gt;yf&lt;/span&gt;
&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color: #0E84B5; font-weight: bold&#34;&gt;pmdarima&lt;/span&gt; &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;import&lt;/span&gt; auto_arima


&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color: #B06; font-weight: bold&#34;&gt;MarketSpaceDynamics&lt;/span&gt;:
    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;__init__&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;, tickers, start_date, end_date, forecast_steps&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;60&lt;/span&gt;, labels&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;None&lt;/span&gt;):
        &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tickers &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; tickers
        &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;start_date &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; start_date
        &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;end_date &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; end_date
        &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;forecast_steps &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; forecast_steps
        &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;labels &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; labels &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;if&lt;/span&gt; labels &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;None&lt;/span&gt; &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;else&lt;/span&gt; {t: t &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; t &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; tickers}
        &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; {}
        &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;fetch_data()

    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;fetch_data&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;):
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; ticker &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tickers:
            raw &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; yf&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;download(
                ticker,
                start&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;start_date,
                end&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;end_date,
                auto_adjust&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;False&lt;/span&gt;,
                progress&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;False&lt;/span&gt;,
            )
            &lt;span style=&#34;color: #888&#34;&gt;# Recent yfinance versions return MultiIndex columns even for one ticker&lt;/span&gt;
            &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;isinstance&lt;/span&gt;(raw&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;columns, pd&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;MultiIndex):
                raw&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;columns &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; raw&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;columns&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;get_level_values(&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;0&lt;/span&gt;)
            df &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; raw[[&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Close&#34;&lt;/span&gt;, &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Volume&#34;&lt;/span&gt;]]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;asfreq(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;B&#34;&lt;/span&gt;)&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;ffill()
            &lt;span style=&#34;color: #888&#34;&gt;# Drop zero-volume rows (holidays, roll artifacts)&lt;/span&gt;
            df &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; df[df[&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Volume&#34;&lt;/span&gt;] &lt;span style=&#34;color: #333&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;rename(columns&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;{&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Close&#34;&lt;/span&gt;: &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Price&#34;&lt;/span&gt;})
            &lt;span style=&#34;color: #888&#34;&gt;# Volume scales differ across exchanges, so each contract&#39;s volume&lt;/span&gt;
            &lt;span style=&#34;color: #888&#34;&gt;# is expressed as its own percentile rank (0 to 1). Both curves then&lt;/span&gt;
            &lt;span style=&#34;color: #888&#34;&gt;# share the same axis and every trading day contributes.&lt;/span&gt;
            df[&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;VolPct&#34;&lt;/span&gt;] &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; df[&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Volume&#34;&lt;/span&gt;]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;rank(pct&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;True&lt;/span&gt;)
            &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data[ticker] &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; df

    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;volume_range&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;):
        &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;&#34;&#34;Full span of volume percentile across all tickers (used for plotting).&#34;&#34;&#34;&lt;/span&gt;
        lo &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;min&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data[t][&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;VolPct&#34;&lt;/span&gt;]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;min() &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; t &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tickers)
        hi &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;max&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data[t][&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;VolPct&#34;&lt;/span&gt;]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;max() &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; t &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tickers)
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;float&lt;/span&gt;(lo), &lt;span style=&#34;color: #007020&#34;&gt;float&lt;/span&gt;(hi)

    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;overlap_range&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;):
        &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;&#34;&#34;Volume range observed for every ticker (used for areas).&lt;/span&gt;

&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        Outside a ticker&#39;s own observed range, np.interp holds the end value&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        flat, so integrating over the full span would let one boundary price&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        dominate the area. Restricting to the overlap avoids that.&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        &#34;&#34;&#34;&lt;/span&gt;
        lo &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;max&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data[t][&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;VolPct&#34;&lt;/span&gt;]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;min() &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; t &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tickers)
        hi &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;min&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data[t][&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;VolPct&#34;&lt;/span&gt;]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;max() &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; t &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tickers)
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;if&lt;/span&gt; hi &lt;span style=&#34;color: #333&#34;&gt;&amp;lt;=&lt;/span&gt; lo:
            &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;raise&lt;/span&gt; ValueError(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Volume ranges do not overlap; areas are not comparable.&#34;&lt;/span&gt;)
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;float&lt;/span&gt;(lo), &lt;span style=&#34;color: #007020&#34;&gt;float&lt;/span&gt;(hi)

    &lt;span style=&#34;color: #555; font-weight: bold&#34;&gt;@staticmethod&lt;/span&gt;
    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;price_volume_curve&lt;/span&gt;(df):
        &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;&#34;&#34;Mean price at each volume percentile, sorted by percentile.&lt;/span&gt;

&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        np.interp requires increasing x values, so the series is sorted by&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        volume percentile and tied percentiles are averaged.&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        &#34;&#34;&#34;&lt;/span&gt;
        curve &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; df&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;groupby(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;VolPct&#34;&lt;/span&gt;)[&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Price&#34;&lt;/span&gt;]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;mean()&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;sort_index()
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;return&lt;/span&gt; curve&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;index&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;to_numpy(dtype&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #007020&#34;&gt;float&lt;/span&gt;), curve&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;to_numpy(dtype&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #007020&#34;&gt;float&lt;/span&gt;)

    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;price_volume_function&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;, df):
        xp, fp &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;price_volume_curve(df)
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;lambda&lt;/span&gt; x: np&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;interp(x, xp, fp)

    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;calculate_area&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;, df, lower_limit, upper_limit):
        &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;&#34;&#34;Exact integral of the piecewise-linear price-volume curve.&lt;/span&gt;

&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        The trapezoid rule is exact for a piecewise-linear function when it is&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        evaluated at every knot, so no numerical quadrature is needed.&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        &#34;&#34;&#34;&lt;/span&gt;
        xp, fp &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;price_volume_curve(df)
        inside &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; xp[(xp &lt;span style=&#34;color: #333&#34;&gt;&amp;gt;&lt;/span&gt; lower_limit) &lt;span style=&#34;color: #333&#34;&gt;&amp;amp;&lt;/span&gt; (xp &lt;span style=&#34;color: #333&#34;&gt;&amp;lt;&lt;/span&gt; upper_limit)]
        x &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; np&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;concatenate([[lower_limit], inside, [upper_limit]])
        y &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; np&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;interp(x, xp, fp)
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;float&lt;/span&gt;(np&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;sum((x[&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;:] &lt;span style=&#34;color: #333&#34;&gt;-&lt;/span&gt; x[:&lt;span style=&#34;color: #333&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;]) &lt;span style=&#34;color: #333&#34;&gt;*&lt;/span&gt; (y[&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;:] &lt;span style=&#34;color: #333&#34;&gt;+&lt;/span&gt; y[:&lt;span style=&#34;color: #333&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;]) &lt;span style=&#34;color: #333&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;2&lt;/span&gt;))

    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;normalized_areas&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;):
        &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;&#34;&#34;Area under each price-volume curve divided by the volume range.&lt;/span&gt;

&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        This equals the average height of the curve over the overlapping&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        volume range, so the result is in price units.&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        &#34;&#34;&#34;&lt;/span&gt;
        lo, hi &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;overlap_range()
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;return&lt;/span&gt; {
            t: &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;calculate_area(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data[t], lo, hi)
            &lt;span style=&#34;color: #333&#34;&gt;/&lt;/span&gt; (hi &lt;span style=&#34;color: #333&#34;&gt;-&lt;/span&gt; lo)
            &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; t &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tickers
        }

    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;forecast_prices&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;, df, steps):
        &lt;span style=&#34;color: #888&#34;&gt;# Pass plain values: dropping zero-volume days leaves gaps in the&lt;/span&gt;
        &lt;span style=&#34;color: #888&#34;&gt;# date index, which statsmodels cannot forecast from.&lt;/span&gt;
        model &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; auto_arima(
            df[&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Price&#34;&lt;/span&gt;]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;to_numpy(dtype&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #007020&#34;&gt;float&lt;/span&gt;),
            start_p&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;,
            start_q&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;,
            max_p&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;3&lt;/span&gt;,
            max_q&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;3&lt;/span&gt;,
            seasonal&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;False&lt;/span&gt;,  &lt;span style=&#34;color: #888&#34;&gt;# no justified 12-period season in business-day data&lt;/span&gt;
            stepwise&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;True&lt;/span&gt;,
            suppress_warnings&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;True&lt;/span&gt;,
            trace&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;False&lt;/span&gt;,
        )
        forecast &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; np&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;asarray(model&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;predict(n_periods&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;steps))
        index &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; pd&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;bdate_range(df&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;index[&lt;span style=&#34;color: #333&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color: #333&#34;&gt;+&lt;/span&gt; pd&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;Timedelta(days&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;), periods&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;steps)
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;return&lt;/span&gt; pd&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;DataFrame({&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Forecast&#34;&lt;/span&gt;: forecast}, index&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;index), model

    &lt;span style=&#34;color: #555; font-weight: bold&#34;&gt;@staticmethod&lt;/span&gt;
    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;compare&lt;/span&gt;(values):
        low &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;min&lt;/span&gt;(values, key&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;values&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;get)
        high &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;max&lt;/span&gt;(values, key&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;values&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;get)
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;return&lt;/span&gt; {
            &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;low&#34;&lt;/span&gt;: (low, values[low]),
            &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;high&#34;&lt;/span&gt;: (high, values[high]),
            &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;spread&#34;&lt;/span&gt;: values[high] &lt;span style=&#34;color: #333&#34;&gt;-&lt;/span&gt; values[low],
        }

    &lt;span style=&#34;color: #888&#34;&gt;# ---------- plots ----------&lt;/span&gt;
    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;plot_price_volume_curves&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;, path&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;None&lt;/span&gt;, n_bins&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;20&lt;/span&gt;):
        &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;&#34;&#34;Binned price-volume curves with each contract&#39;s normalized area.&lt;/span&gt;

&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        Daily points are too noisy to read, so prices are averaged within&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        equal-width volume-percentile bins. Dashed lines mark the normalized&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        areas used in Table 1.&lt;/span&gt;
&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;        &#34;&#34;&#34;&lt;/span&gt;
        areas &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;normalized_areas()
        edges &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; np&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;linspace(&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;, n_bins &lt;span style=&#34;color: #333&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;)
        mids &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; (edges[:&lt;span style=&#34;color: #333&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color: #333&#34;&gt;+&lt;/span&gt; edges[&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;:]) &lt;span style=&#34;color: #333&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;2&lt;/span&gt;
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;figure(figsize&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;(&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;6&lt;/span&gt;))
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; i, t &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;enumerate&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tickers):
            df &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data[t]
            binned &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; df&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;groupby(pd&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;cut(df[&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;VolPct&#34;&lt;/span&gt;], edges, include_lowest&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;True&lt;/span&gt;),
                                observed&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;False&lt;/span&gt;)[&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Price&#34;&lt;/span&gt;]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;mean()&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;to_numpy()
            color &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;f&#34;C{&lt;/span&gt;i&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;}&#34;&lt;/span&gt;
            plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;plot(mids, binned, marker&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;o&#34;&lt;/span&gt;, color&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;color, label&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;labels[t])
            plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;axhline(areas[t], color&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;color, linestyle&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;--&#34;&lt;/span&gt;, linewidth&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;,
                        label&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;f&#34;{&lt;/span&gt;&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;labels[t]&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;} normalized area ({&lt;/span&gt;areas[t]&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;:.2f})&#34;&lt;/span&gt;)
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;xlabel(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Volume percentile&#34;&lt;/span&gt;)
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;ylabel(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Mean price (USD)&#34;&lt;/span&gt;)
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;title(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Price by Volume Percentile&#34;&lt;/span&gt;)
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;legend()
        &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;_finish(path)

    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;plot_closing_prices&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;, path&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;None&lt;/span&gt;):
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;figure(figsize&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;(&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;6&lt;/span&gt;))
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; t &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tickers:
            plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;plot(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data[t]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;index, &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data[t][&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Price&#34;&lt;/span&gt;], label&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;labels[t])
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;xlabel(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Date&#34;&lt;/span&gt;)
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;ylabel(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Price (USD)&#34;&lt;/span&gt;)
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;title(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Closing Prices Over Time&#34;&lt;/span&gt;)
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;legend()
        &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;_finish(path)

    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;plot_forecasts&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;, forecasts, path&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;None&lt;/span&gt;):
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;figure(figsize&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;(&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;6&lt;/span&gt;))
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; i, t &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;enumerate&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tickers):
            color &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;f&#34;C{&lt;/span&gt;i&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;}&#34;&lt;/span&gt;  &lt;span style=&#34;color: #888&#34;&gt;# same color per contract as Figure 4&lt;/span&gt;
            plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;plot(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data[t]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;index, &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data[t][&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Price&#34;&lt;/span&gt;], color&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;color,
                     label&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;f&#34;{&lt;/span&gt;&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;labels[t]&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;} Historical&#34;&lt;/span&gt;)
            plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;plot(forecasts[t]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;index, forecasts[t][&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Forecast&#34;&lt;/span&gt;], color&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;color,
                     linestyle&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;--&#34;&lt;/span&gt;, label&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;f&#34;{&lt;/span&gt;&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;labels[t]&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;} Forecast&#34;&lt;/span&gt;)
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;xlabel(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Date&#34;&lt;/span&gt;)
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;ylabel(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Price (USD)&#34;&lt;/span&gt;)
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;title(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;f&#34;{&lt;/span&gt;&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;forecast_steps&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;}-Day ARIMA Forecast&#34;&lt;/span&gt;)
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;legend()
        &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;_finish(path)

    &lt;span style=&#34;color: #555; font-weight: bold&#34;&gt;@staticmethod&lt;/span&gt;
    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;_finish&lt;/span&gt;(path):
        plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tight_layout()
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;if&lt;/span&gt; path:
            plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;savefig(path)
            plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;close()
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;else&lt;/span&gt;:
            plt&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;show()

    &lt;span style=&#34;color: #888&#34;&gt;# ---------- driver ----------&lt;/span&gt;
    &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color: #06B; font-weight: bold&#34;&gt;run_analysis&lt;/span&gt;(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;, save_figures&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;False&lt;/span&gt;):
        current &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;compare(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;normalized_areas())

        forecasts, models &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; {}, {}
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; t &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tickers:
            forecasts[t], models[t] &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;forecast_prices(&lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data[t], &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;forecast_steps)
        forecasted &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;compare({t: &lt;span style=&#34;color: #007020&#34;&gt;float&lt;/span&gt;(forecasts[t][&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Forecast&#34;&lt;/span&gt;]&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;mean())
                                   &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; t &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tickers})

        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;if&lt;/span&gt; save_figures:
            &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;plot_price_volume_curves(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;price_volume_curves.svg&#34;&lt;/span&gt;)
            &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;plot_closing_prices(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;closing_prices.svg&#34;&lt;/span&gt;)
            &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;plot_forecasts(forecasts, &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;market_analysis_forecast.svg&#34;&lt;/span&gt;)

        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; name, res &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; [(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Current (normalized area)&#34;&lt;/span&gt;, current),
                          (&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;Forecasted (mean forecast price)&#34;&lt;/span&gt;, forecasted)]:
            &lt;span style=&#34;color: #007020&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;f&#34;{&lt;/span&gt;name&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;}:&#34;&lt;/span&gt;)
            &lt;span style=&#34;color: #007020&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;f&#34;  Lower: {&lt;/span&gt;res[&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#39;low&#39;&lt;/span&gt;][&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;} = {&lt;/span&gt;res[&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#39;low&#39;&lt;/span&gt;][&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;]&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;:.2f}&#34;&lt;/span&gt;)
            &lt;span style=&#34;color: #007020&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;f&#34;  Higher: {&lt;/span&gt;res[&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#39;high&#39;&lt;/span&gt;][&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;} = {&lt;/span&gt;res[&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#39;high&#39;&lt;/span&gt;][&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;1&lt;/span&gt;]&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;:.2f}&#34;&lt;/span&gt;)
            &lt;span style=&#34;color: #007020&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;f&#34;  Spread: {&lt;/span&gt;res[&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#39;spread&#39;&lt;/span&gt;]&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;:.2f}&#34;&lt;/span&gt;)
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; t, m &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; models&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;items():
            &lt;span style=&#34;color: #007020&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;f&#34;{&lt;/span&gt;t&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;}: ARIMA{&lt;/span&gt;m&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;order&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;}, AIC = {&lt;/span&gt;m&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;aic()&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;:.2f}&#34;&lt;/span&gt;)

        lo, hi &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;overlap_range()
        &lt;span style=&#34;color: #007020&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;f&#34;Overlapping volume-percentile range: {&lt;/span&gt;lo&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;:.3f} to {&lt;/span&gt;hi&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;:.3f}&#34;&lt;/span&gt;)
        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;for&lt;/span&gt; t &lt;span style=&#34;color: #000; font-weight: bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;tickers:
            v &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;data[t][&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;VolPct&#34;&lt;/span&gt;]
            n_in &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color: #007020&#34;&gt;int&lt;/span&gt;(((v &lt;span style=&#34;color: #333&#34;&gt;&amp;gt;=&lt;/span&gt; lo) &lt;span style=&#34;color: #333&#34;&gt;&amp;amp;&lt;/span&gt; (v &lt;span style=&#34;color: #333&#34;&gt;&amp;lt;=&lt;/span&gt; hi))&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;sum())
            &lt;span style=&#34;color: #007020&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;f&#34;  {&lt;/span&gt;t&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;}: {&lt;/span&gt;n_in&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;} of {&lt;/span&gt;&lt;span style=&#34;color: #007020&#34;&gt;len&lt;/span&gt;(v)&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;} days inside the overlap&#34;&lt;/span&gt;)

        &lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;return&lt;/span&gt; current, forecasted, forecasts, models


&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;if&lt;/span&gt; __name__ &lt;span style=&#34;color: #333&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;__main__&#34;&lt;/span&gt;:
    labels &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;CL=F&#34;&lt;/span&gt;: &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;NYMEX WTI Crude Oil&#34;&lt;/span&gt;, &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;BZ=F&#34;&lt;/span&gt;: &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;ICE Brent Crude Oil&#34;&lt;/span&gt;}
    analysis &lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt; MarketSpaceDynamics(
        [&lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;CL=F&#34;&lt;/span&gt;, &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;BZ=F&#34;&lt;/span&gt;], &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;2022-01-01&#34;&lt;/span&gt;, &lt;span style=&#34;background-color: #FFF0F0&#34;&gt;&#34;2024-01-01&#34;&lt;/span&gt;,
        forecast_steps&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #00D; font-weight: bold&#34;&gt;60&lt;/span&gt;, labels&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;labels,
    )
    analysis&lt;span style=&#34;color: #333&#34;&gt;.&lt;/span&gt;run_analysis(save_figures&lt;span style=&#34;color: #333&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color: #080; font-weight: bold&#34;&gt;True&lt;/span&gt;)&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;style&gt;
.body-footer {
  display: none;
}
&lt;/style&gt;
&lt;/div&gt;
</description>
    </item>
    
  </channel>
</rss>
