algorembrant commited on
Commit
c95b927
·
verified ·
1 Parent(s): 563fa7c

Upload 18 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,9 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ gmp.pdf filter=lfs diff=lfs merge=lfs -text
37
+ mBA-GMP.v3/fig_cmp_vs_gmp.png filter=lfs diff=lfs merge=lfs -text
38
+ mBA-GMP.v3/fig_combined_3panel.png filter=lfs diff=lfs merge=lfs -text
39
+ mBA-GMP.v3/fig_price_scatter.png filter=lfs diff=lfs merge=lfs -text
40
+ mBA-GMP.v3/fig_updown_footprint.png filter=lfs diff=lfs merge=lfs -text
41
+ mBA-GMP.v3/raw_draft_of_concept.png filter=lfs diff=lfs merge=lfs -text
gmp.md ADDED
The diff for this file is too large to render. See raw diff
 
gmp.pdf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6ca3348de80c43b798d11bf36b8359e347f34625051c078c77a8a29b64a1276f
3
+ size 278774
gmp.tex ADDED
@@ -0,0 +1,833 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ \documentclass[conference]{IEEEtran}
2
+
3
+ % ── Packages ──────────────────────────────────────────────────────────────────
4
+ \usepackage{cite}
5
+ \usepackage{amsmath,amssymb,amsfonts}
6
+ \usepackage{algorithmic}
7
+ \usepackage{algorithm}
8
+ \usepackage{graphicx}
9
+ \usepackage{textcomp}
10
+ \usepackage{booktabs}
11
+ \usepackage{multirow}
12
+ \usepackage{tikz}
13
+ \usepackage{pgfplots}
14
+ \pgfplotsset{compat=1.18}
15
+ \usepackage{hyperref}
16
+ \usepackage{cleveref}
17
+
18
+ % ── Meta ──────────────────────────────────────────────────────────────────────
19
+ \hypersetup{
20
+ colorlinks=true,
21
+ linkcolor=blue,
22
+ citecolor=blue,
23
+ urlcolor=blue
24
+ }
25
+
26
+ \def\BibTeX{{\rm B\kern-.05em{\sc i\kern-.025em b}\kern-.08em
27
+ T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}}
28
+
29
+ \begin{document}
30
+
31
+ % ══════════════════════════════════════════════════════════════════════════════
32
+ % TITLE
33
+ % ══════════════════════════════════════════════════════════════════════════════
34
+
35
+ \title{GMP: Gap-filled Market Profile Universal Construction for Any Data Points}
36
+
37
+ \author{\IEEEauthorblockN{ConQ Research Team}\\
38
+ \IEEEauthorblockA{\textit{Continual Quasars}\\
39
+ \today}
40
+ }
41
+
42
+ \maketitle
43
+
44
+ % ══════════════════════════════════════════════════════════════════════════════
45
+ % ABSTRACT
46
+ % ══════════════════════════════════════════════════════════════════════════════
47
+ \begin{abstract}
48
+ Conventional Market Profile (CMP) aggregates price activity into histogram bins, but when applied to any ordered sequence of price points (ticks, candlesticks, or other sampled data), it leaves bins between consecutive points empty. We propose \textbf{GMP (Gap-Filled Market Profile)}, a universal construction method that (i) operates on any sequence of price observations and (ii) interpolates every intermediate price bin traversed between successive points, producing a \emph{gap-filled} profile. Building on this gap‑filled structure, we introduce an \emph{Up/Down‑Bin Footprint Profile} that classifies each bin's contribution directionally, revealing net upward or downward pressure across the price traversal. We formalise CMP and GMP with explicit algorithms, derive the relationship between bin count and a user‑defined bin‑size parameter $\beta$, and present a complete worked example showing how points are grouped into bins under CMP, how gap‑filling transforms the sparse CMP output into a dense GMP profile, and how directional footprints are assigned. Charts and tables demonstrate that GMP yields a strictly denser and more informative distribution than CMP, independent of the original data source.
49
+ \end{abstract}
50
+
51
+ \begin{IEEEkeywords}
52
+ Market Profile, gap-filling interpolation, price bins, directional footprint, high-frequency data, time series
53
+ \end{IEEEkeywords}
54
+
55
+ % ── Side‑by‑side introductory CMP vs GMP figure ─────────────────────────────
56
+ \begin{figure}[!t]
57
+ \centering
58
+ \begin{tikzpicture}
59
+ \begin{axis}[
60
+ title={\textbf{CMP Profile}},
61
+ xbar,
62
+ xlabel={Stacks},
63
+ ylabel={Price (USD)},
64
+ ytick={3000,3001,...,3010},
65
+ yticklabel style={font=\scriptsize},
66
+ xmin=0, xmax=2,
67
+ ymin=2999.5, ymax=3010.5,
68
+ bar width=4pt,
69
+ width=0.42\columnwidth,
70
+ height=6.5cm,
71
+ enlarge y limits=0.05,
72
+ nodes near coords,
73
+ nodes near coords style={font=\tiny},
74
+ name=cmp
75
+ ]
76
+ \addplot[fill=gray!60, draw=black] coordinates {
77
+ (1,3000) (0,3001) (0,3002) (0,3003) (0,3004) (0,3005)
78
+ (0,3006) (0,3007) (0,3008) (0,3009) (1,3010)
79
+ };
80
+ \end{axis}
81
+
82
+ \begin{axis}[
83
+ title={\textbf{GMP Profile}},
84
+ xbar,
85
+ xlabel={Stacks},
86
+ ylabel={},
87
+ ytick={3000,3001,...,3010},
88
+ yticklabel style={font=\scriptsize},
89
+ xmin=0, xmax=2,
90
+ ymin=2999.5, ymax=3010.5,
91
+ bar width=4pt,
92
+ width=0.42\columnwidth,
93
+ height=6.5cm,
94
+ enlarge y limits=0.05,
95
+ nodes near coords,
96
+ nodes near coords style={font=\tiny},
97
+ at={(cmp.east)},
98
+ anchor=west,
99
+ xshift=1.2cm
100
+ ]
101
+ \addplot[fill=blue!50, draw=black] coordinates {
102
+ (1,3000) (1,3001) (1,3002) (1,3003) (1,3004) (1,3005)
103
+ (1,3006) (1,3007) (1,3008) (1,3009) (1,3010)
104
+ };
105
+ \end{axis}
106
+ \end{tikzpicture}
107
+ \caption{Horizontal histogram comparison of CMP (left, grey) and GMP (right, blue) for a price move from 3000 to 3010 with $\beta=1$. CMP shows activity only at the two observed prices; GMP fills all 11 traversed bins. Gap‑filling applies to any data sequence.}
108
+ \label{fig:profile}
109
+ \end{figure}
110
+
111
+ % ══════════════════════════════════════════════════════════════════════════════
112
+ % I. INTRODUCTION
113
+ % ══════════════════════════════════════════════════════════════════════════════
114
+ \section{Introduction}\label{sec:intro}
115
+
116
+ The Market Profile, introduced by Steidlmayer~\cite{steidlmayer1986market} and later formalised by Dalton et~al.~\cite{dalton2007markets}, represents price activity as a horizontal histogram whose bins correspond to discrete price levels and whose bar lengths (``stacks'') reflect the amount of activity observed at each level. In practice, most implementations construct the profile from candlestick TOCHLV (time, open, close, high, low, volume) data: each candle contributes one stack to every bin between its high and low.
117
+
118
+ This approach suffers from a fundamental shortcoming when applied to any sequence of discrete price points: when consecutive points are separated by several price levels, the conventional profile records activity only at the two observed prices, ignoring the fact that price must have traversed every intermediate level. This gap neglect is not specific to any data source—it occurs with ticks, candlesticks, or any sampled price series.
119
+
120
+ We address this issue with \textbf{GMP (Gap‑Filled Market Profile)}. The construction rule is universal: for every ordered sequence of price observations $\{p_i\}_{i=1}^{N}$, every bin between two successive points receives an interpolated stack, producing a profile with no gaps. The method does not depend on the original data frequency, source, or aggregation level; it applies equally to millisecond tick data, hourly candlesticks, or irregularly sampled price records.
121
+
122
+ The main contributions of this work are:
123
+ \begin{enumerate}
124
+ \item A rigorous formalisation of CMP and GMP with explicit algorithms and complexity analyses.
125
+ \item A theoretical relationship between the user‑controlled bin‑size parameter $\beta$ and profile resolution, including a scaling proposition.
126
+ \item A universal gap‑filling methodology that can be applied to any ordered price sequence, irrespective of source.
127
+ \item The introduction of an \emph{Up/Down‑Bin Footprint Profile}, a directional classification derived purely from the price traversal without requiring volume or order‑book data.
128
+ \item A complete, self‑contained illustration of the construction on a ten‑point price sequence, demonstrating all theoretical constructs.
129
+ \end{enumerate}
130
+
131
+ The remainder of this paper is organised as follows. \Cref{sec:related} surveys related work. \Cref{sec:prelim} establishes notation. \Cref{sec:method} defines CMP and GMP formally, presents the GMP algorithm, and introduces the Up/Down‑Bin Footprint Profile. \Cref{sec:walkthrough} provides a complete profile construction example using a 10‑point price sequence. \Cref{sec:binsize} analyses the effect of bin size on profile resolution. \Cref{sec:example} offers a minimal illustrative example. \Cref{sec:discussion} discusses theoretical implications, and \Cref{sec:conclusion} concludes.
132
+
133
+ % ══════════════════════════════════════════════════════════════════════════════
134
+ % II. RELATED WORK
135
+ % ══════════════════════════════════════════════════════════════════════════════
136
+ \section{Related Work}\label{sec:related}
137
+
138
+ \subsection{Market Profile}
139
+ The Market Profile concept originates with Steidlmayer's observation that price distributions at each level reveal where market participants find ``fair value''~\cite{steidlmayer1986market}. Dalton et~al.~\cite{dalton2007markets} extended the framework with auction‑market theory, using half‑hour brackets as time‑price opportunities (TPOs). Both formulations rely on time‑based bars rather than raw ticks, but the underlying logic of binning price activity is independent of the data source.
140
+
141
+ \subsection{Interpolation in Financial Time Series}
142
+ Interpolation techniques are common in high‑frequency finance. Clark~\cite{clark1973subordinated} demonstrated that subordinating returns to trade‑count time yields closer‑to‑Gaussian distributions, motivating trade‑indexed analysis. An\'{e} and Geman~\cite{ane2000order} confirmed that business‑time transformations normalise returns at the tick level. The gap‑filling approach we propose is conceptually similar to linear interpolation on the price axis, but applied to histogram bin counts rather than to prices themselves.
143
+
144
+ \subsection{Footprint and Order‑Flow Analysis}
145
+ Market microstructure theory, including Glosten and Milgrom~\cite{glosten1985bid}, O'Hara~\cite{ohara1995market}, and Madhavan~\cite{madhavan2000market}, provides foundations for analysing directional pressure. Traditional footprint charts distinguish trades at bid versus ask prices. Our Up/Down‑Bin Footprint provides a complementary directional classification derived purely from the sequence of price observations, without requiring volume or order‑book data.
146
+
147
+ % ══════════════════════════════════════════════════════════════════════════════
148
+ % III. PRELIMINARIES
149
+ % ══════════════════════════════════════════════════════════════════════════════
150
+ \section{Preliminaries}\label{sec:prelim}
151
+
152
+ \Cref{tab:notation} summarises the notation used throughout.
153
+
154
+ \begin{table}[!t]
155
+ \centering
156
+ \caption{Notation Summary}
157
+ \label{tab:notation}
158
+ \begin{tabular}{@{}cl@{}}
159
+ \toprule
160
+ \textbf{Symbol} & \textbf{Description} \\
161
+ \midrule
162
+ $N$ & Total number of price observations in the sequence \\
163
+ $p_i$ & Price of the $i$-th observation, $i\in\{1,\dots,N\}$ \\
164
+ $\beta$ & Bin size (price units per bin); default $\beta=1$ \\
165
+ $b(p)$ & Bin index of price $p$: $b(p)=\lfloor p/\beta \rfloor$ \\
166
+ $S[k]$ & Stack count (profile value) at bin~$k$ \\
167
+ $\Delta_i$ & Price displacement: $\Delta_i = p_i - p_{i-1}$ \\
168
+ $K_i$ & Number of bins traversed from observation $i{-}1$ to $i$ \\
169
+ $U[k]$ & Up‑bin count at bin $k$ \\
170
+ $D[k]$ & Down‑bin count at bin $k$ \\
171
+ $\delta[k]$ & Net footprint delta at bin $k$: $\delta[k] = U[k] - D[k]$ \\
172
+ \bottomrule
173
+ \end{tabular}
174
+ \end{table}
175
+
176
+ \begin{definition}[Price observation sequence]
177
+ A \emph{price observation sequence} is an ordered set $\mathcal{P}=\{(t_i,\,p_i)\}_{i=1}^{N}$ where $t_i$ is an index (time, trade number, or any monotonic identifier) and $p_i$ is the observed price.
178
+ \end{definition}
179
+
180
+ \begin{definition}[Bin]
181
+ Given bin size $\beta>0$, the \emph{bin} for price $p$ is the integer index
182
+ \begin{equation}\label{eq:bin}
183
+ b(p) = \left\lfloor \frac{p}{\beta} \right\rfloor.
184
+ \end{equation}
185
+ All prices $p$ satisfying $k\beta \le p < (k+1)\beta$ map to bin~$k$.
186
+ \end{definition}
187
+
188
+ \begin{definition}[Market Profile]
189
+ A \emph{market profile} is a mapping $S:\mathbb{Z}\to\mathbb{N}_0$ where $S[k]$ counts the number of stacks accumulated at bin~$k$.
190
+ \end{definition}
191
+
192
+ % ══════════════════════════════════════════════════════════════════════════════
193
+ % IV. METHODOLOGY
194
+ % ══════════════════════════════════════════════════════════════════════════════
195
+ \section{Methodology}\label{sec:method}
196
+
197
+ \subsection{Conventional Market Profile (CMP)}\label{sec:cmp}
198
+
199
+ CMP records a stack only at the bin of each observed data point:
200
+ \begin{equation}\label{eq:cmp}
201
+ S_{\text{CMP}}[k] \;=\; \sum_{i=1}^{N} \mathbf{1}\!\bigl[b(p_i)=k\bigr],
202
+ \end{equation}
203
+ where $\mathbf{1}[\cdot]$ is the indicator function. Bins with no observed point receive $S_{\text{CMP}}[k]=0$.
204
+
205
+ \begin{algorithm}[!t]
206
+ \caption{CMP Construction}\label{alg:cmp}
207
+ \begin{algorithmic}[1]
208
+ \REQUIRE Price sequence $\{p_i\}_{i=1}^{N}$, bin size $\beta$
209
+ \ENSURE Profile array $S_{\text{CMP}}[\cdot]$
210
+ \STATE Initialise $S_{\text{CMP}}[k]\leftarrow 0\;\;\forall\,k$
211
+ \FOR{$i = 1$ \TO $N$}
212
+ \STATE $k \leftarrow \lfloor p_i / \beta \rfloor$
213
+ \STATE $S_{\text{CMP}}[k] \leftarrow S_{\text{CMP}}[k] + 1$
214
+ \ENDFOR
215
+ \RETURN $S_{\text{CMP}}$
216
+ \end{algorithmic}
217
+ \end{algorithm}
218
+
219
+ \textbf{Complexity.} CMP performs exactly $N$ bin‑index computations and $N$ increments, giving $\mathcal{O}(N)$ time complexity.
220
+
221
+ \subsection{Gap‑Filled Market Profile (GMP)}\label{sec:gmp}
222
+
223
+ GMP augments CMP by filling every \emph{intermediate} bin between two consecutive observations. The construction proceeds in two phases:
224
+
225
+ \begin{enumerate}
226
+ \item \textbf{CMP placement.} Each observation $p_i$ contributes one stack to its own bin $b(p_i)$, exactly as in CMP.
227
+ \item \textbf{Gap‑filling.} For each consecutive pair $(p_{i-1},\,p_i)$ with $i\ge 2$, every bin \emph{strictly between} $b(p_{i-1})$ and $b(p_i)$ (exclusive of both endpoints) receives one additional stack.
228
+ \end{enumerate}
229
+
230
+ Formally, writing $b_i = b(p_i)$:
231
+ \begin{equation}\label{eq:gmp}
232
+ S_{\text{GMP}}[k]
233
+ \;=\;
234
+ \underbrace{\sum_{i=1}^{N}\mathbf{1}\!\bigl[b_i=k\bigr]}_{S_{\text{CMP}}[k]}
235
+ \;+\;
236
+ \sum_{i=2}^{N}
237
+ \;\sum_{j=\min(b_{i-1},\,b_i)+1}^{\max(b_{i-1},\,b_i)-1}
238
+ \!\mathbf{1}\!\bigl[j=k\bigr].
239
+ \end{equation}
240
+
241
+ When $|b_i - b_{i-1}| \le 1$ (adjacent or same bin), the inner sum is empty and no gap‑filling occurs. When $|b_i - b_{i-1}| > 1$, the number of gap‑filled (intermediate) bins is
242
+ \begin{equation}\label{eq:Ki}
243
+ G_i \;=\; \bigl|b(p_i) - b(p_{i-1})\bigr| - 1.
244
+ \end{equation}
245
+ The total span of bins traversed, inclusive of both endpoints, is $K_i = G_i + 2 = |b_i - b_{i-1}| + 1$.
246
+
247
+ \begin{algorithm}[!t]
248
+ \caption{GMP Construction (Two‑Phase)}\label{alg:gmp}
249
+ \begin{algorithmic}[1]
250
+ \REQUIRE Price sequence $\{p_i\}_{i=1}^{N}$, bin size $\beta$
251
+ \ENSURE Profile array $S_{\text{GMP}}[\cdot]$
252
+ \STATE Initialise $S_{\text{GMP}}[k]\leftarrow 0\;\;\forall\,k$
253
+ \FOR{$i = 1$ \TO $N$} \COMMENT{Phase~1: CMP placement}
254
+ \STATE $S_{\text{GMP}}[\lfloor p_i/\beta \rfloor] \leftarrow S_{\text{GMP}}[\lfloor p_i/\beta \rfloor] + 1$
255
+ \ENDFOR
256
+ \FOR{$i = 2$ \TO $N$} \COMMENT{Phase~2: gap‑fill}
257
+ \STATE $k_{\text{from}} \leftarrow \lfloor p_{i-1}/\beta \rfloor$; $k_{\text{to}} \leftarrow \lfloor p_i/\beta \rfloor$
258
+ \IF{$|k_{\text{to}} - k_{\text{from}}| > 1$}
259
+ \STATE $d \leftarrow \text{sign}(k_{\text{to}} - k_{\text{from}})$
260
+ \FOR{$k = k_{\text{from}} + d$ \TO $k_{\text{to}} - d$ \textbf{step} $d$}
261
+ \STATE $S_{\text{GMP}}[k] \leftarrow S_{\text{GMP}}[k] + 1$
262
+ \ENDFOR
263
+ \ENDIF
264
+ \ENDFOR
265
+ \RETURN $S_{\text{GMP}}$
266
+ \end{algorithmic}
267
+ \end{algorithm}
268
+
269
+ \textbf{Complexity.} Let $D=\sum_{i=2}^{N}|b(p_i)-b(p_{i-1})|$ denote the cumulative bin displacement. GMP performs $\mathcal{O}(N + D)$ operations. In the degenerate case where all observations share the same bin, $D=0$ and GMP reduces to CMP. In the worst case, $D=\mathcal{O}(N\cdot\Delta p_{\max}/\beta)$.
270
+
271
+ \subsection{GMP as a Universal Construction}\label{sec:universal}
272
+
273
+ The key contribution of GMP is its universality: the gap‑filling rule applies to \emph{any} ordered price sequence, regardless of the original data's temporal spacing, source, or aggregation level. This includes:
274
+ \begin{itemize}
275
+ \item Raw tick data (millisecond‑resolution bid/ask records)
276
+ \item Candlestick TOCHLV sequences (using close, high, low, or any representative price)
277
+ \item Irregularly sampled price points
278
+ \item Synthetic price paths or simulated data
279
+ \end{itemize}
280
+
281
+ The only requirement is that the sequence be ordered (by time, trade index, or any monotonic index). The construction makes no assumption about the mechanism that generated the prices; it purely interpolates bin traversals between consecutive observations.
282
+
283
+ \subsection{Up/Down‑Bin Footprint Profile}\label{sec:updown}
284
+
285
+ Building upon the gap‑filled structure of GMP, we introduce a directional classification layer termed the \emph{Up/Down‑Bin Footprint Profile}. For every consecutive pair $(p_{i-1},\,p_i)$, the trajectory is evaluated as upward or downward based on the price difference. The origin bin $b(p_{i-1})$ is assigned no directional credit for this move (it has already been evaluated by prior action). However, every subsequent bin along the traversed path up to and including the destination bin $b(p_i)$ increments its \emph{up‑bin} count $U[k]$ if $p_i > p_{i-1}$, or its \emph{down‑bin} count $D[k]$ if $p_i \le p_{i-1}$.
286
+
287
+ \begin{algorithm}[!t]
288
+ \caption{Up/Down‑Bin Footprint Construction}\label{alg:updown}
289
+ \begin{algorithmic}[1]
290
+ \REQUIRE Price sequence $\{p_i\}_{i=1}^{N}$, bin size $\beta$
291
+ \ENSURE Profile arrays $U[\cdot], D[\cdot], \delta[\cdot]$
292
+ \STATE Initialise $U[k]\leftarrow 0, D[k]\leftarrow 0\;\;\forall\,k$
293
+ \FOR{$i = 2$ \TO $N$}
294
+ \STATE $k_{\text{from}} \leftarrow \lfloor p_{i-1}/\beta \rfloor$; $k_{\text{to}} \leftarrow \lfloor p_i/\beta \rfloor$
295
+ \IF{$k_{\text{from}} = k_{\text{to}}$}
296
+ \IF{$p_i > p_{i-1}$}
297
+ \STATE $U[k_{\text{from}}] \leftarrow U[k_{\text{from}}] + 1$
298
+ \ELSE
299
+ \STATE $D[k_{\text{from}}] \leftarrow D[k_{\text{from}}] + 1$
300
+ \ENDIF
301
+ \STATE \textbf{continue}
302
+ \ENDIF
303
+ \STATE $\text{is\_up} \leftarrow (k_{\text{to}} > k_{\text{from}})$
304
+ \STATE $d \leftarrow \text{sign}(k_{\text{to}} - k_{\text{from}})$
305
+ \STATE $k \leftarrow k_{\text{from}} + d$
306
+ \WHILE{\textbf{true}}
307
+ \IF{$\text{is\_up}$}
308
+ \STATE $U[k] \leftarrow U[k] + 1$
309
+ \ELSE
310
+ \STATE $D[k] \leftarrow D[k] + 1$
311
+ \ENDIF
312
+ \IF{$k = k_{\text{to}}$}
313
+ \STATE \textbf{break}
314
+ \ENDIF
315
+ \STATE $k \leftarrow k + d$
316
+ \ENDWHILE
317
+ \ENDFOR
318
+ \FORALL{$k$}
319
+ \STATE $\delta[k] \leftarrow U[k] - D[k]$
320
+ \ENDFOR
321
+ \RETURN $U,\,D,\,\delta$
322
+ \end{algorithmic}
323
+ \end{algorithm}
324
+
325
+ This algorithm traces the same $\mathcal{O}(N+D)$ bins as the GMP phase, maintaining computational efficiency while providing deep structural insight into directional dominance across the price range.
326
+
327
+ % ══════════════════════════════════════════════════════════════════════════════
328
+ % V. PROFILE CONSTRUCTION WALKTHROUGH
329
+ % ══════════════════════════════════════════════════════════════════════════════
330
+ \section{Profile Construction Walkthrough}\label{sec:walkthrough}
331
+
332
+ We illustrate the construction on a ten‑point price sequence. Each observation is a triple $(\text{label}, x, y)$ where \textit{label} is an alphabetic identifier, $x$ is the index, and $y$ the price. \Cref{tab:datapoints} lists the data.
333
+
334
+ \begin{table}[!t]
335
+ \centering
336
+ \caption{Input Observations (10 Points)}
337
+ \label{tab:datapoints}
338
+ \begin{tabular}{@{}ccc@{}}
339
+ \toprule
340
+ \textbf{Label} & \textbf{Index \#} & \textbf{Price (USD)} \\
341
+ \midrule
342
+ A & 1 & 3000.914 \\
343
+ B & 2 & 3003.837 \\
344
+ C & 3 & 3002.432 \\
345
+ D & 4 & 3009.892 \\
346
+ E & 5 & 3007.698 \\
347
+ F & 6 & 3009.176 \\
348
+ G & 7 & 3003.381 \\
349
+ H & 8 & 3004.283 \\
350
+ I & 9 & 3003.512 \\
351
+ J & 10 & 3003.012 \\
352
+ \bottomrule
353
+ \end{tabular}
354
+ \end{table}
355
+
356
+ \begin{figure}[!t]
357
+ \centering
358
+ \begin{tikzpicture}
359
+ \begin{axis}[
360
+ title={Price vs.\ Index},
361
+ xlabel={Index},
362
+ ylabel={Price (USD)},
363
+ ymin=2999.5, ymax=3011,
364
+ grid=both,
365
+ width=\columnwidth,
366
+ height=5cm,
367
+ legend style={at={(0.5,-0.15)}, anchor=north, legend columns=-1}
368
+ ]
369
+ \addplot[
370
+ only marks,
371
+ mark=*,
372
+ mark size=2pt,
373
+ blue
374
+ ] coordinates {
375
+ (1,3000.914) (2,3003.837) (3,3002.432) (4,3009.892) (5,3007.698)
376
+ (6,3009.176) (7,3003.381) (8,3004.283) (9,3003.512) (10,3003.012)
377
+ };
378
+ \legend{Observed price}
379
+ \end{axis}
380
+ \end{tikzpicture}
381
+ \caption{Price vs.\ index for the 10‑point example.}
382
+ \label{fig:price_scatter}
383
+ \end{figure}
384
+
385
+ \subsection{CMP Profile Table}\label{sec:cmp_table}
386
+
387
+ With $\beta=1$, the bin index is $b(p)=\lfloor p\rfloor$. CMP counts points per bin. \Cref{tab:cmp_profile} shows that bins 2, 6, 7, and 9 are empty—the gaps in the conventional profile.
388
+
389
+ \begin{table}[!t]
390
+ \centering
391
+ \caption{CMP Profile Table ($\beta=1$)}
392
+ \label{tab:cmp_profile}
393
+ \begin{tabular}{@{}ccccc@{}}
394
+ \toprule
395
+ \textbf{Bin} & \textbf{From} & \textbf{Until} & \textbf{Group} & \textbf{Stacks} \\
396
+ \midrule
397
+ 1 & 3000 & 3001 & A & 1 \\
398
+ 2 & 3001 & 3002 & & 0 \\
399
+ 3 & 3002 & 3003 & C & 1 \\
400
+ 4 & 3003 & 3004 & BGIJ & 4 \\
401
+ 5 & 3004 & 3005 & H & 1 \\
402
+ 6 & 3005 & 3006 & & 0 \\
403
+ 7 & 3006 & 3007 & & 0 \\
404
+ 8 & 3007 & 3008 & E & 1 \\
405
+ 9 & 3008 & 3009 & & 0 \\
406
+ 10 & 3009 & 3010 & DF & 2 \\
407
+ \midrule
408
+ \multicolumn{4}{c}{\textbf{Total stacks}} & \textbf{10} \\
409
+ \bottomrule
410
+ \end{tabular}
411
+ \end{table}
412
+
413
+ \begin{figure}[!t]
414
+ \centering
415
+ \begin{tikzpicture}
416
+ \begin{axis}[
417
+ title={CMP Profile},
418
+ xbar,
419
+ xlabel={Stacks},
420
+ ylabel={Price (USD)},
421
+ ytick={3000,3001,...,3009},
422
+ yticklabel style={font=\scriptsize},
423
+ xmin=0, xmax=5,
424
+ ymin=2999.5, ymax=3010,
425
+ bar width=4pt,
426
+ width=\columnwidth,
427
+ height=5cm,
428
+ enlarge y limits=0.05,
429
+ nodes near coords,
430
+ nodes near coords style={font=\tiny}
431
+ ]
432
+ \addplot[fill=orange!50, draw=black] coordinates {
433
+ (1,3000) (0,3001) (1,3002) (4,3003) (1,3004)
434
+ (0,3005) (0,3006) (1,3007) (0,3008) (2,3009)
435
+ };
436
+ \end{axis}
437
+ \end{tikzpicture}
438
+ \caption{CMP profile for the 10‑point example ($\beta=1$). Four bins are empty.}
439
+ \label{fig:cmp_chart}
440
+ \end{figure}
441
+
442
+ \subsection{GMP Profile Table}\label{sec:gmp_table}
443
+
444
+ GMP fills intermediate bins between consecutive points. \Cref{tab:gmp_profile} shows every bin now populated, with total stack count 25.
445
+
446
+ \begin{table}[!t]
447
+ \centering
448
+ \caption{GMP Profile Table ($\beta=1$)}
449
+ \label{tab:gmp_profile}
450
+ \begin{tabular}{@{}ccccc@{}}
451
+ \toprule
452
+ \textbf{Bin} & \textbf{From} & \textbf{Until} & \textbf{Group} & \textbf{Stacks} \\
453
+ \midrule
454
+ 1 & 3000 & 3001 & A & 1 \\
455
+ 2 & 3001 & 3002 & A & 1 \\
456
+ 3 & 3002 & 3003 & AC & 2 \\
457
+ 4 & 3003 & 3004 & BCGIJ & 5 \\
458
+ 5 & 3004 & 3005 & CFH & 3 \\
459
+ 6 & 3005 & 3006 & CF & 2 \\
460
+ 7 & 3006 & 3007 & CF & 2 \\
461
+ 8 & 3007 & 3008 & CEF & 3 \\
462
+ 9 & 3008 & 3009 & CDEF & 4 \\
463
+ 10 & 3009 & 3010 & DF & 2 \\
464
+ \midrule
465
+ \multicolumn{4}{c}{\textbf{Total stacks}} & \textbf{25} \\
466
+ \bottomrule
467
+ \end{tabular}
468
+ \end{table}
469
+
470
+ \begin{figure}[!t]
471
+ \centering
472
+ \begin{tikzpicture}
473
+ \begin{axis}[
474
+ title={GMP Profile},
475
+ xbar,
476
+ xlabel={Stacks},
477
+ ylabel={Price (USD)},
478
+ ytick={3000,3001,...,3009},
479
+ yticklabel style={font=\scriptsize},
480
+ xmin=0, xmax=6,
481
+ ymin=2999.5, ymax=3010,
482
+ bar width=4pt,
483
+ width=\columnwidth,
484
+ height=5cm,
485
+ enlarge y limits=0.05,
486
+ nodes near coords,
487
+ nodes near coords style={font=\tiny}
488
+ ]
489
+ \addplot[fill=green!40, draw=black] coordinates {
490
+ (1,3000) (1,3001) (2,3002) (5,3003) (3,3004)
491
+ (2,3005) (2,3006) (3,3007) (4,3008) (2,3009)
492
+ };
493
+ \end{axis}
494
+ \end{tikzpicture}
495
+ \caption{GMP profile for the 10‑point example ($\beta=1$). Every bin is populated.}
496
+ \label{fig:gmp_chart}
497
+ \end{figure}
498
+
499
+ \subsection{CMP vs.\ GMP Side‑by‑Side}\label{sec:cmp_gmp_compare}
500
+
501
+ \Cref{fig:cmp_vs_gmp_10pt} places both profiles side by side. CMP (10 stacks) leaves 40\% of bins empty; GMP (25 stacks) fully covers the range.
502
+
503
+ \begin{figure}[!t]
504
+ \centering
505
+ \begin{tikzpicture}
506
+ \begin{axis}[
507
+ title={CMP},
508
+ xbar,
509
+ xlabel={Stacks},
510
+ ylabel={Price (USD)},
511
+ ytick={3000,3001,...,3009},
512
+ yticklabel style={font=\scriptsize},
513
+ xmin=0, xmax=6,
514
+ ymin=2999.5, ymax=3010,
515
+ bar width=4pt,
516
+ width=0.42\columnwidth,
517
+ height=6cm,
518
+ enlarge y limits=0.05,
519
+ name=cmp_10
520
+ ]
521
+ \addplot[fill=orange!50, draw=black] coordinates {
522
+ (1,3000) (0,3001) (1,3002) (4,3003) (1,3004)
523
+ (0,3005) (0,3006) (1,3007) (0,3008) (2,3009)
524
+ };
525
+ \end{axis}
526
+ \begin{axis}[
527
+ title={GMP},
528
+ xbar,
529
+ xlabel={Stacks},
530
+ ylabel={},
531
+ ytick={3000,3001,...,3009},
532
+ yticklabel style={font=\scriptsize},
533
+ xmin=0, xmax=6,
534
+ ymin=2999.5, ymax=3010,
535
+ bar width=4pt,
536
+ width=0.42\columnwidth,
537
+ height=6cm,
538
+ enlarge y limits=0.05,
539
+ at={(cmp_10.east)},
540
+ anchor=west,
541
+ xshift=0.8cm
542
+ ]
543
+ \addplot[fill=green!40, draw=black] coordinates {
544
+ (1,3000) (1,3001) (2,3002) (5,3003) (3,3004)
545
+ (2,3005) (2,3006) (3,3007) (4,3008) (2,3009)
546
+ };
547
+ \end{axis}
548
+ \end{tikzpicture}
549
+ \caption{CMP vs.\ GMP side‑by‑side.}
550
+ \label{fig:cmp_vs_gmp_10pt}
551
+ \end{figure}
552
+
553
+ \Cref{fig:combined_3panel} presents the entire construction pipeline—raw data, CMP, GMP—in a single three‑panel TikZ graphic, ensuring full reproducibility.
554
+
555
+ \begin{figure*}[!t]
556
+ \centering
557
+ \begin{tikzpicture}
558
+ % Panel 1: raw data scatter
559
+ \begin{axis}[
560
+ title={Raw Data},
561
+ xlabel={Index},
562
+ ylabel={Price (USD)},
563
+ ymin=2999.5, ymax=3011,
564
+ width=0.30\textwidth,
565
+ height=6cm,
566
+ name=raw
567
+ ]
568
+ \addplot[only marks, mark=*, mark size=2pt, blue] coordinates {
569
+ (1,3000.914) (2,3003.837) (3,3002.432) (4,3009.892) (5,3007.698)
570
+ (6,3009.176) (7,3003.381) (8,3004.283) (9,3003.512) (10,3003.012)
571
+ };
572
+ \end{axis}
573
+ % Panel 2: CMP profile
574
+ \begin{axis}[
575
+ title={CMP Profile},
576
+ xbar,
577
+ xlabel={Stacks},
578
+ ylabel={},
579
+ ytick={3000,3001,...,3009},
580
+ yticklabel style={font=\scriptsize},
581
+ xmin=0, xmax=5,
582
+ ymin=2999.5, ymax=3010,
583
+ bar width=4pt,
584
+ width=0.30\textwidth,
585
+ height=6cm,
586
+ enlarge y limits=0.05,
587
+ at={(raw.east)},
588
+ anchor=west,
589
+ xshift=1.2cm
590
+ ]
591
+ \addplot[fill=orange!50, draw=black] coordinates {
592
+ (1,3000) (0,3001) (1,3002) (4,3003) (1,3004)
593
+ (0,3005) (0,3006) (1,3007) (0,3008) (2,3009)
594
+ };
595
+ \end{axis}
596
+ % Panel 3: GMP profile
597
+ \begin{axis}[
598
+ title={GMP Profile},
599
+ xbar,
600
+ xlabel={Stacks},
601
+ ylabel={},
602
+ ytick={3000,3001,...,3009},
603
+ yticklabel style={font=\scriptsize},
604
+ xmin=0, xmax=6,
605
+ ymin=2999.5, ymax=3010,
606
+ bar width=4pt,
607
+ width=0.30\textwidth,
608
+ height=6cm,
609
+ enlarge y limits=0.05,
610
+ at={(raw.east)},
611
+ anchor=west,
612
+ xshift=6cm
613
+ ]
614
+ \addplot[fill=green!40, draw=black] coordinates {
615
+ (1,3000) (1,3001) (2,3002) (5,3003) (3,3004)
616
+ (2,3005) (2,3006) (3,3007) (4,3008) (2,3009)
617
+ };
618
+ \end{axis}
619
+ \end{tikzpicture}
620
+ \caption{Three‑panel overview: raw data (left), CMP (centre), and GMP (right). Gap‑filling produces a continuous profile without empty bins.}
621
+ \label{fig:combined_3panel}
622
+ \end{figure*}
623
+
624
+ \subsection{Up/Down‑Bin Footprint Table}\label{sec:updown_table}
625
+
626
+ Applying \Cref{alg:updown} yields the directional footprint in \Cref{tab:updown_table}. For instance, the move from A to B adds up‑bins at bins~2--4; the move from C to D adds up‑bins at bins~4--10.
627
+
628
+ \begin{table}[!t]
629
+ \centering
630
+ \caption{Up/Down‑Bin Footprint Table ($\beta=1$)}
631
+ \label{tab:updown_table}
632
+ \begin{tabular}{@{}cccccrr@{}}
633
+ \toprule
634
+ \textbf{Bin} & \textbf{From} & \textbf{Until} & \textbf{Group} & \textbf{Down} & \textbf{Up} & \textbf{Delta} \\
635
+ \midrule
636
+ 1 & 3000 & 3001 & A & 0 & 0 & 0 \\
637
+ 2 & 3001 & 3002 & A & 0 & 1 & +1 \\
638
+ 3 & 3002 & 3003 & AC & 1 & 1 & 0 \\
639
+ 4 & 3003 & 3004 & BCGIJ & 3 & 2 & -1 \\
640
+ 5 & 3004 & 3005 & CFH & 1 & 2 & +1 \\
641
+ 6 & 3005 & 3006 & CF & 1 & 1 & 0 \\
642
+ 7 & 3006 & 3007 & CF & 1 & 1 & 0 \\
643
+ 8 & 3007 & 3008 & CEF & 2 & 1 & -1 \\
644
+ 9 & 3008 & 3009 & CDEF & 2 & 2 & 0 \\
645
+ 10 & 3009 & 3010 & DF & 0 & 2 & +2 \\
646
+ \bottomrule
647
+ \end{tabular}
648
+ \end{table}
649
+
650
+ \begin{figure}[!t]
651
+ \centering
652
+ \begin{tikzpicture}
653
+ \begin{axis}[
654
+ title={Up/Down‑Bin Footprint},
655
+ xbar,
656
+ xlabel={Count (Down / Up)},
657
+ ylabel={Price (USD)},
658
+ ytick={3000,3001,...,3009},
659
+ yticklabel style={font=\scriptsize},
660
+ xmin=-3.5, xmax=3.5,
661
+ ymin=2999.5, ymax=3010,
662
+ bar width=4pt,
663
+ width=\columnwidth,
664
+ height=5cm,
665
+ enlarge y limits=0.05,
666
+ legend style={at={(0.5,-0.15)}, anchor=north, legend columns=2}
667
+ ]
668
+ \addplot[fill=red!60, draw=black] coordinates {
669
+ (0,3000) (0,3001) (-1,3002) (-3,3003) (-1,3004)
670
+ (-1,3005) (-1,3006) (-2,3007) (-2,3008) (0,3009)
671
+ };
672
+ \addplot[fill=teal!60, draw=black] coordinates {
673
+ (0,3000) (1,3001) (1,3002) (2,3003) (2,3004)
674
+ (1,3005) (1,3006) (1,3007) (2,3008) (2,3009)
675
+ };
676
+ \legend{Down bins, Up bins}
677
+ \end{axis}
678
+ \end{tikzpicture}
679
+ \caption{Directional footprint: down‑bins (red) and up‑bins (teal).}
680
+ \label{fig:updown_footprint}
681
+ \end{figure}
682
+
683
+ % ══════════════════════════════════════════════════════════════════════════════
684
+ % VI. BIN‑SIZE ANALYSIS
685
+ % ══════════════════════════════════════════════════════════════════════════════
686
+ \section{Effect of Bin Size on Profile Resolution}\label{sec:binsize}
687
+
688
+ The bin‑size parameter $\beta$ controls granularity. For a single displacement $\Delta p = |p_i - p_{i-1}|$, the number of traversed bins is
689
+ \begin{equation}\label{eq:bins_beta}
690
+ K_i(\beta) \;=\;
691
+ \left|\left\lfloor \frac{p_i}{\beta} \right\rfloor
692
+ - \left\lfloor \frac{p_{i-1}}{\beta} \right\rfloor\right|
693
+ + 1.
694
+ \end{equation}
695
+ Halving $\beta$ roughly doubles $K_i$.
696
+
697
+ \begin{proposition}[Bin‑count scaling]\label{prop:scaling}
698
+ For fixed $\Delta p$ and $\beta_1 > \beta_2 > 0$,
699
+ \begin{equation}\label{eq:scaling}
700
+ K_i(\beta_2) \;\ge\;
701
+ \left\lfloor \frac{\beta_1}{\beta_2} \right\rfloor
702
+ \cdot \bigl(K_i(\beta_1) - 1\bigr) + 1.
703
+ \end{equation}
704
+ \end{proposition}
705
+
706
+ \begin{proof}
707
+ Write $\Delta p = (K_i(\beta_1)-1)\,\beta_1 + r_1$, $0 \le r_1 < \beta_1$. Then
708
+ $K_i(\beta_2) = \lfloor \Delta p/\beta_2 \rfloor + 1
709
+ \ge \lfloor (K_i(\beta_1)-1)\,\beta_1/\beta_2 \rfloor + 1
710
+ \ge \lfloor \beta_1/\beta_2 \rfloor\,(K_i(\beta_1)-1) + 1$.
711
+ \end{proof}
712
+
713
+ \Cref{tab:binsize} quantifies this for $\Delta p = 10$.
714
+
715
+ \begin{table}[!t]
716
+ \centering
717
+ \caption{Bin count vs.\ $\beta$ for $\Delta p = 10$}
718
+ \label{tab:binsize}
719
+ \begin{tabular}{@{}cccc@{}}
720
+ \toprule
721
+ $\beta$ & $K_i(\beta)$ & CMP bins & GMP bins filled \\
722
+ \midrule
723
+ 2.0 & 6 & 2 & 6 \\
724
+ 1.0 & 11 & 2 & 11 \\
725
+ 0.5 & 21 & 2 & 21 \\
726
+ 0.25 & 41 & 2 & 41 \\
727
+ 0.1 & 101 & 2 & 101 \\
728
+ \bottomrule
729
+ \end{tabular}
730
+ \end{table}
731
+
732
+ Key observations:
733
+ \begin{itemize}
734
+ \item \textbf{CMP is invariant:} always 2 bins, regardless of $\beta$.
735
+ \item \textbf{GMP scales as $\mathcal{O}(\Delta p/\beta)$:} resolution improves inversely with $\beta$. The lower bound is the minimum meaningful price increment.
736
+ \end{itemize}
737
+
738
+ % ══════════════════════════════════════════════════════════════════════════════
739
+ % VII. ILLUSTRATIVE EXAMPLE
740
+ % ═════════════════════════════════════════════════════════════���════════════════
741
+ \section{Illustrative Example}\label{sec:example}
742
+
743
+ Two observations: $p_1 = 3000$, $p_2 = 3010$, $\beta=1$. \Cref{tab:cmp_vs_gmp} shows CMP (2 stacks) vs.\ GMP (11 stacks). \Cref{fig:profile} plots both.
744
+
745
+ \begin{table}[!t]
746
+ \centering
747
+ \caption{CMP vs.\ GMP ($\beta=1$)}
748
+ \label{tab:cmp_vs_gmp}
749
+ \begin{tabular}{@{}cccc@{}}
750
+ \toprule
751
+ Observation \# & Price & CMP stacks & GMP stacks \\
752
+ \midrule
753
+ 1 & 3000 & 1 & 1 \\
754
+ 0 & 3001 & 0 & 1 \\
755
+ 0 & 3002 & 0 & 1 \\
756
+ 0 & 3003 & 0 & 1 \\
757
+ 0 & 3004 & 0 & 1 \\
758
+ 0 & 3005 & 0 & 1 \\
759
+ 0 & 3006 & 0 & 1 \\
760
+ 0 & 3007 & 0 & 1 \\
761
+ 0 & 3008 & 0 & 1 \\
762
+ 0 & 3009 & 0 & 1 \\
763
+ 2 & 3010 & 1 & 1 \\
764
+ \midrule
765
+ \multicolumn{2}{c}{\textbf{Total stacks}} & \textbf{2} & \textbf{11} \\
766
+ \bottomrule
767
+ \end{tabular}
768
+ \end{table}
769
+
770
+ % ══════════════════════════════════════════════════════════════════════════════
771
+ % VIII. DISCUSSION
772
+ % ══════════════════════════════════════════════════════════════════════════════
773
+ \section{Discussion}\label{sec:discussion}
774
+
775
+ \subsection{Advantages}
776
+ \begin{enumerate}
777
+ \item \textbf{No profile gaps.} All traversed price levels are represented, avoiding sparse CMP histograms.
778
+ \item \textbf{Volume‑neutral interpolation.} Interpolated stacks mark traversal, not fabricated volume.
779
+ \item \textbf{Directional context.} The footprint reveals net pressure without external order‑flow data.
780
+ \item \textbf{Tunable resolution.} $\beta$ adjusts granularity independently of data frequency.
781
+ \item \textbf{Universality.} GMP applies to any ordered price sequence.
782
+ \end{enumerate}
783
+
784
+ \subsection{Limitations}
785
+ \begin{enumerate}
786
+ \item \textbf{Interpolation assumption.} Assumes continuous traversal; genuine price gaps may be over‑represented.
787
+ \item \textbf{Computational cost.} $\mathcal{O}(N+D)$ may be high for large cumulative displacement.
788
+ \item \textbf{Not a volume profile.} GMP is a pure price‑traversal profile; combining with volume is future work.
789
+ \end{enumerate}
790
+
791
+ \subsection{Choosing $\beta$}
792
+ \begin{itemize}
793
+ \item Set $\beta$ near the minimum price increment for maximum resolution.
794
+ \item Enlarge $\beta$ to reduce noise or align with psychological levels.
795
+ \item The resolution advantage of GMP over CMP grows as $\beta$ decreases.
796
+ \end{itemize}
797
+
798
+ % ══════════════════════════════════════════════════════════════════════════════
799
+ % IX. CONCLUSION
800
+ % ══════════════════════════════════════════════════════════════════════════════
801
+ \section{Conclusion}\label{sec:conclusion}
802
+
803
+ We have presented \textbf{GMP (Gap‑Filled Market Profile)}, a universal construction that interpolates all intermediate price bins between consecutive observations. We formalised CMP and GMP, provided algorithms with complexity analysis, and derived the inverse relationship between bin size $\beta$ and profile resolution. The detailed 10‑point illustration and accompanying charts demonstrate that GMP yields a strictly denser and more informative profile, closing the gaps inherent in conventional methods. Future work may explore weighted interpolation and application across asset classes.
804
+
805
+ % ══════════════════════════════════════════════════════════════════════════════
806
+ % REFERENCES
807
+ % ══════════════════════════════════════════════════════════════════════════════
808
+ \begin{thebibliography}{10}
809
+
810
+ \bibitem{steidlmayer1986market}
811
+ J.~Steidlmayer, \emph{Market Profile}, Chicago Board of Trade, 1986.
812
+
813
+ \bibitem{dalton2007markets}
814
+ J.~F.~Dalton, E.~T.~Jones, and R.~B.~Dalton, \emph{Markets in Profile: Profiting from the Auction Process}, John Wiley \& Sons, 2007.
815
+
816
+ \bibitem{clark1973subordinated}
817
+ P.~K.~Clark, ``A subordinated stochastic process model with finite variance for speculative prices,'' \emph{Econometrica}, vol.~41, no.~1, pp.~135--155, 1973.
818
+
819
+ \bibitem{ane2000order}
820
+ T.~An\'{e} and H.~Geman, ``Order flow, transaction clock, and normality of asset returns,'' \emph{The Journal of Finance}, vol.~55, no.~5, pp.~2259--2284, 2000.
821
+
822
+ \bibitem{glosten1985bid}
823
+ L.~R.~Glosten and P.~R.~Milgrom, ``Bid, ask and transaction prices in a specialist market with heterogeneously informed traders,'' \emph{Journal of Financial Economics}, vol.~14, no.~1, pp.~71--100, 1985.
824
+
825
+ \bibitem{ohara1995market}
826
+ M.~O'Hara, \emph{Market Microstructure Theory}, Blackwell, 1995.
827
+
828
+ \bibitem{madhavan2000market}
829
+ A.~Madhavan, ``Market microstructure: A survey,'' \emph{Journal of Financial Markets}, vol.~3, no.~3, pp.~205--258, 2000.
830
+
831
+ \end{thebibliography}
832
+
833
+ \end{document}
mBA-GMP.v3/cmp_profile.csv ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ bin (with binsize = 1 symbol's price unit),price from,price until,datapoint group,number of profile's stacks
2
+ 1,3000,3001,A,1
3
+ 2,3001,3002,,0
4
+ 3,3002,3003,C,1
5
+ 4,3003,3004,BGIJ,4
6
+ 5,3004,3005,H,1
7
+ 6,3005,3006,,0
8
+ 7,3006,3007,,0
9
+ 8,3007,3008,E,1
10
+ 9,3008,3009,,0
11
+ 10,3009,3010,DF,2
mBA-GMP.v3/datapoints.csv ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ datapoint,x-axis trades (raw trades or time),y-axis Price
2
+ A,1,3000.914
3
+ B,2,3003.837
4
+ C,3,3002.432
5
+ D,4,3009.892
6
+ E,5,3007.698
7
+ F,6,3009.176
8
+ G,7,3003.381
9
+ H,8,3004.283
10
+ I,9,3003.512
11
+ J,10,3003.012
mBA-GMP.v3/fig_cmp_profile.png ADDED
mBA-GMP.v3/fig_cmp_vs_gmp.png ADDED

Git LFS Details

  • SHA256: e2e77b3cc26d74929fb66722cab8af53d4dda52b0c4051c828965f10920e0a81
  • Pointer size: 131 Bytes
  • Size of remote file: 131 kB
mBA-GMP.v3/fig_combined_3panel.png ADDED

Git LFS Details

  • SHA256: abf7574bc9377fb7aea265fd5c39671341ad8a1a7a1c6ce814b78c8cf2aaba43
  • Pointer size: 131 Bytes
  • Size of remote file: 238 kB
mBA-GMP.v3/fig_gmp_profile.png ADDED
mBA-GMP.v3/fig_price_scatter.png ADDED

Git LFS Details

  • SHA256: d0bfbedd85715cfbfe6a1d7cd1bf74ee52155a5c0d963aa1a9ea0a171e470971
  • Pointer size: 131 Bytes
  • Size of remote file: 108 kB
mBA-GMP.v3/fig_updown_footprint.png ADDED

Git LFS Details

  • SHA256: 1712bcd8d57fc41e3068db5c65b731eea2eeac8c8c50bea66271898c77381607
  • Pointer size: 131 Bytes
  • Size of remote file: 116 kB
mBA-GMP.v3/generate_profiles.py ADDED
@@ -0,0 +1,620 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ generate_profiles.py — mBA-GMP.v3 Dataframe & Chart Generator
4
+ ==============================================================
5
+ Produces CSV files and publication-quality PNG charts demonstrating the
6
+ Conventional Market Profile (CMP), Gap-filled Market Profile (GMP),
7
+ and Up/Down-Bin Footprint Profile using a 10-datapoint XAUUSD example.
8
+
9
+ Outputs:
10
+ CSV: datapoints.csv, cmp_profile.csv, gmp_profile.csv,
11
+ updown_profile.csv
12
+ PNG: fig_price_scatter.png, fig_cmp_profile.png,
13
+ fig_gmp_profile.png, fig_cmp_vs_gmp.png,
14
+ fig_updown_footprint.png
15
+ """
16
+
17
+ import math
18
+ import csv
19
+ import os
20
+
21
+ # ── Try to import optional plotting libs ─────────────────────────────────────
22
+ try:
23
+ import matplotlib
24
+ matplotlib.use("Agg") # non-interactive backend
25
+ import matplotlib.pyplot as plt
26
+ import matplotlib.ticker as ticker
27
+ HAS_MPL = True
28
+ except ImportError:
29
+ HAS_MPL = False
30
+ print("[WARN] matplotlib not found – CSV files will still be generated "
31
+ "but PNG charts will be skipped.")
32
+
33
+ # ══════════════════════════════════════════════════════════════════════════════
34
+ # 1. RAW DATAPOINTS
35
+ # ══════════════════════════════════════════════════════════════════════════════
36
+
37
+ DATAPOINTS = [
38
+ ("A", 1, 3000.914),
39
+ ("B", 2, 3003.837),
40
+ ("C", 3, 3002.432),
41
+ ("D", 4, 3009.892),
42
+ ("E", 5, 3007.698),
43
+ ("F", 6, 3009.176),
44
+ ("G", 7, 3003.381),
45
+ ("H", 8, 3004.283),
46
+ ("I", 9, 3003.512),
47
+ ("J", 10, 3003.012),
48
+ ]
49
+
50
+ BIN_SIZE = 1 # β = 1 symbol price unit
51
+
52
+ # ══════════════════════════════════════════════════════════════════════════════
53
+ # 2. HELPER FUNCTIONS
54
+ # ══════════════════════════════════════════════════════════════════════════════
55
+
56
+ def bin_index(price: float, beta: float = BIN_SIZE) -> int:
57
+ """Return the bin index for a given price: floor(price / β)."""
58
+ return int(math.floor(price / beta))
59
+
60
+
61
+ def bin_range(price: float, beta: float = BIN_SIZE):
62
+ """Return (price_from, price_until) for the bin containing *price*."""
63
+ b = bin_index(price, beta)
64
+ return b * beta, (b + 1) * beta
65
+
66
+
67
+ def make_bin_key(b: int, beta: float = BIN_SIZE):
68
+ """Return (bin_number_1based, price_from, price_until) for bin index *b*."""
69
+ return (b * beta, (b + 1) * beta)
70
+
71
+ # ══════════════════════════════════════════════════════════════════════════════
72
+ # 3. CMP CONSTRUCTION
73
+ # ══════════════════════════════════════════════════════════════════════════════
74
+
75
+ def build_cmp(datapoints, beta=BIN_SIZE):
76
+ """
77
+ Build CMP profile.
78
+ Returns dict: bin_index -> {"labels": [str], "count": int}
79
+ """
80
+ profile = {}
81
+ for label, _trade, price in datapoints:
82
+ b = bin_index(price, beta)
83
+ if b not in profile:
84
+ profile[b] = {"labels": [], "count": 0}
85
+ profile[b]["labels"].append(label)
86
+ profile[b]["count"] += 1
87
+ return profile
88
+
89
+ # ══════════════════════════════════════════════════════════════════════════════
90
+ # 4. GMP CONSTRUCTION
91
+ # ══════════════════════════════════════════════════════════════════════════════
92
+
93
+ def build_gmp(datapoints, beta=BIN_SIZE):
94
+ """
95
+ Build GMP profile (gap-filled).
96
+
97
+ Convention (matches the dataframe approach):
98
+ 1. Every datapoint fills its OWN bin with its own label (same as CMP).
99
+ 2. For each consecutive pair (i, i+1), the intermediate bins BETWEEN
100
+ b(p_i) and b(p_{i+1}) — exclusive of both endpoints — are filled
101
+ with the SOURCE datapoint's label (datapoint i).
102
+
103
+ Returns dict: bin_index -> {"labels": [str], "count": int}
104
+ """
105
+ profile = {}
106
+
107
+ def add_to_bin(b, label):
108
+ if b not in profile:
109
+ profile[b] = {"labels": [], "count": 0}
110
+ profile[b]["labels"].append(label)
111
+ profile[b]["count"] += 1
112
+
113
+ # ── Step 1: CMP-style placement — each datapoint fills its own bin ──
114
+ for label, _trade, price in datapoints:
115
+ add_to_bin(bin_index(price, beta), label)
116
+
117
+ # ── Step 2: Gap-fill intermediate bins between consecutive pairs ─────
118
+ for idx in range(len(datapoints) - 1):
119
+ src_label, _, src_price = datapoints[idx]
120
+ _dst_label, _, dst_price = datapoints[idx + 1]
121
+
122
+ b_from = bin_index(src_price, beta)
123
+ b_to = bin_index(dst_price, beta)
124
+
125
+ if abs(b_to - b_from) <= 1:
126
+ # Adjacent or same bin — no intermediate bins to fill
127
+ continue
128
+
129
+ direction = 1 if b_to > b_from else -1
130
+ # Fill bins strictly BETWEEN b_from and b_to (exclusive of both)
131
+ b = b_from + direction
132
+ while b != b_to:
133
+ add_to_bin(b, src_label)
134
+ b += direction
135
+
136
+ return profile
137
+
138
+ # ══════════════════════════════════════════════════════════════════════════════
139
+ # 4b. UP/DOWN-BIN FOOTPRINT PROFILE CONSTRUCTION
140
+ # ══════════════════════════════════════════════════════════════════════════════
141
+
142
+ def build_updown_profile(datapoints, beta=BIN_SIZE):
143
+ """
144
+ Build the Up/Down-Bin Footprint Profile.
145
+
146
+ For each consecutive pair of datapoints, every bin on the gap-filled
147
+ path (excluding the source datapoint's own bin) is classified as an
148
+ up-bin or down-bin depending on the direction of the move.
149
+
150
+ The first datapoint (no prior movement) receives 0 up / 0 down.
151
+
152
+ Returns dict: bin_index -> {"labels": [str], "up": int, "down": int}
153
+ """
154
+ # ── Collect GMP group labels (reuse from GMP logic) ──────────────────
155
+ groups = {} # bin_index -> list of labels
156
+
157
+ def add_label(b, label):
158
+ if b not in groups:
159
+ groups[b] = []
160
+ groups[b].append(label)
161
+
162
+ # CMP placement
163
+ for label, _trade, price in datapoints:
164
+ add_label(bin_index(price, beta), label)
165
+
166
+ # Gap-fill intermediate labels
167
+ for idx in range(len(datapoints) - 1):
168
+ src_label, _, src_price = datapoints[idx]
169
+ _, _, dst_price = datapoints[idx + 1]
170
+ b_from = bin_index(src_price, beta)
171
+ b_to = bin_index(dst_price, beta)
172
+ if abs(b_to - b_from) <= 1:
173
+ continue
174
+ direction = 1 if b_to > b_from else -1
175
+ b = b_from + direction
176
+ while b != b_to:
177
+ add_label(b, src_label)
178
+ b += direction
179
+
180
+ # ── Now compute up/down counts per bin ────────────────────────────────
181
+ up_counts = {} # bin_index -> int
182
+ down_counts = {} # bin_index -> int
183
+
184
+ for idx in range(len(datapoints) - 1):
185
+ _, _, src_price = datapoints[idx]
186
+ _, _, dst_price = datapoints[idx + 1]
187
+
188
+ b_from = bin_index(src_price, beta)
189
+ b_to = bin_index(dst_price, beta)
190
+
191
+ if b_from == b_to:
192
+ # Same bin, but price might have moved
193
+ if dst_price > src_price:
194
+ up_counts[b_from] = up_counts.get(b_from, 0) + 1
195
+ elif dst_price < src_price:
196
+ down_counts[b_from] = down_counts.get(b_from, 0) + 1
197
+ continue
198
+
199
+ is_up = b_to > b_from
200
+ direction = 1 if is_up else -1
201
+
202
+ # Every bin on the path AFTER the source bin (exclusive of source,
203
+ # inclusive of destination) gets a directional count.
204
+ b = b_from + direction
205
+ while True:
206
+ if is_up:
207
+ up_counts[b] = up_counts.get(b, 0) + 1
208
+ else:
209
+ down_counts[b] = down_counts.get(b, 0) + 1
210
+ if b == b_to:
211
+ break
212
+ b += direction
213
+
214
+ # ── Merge into result dict ───────────────────────────────────────────
215
+ all_bins = set(groups.keys()) | set(up_counts.keys()) | set(down_counts.keys())
216
+ profile = {}
217
+ for b in all_bins:
218
+ profile[b] = {
219
+ "labels": sorted(groups.get(b, [])),
220
+ "up": up_counts.get(b, 0),
221
+ "down": down_counts.get(b, 0),
222
+ }
223
+ return profile
224
+
225
+ # ══════════════════════════════════════════════════════════════���═══════════════
226
+ # 5. CSV OUTPUT
227
+ # ══════════════════════════════════════════════════════════════════════════════
228
+
229
+ def write_datapoints_csv(datapoints, path="datapoints.csv"):
230
+ """Write the raw datapoints to CSV."""
231
+ with open(path, "w", newline="") as f:
232
+ w = csv.writer(f)
233
+ w.writerow(["datapoint", "x-axis trades (raw trades or time)", "y-axis Price"])
234
+ for label, trade, price in datapoints:
235
+ w.writerow([label, trade, f"{price:.3f}"])
236
+ print(f"[OK] {path}")
237
+
238
+
239
+ def write_profile_csv(profile, beta, path):
240
+ """Write a profile (CMP or GMP) to CSV, bins numbered 1..N from lowest."""
241
+ if not profile:
242
+ print(f"[WARN] Empty profile, skipping {path}")
243
+ return
244
+
245
+ b_min = min(profile.keys())
246
+ b_max = max(profile.keys())
247
+
248
+ # Include ALL bins from b_min to b_max (even empty ones)
249
+ rows = []
250
+ bin_number = 1
251
+ for b in range(b_min, b_max + 1):
252
+ p_from = b * beta
253
+ p_until = (b + 1) * beta
254
+ info = profile.get(b, {"labels": [], "count": 0})
255
+ group = "".join(sorted(info["labels"]))
256
+ count = info["count"]
257
+ rows.append([bin_number, int(p_from), int(p_until), group, count])
258
+ bin_number += 1
259
+
260
+ with open(path, "w", newline="") as f:
261
+ w = csv.writer(f)
262
+ w.writerow([
263
+ f"bin (with binsize = {beta} symbol's price unit)",
264
+ "price from", "price until", "datapoint group",
265
+ "number of profile's stacks"
266
+ ])
267
+ for row in rows:
268
+ w.writerow(row)
269
+ print(f"[OK] {path}")
270
+
271
+
272
+ def write_updown_profile_csv(updown_profile, gmp_groups, beta, path):
273
+ """Write the Up/Down-Bin Footprint Profile to CSV."""
274
+ if not updown_profile:
275
+ print(f"[WARN] Empty profile, skipping {path}")
276
+ return
277
+
278
+ b_min = min(updown_profile.keys())
279
+ b_max = max(updown_profile.keys())
280
+
281
+ rows = []
282
+ bin_number = 1
283
+ for b in range(b_min, b_max + 1):
284
+ p_from = b * beta
285
+ p_until = (b + 1) * beta
286
+ info = updown_profile.get(b, {"labels": [], "up": 0, "down": 0})
287
+ group = "".join(info["labels"])
288
+ up_val = info["up"]
289
+ down_val = info["down"]
290
+ delta_val = up_val - down_val
291
+ rows.append([bin_number, int(p_from), int(p_until), group,
292
+ down_val, up_val, delta_val])
293
+ bin_number += 1
294
+
295
+ with open(path, "w", newline="") as f:
296
+ w = csv.writer(f)
297
+ w.writerow([
298
+ f"bin (with binsize = {beta} symbol's price unit)",
299
+ "price from", "price until", "datapoint group",
300
+ "down-bin profile's stacks", "up-bin profile's stacks",
301
+ "delta-bin profile's stacks"
302
+ ])
303
+ for row in rows:
304
+ w.writerow(row)
305
+ print(f"[OK] {path}")
306
+
307
+ # ══════════════════════════════════════════════════════════════════════════════
308
+ # 6. CHART GENERATION
309
+ # ══════════════════════════════════════════════════════════════════════════════
310
+
311
+ # ── Color palette (white / light theme) ──────────────────────────────────────
312
+ CLR_BG = "#ffffff"
313
+ CLR_FG = "#1a1a1a"
314
+ CLR_GRID = "#d0d0d0"
315
+ CLR_ACCENT1 = "#1565c0" # deep blue (scatter)
316
+ CLR_ACCENT2 = "#e65100" # deep orange (CMP)
317
+ CLR_ACCENT3 = "#2e7d32" # deep green (GMP)
318
+ CLR_MUTED = "#607d8b"
319
+ CLR_LABEL = "#333333" # label text
320
+
321
+ CHART_DPI = 300
322
+
323
+
324
+ def _apply_style(ax, title=""):
325
+ """Apply a consistent white/light theme to an axes object."""
326
+ ax.set_facecolor(CLR_BG)
327
+ ax.figure.set_facecolor(CLR_BG)
328
+ ax.tick_params(colors=CLR_FG, labelsize=8)
329
+ ax.xaxis.label.set_color(CLR_FG)
330
+ ax.yaxis.label.set_color(CLR_FG)
331
+ ax.title.set_color(CLR_FG)
332
+ for spine in ax.spines.values():
333
+ spine.set_color(CLR_GRID)
334
+ ax.grid(True, color=CLR_GRID, linewidth=0.5, alpha=0.4)
335
+ if title:
336
+ ax.set_title(title, fontsize=11, fontweight="bold", pad=10)
337
+
338
+
339
+ def chart_price_scatter(datapoints, path="fig_price_scatter.png", ax=None):
340
+ """Scatter + line plot of price vs trade index, labeled A–J."""
341
+ labels = [d[0] for d in datapoints]
342
+ trades = [d[1] for d in datapoints]
343
+ prices = [d[2] for d in datapoints]
344
+
345
+ standalone = ax is None
346
+ if standalone:
347
+ fig, ax = plt.subplots(figsize=(7, 4))
348
+ _apply_style(ax, "Price vs. Trade Index (Datapoints A–J)")
349
+
350
+ ax.plot(trades, prices, color=CLR_ACCENT1, linewidth=1.2, alpha=0.45,
351
+ zorder=1)
352
+ ax.scatter(trades, prices, color=CLR_ACCENT1, s=52, zorder=2,
353
+ edgecolors="white", linewidths=0.6)
354
+
355
+ for lbl, x, y in zip(labels, trades, prices):
356
+ ax.annotate(lbl, (x, y), textcoords="offset points",
357
+ xytext=(0, 10), ha="center", fontsize=8,
358
+ fontweight="bold", color=CLR_LABEL)
359
+
360
+ ax.set_xlabel("Trade Index (raw trades)", fontsize=9)
361
+ ax.set_ylabel("Price (USD)", fontsize=9)
362
+ ax.yaxis.set_major_formatter(ticker.FormatStrFormatter("%.0f"))
363
+
364
+ if standalone:
365
+ fig.tight_layout()
366
+ fig.savefig(path, dpi=CHART_DPI, bbox_inches="tight")
367
+ plt.close(fig)
368
+ print(f"[OK] {path}")
369
+
370
+
371
+ def _draw_profile(ax, profile, beta, title, bar_color):
372
+ """Draw a horizontal bar chart for a profile onto *ax*."""
373
+ b_min = min(profile.keys())
374
+ b_max = max(profile.keys())
375
+
376
+ bin_labels = []
377
+ stacks = []
378
+ groups = []
379
+ for b in range(b_min, b_max + 1):
380
+ p_from = b * beta
381
+ p_until = (b + 1) * beta
382
+ bin_labels.append(f"{int(p_from)}–{int(p_until)}")
383
+ info = profile.get(b, {"labels": [], "count": 0})
384
+ stacks.append(info["count"])
385
+ groups.append("".join(sorted(info["labels"])))
386
+
387
+ y_pos = range(len(bin_labels))
388
+ bars = ax.barh(y_pos, stacks, color=bar_color, edgecolor="white",
389
+ linewidth=0.5, height=0.7, alpha=0.85)
390
+
391
+ ax.set_yticks(y_pos)
392
+ ax.set_yticklabels(bin_labels, fontsize=7)
393
+ ax.set_xlabel("Stacks", fontsize=9)
394
+ ax.set_ylabel("Price Bin (USD)", fontsize=9)
395
+
396
+ # Annotate bars with datapoint group letters
397
+ max_s = max(stacks) if stacks else 1
398
+ for i, (bar, grp) in enumerate(zip(bars, groups)):
399
+ if grp:
400
+ ax.text(bar.get_width() + 0.12, bar.get_y() + bar.get_height() / 2,
401
+ grp, va="center", ha="left", fontsize=7, color=CLR_LABEL,
402
+ fontweight="bold")
403
+
404
+ ax.set_xlim(0, max_s + 2)
405
+ _apply_style(ax, title)
406
+
407
+
408
+ def chart_profile(profile, beta, path, title, bar_color):
409
+ """Standalone horizontal bar chart for a single profile (CMP or GMP)."""
410
+ if not profile:
411
+ return
412
+ fig, ax = plt.subplots(figsize=(6, 5))
413
+ _draw_profile(ax, profile, beta, title, bar_color)
414
+ fig.tight_layout()
415
+ fig.savefig(path, dpi=CHART_DPI, bbox_inches="tight")
416
+ plt.close(fig)
417
+ print(f"[OK] {path}")
418
+
419
+
420
+ def chart_cmp_vs_gmp(cmp_profile, gmp_profile, beta,
421
+ path="fig_cmp_vs_gmp.png"):
422
+ """Side-by-side comparison of CMP and GMP profiles (2-panel)."""
423
+ if not cmp_profile or not gmp_profile:
424
+ return
425
+
426
+ fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(11, 5), sharey=True)
427
+
428
+ _draw_profile(ax1, cmp_profile, beta, "CMP Profile", CLR_ACCENT2)
429
+ _draw_profile(ax2, gmp_profile, beta, "GMP Profile", CLR_ACCENT3)
430
+ ax2.set_ylabel("") # avoid duplicate y-label
431
+
432
+ fig.suptitle("CMP vs. GMP — 10-Datapoint Example (β = 1)",
433
+ fontsize=13, fontweight="bold", color=CLR_FG, y=1.01)
434
+ fig.tight_layout()
435
+ fig.savefig(path, dpi=CHART_DPI, bbox_inches="tight")
436
+ plt.close(fig)
437
+ print(f"[OK] {path}")
438
+
439
+
440
+ def chart_combined_3panel(datapoints, cmp_profile, gmp_profile, beta,
441
+ path="fig_combined_3panel.png"):
442
+ """Three-panel chart: Datapoints | CMP with letters | GMP with letters."""
443
+ if not cmp_profile or not gmp_profile:
444
+ return
445
+
446
+ fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(16, 5.5),
447
+ gridspec_kw={"width_ratios": [1.1, 1, 1]})
448
+
449
+ # ── Panel 1: Datapoints scatter with labels ──────────────────────────
450
+ labels = [d[0] for d in datapoints]
451
+ trades = [d[1] for d in datapoints]
452
+ prices = [d[2] for d in datapoints]
453
+
454
+ _apply_style(ax1, "Datapoints (A–J)")
455
+ ax1.plot(trades, prices, color=CLR_ACCENT1, linewidth=1.2, alpha=0.4,
456
+ zorder=1)
457
+ ax1.scatter(trades, prices, color=CLR_ACCENT1, s=52, zorder=2,
458
+ edgecolors="white", linewidths=0.6)
459
+ for lbl, x, y in zip(labels, trades, prices):
460
+ ax1.annotate(lbl, (x, y), textcoords="offset points",
461
+ xytext=(0, 10), ha="center", fontsize=9,
462
+ fontweight="bold", color=CLR_LABEL)
463
+ ax1.set_xlabel("Trade Index", fontsize=9)
464
+ ax1.set_ylabel("Price (USD)", fontsize=9)
465
+ ax1.yaxis.set_major_formatter(ticker.FormatStrFormatter("%.0f"))
466
+
467
+ # ── Panel 2: CMP with group letters ──────────────────────────────────
468
+ _draw_profile(ax2, cmp_profile, beta, "CMP with Letters", CLR_ACCENT2)
469
+
470
+ # ── Panel 3: GMP with group letters ──────────────────────────────────
471
+ _draw_profile(ax3, gmp_profile, beta, "GMP with Letters", CLR_ACCENT3)
472
+ ax3.set_ylabel("") # avoid duplicate y-label
473
+
474
+ fig.suptitle("Datapoints → CMP → GMP (β = 1)",
475
+ fontsize=14, fontweight="bold", color=CLR_FG, y=1.02)
476
+ fig.tight_layout()
477
+ fig.savefig(path, dpi=CHART_DPI, bbox_inches="tight")
478
+ plt.close(fig)
479
+ print(f"[OK] {path}")
480
+
481
+
482
+ def chart_updown_footprint(updown_profile, beta,
483
+ path="fig_updown_footprint.png"):
484
+ """Dual horizontal bar chart: down-bins (left/red) vs up-bins (right/teal)."""
485
+ if not updown_profile:
486
+ return
487
+
488
+ CLR_UP = "#00897b" # teal
489
+ CLR_DOWN = "#e53935" # red
490
+
491
+ b_min = min(updown_profile.keys())
492
+ b_max = max(updown_profile.keys())
493
+
494
+ bin_labels = []
495
+ up_vals = []
496
+ down_vals = []
497
+ delta_vals = []
498
+ for b in range(b_min, b_max + 1):
499
+ p_from = b * beta
500
+ p_until = (b + 1) * beta
501
+ bin_labels.append(f"{int(p_from)}-{int(p_until)}")
502
+ info = updown_profile.get(b, {"labels": [], "up": 0, "down": 0})
503
+ up_vals.append(info["up"])
504
+ down_vals.append(info["down"])
505
+ delta_vals.append(info["up"] - info["down"])
506
+
507
+ y_pos = list(range(len(bin_labels)))
508
+ max_val = max(max(up_vals, default=1), max(down_vals, default=1), 1)
509
+
510
+ fig, ax = plt.subplots(figsize=(8, 5.5))
511
+ _apply_style(ax, "Up/Down-Bin Footprint Profile (GMP-based)")
512
+
513
+ # Down bars extend to the LEFT (negative x)
514
+ bars_down = ax.barh(y_pos, [-d for d in down_vals], color=CLR_DOWN,
515
+ edgecolor="white", linewidth=0.5, height=0.65,
516
+ alpha=0.85, label="Down-bin")
517
+ # Up bars extend to the RIGHT (positive x)
518
+ bars_up = ax.barh(y_pos, up_vals, color=CLR_UP,
519
+ edgecolor="white", linewidth=0.5, height=0.65,
520
+ alpha=0.85, label="Up-bin")
521
+
522
+ # Annotate bars with counts
523
+ for i, (dv, uv, deltav) in enumerate(zip(down_vals, up_vals, delta_vals)):
524
+ if dv > 0:
525
+ ax.text(-dv - 0.15, i, str(dv), va="center", ha="right",
526
+ fontsize=7, color=CLR_DOWN, fontweight="bold")
527
+ if uv > 0:
528
+ ax.text(uv + 0.15, i, str(uv), va="center", ha="left",
529
+ fontsize=7, color=CLR_UP, fontweight="bold")
530
+ # Delta annotation at far right
531
+ delta_color = CLR_UP if deltav > 0 else (CLR_DOWN if deltav < 0 else CLR_MUTED)
532
+ delta_str = f"{deltav:+d}" if deltav != 0 else "0"
533
+ ax.text(max_val + 1.0, i, f"\u0394={delta_str}", va="center", ha="left",
534
+ fontsize=6.5, color=delta_color)
535
+
536
+ ax.set_yticks(y_pos)
537
+ ax.set_yticklabels(bin_labels, fontsize=7)
538
+ ax.set_xlabel("Stacks", fontsize=9)
539
+ ax.set_ylabel("Price Bin (USD)", fontsize=9)
540
+ ax.axvline(0, color=CLR_FG, linewidth=0.6)
541
+ ax.set_xlim(-max_val - 1.5, max_val + 2.5)
542
+ ax.legend(loc="lower right", fontsize=8)
543
+
544
+ fig.tight_layout()
545
+ fig.savefig(path, dpi=CHART_DPI, bbox_inches="tight")
546
+ plt.close(fig)
547
+ print(f"[OK] {path}")
548
+
549
+ # ══════════════════════════════════════════════════════════════════════════════
550
+ # 7. MAIN
551
+ # ══════════════════════════════════════════════════════════════════════════════
552
+
553
+ def main():
554
+ out_dir = os.path.dirname(os.path.abspath(__file__))
555
+
556
+ # ── Build profiles ────────────────────────────────────────────────────
557
+ cmp = build_cmp(DATAPOINTS, BIN_SIZE)
558
+ gmp = build_gmp(DATAPOINTS, BIN_SIZE)
559
+ updown = build_updown_profile(DATAPOINTS, BIN_SIZE)
560
+
561
+ # ── Write CSVs ────────────────────────────────────────────────────────
562
+ write_datapoints_csv(DATAPOINTS, os.path.join(out_dir, "datapoints.csv"))
563
+ write_profile_csv(cmp, BIN_SIZE, os.path.join(out_dir, "cmp_profile.csv"))
564
+ write_profile_csv(gmp, BIN_SIZE, os.path.join(out_dir, "gmp_profile.csv"))
565
+ write_updown_profile_csv(updown, gmp, BIN_SIZE,
566
+ os.path.join(out_dir, "updown_profile.csv"))
567
+
568
+ # ── Generate charts ───────────────────────────────────────────────────
569
+ if HAS_MPL:
570
+ chart_price_scatter(
571
+ DATAPOINTS, os.path.join(out_dir, "fig_price_scatter.png"))
572
+ chart_profile(
573
+ cmp, BIN_SIZE, os.path.join(out_dir, "fig_cmp_profile.png"),
574
+ "Conventional Market Profile (CMP)", CLR_ACCENT2)
575
+ chart_profile(
576
+ gmp, BIN_SIZE, os.path.join(out_dir, "fig_gmp_profile.png"),
577
+ "Gap-Filled Market Profile (GMP)", CLR_ACCENT3)
578
+ chart_cmp_vs_gmp(
579
+ cmp, gmp, BIN_SIZE,
580
+ os.path.join(out_dir, "fig_cmp_vs_gmp.png"))
581
+ chart_combined_3panel(
582
+ DATAPOINTS, cmp, gmp, BIN_SIZE,
583
+ os.path.join(out_dir, "fig_combined_3panel.png"))
584
+ chart_updown_footprint(
585
+ updown, BIN_SIZE,
586
+ os.path.join(out_dir, "fig_updown_footprint.png"))
587
+
588
+ # ── Print summary ─────────────────────────────────────────────────────
589
+ print("\n── CMP Profile ──")
590
+ b_min = min(cmp.keys())
591
+ b_max = max(cmp.keys())
592
+ for b in range(b_min, b_max + 1):
593
+ info = cmp.get(b, {"labels": [], "count": 0})
594
+ grp = "".join(sorted(info["labels"]))
595
+ print(f" Bin {b - b_min + 1}: {int(b * BIN_SIZE)}–{int((b+1) * BIN_SIZE)} "
596
+ f"group={grp or '—':6s} stacks={info['count']}")
597
+
598
+ print("\n── GMP Profile ──")
599
+ b_min = min(gmp.keys())
600
+ b_max = max(gmp.keys())
601
+ for b in range(b_min, b_max + 1):
602
+ info = gmp.get(b, {"labels": [], "count": 0})
603
+ grp = "".join(sorted(info["labels"]))
604
+ print(f" Bin {b - b_min + 1}: {int(b * BIN_SIZE)}–{int((b+1) * BIN_SIZE)} "
605
+ f"group={grp or '—':6s} stacks={info['count']}")
606
+
607
+ print("\n── Up/Down-Bin Footprint Profile ──")
608
+ b_min = min(updown.keys())
609
+ b_max = max(updown.keys())
610
+ for b in range(b_min, b_max + 1):
611
+ info = updown.get(b, {"labels": [], "up": 0, "down": 0})
612
+ grp = "".join(info["labels"])
613
+ delta = info["up"] - info["down"]
614
+ print(f" Bin {b - b_min + 1}: {int(b * BIN_SIZE)}–{int((b+1) * BIN_SIZE)} "
615
+ f"group={grp or '—':6s} up={info['up']} down={info['down']} "
616
+ f"delta={delta:+d}")
617
+
618
+
619
+ if __name__ == "__main__":
620
+ main()
mBA-GMP.v3/gmp.tex ADDED
@@ -0,0 +1,813 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ \documentclass[conference]{IEEEtran}
2
+
3
+ % ── Packages ──────────────────────────────────────────────────────────────────
4
+ \usepackage{cite}
5
+ \usepackage{amsmath,amssymb,amsfonts}
6
+ \usepackage{algorithmic}
7
+ \usepackage{algorithm}
8
+ \usepackage{graphicx}
9
+ \usepackage{textcomp}
10
+ \usepackage{booktabs}
11
+ \usepackage{multirow}
12
+ \usepackage{tikz}
13
+ \usepackage{pgfplots}
14
+ \pgfplotsset{compat=1.18}
15
+ \usepackage{hyperref}
16
+ \usepackage{cleveref}
17
+
18
+ % ── Meta ──────────────────────────────────────────────────────────────────────
19
+ \hypersetup{
20
+ colorlinks=true,
21
+ linkcolor=blue,
22
+ citecolor=blue,
23
+ urlcolor=blue
24
+ }
25
+
26
+ \def\BibTeX{{\rm B\kern-.05em{\sc i\kern-.025em b}\kern-.08em
27
+ T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}}
28
+
29
+ \begin{document}
30
+
31
+ % ══════════════════════════════════════════════════════════════════════════════
32
+ % TITLE
33
+ % ══════════════════════════════════════════════════════════════════════════════
34
+
35
+ \title{GMP: Gap-filled Market Profile Construction for Any Data Points}
36
+
37
+ \author{\IEEEauthorblockN{ConQ Research Team}\\
38
+ \IEEEauthorblockA{\textit{Continual Quasars}\\
39
+ \today}
40
+ }
41
+
42
+ \maketitle
43
+
44
+ % ══════════════════════════════════════════════════════════════════════════════
45
+ % ABSTRACT
46
+ % ══════════════════════════════════════════════════════════════════════════════
47
+ \begin{abstract}
48
+ Conventional Market Profile (CMP) aggregates price activity into histogram bins, but when applied to any ordered sequence of price points (ticks, candlesticks, or other sampled data), it leaves bins between consecutive points empty. We propose \textbf{GMP (Gap-Filled Market Profile)}, a universal construction method that (i) operates on any sequence of price observations and (ii) interpolates every intermediate price bin traversed between successive points, producing a \emph{gap-filled} profile. Building on this gap‑filled structure, we introduce an \emph{Up/Down‑Bin Footprint Profile} that classifies each bin's contribution directionally, revealing net upward or downward pressure across the price traversal. We formalise CMP and GMP with explicit algorithms, derive the relationship between bin count and a user‑defined bin‑size parameter $\beta$, and present a complete worked example showing how points are grouped into bins under CMP, how gap‑filling transforms the sparse CMP output into a dense GMP profile, and how directional footprints are assigned. Charts and tables demonstrate that GMP yields a strictly denser and more informative distribution than CMP, independent of the original data source.
49
+ \end{abstract}
50
+
51
+ \begin{IEEEkeywords}
52
+ Market Profile, gap-filling interpolation, price bins, directional footprint, high-frequency data, time series
53
+ \end{IEEEkeywords}
54
+
55
+
56
+ % ── Side‑by‑side introductory CMP vs GMP figure ─────────────────────────────
57
+ \begin{figure}[!t]
58
+ \centering
59
+ \begin{tikzpicture}
60
+ \begin{axis}[
61
+ title={\textbf{CMP Profile}},
62
+ xbar,
63
+ xlabel={Stacks},
64
+ ylabel={Price (USD)},
65
+ ytick={3000,3001,...,3010},
66
+ yticklabel style={font=\scriptsize},
67
+ xmin=0, xmax=2,
68
+ ymin=2999.5, ymax=3010.5,
69
+ bar width=4pt,
70
+ width=0.42\columnwidth,
71
+ height=6.5cm,
72
+ enlarge y limits=0.05,
73
+ nodes near coords,
74
+ nodes near coords style={font=\tiny},
75
+ name=cmp
76
+ ]
77
+ \addplot[fill=gray!60, draw=black] coordinates {
78
+ (1,3000) (0,3001) (0,3002) (0,3003) (0,3004) (0,3005)
79
+ (0,3006) (0,3007) (0,3008) (0,3009) (1,3010)
80
+ };
81
+ \end{axis}
82
+
83
+ \begin{axis}[
84
+ title={\textbf{GMP Profile}},
85
+ xbar,
86
+ xlabel={Stacks},
87
+ ylabel={},
88
+ ytick={3000,3001,...,3010},
89
+ yticklabel style={font=\scriptsize},
90
+ xmin=0, xmax=2,
91
+ ymin=2999.5, ymax=3010.5,
92
+ bar width=4pt,
93
+ width=0.42\columnwidth,
94
+ height=6.5cm,
95
+ enlarge y limits=0.05,
96
+ nodes near coords,
97
+ nodes near coords style={font=\tiny},
98
+ at={(cmp.east)},
99
+ anchor=west,
100
+ xshift=1.2cm
101
+ ]
102
+ \addplot[fill=blue!50, draw=black] coordinates {
103
+ (1,3000) (1,3001) (1,3002) (1,3003) (1,3004) (1,3005)
104
+ (1,3006) (1,3007) (1,3008) (1,3009) (1,3010)
105
+ };
106
+ \end{axis}
107
+ \end{tikzpicture}
108
+ \caption{Horizontal histogram comparison of CMP (left, grey) and GMP (right, blue) for a price move from 3000 to 3010 with $\beta=1$. CMP shows activity only at the two observed prices; GMP fills all 11 traversed bins. Gap‑filling applies to any data sequence.}
109
+ \label{fig:profile}
110
+ \end{figure}
111
+
112
+ % ══════════════════════════════════════════════════════════════════════════════
113
+ % I. INTRODUCTION
114
+ % ══════════════════════════════════════════════════════════════════════════════
115
+ \section{Introduction}\label{sec:intro}
116
+
117
+ The Market Profile, introduced by Steidlmayer~\cite{steidlmayer1986market} and later formalised by Dalton et~al.~\cite{dalton2007markets}, represents price activity as a horizontal histogram whose bins correspond to discrete price levels and whose bar lengths (``stacks'') reflect the amount of activity observed at each level. In practice, most implementations construct the profile from candlestick TOCHLV (time, open, close, high, low, volume) data: each candle contributes one stack to every bin between its high and low.
118
+
119
+ This approach suffers from a fundamental shortcoming when applied to any sequence of discrete price points: when consecutive points are separated by several price levels, the conventional profile records activity only at the two observed prices, ignoring the fact that price must have traversed every intermediate level. This gap neglect is not specific to any data source—it occurs with ticks, candlesticks, or any sampled price series.
120
+
121
+ We address this issue with \textbf{GMP (Gap‑Filled Market Profile)}. The construction rule is universal: for every ordered sequence of price observations $\{p_i\}_{i=1}^{N}$, every bin between two successive points receives an interpolated stack, producing a profile with no gaps. The method does not depend on the original data frequency, source, or aggregation level; it applies equally to millisecond tick data, hourly candlesticks, or irregularly sampled price records.
122
+
123
+ The main contributions of this work are:
124
+ \begin{enumerate}
125
+ \item A rigorous formalisation of CMP and GMP with explicit algorithms and complexity analyses.
126
+ \item A theoretical relationship between the user‑controlled bin‑size parameter $\beta$ and profile resolution, including a scaling proposition.
127
+ \item A universal gap‑filling methodology that can be applied to any ordered price sequence, irrespective of source.
128
+ \item The introduction of an \emph{Up/Down‑Bin Footprint Profile}, a directional classification derived purely from the price traversal without requiring volume or order‑book data.
129
+ \item A complete, self‑contained illustration of the construction on a ten‑point price sequence, demonstrating all theoretical constructs.
130
+ \end{enumerate}
131
+
132
+ The remainder of this paper is organised as follows. \Cref{sec:related} surveys related work. \Cref{sec:prelim} establishes notation. \Cref{sec:method} defines CMP and GMP formally, presents the GMP algorithm, and introduces the Up/Down‑Bin Footprint Profile. \Cref{sec:walkthrough} provides a complete profile construction example using a 10‑point price sequence. \Cref{sec:binsize} analyses the effect of bin size on profile resolution. \Cref{sec:example} offers a minimal illustrative example. \Cref{sec:discussion} discusses theoretical implications, and \Cref{sec:conclusion} concludes.
133
+
134
+ % ══════════════════════════════════════════════════════════════════════════════
135
+ % II. RELATED WORK
136
+ % ══════════════════════════════════════════════════════════════════════════════
137
+ \section{Related Work}\label{sec:related}
138
+
139
+ \subsection{Market Profile}
140
+ The Market Profile concept originates with Steidlmayer's observation that price distributions at each level reveal where market participants find ``fair value''~\cite{steidlmayer1986market}. Dalton et~al.~\cite{dalton2007markets} extended the framework with auction‑market theory, using half‑hour brackets as time‑price opportunities (TPOs). Both formulations rely on time‑based bars rather than raw ticks, but the underlying logic of binning price activity is independent of the data source.
141
+
142
+ \subsection{Interpolation in Financial Time Series}
143
+ Interpolation techniques are common in high‑frequency finance. Clark~\cite{clark1973subordinated} demonstrated that subordinating returns to trade‑count time yields closer‑to‑Gaussian distributions, motivating trade‑indexed analysis. An\'{e} and Geman~\cite{ane2000order} confirmed that business‑time transformations normalise returns at the tick level. The gap‑filling approach we propose is conceptually similar to linear interpolation on the price axis, but applied to histogram bin counts rather than to prices themselves.
144
+
145
+ \subsection{Footprint and Order‑Flow Analysis}
146
+ Market microstructure theory, including Glosten and Milgrom~\cite{glosten1985bid}, O'Hara~\cite{ohara1995market}, and Madhavan~\cite{madhavan2000market}, provides foundations for analysing directional pressure. Traditional footprint charts distinguish trades at bid versus ask prices. Our Up/Down‑Bin Footprint provides a complementary directional classification derived purely from the sequence of price observations, without requiring volume or order‑book data.
147
+
148
+ % ══════════════════════════════════════════════════════════════════════════════
149
+ % III. PRELIMINARIES
150
+ % ══════════════════════════════════════════════════════════════════════════════
151
+ \section{Preliminaries}\label{sec:prelim}
152
+
153
+ \Cref{tab:notation} summarises the notation used throughout.
154
+
155
+ \begin{table}[!t]
156
+ \centering
157
+ \caption{Notation Summary}
158
+ \label{tab:notation}
159
+ \begin{tabular}{@{}cl@{}}
160
+ \toprule
161
+ \textbf{Symbol} & \textbf{Description} \\
162
+ \midrule
163
+ $N$ & Total number of price observations in the sequence \\
164
+ $p_i$ & Price of the $i$-th observation, $i\in\{1,\dots,N\}$ \\
165
+ $\beta$ & Bin size (price units per bin); default $\beta=1$ \\
166
+ $b(p)$ & Bin index of price $p$: $b(p)=\lfloor p/\beta \rfloor$ \\
167
+ $S[k]$ & Stack count (profile value) at bin~$k$ \\
168
+ $\Delta_i$ & Price displacement: $\Delta_i = p_i - p_{i-1}$ \\
169
+ $K_i$ & Number of bins traversed from observation $i{-}1$ to $i$ \\
170
+ $U[k]$ & Up‑bin count at bin $k$ \\
171
+ $D[k]$ & Down‑bin count at bin $k$ \\
172
+ $\delta[k]$ & Net footprint delta at bin $k$: $\delta[k] = U[k] - D[k]$ \\
173
+ \bottomrule
174
+ \end{tabular}
175
+ \end{table}
176
+
177
+ \begin{definition}[Price observation sequence]
178
+ A \emph{price observation sequence} is an ordered set $\mathcal{P}=\{(t_i,\,p_i)\}_{i=1}^{N}$ where $t_i$ is an index (time, trade number, or any monotonic identifier) and $p_i$ is the observed price.
179
+ \end{definition}
180
+
181
+ \begin{definition}[Bin]
182
+ Given bin size $\beta>0$, the \emph{bin} for price $p$ is the integer index
183
+ \begin{equation}\label{eq:bin}
184
+ b(p) = \left\lfloor \frac{p}{\beta} \right\rfloor.
185
+ \end{equation}
186
+ All prices $p$ satisfying $k\beta \le p < (k+1)\beta$ map to bin~$k$.
187
+ \end{definition}
188
+
189
+ \begin{definition}[Market Profile]
190
+ A \emph{market profile} is a mapping $S:\mathbb{Z}\to\mathbb{N}_0$ where $S[k]$ counts the number of stacks accumulated at bin~$k$.
191
+ \end{definition}
192
+
193
+ % ══════════════════════════════════════════════════════════════════════════════
194
+ % IV. METHODOLOGY
195
+ % ══════════════════════════════════════════════════════════════════════════════
196
+ \section{Methodology}\label{sec:method}
197
+
198
+ \subsection{Conventional Market Profile (CMP)}\label{sec:cmp}
199
+
200
+ CMP records a stack only at the bin of each observed data point:
201
+ \begin{equation}\label{eq:cmp}
202
+ S_{\text{CMP}}[k] \;=\; \sum_{i=1}^{N} \mathbf{1}\!\bigl[b(p_i)=k\bigr],
203
+ \end{equation}
204
+ where $\mathbf{1}[\cdot]$ is the indicator function. Bins with no observed point receive $S_{\text{CMP}}[k]=0$.
205
+
206
+ \begin{algorithm}[!t]
207
+ \caption{CMP Construction}\label{alg:cmp}
208
+ \begin{algorithmic}[1]
209
+ \REQUIRE Price sequence $\{p_i\}_{i=1}^{N}$, bin size $\beta$
210
+ \ENSURE Profile array $S_{\text{CMP}}[\cdot]$
211
+ \STATE Initialise $S_{\text{CMP}}[k]\leftarrow 0\;\;\forall\,k$
212
+ \FOR{$i = 1$ \TO $N$}
213
+ \STATE $k \leftarrow \lfloor p_i / \beta \rfloor$
214
+ \STATE $S_{\text{CMP}}[k] \leftarrow S_{\text{CMP}}[k] + 1$
215
+ \ENDFOR
216
+ \RETURN $S_{\text{CMP}}$
217
+ \end{algorithmic}
218
+ \end{algorithm}
219
+
220
+ \textbf{Complexity.} CMP performs exactly $N$ bin‑index computations and $N$ increments, giving $\mathcal{O}(N)$ time complexity.
221
+
222
+ \subsection{Gap‑Filled Market Profile (GMP)}\label{sec:gmp}
223
+
224
+ GMP augments CMP by filling every \emph{intermediate} bin between two consecutive observations. The construction proceeds in two phases:
225
+
226
+ \begin{enumerate}
227
+ \item \textbf{CMP placement.} Each observation $p_i$ contributes one stack to its own bin $b(p_i)$, exactly as in CMP.
228
+ \item \textbf{Gap‑filling.} For each consecutive pair $(p_{i-1},\,p_i)$ with $i\ge 2$, every bin \emph{strictly between} $b(p_{i-1})$ and $b(p_i)$ (exclusive of both endpoints) receives one additional stack.
229
+ \end{enumerate}
230
+
231
+ Formally, writing $b_i = b(p_i)$:
232
+ \begin{equation}\label{eq:gmp}
233
+ S_{\text{GMP}}[k]
234
+ \;=\;
235
+ \underbrace{\sum_{i=1}^{N}\mathbf{1}\!\bigl[b_i=k\bigr]}_{S_{\text{CMP}}[k]}
236
+ \;+\;
237
+ \sum_{i=2}^{N}
238
+ \;\sum_{j=\min(b_{i-1},\,b_i)+1}^{\max(b_{i-1},\,b_i)-1}
239
+ \!\mathbf{1}\!\bigl[j=k\bigr].
240
+ \end{equation}
241
+
242
+ When $|b_i - b_{i-1}| \le 1$ (adjacent or same bin), the inner sum is empty and no gap‑filling occurs. When $|b_i - b_{i-1}| > 1$, the number of gap‑filled (intermediate) bins is
243
+ \begin{equation}\label{eq:Ki}
244
+ G_i \;=\; \bigl|b(p_i) - b(p_{i-1})\bigr| - 1.
245
+ \end{equation}
246
+ The total span of bins traversed, inclusive of both endpoints, is $K_i = G_i + 2 = |b_i - b_{i-1}| + 1$.
247
+
248
+ \begin{algorithm}[!t]
249
+ \caption{GMP Construction (Two‑Phase)}\label{alg:gmp}
250
+ \begin{algorithmic}[1]
251
+ \REQUIRE Price sequence $\{p_i\}_{i=1}^{N}$, bin size $\beta$
252
+ \ENSURE Profile array $S_{\text{GMP}}[\cdot]$
253
+ \STATE Initialise $S_{\text{GMP}}[k]\leftarrow 0\;\;\forall\,k$
254
+ \FOR{$i = 1$ \TO $N$} \COMMENT{Phase~1: CMP placement}
255
+ \STATE $S_{\text{GMP}}[\lfloor p_i/\beta \rfloor] \leftarrow S_{\text{GMP}}[\lfloor p_i/\beta \rfloor] + 1$
256
+ \ENDFOR
257
+ \FOR{$i = 2$ \TO $N$} \COMMENT{Phase~2: gap‑fill}
258
+ \STATE $k_{\text{from}} \leftarrow \lfloor p_{i-1}/\beta \rfloor$; $k_{\text{to}} \leftarrow \lfloor p_i/\beta \rfloor$
259
+ \IF{$|k_{\text{to}} - k_{\text{from}}| > 1$}
260
+ \STATE $d \leftarrow \text{sign}(k_{\text{to}} - k_{\text{from}})$
261
+ \FOR{$k = k_{\text{from}} + d$ \TO $k_{\text{to}} - d$ \textbf{step} $d$}
262
+ \STATE $S_{\text{GMP}}[k] \leftarrow S_{\text{GMP}}[k] + 1$
263
+ \ENDFOR
264
+ \ENDIF
265
+ \ENDFOR
266
+ \RETURN $S_{\text{GMP}}$
267
+ \end{algorithmic}
268
+ \end{algorithm}
269
+
270
+ \textbf{Complexity.} Let $D=\sum_{i=2}^{N}|b(p_i)-b(p_{i-1})|$ denote the cumulative bin displacement. GMP performs $\mathcal{O}(N + D)$ operations. In the degenerate case where all observations share the same bin, $D=0$ and GMP reduces to CMP. In the worst case, $D=\mathcal{O}(N\cdot\Delta p_{\max}/\beta)$.
271
+
272
+ \subsection{GMP as a Universal Construction}\label{sec:universal}
273
+
274
+ The key contribution of GMP is its universality: the gap‑filling rule applies to \emph{any} ordered price sequence, regardless of the original data's temporal spacing, source, or aggregation level. This includes:
275
+ \begin{itemize}
276
+ \item Raw tick data (millisecond‑resolution bid/ask records)
277
+ \item Candlestick TOCHLV sequences (using close, high, low, or any representative price)
278
+ \item Irregularly sampled price points
279
+ \item Synthetic price paths or simulated data
280
+ \end{itemize}
281
+
282
+ The only requirement is that the sequence be ordered (by time, trade index, or any monotonic index). The construction makes no assumption about the mechanism that generated the prices; it purely interpolates bin traversals between consecutive observations.
283
+
284
+ \subsection{Up/Down‑Bin Footprint Profile}\label{sec:updown}
285
+
286
+ Building upon the gap‑filled structure of GMP, we introduce a directional classification layer termed the \emph{Up/Down‑Bin Footprint Profile}. For every consecutive pair $(p_{i-1},\,p_i)$, the trajectory is evaluated as upward or downward based on the price difference. The origin bin $b(p_{i-1})$ is assigned no directional credit for this move (it has already been evaluated by prior action). However, every subsequent bin along the traversed path up to and including the destination bin $b(p_i)$ increments its \emph{up‑bin} count $U[k]$ if $p_i > p_{i-1}$, or its \emph{down‑bin} count $D[k]$ if $p_i \le p_{i-1}$.
287
+
288
+ \begin{algorithm}[!t]
289
+ \caption{Up/Down‑Bin Footprint Construction}\label{alg:updown}
290
+ \begin{algorithmic}[1]
291
+ \REQUIRE Price sequence $\{p_i\}_{i=1}^{N}$, bin size $\beta$
292
+ \ENSURE Profile arrays $U[\cdot], D[\cdot], \delta[\cdot]$
293
+ \STATE Initialise $U[k]\leftarrow 0, D[k]\leftarrow 0\;\;\forall\,k$
294
+ \FOR{$i = 2$ \TO $N$}
295
+ \STATE $k_{\text{from}} \leftarrow \lfloor p_{i-1}/\beta \rfloor$; $k_{\text{to}} \leftarrow \lfloor p_i/\beta \rfloor$
296
+ \IF{$k_{\text{from}} = k_{\text{to}}$}
297
+ \IF{$p_i > p_{i-1}$}
298
+ \STATE $U[k_{\text{from}}] \leftarrow U[k_{\text{from}}] + 1$
299
+ \ELSE
300
+ \STATE $D[k_{\text{from}}] \leftarrow D[k_{\text{from}}] + 1$
301
+ \ENDIF
302
+ \STATE \textbf{continue}
303
+ \ENDIF
304
+ \STATE $\text{is\_up} \leftarrow (k_{\text{to}} > k_{\text{from}})$
305
+ \STATE $d \leftarrow \text{sign}(k_{\text{to}} - k_{\text{from}})$
306
+ \STATE $k \leftarrow k_{\text{from}} + d$
307
+ \WHILE{\textbf{true}}
308
+ \IF{$\text{is\_up}$}
309
+ \STATE $U[k] \leftarrow U[k] + 1$
310
+ \ELSE
311
+ \STATE $D[k] \leftarrow D[k] + 1$
312
+ \ENDIF
313
+ \IF{$k = k_{\text{to}}$}
314
+ \STATE \textbf{break}
315
+ \ENDIF
316
+ \STATE $k \leftarrow k + d$
317
+ \ENDWHILE
318
+ \ENDFOR
319
+ \FORALL{$k$}
320
+ \STATE $\delta[k] \leftarrow U[k] - D[k]$
321
+ \ENDFOR
322
+ \RETURN $U,\,D,\,\delta$
323
+ \end{algorithmic}
324
+ \end{algorithm}
325
+
326
+ This algorithm traces the same $\mathcal{O}(N+D)$ bins as the GMP phase, maintaining computational efficiency while providing deep structural insight into directional dominance across the price range.
327
+
328
+ % ══════════════════════════════════════════════════════════════════════════════
329
+ % V. PROFILE CONSTRUCTION WALKTHROUGH
330
+ % ══════════════════════════════════════════════════════════════════════════════
331
+ \section{Profile Construction Walkthrough}\label{sec:walkthrough}
332
+
333
+ We illustrate the construction on a ten‑point price sequence. Each observation is a triple $(\text{label}, x, y)$ where \textit{label} is an alphabetic identifier, $x$ is the index, and $y$ the price. \Cref{tab:datapoints} lists the data.
334
+
335
+ \begin{table}[!t]
336
+ \centering
337
+ \caption{Input Observations (10 Points)}
338
+ \label{tab:datapoints}
339
+ \begin{tabular}{@{}ccc@{}}
340
+ \toprule
341
+ \textbf{Label} & \textbf{Index \#} & \textbf{Price (USD)} \\
342
+ \midrule
343
+ A & 1 & 3000.914 \\
344
+ B & 2 & 3003.837 \\
345
+ C & 3 & 3002.432 \\
346
+ D & 4 & 3009.892 \\
347
+ E & 5 & 3007.698 \\
348
+ F & 6 & 3009.176 \\
349
+ G & 7 & 3003.381 \\
350
+ H & 8 & 3004.283 \\
351
+ I & 9 & 3003.512 \\
352
+ J & 10 & 3003.012 \\
353
+ \bottomrule
354
+ \end{tabular}
355
+ \end{table}
356
+
357
+ \begin{figure}[!t]
358
+ \centering
359
+ \begin{tikzpicture}
360
+ \begin{axis}[
361
+ title={Price vs.\ Index},
362
+ xlabel={Index},
363
+ ylabel={Price (USD)},
364
+ ymin=2999.5, ymax=3011,
365
+ grid=both,
366
+ width=\columnwidth,
367
+ height=5cm,
368
+ legend style={at={(0.5,-0.15)}, anchor=north, legend columns=-1}
369
+ ]
370
+ \addplot[
371
+ only marks,
372
+ mark=*,
373
+ mark size=2pt,
374
+ blue
375
+ ] coordinates {
376
+ (1,3000.914) (2,3003.837) (3,3002.432) (4,3009.892) (5,3007.698)
377
+ (6,3009.176) (7,3003.381) (8,3004.283) (9,3003.512) (10,3003.012)
378
+ };
379
+ \legend{Observed price}
380
+ \end{axis}
381
+ \end{tikzpicture}
382
+ \caption{Price vs.\ index for the 10‑point example.}
383
+ \label{fig:price_scatter}
384
+ \end{figure}
385
+
386
+ \subsection{CMP Profile Table}\label{sec:cmp_table}
387
+
388
+ With $\beta=1$, the bin index is $b(p)=\lfloor p\rfloor$. CMP counts points per bin. \Cref{tab:cmp_profile} shows that bins 2, 6, 7, and 9 are empty—the gaps in the conventional profile.
389
+
390
+ \begin{table}[!t]
391
+ \centering
392
+ \caption{CMP Profile Table ($\beta=1$)}
393
+ \label{tab:cmp_profile}
394
+ \begin{tabular}{@{}ccccc@{}}
395
+ \toprule
396
+ \textbf{Bin} & \textbf{From} & \textbf{Until} & \textbf{Group} & \textbf{Stacks} \\
397
+ \midrule
398
+ 1 & 3000 & 3001 & A & 1 \\
399
+ 2 & 3001 & 3002 & & 0 \\
400
+ 3 & 3002 & 3003 & C & 1 \\
401
+ 4 & 3003 & 3004 & BGIJ & 4 \\
402
+ 5 & 3004 & 3005 & H & 1 \\
403
+ 6 & 3005 & 3006 & & 0 \\
404
+ 7 & 3006 & 3007 & & 0 \\
405
+ 8 & 3007 & 3008 & E & 1 \\
406
+ 9 & 3008 & 3009 & & 0 \\
407
+ 10 & 3009 & 3010 & DF & 2 \\
408
+ \midrule
409
+ \multicolumn{4}{c}{\textbf{Total stacks}} & \textbf{10} \\
410
+ \bottomrule
411
+ \end{tabular}
412
+ \end{table}
413
+
414
+ \begin{figure}[!t]
415
+ \centering
416
+ \begin{tikzpicture}
417
+ \begin{axis}[
418
+ title={CMP Profile},
419
+ xbar,
420
+ xlabel={Stacks},
421
+ ylabel={Price (USD)},
422
+ ytick={3000,3001,...,3009},
423
+ yticklabel style={font=\scriptsize},
424
+ xmin=0, xmax=5,
425
+ ymin=2999.5, ymax=3010,
426
+ bar width=4pt,
427
+ width=\columnwidth,
428
+ height=5cm,
429
+ enlarge y limits=0.05,
430
+ nodes near coords,
431
+ nodes near coords style={font=\tiny}
432
+ ]
433
+ \addplot[fill=orange!50, draw=black] coordinates {
434
+ (1,3000) (0,3001) (1,3002) (4,3003) (1,3004)
435
+ (0,3005) (0,3006) (1,3007) (0,3008) (2,3009)
436
+ };
437
+ \end{axis}
438
+ \end{tikzpicture}
439
+ \caption{CMP profile for the 10‑point example ($\beta=1$). Four bins are empty.}
440
+ \label{fig:cmp_chart}
441
+ \end{figure}
442
+
443
+ \subsection{GMP Profile Table}\label{sec:gmp_table}
444
+
445
+ GMP fills intermediate bins between consecutive points. \Cref{tab:gmp_profile} shows every bin now populated, with total stack count 25.
446
+
447
+ \begin{table}[!t]
448
+ \centering
449
+ \caption{GMP Profile Table ($\beta=1$)}
450
+ \label{tab:gmp_profile}
451
+ \begin{tabular}{@{}ccccc@{}}
452
+ \toprule
453
+ \textbf{Bin} & \textbf{From} & \textbf{Until} & \textbf{Group} & \textbf{Stacks} \\
454
+ \midrule
455
+ 1 & 3000 & 3001 & A & 1 \\
456
+ 2 & 3001 & 3002 & A & 1 \\
457
+ 3 & 3002 & 3003 & AC & 2 \\
458
+ 4 & 3003 & 3004 & BCGIJ & 5 \\
459
+ 5 & 3004 & 3005 & CFH & 3 \\
460
+ 6 & 3005 & 3006 & CF & 2 \\
461
+ 7 & 3006 & 3007 & CF & 2 \\
462
+ 8 & 3007 & 3008 & CEF & 3 \\
463
+ 9 & 3008 & 3009 & CDEF & 4 \\
464
+ 10 & 3009 & 3010 & DF & 2 \\
465
+ \midrule
466
+ \multicolumn{4}{c}{\textbf{Total stacks}} & \textbf{25} \\
467
+ \bottomrule
468
+ \end{tabular}
469
+ \end{table}
470
+
471
+ \begin{figure}[!t]
472
+ \centering
473
+ \begin{tikzpicture}
474
+ \begin{axis}[
475
+ title={GMP Profile},
476
+ xbar,
477
+ xlabel={Stacks},
478
+ ylabel={Price (USD)},
479
+ ytick={3000,3001,...,3009},
480
+ yticklabel style={font=\scriptsize},
481
+ xmin=0, xmax=6,
482
+ ymin=2999.5, ymax=3010,
483
+ bar width=4pt,
484
+ width=\columnwidth,
485
+ height=5cm,
486
+ enlarge y limits=0.05,
487
+ nodes near coords,
488
+ nodes near coords style={font=\tiny}
489
+ ]
490
+ \addplot[fill=green!40, draw=black] coordinates {
491
+ (1,3000) (1,3001) (2,3002) (5,3003) (3,3004)
492
+ (2,3005) (2,3006) (3,3007) (4,3008) (2,3009)
493
+ };
494
+ \end{axis}
495
+ \end{tikzpicture}
496
+ \caption{GMP profile for the 10‑point example ($\beta=1$). Every bin is populated.}
497
+ \label{fig:gmp_chart}
498
+ \end{figure}
499
+
500
+ \subsection{CMP vs.\ GMP Side‑by‑Side}\label{sec:cmp_gmp_compare}
501
+
502
+ \Cref{fig:cmp_vs_gmp_10pt} places both profiles side by side. CMP (10 stacks) leaves 40\% of bins empty; GMP (25 stacks) fully covers the range.
503
+
504
+ \begin{figure}[!t]
505
+ \centering
506
+ \begin{tikzpicture}
507
+ \begin{axis}[
508
+ title={CMP},
509
+ xbar,
510
+ xlabel={Stacks},
511
+ ylabel={Price (USD)},
512
+ ytick={3000,3001,...,3009},
513
+ yticklabel style={font=\scriptsize},
514
+ xmin=0, xmax=6,
515
+ ymin=2999.5, ymax=3010,
516
+ bar width=4pt,
517
+ width=0.42\columnwidth,
518
+ height=6cm,
519
+ enlarge y limits=0.05,
520
+ name=cmp_10
521
+ ]
522
+ \addplot[fill=orange!50, draw=black] coordinates {
523
+ (1,3000) (0,3001) (1,3002) (4,3003) (1,3004)
524
+ (0,3005) (0,3006) (1,3007) (0,3008) (2,3009)
525
+ };
526
+ \end{axis}
527
+ \begin{axis}[
528
+ title={GMP},
529
+ xbar,
530
+ xlabel={Stacks},
531
+ ylabel={},
532
+ ytick={3000,3001,...,3009},
533
+ yticklabel style={font=\scriptsize},
534
+ xmin=0, xmax=6,
535
+ ymin=2999.5, ymax=3010,
536
+ bar width=4pt,
537
+ width=0.42\columnwidth,
538
+ height=6cm,
539
+ enlarge y limits=0.05,
540
+ at={(cmp_10.east)},
541
+ anchor=west,
542
+ xshift=0.8cm
543
+ ]
544
+ \addplot[fill=green!40, draw=black] coordinates {
545
+ (1,3000) (1,3001) (2,3002) (5,3003) (3,3004)
546
+ (2,3005) (2,3006) (3,3007) (4,3008) (2,3009)
547
+ };
548
+ \end{axis}
549
+ \end{tikzpicture}
550
+ \caption{CMP vs.\ GMP side‑by‑side.}
551
+ \label{fig:cmp_vs_gmp_10pt}
552
+ \end{figure}
553
+
554
+ \Cref{fig:combined_3panel} presents the entire construction pipeline—raw data, CMP, GMP—in a single three‑panel TikZ graphic, ensuring full reproducibility.
555
+
556
+ \begin{figure*}[!t]
557
+ \centering
558
+ \begin{tikzpicture}
559
+ % Panel 1: raw data scatter
560
+ \begin{axis}[
561
+ title={Raw Data},
562
+ xlabel={Index},
563
+ ylabel={Price (USD)},
564
+ ymin=2999.5, ymax=3011,
565
+ width=0.30\textwidth,
566
+ height=6cm,
567
+ name=raw
568
+ ]
569
+ \addplot[only marks, mark=*, mark size=2pt, blue] coordinates {
570
+ (1,3000.914) (2,3003.837) (3,3002.432) (4,3009.892) (5,3007.698)
571
+ (6,3009.176) (7,3003.381) (8,3004.283) (9,3003.512) (10,3003.012)
572
+ };
573
+ \end{axis}
574
+ % Panel 2: CMP profile
575
+ \begin{axis}[
576
+ title={CMP Profile},
577
+ xbar,
578
+ xlabel={Stacks},
579
+ ylabel={},
580
+ ytick={3000,3001,...,3009},
581
+ yticklabel style={font=\scriptsize},
582
+ xmin=0, xmax=5,
583
+ ymin=2999.5, ymax=3010,
584
+ bar width=4pt,
585
+ width=0.30\textwidth,
586
+ height=6cm,
587
+ enlarge y limits=0.05,
588
+ at={(raw.east)},
589
+ anchor=west,
590
+ xshift=1.2cm
591
+ ]
592
+ \addplot[fill=orange!50, draw=black] coordinates {
593
+ (1,3000) (0,3001) (1,3002) (4,3003) (1,3004)
594
+ (0,3005) (0,3006) (1,3007) (0,3008) (2,3009)
595
+ };
596
+ \end{axis}
597
+ % Panel 3: GMP profile
598
+ \begin{axis}[
599
+ title={GMP Profile},
600
+ xbar,
601
+ xlabel={Stacks},
602
+ ylabel={},
603
+ ytick={3000,3001,...,3009},
604
+ yticklabel style={font=\scriptsize},
605
+ xmin=0, xmax=6,
606
+ ymin=2999.5, ymax=3010,
607
+ bar width=4pt,
608
+ width=0.30\textwidth,
609
+ height=6cm,
610
+ enlarge y limits=0.05,
611
+ at={(raw.east)},
612
+ anchor=west,
613
+ xshift=6cm
614
+ ]
615
+ \addplot[fill=green!40, draw=black] coordinates {
616
+ (1,3000) (1,3001) (2,3002) (5,3003) (3,3004)
617
+ (2,3005) (2,3006) (3,3007) (4,3008) (2,3009)
618
+ };
619
+ \end{axis}
620
+ \end{tikzpicture}
621
+ \caption{Three‑panel overview: raw data (left), CMP (centre), and GMP (right). Gap‑filling produces a continuous profile without empty bins.}
622
+ \label{fig:combined_3panel}
623
+ \end{figure*}
624
+
625
+ \subsection{Up/Down‑Bin Footprint Table}\label{sec:updown_table}
626
+
627
+ Applying \Cref{alg:updown} yields the directional footprint in \Cref{tab:updown_table}. For instance, the move from A to B adds up‑bins at bins~2--4; the move from C to D adds up‑bins at bins~4--10.
628
+
629
+ \begin{table}[!t]
630
+ \centering
631
+ \caption{Up/Down‑Bin Footprint Table ($\beta=1$)}
632
+ \label{tab:updown_table}
633
+ \begin{tabular}{@{}cccccrr@{}}
634
+ \toprule
635
+ \textbf{Bin} & \textbf{From} & \textbf{Until} & \textbf{Group} & \textbf{Down} & \textbf{Up} & \textbf{Delta} \\
636
+ \midrule
637
+ 1 & 3000 & 3001 & A & 0 & 0 & 0 \\
638
+ 2 & 3001 & 3002 & A & 0 & 1 & +1 \\
639
+ 3 & 3002 & 3003 & AC & 1 & 1 & 0 \\
640
+ 4 & 3003 & 3004 & BCGIJ & 3 & 2 & -1 \\
641
+ 5 & 3004 & 3005 & CFH & 1 & 2 & +1 \\
642
+ 6 & 3005 & 3006 & CF & 1 & 1 & 0 \\
643
+ 7 & 3006 & 3007 & CF & 1 & 1 & 0 \\
644
+ 8 & 3007 & 3008 & CEF & 2 & 1 & -1 \\
645
+ 9 & 3008 & 3009 & CDEF & 2 & 2 & 0 \\
646
+ 10 & 3009 & 3010 & DF & 0 & 2 & +2 \\
647
+ \bottomrule
648
+ \end{tabular}
649
+ \end{table}
650
+
651
+ \begin{figure}[!t]
652
+ \centering
653
+ \begin{tikzpicture}
654
+ \begin{axis}[
655
+ title={Up/Down‑Bin Footprint},
656
+ xbar,
657
+ xlabel={Count (Down / Up)},
658
+ ylabel={Price (USD)},
659
+ ytick={3000,3001,...,3009},
660
+ yticklabel style={font=\scriptsize},
661
+ xmin=-3.5, xmax=3.5,
662
+ ymin=2999.5, ymax=3010,
663
+ bar width=4pt,
664
+ width=\columnwidth,
665
+ height=5cm,
666
+ enlarge y limits=0.05,
667
+ legend style={at={(0.5,-0.15)}, anchor=north, legend columns=2}
668
+ ]
669
+ \addplot[fill=red!60, draw=black] coordinates {
670
+ (0,3000) (0,3001) (-1,3002) (-3,3003) (-1,3004)
671
+ (-1,3005) (-1,3006) (-2,3007) (-2,3008) (0,3009)
672
+ };
673
+ \addplot[fill=teal!60, draw=black] coordinates {
674
+ (0,3000) (1,3001) (1,3002) (2,3003) (2,3004)
675
+ (1,3005) (1,3006) (1,3007) (2,3008) (2,3009)
676
+ };
677
+ \legend{Down bins, Up bins}
678
+ \end{axis}
679
+ \end{tikzpicture}
680
+ \caption{Directional footprint: down‑bins (red) and up‑bins (teal).}
681
+ \label{fig:updown_footprint}
682
+ \end{figure}
683
+
684
+ % ══════════════════════════════════════════════════════════════════════════════
685
+ % VI. BIN‑SIZE ANALYSIS
686
+ % ══════════════════════════════════════════════════════════════════════════════
687
+ \section{Effect of Bin Size on Profile Resolution}\label{sec:binsize}
688
+
689
+ The bin‑size parameter $\beta$ controls granularity. For a single displacement $\Delta p = |p_i - p_{i-1}|$, the number of traversed bins is
690
+ \begin{equation}\label{eq:bins_beta}
691
+ K_i(\beta) \;=\;
692
+ \left|\left\lfloor \frac{p_i}{\beta} \right\rfloor
693
+ - \left\lfloor \frac{p_{i-1}}{\beta} \right\rfloor\right|
694
+ + 1.
695
+ \end{equation}
696
+ Halving $\beta$ roughly doubles $K_i$.
697
+
698
+ \begin{proposition}[Bin‑count scaling]\label{prop:scaling}
699
+ For fixed $\Delta p$ and $\beta_1 > \beta_2 > 0$,
700
+ \begin{equation}\label{eq:scaling}
701
+ K_i(\beta_2) \;\ge\;
702
+ \left\lfloor \frac{\beta_1}{\beta_2} \right\rfloor
703
+ \cdot \bigl(K_i(\beta_1) - 1\bigr) + 1.
704
+ \end{equation}
705
+ \end{proposition}
706
+
707
+ \begin{proof}
708
+ Write $\Delta p = (K_i(\beta_1)-1)\,\beta_1 + r_1$, $0 \le r_1 < \beta_1$. Then
709
+ $K_i(\beta_2) = \lfloor \Delta p/\beta_2 \rfloor + 1
710
+ \ge \lfloor (K_i(\beta_1)-1)\,\beta_1/\beta_2 \rfloor + 1
711
+ \ge \lfloor \beta_1/\beta_2 \rfloor\,(K_i(\beta_1)-1) + 1$.
712
+ \end{proof}
713
+
714
+ \Cref{tab:binsize} quantifies this for $\Delta p = 10$.
715
+
716
+ \begin{table}[!t]
717
+ \centering
718
+ \caption{Bin count vs.\ $\beta$ for $\Delta p = 10$}
719
+ \label{tab:binsize}
720
+ \begin{tabular}{@{}cccc@{}}
721
+ \toprule
722
+ $\beta$ & $K_i(\beta)$ & CMP bins & GMP bins filled \\
723
+ \midrule
724
+ 2.0 & 6 & 2 & 6 \\
725
+ 1.0 & 11 & 2 & 11 \\
726
+ 0.5 & 21 & 2 & 21 \\
727
+ 0.25 & 41 & 2 & 41 \\
728
+ 0.1 & 101 & 2 & 101 \\
729
+ \bottomrule
730
+ \end{tabular}
731
+ \end{table}
732
+
733
+ Key observations:
734
+ \begin{itemize}
735
+ \item \textbf{CMP is invariant:} always 2 bins, regardless of $\beta$.
736
+ \item \textbf{GMP scales as $\mathcal{O}(\Delta p/\beta)$:} resolution improves inversely with $\beta$. The lower bound is the minimum meaningful price increment.
737
+ \end{itemize}
738
+
739
+ % ══════════════════════════════════════════════════════════════════════════════
740
+ % VII. ILLUSTRATIVE EXAMPLE
741
+ % ═══════════════════════════════════════════════════════════════��══════════════
742
+ \section{Illustrative Example}\label{sec:example}
743
+
744
+ Two observations: $p_1 = 3000$, $p_2 = 3010$, $\beta=1$. \Cref{tab:cmp_vs_gmp} shows CMP (2 stacks) vs.\ GMP (11 stacks). \Cref{fig:profile} plots both.
745
+
746
+ \begin{table}[!t]
747
+ \centering
748
+ \caption{CMP vs.\ GMP ($\beta=1$)}
749
+ \label{tab:cmp_vs_gmp}
750
+ \begin{tabular}{@{}cccc@{}}
751
+ \toprule
752
+ Observation \# & Price & CMP stacks & GMP stacks \\
753
+ \midrule
754
+ 1 & 3000 & 1 & 1 \\
755
+ 0 & 3001 & 0 & 1 \\
756
+ 0 & 3002 & 0 & 1 \\
757
+ 0 & 3003 & 0 & 1 \\
758
+ 0 & 3004 & 0 & 1 \\
759
+ 0 & 3005 & 0 & 1 \\
760
+ 0 & 3006 & 0 & 1 \\
761
+ 0 & 3007 & 0 & 1 \\
762
+ 0 & 3008 & 0 & 1 \\
763
+ 0 & 3009 & 0 & 1 \\
764
+ 2 & 3010 & 1 & 1 \\
765
+ \midrule
766
+ \multicolumn{2}{c}{\textbf{Total stacks}} & \textbf{2} & \textbf{11} \\
767
+ \bottomrule
768
+ \end{tabular}
769
+ \end{table}
770
+
771
+ % ══════════════════════════════════════════════════════════════════════════════
772
+ % VIII. DISCUSSION
773
+ % ══════════════════════════════════════════════════════════════════════════════
774
+ \section{Discussion}\label{sec:discussion}
775
+
776
+ \subsection{Advantages}
777
+ \begin{enumerate}
778
+ \item \textbf{No profile gaps.} All traversed price levels are represented, avoiding sparse CMP histograms.
779
+ \item \textbf{Volume‑neutral interpolation.} Interpolated stacks mark traversal, not fabricated volume.
780
+ \item \textbf{Directional context.} The footprint reveals net pressure without external order‑flow data.
781
+ \item \textbf{Tunable resolution.} $\beta$ adjusts granularity independently of data frequency.
782
+ \item \textbf{Universality.} GMP applies to any ordered price sequence.
783
+ \end{enumerate}
784
+
785
+ \subsection{Limitations}
786
+ \begin{enumerate}
787
+ \item \textbf{Interpolation assumption.} Assumes continuous traversal; genuine price gaps may be over‑represented.
788
+ \item \textbf{Computational cost.} $\mathcal{O}(N+D)$ may be high for large cumulative displacement.
789
+ \item \textbf{Not a volume profile.} GMP is a pure price‑traversal profile; combining with volume is future work.
790
+ \end{enumerate}
791
+
792
+ \subsection{Choosing $\beta$}
793
+ \begin{itemize}
794
+ \item Set $\beta$ near the minimum price increment for maximum resolution.
795
+ \item Enlarge $\beta$ to reduce noise or align with psychological levels.
796
+ \item The resolution advantage of GMP over CMP grows as $\beta$ decreases.
797
+ \end{itemize}
798
+
799
+ % ══════════════════════════════════════════════════════════════════════════════
800
+ % IX. CONCLUSION
801
+ % ══════════════════════════════════════════════════════════════════════════════
802
+ \section{Conclusion}\label{sec:conclusion}
803
+
804
+ We have presented \textbf{GMP (Gap‑Filled Market Profile)}, a universal construction that interpolates all intermediate price bins between consecutive observations. We formalised CMP and GMP, provided algorithms with complexity analysis, and derived the inverse relationship between bin size $\beta$ and profile resolution. The detailed 10‑point illustration and accompanying charts demonstrate that GMP yields a strictly denser and more informative profile, closing the gaps inherent in conventional methods. Future work may explore weighted interpolation and application across asset classes.
805
+
806
+ \newpage
807
+ % ══════════════════════════════════════════════════════════════════════════════
808
+ % REFERENCES
809
+ % ══════════════════════════════════════════════════════════════════════════════
810
+ \bibliographystyle{IEEEtran}
811
+ \bibliography{references}
812
+
813
+ \end{document}
mBA-GMP.v3/gmp_profile.csv ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ bin (with binsize = 1 symbol's price unit),price from,price until,datapoint group,number of profile's stacks
2
+ 1,3000,3001,A,1
3
+ 2,3001,3002,A,1
4
+ 3,3002,3003,AC,2
5
+ 4,3003,3004,BCGIJ,5
6
+ 5,3004,3005,CFH,3
7
+ 6,3005,3006,CF,2
8
+ 7,3006,3007,CF,2
9
+ 8,3007,3008,CEF,3
10
+ 9,3008,3009,CDEF,4
11
+ 10,3009,3010,DF,2
mBA-GMP.v3/main.tex ADDED
@@ -0,0 +1,953 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ \documentclass[conference]{IEEEtran}
2
+
3
+ % ── Packages ──────────────────────────────────────────────────────────────────
4
+ \usepackage{cite}
5
+ \usepackage{amsmath,amssymb,amsfonts}
6
+ \usepackage{algorithmic}
7
+ \usepackage{algorithm}
8
+ \usepackage{graphicx}
9
+ \usepackage{textcomp}
10
+ \usepackage{booktabs}
11
+ \usepackage{multirow}
12
+ \usepackage{tikz}
13
+ \usepackage{pgfplots}
14
+ \pgfplotsset{compat=1.18}
15
+ \usepackage{hyperref}
16
+ \usepackage{cleveref}
17
+
18
+ % ── Meta ──────────────────────────────────────────────────────────────────────
19
+ \hypersetup{
20
+ colorlinks=true,
21
+ linkcolor=blue,
22
+ citecolor=blue,
23
+ urlcolor=blue
24
+ }
25
+
26
+ \def\BibTeX{{\rm B\kern-.05em{\sc i\kern-.025em b}\kern-.08em
27
+ T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}}
28
+
29
+ \begin{document}
30
+
31
+ % ══════════════════════════════════════════════════════════════════════════════
32
+ % TITLE
33
+ % ══════════════════════════════════════════════════════════════════════════════
34
+
35
+
36
+ \title{mBA-GMP.\textit{v3}: Micro Bid-Ask Gap-Filled Market Profile\textsuperscript{*}}
37
+
38
+ \author{%
39
+ \href{https://github.com/ContinualQuasars}{\includegraphics[height=1.6ex]{ContinualQuasars_icon.png}}\ \textit{Continual Quasars, Research Team}\\%
40
+ February 20, 2026%
41
+ }
42
+
43
+ \maketitle
44
+
45
+ % ══════════════════════════════════════════════════════════════════════════════
46
+ % ABSTRACT
47
+ % ══════════════════════════════════════════════════════════════════════════════
48
+ \begin{abstract}
49
+ Conventional Market Profile (CMP) aggregates price activity into histogram
50
+ bins using candlestick-derived data (TOCHLV), discarding the intra-bar
51
+ microstructure and leaving price bins between consecutive trades empty. We
52
+ propose \textbf{mBA-GMP} (\textit{micro Bid-Ask Gap-filled Market Profile}),
53
+ a method that (i)~operates on raw, microsecond-resolution bid/ask
54
+ tick-formation data rather than pre-aggregated candlesticks, and
55
+ (ii)~interpolates every intermediate price bin traversed between successive
56
+ ticks, producing a \emph{gap-filled} profile. Building on this gap-filled
57
+ structure, we further introduce an \emph{Up/Down-Bin Footprint Profile} that
58
+ classifies each bin's contribution directionally, revealing the net upward
59
+ or downward pressure across the price traversal. We formalise CMP and
60
+ GMP with explicit algorithms, derive the relationship between bin-count and
61
+ a user-defined bin-size parameter~$\beta$, and introduce a \emph{dataframe
62
+ recording approach} that walks through a 10-datapoint XAUUSD example to
63
+ show how datapoints are grouped into price bins (the CMP dataframe),
64
+ how gap-filling transforms the sparse CMP output into a dense GMP
65
+ dataframe, and how directional footprints are assigned. We demonstrate via
66
+ generated charts and CSV data that mBA-GMP yields a strictly denser and
67
+ more informative distribution than CMP.
68
+ \end{abstract}
69
+
70
+ \begin{IEEEkeywords}
71
+ Market Profile, tick data, bid-ask spread, gap-filling interpolation,
72
+ high-frequency data, market microstructure, XAUUSD
73
+ \end{IEEEkeywords}
74
+
75
+ \vspace{0.5\baselineskip}
76
+ \hrule
77
+ \vspace{0.5\baselineskip}
78
+
79
+ {\footnotesize\noindent\textsuperscript{*}This research is conducted by the Continual Quasars Research Team at: {\color{blue}\href{https://github.com/ContinualQuasars}{github.com/ContinualQuasars}}\par}
80
+
81
+ \begin{figure}[!t]
82
+ \centering
83
+ \begin{tikzpicture}
84
+ \begin{axis}[
85
+ title={\textbf{CMP Profile}},
86
+ xbar,
87
+ xlabel={Stacks},
88
+ ylabel={Price (USD)},
89
+ ytick={3000,3001,...,3010},
90
+ yticklabel style={font=\scriptsize},
91
+ xmin=0, xmax=2,
92
+ ymin=2999.5, ymax=3010.5,
93
+ bar width=4pt,
94
+ width=0.42\columnwidth,
95
+ height=6.5cm,
96
+ enlarge y limits=0.05,
97
+ nodes near coords,
98
+ nodes near coords style={font=\tiny},
99
+ name=cmp
100
+ ]
101
+ \addplot[fill=gray!60, draw=black] coordinates {
102
+ (1,3000) (0,3001) (0,3002) (0,3003) (0,3004) (0,3005)
103
+ (0,3006) (0,3007) (0,3008) (0,3009) (1,3010)
104
+ };
105
+ \end{axis}
106
+
107
+ \begin{axis}[
108
+ title={\textbf{GMP Profile}},
109
+ xbar,
110
+ xlabel={Stacks},
111
+ ylabel={},
112
+ ytick={3000,3001,...,3010},
113
+ yticklabel style={font=\scriptsize},
114
+ xmin=0, xmax=2,
115
+ ymin=2999.5, ymax=3010.5,
116
+ bar width=4pt,
117
+ width=0.42\columnwidth,
118
+ height=6.5cm,
119
+ enlarge y limits=0.05,
120
+ nodes near coords,
121
+ nodes near coords style={font=\tiny},
122
+ at={(cmp.east)},
123
+ anchor=west,
124
+ xshift=1.2cm
125
+ ]
126
+ \addplot[fill=blue!50, draw=black] coordinates {
127
+ (1,3000) (1,3001) (1,3002) (1,3003) (1,3004) (1,3005)
128
+ (1,3006) (1,3007) (1,3008) (1,3009) (1,3010)
129
+ };
130
+ \end{axis}
131
+ \end{tikzpicture}
132
+ \caption{Horizontal histogram comparison of CMP (left, grey) and GMP
133
+ (right, blue) for XAUUSD with $\beta=1$. CMP shows activity only at
134
+ the two observed prices; GMP fills all 11~traversed bins. The
135
+ gap-filling approach is most effective when applied to micro bid/ask
136
+ (mBA) raw tick-formation data.}
137
+ \label{fig:profile}
138
+ \end{figure}
139
+ % ══════════════════════════════════════════════════════════════════════════════
140
+ % I. INTRODUCTION
141
+ % ══════════════════════════════════════════════════════════════════════════════
142
+ \section{Introduction}\label{sec:intro}
143
+
144
+ The Market Profile, introduced by Steidlmayer~\cite{steidlmayer1986market}
145
+ and later formalised by Dalton et~al.~\cite{dalton2007markets}, represents
146
+ price activity as a horizontal histogram whose bins correspond to discrete
147
+ price levels and whose bar lengths (``stacks'') reflect the amount of
148
+ activity observed at each level. In practice, most implementations
149
+ construct the profile from candlestick TOCHLV (time, open, close, high, low, volume) data: each candle
150
+ contributes one stack to every bin between its high and low.
151
+
152
+ This approach suffers from two shortcomings:
153
+
154
+ \begin{enumerate}
155
+ \item \textbf{Aggregation loss.}\;Candlesticks pre-aggregate raw ticks
156
+ into time-based bars chosen by the broker or exchange, irreversibly
157
+ discarding the sequence and microsecond timing of individual
158
+ bid/ask updates~\cite{engle2000econometrics,easley1992time}.
159
+ \item \textbf{Gap neglect.}\;When consecutive \emph{raw} ticks are
160
+ separated by several price levels, the conventional profile records
161
+ activity only at the two observed prices, ignoring the fact that price
162
+ must have traversed every intermediate level.
163
+ \end{enumerate}
164
+
165
+ We address both issues with \textbf{mBA-GMP}. The prefix \textit{mBA}
166
+ (micro Bid-Ask) specifies the data domain: raw, micro\-/millisecond-stamped
167
+ bid/ask tick-formation records---the smallest observable price changes.
168
+ The suffix \textit{GMP} (Gap-filled Market Profile) specifies the
169
+ construction rule: every price bin between two successive ticks receives an
170
+ interpolated stack, producing a profile with no gaps.
171
+
172
+
173
+ The remainder of this paper is organised as follows.
174
+ \Cref{sec:related} surveys related work.
175
+ \Cref{sec:prelim} establishes notation.
176
+ \Cref{sec:method} defines CMP and GMP formally, presents the mBA-GMP
177
+ algorithm, and introduces the Up/Down-Bin Footprint Profile.
178
+ \Cref{sec:dataframe} introduces the dataframe recording approach and
179
+ walks through a 10-datapoint worked example showing CMP, GMP, and footprint
180
+ construction step by step.
181
+ \Cref{sec:binsize} analyses the effect of bin-size on profile resolution.
182
+ \Cref{sec:example} provides an additional worked example with XAUUSD.
183
+ \Cref{sec:discussion} discusses practical implications, and
184
+ \Cref{sec:conclusion} concludes.
185
+
186
+
187
+ % ══════════════════════════════════════════════════════════════════════════════
188
+ % II. RELATED WORK
189
+ % ══════════════════════════════════════════════════════════════════════════════
190
+ \section{Related Work}\label{sec:related}
191
+
192
+ \subsection{Market Profile}
193
+ The Market Profile concept originates with Steidlmayer's observation that
194
+ price distributions at each level reveal where market participants find
195
+ ``fair value''~\cite{steidlmayer1986market}. Dalton et~al.~\cite{dalton2007markets} extended the framework with auction-market
196
+ theory, using half-hour brackets as time-price opportunities (TPOs). Both
197
+ formulations rely on time-based bars rather than raw ticks.
198
+
199
+ \subsection{Tick-Level Analysis}
200
+ Clark~\cite{clark1973subordinated} demonstrated that subordinating returns
201
+ to trade-count time yields closer-to-Gaussian distributions, motivating
202
+ trade-indexed (rather than time-indexed) analysis.
203
+ An\'{e} and Geman~\cite{ane2000order} confirmed that business-time
204
+ transformations normalise returns at the tick level.
205
+ Engle~\cite{engle2000econometrics} introduced econometric models tailored
206
+ to ultra-high-frequency data.
207
+
208
+
209
+ \subsection{Market Microstructure}
210
+ The theoretical foundations of bid-ask price formation are laid out by
211
+ Glosten and Milgrom~\cite{glosten1985bid}, O'Hara~\cite{ohara1995market},
212
+ and the comprehensive survey of Madhavan~\cite{madhavan2000market}.
213
+ Hasbrouck~\cite{hasbrouck2007empirical} provides empirical methods for
214
+ tick-level inference. Bouchaud et~al.~\cite{bouchaud2018trades} present a
215
+ modern, physics-inspired treatment linking order flow to price dynamics.
216
+
217
+ A common thread across these works is that raw tick data preserves
218
+ information lost by any form of aggregation. Our contribution is to
219
+ combine this insight with a gap-filling interpolation rule applied to the
220
+ Market Profile histogram.
221
+
222
+
223
+ % ══════════════════════════════════════════════════════════════════════════════
224
+ % III. PRELIMINARIES
225
+ % ══════════════════════════════════════════════════════════════════════════════
226
+ \section{Preliminaries}\label{sec:prelim}
227
+
228
+ \Cref{tab:notation} summarises the notation used throughout.
229
+
230
+ \begin{table}[!t]
231
+ \centering
232
+ \caption{Notation Summary}
233
+ \label{tab:notation}
234
+ \begin{tabular}{@{}cl@{}}
235
+ \toprule
236
+ \textbf{Symbol} & \textbf{Description} \\
237
+ \midrule
238
+ $N$ & Total number of raw ticks in the dataset \\
239
+ $p_i$ & Price of the $i$-th tick, $i\in\{1,\dots,N\}$ \\
240
+ $\beta$ & Bin size (price units per bin); default $\beta=1$ \\
241
+ $b(p)$ & Bin index of price $p$: $b(p)=\lfloor p/\beta \rfloor$ \\
242
+ $S[k]$ & Stack count (profile value) at bin~$k$ \\
243
+ $\Delta_i$ & Price displacement: $\Delta_i = p_i - p_{i-1}$ \\
244
+ $K_i$ & Number of bins traversed from tick $i{-}1$ to $i$ \\
245
+ $U[k]$ & Up-bin count at bin $k$ \\
246
+ $D[k]$ & Down-bin count at bin $k$ \\
247
+ $\delta[k]$ & Net footprint delta at bin $k$: $\delta[k] = U[k] - D[k]$ \\
248
+ \bottomrule
249
+ \end{tabular}
250
+ \end{table}
251
+
252
+ \begin{definition}[Tick-formation]
253
+ A \emph{tick-formation} is the smallest observable change in the bid or
254
+ ask price as recorded by the broker. Formally, a tick stream is an
255
+ ordered sequence $\mathcal{T}=\{(t_i,\,p_i)\}_{i=1}^{N}$ where $t_i$
256
+ is the micro\-/millisecond timestamp and $p_i$ is the observed price.
257
+ \end{definition}
258
+
259
+ \begin{definition}[Bin]
260
+ Given bin size $\beta>0$, the \emph{bin} for price $p$ is the integer
261
+ index
262
+ \begin{equation}\label{eq:bin}
263
+ b(p) = \left\lfloor \frac{p}{\beta} \right\rfloor.
264
+ \end{equation}
265
+ All prices $p$ satisfying $k\beta \le p < (k+1)\beta$ map to bin~$k$.
266
+ \end{definition}
267
+
268
+
269
+ \begin{definition}[Market Profile]
270
+ A \emph{market profile} is a mapping $S:\mathbb{Z}\to\mathbb{N}_0$
271
+ where $S[k]$ counts the number of stacks accumulated at bin~$k$.
272
+ \end{definition}
273
+
274
+
275
+ % ══════════════════════════════════════════════════════════════════════════════
276
+ % IV. METHODOLOGY
277
+ % ══════════════════════════════════════════════════════════════════════════════
278
+ \section{Methodology}\label{sec:method}
279
+
280
+ \subsection{Conventional Market Profile (CMP)}\label{sec:cmp}
281
+
282
+ CMP records a stack only at the bin of each observed data point:
283
+ \begin{equation}\label{eq:cmp}
284
+ S_{\text{CMP}}[k] \;=\; \sum_{i=1}^{N} \mathbf{1}\!\bigl[b(p_i)=k\bigr],
285
+ \end{equation}
286
+ where $\mathbf{1}[\cdot]$ is the indicator function. Bins with no
287
+ observed tick receive $S_{\text{CMP}}[k]=0$.
288
+
289
+ \smallskip
290
+ \begin{algorithm}[!t]
291
+ \caption{CMP Construction}\label{alg:cmp}
292
+ \begin{algorithmic}[1]
293
+ \REQUIRE Tick stream $\{p_i\}_{i=1}^{N}$, bin size $\beta$
294
+ \ENSURE Profile array $S_{\text{CMP}}[\cdot]$
295
+ \STATE Initialise $S_{\text{CMP}}[k]\leftarrow 0\;\;\forall\,k$
296
+ \FOR{$i = 1$ \TO $N$}
297
+ \STATE $k \leftarrow \lfloor p_i / \beta \rfloor$
298
+ \STATE $S_{\text{CMP}}[k] \leftarrow S_{\text{CMP}}[k] + 1$
299
+ \ENDFOR
300
+ \RETURN $S_{\text{CMP}}$
301
+ \end{algorithmic}
302
+ \end{algorithm}
303
+
304
+ \textbf{Complexity.}\;CMP performs exactly $N$ bin-index computations and
305
+ $N$ increments, giving $\mathcal{O}(N)$ time complexity.
306
+
307
+ \subsection{Gap-Filled Market Profile (GMP)}\label{sec:gmp}
308
+
309
+ GMP augments CMP by filling every \emph{intermediate} bin between two
310
+ consecutive ticks. The construction proceeds in two phases:
311
+
312
+ \begin{enumerate}
313
+ \item \textbf{CMP placement.}\;Each tick~$p_i$ contributes one stack to
314
+ its own bin~$b(p_i)$, exactly as in CMP.
315
+ \item \textbf{Gap-filling.}\;For each consecutive pair
316
+ $(p_{i-1},\,p_i)$ with $i\ge 2$, every bin \emph{strictly between}
317
+ $b(p_{i-1})$ and $b(p_i)$ (exclusive of both endpoints) receives one
318
+ additional stack.
319
+ \end{enumerate}
320
+
321
+ \noindent Formally, writing $b_i = b(p_i)$:
322
+
323
+ \begin{equation}\label{eq:gmp}
324
+ S_{\text{GMP}}[k]
325
+ \;=\;
326
+ \underbrace{\sum_{i=1}^{N}\mathbf{1}\!\bigl[b_i=k\bigr]}_{S_{\text{CMP}}[k]}
327
+ \;+\;
328
+ \sum_{i=2}^{N}
329
+ \;\sum_{j=\min(b_{i-1},\,b_i)+1}^{\max(b_{i-1},\,b_i)-1}
330
+ \!\mathbf{1}\!\bigl[j=k\bigr].
331
+ \end{equation}
332
+
333
+ When $|b_i - b_{i-1}| \le 1$ (adjacent or same bin), the inner sum is
334
+ empty and no gap-filling occurs. When $|b_i - b_{i-1}| > 1$, the number
335
+ of gap-filled (intermediate) bins is
336
+ \begin{equation}\label{eq:Ki}
337
+ G_i \;=\; \bigl|b(p_i) - b(p_{i-1})\bigr| - 1.
338
+ \end{equation}
339
+ The total span of bins traversed, inclusive of both endpoints, is
340
+ $K_i = G_i + 2 = |b_i - b_{i-1}| + 1$.
341
+
342
+ \begin{algorithm}[!t]
343
+ \caption{GMP Construction (Two-Phase)}\label{alg:gmp}
344
+ \begin{algorithmic}[1]
345
+ \REQUIRE Tick stream $\{p_i\}_{i=1}^{N}$, bin size $\beta$
346
+ \ENSURE Profile array $S_{\text{GMP}}[\cdot]$
347
+ \STATE Initialise $S_{\text{GMP}}[k]\leftarrow 0\;\;\forall\,k$
348
+ \FOR{$i = 1$ \TO $N$} \COMMENT{Phase~1: CMP placement}
349
+ \STATE $S_{\text{GMP}}[\lfloor p_i/\beta \rfloor] \leftarrow
350
+ S_{\text{GMP}}[\lfloor p_i/\beta \rfloor] + 1$
351
+ \ENDFOR
352
+ \FOR{$i = 2$ \TO $N$} \COMMENT{Phase~2: gap-fill}
353
+ \STATE $k_{\text{from}} \leftarrow \lfloor p_{i-1}/\beta \rfloor$;
354
+ $k_{\text{to}} \leftarrow \lfloor p_i/\beta \rfloor$
355
+ \IF{$|k_{\text{to}} - k_{\text{from}}| > 1$}
356
+ \STATE $d \leftarrow \text{sign}(k_{\text{to}} - k_{\text{from}})$
357
+ \FOR{$k = k_{\text{from}} + d$ \TO $k_{\text{to}} - d$ \textbf{step} $d$}
358
+ \STATE $S_{\text{GMP}}[k] \leftarrow S_{\text{GMP}}[k] + 1$
359
+ \ENDFOR
360
+ \ENDIF
361
+ \ENDFOR
362
+ \RETURN $S_{\text{GMP}}$
363
+ \end{algorithmic}
364
+ \end{algorithm}
365
+
366
+ \textbf{Complexity.}\;Let
367
+ $D=\sum_{i=2}^{N}|b(p_i)-b(p_{i-1})|$ denote the cumulative bin
368
+ displacement. GMP performs $\mathcal{O}(N + D)$ operations. In the
369
+ degenerate case where all ticks share the same bin, $D=0$ and GMP reduces
370
+ to CMP. In the worst case, $D=\mathcal{O}(N\cdot\Delta p_{\max}/\beta)$.
371
+
372
+ \subsection{mBA-GMP: Applying GMP to Raw Tick Data}\label{sec:mba}
373
+
374
+ The key contribution of mBA-GMP is \emph{not} a novel interpolation rule
375
+ per~se, but rather the principled insistence that GMP must be applied to
376
+ raw bid/ask tick-formation data:
377
+
378
+ \begin{enumerate}
379
+ \item \textbf{Data source.}\;Use the broker's micro\-/millisecond
380
+ bid/ask feed---the lowest-granularity record available---rather than
381
+ any TOCHLV candlestick derivative.
382
+ \item \textbf{Trade indexing.}\;Index the $x$-axis by trade sequence
383
+ number, not by wall-clock time (cf.~\cite{clark1973subordinated,
384
+ ane2000order}).
385
+ \item \textbf{Gap filling.}\;Apply \Cref{alg:gmp} to the tick stream.
386
+ \end{enumerate}
387
+
388
+ \begin{algorithm}[!t]
389
+ \caption{mBA-GMP Pipeline}\label{alg:mba}
390
+ \begin{algorithmic}[1]
391
+ \REQUIRE Raw bid/ask tick feed $\mathcal{T}$, bin size $\beta$
392
+ \ENSURE Gap-filled profile $S_{\text{GMP}}[\cdot]$
393
+ \STATE Extract price sequence $\{p_i\}_{i=1}^{N}$ from $\mathcal{T}$,
394
+ indexed by trade count
395
+ \STATE $S_{\text{GMP}} \leftarrow \textsc{GMP}(\{p_i\},\,\beta)$
396
+ \COMMENT{Algorithm~\ref{alg:gmp}}
397
+ \RETURN $S_{\text{GMP}}$
398
+ \end{algorithmic}
399
+ \end{algorithm}
400
+
401
+ By operating on raw ticks, mBA-GMP avoids the aggregation artefacts
402
+ inherent in candlestick data~\cite{harris1990estimation} (e.g., arbitrary
403
+ bar boundaries, concealed intra-bar reversals) and ensures that every
404
+ micro-level price traversal is captured in the profile.
405
+
406
+ \subsection{Up/Down-Bin Footprint Profile}\label{sec:updown}
407
+
408
+ Building upon the gap-filled structure of GMP, we introduce a directional
409
+ classification layer termed the \emph{Up/Down-Bin Footprint Profile}.
410
+ Unlike order-flow bid/ask footprint charts which rely on volume traded at
411
+ the bid versus the ask, our footprint is derived purely from the GMP
412
+ transitive mechanics.
413
+
414
+ For every consecutive pair $(p_{i-1},\,p_i)$, the trajectory is evaluated
415
+ as an upward or downward movement based solely on the price difference.
416
+ The origin bin $b(p_{i-1})$ is assigned no directional credit relating
417
+ to this specific move (it has already been evaluated by prior action).
418
+ However, every subsequent bin along the traversed path up to and including
419
+ the destination bin $b(p_i)$ increments its \emph{up-bin} count $U[k]$ if $p_i > p_{i-1}$,
420
+ or its \emph{down-bin} count $D[k]$ if $p_i \le p_{i-1}$.
421
+
422
+ \begin{algorithm}[!t]
423
+ \caption{Up/Down-Bin Footprint Construction}\label{alg:updown}
424
+ \begin{algorithmic}[1]
425
+ \REQUIRE Tick stream $\{p_i\}_{i=1}^{N}$, bin size $\beta$
426
+ \ENSURE Profile arrays $U[\cdot], D[\cdot], \delta[\cdot]$
427
+ \STATE Initialise $U[k]\leftarrow 0, D[k]\leftarrow 0\;\;\forall\,k$
428
+ \FOR{$i = 2$ \TO $N$}
429
+ \STATE $k_{\text{from}} \leftarrow \lfloor p_{i-1}/\beta \rfloor$;
430
+ $k_{\text{to}} \leftarrow \lfloor p_i/\beta \rfloor$
431
+ \IF{$k_{\text{from}} = k_{\text{to}}$}
432
+ \IF{$p_i > p_{i-1}$}
433
+ \STATE $U[k_{\text{from}}] \leftarrow U[k_{\text{from}}] + 1$
434
+ \ELSE
435
+ \STATE $D[k_{\text{from}}] \leftarrow D[k_{\text{from}}] + 1$
436
+ \ENDIF
437
+ \STATE \textbf{continue}
438
+ \ENDIF
439
+ \STATE $\text{is\_up} \leftarrow (k_{\text{to}} > k_{\text{from}})$
440
+ \STATE $d \leftarrow \text{sign}(k_{\text{to}} - k_{\text{from}})$
441
+ \STATE $k \leftarrow k_{\text{from}} + d$
442
+ \WHILE{\textbf{true}}
443
+ \IF{$\text{is\_up}$}
444
+ \STATE $U[k] \leftarrow U[k] + 1$
445
+ \ELSE
446
+ \STATE $D[k] \leftarrow D[k] + 1$
447
+ \ENDIF
448
+ \IF{$k = k_{\text{to}}$}
449
+ \STATE \textbf{break}
450
+ \ENDIF
451
+ \STATE $k \leftarrow k + d$
452
+ \ENDWHILE
453
+ \ENDFOR
454
+ \FORALL{$k$}
455
+ \STATE $\delta[k] \leftarrow U[k] - D[k]$
456
+ \ENDFOR
457
+ \RETURN $U,\,D,\,\delta$
458
+ \end{algorithmic}
459
+ \end{algorithm}
460
+
461
+ This algorithm traces the same $\mathcal{O}(N+D)$ bins as the GMP phase,
462
+ maintaining computational efficiency while providing deep structural
463
+ insight into directional dominance across the price range.
464
+
465
+
466
+ % ══════════════════════════════════════════════════════════════════════════════
467
+ % V. DATAFRAME RECORDING APPROACH
468
+ % ══════════════════════════════════════════════════════════════════════════════
469
+ \section{Dataframe Recording Approach}\label{sec:dataframe}
470
+
471
+ To build practical intuition for how CMP and GMP profiles are constructed,
472
+ this section walks through a concrete 10-datapoint example using a
473
+ \emph{dataframe}-style representation. Each raw data record is a triple
474
+ $(\text{label},\;x,\;y)$ where \textit{label} is an alphabetic identifier,
475
+ $x$ is the trade index (or time), and $y$ is the observed price.
476
+ \Cref{tab:datapoints} lists the input data.
477
+
478
+ \begin{table}[!t]
479
+ \centering
480
+ \caption{Input Datapoints (XAUUSD Example, 10 Ticks)}
481
+ \label{tab:datapoints}
482
+ \begin{tabular}{@{}ccc@{}}
483
+ \toprule
484
+ \textbf{Datapoint} & \textbf{Trade \#} & \textbf{Price (USD)} \\
485
+ \midrule
486
+ A & 1 & 3000.914 \\
487
+ B & 2 & 3003.837 \\
488
+ C & 3 & 3002.432 \\
489
+ D & 4 & 3009.892 \\
490
+ E & 5 & 3007.698 \\
491
+ F & 6 & 3009.176 \\
492
+ G & 7 & 3003.381 \\
493
+ H & 8 & 3004.283 \\
494
+ I & 9 & 3003.512 \\
495
+ J & 10 & 3003.012 \\
496
+ \bottomrule
497
+ \end{tabular}
498
+ \end{table}
499
+
500
+ \Cref{fig:price_scatter} plots these datapoints as a price-vs-trade-index
501
+ scatter chart, illustrating the raw price path that both CMP and GMP
502
+ will profile.
503
+
504
+ \begin{figure}[!t]
505
+ \centering
506
+ \includegraphics[width=\columnwidth]{fig_price_scatter.png}
507
+ \caption{Price vs.\ trade index for the 10-datapoint XAUUSD example
508
+ (A--J). Each point represents one raw tick-formation record.}
509
+ \label{fig:price_scatter}
510
+ \end{figure}
511
+
512
+ \subsection{CMP Output Dataframe}\label{sec:df_cmp}
513
+
514
+ Using $\beta=1$, the bin index for each tick is $b(p)=\lfloor p\rfloor$.
515
+ CMP simply counts how many datapoints fall into each bin.
516
+ \Cref{tab:cmp_df} shows the resulting dataframe: bins are numbered~1
517
+ through~10 from the lowest observed price to the highest. The
518
+ \emph{datapoint group} column records which labels landed in each bin,
519
+ and \emph{stacks} is the group size.
520
+
521
+ \begin{table}[!t]
522
+ \centering
523
+ \caption{CMP Output Dataframe ($\beta=1$)}
524
+ \label{tab:cmp_df}
525
+ \begin{tabular}{@{}ccccc@{}}
526
+ \toprule
527
+ \textbf{Bin} & \textbf{From} & \textbf{Until}
528
+ & \textbf{Group} & \textbf{Stacks} \\
529
+ \midrule
530
+ 1 & 3000 & 3001 & A & 1 \\
531
+ 2 & 3001 & 3002 & & 0 \\
532
+ 3 & 3002 & 3003 & C & 1 \\
533
+ 4 & 3003 & 3004 & BGIJ & 4 \\
534
+ 5 & 3004 & 3005 & H & 1 \\
535
+ 6 & 3005 & 3006 & & 0 \\
536
+ 7 & 3006 & 3007 & & 0 \\
537
+ 8 & 3007 & 3008 & E & 1 \\
538
+ 9 & 3008 & 3009 & & 0 \\
539
+ 10 & 3009 & 3010 & DF & 2 \\
540
+ \midrule
541
+ \multicolumn{4}{c}{\textbf{Total stacks}} & \textbf{10} \\
542
+ \bottomrule
543
+ \end{tabular}
544
+ \end{table}
545
+
546
+ Note that bins~2, 6, 7, and~9 have zero stacks---these are the
547
+ \emph{gaps} in the CMP profile. The CMP histogram formed by the
548
+ \emph{datapoint group} column is exactly the $y$-distribution
549
+ histogram used by traditional Market Profile implementations.
550
+
551
+ \begin{figure}[!t]
552
+ \centering
553
+ \includegraphics[width=0.85\columnwidth]{fig_cmp_profile.png}
554
+ \caption{CMP profile for the 10-datapoint example ($\beta=1$).
555
+ Four bins (2,\,6,\,7,\,9) are empty, revealing gaps in price coverage.}
556
+ \label{fig:cmp_chart}
557
+ \end{figure}
558
+
559
+ \subsection{GMP Output Dataframe}\label{sec:df_gmp}
560
+
561
+ GMP augments the CMP result by filling every intermediate bin that price
562
+ must have traversed between consecutive datapoints. The gap-filling
563
+ convention is:
564
+
565
+ \begin{enumerate}
566
+ \item Each datapoint contributes one stack to its own bin (identical to
567
+ CMP).
568
+ \item For each consecutive pair $(i,\,i{+}1)$, every bin strictly
569
+ \emph{between} $b(p_i)$ and $b(p_{i+1})$ (exclusive of both
570
+ endpoints) receives one additional stack, labelled with the
571
+ source datapoint~$i$.
572
+ \end{enumerate}
573
+
574
+ \Cref{tab:gmp_df} shows the resulting GMP dataframe. All bins now have
575
+ at least one stack---no gaps remain.
576
+
577
+ \begin{table}[!t]
578
+ \centering
579
+ \caption{GMP Output Dataframe ($\beta=1$)}
580
+ \label{tab:gmp_df}
581
+ \begin{tabular}{@{}ccccc@{}}
582
+ \toprule
583
+ \textbf{Bin} & \textbf{From} & \textbf{Until}
584
+ & \textbf{Group} & \textbf{Stacks} \\
585
+ \midrule
586
+ 1 & 3000 & 3001 & A & 1 \\
587
+ 2 & 3001 & 3002 & A & 1 \\
588
+ 3 & 3002 & 3003 & AC & 2 \\
589
+ 4 & 3003 & 3004 & BCGIJ & 5 \\
590
+ 5 & 3004 & 3005 & CFH & 3 \\
591
+ 6 & 3005 & 3006 & CF & 2 \\
592
+ 7 & 3006 & 3007 & CF & 2 \\
593
+ 8 & 3007 & 3008 & CEF & 3 \\
594
+ 9 & 3008 & 3009 & CDEF & 4 \\
595
+ 10 & 3009 & 3010 & DF & 2 \\
596
+ \midrule
597
+ \multicolumn{4}{c}{\textbf{Total stacks}} & \textbf{25} \\
598
+ \bottomrule
599
+ \end{tabular}
600
+ \end{table}
601
+
602
+ \begin{figure}[!t]
603
+ \centering
604
+ \includegraphics[width=0.85\columnwidth]{fig_gmp_profile.png}
605
+ \caption{GMP profile for the 10-datapoint example ($\beta=1$).
606
+ Every bin is populated; the profile fully represents the price
607
+ range traversed by the market.}
608
+ \label{fig:gmp_chart}
609
+ \end{figure}
610
+
611
+ \subsection{CMP vs.\ GMP Side-by-Side}\label{sec:df_compare}
612
+
613
+ \Cref{fig:cmp_vs_gmp_10pt} places both profiles side by side. The
614
+ contrast is striking: CMP concentrates stacks at a handful of prices
615
+ (total~10~stacks), leaving 40\,\% of bins empty, while GMP distributes
616
+ 25~stacks across all 10~bins, yielding a strictly denser and more
617
+ informative volume-at-price distribution.
618
+
619
+ \begin{figure}[!t]
620
+ \centering
621
+ \includegraphics[width=\columnwidth]{fig_cmp_vs_gmp.png}
622
+ \caption{Side-by-side comparison of CMP (left, orange) and GMP (right,
623
+ green) for the 10-datapoint XAUUSD example with $\beta=1$.}
624
+ \label{fig:cmp_vs_gmp_10pt}
625
+ \end{figure}
626
+
627
+ \Cref{fig:combined_3panel} presents the entire pipeline---from raw
628
+ datapoints, through CMP, to GMP---in a single three-panel view, with
629
+ every bar annotated by its constituent datapoint letters.
630
+
631
+ \begin{figure*}[!t]
632
+ \centering
633
+ \includegraphics[width=\textwidth]{fig_combined_3panel.png}
634
+ \caption{Three-panel overview: raw datapoints (left), CMP profile
635
+ with group letters (centre), and GMP profile with group letters
636
+ (right). Every bar is annotated with the alphabetic labels of the
637
+ datapoints it contains, making the gap-filling effect directly
638
+ visible. The gap-filling approach is most effective when applied to micro bid/ask
639
+ (mBA) raw tick-formation data.}
640
+ \label{fig:combined_3panel}
641
+ \end{figure*}
642
+
643
+ \begin{quote}
644
+ \textbf{Rendering note.}\;In the dataframe tables above, bin~1
645
+ (lowest price) appears at the \emph{top} of the table. On an actual
646
+ price chart, however, the lowest price is at the \emph{bottom} of the
647
+ $y$-axis and the highest price at the top---the profile histogram is
648
+ effectively ``flipped'' relative to the tabular representation.
649
+ \end{quote}
650
+
651
+ \subsection{Up/Down-Bin Footprint Dataframe}\label{sec:df_updown}
652
+
653
+ Applying \Cref{alg:updown} to the same 10-datapoint trajectory yields
654
+ the directional footprint dataframe shown in \Cref{tab:updown_df}.
655
+ For example, the move from A (3000.914) to B (3003.837) causes bins 2, 3, and 4
656
+ to receive $+1$ up-bin point. The movement from C (3002.432) to D (3009.892)
657
+ applies up-bin points to bins 4 through 10. Downward movements, such as
658
+ B down to C, or D down to E, function symmetrically. Note that
659
+ the very first datapoint (A) does not carry directional value as there is
660
+ no precedent movement. Price movement within the same bin is correctly
661
+ assigned its respective directional label.
662
+
663
+ \begin{table}[!t]
664
+ \centering
665
+ \caption{Up/Down-Bin Footprint Output Dataframe ($\beta=1$)}
666
+ \label{tab:updown_df}
667
+ \begin{tabular}{@{}cccccrr@{}}
668
+ \toprule
669
+ \textbf{Bin} & \textbf{From} & \textbf{Until}
670
+ & \textbf{Group} & \textbf{Down} & \textbf{Up} & \textbf{Delta} \\
671
+ \midrule
672
+ 1 & 3000 & 3001 & A & 0 & 0 & 0 \\
673
+ 2 & 3001 & 3002 & A & 0 & 1 & +1 \\
674
+ 3 & 3002 & 3003 & AC & 1 & 1 & 0 \\
675
+ 4 & 3003 & 3004 & BCGIJ & 3 & 2 & -1 \\
676
+ 5 & 3004 & 3005 & CFH & 1 & 2 & +1 \\
677
+ 6 & 3005 & 3006 & CF & 1 & 1 & 0 \\
678
+ 7 & 3006 & 3007 & CF & 1 & 1 & 0 \\
679
+ 8 & 3007 & 3008 & CEF & 2 & 1 & -1 \\
680
+ 9 & 3008 & 3009 & CDEF & 2 & 2 & 0 \\
681
+ 10 & 3009 & 3010 & DF & 0 & 2 & +2 \\
682
+ \bottomrule
683
+ \end{tabular}
684
+ \end{table}
685
+
686
+ \Cref{fig:updown_footprint} visualises this footprint as a dual-axis
687
+ histogram. Each bin possesses opposing horizontal stacks indicating the
688
+ total amount of upward versus downward crossing, exposing the directional bias
689
+ driving the profile gap-fills.
690
+
691
+ \begin{figure}[!t]
692
+ \centering
693
+ \includegraphics[width=\columnwidth]{fig_updown_footprint.png}
694
+ \caption{Up/Down-Bin Footprint Profile for the 10-datapoint example.
695
+ Red bars (left) signify down-bin gap-fills; teal bars (right) signify
696
+ up-bin gap-fills. Delta values $\delta[k]$ denote net directional
697
+ pressure at each price bin.}
698
+ \label{fig:updown_footprint}
699
+ \end{figure}
700
+
701
+
702
+ % ══════════════════════════════════════════════════════════════════════════════
703
+ % VI. BIN-SIZE ANALYSIS
704
+ % ══════════════════════════════════════════════════════════════════════════════
705
+ \section{Effect of Bin Size on Profile Resolution}\label{sec:binsize}
706
+
707
+
708
+ The bin-size parameter $\beta$ controls the granularity of the profile.
709
+ For two consecutive ticks at prices $p_{i-1}$ and $p_i$, the total number
710
+ of bins traversed (inclusive of both endpoints) is
711
+ \begin{equation}\label{eq:bins_beta}
712
+ K_i(\beta) \;=\;
713
+ \left|\left\lfloor \frac{p_i}{\beta} \right\rfloor
714
+ - \left\lfloor \frac{p_{i-1}}{\beta} \right\rfloor\right|
715
+ + 1.
716
+ \end{equation}
717
+
718
+ \noindent Halving $\beta$ approximately doubles the number of interpolated
719
+ bins, while doubling $\beta$ approximately halves it.
720
+
721
+ \begin{proposition}[Bin-count scaling]\label{prop:scaling}
722
+ For a fixed price displacement $\Delta p = |p_i - p_{i-1}|$ and bin
723
+ sizes $\beta_1 > \beta_2 > 0$, the bin counts satisfy
724
+ \begin{equation}\label{eq:scaling}
725
+ K_i(\beta_2) \;\ge\;
726
+ \left\lfloor \frac{\beta_1}{\beta_2} \right\rfloor
727
+ \cdot \bigl(K_i(\beta_1) - 1\bigr) + 1.
728
+ \end{equation}
729
+ \end{proposition}
730
+
731
+ \begin{proof}
732
+ Write $\Delta p = (K_i(\beta_1)-1)\,\beta_1 + r_1$ where
733
+ $0 \le r_1 < \beta_1$. Then
734
+ $K_i(\beta_2) = \lfloor \Delta p / \beta_2 \rfloor + 1
735
+ \ge \lfloor (K_i(\beta_1)-1)\,\beta_1 / \beta_2 \rfloor + 1
736
+ \ge \lfloor \beta_1/\beta_2 \rfloor\,(K_i(\beta_1)-1) + 1$.
737
+ \end{proof}
738
+
739
+ \Cref{tab:binsize} illustrates how varying $\beta$ changes the GMP
740
+ resolution for the XAUUSD example where price moves from \$3{,}000 to
741
+ \$3{,}010 ($\Delta p = 10$).
742
+
743
+ \begin{table}[!t]
744
+ \centering
745
+ \caption{Effect of Bin Size ($\beta$) on GMP Bin Count for $\Delta p = 10$}
746
+ \label{tab:binsize}
747
+ \begin{tabular}{@{}cccc@{}}
748
+ \toprule
749
+ $\beta$ (USD) & $K_i(\beta)$ & CMP bins & GMP bins filled \\
750
+ \midrule
751
+ 2.0 & 6 & 2 & 6 \\
752
+ 1.0 & 11 & 2 & 11 \\
753
+ 0.5 & 21 & 2 & 21 \\
754
+ 0.25 & 41 & 2 & 41 \\
755
+ 0.1 & 101 & 2 & 101 \\
756
+ \bottomrule
757
+ \end{tabular}
758
+ \end{table}
759
+
760
+ \noindent
761
+ Two key observations follow:
762
+ \begin{itemize}
763
+ \item \textbf{CMP is invariant to~$\beta$ in bin count:} regardless
764
+ of~$\beta$, CMP always fills exactly~2 bins (one per observed tick),
765
+ because no intermediate bins are populated.
766
+ \item \textbf{GMP scales as~$\mathcal{O}(\Delta p\,/\,\beta)$:}
767
+ the filled bin count grows inversely with~$\beta$, producing a
768
+ progressively finer-grained profile. Setting $\beta$~below the
769
+ instrument's tick size yields redundant empty bins, so the practical
770
+ lower bound is $\beta \ge \text{tick\_size}$.
771
+ \end{itemize}
772
+
773
+ \Cref{tab:binsize_half} presents the full GMP profile comparison for
774
+ $\beta=1$ versus $\beta=0.5$.
775
+
776
+ \begin{table}[!t]
777
+ \centering
778
+ \caption{GMP Profile: $\beta=1$ vs.\ $\beta=0.5$ (Price from \$3{,}000 to \$3{,}010)}
779
+ \label{tab:binsize_half}
780
+ \begin{tabular}{@{}cccc@{}}
781
+ \toprule
782
+ Price (USD) & CMP & GMP ($\beta\!=\!1$) & GMP ($\beta\!=\!0.5$) \\
783
+ \midrule
784
+ 3000.0 & 1 & 1 & 1 \\
785
+ 3000.5 & 0 & & 1 \\
786
+ 3001.0 & 0 & 1 & 1 \\
787
+ 3001.5 & 0 & & 1 \\
788
+ 3002.0 & 0 & 1 & 1 \\
789
+ 3002.5 & 0 & & 1 \\
790
+ 3003.0 & 0 & 1 & 1 \\
791
+ 3003.5 & 0 & & 1 \\
792
+ 3004.0 & 0 & 1 & 1 \\
793
+ 3004.5 & 0 & & 1 \\
794
+ 3005.0 & 0 & 1 & 1 \\
795
+ 3005.5 & 0 & & 1 \\
796
+ 3006.0 & 0 & 1 & 1 \\
797
+ 3006.5 & 0 & & 1 \\
798
+ 3007.0 & 0 & 1 & 1 \\
799
+ 3007.5 & 0 & & 1 \\
800
+ 3008.0 & 0 & 1 & 1 \\
801
+ 3008.5 & 0 & & 1 \\
802
+ 3009.0 & 0 & 1 & 1 \\
803
+ 3009.5 & 0 & & 1 \\
804
+ 3010.0 & 1 & 1 & 1 \\
805
+ \midrule
806
+ \textbf{Total bins} & \textbf{2} & \textbf{11} & \textbf{21} \\
807
+ \bottomrule
808
+ \end{tabular}
809
+ \end{table}
810
+
811
+
812
+ % ══════════════════════════════════════════════════════════════════════════════
813
+ % VII. ILLUSTRATIVE EXAMPLE
814
+ % ══════════════════════════════════════════════════════════════════════════════
815
+ \section{Illustrative Example}\label{sec:example}
816
+
817
+ Consider two raw XAUUSD ticks with $\beta=1$:
818
+ \begin{itemize}
819
+ \item Tick~1: trade at $p_1 = \$3{,}000$.
820
+ \item Tick~2: trade at $p_2 = \$3{,}010$.
821
+ \end{itemize}
822
+
823
+ \Cref{tab:cmp_vs_gmp} shows the resulting profiles side-by-side.
824
+
825
+ \begin{table}[!t]
826
+ \centering
827
+ \caption{CMP vs.\ GMP Comparison ($\beta=1$, XAUUSD)}
828
+ \label{tab:cmp_vs_gmp}
829
+ \begin{tabular}{@{}cccc@{}}
830
+ \toprule
831
+ Trade \# & Price (USD) & CMP stacks & GMP stacks \\
832
+ \midrule
833
+ 1 & 3000 & 1 & 1 \\
834
+ 0 & 3001 & 0 & 1 \\
835
+ 0 & 3002 & 0 & 1 \\
836
+ 0 & 3003 & 0 & 1 \\
837
+ 0 & 3004 & 0 & 1 \\
838
+ 0 & 3005 & 0 & 1 \\
839
+ 0 & 3006 & 0 & 1 \\
840
+ 0 & 3007 & 0 & 1 \\
841
+ 0 & 3008 & 0 & 1 \\
842
+ 0 & 3009 & 0 & 1 \\
843
+ 2 & 3010 & 1 & 1 \\
844
+ \midrule
845
+ \multicolumn{2}{c}{\textbf{Total stacks}} & \textbf{2} & \textbf{11} \\
846
+ \bottomrule
847
+ \end{tabular}
848
+ \end{table}
849
+
850
+ CMP records only 2~stacks at the observed prices; GMP records
851
+ 11~stacks spanning the full traversal. \Cref{fig:profile} visualises
852
+ both profiles as horizontal histograms.
853
+
854
+
855
+
856
+
857
+ % ══════════════════════════════════════════════════════════════════════════════
858
+ % VIII. DISCUSSION
859
+ % ══════════════════════════════════════════════════════════════════════════════
860
+ \section{Discussion}\label{sec:discussion}
861
+
862
+ \subsection{Advantages}
863
+
864
+ \begin{enumerate}
865
+ \item \textbf{Maximal resolution.}\;By operating on raw bid/ask ticks,
866
+ mBA-GMP captures every price movement the broker records---no
867
+ information is pre-aggregated or discarded.
868
+ \item \textbf{No profile gaps.}\;Gap-filling ensures that every price
869
+ level traversed by the market is represented, preventing the sparse,
870
+ misleading histograms produced by CMP on fast-moving ticks.
871
+ \item \textbf{Volume-neutral interpolation.}\;Interpolated bins receive
872
+ exactly one stack each, reflecting a traversal rather than fabricating
873
+ volume. This preserves the interpretive semantics of the profile:
874
+ high-stack regions still correspond to genuine price acceptance.
875
+ \item \textbf{Directional Context.}\;By classifying gap-filled stacks into
876
+ up/down bins, the resultant footprint profile reveals net directional
877
+ pressure across the evaluated interval, independent of conventional
878
+ bid/ask volume mechanics.
879
+ \item \textbf{Tunable resolution via~$\beta$.}\;The bin-size parameter
880
+ allows practitioners to control profile granularity without altering
881
+ the underlying data, unlike candlestick-based approaches where
882
+ resolution is fixed by the bar period.
883
+ \end{enumerate}
884
+
885
+ \subsection{Limitations}
886
+
887
+ \begin{enumerate}
888
+ \item \textbf{Data availability.}\;Not all brokers expose raw
889
+ micro\-/millisecond tick feeds. Where only TOCHLV data is available,
890
+ GMP can still be applied to candlestick prices, but the
891
+ ``mBA'' guarantee is lost.
892
+ \item \textbf{Computational cost.}\;The $\mathcal{O}(N + D)$ complexity
893
+ implies that highly volatile instruments with large cumulative
894
+ displacement~$D$ will require proportionally more computation. For
895
+ modern hardware this is rarely a practical bottleneck, but
896
+ memory-constrained environments may require streaming or windowed
897
+ implementations.
898
+ \item \textbf{Interpolation assumption.}\;Gap-filling assumes that price
899
+ continuously traverses every intermediate level. In instruments with
900
+ genuine price gaps (e.g., exchange-traded equities at market open),
901
+ this assumption may over-represent bins that were never actually
902
+ available for trading.
903
+ \end{enumerate}
904
+
905
+ \subsection{Practical Guidance on Choosing $\beta$}
906
+
907
+ \begin{itemize}
908
+ \item Set $\beta$ near to the instrument's minimum tick size for maximum
909
+ resolution (e.g., $\beta = 0.01$ for XAUUSD's 0.001 lowest tick, on many brokers).
910
+ \item Increase $\beta$ to reduce noise in low-liquidity regimes or to
911
+ align bins with round-number psychological levels.
912
+ \item As shown in \Cref{sec:binsize}, CMP bin count is invariant
913
+ to~$\beta$; thus, the resolution advantage of GMP grows as $\beta$
914
+ decreases.
915
+ \end{itemize}
916
+
917
+
918
+ % ══════════════════════════════════════════════════════════════════════════════
919
+ % IX. CONCLUSION
920
+ % ══════════════════════════════════════════════════════════════════════════════
921
+ \section{Conclusion}\label{sec:conclusion}
922
+
923
+ We have presented \textbf{mBA-GMP}, a market-profile construction method
924
+ that combines two principles: (i)~sourcing data from raw micro\-/millisecond
925
+ bid/ask tick-formation records rather than pre-aggregated candlesticks,
926
+ and (ii)~interpolating all intermediate price bins between consecutive
927
+ ticks. We formalised both Conventional Market Profile (CMP) and
928
+ Gap-filled Market Profile (GMP), provided pseudocode algorithms with
929
+ complexity analysis, and demonstrated that the bin-size parameter~$\beta$
930
+ controls profile resolution with a simple inverse relationship.
931
+
932
+ The dataframe recording approach (\Cref{sec:dataframe}) showed concretely
933
+ how 10~raw datapoints map to CMP bins with gaps, how gap-filling
934
+ produces a GMP dataframe in which every price bin is populated, and how
935
+ these intermediate bins are classified into directional up/down stacks
936
+ to yield a structural footprint. The accompanying charts and tabulated
937
+ outputs make the method reproducible and directly applicable to real-world
938
+ tick streams.
939
+
940
+ Future directions include extending the gap-filling convention to
941
+ weighted interpolation (where intermediate bins receive fractional stacks
942
+ proportional to their traversal speed) and evaluating mBA-GMP on
943
+ live order-book data across multiple asset classes.
944
+
945
+
946
+ \newpage
947
+ % ══════════════════════════════════════════════════════════════════════════════
948
+ % REFERENCES
949
+ % ══════════════════════════════════════════════════════════════════════════════
950
+ \bibliographystyle{IEEEtran}
951
+ \bibliography{references}
952
+
953
+ \end{document}
mBA-GMP.v3/raw_draft_of_concept.png ADDED

Git LFS Details

  • SHA256: c03511fbff70de1bd935d3a816cbcc81ee1709a7f10cb70ab97d885c3e7490d5
  • Pointer size: 131 Bytes
  • Size of remote file: 238 kB
mBA-GMP.v3/references.bib ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @book{steidlmayer1986market,
2
+ title = {Market Profile: The Key to Understanding Market Dynamics},
3
+ author = {Steidlmayer, J. Peter and Koy, Kevin},
4
+ year = {1986},
5
+ publisher = {Probus Publishing}
6
+ }
7
+
8
+ @book{dalton2007markets,
9
+ title = {Markets in Profile: Profiting from the Auction Process},
10
+ author = {Dalton, James F. and Jones, Eric T. and Dalton, Robert B.},
11
+ year = {2007},
12
+ publisher = {John Wiley \& Sons}
13
+ }
14
+
15
+ @article{engle2000econometrics,
16
+ title = {The Econometrics of Ultra-High-Frequency Data},
17
+ author = {Engle, Robert F.},
18
+ journal = {Econometrica},
19
+ volume = {68},
20
+ number = {1},
21
+ pages = {1--22},
22
+ year = {2000}
23
+ }
24
+
25
+ @book{hasbrouck2007empirical,
26
+ title = {Empirical Market Microstructure: The Institutions, Economics, and Econometrics of Securities Trading},
27
+ author = {Hasbrouck, Joel},
28
+ year = {2007},
29
+ publisher = {Oxford University Press}
30
+ }
31
+
32
+ @article{ane2000order,
33
+ title = {Order Flow, Transaction Clock, and Normality of Asset Returns},
34
+ author = {An\'{e}, Thierry and Geman, H\'{e}lyette},
35
+ journal = {The Journal of Finance},
36
+ volume = {55},
37
+ number = {5},
38
+ pages = {2259--2284},
39
+ year = {2000}
40
+ }
41
+
42
+ @article{clark1973subordinated,
43
+ title = {A Subordinated Stochastic Process Model with Finite Variance for Speculative Prices},
44
+ author = {Clark, Peter K.},
45
+ journal = {Econometrica},
46
+ volume = {41},
47
+ number = {1},
48
+ pages = {135--155},
49
+ year = {1973}
50
+ }
51
+
52
+ @article{easley1992time,
53
+ title = {Time and the Process of Security Price Adjustment},
54
+ author = {Easley, David and O'Hara, Maureen},
55
+ journal = {The Journal of Finance},
56
+ volume = {47},
57
+ number = {2},
58
+ pages = {577--605},
59
+ year = {1992}
60
+ }
61
+
62
+ @book{ohara1995market,
63
+ title = {Market Microstructure Theory},
64
+ author = {O'Hara, Maureen},
65
+ year = {1995},
66
+ publisher = {Blackwell Publishers}
67
+ }
68
+
69
+ @book{bouchaud2018trades,
70
+ title = {Trades, Quotes and Prices: Financial Markets Under the Microscope},
71
+ author = {Bouchaud, Jean-Philippe and Bonart, Julius and Donier, Jonathan and Gould, Martin},
72
+ publisher = {Cambridge University Press},
73
+ year = {2018}
74
+ }
75
+
76
+ @article{glosten1985bid,
77
+ title = {Bid, Ask and Transaction Prices in a Specialist Market with Heterogeneously Informed Traders},
78
+ author = {Glosten, Lawrence R. and Milgrom, Paul R.},
79
+ journal = {Journal of Financial Economics},
80
+ volume = {14},
81
+ number = {1},
82
+ pages = {71--100},
83
+ year = {1985}
84
+ }
85
+
86
+ @article{madhavan2000market,
87
+ title = {Market Microstructure: A Survey},
88
+ author = {Madhavan, Ananth},
89
+ journal = {Journal of Financial Markets},
90
+ volume = {3},
91
+ number = {3},
92
+ pages = {205--258},
93
+ year = {2000}
94
+ }
95
+
96
+ @article{harris1990estimation,
97
+ title = {Estimation of Stock Price Variances and Serial Covariances from Discrete Observations},
98
+ author = {Harris, Frederick H. deB.},
99
+ journal = {Journal of Financial and Quantitative Analysis},
100
+ volume = {25},
101
+ number = {3},
102
+ pages = {291--306},
103
+ year = {1990}
104
+ }
mBA-GMP.v3/updown_profile.csv ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ bin (with binsize = 1 symbol's price unit),price from,price until,datapoint group,down-bin profile's stacks,up-bin profile's stacks,delta-bin profile's stacks
2
+ 1,3000,3001,A,0,0,0
3
+ 2,3001,3002,A,0,1,1
4
+ 3,3002,3003,AC,1,1,0
5
+ 4,3003,3004,BCGIJ,3,2,-1
6
+ 5,3004,3005,CFH,1,2,1
7
+ 6,3005,3006,CF,1,1,0
8
+ 7,3006,3007,CF,1,1,0
9
+ 8,3007,3008,CEF,2,1,-1
10
+ 9,3008,3009,CDEF,2,2,0
11
+ 10,3009,3010,DF,0,2,2