mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
Repository Structure:
- Move files from cluttered root directory into organized structure
- Create archive/ for archived data and scraper results
- Create bugulma/ for the complete application (frontend + backend)
- Create data/ for sample datasets and reference materials
- Create docs/ for comprehensive documentation structure
- Create scripts/ for utility scripts and API tools
Backend Implementation:
- Implement 3 missing backend endpoints identified in gap analysis:
* GET /api/v1/organizations/{id}/matching/direct - Direct symbiosis matches
* GET /api/v1/users/me/organizations - User organizations
* POST /api/v1/proposals/{id}/status - Update proposal status
- Add complete proposal domain model, repository, and service layers
- Create database migration for proposals table
- Fix CLI server command registration issue
API Documentation:
- Add comprehensive proposals.md API documentation
- Update README.md with Users and Proposals API sections
- Document all request/response formats, error codes, and business rules
Code Quality:
- Follow existing Go backend architecture patterns
- Add proper error handling and validation
- Match frontend expected response schemas
- Maintain clean separation of concerns (handler -> service -> repository)
654 lines
20 KiB
Go
654 lines
20 KiB
Go
package financial
|
||
|
||
import (
|
||
"fmt"
|
||
"math"
|
||
"time"
|
||
)
|
||
|
||
// FinancialCalculator implements the Calculator interface with proper separation of concerns
|
||
type FinancialCalculator struct {
|
||
config *Config
|
||
npvCalc NPVCalculator
|
||
irrCalc IRRCalculator
|
||
paybackCalc PaybackCalculator
|
||
sensitivityCalc SensitivityAnalyzer
|
||
riskAssessor RiskAssessor
|
||
co2Calc CO2Calculator
|
||
capexEstimator CapexEstimator
|
||
transportCalc TransportCostCalculator
|
||
}
|
||
|
||
// NewFinancialCalculator creates a new financial calculator with all dependencies
|
||
func NewFinancialCalculator(
|
||
config *Config,
|
||
npvCalc NPVCalculator,
|
||
irrCalc IRRCalculator,
|
||
paybackCalc PaybackCalculator,
|
||
sensitivityCalc SensitivityAnalyzer,
|
||
riskAssessor RiskAssessor,
|
||
co2Calc CO2Calculator,
|
||
capexEstimator CapexEstimator,
|
||
transportCalc TransportCostCalculator,
|
||
) *FinancialCalculator {
|
||
return &FinancialCalculator{
|
||
config: config,
|
||
npvCalc: npvCalc,
|
||
irrCalc: irrCalc,
|
||
paybackCalc: paybackCalc,
|
||
sensitivityCalc: sensitivityCalc,
|
||
riskAssessor: riskAssessor,
|
||
co2Calc: co2Calc,
|
||
capexEstimator: capexEstimator,
|
||
transportCalc: transportCalc,
|
||
}
|
||
}
|
||
|
||
// Calculate performs economic analysis based on the specified type
|
||
func (fc *FinancialCalculator) Calculate(
|
||
analysisType AnalysisType,
|
||
data *ResourceFlowData,
|
||
assumptions *EconomicAssumptions,
|
||
) (interface{}, error) {
|
||
|
||
// Ensure assumptions have defaults
|
||
if assumptions == nil {
|
||
assumptions = fc.getDefaultAssumptions()
|
||
}
|
||
|
||
// Perform basic economic analysis
|
||
basicAnalysis, err := fc.calculateBasicAnalysis(data, assumptions)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to calculate basic analysis: %w", err)
|
||
}
|
||
|
||
// Add analysis metadata
|
||
basicAnalysis.AnalysisType = analysisType
|
||
basicAnalysis.AnalysisDate = time.Now()
|
||
basicAnalysis.Version = "1.0.0"
|
||
|
||
switch analysisType {
|
||
case AnalysisTypeBasic:
|
||
return basicAnalysis, nil
|
||
|
||
case AnalysisTypeAdvanced:
|
||
return fc.calculateAdvancedAnalysis(basicAnalysis, data, assumptions)
|
||
|
||
case AnalysisTypeSensitivity:
|
||
return fc.calculateSensitivityAnalysis(basicAnalysis, assumptions)
|
||
|
||
default:
|
||
return nil, fmt.Errorf("unsupported analysis type: %s", analysisType)
|
||
}
|
||
}
|
||
|
||
// calculateBasicAnalysis performs the core economic calculations
|
||
func (fc *FinancialCalculator) calculateBasicAnalysis(
|
||
data *ResourceFlowData,
|
||
assumptions *EconomicAssumptions,
|
||
) (*EconomicAnalysis, error) {
|
||
|
||
// Calculate transport cost per unit
|
||
transportCostPerUnit := fc.transportCalc.CalculateTransportCost(data.ResourceType, data.DistanceKm)
|
||
|
||
// Annual savings calculation
|
||
// savings = (buyer_cost - seller_cost - transport) × annual_volume
|
||
unitSavings := data.CostIn - data.CostOut - transportCostPerUnit
|
||
annualSavings := unitSavings * data.AnnualVolume
|
||
|
||
// Estimate CAPEX
|
||
capex := fc.capexEstimator.EstimateCapex(data.ResourceType, data.DistanceKm, data.AnnualVolume)
|
||
|
||
// Estimate OPEX
|
||
opex := capex * fc.config.OpexPctOfCapex
|
||
|
||
// Calculate net annual cash flow
|
||
netAnnualCashFlow := annualSavings - opex
|
||
|
||
// Calculate NPV
|
||
npv := fc.npvCalc.CalculateNPV(capex, netAnnualCashFlow, assumptions.DiscountRate, assumptions.ProjectLifeYears)
|
||
|
||
// Calculate IRR
|
||
irr := fc.irrCalc.CalculateIRR(capex, netAnnualCashFlow, assumptions.ProjectLifeYears)
|
||
|
||
// Calculate simple payback period
|
||
payback := fc.paybackCalc.CalculatePaybackPeriod(capex, netAnnualCashFlow)
|
||
|
||
// Calculate CO₂ avoided
|
||
co2Avoided := fc.co2Calc.CalculateCO2Reduction(data.ResourceType, data.AnnualVolume)
|
||
|
||
// Determine viability
|
||
isViable := fc.assessViability(npv, irr, payback, assumptions)
|
||
|
||
// Calculate confidence score based on data completeness and risk
|
||
confidenceScore := fc.calculateConfidenceScore(data, assumptions)
|
||
|
||
return &EconomicAnalysis{
|
||
NPV: npv,
|
||
IRR: irr,
|
||
PaybackYears: payback,
|
||
AnnualSavings: annualSavings,
|
||
CapexRequired: capex,
|
||
OpexPerYear: opex,
|
||
CO2AvoidedTonnes: co2Avoided,
|
||
IsViable: isViable,
|
||
ConfidenceScore: confidenceScore,
|
||
}, nil
|
||
}
|
||
|
||
// calculateAdvancedAnalysis performs comprehensive advanced economic analysis
|
||
func (fc *FinancialCalculator) calculateAdvancedAnalysis(
|
||
basic *EconomicAnalysis,
|
||
data *ResourceFlowData,
|
||
assumptions *EconomicAssumptions,
|
||
) (*AdvancedEconomicAnalysis, error) {
|
||
|
||
// Perform sensitivity analysis
|
||
sensitivityScenarios := fc.sensitivityCalc.AnalyzeSensitivity(basic, assumptions)
|
||
|
||
// Perform risk assessment
|
||
riskAssessment := fc.riskAssessor.AssessRisk(data)
|
||
|
||
// Calculate risk-adjusted metrics
|
||
riskAdjustedNPV := fc.calculateRiskAdjustedNPV(basic.NPV, riskAssessment)
|
||
riskAdjustedIRR := fc.calculateRiskAdjustedIRR(basic.IRR, riskAssessment)
|
||
|
||
// Assess implementation complexity
|
||
implementationComplexity := fc.assessImplementationComplexity(data)
|
||
|
||
// Identify regulatory requirements
|
||
regulatoryRequirements := fc.identifyRegulatoryRequirements(data.ResourceType)
|
||
|
||
// Calculate detailed CO2 reduction breakdown
|
||
co2Breakdown := fc.calculateCO2ReductionBreakdown(data.ResourceType, data.AnnualVolume, data.DistanceKm)
|
||
|
||
// Generate mitigation strategies
|
||
mitigationStrategies := fc.generateMitigationStrategies(riskAssessment)
|
||
|
||
// Generate optimization recommendations
|
||
recommendedActions := fc.generateOptimizationRecommendations(basic, sensitivityScenarios, riskAssessment)
|
||
|
||
// Adjust confidence score based on risk and sensitivity
|
||
confidenceScore := fc.calculateAdvancedConfidenceScore(basic.ConfidenceScore, sensitivityScenarios, riskAssessment)
|
||
|
||
return &AdvancedEconomicAnalysis{
|
||
EconomicAnalysis: EconomicAnalysis{
|
||
NPV: basic.NPV,
|
||
IRR: basic.IRR,
|
||
PaybackYears: basic.PaybackYears,
|
||
AnnualSavings: basic.AnnualSavings,
|
||
CapexRequired: basic.CapexRequired,
|
||
OpexPerYear: basic.OpexPerYear,
|
||
CO2AvoidedTonnes: basic.CO2AvoidedTonnes,
|
||
IsViable: basic.IsViable,
|
||
ConfidenceScore: confidenceScore,
|
||
AnalysisDate: time.Now(),
|
||
AnalysisType: AnalysisTypeAdvanced,
|
||
Version: "2.0.0",
|
||
},
|
||
SensitivityScenarios: sensitivityScenarios,
|
||
RiskAdjustedNPV: riskAdjustedNPV,
|
||
RiskAdjustedIRR: riskAdjustedIRR,
|
||
ImplementationComplexity: implementationComplexity,
|
||
RegulatoryRequirements: regulatoryRequirements,
|
||
CO2ReductionBreakdown: co2Breakdown,
|
||
RiskProfile: *riskAssessment,
|
||
MitigationStrategies: mitigationStrategies,
|
||
RecommendedActions: recommendedActions,
|
||
}, nil
|
||
}
|
||
|
||
// calculateSensitivityAnalysis performs detailed sensitivity analysis
|
||
func (fc *FinancialCalculator) calculateSensitivityAnalysis(
|
||
basic *EconomicAnalysis,
|
||
assumptions *EconomicAssumptions,
|
||
) (*EconomicAnalysis, error) {
|
||
|
||
// Start with basic analysis
|
||
sensitivity := *basic
|
||
sensitivity.AnalysisType = AnalysisTypeSensitivity
|
||
|
||
// Perform sensitivity analysis
|
||
scenarios := fc.sensitivityCalc.AnalyzeSensitivity(basic, assumptions)
|
||
|
||
// Calculate confidence based on sensitivity results
|
||
sensitivity.ConfidenceScore = fc.calculateSensitivityConfidence(scenarios)
|
||
|
||
return &sensitivity, nil
|
||
}
|
||
|
||
// assessViability determines if the investment is economically viable
|
||
func (fc *FinancialCalculator) assessViability(npv, irr, payback float64, assumptions *EconomicAssumptions) bool {
|
||
// NPV must be positive
|
||
if npv <= 0 {
|
||
return false
|
||
}
|
||
|
||
// IRR must be greater than discount rate
|
||
if irr <= assumptions.DiscountRate*100 {
|
||
return false
|
||
}
|
||
|
||
// Payback period must be within project life
|
||
if payback >= float64(assumptions.ProjectLifeYears) {
|
||
return false
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
// calculateConfidenceScore calculates confidence in the analysis based on data quality
|
||
func (fc *FinancialCalculator) calculateConfidenceScore(data *ResourceFlowData, assumptions *EconomicAssumptions) float64 {
|
||
confidence := 1.0
|
||
|
||
// Reduce confidence if distance is very long (higher uncertainty)
|
||
if data.DistanceKm > 50 {
|
||
confidence *= 0.9
|
||
}
|
||
|
||
// Reduce confidence if volume is very low (higher per-unit cost uncertainty)
|
||
if data.AnnualVolume < 100 {
|
||
confidence *= 0.95
|
||
}
|
||
|
||
// Reduce confidence if project life is very long (higher uncertainty)
|
||
if assumptions.ProjectLifeYears > 20 {
|
||
confidence *= 0.9
|
||
}
|
||
|
||
return confidence
|
||
}
|
||
|
||
// adjustConfidenceForRisk adjusts confidence based on risk assessment
|
||
func (fc *FinancialCalculator) adjustConfidenceForRisk(confidence float64, risk *RiskAssessment) float64 {
|
||
// Reduce confidence based on overall risk level
|
||
switch risk.RiskLevel {
|
||
case "low":
|
||
return confidence * 1.0
|
||
case "medium":
|
||
return confidence * 0.9
|
||
case "high":
|
||
return confidence * 0.7
|
||
case "critical":
|
||
return confidence * 0.5
|
||
default:
|
||
return confidence * 0.8
|
||
}
|
||
}
|
||
|
||
// calculateSensitivityConfidence calculates confidence based on sensitivity analysis
|
||
func (fc *FinancialCalculator) calculateSensitivityConfidence(scenarios []SensitivityScenario) float64 {
|
||
// Analyze how NPV changes with parameter variations
|
||
var totalVariation float64
|
||
var variationCount int
|
||
|
||
for _, scenario := range scenarios {
|
||
if scenario.VariableName == "discount_rate" || scenario.VariableName == "capex" {
|
||
totalVariation += scenario.ImpactOnNPV
|
||
variationCount++
|
||
}
|
||
}
|
||
|
||
if variationCount == 0 {
|
||
return 0.8 // Default confidence
|
||
}
|
||
|
||
avgVariation := totalVariation / float64(variationCount)
|
||
|
||
// Lower confidence if NPV is highly sensitive to key parameters
|
||
if avgVariation > 0.3 { // More than 30% variation
|
||
return 0.6
|
||
} else if avgVariation > 0.1 { // More than 10% variation
|
||
return 0.8
|
||
}
|
||
|
||
return 0.9
|
||
}
|
||
|
||
// calculateRiskAdjustedNPV adjusts NPV for risk
|
||
func (fc *FinancialCalculator) calculateRiskAdjustedNPV(npv float64, risk *RiskAssessment) float64 {
|
||
riskAdjustment := 1.0
|
||
switch risk.RiskLevel {
|
||
case "low":
|
||
riskAdjustment = 0.95
|
||
case "medium":
|
||
riskAdjustment = 0.85
|
||
case "high":
|
||
riskAdjustment = 0.7
|
||
case "critical":
|
||
riskAdjustment = 0.5
|
||
}
|
||
return npv * riskAdjustment
|
||
}
|
||
|
||
// calculateRiskAdjustedIRR adjusts IRR for risk
|
||
func (fc *FinancialCalculator) calculateRiskAdjustedIRR(irr float64, risk *RiskAssessment) float64 {
|
||
riskAdjustment := 0.0
|
||
switch risk.RiskLevel {
|
||
case "low":
|
||
riskAdjustment = 0.02 // +2%
|
||
case "medium":
|
||
riskAdjustment = -0.01 // -1%
|
||
case "high":
|
||
riskAdjustment = -0.05 // -5%
|
||
case "critical":
|
||
riskAdjustment = -0.10 // -10%
|
||
}
|
||
return irr - riskAdjustment
|
||
}
|
||
|
||
// assessImplementationComplexity evaluates how complex it would be to implement this match
|
||
func (fc *FinancialCalculator) assessImplementationComplexity(data *ResourceFlowData) ImplementationComplexity {
|
||
complexity := ImplementationComplexity{
|
||
Score: 1.0, // Base score
|
||
TechnicalChallenges: []string{},
|
||
ResourceRequirements: []string{},
|
||
TimelineEstimate: "3-6 months",
|
||
}
|
||
|
||
// Distance affects complexity
|
||
if data.DistanceKm > 100 {
|
||
complexity.Score += 0.3
|
||
complexity.TechnicalChallenges = append(complexity.TechnicalChallenges, "Long-distance transport logistics")
|
||
}
|
||
if data.DistanceKm > 500 {
|
||
complexity.Score += 0.5
|
||
complexity.TechnicalChallenges = append(complexity.TechnicalChallenges, "International/cross-border requirements")
|
||
complexity.TimelineEstimate = "6-12 months"
|
||
}
|
||
|
||
// Volume affects scale
|
||
if data.AnnualVolume > 10000 {
|
||
complexity.Score += 0.2
|
||
complexity.ResourceRequirements = append(complexity.ResourceRequirements, "Large-scale infrastructure investment")
|
||
}
|
||
|
||
// Resource type affects technical requirements
|
||
switch data.ResourceType {
|
||
case "heat", "steam":
|
||
complexity.TechnicalChallenges = append(complexity.TechnicalChallenges, "Thermal energy transfer systems")
|
||
case "wastewater":
|
||
complexity.TechnicalChallenges = append(complexity.TechnicalChallenges, "Water quality monitoring and treatment")
|
||
case "biowaste":
|
||
complexity.TechnicalChallenges = append(complexity.TechnicalChallenges, "Organic waste processing equipment")
|
||
}
|
||
|
||
return complexity
|
||
}
|
||
|
||
// identifyRegulatoryRequirements identifies applicable regulations for the resource type
|
||
func (fc *FinancialCalculator) identifyRegulatoryRequirements(resourceType string) []RegulatoryRequirement {
|
||
var requirements []RegulatoryRequirement
|
||
|
||
switch resourceType {
|
||
case "heat", "steam":
|
||
requirements = append(requirements, RegulatoryRequirement{
|
||
Type: "Energy Trading License",
|
||
Description: "Required for commercial energy exchange",
|
||
EstimatedCost: 50000,
|
||
TimeToObtain: "3-6 months",
|
||
})
|
||
case "wastewater":
|
||
requirements = append(requirements, RegulatoryRequirement{
|
||
Type: "Environmental Permit",
|
||
Description: "Wastewater discharge and quality standards",
|
||
EstimatedCost: 25000,
|
||
TimeToObtain: "2-4 months",
|
||
})
|
||
case "biowaste":
|
||
requirements = append(requirements, RegulatoryRequirement{
|
||
Type: "Waste Management License",
|
||
Description: "Organic waste processing authorization",
|
||
EstimatedCost: 15000,
|
||
TimeToObtain: "1-3 months",
|
||
})
|
||
}
|
||
|
||
// Common requirements
|
||
requirements = append(requirements, RegulatoryRequirement{
|
||
Type: "Contract Registration",
|
||
Description: "Legal contract registration with local authorities",
|
||
EstimatedCost: 5000,
|
||
TimeToObtain: "1 month",
|
||
})
|
||
|
||
return requirements
|
||
}
|
||
|
||
// calculateCO2ReductionBreakdown provides detailed CO2 reduction analysis
|
||
func (fc *FinancialCalculator) calculateCO2ReductionBreakdown(resourceType string, annualVolume, distanceKm float64) CO2ReductionBreakdown {
|
||
breakdown := CO2ReductionBreakdown{
|
||
TotalTonnes: 0,
|
||
Categories: []CO2Category{},
|
||
}
|
||
|
||
switch resourceType {
|
||
case "heat", "steam":
|
||
// Avoided grid electricity for heating
|
||
gridAvoided := annualVolume * fc.config.GridEmissionFactor * fc.config.HeatEfficiency
|
||
breakdown.Categories = append(breakdown.Categories, CO2Category{
|
||
Name: "Grid Electricity Avoidance",
|
||
Tonnes: gridAvoided,
|
||
Percentage: 0,
|
||
})
|
||
|
||
// Transport emissions (diesel trucks vs pipeline)
|
||
transportAvoided := fc.calculateTransportEmissionAvoidance(resourceType, annualVolume, distanceKm)
|
||
breakdown.Categories = append(breakdown.Categories, CO2Category{
|
||
Name: "Transport Emission Reduction",
|
||
Tonnes: transportAvoided,
|
||
Percentage: 0,
|
||
})
|
||
|
||
case "wastewater":
|
||
// Water treatment energy savings
|
||
treatmentEnergy := annualVolume * fc.config.WaterTreatmentKwh / 1000 // Convert to MWh
|
||
treatmentAvoided := treatmentEnergy * fc.config.GridEmissionFactor
|
||
breakdown.Categories = append(breakdown.Categories, CO2Category{
|
||
Name: "Water Treatment Energy Savings",
|
||
Tonnes: treatmentAvoided,
|
||
Percentage: 0,
|
||
})
|
||
|
||
case "biowaste":
|
||
// Landfill methane avoidance
|
||
methaneAvoided := annualVolume * fc.config.WasteDiversionCo2
|
||
breakdown.Categories = append(breakdown.Categories, CO2Category{
|
||
Name: "Landfill Methane Reduction",
|
||
Tonnes: methaneAvoided,
|
||
Percentage: 0,
|
||
})
|
||
|
||
// Compost benefits (carbon sequestration)
|
||
sequestration := annualVolume * fc.config.CompostCarbonSeq // Assume 0.1 t CO2/tonne compost
|
||
breakdown.Categories = append(breakdown.Categories, CO2Category{
|
||
Name: "Carbon Sequestration",
|
||
Tonnes: sequestration,
|
||
Percentage: 0,
|
||
})
|
||
}
|
||
|
||
// Calculate total and percentages
|
||
for i := range breakdown.Categories {
|
||
breakdown.TotalTonnes += breakdown.Categories[i].Tonnes
|
||
}
|
||
for i := range breakdown.Categories {
|
||
if breakdown.TotalTonnes > 0 {
|
||
breakdown.Categories[i].Percentage = breakdown.Categories[i].Tonnes / breakdown.TotalTonnes * 100
|
||
}
|
||
}
|
||
|
||
return breakdown
|
||
}
|
||
|
||
// calculateTransportEmissionAvoidance calculates CO2 savings from reduced transport
|
||
func (fc *FinancialCalculator) calculateTransportEmissionAvoidance(resourceType string, annualVolume, distanceKm float64) float64 {
|
||
// Assume traditional transport would be by truck
|
||
// Estimate truck trips needed for traditional transport
|
||
var truckEfficiency float64
|
||
switch resourceType {
|
||
case "heat", "steam":
|
||
truckEfficiency = 0.1 // 10% of energy lost in transport
|
||
default:
|
||
truckEfficiency = 0.05 // 5% loss for other resources
|
||
}
|
||
|
||
// CO2 per km for truck transport (assume diesel truck: 0.0005 tonnes CO2 per km)
|
||
truckEmissionFactor := 0.0005
|
||
traditionalTransport := annualVolume * truckEfficiency * distanceKm * truckEmissionFactor * 365 // Daily transport
|
||
|
||
return traditionalTransport
|
||
}
|
||
|
||
// generateMitigationStrategies provides risk mitigation recommendations
|
||
func (fc *FinancialCalculator) generateMitigationStrategies(risk *RiskAssessment) []string {
|
||
strategies := []string{}
|
||
|
||
switch risk.RiskLevel {
|
||
case "high", "critical":
|
||
strategies = append(strategies,
|
||
"Implement comprehensive monitoring and control systems",
|
||
"Establish contingency budgets (15-20% of CAPEX)",
|
||
"Develop detailed risk management plan with regular reviews",
|
||
"Consider phased implementation to reduce exposure",
|
||
)
|
||
case "medium":
|
||
strategies = append(strategies,
|
||
"Regular performance monitoring and reporting",
|
||
"Maintain contingency reserves",
|
||
"Establish clear success metrics and KPIs",
|
||
)
|
||
default:
|
||
strategies = append(strategies,
|
||
"Standard project management practices",
|
||
"Regular progress reviews",
|
||
)
|
||
}
|
||
|
||
// Add resource-type specific strategies
|
||
if risk.PrimaryRisks != nil {
|
||
for _, riskFactor := range risk.PrimaryRisks {
|
||
switch riskFactor {
|
||
case "technical_failure":
|
||
strategies = append(strategies, "Redundant system design with backup capacity")
|
||
case "regulatory_changes":
|
||
strategies = append(strategies, "Legal consultation and regulatory monitoring service")
|
||
case "market_volatility":
|
||
strategies = append(strategies, "Flexible contract terms with price adjustment clauses")
|
||
}
|
||
}
|
||
}
|
||
|
||
return strategies
|
||
}
|
||
|
||
// generateOptimizationRecommendations provides actionable optimization suggestions
|
||
func (fc *FinancialCalculator) generateOptimizationRecommendations(
|
||
basic *EconomicAnalysis,
|
||
sensitivityScenarios []SensitivityScenario,
|
||
risk *RiskAssessment,
|
||
) []RecommendedAction {
|
||
|
||
recommendations := []RecommendedAction{}
|
||
|
||
// NPV optimization
|
||
if basic.NPV > 0 {
|
||
recommendations = append(recommendations, RecommendedAction{
|
||
Priority: "high",
|
||
Action: "Maximize NPV through operational efficiency improvements",
|
||
ExpectedImpact: "5-15% NPV increase",
|
||
Timeframe: "6-12 months",
|
||
})
|
||
}
|
||
|
||
// Payback period optimization
|
||
if basic.PaybackYears > 5 {
|
||
recommendations = append(recommendations, RecommendedAction{
|
||
Priority: "high",
|
||
Action: "Accelerate payback through phased implementation",
|
||
ExpectedImpact: "20-30% faster payback",
|
||
Timeframe: "3-6 months",
|
||
})
|
||
}
|
||
|
||
// Risk mitigation
|
||
if risk.RiskLevel == "high" || risk.RiskLevel == "critical" {
|
||
recommendations = append(recommendations, RecommendedAction{
|
||
Priority: "high",
|
||
Action: "Implement comprehensive risk mitigation plan",
|
||
ExpectedImpact: "30-50% risk reduction",
|
||
Timeframe: "1-3 months",
|
||
})
|
||
}
|
||
|
||
// Cost reduction based on sensitivity analysis
|
||
for _, scenario := range sensitivityScenarios {
|
||
if scenario.VariableName == "capex" && scenario.RiskLevel == "high" {
|
||
recommendations = append(recommendations, RecommendedAction{
|
||
Priority: "medium",
|
||
Action: "Explore alternative technology options to reduce CAPEX",
|
||
ExpectedImpact: "10-25% CAPEX reduction",
|
||
Timeframe: "2-4 months",
|
||
})
|
||
}
|
||
}
|
||
|
||
return recommendations
|
||
}
|
||
|
||
// calculateAdvancedConfidenceScore provides more sophisticated confidence calculation
|
||
func (fc *FinancialCalculator) calculateAdvancedConfidenceScore(
|
||
baseConfidence float64,
|
||
sensitivityScenarios []SensitivityScenario,
|
||
risk *RiskAssessment,
|
||
) float64 {
|
||
|
||
confidence := baseConfidence
|
||
|
||
// Reduce confidence based on sensitivity volatility
|
||
var totalSensitivityImpact float64
|
||
var highImpactCount int
|
||
for _, scenario := range sensitivityScenarios {
|
||
totalSensitivityImpact += math.Abs(scenario.ImpactOnNPV)
|
||
if scenario.RiskLevel == "high" || scenario.RiskLevel == "critical" {
|
||
highImpactCount++
|
||
}
|
||
}
|
||
|
||
if len(sensitivityScenarios) > 0 {
|
||
avgSensitivityImpact := totalSensitivityImpact / float64(len(sensitivityScenarios))
|
||
confidence *= (1 - avgSensitivityImpact*0.5) // Reduce confidence by sensitivity impact
|
||
}
|
||
|
||
// Further reduce confidence based on high-impact scenarios
|
||
if highImpactCount > 0 {
|
||
confidence *= (1 - float64(highImpactCount)/float64(len(sensitivityScenarios))*0.3)
|
||
}
|
||
|
||
// Adjust for risk level
|
||
switch risk.RiskLevel {
|
||
case "medium":
|
||
confidence *= 0.9
|
||
case "high":
|
||
confidence *= 0.7
|
||
case "critical":
|
||
confidence *= 0.5
|
||
}
|
||
|
||
// Ensure confidence doesn't go below 0.1
|
||
if confidence < 0.1 {
|
||
confidence = 0.1
|
||
}
|
||
|
||
return confidence
|
||
}
|
||
|
||
// getDefaultAssumptions returns default economic assumptions
|
||
func (fc *FinancialCalculator) getDefaultAssumptions() *EconomicAssumptions {
|
||
return &EconomicAssumptions{
|
||
DiscountRate: fc.config.DefaultDiscountRate,
|
||
ProjectLifeYears: fc.config.DefaultProjectLife,
|
||
OperatingHoursYear: 8760, // 24/7 operation
|
||
}
|
||
}
|