Day-Count Conventions and Variance Interpolation in Volatility Curves
Summary
The document explains how QuantLib’s BlackVarianceCurve distributes variance through time according to its day-count convention. Because the curve interpolates linearly in variance, using Business/252 produces a constant variance increment per business day between nodes, while Actual/365 allocates variance by calendar day. This allows a quoted term volatility to translate into a daily variance profile without manually constructing a separate volatility for each date.
An example shows a one-week quote represented as total variance using five business days over 252, with equal increments across those days. It also clarifies that volatility over a period is recovered from variance divided by the corresponding year fraction, and that forward volatility between future dates uses the variance change over that interval. The example illustrates behavior between curve nodes; results depend on the chosen day counter, and calendar-day conventions allocate more variance over weekends than weekdays.
Key ideas
- BlackVarianceCurve interpolates linearly in variance between its dated volatility nodes.
- Business/252 allocates equal variance increments to business days between nodes.
- Actual/365 allocates variance according to calendar time, including weekend days.
- Volatility for an interval is the square root of its variance divided by the interval’s year fraction.
Tags
Full text
# Day weight conventions for vol curves in quantlib
# Day weight conventions for vol curves in quantlib
I'm trying to build a day weight 'aware' vol curve (simple term structure in time, but flat across a given time slice) in quantlib. I've supplied a list of dates & vols and built it with ql.blackVarianceCurve, trying different pre-defined daycount types (Actual365Fixed, Business252 etc). My aim would be initially to produce a vol curve that has constant variance per business day. So if I were to give it 1w vol = 10%, it would understand that (ignoring holidays) 1w at 10% represents term variance of 10%^2 * 7/365, and that is evenly distributed across the 5 business days. Overnight vol [from thurs to fri] = 10% * sqrt(7/5) = 11.83% Monday vol [from thurs to mon] = 10%*(7/5 * 2/4) = 8.366% etc ie the quoted vols are adjusted for business/calendar day fraction.
In theory I could write a function which does this, outputting each business day implied vol [appropriately adjusted] and then input that into the quantlib functions, but that seems like a heavy handed approach.
thanks in advance for any help.
## Answer by Luigi Ballabio (score 1)
https://quant.stackexchange.com/a/85690
By default, `BlackVarianceCurve` interpolates linearly in variance; this has the effect you want, i.e., depending on the day counter, constant variance per day (`Actual365Fixed`) or business day (`Business252`).
I'll use a simple setup based on June 18th 2026, a Thursday:
```
In [1]: import QuantLib as ql
...: import math
In [2]: today = ql.Date(18, ql.June, 2026)
...: ql.Settings.instance().evaluationDate = today
In [3]: dates = [ today + 7, today + 14 ]
...: vols = [ 0.10, 0.12 ]
...: vol = ql.BlackVarianceCurve(today, dates, vols, ql.Business252(ql.WeekendsOnly()))
```
So a 10% one-week volatility and a 12% two-weeks volatility.
If you ask for the variance one week from today (i.e., at `today+7`), you'll get what you expect: $\sigma^2 T$, with $\sigma$ = 10% and $T$ = 5/252 according to the business/252 day count convention:
```
In [4]: var1w = vol.blackVariance(today + 7, 1.0)
...:
...: print(var1w)
...: print(0.10**2 * (5/252))
0.0001984126984126984
0.00019841269841269844
```
If you ask for the variance for Friday (one day from today), you'll get a fifth of that:
```
In [5]: var1d = vol.blackVariance(today + 1, 1.0)
...:
...: print(var1d)
...: print(var1w / 5)
3.968253968253968e-05
3.968253968253968e-05
```
and if you ask for the variance at each of the other business days, you'll see that it increases by the same amount per day:
```
In [6]: var4d = vol.blackVariance(today + 4, 1.0) # Monday
...: var5d = vol.blackVariance(today + 5, 1.0) # Tuesday
...: var6d = vol.blackVariance(today + 6, 1.0) # Wednesday
In [7]: print(var4d - var1d)
...: print(var5d - var4d)
...: print(var6d - var5d)
...: print(var1w - var6d)
3.968253968253968e-05
3.968253968253968e-05
3.968253968253968e-05
3.968253968253968e-05
```
so I'd say that this fulfills your expectation that the variance is evenly distributed across the 5 business days. If you try it out, you'll get the same behavior (with a different variance-per-day) between the one-week and two-weeks nodes.
I'm not sure I understand how you're calculating the volatility you'd expect, though. For any time, given the variance $V$, you'll get the volatility from today to that time by inverting the same $V = \sigma^2 t$ formula you used before, so $\sigma = \sqrt{(V/t)}$. For instance, the one-day volatility ($t$=1/252) would be
```
In [8]: print(math.sqrt(var1d / (1/252)))
0.1
```
and you can also retrieve it directly as
```
In [9]: print(vol.blackVol(today + 1, 1.0))
0.1
```
If you want the volatility between two dates in the future (e.g., Monday and Tuesday) you can use the same $\sigma = \sqrt{(V/t)}$ formula, but with $V$ being the variance between Monday and Tuesday and $t$ being the time between them (1/252); or you can call
```
In [10]: print(vol.blackForwardVol(today + 4, today + 5, 1.0))
0.1
```
As long as you stay in the first week, though, you're interpolating linearly in time between $t$=0 (where the variance is also 0) and the first node ($t$=$T$=5/252). This means that the volatility will be constant and equal to $\sigma$ over any period in the first week (you can work it out easily with paper and pencil). Over the second week, you'll see the volatility change:
```
In [11]: print(vol.blackForwardVol(today + 11, today + 12, 1.0))
0.13711309200802083
```
If you use Actual/365, you'll see the same behavior, except that between Friday and Monday the variance will increase three times as much as between Monday and Tuesday, and you'll have to calculate times as $n$/365 where $n$ is the number of calendar days.Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.