Convolutional Neural Networks
A convolutional network learns a small set of pattern detectors and slides each one across the whole input, so a shape learned in one place is recognised everywhere. That single idea cuts the parameter count by orders of magnitude and is what makes networks work on images and price series.
Prerequisites: The Multilayer Perceptron, Backpropagation
Hand a The Multilayer Perceptron a 256-day window of prices and it faces a problem it cannot see its way out of: to the network, the 40th input and the 41st input are two unrelated quantities. If a sharp reversal on day 40 predicts something, the model learns that fact with one set of weights. When the same reversal shows up on day 41 — as it inevitably will, since patterns do not politely align to fixed offsets — none of that learning transfers. It has to learn the shape again, from scratch, at every possible position.
The bill arrives twice. First in data, because each position needs its own examples. Second in parameters: a dense layer from 256 inputs to 64 units already carries 16,448 weights, and none of them share anything.
The analogy: one stencil, slid across the page
Cut a shape out of cardboard — say a V, for a dip and recovery. Now slide that stencil along a printed price chart, and at every position write down how well the chart matches the cutout underneath. You get a new series: a running score of "how V-ish is the chart around here". One stencil, used at every position, and it works just as well on a chart of 8 bars as on one of 8,000.
That is a convolution, and quants have been running them by hand forever. A 20-day moving average is a convolution with a stencil of twenty equal weights. A momentum signal that subtracts the old price from the recent one is a convolution with a stencil that is negative at the back and positive at the front. The only thing a convolutional network adds is that it learns the shape of the stencil from the data instead of you choosing it, and it learns several stencils at once.
The maths
For a one-dimensional series and a kernel (the stencil) of weights , the output at position is
In words: line the kernel up starting at position , multiply each weight by the value beneath it, add them up, add a bias. Then move one position right and do it again. The resulting series is called a feature map — one number per position saying how strongly this particular pattern fired there.
Every symbol matters and there are only four. is the pattern being looked for. is how many bars the pattern spans. is a threshold offset. is where you currently are. The kernel weights are the same at every — that is weight sharing, and it is the whole source of the savings.
Worked example 1: a convolution by hand
Take eight closing prices: . Use the kernel with , which measures "how much higher is the price two bars on".
Slide it along, one position at a time:
- Position 1 covers :
- Position 2 covers :
- Position 3 covers :
- Position 4 covers :
- Position 5 covers :
- Position 6 covers :
The feature map is and its peak at position 4 correctly flags the steepest advance. Three numbers described the whole detector. Pass this through a ReLU and downward moves become zero, leaving a clean "rising" channel; a second kernel gives you the matching "falling" channel.
Note the length: eight inputs became six outputs. In general the output length is
where is the input length, the kernel width, the padding added at the edges and the stride (how far the kernel jumps each time). In words: count how many places the kernel fits. With , , no padding and stride 1 you get outputs; add and you get , preserving length; use stride instead and you get , halving the series.
Worked example 2: what weight sharing actually saves
Compare two layers reading the same 256-bar window.
Dense layer, 64 units. Every unit has one weight per input plus a bias:
Convolutional layer, 8 kernels of width 5. Every kernel has five weights plus a bias, and that is all — the same five are reused at all 252 positions:
That is 343 times fewer parameters, and it produces more numbers: 8 channels by 252 positions, or 2,016 values, versus 64. Fewer things to learn, more structure extracted. On noisy financial data, where the binding constraint is almost always the amount of independent signal in the sample, that ratio is the difference between a model that generalises and one that memorises.
Depth buys width of view
A width-5 kernel only ever sees five bars. Stack a second convolutional layer on top and each of its outputs summarises five outputs of the first, which between them covered nine input bars. This span is the receptive field, and for stacked layers of width it is — so four layers of width 5 see 17 bars.
That hierarchy is the second half of the idea. On images, early kernels find edges, later ones find corners and textures, later still whole objects. On a price series, early kernels find single-bar jumps and gaps, later ones find multi-day patterns built from those pieces.
Two commitments define a convolutional layer: weight sharing (the same detector is applied everywhere, so a pattern learned once is recognised anywhere) and locality (each output depends only on a short neighbouring window). Both are assumptions about your data. When they hold, you get a huge reduction in parameters for free.
What this means in practice
Convolutions apply to any input where neighbouring positions genuinely belong together: a price or volume series, an order book snapshot across price levels, a volatility surface across strike and tenor. Multiple related series become channels — feed open, high, low, close and volume as five channels and the kernels learn patterns across them jointly, exactly as the three colour channels work in an image.
They are the wrong tool when position is arbitrary. A row of cross-sectional factor exposures — value, momentum, quality, size — has no meaningful ordering, so "neighbouring columns belong together" is simply false and a plain MLP or gradient-boosted tree is the honest choice.
Practically, kernels are learned by ordinary Backpropagation with one twist: because a weight is used at every position, its gradient is the sum of the gradients from all those positions. That is also why convolutional layers train stably even when they are deep.
The trap that ruins quant CNNs: a standard convolution is centred. Ask a library for "same" padding and it pads both ends, so the output at time is computed from bars on both sides of — including the future. Nothing errors, nothing warns, and your backtest looks extraordinary. Time series need causal convolutions, padded only on the left, so position sees and earlier and nothing else. A second, smaller confusion: what deep learning frameworks call convolution is technically cross-correlation, since they do not flip the kernel. It makes no difference to a learned filter, but it will trip you up when comparing against signal-processing formulas.
Related concepts
Practice in interviews
Further reading
- LeCun et al., Gradient-Based Learning Applied to Document Recognition (1998)
- Goodfellow, Bengio & Courville, Deep Learning, ch. 9