Input schema (JSON)
{
"type": "object",
"$defs": {
"CPPInput": {
"type": "object",
"title": "CPPInput",
"properties": {
"enabled": {
"type": "boolean",
"title": "Enabled",
"description": "Whether this government benefit is in the plan. Decide this for each person: off means the plan counts none of this income."
},
"start_age": {
"type": "integer",
"title": "Start Age",
"description": "Age the benefit starts, a whole number from 60 to 70."
},
"expected_fraction": {
"type": "number",
"title": "Expected Fraction",
"maximum": 1,
"minimum": 0,
"description": "CPP at 65 as a FRACTION 0-1 of the maximum, $1,507.65 a month (0.6 means 60%, never 60). From a monthly amount at 65: that amount divided by 1507.65."
}
},
"additionalProperties": false
},
"OASInput": {
"type": "object",
"title": "OASInput",
"properties": {
"enabled": {
"type": "boolean",
"title": "Enabled",
"description": "Whether this government benefit is in the plan. Decide this for each person: off means the plan counts none of this income."
},
"start_age": {
"type": "integer",
"title": "Start Age",
"description": "Age the benefit starts, a whole number from 65 to 70. Someone with under 10 years in Canada after 18 at 65 first qualifies later, once their residence reaches that, and starts from then."
},
"arrival_age": {
"type": "integer",
"title": "Arrival Age",
"maximum": 100,
"minimum": 0
}
},
"additionalProperties": false
},
"TaxInput": {
"type": "object",
"title": "TaxInput",
"required": [
"enabled",
"province"
],
"properties": {
"enabled": {
"type": "boolean",
"title": "Enabled",
"description": "Whether income taxes are modelled. Decide this deliberately: off shows pre-tax figures, which overstate what a retiree can spend."
},
"province": {
"type": "string",
"title": "Province"
},
"filing_status": {
"enum": [
"",
"single",
"married_filing_jointly",
"head_of_household"
],
"type": "string",
"title": "Filing Status",
"description": "US only, the household's federal and state filing status: single or head_of_household for one person, married_filing_jointly for a couple (the plan refuses any other pairing). Left out, it follows the household: married_filing_jointly with a partner in the plan, else single. Empty for Canada, which taxes each person on their own."
}
},
"additionalProperties": false
},
"AccountItem": {
"type": "object",
"title": "AccountItem",
"required": [
"type",
"balance",
"owner"
],
"properties": {
"type": {
"enum": [
"Non-Registered",
"RRSP",
"TFSA",
"BROKERAGE",
"TRADITIONAL_401K",
"TRADITIONAL_IRA",
"ROTH_401K",
"ROTH_IRA"
],
"type": "string",
"title": "Type"
},
"owner": {
"enum": [
"person1",
"person2"
],
"type": "string",
"title": "Owner"
},
"balance": {
"type": "number",
"title": "Balance"
}
},
"additionalProperties": false
},
"PensionItem": {
"type": "object",
"title": "PensionItem",
"required": [
"name",
"amount",
"period",
"start_age",
"end_age",
"indexed"
],
"properties": {
"name": {
"type": "string",
"title": "Name"
},
"amount": {
"type": "number",
"title": "Amount",
"minimum": 0,
"description": "The pension in today's dollars per period (a month or a year, as period says). indexed true grows it with inflation from today; false keeps this dollar amount."
},
"period": {
"enum": [
"monthly",
"yearly"
],
"type": "string",
"title": "Period"
},
"end_age": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "End Age"
},
"indexed": {
"type": "boolean",
"title": "Indexed"
},
"start_age": {
"type": "number",
"title": "Start Age"
}
},
"additionalProperties": false
},
"Person1Input": {
"type": "object",
"title": "Person1Input",
"required": [
"birth_year"
],
"properties": {
"sex": {
"enum": [
"combined",
"male",
"female"
],
"type": "string",
"title": "Sex"
},
"name": {
"type": "string",
"title": "Name"
},
"n_years": {
"type": "integer",
"title": "N Years",
"maximum": 100,
"minimum": 1,
"description": "Years the plan runs from the current year. To plan to an age: that age minus the person's age this year."
},
"benefits": {
"$ref": "#/$defs/BenefitsInput"
},
"birth_year": {
"type": "integer",
"title": "Birth Year",
"description": "Calendar year the person was born. From an age: the current year minus that age."
},
"initial_acb": {
"type": "number",
"title": "Initial Acb"
},
"horizon_mode": {
"enum": [
"fixed",
"life_expectancy"
],
"type": "string",
"title": "Horizon Mode"
},
"annual_income": {
"type": "number",
"title": "Annual Income",
"description": "Employment income after payroll contributions (CPP/CPP2/EI in Canada, Social Security and Medicare in the US), before income tax, in today's dollars a YEAR, earned until retirement_year; not the gross salary. It stays flat unless income growth is on. 0 for someone already retired."
},
"custom_pensions": {
"type": "array",
"items": {
"$ref": "#/$defs/PensionItem"
},
"title": "Custom Pensions",
"maxItems": 20
},
"retirement_year": {
"type": "integer",
"title": "Retirement Year",
"description": "Calendar year the person stops working; the current year or earlier means already retired. From a retirement age: birth_year plus that age."
},
"income_growth_rate": {
"type": "number",
"title": "Income Growth Rate",
"maximum": 20,
"minimum": 0,
"description": "Yearly salary growth for income_growth_type fixed_rate, in WHOLE percent: 3 means 3% a year, not 0.03."
},
"income_growth_type": {
"type": "string",
"title": "Income Growth Type"
},
"income_growth_enabled": {
"type": "boolean",
"title": "Income Growth Enabled"
}
},
"additionalProperties": false
},
"Person2Input": {
"type": "object",
"title": "Person2Input",
"properties": {
"sex": {
"enum": [
"combined",
"male",
"female"
],
"type": "string",
"title": "Sex"
},
"name": {
"type": "string",
"title": "Name"
},
"enabled": {
"type": "boolean",
"title": "Enabled"
},
"n_years": {
"type": "integer",
"title": "N Years",
"maximum": 100,
"minimum": 1,
"description": "Years the plan runs from the current year. To plan to an age: that age minus the person's age this year."
},
"benefits": {
"$ref": "#/$defs/BenefitsInput"
},
"birth_year": {
"type": "integer",
"title": "Birth Year",
"description": "Calendar year the person was born. From an age: the current year minus that age."
},
"initial_acb": {
"type": "number",
"title": "Initial Acb"
},
"horizon_mode": {
"enum": [
"fixed",
"life_expectancy"
],
"type": "string",
"title": "Horizon Mode"
},
"annual_income": {
"type": "number",
"title": "Annual Income",
"description": "Employment income after payroll contributions (CPP/CPP2/EI in Canada, Social Security and Medicare in the US), before income tax, in today's dollars a YEAR, earned until retirement_year; not the gross salary. It stays flat unless income growth is on. 0 for someone already retired."
},
"custom_pensions": {
"type": "array",
"items": {
"$ref": "#/$defs/PensionItem"
},
"title": "Custom Pensions",
"maxItems": 20
},
"retirement_year": {
"type": "integer",
"title": "Retirement Year",
"description": "Calendar year the person stops working; the current year or earlier means already retired. From a retirement age: birth_year plus that age."
},
"income_growth_rate": {
"type": "number",
"title": "Income Growth Rate",
"maximum": 20,
"minimum": 0,
"description": "Yearly salary growth for income_growth_type fixed_rate, in WHOLE percent: 3 means 3% a year, not 0.03."
},
"income_growth_type": {
"type": "string",
"title": "Income Growth Type"
},
"income_growth_enabled": {
"type": "boolean",
"title": "Income Growth Enabled"
}
},
"additionalProperties": false
},
"BenefitsInput": {
"type": "object",
"title": "BenefitsInput",
"properties": {
"cpp": {
"$ref": "#/$defs/CPPInput"
},
"oas": {
"$ref": "#/$defs/OASInput"
},
"social_security": {
"$ref": "#/$defs/SocialSecurityInput"
}
},
"additionalProperties": false
},
"LifeEventItem": {
"type": "object",
"title": "LifeEventItem",
"required": [
"type",
"year",
"amount",
"name",
"owner"
],
"properties": {
"name": {
"type": "string",
"title": "Name"
},
"type": {
"type": "string",
"title": "Type",
"description": "lump_sum_income (money received, e.g. an inheritance or a home sale) or lump_sum_withdrawal (a one-off expense, e.g. a car or a roof)."
},
"year": {
"type": "integer",
"title": "Year"
},
"owner": {
"enum": [
"person1",
"person2"
],
"type": "string",
"title": "Owner",
"description": "Whose event it is: person1, or person2 when the partner is in the plan."
},
"amount": {
"type": "number",
"title": "Amount",
"description": "The one-off amount in dollars, zero or more, as of the event's year: not adjusted for inflation. type says whether it comes in or goes out."
}
},
"additionalProperties": false
},
"AllocationInput": {
"type": "object",
"title": "AllocationInput",
"properties": {
"cash": {
"type": "number",
"title": "Cash",
"maximum": 1,
"minimum": 0
},
"bonds": {
"type": "number",
"title": "Bonds",
"maximum": 1,
"minimum": 0
},
"domestic": {
"type": "number",
"title": "Domestic",
"maximum": 1,
"minimum": 0
},
"international": {
"type": "number",
"title": "International",
"maximum": 1,
"minimum": 0
}
},
"additionalProperties": false
},
"SocialSecurityInput": {
"type": "object",
"title": "SocialSecurityInput",
"properties": {
"enabled": {
"type": "boolean",
"title": "Enabled",
"description": "Whether this government benefit is in the plan. Decide this for each person: off means the plan counts none of this income."
},
"start_age": {
"type": "integer",
"title": "Start Age",
"description": "Age the benefit starts, a whole number from 62 to 70."
},
"benefit_at_fra": {
"type": "number",
"title": "Benefit At Fra",
"minimum": 0,
"description": "Estimated Social Security benefit at Full Retirement Age in dollars a MONTH (today's dollars), as on the SSA statement, e.g. 2500. Never the yearly amount: divide a yearly figure by 12."
}
},
"additionalProperties": false
}
},
"title": "RunPlanArguments",
"required": [
"resident_country",
"withdrawal_amount",
"tax",
"accounts",
"person1"
],
"properties": {
"tax": {
"$ref": "#/$defs/TaxInput"
},
"person1": {
"$ref": "#/$defs/Person1Input"
},
"person2": {
"$ref": "#/$defs/Person2Input"
},
"accounts": {
"type": "array",
"items": {
"$ref": "#/$defs/AccountItem"
},
"title": "Accounts",
"maxItems": 20,
"minItems": 1
},
"essential": {
"anyOf": [
{
"type": "number",
"minimum": 0
},
{
"type": "null"
}
],
"title": "Essential",
"description": "floor_ceiling and yale only: the yearly spending that never flexes, in today's dollars a YEAR, at most withdrawal_amount; the rest can be cut in bad years. Left out, it is the plan builder's default, the smaller of $35,000 and withdrawal_amount. Null is the only value for constant_dollar; under floor_ceiling or yale null makes the WHOLE spending the floor, so none of it flexes."
},
"floor_pct": {
"type": "number",
"title": "Floor Pct",
"maximum": 1,
"minimum": 0,
"description": "floor_ceiling only: the largest yearly cut in real spending, as a FRACTION 0-1 (0.025 means spending can fall at most 2.5% a year below inflation)."
},
"plan_name": {
"type": "string",
"title": "Plan Name",
"description": "A short name for this scenario as the person would recognise it, e.g. 'CPP at 70' or 'Retire at 60'. Name each option differently when comparing."
},
"allocation": {
"$ref": "#/$defs/AllocationInput"
},
"ceiling_pct": {
"type": "number",
"title": "Ceiling Pct",
"maximum": 1,
"minimum": 0,
"description": "floor_ceiling only: the largest yearly raise in real spending, as a FRACTION 0-1 (0.05 means spending can rise at most 5% a year above inflation)."
},
"life_events": {
"type": "array",
"items": {
"$ref": "#/$defs/LifeEventItem"
},
"title": "Life Events",
"maxItems": 20
},
"random_seed": {
"anyOf": [
{
"type": "integer",
"minimum": 0
},
{
"type": "null"
}
],
"title": "Random Seed",
"description": "Seed for the simulated market paths. A fresh plan fixes it, so runs and comparisons use the same market paths; null draws fresh paths on each new run (the same run_plan call again within 15 minutes returns the earlier run)."
},
"block_length": {
"type": "integer",
"title": "Block Length",
"maximum": 600,
"minimum": 1,
"description": "Length in MONTHS of each run of consecutive market history the simulation samples (120 means 10 years). Longer blocks keep more of history's long good and bad spells."
},
"yale_smoothing": {
"type": "number",
"title": "Yale Smoothing",
"maximum": 1,
"minimum": 0,
"description": "yale only: the weight, as a FRACTION 0-1, on last year's spending grown with inflation; the rest follows the portfolio's value. 1 behaves like constant_dollar, 0 like a fixed percentage of the portfolio."
},
"resident_country": {
"enum": [
"CAN",
"USA",
"INTL"
],
"type": "string",
"title": "Resident Country"
},
"withdrawal_amount": {
"type": "number",
"title": "Withdrawal Amount",
"description": "Annual spending in today's dollars, after tax, from all sources (benefits, pensions, other income, investment income and withdrawals); not the portfolio withdrawal. Under floor_ceiling and yale it is the first year's spending, which then moves with the portfolio."
},
"withdrawal_strategy": {
"enum": [
"constant_dollar",
"floor_ceiling",
"yale"
],
"type": "string",
"title": "Withdrawal Strategy"
}
},
"additionalProperties": false
}