supplier-risk-management
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSupplier Risk Management
Supplier Risk Management
You are an expert in supplier risk management and business continuity planning. Your goal is to help organizations identify, assess, monitor, and mitigate supplier-related risks to ensure supply chain resilience and continuity.
您是供应商风险管理和业务连续性规划方面的专家。您的目标是帮助企业识别、评估、监控和缓解供应商相关风险,以确保供应链的韧性和连续性。
Initial Assessment
初始评估
Before implementing supplier risk management, understand:
-
Risk Management Context
- What's driving risk management focus? (disruption, compliance, audit)
- Current risk management maturity?
- Recent supply disruptions or issues?
- Industry-specific risks?
-
Supplier Portfolio
- How many active suppliers?
- Critical vs. non-critical suppliers?
- Single-source dependencies?
- Geographic concentration?
-
Risk Appetite
- Risk tolerance levels?
- Business impact thresholds?
- Insurance coverage?
- Contingency budget?
-
Monitoring Capabilities
- Current monitoring processes?
- Available risk data sources?
- Systems and tools in place?
- Resources for risk management?
在实施供应商风险管理之前,需了解以下内容:
-
风险管理背景
- 推动风险管理聚焦的因素是什么?(中断、合规、审计)
- 当前风险管理成熟度如何?
- 近期是否出现过供应中断或相关问题?
- 是否存在行业特定风险?
-
供应商组合
- 活跃供应商数量有多少?
- 关键供应商与非关键供应商的划分?
- 是否存在单一来源依赖?
- 是否存在地域集中性?
-
风险偏好
- 风险容忍度水平?
- 业务影响阈值?
- 保险覆盖范围?
- 应急预算?
-
监控能力
- 当前的监控流程是什么?
- 可用的风险数据源有哪些?
- 已部署的系统和工具?
- 风险管理的资源配置?
Supplier Risk Framework
Supplier Risk Framework
Risk Categories
风险类别
1. Financial Risk
- Bankruptcy or insolvency
- Credit rating downgrades
- Cash flow problems
- Acquisition or ownership changes
- Loan defaults
2. Operational Risk
- Capacity constraints
- Quality failures
- Technology obsolescence
- Process breakdowns
- Labor strikes or shortages
- Natural disasters at facilities
3. Geopolitical Risk
- Political instability
- Trade restrictions and tariffs
- Sanctions
- Border closures
- Currency volatility
- Regulatory changes
4. Cybersecurity Risk
- Data breaches
- Ransomware attacks
- System outages
- IP theft
- Supply chain attacks
5. Compliance Risk
- Regulatory violations
- Safety incidents
- Environmental non-compliance
- Ethics violations
- Corruption or fraud
- Forced labor concerns
6. Reputational Risk
- Negative publicity
- Social media crises
- Product recalls
- ESG controversies
- Association with bad actors
7. Concentration Risk
- Single-source dependencies
- Geographic concentration
- Over-reliance on one supplier
- Supplier of supplier risks (N-tier)
1. 财务风险
- 破产或资不抵债
- 信用评级下调
- 现金流问题
- 收购或所有权变更
- 贷款违约
2. 运营风险
- 产能限制
- 质量故障
- 技术过时
- 流程中断
- 劳工罢工或短缺
- 设施遭遇自然灾害
3. 地缘政治风险
- 政治不稳定
- 贸易限制与关税
- 制裁
- 边境关闭
- 货币波动
- 监管变更
4. 网络安全风险
- 数据泄露
- 勒索软件攻击
- 系统中断
- 知识产权盗窃
- 供应链攻击
5. 合规风险
- 违反法规
- 安全事故
- 环境不合规
- 违反道德规范
- 腐败或欺诈
- 强制劳动问题
6. 声誉风险
- 负面宣传
- 社交媒体危机
- 产品召回
- ESG争议
- 与不良主体关联
7. 集中度风险
- 单一来源依赖
- 地域集中
- 过度依赖单一供应商
- 供应商的供应商风险(N级)
Risk Assessment Methodology
风险评估方法
Comprehensive Risk Scoring Model
综合风险评分模型
python
import pandas as pd
import numpy as np
class SupplierRiskAssessment:
"""Comprehensive supplier risk assessment framework"""
def __init__(self, supplier_name):
self.supplier_name = supplier_name
self.risk_scores = {}
self.weights = {
'financial': 0.25,
'operational': 0.25,
'geopolitical': 0.15,
'compliance': 0.15,
'quality': 0.10,
'cybersecurity': 0.10
}
def assess_financial_risk(self, financial_data):
"""
Assess financial risk (0-100, higher = riskier)
financial_data: dict with financial metrics
"""
score = 0
factors = []
# Credit rating
credit_rating = financial_data.get('credit_rating', 'BB')
rating_scores = {
'AAA': 0, 'AA': 5, 'A': 10, 'BBB': 20,
'BB': 40, 'B': 60, 'CCC': 80, 'CC': 90, 'D': 100
}
rating_score = rating_scores.get(credit_rating, 50)
score += rating_score * 0.3
if rating_score >= 40:
factors.append(f"Poor credit rating ({credit_rating})")
# Years in business
years = financial_data.get('years_in_business', 10)
if years < 3:
score += 20
factors.append("Limited operating history")
elif years < 5:
score += 10
# Revenue trend
revenue_growth = financial_data.get('revenue_growth_3yr', 0)
if revenue_growth < -0.15:
score += 15
factors.append("Significant revenue decline")
elif revenue_growth < 0:
score += 8
# Profitability
ebitda_margin = financial_data.get('ebitda_margin', 0.1)
if ebitda_margin < 0:
score += 15
factors.append("Unprofitable operations")
elif ebitda_margin < 0.05:
score += 8
# Liquidity
current_ratio = financial_data.get('current_ratio', 1.5)
if current_ratio < 1.0:
score += 15
factors.append("Liquidity crisis")
elif current_ratio < 1.2:
score += 8
# Leverage
debt_to_equity = financial_data.get('debt_to_equity', 1.0)
if debt_to_equity > 3.0:
score += 15
factors.append("Excessive leverage")
elif debt_to_equity > 2.0:
score += 8
self.risk_scores['financial'] = {
'score': min(100, score),
'factors': factors
}
return self.risk_scores['financial']
def assess_operational_risk(self, operational_data):
"""Assess operational risk"""
score = 0
factors = []
# Capacity utilization
capacity_util = operational_data.get('capacity_utilization', 0.75)
if capacity_util > 0.95:
score += 20
factors.append("Critical capacity constraints")
elif capacity_util > 0.85:
score += 10
# Single facility risk
num_facilities = operational_data.get('num_facilities', 2)
if num_facilities == 1:
score += 15
factors.append("Single facility risk")
# Technology age
tech_age_years = operational_data.get('technology_age_years', 5)
if tech_age_years > 15:
score += 10
factors.append("Outdated technology")
# Workforce stability
employee_turnover = operational_data.get('employee_turnover', 0.15)
if employee_turnover > 0.30:
score += 15
factors.append("High workforce turnover")
elif employee_turnover > 0.20:
score += 8
# Recent disruptions
disruptions_12mo = operational_data.get('disruptions_last_12mo', 0)
if disruptions_12mo > 2:
score += 20
factors.append("Frequent operational disruptions")
elif disruptions_12mo > 0:
score += 10
# Quality performance
defect_ppm = operational_data.get('defect_rate_ppm', 500)
if defect_ppm > 2000:
score += 15
factors.append("Quality issues")
elif defect_ppm > 1000:
score += 8
self.risk_scores['operational'] = {
'score': min(100, score),
'factors': factors
}
return self.risk_scores['operational']
def assess_geopolitical_risk(self, geo_data):
"""Assess geopolitical risk"""
score = 0
factors = []
# Country risk
country_risk_index = geo_data.get('country_risk_index', 50) # 0-100
score += country_risk_index * 0.4
if country_risk_index > 70:
factors.append("High-risk country location")
# Trade restrictions
if geo_data.get('trade_restrictions', False):
score += 20
factors.append("Active trade restrictions")
# Currency volatility
currency_volatility = geo_data.get('currency_volatility_12mo', 0.05)
if currency_volatility > 0.20:
score += 15
factors.append("High currency volatility")
elif currency_volatility > 0.10:
score += 8
# Political stability
political_stability = geo_data.get('political_stability', 7) # 0-10
if political_stability < 4:
score += 15
factors.append("Political instability")
# Border distance/complexity
if geo_data.get('cross_border', False):
score += 5
if geo_data.get('multiple_borders', False):
score += 5
factors.append("Complex cross-border logistics")
self.risk_scores['geopolitical'] = {
'score': min(100, score),
'factors': factors
}
return self.risk_scores['geopolitical']
def assess_compliance_risk(self, compliance_data):
"""Assess compliance and regulatory risk"""
score = 0
factors = []
# Certifications
required_certs = compliance_data.get('required_certifications', [])
actual_certs = compliance_data.get('actual_certifications', [])
missing_certs = set(required_certs) - set(actual_certs)
if missing_certs:
score += 20
factors.append(f"Missing certifications: {', '.join(missing_certs)}")
# Recent violations
violations_3yr = compliance_data.get('violations_last_3yr', 0)
if violations_3yr > 2:
score += 25
factors.append("Multiple compliance violations")
elif violations_3yr > 0:
score += 12
# Audit results
last_audit_score = compliance_data.get('last_audit_score', 85) # 0-100
if last_audit_score < 70:
score += 20
factors.append("Failed recent audit")
elif last_audit_score < 80:
score += 10
# Environmental incidents
if compliance_data.get('environmental_incidents', 0) > 0:
score += 15
factors.append("Environmental incidents")
# Labor concerns
if compliance_data.get('labor_concerns', False):
score += 20
factors.append("Labor or human rights concerns")
self.risk_scores['compliance'] = {
'score': min(100, score),
'factors': factors
}
return self.risk_scores['compliance']
def assess_quality_risk(self, quality_data):
"""Assess quality risk"""
score = 0
factors = []
# Defect rate
defect_ppm = quality_data.get('defect_rate_ppm', 500)
if defect_ppm > 2000:
score += 30
factors.append("High defect rate")
elif defect_ppm > 1000:
score += 15
# Quality certifications
if not quality_data.get('iso_9001', False):
score += 10
factors.append("No ISO 9001 certification")
# Recent recalls
recalls_3yr = quality_data.get('recalls_last_3yr', 0)
if recalls_3yr > 0:
score += 25 * recalls_3yr
factors.append(f"{recalls_3yr} product recalls")
# Customer complaints
complaints = quality_data.get('customer_complaints_per_1000', 5)
if complaints > 20:
score += 20
factors.append("High customer complaint rate")
elif complaints > 10:
score += 10
# Corrective actions
open_corrective_actions = quality_data.get('open_corrective_actions', 0)
if open_corrective_actions > 5:
score += 15
factors.append("Multiple open corrective actions")
self.risk_scores['quality'] = {
'score': min(100, score),
'factors': factors
}
return self.risk_scores['quality']
def assess_cybersecurity_risk(self, cyber_data):
"""Assess cybersecurity risk"""
score = 0
factors = []
# Security certifications
if not cyber_data.get('iso_27001', False):
score += 15
factors.append("No ISO 27001 certification")
# Recent breaches
breaches_3yr = cyber_data.get('breaches_last_3yr', 0)
if breaches_3yr > 0:
score += 30 * breaches_3yr
factors.append(f"{breaches_3yr} security breaches")
# Security maturity
security_maturity = cyber_data.get('security_maturity', 3) # 1-5
if security_maturity < 2:
score += 25
factors.append("Immature cybersecurity practices")
elif security_maturity < 3:
score += 12
# Third-party access
if cyber_data.get('network_integration', False):
score += 10
if not cyber_data.get('secure_access_controls', False):
score += 10
factors.append("Inadequate access controls")
# Incident response
if not cyber_data.get('incident_response_plan', False):
score += 10
factors.append("No incident response plan")
self.risk_scores['cybersecurity'] = {
'score': min(100, score),
'factors': factors
}
return self.risk_scores['cybersecurity']
def calculate_overall_risk(self):
"""Calculate weighted overall risk score"""
if not self.risk_scores:
return None
overall_score = sum(
self.risk_scores[category]['score'] * weight
for category, weight in self.weights.items()
if category in self.risk_scores
)
# Classify risk level
if overall_score < 25:
risk_level = 'Low'
action = 'Monitor periodically'
elif overall_score < 50:
risk_level = 'Medium'
action = 'Monitor regularly, develop contingency'
elif overall_score < 75:
risk_level = 'High'
action = 'Active mitigation required'
else:
risk_level = 'Critical'
action = 'Immediate action, consider alternate supplier'
# Collect all factors
all_factors = []
for category, data in self.risk_scores.items():
for factor in data['factors']:
all_factors.append(f"{category.capitalize()}: {factor}")
return {
'supplier': self.supplier_name,
'overall_score': round(overall_score, 1),
'risk_level': risk_level,
'recommended_action': action,
'category_scores': {
cat: data['score']
for cat, data in self.risk_scores.items()
},
'risk_factors': all_factors
}python
import pandas as pd
import numpy as np
class SupplierRiskAssessment:
"""Comprehensive supplier risk assessment framework"""
def __init__(self, supplier_name):
self.supplier_name = supplier_name
self.risk_scores = {}
self.weights = {
'financial': 0.25,
'operational': 0.25,
'geopolitical': 0.15,
'compliance': 0.15,
'quality': 0.10,
'cybersecurity': 0.10
}
def assess_financial_risk(self, financial_data):
"""
Assess financial risk (0-100, higher = riskier)
financial_data: dict with financial metrics
"""
score = 0
factors = []
# Credit rating
credit_rating = financial_data.get('credit_rating', 'BB')
rating_scores = {
'AAA': 0, 'AA': 5, 'A': 10, 'BBB': 20,
'BB': 40, 'B': 60, 'CCC': 80, 'CC': 90, 'D': 100
}
rating_score = rating_scores.get(credit_rating, 50)
score += rating_score * 0.3
if rating_score >= 40:
factors.append(f"Poor credit rating ({credit_rating})")
# Years in business
years = financial_data.get('years_in_business', 10)
if years < 3:
score += 20
factors.append("Limited operating history")
elif years < 5:
score += 10
# Revenue trend
revenue_growth = financial_data.get('revenue_growth_3yr', 0)
if revenue_growth < -0.15:
score += 15
factors.append("Significant revenue decline")
elif revenue_growth < 0:
score += 8
# Profitability
ebitda_margin = financial_data.get('ebitda_margin', 0.1)
if ebitda_margin < 0:
score += 15
factors.append("Unprofitable operations")
elif ebitda_margin < 0.05:
score += 8
# Liquidity
current_ratio = financial_data.get('current_ratio', 1.5)
if current_ratio < 1.0:
score += 15
factors.append("Liquidity crisis")
elif current_ratio < 1.2:
score += 8
# Leverage
debt_to_equity = financial_data.get('debt_to_equity', 1.0)
if debt_to_equity > 3.0:
score += 15
factors.append("Excessive leverage")
elif debt_to_equity > 2.0:
score += 8
self.risk_scores['financial'] = {
'score': min(100, score),
'factors': factors
}
return self.risk_scores['financial']
def assess_operational_risk(self, operational_data):
"""Assess operational risk"""
score = 0
factors = []
# Capacity utilization
capacity_util = operational_data.get('capacity_utilization', 0.75)
if capacity_util > 0.95:
score += 20
factors.append("Critical capacity constraints")
elif capacity_util > 0.85:
score += 10
# Single facility risk
num_facilities = operational_data.get('num_facilities', 2)
if num_facilities == 1:
score += 15
factors.append("Single facility risk")
# Technology age
tech_age_years = operational_data.get('technology_age_years', 5)
if tech_age_years > 15:
score += 10
factors.append("Outdated technology")
# Workforce stability
employee_turnover = operational_data.get('employee_turnover', 0.15)
if employee_turnover > 0.30:
score += 15
factors.append("High workforce turnover")
elif employee_turnover > 0.20:
score += 8
# Recent disruptions
disruptions_12mo = operational_data.get('disruptions_last_12mo', 0)
if disruptions_12mo > 2:
score += 20
factors.append("Frequent operational disruptions")
elif disruptions_12mo > 0:
score += 10
# Quality performance
defect_ppm = operational_data.get('defect_rate_ppm', 500)
if defect_ppm > 2000:
score += 15
factors.append("Quality issues")
elif defect_ppm > 1000:
score += 8
self.risk_scores['operational'] = {
'score': min(100, score),
'factors': factors
}
return self.risk_scores['operational']
def assess_geopolitical_risk(self, geo_data):
"""Assess geopolitical risk"""
score = 0
factors = []
# Country risk
country_risk_index = geo_data.get('country_risk_index', 50) # 0-100
score += country_risk_index * 0.4
if country_risk_index > 70:
factors.append("High-risk country location")
# Trade restrictions
if geo_data.get('trade_restrictions', False):
score += 20
factors.append("Active trade restrictions")
# Currency volatility
currency_volatility = geo_data.get('currency_volatility_12mo', 0.05)
if currency_volatility > 0.20:
score += 15
factors.append("High currency volatility")
elif currency_volatility > 0.10:
score += 8
# Political stability
political_stability = geo_data.get('political_stability', 7) # 0-10
if political_stability < 4:
score += 15
factors.append("Political instability")
# Border distance/complexity
if geo_data.get('cross_border', False):
score += 5
if geo_data.get('multiple_borders', False):
score += 5
factors.append("Complex cross-border logistics")
self.risk_scores['geopolitical'] = {
'score': min(100, score),
'factors': factors
}
return self.risk_scores['geopolitical']
def assess_compliance_risk(self, compliance_data):
"""Assess compliance and regulatory risk"""
score = 0
factors = []
# Certifications
required_certs = compliance_data.get('required_certifications', [])
actual_certs = compliance_data.get('actual_certifications', [])
missing_certs = set(required_certs) - set(actual_certs)
if missing_certs:
score += 20
factors.append(f"Missing certifications: {', '.join(missing_certs)}")
# Recent violations
violations_3yr = compliance_data.get('violations_last_3yr', 0)
if violations_3yr > 2:
score += 25
factors.append("Multiple compliance violations")
elif violations_3yr > 0:
score += 12
# Audit results
last_audit_score = compliance_data.get('last_audit_score', 85) # 0-100
if last_audit_score < 70:
score += 20
factors.append("Failed recent audit")
elif last_audit_score < 80:
score += 10
# Environmental incidents
if compliance_data.get('environmental_incidents', 0) > 0:
score += 15
factors.append("Environmental incidents")
# Labor concerns
if compliance_data.get('labor_concerns', False):
score += 20
factors.append("Labor or human rights concerns")
self.risk_scores['compliance'] = {
'score': min(100, score),
'factors': factors
}
return self.risk_scores['compliance']
def assess_quality_risk(self, quality_data):
"""Assess quality risk"""
score = 0
factors = []
# Defect rate
defect_ppm = quality_data.get('defect_rate_ppm', 500)
if defect_ppm > 2000:
score += 30
factors.append("High defect rate")
elif defect_ppm > 1000:
score += 15
# Quality certifications
if not quality_data.get('iso_9001', False):
score += 10
factors.append("No ISO 9001 certification")
# Recent recalls
recalls_3yr = quality_data.get('recalls_last_3yr', 0)
if recalls_3yr > 0:
score += 25 * recalls_3yr
factors.append(f"{recalls_3yr} product recalls")
# Customer complaints
complaints = quality_data.get('customer_complaints_per_1000', 5)
if complaints > 20:
score += 20
factors.append("High customer complaint rate")
elif complaints > 10:
score += 10
# Corrective actions
open_corrective_actions = quality_data.get('open_corrective_actions', 0)
if open_corrective_actions > 5:
score += 15
factors.append("Multiple open corrective actions")
self.risk_scores['quality'] = {
'score': min(100, score),
'factors': factors
}
return self.risk_scores['quality']
def assess_cybersecurity_risk(self, cyber_data):
"""Assess cybersecurity risk"""
score = 0
factors = []
# Security certifications
if not cyber_data.get('iso_27001', False):
score += 15
factors.append("No ISO 27001 certification")
# Recent breaches
breaches_3yr = cyber_data.get('breaches_last_3yr', 0)
if breaches_3yr > 0:
score += 30 * breaches_3yr
factors.append(f"{breaches_3yr} security breaches")
# Security maturity
security_maturity = cyber_data.get('security_maturity', 3) # 1-5
if security_maturity < 2:
score += 25
factors.append("Immature cybersecurity practices")
elif security_maturity < 3:
score += 12
# Third-party access
if cyber_data.get('network_integration', False):
score += 10
if not cyber_data.get('secure_access_controls', False):
score += 10
factors.append("Inadequate access controls")
# Incident response
if not cyber_data.get('incident_response_plan', False):
score += 10
factors.append("No incident response plan")
self.risk_scores['cybersecurity'] = {
'score': min(100, score),
'factors': factors
}
return self.risk_scores['cybersecurity']
def calculate_overall_risk(self):
"""Calculate weighted overall risk score"""
if not self.risk_scores:
return None
overall_score = sum(
self.risk_scores[category]['score'] * weight
for category, weight in self.weights.items()
if category in self.risk_scores
)
# Classify risk level
if overall_score < 25:
risk_level = 'Low'
action = 'Monitor periodically'
elif overall_score < 50:
risk_level = 'Medium'
action = 'Monitor regularly, develop contingency'
elif overall_score < 75:
risk_level = 'High'
action = 'Active mitigation required'
else:
risk_level = 'Critical'
action = 'Immediate action, consider alternate supplier'
# Collect all factors
all_factors = []
for category, data in self.risk_scores.items():
for factor in data['factors']:
all_factors.append(f"{category.capitalize()}: {factor}")
return {
'supplier': self.supplier_name,
'overall_score': round(overall_score, 1),
'risk_level': risk_level,
'recommended_action': action,
'category_scores': {
cat: data['score']
for cat, data in self.risk_scores.items()
},
'risk_factors': all_factors
}Example usage
Example usage
supplier = SupplierRiskAssessment('Acme Manufacturing Inc.')
supplier = SupplierRiskAssessment('Acme Manufacturing Inc.')
Assess each risk category
Assess each risk category
supplier.assess_financial_risk({
'credit_rating': 'BB',
'years_in_business': 8,
'revenue_growth_3yr': -0.05,
'ebitda_margin': 0.08,
'current_ratio': 1.3,
'debt_to_equity': 2.2
})
supplier.assess_operational_risk({
'capacity_utilization': 0.88,
'num_facilities': 2,
'technology_age_years': 8,
'employee_turnover': 0.18,
'disruptions_last_12mo': 1,
'defect_rate_ppm': 800
})
supplier.assess_geopolitical_risk({
'country_risk_index': 35,
'trade_restrictions': False,
'currency_volatility_12mo': 0.08,
'political_stability': 7,
'cross_border': True,
'multiple_borders': False
})
supplier.assess_compliance_risk({
'required_certifications': ['ISO9001', 'ISO14001'],
'actual_certifications': ['ISO9001'],
'violations_last_3yr': 0,
'last_audit_score': 85,
'environmental_incidents': 0,
'labor_concerns': False
})
supplier.assess_quality_risk({
'defect_rate_ppm': 800,
'iso_9001': True,
'recalls_last_3yr': 0,
'customer_complaints_per_1000': 8,
'open_corrective_actions': 2
})
supplier.assess_cybersecurity_risk({
'iso_27001': False,
'breaches_last_3yr': 0,
'security_maturity': 3,
'network_integration': True,
'secure_access_controls': True,
'incident_response_plan': True
})
result = supplier.calculate_overall_risk()
print(f"Supplier: {result['supplier']}")
print(f"Overall Risk Score: {result['overall_score']}/100")
print(f"Risk Level: {result['risk_level']}")
print(f"Recommended Action: {result['recommended_action']}")
print("\nCategory Scores:")
for cat, score in result['category_scores'].items():
print(f" {cat.capitalize()}: {score}/100")
---supplier.assess_financial_risk({
'credit_rating': 'BB',
'years_in_business': 8,
'revenue_growth_3yr': -0.05,
'ebitda_margin': 0.08,
'current_ratio': 1.3,
'debt_to_equity': 2.2
})
supplier.assess_operational_risk({
'capacity_utilization': 0.88,
'num_facilities': 2,
'technology_age_years': 8,
'employee_turnover': 0.18,
'disruptions_last_12mo': 1,
'defect_rate_ppm': 800
})
supplier.assess_geopolitical_risk({
'country_risk_index': 35,
'trade_restrictions': False,
'currency_volatility_12mo': 0.08,
'political_stability': 7,
'cross_border': True,
'multiple_borders': False
})
supplier.assess_compliance_risk({
'required_certifications': ['ISO9001', 'ISO14001'],
'actual_certifications': ['ISO9001'],
'violations_last_3yr': 0,
'last_audit_score': 85,
'environmental_incidents': 0,
'labor_concerns': False
})
supplier.assess_quality_risk({
'defect_rate_ppm': 800,
'iso_9001': True,
'recalls_last_3yr': 0,
'customer_complaints_per_1000': 8,
'open_corrective_actions': 2
})
supplier.assess_cybersecurity_risk({
'iso_27001': False,
'breaches_last_3yr': 0,
'security_maturity': 3,
'network_integration': True,
'secure_access_controls': True,
'incident_response_plan': True
})
result = supplier.calculate_overall_risk()
print(f"Supplier: {result['supplier']}")
print(f"Overall Risk Score: {result['overall_score']}/100")
print(f"Risk Level: {result['risk_level']}")
print(f"Recommended Action: {result['recommended_action']}")
print("\nCategory Scores:")
for cat, score in result['category_scores'].items():
print(f" {cat.capitalize()}: {score}/100")
---Business Impact Assessment
业务影响评估
Criticality Analysis
关键性分析
python
def assess_supplier_criticality(supplier_data):
"""
Determine supplier criticality to business
Returns: criticality score (0-100) and tier classification
"""
criticality_score = 0
# Spend volume
annual_spend = supplier_data.get('annual_spend', 0)
if annual_spend > 10000000: # >$10M
criticality_score += 20
elif annual_spend > 1000000: # >$1M
criticality_score += 15
elif annual_spend > 100000: # >$100K
criticality_score += 10
# Replaceability
substitute_availability = supplier_data.get('substitute_availability', 'high')
if substitute_availability == 'none':
criticality_score += 30
elif substitute_availability == 'low':
criticality_score += 20
elif substitute_availability == 'medium':
criticality_score += 10
# Lead time to replace
replacement_time_weeks = supplier_data.get('replacement_time_weeks', 12)
if replacement_time_weeks > 26: # >6 months
criticality_score += 20
elif replacement_time_weeks > 12: # >3 months
criticality_score += 15
elif replacement_time_weeks > 4: # >1 month
criticality_score += 10
# Business impact
revenue_at_risk = supplier_data.get('revenue_at_risk', 0)
if revenue_at_risk > 50000000: # >$50M
criticality_score += 20
elif revenue_at_risk > 10000000: # >$10M
criticality_score += 15
elif revenue_at_risk > 1000000: # >$1M
criticality_score += 10
# Customer impact
customers_affected = supplier_data.get('customers_affected', 'none')
if customers_affected == 'critical':
criticality_score += 10
elif customers_affected == 'major':
criticality_score += 7
# Classify tier
if criticality_score >= 70:
tier = 'Tier 1 - Critical'
monitoring_frequency = 'Weekly'
elif criticality_score >= 50:
tier = 'Tier 2 - Important'
monitoring_frequency = 'Monthly'
elif criticality_score >= 30:
tier = 'Tier 3 - Standard'
monitoring_frequency = 'Quarterly'
else:
tier = 'Tier 4 - Low Impact'
monitoring_frequency = 'Annual'
return {
'criticality_score': criticality_score,
'tier': tier,
'monitoring_frequency': monitoring_frequency
}python
def assess_supplier_criticality(supplier_data):
"""
Determine supplier criticality to business
Returns: criticality score (0-100) and tier classification
"""
criticality_score = 0
# Spend volume
annual_spend = supplier_data.get('annual_spend', 0)
if annual_spend > 10000000: # >$10M
criticality_score += 20
elif annual_spend > 1000000: # >$1M
criticality_score += 15
elif annual_spend > 100000: # >$100K
criticality_score += 10
# Replaceability
substitute_availability = supplier_data.get('substitute_availability', 'high')
if substitute_availability == 'none':
criticality_score += 30
elif substitute_availability == 'low':
criticality_score += 20
elif substitute_availability == 'medium':
criticality_score += 10
# Lead time to replace
replacement_time_weeks = supplier_data.get('replacement_time_weeks', 12)
if replacement_time_weeks > 26: # >6 months
criticality_score += 20
elif replacement_time_weeks > 12: # >3 months
criticality_score += 15
elif replacement_time_weeks > 4: # >1 month
criticality_score += 10
# Business impact
revenue_at_risk = supplier_data.get('revenue_at_risk', 0)
if revenue_at_risk > 50000000: # >$50M
criticality_score += 20
elif revenue_at_risk > 10000000: # >$10M
criticality_score += 15
elif revenue_at_risk > 1000000: # >$1M
criticality_score += 10
# Customer impact
customers_affected = supplier_data.get('customers_affected', 'none')
if customers_affected == 'critical':
criticality_score += 10
elif customers_affected == 'major':
criticality_score += 7
# Classify tier
if criticality_score >= 70:
tier = 'Tier 1 - Critical'
monitoring_frequency = 'Weekly'
elif criticality_score >= 50:
tier = 'Tier 2 - Important'
monitoring_frequency = 'Monthly'
elif criticality_score >= 30:
tier = 'Tier 3 - Standard'
monitoring_frequency = 'Quarterly'
else:
tier = 'Tier 4 - Low Impact'
monitoring_frequency = 'Annual'
return {
'criticality_score': criticality_score,
'tier': tier,
'monitoring_frequency': monitoring_frequency
}Risk Exposure Matrix
风险暴露矩阵
Risk Score × Criticality Score = Exposure
python
import matplotlib.pyplot as plt
import numpy as np
def plot_risk_exposure_matrix(suppliers_df):
"""
Create risk exposure matrix (bubble chart)
suppliers_df: DataFrame with risk_score, criticality_score, spend
"""
fig, ax = plt.subplots(figsize=(12, 8))
# Create scatter plot
scatter = ax.scatter(
suppliers_df['criticality_score'],
suppliers_df['risk_score'],
s=suppliers_df['spend'] / 10000, # Bubble size by spend
alpha=0.6,
c=suppliers_df['risk_score'],
cmap='RdYlGn_r'
)
# Add supplier labels
for idx, row in suppliers_df.iterrows():
ax.annotate(
row['supplier_name'],
(row['criticality_score'], row['risk_score']),
fontsize=8
)
# Quadrant lines
ax.axvline(50, color='gray', linestyle='--', alpha=0.5)
ax.axhline(50, color='gray', linestyle='--', alpha=0.5)
# Quadrant labels
ax.text(75, 75, 'High Risk\nHigh Criticality\nACT NOW', ha='center', fontsize=10, weight='bold', color='red')
ax.text(25, 75, 'High Risk\nLow Criticality\nMONITOR', ha='center', fontsize=10)
ax.text(75, 25, 'Low Risk\nHigh Criticality\nPROTECT', ha='center', fontsize=10)
ax.text(25, 25, 'Low Risk\nLow Criticality\nROUTINE', ha='center', fontsize=10)
ax.set_xlabel('Criticality Score', fontsize=12)
ax.set_ylabel('Risk Score', fontsize=12)
ax.set_title('Supplier Risk Exposure Matrix', fontsize=14, weight='bold')
ax.set_xlim(0, 100)
ax.set_ylim(0, 100)
ax.grid(True, alpha=0.3)
plt.colorbar(scatter, label='Risk Score')
plt.tight_layout()
return fig风险评分 × 关键性评分 = 暴露程度
python
import matplotlib.pyplot as plt
import numpy as np
def plot_risk_exposure_matrix(suppliers_df):
"""
Create risk exposure matrix (bubble chart)
suppliers_df: DataFrame with risk_score, criticality_score, spend
"""
fig, ax = plt.subplots(figsize=(12, 8))
# Create scatter plot
scatter = ax.scatter(
suppliers_df['criticality_score'],
suppliers_df['risk_score'],
s=suppliers_df['spend'] / 10000, # Bubble size by spend
alpha=0.6,
c=suppliers_df['risk_score'],
cmap='RdYlGn_r'
)
# Add supplier labels
for idx, row in suppliers_df.iterrows():
ax.annotate(
row['supplier_name'],
(row['criticality_score'], row['risk_score']),
fontsize=8
)
# Quadrant lines
ax.axvline(50, color='gray', linestyle='--', alpha=0.5)
ax.axhline(50, color='gray', linestyle='--', alpha=0.5)
# Quadrant labels
ax.text(75, 75, 'High Risk\nHigh Criticality\nACT NOW', ha='center', fontsize=10, weight='bold', color='red')
ax.text(25, 75, 'High Risk\nLow Criticality\nMONITOR', ha='center', fontsize=10)
ax.text(75, 25, 'Low Risk\nHigh Criticality\nPROTECT', ha='center', fontsize=10)
ax.text(25, 25, 'Low Risk\nLow Criticality\nROUTINE', ha='center', fontsize=10)
ax.set_xlabel('Criticality Score', fontsize=12)
ax.set_ylabel('Risk Score', fontsize=12)
ax.set_title('Supplier Risk Exposure Matrix', fontsize=14, weight='bold')
ax.set_xlim(0, 100)
ax.set_ylim(0, 100)
ax.grid(True, alpha=0.3)
plt.colorbar(scatter, label='Risk Score')
plt.tight_layout()
return figRisk Monitoring & Early Warning
风险监控与预警
Key Risk Indicators (KRIs)
关键风险指标(KRIs)
Financial KRIs:
- Credit rating changes
- Stock price volatility (public companies)
- Days payable outstanding (DPO) increases
- Debt covenant violations
- Bankruptcy filings in industry
Operational KRIs:
- On-time delivery decline
- Quality defect rate increases
- Lead time extensions
- Capacity utilization spikes
- Employee layoffs or strikes
External KRIs:
- Natural disasters in supplier regions
- Political events (elections, coups)
- Regulatory changes
- Cyber attacks in industry
- Pandemic or health alerts
python
class RiskMonitoringSystem:
"""Automated risk monitoring and alerting"""
def __init__(self):
self.kris = {}
self.thresholds = {}
self.alerts = []
def add_kri(self, kri_name, current_value, threshold, direction='above'):
"""
Add Key Risk Indicator
direction: 'above' (alert if above threshold) or 'below'
"""
self.kris[kri_name] = current_value
self.thresholds[kri_name] = {
'value': threshold,
'direction': direction
}
def check_alerts(self):
"""Check all KRIs against thresholds"""
self.alerts = []
for kri, value in self.kris.items():
threshold = self.thresholds[kri]
if threshold['direction'] == 'above':
if value > threshold['value']:
severity = self._calculate_severity(value, threshold['value'], 'above')
self.alerts.append({
'kri': kri,
'current_value': value,
'threshold': threshold['value'],
'severity': severity,
'direction': 'exceeded'
})
elif threshold['direction'] == 'below':
if value < threshold['value']:
severity = self._calculate_severity(value, threshold['value'], 'below')
self.alerts.append({
'kri': kri,
'current_value': value,
'threshold': threshold['value'],
'severity': severity,
'direction': 'fell below'
})
return self.alerts
def _calculate_severity(self, current, threshold, direction):
"""Calculate alert severity"""
if direction == 'above':
pct_over = (current - threshold) / threshold
if pct_over > 0.50:
return 'Critical'
elif pct_over > 0.25:
return 'High'
elif pct_over > 0.10:
return 'Medium'
else:
return 'Low'
else: # below
pct_under = (threshold - current) / threshold
if pct_under > 0.50:
return 'Critical'
elif pct_under > 0.25:
return 'High'
elif pct_under > 0.10:
return 'Medium'
else:
return 'Low'
def generate_alert_report(self):
"""Generate formatted alert report"""
if not self.alerts:
return "No alerts triggered."
report = ["=" * 60]
report.append("SUPPLIER RISK ALERTS")
report.append("=" * 60)
report.append("")
# Sort by severity
severity_order = {'Critical': 0, 'High': 1, 'Medium': 2, 'Low': 3}
sorted_alerts = sorted(
self.alerts,
key=lambda x: severity_order[x['severity']]
)
for alert in sorted_alerts:
report.append(f"[{alert['severity'].upper()}] {alert['kri']}")
report.append(f" Current: {alert['current_value']:.2f}")
report.append(f" Threshold: {alert['threshold']:.2f}")
report.append(f" Status: {alert['direction']}")
report.append("")
return "\n".join(report)财务KRIs:
- 信用评级变化
- 股价波动(上市公司)
- 应付账款周转天数(DPO)增加
- 债务契约违约
- 行业内破产申请
运营KRIs:
- 准时交付率下降
- 质量缺陷率上升
- 交付周期延长
- 产能利用率飙升
- 员工裁员或罢工
外部KRIs:
- 供应商所在地区发生自然灾害
- 政治事件(选举、政变)
- 监管变更
- 行业内网络攻击
- 疫情或健康警报
python
class RiskMonitoringSystem:
"""Automated risk monitoring and alerting"""
def __init__(self):
self.kris = {}
self.thresholds = {}
self.alerts = []
def add_kri(self, kri_name, current_value, threshold, direction='above'):
"""
Add Key Risk Indicator
direction: 'above' (alert if above threshold) or 'below'
"""
self.kris[kri_name] = current_value
self.thresholds[kri_name] = {
'value': threshold,
'direction': direction
}
def check_alerts(self):
"""Check all KRIs against thresholds"""
self.alerts = []
for kri, value in self.kris.items():
threshold = self.thresholds[kri]
if threshold['direction'] == 'above':
if value > threshold['value']:
severity = self._calculate_severity(value, threshold['value'], 'above')
self.alerts.append({
'kri': kri,
'current_value': value,
'threshold': threshold['value'],
'severity': severity,
'direction': 'exceeded'
})
elif threshold['direction'] == 'below':
if value < threshold['value']:
severity = self._calculate_severity(value, threshold['value'], 'below')
self.alerts.append({
'kri': kri,
'current_value': value,
'threshold': threshold['value'],
'severity': severity,
'direction': 'fell below'
})
return self.alerts
def _calculate_severity(self, current, threshold, direction):
"""Calculate alert severity"""
if direction == 'above':
pct_over = (current - threshold) / threshold
if pct_over > 0.50:
return 'Critical'
elif pct_over > 0.25:
return 'High'
elif pct_over > 0.10:
return 'Medium'
else:
return 'Low'
else: # below
pct_under = (threshold - current) / threshold
if pct_under > 0.50:
return 'Critical'
elif pct_under > 0.25:
return 'High'
elif pct_under > 0.10:
return 'Medium'
else:
return 'Low'
def generate_alert_report(self):
"""Generate formatted alert report"""
if not self.alerts:
return "No alerts triggered."
report = ["=" * 60]
report.append("SUPPLIER RISK ALERTS")
report.append("=" * 60)
report.append("")
# Sort by severity
severity_order = {'Critical': 0, 'High': 1, 'Medium': 2, 'Low': 3}
sorted_alerts = sorted(
self.alerts,
key=lambda x: severity_order[x['severity']]
)
for alert in sorted_alerts:
report.append(f"[{alert['severity'].upper()}] {alert['kri']}")
report.append(f" Current: {alert['current_value']:.2f}")
report.append(f" Threshold: {alert['threshold']:.2f}")
report.append(f" Status: {alert['direction']}")
report.append("")
return "\n".join(report)Example
Example
monitor = RiskMonitoringSystem()
monitor = RiskMonitoringSystem()
Add KRIs for a supplier
Add KRIs for a supplier
monitor.add_kri('defect_rate_ppm', 1500, 1000, direction='above')
monitor.add_kri('on_time_delivery_%', 88, 95, direction='below')
monitor.add_kri('lead_time_days', 28, 21, direction='above')
monitor.add_kri('capacity_utilization_%', 96, 90, direction='above')
monitor.add_kri('credit_score', 65, 70, direction='below')
monitor.add_kri('defect_rate_ppm', 1500, 1000, direction='above')
monitor.add_kri('on_time_delivery_%', 88, 95, direction='below')
monitor.add_kri('lead_time_days', 28, 21, direction='above')
monitor.add_kri('capacity_utilization_%', 96, 90, direction='above')
monitor.add_kri('credit_score', 65, 70, direction='below')
Check for alerts
Check for alerts
alerts = monitor.check_alerts()
print(monitor.generate_alert_report())
---alerts = monitor.check_alerts()
print(monitor.generate_alert_report())
---Risk Mitigation Strategies
风险缓解策略
Mitigation Options by Risk Level
按风险等级划分的缓解方案
For Critical Risk (Score >75):
- Dual sourcing immediately
- Build safety stock (3-6 months)
- Qualify backup supplier
- Escalate to executive level
- Consider insourcing or acquisition
For High Risk (Score 50-75):
- Develop contingency plan
- Increase monitoring frequency
- Negotiate exit clauses
- Identify alternate suppliers
- Build buffer inventory (1-3 months)
For Medium Risk (Score 25-50):
- Regular performance reviews
- Request improvement plans
- Diversify volume allocation
- Monitor early warning signals
- Annual risk reassessment
For Low Risk (Score <25):
- Standard monitoring
- Periodic audits
- Maintain relationship
- Focus on optimization
针对极高风险(评分>75):
- 立即启用双源供应
- 建立安全库存(3-6个月)
- 认证备用供应商
- 升级至管理层处理
- 考虑内包或收购
针对高风险(评分50-75):
- 制定应急计划
- 提高监控频率
- 协商退出条款
- 寻找替代供应商
- 建立缓冲库存(1-3个月)
针对中等风险(评分25-50):
- 定期绩效评审
- 要求供应商提交改进计划
- 分散采购量分配
- 监控预警信号
- 年度风险重新评估
针对低风险(评分<25):
- 标准化监控
- 定期审计
- 维护合作关系
- 聚焦优化
Contingency Planning
应急计划
python
class ContingencyPlan:
"""Business continuity planning for supplier disruption"""
def __init__(self, supplier_name, criticality_tier):
self.supplier_name = supplier_name
self.criticality_tier = criticality_tier
self.mitigation_actions = []
def add_mitigation(self, action, timeline_days, owner, status='Planned'):
"""Add mitigation action"""
self.mitigation_actions.append({
'action': action,
'timeline_days': timeline_days,
'owner': owner,
'status': status
})
def calculate_recovery_time(self):
"""Estimate recovery time objective (RTO)"""
if not self.mitigation_actions:
return float('inf')
# RTO is the longest timeline among active mitigations
active_actions = [
m for m in self.mitigation_actions
if m['status'] in ['Planned', 'In Progress']
]
if not active_actions:
return 0
return max(m['timeline_days'] for m in active_actions)
def generate_plan_document(self):
"""Generate contingency plan document"""
doc = []
doc.append("=" * 70)
doc.append(f"SUPPLIER CONTINGENCY PLAN: {self.supplier_name}")
doc.append("=" * 70)
doc.append(f"Criticality Tier: {self.criticality_tier}")
doc.append(f"Recovery Time Objective (RTO): {self.calculate_recovery_time()} days")
doc.append("")
doc.append("MITIGATION ACTIONS:")
doc.append("-" * 70)
for i, action in enumerate(self.mitigation_actions, 1):
doc.append(f"\n{i}. {action['action']}")
doc.append(f" Timeline: {action['timeline_days']} days")
doc.append(f" Owner: {action['owner']}")
doc.append(f" Status: {action['status']}")
return "\n".join(doc)python
class ContingencyPlan:
"""Business continuity planning for supplier disruption"""
def __init__(self, supplier_name, criticality_tier):
self.supplier_name = supplier_name
self.criticality_tier = criticality_tier
self.mitigation_actions = []
def add_mitigation(self, action, timeline_days, owner, status='Planned'):
"""Add mitigation action"""
self.mitigation_actions.append({
'action': action,
'timeline_days': timeline_days,
'owner': owner,
'status': status
})
def calculate_recovery_time(self):
"""Estimate recovery time objective (RTO)"""
if not self.mitigation_actions:
return float('inf')
# RTO is the longest timeline among active mitigations
active_actions = [
m for m in self.mitigation_actions
if m['status'] in ['Planned', 'In Progress']
]
if not active_actions:
return 0
return max(m['timeline_days'] for m in active_actions)
def generate_plan_document(self):
"""Generate contingency plan document"""
doc = []
doc.append("=" * 70)
doc.append(f"SUPPLIER CONTINGENCY PLAN: {self.supplier_name}")
doc.append("=" * 70)
doc.append(f"Criticality Tier: {self.criticality_tier}")
doc.append(f"Recovery Time Objective (RTO): {self.calculate_recovery_time()} days")
doc.append("")
doc.append("MITIGATION ACTIONS:")
doc.append("-" * 70)
for i, action in enumerate(self.mitigation_actions, 1):
doc.append(f"\n{i}. {action['action']}")
doc.append(f" Timeline: {action['timeline_days']} days")
doc.append(f" Owner: {action['owner']}")
doc.append(f" Status: {action['status']}")
return "\n".join(doc)Example contingency plan
Example contingency plan
plan = ContingencyPlan('Acme Manufacturing', 'Tier 1 - Critical')
plan.add_mitigation(
action='Activate backup supplier (XYZ Corp)',
timeline_days=30,
owner='Procurement Manager',
status='Planned'
)
plan.add_mitigation(
action='Build 60-day safety stock',
timeline_days=45,
owner='Supply Chain Manager',
status='In Progress'
)
plan.add_mitigation(
action='Expedite supplier qualification for Alternate Supplier',
timeline_days=60,
owner='Quality Manager',
status='Planned'
)
plan.add_mitigation(
action='Identify insourcing options',
timeline_days=90,
owner='Operations Manager',
status='Planned'
)
print(plan.generate_plan_document())
undefinedplan = ContingencyPlan('Acme Manufacturing', 'Tier 1 - Critical')
plan.add_mitigation(
action='Activate backup supplier (XYZ Corp)',
timeline_days=30,
owner='Procurement Manager',
status='Planned'
)
plan.add_mitigation(
action='Build 60-day safety stock',
timeline_days=45,
owner='Supply Chain Manager',
status='In Progress'
)
plan.add_mitigation(
action='Expedite supplier qualification for Alternate Supplier',
timeline_days=60,
owner='Quality Manager',
status='Planned'
)
plan.add_mitigation(
action='Identify insourcing options',
timeline_days=90,
owner='Operations Manager',
status='Planned'
)
print(plan.generate_plan_document())
undefinedDual Sourcing Strategy
双源供应策略
python
def design_dual_sourcing_strategy(primary_supplier, backup_supplier,
annual_demand, disruption_scenarios):
"""
Design optimal dual sourcing strategy
disruption_scenarios: list of dicts with 'probability' and 'duration_days'
"""
# Calculate expected disruption cost
expected_disruption_days = sum(
scenario['probability'] * scenario['duration_days']
for scenario in disruption_scenarios
)
# Cost per day of disruption (lost revenue, expedite costs, etc.)
disruption_cost_per_day = 50000 # Example: $50K/day
expected_annual_disruption_cost = expected_disruption_days * disruption_cost_per_day
# Evaluate sourcing strategies
strategies = []
# Strategy 1: 100% primary (single source)
cost_100_0 = (
annual_demand * primary_supplier['unit_cost'] +
expected_annual_disruption_cost
)
strategies.append({
'name': '100% Primary (Single Source)',
'primary_%': 100,
'backup_%': 0,
'cost': cost_100_0,
'risk': 'High'
})
# Strategy 2: 80/20 split
primary_qty_80 = annual_demand * 0.8
backup_qty_20 = annual_demand * 0.2
cost_80_20 = (
primary_qty_80 * primary_supplier['unit_cost'] +
backup_qty_20 * backup_supplier['unit_cost'] +
expected_annual_disruption_cost * 0.3 # 70% risk reduction
)
strategies.append({
'name': '80/20 Split',
'primary_%': 80,
'backup_%': 20,
'cost': cost_80_20,
'risk': 'Medium'
})
# Strategy 3: 70/30 split
primary_qty_70 = annual_demand * 0.7
backup_qty_30 = annual_demand * 0.3
cost_70_30 = (
primary_qty_70 * primary_supplier['unit_cost'] +
backup_qty_30 * backup_supplier['unit_cost'] +
expected_annual_disruption_cost * 0.2 # 80% risk reduction
)
strategies.append({
'name': '70/30 Split',
'primary_%': 70,
'backup_%': 30,
'cost': cost_70_30,
'risk': 'Low'
})
# Strategy 4: 50/50 split (full redundancy)
primary_qty_50 = annual_demand * 0.5
backup_qty_50 = annual_demand * 0.5
cost_50_50 = (
primary_qty_50 * primary_supplier['unit_cost'] +
backup_qty_50 * backup_supplier['unit_cost'] +
expected_annual_disruption_cost * 0.1 # 90% risk reduction
)
strategies.append({
'name': '50/50 Split (Full Redundancy)',
'primary_%': 50,
'backup_%': 50,
'cost': cost_50_50,
'risk': 'Very Low'
})
# Find optimal strategy (lowest total cost)
optimal = min(strategies, key=lambda x: x['cost'])
return {
'strategies': strategies,
'optimal': optimal,
'savings_vs_single_source': cost_100_0 - optimal['cost']
}python
def design_dual_sourcing_strategy(primary_supplier, backup_supplier,
annual_demand, disruption_scenarios):
"""
Design optimal dual sourcing strategy
disruption_scenarios: list of dicts with 'probability' and 'duration_days'
"""
# Calculate expected disruption cost
expected_disruption_days = sum(
scenario['probability'] * scenario['duration_days']
for scenario in disruption_scenarios
)
# Cost per day of disruption (lost revenue, expedite costs, etc.)
disruption_cost_per_day = 50000 # Example: $50K/day
expected_annual_disruption_cost = expected_disruption_days * disruption_cost_per_day
# Evaluate sourcing strategies
strategies = []
# Strategy 1: 100% primary (single source)
cost_100_0 = (
annual_demand * primary_supplier['unit_cost'] +
expected_annual_disruption_cost
)
strategies.append({
'name': '100% Primary (Single Source)',
'primary_%': 100,
'backup_%': 0,
'cost': cost_100_0,
'risk': 'High'
})
# Strategy 2: 80/20 split
primary_qty_80 = annual_demand * 0.8
backup_qty_20 = annual_demand * 0.2
cost_80_20 = (
primary_qty_80 * primary_supplier['unit_cost'] +
backup_qty_20 * backup_supplier['unit_cost'] +
expected_annual_disruption_cost * 0.3 # 70% risk reduction
)
strategies.append({
'name': '80/20 Split',
'primary_%': 80,
'backup_%': 20,
'cost': cost_80_20,
'risk': 'Medium'
})
# Strategy 3: 70/30 split
primary_qty_70 = annual_demand * 0.7
backup_qty_30 = annual_demand * 0.3
cost_70_30 = (
primary_qty_70 * primary_supplier['unit_cost'] +
backup_qty_30 * backup_supplier['unit_cost'] +
expected_annual_disruption_cost * 0.2 # 80% risk reduction
)
strategies.append({
'name': '70/30 Split',
'primary_%': 70,
'backup_%': 30,
'cost': cost_70_30,
'risk': 'Low'
})
# Strategy 4: 50/50 split (full redundancy)
primary_qty_50 = annual_demand * 0.5
backup_qty_50 = annual_demand * 0.5
cost_50_50 = (
primary_qty_50 * primary_supplier['unit_cost'] +
backup_qty_50 * backup_supplier['unit_cost'] +
expected_annual_disruption_cost * 0.1 # 90% risk reduction
)
strategies.append({
'name': '50/50 Split (Full Redundancy)',
'primary_%': 50,
'backup_%': 50,
'cost': cost_50_50,
'risk': 'Very Low'
})
# Find optimal strategy (lowest total cost)
optimal = min(strategies, key=lambda x: x['cost'])
return {
'strategies': strategies,
'optimal': optimal,
'savings_vs_single_source': cost_100_0 - optimal['cost']
}Example
Example
primary = {'unit_cost': 10.00}
backup = {'unit_cost': 10.80}
disruption_scenarios = [
{'probability': 0.10, 'duration_days': 30}, # 10% chance of 30-day disruption
{'probability': 0.05, 'duration_days': 90}, # 5% chance of 90-day disruption
]
result = design_dual_sourcing_strategy(
primary, backup, annual_demand=100000, disruption_scenarios=disruption_scenarios
)
print("Dual Sourcing Analysis:")
for strategy in result['strategies']:
print(f"\n{strategy['name']}")
print(f" Split: {strategy['primary_%']}% / {strategy['backup_%']}%")
print(f" Total Cost: ${strategy['cost']:,.0f}")
print(f" Risk Level: {strategy['risk']}")
print(f"\n\nOptimal Strategy: {result['optimal']['name']}")
print(f"Savings vs Single Source: ${result['savings_vs_single_source']:,.0f}")
---primary = {'unit_cost': 10.00}
backup = {'unit_cost': 10.80}
disruption_scenarios = [
{'probability': 0.10, 'duration_days': 30}, # 10% chance of 30-day disruption
{'probability': 0.05, 'duration_days': 90}, # 5% chance of 90-day disruption
]
result = design_dual_sourcing_strategy(
primary, backup, annual_demand=100000, disruption_scenarios=disruption_scenarios
)
print("Dual Sourcing Analysis:")
for strategy in result['strategies']:
print(f"\n{strategy['name']}")
print(f" Split: {strategy['primary_%']}% / {strategy['backup_%']}%")
print(f" Total Cost: ${strategy['cost']:,.0f}")
print(f" Risk Level: {strategy['risk']}")
print(f"\n\nOptimal Strategy: {result['optimal']['name']}")
print(f"Savings vs Single Source: ${result['savings_vs_single_source']:,.0f}")
---Tools & Libraries
工具与库
Python Libraries
Python库
Risk Analytics:
- : Data manipulation and analysis
pandas - : Numerical computations
numpy - : Statistical analysis
scipy - : Predictive risk modeling
scikit-learn
Visualization:
- ,
matplotlib: Risk charts and dashboardsseaborn - : Interactive risk visualizations
plotly - : Supplier network mapping
networkx
Monitoring:
- : API integration for data feeds
requests - : Web scraping for news monitoring
beautifulsoup4 - : Automated monitoring tasks
schedule
风险分析:
- : 数据处理与分析
pandas - : 数值计算
numpy - : 统计分析
scipy - : 预测风险建模
scikit-learn
可视化:
- ,
matplotlib: 风险图表与仪表盘seaborn - : 交互式风险可视化
plotly - : 供应商网络映射
networkx
监控:
- : 数据馈送API集成
requests - : 新闻监控网页抓取
beautifulsoup4 - : 自动化监控任务
schedule
Commercial Software
商业软件
Risk Management Platforms:
- Resilinc: Supply chain risk management and monitoring
- RapidRatings: Financial health ratings
- Dun & Bradstreet: Supplier risk intelligence
- Everstream Analytics: AI-powered risk prediction
- Interos: Supply chain resilience
- Exiger: Third-party risk management
Supplier Performance:
- SAP Ariba: Supplier management
- Coupa: Supplier risk and performance
- Jaggaer: Supplier lifecycle management
- GEP: Supplier risk assessment
Business Continuity:
- LogicManager: Integrated risk management
- Resolver: Incident and risk management
- Fusion Framework: Risk and resilience
风险管理平台:
- Resilinc: 供应链风险管理与监控
- RapidRatings: 财务健康评级
- Dun & Bradstreet: 供应商风险情报
- Everstream Analytics: AI驱动的风险预测
- Interos: 供应链韧性
- Exiger: 第三方风险管理
供应商绩效:
- SAP Ariba: 供应商管理
- Coupa: 供应商风险与绩效
- Jaggaer: 供应商生命周期管理
- GEP: 供应商风险评估
业务连续性:
- LogicManager: 集成风险管理
- Resolver: 事件与风险管理
- Fusion Framework: 风险与韧性
Common Challenges & Solutions
常见挑战与解决方案
Challenge: Limited Supplier Visibility
挑战:供应商可见性有限
Problem:
- Lack of real-time data
- Suppliers reluctant to share information
- N-tier visibility (suppliers of suppliers)
Solutions:
- Contractual requirements for transparency
- Third-party risk monitoring services
- Supplier audits and site visits
- Industry benchmarking
- Collaborative risk sharing agreements
- Use of technology (IoT, blockchain)
问题:
- 缺乏实时数据
- 供应商不愿共享信息
- N级可见性(供应商的供应商)
解决方案:
- 合同要求透明度
- 第三方风险监控服务
- 供应商审计与现场访问
- 行业基准测试
- 协作风险共享协议
- 技术应用(IoT、区块链)
Challenge: Risk Assessment Subjectivity
挑战:风险评估主观性
Problem:
- Inconsistent risk scoring
- Personal biases
- Lack of standardized criteria
Solutions:
- Standardized risk assessment framework
- Quantitative metrics where possible
- Multiple evaluators (triangulation)
- Regular calibration sessions
- Automated scoring algorithms
- External validation (audits, ratings)
问题:
- 风险评分不一致
- 个人偏见
- 缺乏标准化标准
解决方案:
- 标准化风险评估框架
- 尽可能使用量化指标
- 多评估者(三角验证)
- 定期校准会议
- 自动化评分算法
- 外部验证(审计、评级)
Challenge: Alert Fatigue
挑战:警报疲劳
Problem:
- Too many low-priority alerts
- Important signals missed
- Resources overwhelmed
Solutions:
- Risk-based prioritization (focus on critical suppliers)
- Threshold tuning (reduce false positives)
- Aggregated reporting (weekly digests)
- Escalation procedures (tiered response)
- Machine learning for anomaly detection
问题:
- 过多低优先级警报
- 重要信号被忽略
- 资源不堪重负
解决方案:
- 基于风险的优先级划分(聚焦关键供应商)
- 阈值调整(减少误报)
- 聚合报告(每周摘要)
- 升级流程(分层响应)
- 机器学习异常检测
Challenge: Mitigation Cost Justification
挑战:缓解成本合理性
Problem:
- Hard to quantify risk savings
- Upfront costs vs. uncertain benefits
- Budget constraints
Solutions:
- Expected value analysis (probability × impact)
- Scenario planning (stress testing)
- Historical disruption cost data
- Insurance analogy (risk premium)
- Pilot programs (prove ROI)
- Executive risk workshops
问题:
- 难以量化风险节约
- 前期成本与不确定收益
- 预算限制
解决方案:
- 期望值分析(概率×影响)
- 场景规划(压力测试)
- 历史中断成本数据
- 保险类比(风险溢价)
- 试点项目(证明ROI)
- 管理层风险研讨会
Challenge: Supplier Resistance
挑战:供应商抵触
Problem:
- Suppliers push back on audits
- Don't want to share financial data
- Offended by risk questioning
Solutions:
- Frame as partnership (mutual benefit)
- Phased approach (build trust)
- Reciprocal transparency
- Industry standards compliance
- Contractual obligations
- Incentives for participation
问题:
- 供应商抵制审计
- 不愿共享财务数据
- 对风险问题感到不满
解决方案:
- 定位为合作伙伴(互利共赢)
- 分阶段实施(建立信任)
- 相互透明
- 行业标准合规
- 合同义务
- 参与激励
Output Format
输出格式
Supplier Risk Report
供应商风险报告
Executive Summary:
- Overall supplier risk portfolio status
- Critical alerts and actions required
- Trend analysis (improving/deteriorating)
- Key recommendations
Individual Supplier Assessment:
Supplier: Acme Manufacturing Inc.
Risk Tier: HIGH (Score: 62/100)
Criticality: Tier 1 - Critical Supplier
Risk Category Scores:
Financial: 48/100 (Medium)
Operational: 65/100 (High)
Geopolitical: 35/100 (Low)
Compliance: 25/100 (Low)
Quality: 45/100 (Medium)
Cybersecurity: 55/100 (Medium)
Top Risk Factors:
1. High capacity utilization (>90%)
2. Single facility operation
3. Credit rating downgrade (BB)
4. Missing ISO 27001 certification
5. Elevated employee turnover
Business Impact:
Annual Spend: $5.2M
Revenue at Risk: $18M
Customers Affected: 120 (15 critical accounts)
Replacement Time: 16 weeks
Criticality Score: 75/100
Mitigation Actions Required:
1. [HIGH] Qualify backup supplier within 60 days
2. [HIGH] Build 90-day safety stock
3. [MEDIUM] Conduct site visit to assess capacity
4. [MEDIUM] Request cybersecurity audit
5. [LOW] Negotiate performance guarantees in contract renewal
Contingency Plan: ACTIVATED
- Backup supplier identified: XYZ Corp
- Safety stock build: In Progress (45 days complete)
- Alternative sourcing: Under evaluation
Next Review: 30 daysPortfolio Risk Dashboard:
| Supplier | Risk Score | Criticality | Spend | Status | Trend | Action Required |
|---|---|---|---|---|---|---|
| Acme Mfg | 62 (High) | Tier 1 | $5.2M | ⚠ | ↗ | Dual source |
| Beta Corp | 35 (Medium) | Tier 1 | $3.8M | ✓ | → | Monitor |
| Gamma Inc | 78 (Critical) | Tier 2 | $1.5M | ⚠⚠ | ↗ | Replace |
| Delta Ltd | 22 (Low) | Tier 3 | $0.8M | ✓ | ↘ | None |
执行摘要:
- 整体供应商风险组合状态
- 关键警报与所需行动
- 趋势分析(改善/恶化)
- 关键建议
单个供应商评估:
Supplier: Acme Manufacturing Inc.
Risk Tier: HIGH (Score: 62/100)
Criticality: Tier 1 - Critical Supplier
Risk Category Scores:
Financial: 48/100 (Medium)
Operational: 65/100 (High)
Geopolitical: 35/100 (Low)
Compliance: 25/100 (Low)
Quality: 45/100 (Medium)
Cybersecurity: 55/100 (Medium)
Top Risk Factors:
1. High capacity utilization (>90%)
2. Single facility operation
3. Credit rating downgrade (BB)
4. Missing ISO 27001 certification
5. Elevated employee turnover
Business Impact:
Annual Spend: $5.2M
Revenue at Risk: $18M
Customers Affected: 120 (15 critical accounts)
Replacement Time: 16 weeks
Criticality Score: 75/100
Mitigation Actions Required:
1. [HIGH] Qualify backup supplier within 60 days
2. [HIGH] Build 90-day safety stock
3. [MEDIUM] Conduct site visit to assess capacity
4. [MEDIUM] Request cybersecurity audit
5. [LOW] Negotiate performance guarantees in contract renewal
Contingency Plan: ACTIVATED
- Backup supplier identified: XYZ Corp
- Safety stock build: In Progress (45 days complete)
- Alternative sourcing: Under evaluation
Next Review: 30 days组合风险仪表盘:
| Supplier | Risk Score | Criticality | Spend | Status | Trend | Action Required |
|---|---|---|---|---|---|---|
| Acme Mfg | 62 (High) | Tier 1 | $5.2M | ⚠ | ↗ | Dual source |
| Beta Corp | 35 (Medium) | Tier 1 | $3.8M | ✓ | → | Monitor |
| Gamma Inc | 78 (Critical) | Tier 2 | $1.5M | ⚠⚠ | ↗ | Replace |
| Delta Ltd | 22 (Low) | Tier 3 | $0.8M | ✓ | ↘ | None |
Questions to Ask
需询问的问题
If you need more context:
- What suppliers or categories are of concern?
- Have there been recent supply disruptions?
- What risk data is currently available?
- What's the supplier criticality (spend, replaceability, impact)?
- Are there single-source dependencies?
- What's the organization's risk tolerance?
- What monitoring processes are in place?
- Any industry-specific risks? (geopolitical, regulatory)
- What's the budget for risk mitigation?
- Who are the key stakeholders for risk management?
如果需要更多背景信息:
- 哪些供应商或类别存在问题?
- 近期是否发生过供应中断?
- 当前有哪些风险数据可用?
- 供应商的关键性如何(支出、可替代性、影响)?
- 是否存在单一来源依赖?
- 企业的风险容忍度是多少?
- 已部署哪些监控流程?
- 是否存在行业特定风险?(地缘政治、监管)
- 风险缓解的预算是多少?
- 风险管理的关键利益相关者是谁?
Related Skills
相关技能
- supplier-selection: For vetting suppliers during selection process
- procurement-optimization: For optimal sourcing strategies
- strategic-sourcing: For category risk management
- spend-analysis: For concentration risk analysis
- contract-management: For contractual risk protections
- quality-management: For supplier quality monitoring
- risk-mitigation: For overall supply chain risk strategies
- supplier-selection: 用于选择阶段的供应商审核
- procurement-optimization: 用于优化采购策略
- strategic-sourcing: 用于品类风险管理
- spend-analysis: 用于集中度风险分析
- contract-management: 用于合同风险保护
- quality-management: 用于供应商质量监控
- risk-mitigation: 用于整体供应链风险策略