Scenario Planning
Scenario planning is a structured methodology for exploring multiple plausible futures rather than predicting a single one. Developed at Royal Dutch Shell in the 1970s and refined by the Global Business Network (GBN), it helps organizations prepare for uncertainty by building detailed narratives of how the future might unfold. Unlike forecasting, which asks "What will happen?", scenario planning asks "What could happen, and how would we respond?" ## Key Points - Structural breaks occur (pandemics, financial crises, technological disruptions) - Multiple interacting uncertainties create unpredictable combinations - Human decisions and responses change the trajectory - Black swan events invalidate historical patterns - "What will the future look like?" (too vague) - "Will AI replace jobs?" (too narrow, binary) - "How should our company position itself in the healthcare market over the next 10 years?" - "What workforce strategy should we adopt given potential AI disruption by 2030?" - "How might the energy transition reshape our industry's competitive landscape by 2035?" - Specific enough to guide research - Broad enough to allow diverse scenarios - Relevant to actual strategic decisions
skilldb get prediction-skills/scenario-planningFull skill: 545 linesScenario Planning
Overview
Scenario planning is a structured methodology for exploring multiple plausible futures rather than predicting a single one. Developed at Royal Dutch Shell in the 1970s and refined by the Global Business Network (GBN), it helps organizations prepare for uncertainty by building detailed narratives of how the future might unfold. Unlike forecasting, which asks "What will happen?", scenario planning asks "What could happen, and how would we respond?"
The Core Philosophy
Why Not Just Forecast?
Traditional forecasting extrapolates from the past and assumes continuity. It fails spectacularly when:
- Structural breaks occur (pandemics, financial crises, technological disruptions)
- Multiple interacting uncertainties create unpredictable combinations
- Human decisions and responses change the trajectory
- Black swan events invalidate historical patterns
Scenario planning embraces uncertainty as irreducible and builds strategic flexibility instead of point predictions.
The Shell Story
In the early 1970s, Shell's scenario planners (led by Pierre Wack) developed scenarios that included an oil price shock. While other oil companies were caught off guard by the 1973 OPEC embargo, Shell had already stress-tested their strategies against this possibility. Shell rose from the weakest of the "Seven Sisters" to one of the two strongest within a decade.
The GBN/Shell Method
Step 1: Define the Focal Question
The scenario planning exercise must center on a specific strategic question:
Bad focal questions:
- "What will the future look like?" (too vague)
- "Will AI replace jobs?" (too narrow, binary)
Good focal questions:
- "How should our company position itself in the healthcare market over the next 10 years?"
- "What workforce strategy should we adopt given potential AI disruption by 2030?"
- "How might the energy transition reshape our industry's competitive landscape by 2035?"
The focal question should be:
- Specific enough to guide research
- Broad enough to allow diverse scenarios
- Relevant to actual strategic decisions
- Time-bounded (5-20 year horizon typically)
Step 2: Identify Driving Forces
Map the forces that will shape the answer to your focal question:
class DrivingForce:
"""A force that shapes the future relevant to the focal question."""
def __init__(self, name: str, category: str, description: str):
self.name = name
self.category = category # STEEP: Social, Tech, Economic, Environmental, Political
self.description = description
self.impact = 0 # 1-5 scale
self.uncertainty = 0 # 1-5 scale
def __repr__(self):
return f"{self.name} (Impact: {self.impact}, Uncertainty: {self.uncertainty})"
def identify_driving_forces(focal_question: str) -> list:
"""Systematic identification of driving forces using STEEP framework."""
categories = {
'Social': [
'Demographics', 'Consumer behavior', 'Cultural values',
'Education levels', 'Urbanization', 'Health trends',
'Inequality', 'Migration patterns'
],
'Technological': [
'AI/ML capabilities', 'Energy technology', 'Biotech',
'Computing power', 'Connectivity', 'Automation',
'Materials science', 'Space technology'
],
'Economic': [
'Growth rates', 'Interest rates', 'Trade patterns',
'Currency dynamics', 'Labor markets', 'Commodity prices',
'Financial innovation', 'Debt levels'
],
'Environmental': [
'Climate change', 'Resource scarcity', 'Biodiversity',
'Pollution', 'Extreme weather', 'Energy transition',
'Water availability', 'Land use'
],
'Political': [
'Geopolitical alignment', 'Regulation', 'Trade policy',
'Political stability', 'International cooperation',
'Military dynamics', 'Governance models', 'Populism'
]
}
forces = []
for category, subcategories in categories.items():
for sub in subcategories:
force = DrivingForce(
name=sub,
category=category,
description=f"How {sub.lower()} affects {focal_question}"
)
forces.append(force)
return forces
Step 3: Rank by Impact and Uncertainty
Plot all driving forces on a 2x2 matrix:
High Uncertainty
|
| SCENARIO MONITOR
| DRIVERS (wild cards)
|
| PREDETERMINED LOW PRIORITY
| ELEMENTS
|__________________ High Impact
Low High
def prioritize_forces(forces: list) -> dict:
"""Separate forces into categories based on impact/uncertainty."""
predetermined = [] # High impact, low uncertainty (will happen)
scenario_drivers = [] # High impact, high uncertainty (define scenarios)
monitors = [] # Low impact, high uncertainty (watch these)
background = [] # Low impact, low uncertainty (ignore)
for force in forces:
if force.impact >= 4 and force.uncertainty >= 4:
scenario_drivers.append(force)
elif force.impact >= 4 and force.uncertainty < 4:
predetermined.append(force)
elif force.impact < 4 and force.uncertainty >= 4:
monitors.append(force)
else:
background.append(force)
return {
'scenario_drivers': scenario_drivers,
'predetermined': predetermined,
'monitors': monitors,
'background': background
}
Predetermined elements appear in ALL scenarios (e.g., aging demographics in developed nations). Scenario drivers are the axes that differentiate your scenarios.
Step 4: Select Scenario Axes
Choose the two most critical uncertainties as your scenario axes. This creates a 2x2 matrix with four distinct scenarios.
Example for "Future of Urban Transportation by 2035":
Axis 1: Autonomous vehicle technology
(Breakthrough <-----> Incremental progress)
Axis 2: Urban policy orientation
(Car-centric <-----> Transit/density-centric)
Transit-Centric Policy
|
"Green | "Autonomous
Transit | Transit Hub"
City" |
|
————————————+————————————————
|
"Car | "Robot
Status | Car
Quo" | Paradise"
|
Car-Centric Policy
Incremental AV Breakthrough AV
Step 5: Build Scenario Narratives
Each quadrant becomes a detailed narrative — a story of how the world arrives at that state:
class Scenario:
"""A detailed scenario narrative."""
def __init__(self, name: str, tagline: str):
self.name = name
self.tagline = tagline # One-line summary
self.narrative = "" # Full story
self.key_events = [] # Timeline of events
self.implications = {} # Implications by stakeholder
self.early_indicators = [] # Signs this scenario is unfolding
self.strategic_responses = [] # What to do if this happens
def add_event(self, year: int, event: str, probability_driver: str):
self.key_events.append({
'year': year,
'event': event,
'driver': probability_driver
})
def add_implication(self, stakeholder: str, impact: str, severity: int):
if stakeholder not in self.implications:
self.implications[stakeholder] = []
self.implications[stakeholder].append({
'impact': impact,
'severity': severity # 1-5
})
def build_scenario_set(axes: tuple, focal_question: str) -> list:
"""Build four scenarios from two axes."""
axis1_name, axis1_poles = axes[0]
axis2_name, axis2_poles = axes[1]
scenarios = []
quadrants = [
(axis1_poles[0], axis2_poles[0]),
(axis1_poles[0], axis2_poles[1]),
(axis1_poles[1], axis2_poles[0]),
(axis1_poles[1], axis2_poles[1])
]
for pole1, pole2 in quadrants:
scenario = Scenario(
name=f"{pole1} + {pole2}",
tagline=f"A world where {pole1.lower()} meets {pole2.lower()}"
)
scenarios.append(scenario)
return scenarios
Step 6: Identify Early Indicators
For each scenario, define observable signals that would indicate it is beginning to unfold:
class EarlyIndicator:
"""An observable signal that a scenario is materializing."""
def __init__(self, description: str, data_source: str,
threshold: str, scenario: str):
self.description = description
self.data_source = data_source
self.threshold = threshold
self.scenario = scenario
self.current_status = "not_triggered"
def check(self, current_data: dict) -> bool:
"""Check if this indicator has been triggered."""
pass # Implementation depends on data source
def create_indicator_dashboard(scenarios: list) -> dict:
"""Build a monitoring dashboard for all scenario indicators."""
dashboard = {}
for scenario in scenarios:
dashboard[scenario.name] = {
'indicators': scenario.early_indicators,
'triggered_count': 0,
'total_count': len(scenario.early_indicators),
'probability_estimate': 0.25 # Start equal
}
return dashboard
The Cone of Plausibility
Visualizing the Future Space
The cone of plausibility expands from the present into the future, representing the widening range of possible outcomes:
Present Future
| /
| / Possible (could happen)
| /
| / Plausible (could happen given trends)
| /
| / Probable (likely to happen)
| /
| / Projected (baseline continuation)
| /
| /
| /
| /
| /
| /
| /
|/
Now 5 years 10 years 20 years
class ConeOfPlausibility:
"""Model the cone of plausibility for scenario planning."""
def __init__(self, base_year: int, horizon_years: int):
self.base_year = base_year
self.horizon = horizon_years
self.layers = {
'projected': {'width_factor': 0.1, 'confidence': 0.8},
'probable': {'width_factor': 0.3, 'confidence': 0.6},
'plausible': {'width_factor': 0.6, 'confidence': 0.3},
'possible': {'width_factor': 1.0, 'confidence': 0.1}
}
def get_range(self, variable: str, base_value: float,
year: int, layer: str = 'plausible') -> tuple:
"""Get the range of a variable at a future year."""
years_out = year - self.base_year
factor = self.layers[layer]['width_factor']
spread = base_value * factor * (years_out / self.horizon) ** 0.5
return (base_value - spread, base_value + spread)
def classify_scenario(self, scenario_outcomes: dict,
base_values: dict) -> str:
"""Classify a scenario as projected/probable/plausible/possible."""
for layer in ['projected', 'probable', 'plausible', 'possible']:
all_in_range = True
for var, value in scenario_outcomes.items():
low, high = self.get_range(
var, base_values[var],
self.base_year + self.horizon, layer
)
if not (low <= value <= high):
all_in_range = False
break
if all_in_range:
return layer
return 'impossible'
Wildcard Events
Identifying and Incorporating Wildcards
Wildcards are low-probability, high-impact events that can disrupt any scenario:
class WildcardEvent:
"""A low-probability, high-impact disruptive event."""
def __init__(self, name: str, probability: float,
impact_magnitude: int, category: str):
self.name = name
self.probability = probability # Annual probability
self.impact_magnitude = impact_magnitude # 1-10
self.category = category
self.affected_scenarios = [] # Which scenarios it disrupts
self.cascade_effects = [] # Secondary effects
@property
def expected_impact(self) -> float:
return self.probability * self.impact_magnitude
WILDCARD_CATALOG = [
WildcardEvent("Major pandemic", 0.02, 9, "health"),
WildcardEvent("Large asteroid impact", 0.0001, 10, "natural"),
WildcardEvent("Global financial system collapse", 0.01, 8, "economic"),
WildcardEvent("Breakthrough in fusion energy", 0.03, 8, "technology"),
WildcardEvent("Superintelligent AI emergence", 0.01, 10, "technology"),
WildcardEvent("Major volcanic eruption (VEI 7+)", 0.005, 9, "natural"),
WildcardEvent("Global cyberattack on infrastructure", 0.03, 7, "security"),
WildcardEvent("Collapse of major nation-state", 0.01, 7, "political"),
WildcardEvent("Discovery of extraterrestrial life", 0.005, 6, "science"),
WildcardEvent("Major climate tipping point crossed", 0.05, 8, "environment"),
]
Stress-Testing Against Wildcards
def stress_test_strategy(strategy: dict, scenarios: list,
wildcards: list) -> dict:
"""Test a strategy's resilience across scenarios and wildcards."""
results = {
'scenario_performance': {},
'wildcard_vulnerability': {},
'overall_robustness': 0.0
}
for scenario in scenarios:
performance = evaluate_strategy_in_scenario(strategy, scenario)
results['scenario_performance'][scenario.name] = performance
for wildcard in wildcards:
for scenario in scenarios:
vulnerability = evaluate_wildcard_impact(
strategy, scenario, wildcard
)
key = f"{scenario.name} + {wildcard.name}"
results['wildcard_vulnerability'][key] = vulnerability
# Overall robustness = worst-case performance
all_scores = list(results['scenario_performance'].values())
results['overall_robustness'] = min(all_scores) if all_scores else 0
return results
def evaluate_strategy_in_scenario(strategy: dict, scenario) -> float:
"""Score a strategy's performance in a given scenario (0-1)."""
# In practice, this involves detailed modeling
return 0.5 # Placeholder
def evaluate_wildcard_impact(strategy: dict, scenario, wildcard) -> float:
"""Assess how a wildcard affects strategy performance in a scenario."""
base = evaluate_strategy_in_scenario(strategy, scenario)
# Wildcards degrade performance by their impact magnitude
degradation = wildcard.impact_magnitude / 10.0
return max(0, base - degradation * 0.5)
Practical Scenario Planning Workshop
Workshop Agenda (2-Day Format)
DAY 1: EXPLORATION
09:00 - 10:00 Focal question definition and alignment
10:00 - 12:00 Driving forces brainstorm (STEEP framework)
- Individual brainstorm (15 min)
- Small group clustering (45 min)
- Full group prioritization (60 min)
12:00 - 13:00 Lunch
13:00 - 15:00 Impact/Uncertainty ranking
- Dot voting on impact (30 min)
- Dot voting on uncertainty (30 min)
- Discussion and calibration (60 min)
15:00 - 17:00 Axis selection and scenario naming
- Propose candidate axes (30 min)
- Test combinations (30 min)
- Select final 2x2 and name scenarios (60 min)
DAY 2: CONSTRUCTION
09:00 - 12:00 Scenario narrative development (4 breakout groups)
- Each group develops one scenario
- Timeline of key events
- Day-in-the-life vignettes
- Key data points and indicators
12:00 - 13:00 Lunch
13:00 - 14:30 Scenario presentations and cross-pollination
14:30 - 16:00 Strategic implications
- What strategies work in all scenarios?
- What are scenario-specific strategies?
- What are the no-regret moves?
16:00 - 17:00 Early indicator identification and action planning
Facilitation Best Practices
- Suspend judgment: The goal is plausibility, not probability
- Name scenarios memorably: "Green Sprint" is better than "Scenario B"
- Avoid "good" and "bad" scenarios: Each should have both opportunities and threats
- Include diverse perspectives: Invite outsiders, young employees, contrarians
- Make it vivid: Use newspaper headlines, personal stories, data visualizations
- Connect to decisions: Every scenario should lead to "so what should we do?"
- Revisit regularly: Update scenarios annually or when major events occur
Scenario-Strategy Integration
The Wind-Tunneling Approach
Test each strategic option against all scenarios:
def wind_tunnel(strategies: list, scenarios: list) -> dict:
"""Wind-tunnel strategies against scenarios."""
matrix = {}
for strategy in strategies:
matrix[strategy['name']] = {}
for scenario in scenarios:
score = evaluate_strategy_in_scenario(strategy, scenario)
matrix[strategy['name']][scenario.name] = score
# Identify robust strategies (perform well across all scenarios)
robust = {}
for strategy_name, scores in matrix.items():
min_score = min(scores.values())
max_score = max(scores.values())
avg_score = sum(scores.values()) / len(scores)
robust[strategy_name] = {
'min': min_score,
'max': max_score,
'avg': avg_score,
'range': max_score - min_score,
'robustness': min_score # Maximin criterion
}
return {
'matrix': matrix,
'robustness_ranking': sorted(
robust.items(), key=lambda x: -x[1]['robustness']
)
}
No-Regret Moves
Identify actions that are beneficial across ALL scenarios:
No-regret moves (good in every scenario):
- Build organizational agility
- Invest in talent development
- Diversify supplier base
- Strengthen digital capabilities
Hedging moves (insurance against specific scenarios):
- Maintain option on alternative technology
- Build relationships in emerging markets
- Develop contingency supply chains
Big bets (high payoff in one scenario, cost in others):
- Go all-in on one technology platform
- Major acquisition in a specific market
- Complete business model pivot
Key Takeaways
- Scenario planning is not about predicting the future; it is about preparing for multiple plausible futures
- The value is in the process (expanding mental models) as much as the output (scenario documents)
- Two axes creating four scenarios is the sweet spot: enough variety, manageable complexity
- Predetermined elements (high impact, low uncertainty) appear in all scenarios and ground them in reality
- Early indicators convert scenarios from static documents into active monitoring systems
- Wind-tunneling strategies against scenarios reveals robust vs. fragile strategic options
- No-regret moves are the immediate action items; hedging moves and big bets require scenario monitoring
- Wildcard events should stress-test even the most carefully constructed scenarios
Install this skill directly: skilldb add prediction-skills