Serialization
All major curve types and the Solver support JSON
serialization via to_json() and from_json(). This enables persisting
calibrated curves to disk, transmitting them over a network, or inspecting
their structure for debugging. Links to
DiscountCurve for the primary example.
Discount Curve Round-Trip
The serialization pattern is the same for all curve types: call to_json() to
get a JSON string, and the corresponding static from_json() to restore the
object. The restored curve produces identical query results.
import datetime
import json
from vade import DiscountCurve, LineCurve, NelsonSiegel, Solver, Deposit, IRS
effective = datetime.date(2025, 6, 16)
curve = DiscountCurve(
{
effective: 1.0,
datetime.date(2025, 12, 16): 0.98,
datetime.date(2026, 6, 16): 0.96,
datetime.date(2027, 6, 16): 0.925,
datetime.date(2030, 6, 16): 0.87,
},
interpolation="log_linear",
convention="act360",
)
json_str = curve.to_json()
isinstance(json_str, str) # True
restored = DiscountCurve.from_json(json_str)
float(restored.discount_factor(datetime.date(2026, 6, 16))) # 0.96
assert float(restored.discount_factor(datetime.date(2026, 6, 16))) == float(
curve.discount_factor(datetime.date(2026, 6, 16))
)LineCurve and Parametric Curves
The same to_json() / from_json() pattern applies to
LineCurve and parametric curve types like
NelsonSiegel. Each type's from_json() is a
static method that returns the correct type.
line = LineCurve(
{
effective: 0.040,
datetime.date(2026, 6, 16): 0.039,
datetime.date(2027, 6, 16): 0.038,
},
interpolation="linear",
convention="act360",
)
line_restored = LineCurve.from_json(line.to_json())
float(line_restored.discount_factor(datetime.date(2026, 6, 16))) # 0.9612299019102728
assert float(line_restored.discount_factor(datetime.date(2026, 6, 16))) == float(
line.discount_factor(datetime.date(2026, 6, 16))
)
ns = NelsonSiegel(
beta0=0.04, beta1=-0.02, beta2=0.03, tau=1.5,
base_date=effective, convention="act365f",
)
ns_restored = NelsonSiegel.from_json(ns.to_json())
float(ns_restored.zero_rate(effective, datetime.date(2026, 6, 16))) # 0.03189622964353336
assert float(ns_restored.zero_rate(effective, datetime.date(2026, 6, 16))) == float(
ns.zero_rate(effective, datetime.date(2026, 6, 16))
)Solver State
Persisting a calibrated Solver captures the full calibration state -- curves, instruments, and weights. This is useful for reproducibility: save after calibration, restore later without re-running the optimization.
cal_curve = DiscountCurve(
{
effective: 1.0,
datetime.date(2025, 12, 16): 1.0,
datetime.date(2026, 6, 16): 1.0,
datetime.date(2027, 6, 16): 1.0,
},
interpolation="log_linear",
convention="act360",
id="sofr",
)
dep = Deposit(effective=effective, termination="6m", rate=0.0, convention="act360")
irs_1y = IRS(
effective=effective, termination="1y", frequency="a",
fixed_rate=0.0, convention="act360", float_convention="act360",
)
irs_2y = IRS(
effective=effective, termination="2y", frequency="a",
fixed_rate=0.0, convention="act360", float_convention="act360",
)
solver = Solver(
curves=[cal_curve],
instruments=[(dep, 0.0430), (irs_1y, 4.00), (irs_2y, 3.85)],
)
result = solver.iterate()
assert result.converged
df_before = float(solver.get_curve(0).discount_factor(datetime.date(2026, 6, 16)))
solver_json = solver.to_json()
restored_solver = Solver.from_json(solver_json)
df_after = float(restored_solver.get_curve(0).discount_factor(datetime.date(2026, 6, 16)))
df_before # 0.9610212072035146
df_after # 0.9610212072035146
assert abs(df_before - df_after) < 1e-10Inspecting JSON Structure
Use json.loads() on the serialized string to inspect the internal structure.
This is useful for debugging and integrating with external tools that consume
JSON.
data = json.loads(curve.to_json())
sorted(data.keys()) # ['calendar', 'convention', 'id', 'interpolator', 'modifier', 'nodes']Next Steps
- Bootstrap & Parametric Curves -- Iterative bootstrap and parametric curve models
- Bonds -- Bond analytics and spreads
MarketContext Serialization
For serializing and restoring a complete market environment (curves, fixings, FX rates, calendars), see the Market Context guide.