Scenarios API¶
API reference for scenario expansion, shock operations, and stress testing.
Core Functions¶
with_scenarios¶
batch_scenarios¶
describe_scenarios¶
Generate human-readable descriptions of scenario configurations.
Creates audit-trail-ready documentation of what shocks are applied in each scenario. Useful for governance, compliance, and model documentation requirements.
When to use
- Generating audit trails for regulatory compliance
- Documenting scenario configurations in model reports
- Creating change logs for assumption modifications
- Building scenario comparison reports
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scenarios
|
dict[str, list[Shock]]
|
Mapping of scenario ID to list of shocks |
required |
output_format
|
Literal['text', 'markdown', 'dict']
|
Output format - "markdown" (default), "text", or "dict" |
'markdown'
|
Returns:
| Type | Description |
|---|---|
str | dict[str, list[str]]
|
Formatted description string, or dict for programmatic access |
Examples:¶
Generate markdown documentation:
```python no_output_check from gaspatchio_core.scenarios import describe_scenarios from gaspatchio_core.scenarios.shocks import MultiplicativeShock
scenarios = { "BASE": [], "STRESSED": [MultiplicativeShock(factor=1.2, table="mortality")], }
print(describe_scenarios(scenarios))
**Get as dictionary for programmatic access:**
```python no_output_check
result = describe_scenarios(scenarios, output_format="dict")
for scenario_id, shocks in result.items():
print(f"{scenario_id}: {len(shocks)} shocks")
sensitivity_analysis¶
Config Parsing¶
parse_shock_config¶
parse_scenario_config¶
Basic Shock Classes¶
MultiplicativeShock¶
Bases: Shock
A shock that multiplies values by a factor.
Used for scenarios like "increase mortality by 20%" (factor=1.2) or "decrease lapse by 10%" (factor=0.9).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factor
|
float
|
The multiplicative factor to apply |
required |
table
|
str | None
|
Optional table name this shock targets |
None
|
column
|
str | None
|
Optional column name this shock targets |
None
|
When to use
- Stress testing with percentage changes
- Sensitivity analysis on rates
- Regulatory capital scenarios (e.g., SCR shocks)
Examples:¶
20% increase in mortality:
```python no_output_check from gaspatchio_core.scenarios.shocks import MultiplicativeShock
shock = MultiplicativeShock(factor=1.2, table="mortality")
**10% decrease in lapse rates:**
```python no_output_check
shock = MultiplicativeShock(factor=0.9, table="lapse")
describe() -> str
¶
Return description of this shock.
AdditiveShock¶
Bases: Shock
A shock that adds a constant delta to values.
Used for scenarios like "increase discount rate by 50bps" (delta=0.005) or "decrease expense loading by 1%" (delta=-0.01).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
delta
|
float
|
The additive constant to apply |
required |
table
|
str | None
|
Optional table name this shock targets |
None
|
column
|
str | None
|
Optional column name this shock targets |
None
|
When to use
- Interest rate shocks (parallel shifts)
- Expense loading adjustments
- Basis point changes to rates
Examples:¶
Add 50bps to discount rates:
```python no_output_check from gaspatchio_core.scenarios.shocks import AdditiveShock
shock = AdditiveShock(delta=0.005, table="discount_rates")
**Subtract 1% from expense loading:**
```python no_output_check
shock = AdditiveShock(delta=-0.01, table="expenses")
describe() -> str
¶
Return description of this shock.
OverrideShock¶
Bases: Shock
A shock that replaces all values with a constant.
Used for scenarios like "set lapse to zero" (value=0.0) or "assume 100% mortality" (value=1.0).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
Any
|
The constant value to set |
required |
table
|
str | None
|
Optional table name this shock targets |
None
|
column
|
str | None
|
Optional column name this shock targets |
None
|
When to use
- Extreme stress scenarios
- Disabling a decrement entirely
- Testing boundary conditions
Examples:¶
Set lapse rates to zero:
```python no_output_check from gaspatchio_core.scenarios.shocks import OverrideShock
shock = OverrideShock(value=0.0, table="lapse")
**Override discount rate to flat 5%:**
```python no_output_check
shock = OverrideShock(value=0.05, table="discount_rates")
describe() -> str
¶
Return description of this shock.
Value Constraint Shocks¶
ClipShock¶
Bases: Shock
A shock that clips (caps/floors) values to a range.
Used for scenarios like "lapse rate cannot exceed 100%" (max=1.0) or "mortality floor of 0.1%" (min=0.001). Can also combine both.
This is essential for regulatory scenarios like Solvency II SCR lapse up, where shocked values must be capped at actuarial limits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_value
|
float | None
|
Optional floor value (values below are set to this) |
None
|
max_value
|
float | None
|
Optional ceiling value (values above are set to this) |
None
|
table
|
str | None
|
Optional table name this shock targets |
None
|
column
|
str | None
|
Optional column name this shock targets |
None
|
When to use
- Post-shock value constraints (e.g., lapse ≤ 100%)
- Regulatory scenarios with actuarial limits
- Preventing unrealistic shocked values
- Combining with other shocks in a pipeline
Examples:¶
Cap lapse rates at 100%:
```python no_output_check from gaspatchio_core.scenarios.shocks import ClipShock
shock = ClipShock(max_value=1.0, table="lapse")
**Floor mortality at 0.1%:**
```python no_output_check
shock = ClipShock(min_value=0.001, table="mortality")
Clip to a range:
python no_output_check
shock = ClipShock(min_value=0.0, max_value=1.0, table="rates")
describe() -> str
¶
Return description of this shock.
Composable Shocks¶
PipelineShock¶
Bases: Shock
A shock that chains multiple operations in sequence.
Used for complex scenarios like "multiply by 1.5 then cap at 100%" which requires composing multiple shock operations.
The operations are applied left-to-right: the output of each shock becomes the input to the next.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shocks
|
tuple[Shock, ...]
|
Sequence of shocks to apply in order |
tuple()
|
table
|
str | None
|
Optional table name this shock targets |
None
|
column
|
str | None
|
Optional column name this shock targets |
None
|
When to use
- Solvency II lapse up: multiply then cap
- Complex stress scenarios with multiple transformations
- Building reusable shock combinations
Examples:¶
Solvency II lapse up (multiply by 1.5, cap at 100%):
```python no_output_check from gaspatchio_core.scenarios.shocks import ( PipelineShock, MultiplicativeShock, ClipShock, )
shock = PipelineShock( shocks=[ MultiplicativeShock(factor=1.5), ClipShock(max_value=1.0), ], table="lapse", ) ```
Lapse down with floor (multiply by 0.5, floor at original - 0.2):
This would need a custom approach for relative floors.
describe() -> str
¶
Return description of this shock.
MaxShock¶
Bases: Shock
A shock that takes the maximum of two shock expressions.
Used for scenarios like Solvency II lapse down: "max(lapse × 0.5, lapse - 0.2)" where the result is the larger of two transformations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shock_a
|
Shock
|
First shock option |
required |
shock_b
|
Shock
|
Second shock option |
required |
table
|
str | None
|
Optional table name this shock targets |
None
|
column
|
str | None
|
Optional column name this shock targets |
None
|
When to use
- Solvency II lapse down: max(×0.5, -0.2)
- Taking the less severe of two shocks
- Complex regulatory scenarios
Examples:¶
Solvency II lapse down:
```python no_output_check from gaspatchio_core.scenarios.shocks import ( MaxShock, MultiplicativeShock, AdditiveShock, )
shock = MaxShock( shock_a=MultiplicativeShock(factor=0.5), shock_b=AdditiveShock(delta=-0.2), table="lapse", )
Result: max(lapse × 0.5, lapse - 0.2)¶
```
describe() -> str
¶
Return description of this shock.
MinShock¶
Bases: Shock
A shock that takes the minimum of two shock expressions.
Used for scenarios where the result should be the smaller of two transformations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shock_a
|
Shock
|
First shock option |
required |
shock_b
|
Shock
|
Second shock option |
required |
table
|
str | None
|
Optional table name this shock targets |
None
|
column
|
str | None
|
Optional column name this shock targets |
None
|
When to use
- Taking the more severe of two shocks
- Cap scenarios (similar to ClipShock but based on transformations)
- Complex regulatory scenarios
Examples:¶
Take the lower of two mortality assumptions:
```python no_output_check from gaspatchio_core.scenarios.shocks import ( MinShock, MultiplicativeShock, OverrideShock, )
shock = MinShock( shock_a=MultiplicativeShock(factor=1.5), shock_b=OverrideShock(value=0.1), # Cap at 10% mortality table="mortality", ) ```
describe() -> str
¶
Return description of this shock.
Filter Shocks¶
FilteredShock¶
Bases: Shock
A shock that applies only to rows matching a filter condition (WHERE clause).
Used for dimension-filtered shocks like "increase early-duration lapse by 25%" where only rows matching the filter are modified.
This implements GSP-65: Dimension-filtered shocks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shock
|
Shock
|
The shock to apply to matching rows |
required |
where
|
FilterCondition
|
Filter condition dictionary |
required |
table
|
str | None
|
Optional table name this shock targets |
None
|
column
|
str | None
|
Optional column name this shock targets |
None
|
When to use
- Apply shocks to specific segments (e.g., early durations)
- Age-specific mortality adjustments
- Product-specific lapse stress
- Regulatory scenarios with conditional shocks
Examples:¶
Increase early-duration lapse by 25%:
```python no_output_check from gaspatchio_core.scenarios.shocks import FilteredShock, MultiplicativeShock
shock = FilteredShock( shock=MultiplicativeShock(factor=1.25), where={"duration": {"lte": 3}}, table="lapse", )
**Mortality shock for elderly lives:**
```python no_output_check
shock = FilteredShock(
shock=MultiplicativeShock(factor=1.15),
where={"attained_age": {"gte": 65}},
table="mortality",
)
Complex filter with multiple conditions:
python no_output_check
shock = FilteredShock(
shock=AdditiveShock(delta=0.02),
where={"sex": "F", "smoker_status": "S"},
table="mortality",
)
describe() -> str
¶
Return description of this shock.
TimeConditionalShock¶
Bases: Shock
A shock that applies only at specific projection times (WHEN clause).
Used for time-conditional shocks like "40% mass lapse at t=0 only" where the shock is applied based on projection period.
This implements GSP-74: Time-conditional shocks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shock
|
Shock
|
The shock to apply at matching times |
required |
when
|
FilterCondition
|
Time condition dictionary (uses 't' column by default) |
required |
table
|
str | None
|
Optional table name this shock targets |
None
|
column
|
str | None
|
Optional column name this shock targets |
None
|
time_column
|
str
|
Column name for time (default: "t") |
't'
|
When to use
- Mass lapse at policy inception (t=0)
- First-year expense shocks
- Time-limited stress scenarios
- Shock only during specific periods
Examples:¶
Mass lapse at t=0:
```python no_output_check from gaspatchio_core.scenarios.shocks import TimeConditionalShock, AdditiveShock
shock = TimeConditionalShock( shock=AdditiveShock(delta=0.40), # Add 40% lapse when={"t": {"eq": 0}}, table="lapse", )
**Expense shock for first 5 years:**
```python no_output_check
shock = TimeConditionalShock(
shock=MultiplicativeShock(factor=1.10),
when={"t": {"lte": 5}},
table="expenses",
)
describe() -> str
¶
Return description of this shock.
Parameter Shocks¶
ParameterShock¶
A shock specification for scalar model parameters (not table values).
Used for scenarios like "increase expense inflation by 1%" where the target is a scalar model input rather than an assumption table.
Unlike table shocks, parameter shocks store the transformation specification and are applied at model setup time by the model code.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
param
|
str
|
Name of the parameter to shock |
required |
operation
|
str
|
Type of operation ("multiply", "add", or "set") |
required |
value
|
float
|
Value for the operation (factor, delta, or constant) |
required |
When to use
- Shocking scalar model inputs (expense inflation, discount rate spread)
- Parameters that aren't stored in assumption tables
- Model-level sensitivity analysis
Not a Shock subclass
ParameterShock is NOT a Shock subclass because it doesn't operate on Polars expressions. It stores the shock specification for the model code to apply.
Examples:¶
Add 1% to expense inflation:
```python no_output_check from gaspatchio_core.scenarios.shocks import ParameterShock
shock = ParameterShock(param="expense_inflation", operation="add", value=0.01)
Apply in model code:¶
base_inflation = 0.02 shocked_inflation = shock.apply(base_inflation) # 0.03
**Multiply discount spread:**
```python no_output_check
shock = ParameterShock(param="discount_spread", operation="multiply", value=1.5)
apply(base_value: float) -> float
¶
Apply this shock to a base parameter value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_value
|
float
|
The original parameter value |
required |
Returns:
| Type | Description |
|---|---|
float
|
The shocked parameter value |
describe() -> str
¶
Return a human-readable description of this shock.
Related Table Methods¶
The following methods on the Table class work with scenarios:
Table.from_scenario_files()- Load separate assumption files per scenarioTable.from_scenario_template()- Load scenario files using a path templateTable.from_shocks()- Create multiple shocked tables from shock specificationsTable.with_shock()- Apply a single shock to create a modified table
See the Actuarial Frame API for details on these methods.
See Also¶
- Shock Operations - Conceptual guide with progressive examples
- What-If Analysis - Natural language to config translation
- Scenarios Overview - High-level scenario concepts