Frequency conversion (fconvert)¶
Round-trip frequency conversion across YP frequencies (Yearly / HalfYearly / Quarterly /
Monthly) and calendar frequencies (Daily / BDaily / Weekly). Public surface: fconvert,
fconvert_tseries, fconvert_mit, fconvert_range, fconvert_parts, extend_series,
strip_tseries / strip_tseries_inplace, trim_series.
YP→YP aggregate (lower-frequency) paths route through a Cython kernel that fuses the
two nested loops in aggregate_groups_numpy; introspect with fconvert_is_cython().
tsecon.fconvert ¶
Frequency-conversion subsystem.
Mirrors TimeSeriesEcon.jl/src/fconvert/. The single user-facing entry is
:func:fconvert, which dispatches on the second positional argument:
fconvert(target, mit, *, ref=..., round_to=...)— convert an :class:~tsecon.mit.MIT.round_tois only meaningful for BDaily targets.fconvert(target, mitrange, *, trim=...)— convert an :class:~tsecon.mitrange.MITRange.fconvert(target, tseries, *, method=..., ref=...)— convert a :class:~tsecon.tseries.TSeriesusing a built-in aggregator / spreader.fconvert(f, target, tseries, *, ref=..., **kwargs)— convert a TSeries using the custom callablef.
Lower-level entries (also exported) for callers that already know the input type:
- :func:
fconvert_mit/ :func:fconvert_range/ :func:fconvert_tseries— the per-input-type entry points (no Julia-style multiple-dispatch overhead). - :func:
fconvert_parts— internal triple used by the YP→YP TSeries conversion path ((period, source_month, target_month)); exposed for advanced use.
Helpers and series-shape operations:
- :func:
extend_series— pad to align with target-period boundaries. - :func:
trim_series— restrict to the inner aligned range. - :func:
strip_tseries/ :func:strip_tseries_inplace— drop leading and trailing typenan entries. - :func:
repeat_uneven/ :func:divide_uneven/ :func:linear_uneven— vector helpers used by the higher-frequency conversion methods (and available as the canonical custom-function aliases that mirrormethod="const" / "even" / "linear"exactly).
Currently still ⬜: the BDaily kwarg variants (skip_holidays /
skip_all_nans / holidays_map) block on the options.jl port; and
BDaily-source :func:extend_series needs the cleanedvalues plumbing.
divide_uneven ¶
Divide each element of x by its inner count, then repeat.
Returns a Float64 vector of length sum(inner). Mirrors the Julia
divide_uneven: divide_uneven([1, 2, 4], [2, 1, 4]) ==
[0.5, 0.5, 2.0, 1.0, 1.0, 1.0, 1.0]. Extra keyword arguments are
accepted and ignored.
Source code in src/tsecon/fconvert/_helpers.py
linear_uneven ¶
linear_uneven(
x: ArrayLike,
output_lengths: ArrayLike,
*,
ref: Ref = "end",
**_kwargs: object,
) -> np.ndarray
Linearly interpolate x across per-input output counts.
Returns a Float64 vector of length sum(output_lengths). ref="end"
treats each input value as the end-point of its segment; ref="begin"
treats it as the start-point. Tail-end segments extrapolate with the slope
of the adjacent segment.
Source code in src/tsecon/fconvert/_helpers.py
repeat_uneven ¶
Repeat each element of x according to the matching count in inner.
Returns a vector of length sum(inner). Mirrors the Julia
repeat_uneven: repeat_uneven([1, 2, 4], [2, 1, 4]) ==
[1, 1, 2, 4, 4, 4, 4]. Extra keyword arguments are accepted and
ignored — required so this helper is drop-in callable from
:func:tsecon.fconvert.fconvert (which always forwards ref and
outrange).
Source code in src/tsecon/fconvert/_helpers.py
strip_tseries ¶
Return a new :class:TSeries with leading and trailing typenan trimmed.
Mirrors Julia's Base.strip(t::TSeries). The original is unchanged.
An all-typenan input returns an empty TSeries anchored at firstdate.
Source code in src/tsecon/fconvert/_helpers.py
strip_tseries_inplace ¶
Trim leading and trailing typenan entries in place; return t.
Mirrors Julia's strip!(t::TSeries).
fconvert_mit ¶
fconvert_mit(
target: FrequencyLike,
mit_from: MIT,
*,
ref: Ref = "end",
round_to: RoundTo = "current",
) -> MIT
Convert mit_from to target.
For YP→YP and any Calendar-involving conversion ref selects whether to
align to the end of the source period ("end", the default) or the start
("begin"). Mirrors Julia's fconvert(F_to, MIT_from; ref=:end).
When the target is :class:BDaily, round_to controls how a date that
lands on a weekend is resolved: "current" (default) raises on
weekends, "previous" snaps to the preceding business day, "next"
snaps forward.
Examples:
>>> from tsecon import yy, Quarterly
>>> fconvert_mit(Quarterly, yy(22), ref="end")
22Q4
>>> fconvert_mit(Quarterly, yy(22), ref="begin")
22Q1
Source code in src/tsecon/fconvert/_mit.py
fconvert_parts ¶
fconvert_parts(
target: FrequencyLike,
mit_from: MIT,
*,
ref: Ref = "end",
) -> tuple[int, int, int]
Return (to_period, from_month, to_month) for the YP→YP boundary.
With ref="end" the second / third elements are the end-month-of-year
of the source / target periods; with ref="begin" they are the start
months. Mirrors Julia's fconvert_parts. YP-only; raises for any
Calendar source or target.
Source code in src/tsecon/fconvert/_mit.py
fconvert_range ¶
fconvert_range(
target: FrequencyLike,
range_from: MITRange,
*,
trim: Trim = "both",
parts: bool = False,
skip_holidays: bool = False,
holidays_map: TSeries | None = None,
) -> MITRange | tuple[int, int, int, int, int, int]
Convert range_from to target.
trim controls whether the start and / or end of the output range are
truncated when the source range begins or ends partway through a target
period. With parts=True (YP→YP only) returns the six-tuple
(fi_to_period, fi_from_start_month, fi_to_start_month, li_to_period,
li_from_end_month, li_to_end_month) used by the TSeries conversion path.
For BDaily-source lower-frequency conversion, skip_holidays /
holidays_map shift the boundary predecessor / successor past
consecutive holidays before applying the truncation check (mirrors
fconvert_mit.jl lines 239-258). skip_holidays=True consults the
global getoption('bdaily_holidays_map') map; holidays_map=t
overrides it. The kwargs are only meaningful when range_from's
frequency is BDaily and the conversion is to a lower frequency;
elsewhere they're accepted as no-ops to keep the dispatcher uniform.
Examples:
>>> from tsecon import yy, mitrange, Quarterly
>>> fconvert_range(Quarterly, mitrange(yy(22), yy(24)))
22Q1:24Q4
Source code in src/tsecon/fconvert/_mit.py
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | |
extend_series ¶
extend_series(
target: FrequencyLike,
t: TSeries,
*,
direction: ExtendDirection = "both",
method: ExtendMethod = "mean",
) -> TSeries
Pad a TSeries to align with target-frequency period boundaries.
Returns a new TSeries (the input is not mutated). method="mean" fills
each padded section with the mean of the existing values that fall within
the spanned target period; method="end" repeats the nearest in-range
value (last value for the trailing pad, first in-range value for the
leading pad — matching Julia's behaviour when there is exactly one value
in the spanning period).
Source / target may be any non-Unit frequency. For a BDaily source the
in-range first/last value used by method="end", and the per-period
mean used by method="mean", are computed via
cleanedvalues(...; skip_all_nans=True) so leading / trailing NaNs do
not poison the fill (matches Julia's BDaily branch at
fconvert_helpers.jl lines 309-326).
Source code in src/tsecon/fconvert/_tseries.py
fconvert_is_cython ¶
Return True iff the Cython-compiled fconvert kernel was importable.
Useful for tests, benchmarks, and diagnostic prints — the public
:func:fconvert_tseries is implementation-agnostic. When this
returns False the same calls go through the pure-NumPy kernel
in _fconvert_kernels.py; behaviour is identical, only speed
differs.
Source code in src/tsecon/fconvert/_tseries.py
fconvert_tseries ¶
fconvert_tseries(
arg1: FrequencyLike | Callable[..., Any],
arg2: TSeries | FrequencyLike,
arg3: TSeries | None = None,
*,
method: _AnyMethod | None = None,
ref: Ref | None = None,
**kwargs: Any,
) -> TSeries
Convert t to target frequency.
Two call shapes mirror Julia's two fconvert overloads:
fconvert_tseries(target, t, *, method=..., ref=...)— built-in aggregator / spreader.methodis one of"mean" / "sum" / "min" / "max" / "point" / "begin" / "end"for lower-frequency conversions and"const" / "even" / "linear"for higher-frequency conversions.fconvert_tseries(f, target, t, *, ref=..., **kwargs)— pass a custom callable. For lower-frequency conversionsfmust accept a single vector and return a scalar; for higher-frequency conversions it must accept(values, output_lengths)plus the keyword argumentsref=...andoutrange=....
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
arg1
|
FrequencyLike or Callable
|
Either the target frequency (built-in form) or the custom callable (three-positional form). |
required |
arg2
|
TSeries or FrequencyLike
|
The TSeries to convert in the built-in form, or the target frequency in the three-positional form. |
required |
arg3
|
TSeries
|
The TSeries to convert in the three-positional custom-callable form. |
None
|
method
|
str
|
Aggregator / spreader name. Lower-frequency:
|
None
|
ref
|
('begin', 'end')
|
Boundary anchor used when the source / target periods do not
align exactly. Defaults to |
"begin"
|
**kwargs
|
Any
|
Forwarded to the custom callable in the three-positional form.
For BDaily source on lower-frequency conversion, also accepts
|
{}
|
Returns:
| Type | Description |
|---|---|
TSeries
|
A new series at the |
Raises:
| Type | Description |
|---|---|
ValueError
|
Source or target is |
TypeError
|
The custom-callable form is used incorrectly, or
|
NotImplementedError
|
Conversion direction is not yet implemented. |
Examples:
Spread a Quarterly series across each quarter's three months
using the "const" (repeat) method::
>>> from tsecon import qq, TSeries, Monthly, fconvert_tseries
>>> import numpy as np
>>> q = TSeries(qq(2020, 1), np.arange(1, 11, dtype=float))
>>> m = fconvert_tseries(Monthly, q, method="const")
>>> m.firstdate
2020M1
>>> m.lastdate
2022M6
Aggregate a Monthly series to Quarterly with the mean::
>>> from tsecon import mm, Quarterly
>>> series = TSeries(mm(2020, 1), np.arange(1.0, 13.0))
>>> fconvert_tseries(Quarterly, series, method="mean").values.tolist()
[2.0, 5.0, 8.0, 11.0]
Source code in src/tsecon/fconvert/_tseries.py
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | |
trim_series ¶
trim_series(
target: FrequencyLike,
t: TSeries,
*,
direction: ExtendDirection = "both",
) -> TSeries
Trim a TSeries to ranges that align with target-frequency boundaries.
Returns a new TSeries restricted to the inner range produced by
fconvert(F_from, fconvert(F_to, rangeof(t), trim=direction)).
Source code in src/tsecon/fconvert/_tseries.py
fconvert ¶
fconvert(
target: FrequencyLike,
what: MIT,
*,
ref: str = "end",
round_to: str = "current",
) -> MIT
Convert an :class:MIT, :class:MITRange, or :class:TSeries to a target frequency.
See the module-level docstring for the four call shapes. Dispatches on the second positional argument (or, when a callable is the first positional argument, the third).