Currency Risk Management: Protecting Against Rate Fluctuations

Implement comprehensive currency risk management strategies to protect your business from exchange rate volatility.

Currency Risk Management: Protecting Against Rate Fluctuations
August 15, 2025
52 min read
Currency Exchange

Currency Risk Management: Protecting Against Rate Fluctuations


Currency risk management is essential for businesses operating in multiple currencies. Implementing effective hedging strategies and risk controls protects against adverse exchange rate movements while enabling global growth.


Currency Risk Management Overview

Currency Risk Management Overview


Business Impact

  • User experience enhancement
  • Operational efficiency gains
  • Cost optimization opportunities
  • Risk mitigation strategies

Practical Implementation Examples


Currency Risk Assessment Engine


// Production-ready currency risk assessment engine for comprehensive risk analysis
interface CurrencyPosition {
  currency: string
  amount: number
  baseCurrency: string
  positionType: 'asset' | 'liability' | 'derivative'
  maturityDate?: number
  hedgeRatio?: number
}

interface MarketData {
  currencyPair: string
  bid: number
  ask: number
  timestamp: number
  volume: number
  volatility: number
}

interface RiskMetrics {
  var95: number // Value at Risk 95%
  var99: number // Value at Risk 99%
  expectedShortfall: number
  beta: number // Sensitivity to market movements
  delta: number // Price sensitivity
  gamma: number // Rate of change of delta
  vega: number // Volatility sensitivity
  theta: number // Time decay
  rho: number // Interest rate sensitivity
}

interface RiskAssessment {
  portfolioId: string
  assessmentDate: number
  totalExposure: number
  riskByCurrency: Record<string, {
    exposure: number
    var95: number
    var99: number
    concentrationRisk: number
    liquidityRisk: number
  }>
  correlationMatrix: Record<string, number>
  stressTestResults: {
    scenario: string
    impact: number
    probability: number
  }[]
  riskLimits: {
    maxExposurePerCurrency: number
    maxConcentration: number
    maxVaR95: number
    maxDrawdown: number
  }
  recommendations: string[]
  riskLevel: 'low' | 'medium' | 'high' | 'critical'
}

class CurrencyRiskAssessmentEngine {
  private positions: Map<string, CurrencyPosition[]> = new Map()
  private marketData: Map<string, MarketData[]> = new Map()
  private riskCache: Map<string, { metrics: RiskMetrics; timestamp: number }> = new Map()
  private volatilityModels: Map<string, any> = new Map()

  constructor() {
    this.initializeVolatilityModels()
  }

  async assessPortfolioRisk(portfolioId: string): Promise<RiskAssessment> {
    const positions = this.positions.get(portfolioId) || []
    if (positions.length === 0) {
      throw new Error(`No positions found for portfolio ${portfolioId}`)
    }

    try {
      // Calculate total exposure by currency
      const exposureByCurrency = this.calculateExposureByCurrency(positions)

      // Get current market data
      const marketData = await this.getCurrentMarketData(Object.keys(exposureByCurrency))

      // Calculate risk metrics for each currency
      const riskByCurrency = await this.calculateRiskByCurrency(exposureByCurrency, marketData)

      // Calculate correlation matrix
      const correlationMatrix = this.calculateCorrelationMatrix(marketData)

      // Perform stress testing
      const stressTestResults = await this.performStressTests(positions, marketData)

      // Check risk limits
      const riskLimits = this.getRiskLimits(portfolioId)

      // Generate recommendations
      const recommendations = this.generateRiskRecommendations(riskByCurrency, riskLimits)

      // Determine overall risk level
      const riskLevel = this.determineRiskLevel(riskByCurrency, stressTestResults)

      return {
        portfolioId,
        assessmentDate: Date.now(),
        totalExposure: Object.values(exposureByCurrency).reduce((sum, exp) => sum + exp, 0),
        riskByCurrency,
        correlationMatrix,
        stressTestResults,
        riskLimits,
        recommendations,
        riskLevel
      }

    } catch (error) {
      console.error('Portfolio risk assessment failed:', error)

      return {
        portfolioId,
        assessmentDate: Date.now(),
        totalExposure: 0,
        riskByCurrency: {},
        correlationMatrix: {},
        stressTestResults: [],
        riskLimits: {
          maxExposurePerCurrency: 0,
          maxConcentration: 0,
          maxVaR95: 0,
          maxDrawdown: 0
        },
        recommendations: ['Assessment failed - manual review required'],
        riskLevel: 'critical'
      }
    }
  }

  private calculateExposureByCurrency(positions: CurrencyPosition[]): Record<string, number> {
    return positions.reduce((acc, position) => {
      const currentExposure = acc[position.currency] || 0

      if (position.positionType === 'asset') {
        acc[position.currency] = currentExposure + position.amount
      } else if (position.positionType === 'liability') {
        acc[position.currency] = currentExposure - position.amount
      } else if (position.positionType === 'derivative') {
        // For derivatives, calculate net exposure based on hedge ratio
        const derivativeExposure = position.amount * (position.hedgeRatio || 1)
        acc[position.currency] = currentExposure + derivativeExposure
      }

      return acc
    }, {} as Record<string, number>)
  }

  private async getCurrentMarketData(currencies: string[]): Promise<Record<string, MarketData>> {
    const marketData: Record<string, MarketData> = {}

    // In production, fetch from real-time market data providers
    // For demo, generate mock data
    for (const currency of currencies) {
      marketData[currency] = {
        currencyPair: `USD/${currency}`,
        bid: 1 + (Math.random() - 0.5) * 0.1, // Random rate around 1
        ask: 1 + (Math.random() - 0.5) * 0.1 + 0.001,
        timestamp: Date.now(),
        volume: Math.floor(Math.random() * 1000000),
        volatility: 0.01 + Math.random() * 0.05 // 1-6% volatility
      }
    }

    return marketData
  }

  private async calculateRiskByCurrency(
    exposureByCurrency: Record<string, number>,
    marketData: Record<string, MarketData>
  ): Promise<Record<string, any>> {
    const riskByCurrency: Record<string, any> = {}

    for (const [currency, exposure] of Object.entries(exposureByCurrency)) {
      const data = marketData[currency]
      if (!data) continue

      // Calculate VaR using historical simulation
      const var95 = this.calculateVaR(exposure, data.volatility, 0.95)
      const var99 = this.calculateVaR(exposure, data.volatility, 0.99)

      // Calculate concentration risk (percentage of total portfolio)
      const totalExposure = Object.values(exposureByCurrency).reduce((sum, exp) => sum + Math.abs(exp), 0)
      const concentrationRisk = Math.abs(exposure) / totalExposure

      // Assess liquidity risk based on market volume and position size
      const liquidityRisk = this.assessLiquidityRisk(Math.abs(exposure), data.volume)

      riskByCurrency[currency] = {
        exposure,
        var95,
        var99,
        concentrationRisk,
        liquidityRisk
      }
    }

    return riskByCurrency
  }

  private calculateVaR(exposure: number, volatility: number, confidence: number): number {
    // Simplified VaR calculation using normal distribution
    // In production, use historical simulation or Monte Carlo
    const zScore = confidence === 0.95 ? 1.645 : 2.326
    return Math.abs(exposure) * volatility * zScore * Math.sqrt(1) // Assuming 1-day horizon
  }

  private assessLiquidityRisk(positionSize: number, marketVolume: number): number {
    const ratio = positionSize / marketVolume

    if (ratio < 0.001) return 0.1 // Very liquid
    if (ratio < 0.01) return 0.3  // Moderately liquid
    if (ratio < 0.1) return 0.7   // Low liquidity
    return 1.0 // Illiquid
  }

  private calculateCorrelationMatrix(marketData: Record<string, MarketData>): Record<string, number> {
    // Simplified correlation calculation
    // In production, use proper time series analysis
    const correlations: Record<string, number> = {}

    const currencies = Object.keys(marketData)
    for (let i = 0; i < currencies.length; i++) {
      for (let j = i + 1; j < currencies.length; j++) {
        const curr1 = currencies[i]
        const curr2 = currencies[j]

        // Generate mock correlation based on currency pairs
        let correlation = Math.random() * 0.6 + 0.2 // 0.2 to 0.8 range

        // Adjust for regional correlations
        if (this.areRegionalCurrencies(curr1, curr2)) {
          correlation += 0.3 // Higher correlation for regional pairs
        }

        correlations[`${curr1}-${curr2}`] = Math.min(correlation, 1.0)
      }
    }

    return correlations
  }

  private areRegionalCurrencies(curr1: string, curr2: string): boolean {
    const europeanCurrencies = ['EUR', 'GBP', 'CHF', 'SEK', 'NOK', 'DKK']
    const asianCurrencies = ['JPY', 'CNY', 'KRW', 'SGD', 'HKD']

    const curr1Regional = europeanCurrencies.includes(curr1) && europeanCurrencies.includes(curr2)
    const curr2Regional = asianCurrencies.includes(curr1) && asianCurrencies.includes(curr2)

    return curr1Regional || curr2Regional
  }

  private async performStressTests(
    positions: CurrencyPosition[],
    marketData: Record<string, MarketData>
  ): Promise<Array<{ scenario: string; impact: number; probability: number }>> {
    const scenarios = [
      { name: 'Major Currency Crisis', impact: -0.15, probability: 0.05 },
      { name: 'Interest Rate Shock', impact: -0.08, probability: 0.15 },
      { name: 'Geopolitical Event', impact: -0.10, probability: 0.10 },
      { name: 'Economic Recession', impact: -0.12, probability: 0.08 },
      { name: 'Trade War Escalation', impact: -0.06, probability: 0.20 }
    ]

    return scenarios.map(scenario => {
      // Calculate portfolio impact for each scenario
      const totalImpact = positions.reduce((sum, position) => {
        const currencyData = marketData[position.currency]
        if (!currencyData) return sum

        const positionImpact = position.amount * scenario.impact
        return sum + positionImpact
      }, 0)

      return {
        scenario: scenario.name,
        impact: Math.abs(totalImpact),
        probability: scenario.probability
      }
    })
  }

  private getRiskLimits(portfolioId: string): RiskAssessment['riskLimits'] {
    // In production, load from portfolio configuration
    return {
      maxExposurePerCurrency: 1000000, // $1M per currency
      maxConcentration: 0.25, // 25% max concentration
      maxVaR95: 50000, // $50K max daily loss at 95% confidence
      maxDrawdown: 0.15 // 15% max drawdown
    }
  }

  private generateRiskRecommendations(
    riskByCurrency: Record<string, any>,
    riskLimits: RiskAssessment['riskLimits']
  ): string[] {
    const recommendations: string[] = []

    for (const [currency, risk] of Object.entries(riskByCurrency)) {
      if (risk.concentrationRisk > riskLimits.maxConcentration) {
        recommendations.push(`Reduce concentration in ${currency} - currently ${(risk.concentrationRisk * 100).toFixed(1)}%`)
      }

      if (risk.var95 > riskLimits.maxVaR95) {
        recommendations.push(`High VaR in ${currency} - consider hedging strategies`)
      }

      if (risk.liquidityRisk > 0.7) {
        recommendations.push(`Low liquidity in ${currency} - monitor position sizing`)
      }
    }

    if (recommendations.length === 0) {
      recommendations.push('Portfolio risk levels are within acceptable limits')
    }

    return recommendations
  }

  private determineRiskLevel(
    riskByCurrency: Record<string, any>,
    stressTestResults: Array<{ scenario: string; impact: number; probability: number }>
  ): 'low' | 'medium' | 'high' | 'critical' {
    const highRiskCount = Object.values(riskByCurrency).filter((risk: any) =>
      risk.var95 > 10000 || risk.concentrationRisk > 0.2
    ).length

    const criticalStressTest = stressTestResults.some(test => test.impact > 100000)

    if (criticalStressTest || highRiskCount > 2) return 'critical'
    if (highRiskCount > 0 || stressTestResults.some(test => test.impact > 50000)) return 'high'
    if (highRiskCount === 0 && stressTestResults.some(test => test.impact > 25000)) return 'medium'

    return 'low'
  }

  private initializeVolatilityModels(): void {
    // Initialize GARCH or other volatility models for each currency
    const majorCurrencies = ['EUR', 'GBP', 'JPY', 'CHF', 'CAD', 'AUD']

    majorCurrencies.forEach(currency => {
      this.volatilityModels.set(currency, {
        model: 'GARCH(1,1)',
        parameters: {
          omega: 0.0001,
          alpha: 0.1,
          beta: 0.8
        }
      })
    })
  }

  // Add position to portfolio
  addPosition(portfolioId: string, position: CurrencyPosition): void {
    if (!this.positions.has(portfolioId)) {
      this.positions.set(portfolioId, [])
    }

    this.positions.get(portfolioId)!.push(position)

    // Clear risk cache when positions change
    this.riskCache.delete(portfolioId)
  }

  // Remove position from portfolio
  removePosition(portfolioId: string, currency: string, positionType: string): boolean {
    const positions = this.positions.get(portfolioId)
    if (!positions) return false

    const index = positions.findIndex(p => p.currency === currency && p.positionType === positionType)
    if (index >= 0) {
      positions.splice(index, 1)

      // Clear risk cache when positions change
      this.riskCache.delete(portfolioId)
      return true
    }

    return false
  }

  // Get portfolio summary
  getPortfolioSummary(portfolioId: string): {
    totalPositions: number
    currencies: string[]
    totalExposure: number
    lastAssessment?: RiskAssessment
  } {
    const positions = this.positions.get(portfolioId) || []
    const currencies = [...new Set(positions.map(p => p.currency))]

    const totalExposure = positions.reduce((sum, position) => {
      return sum + Math.abs(position.amount)
    }, 0)

    const lastAssessment = this.riskCache.get(portfolioId)?.metrics

    return {
      totalPositions: positions.length,
      currencies,
      totalExposure,
      lastAssessment
    }
  }

  // Update market data
  updateMarketData(currency: string, data: MarketData): void {
    if (!this.marketData.has(currency)) {
      this.marketData.set(currency, [])
    }

    const currencyData = this.marketData.get(currency)!
    currencyData.push(data)

    // Keep only last 1000 data points
    if (currencyData.length > 1000) {
      currencyData.shift()
    }

    // Clear risk cache when market data updates
    this.riskCache.clear()
  }
}

// Initialize currency risk assessment engine
const riskAssessmentEngine = new CurrencyRiskAssessmentEngine()

// Portfolio risk assessment endpoint
app.post('/api/risk/assess-portfolio', async (req, res) => {
  try {
    const { portfolioId } = req.body

    if (!portfolioId) {
      return res.status(400).json({ error: 'portfolioId required' })
    }

    const assessment = await riskAssessmentEngine.assessPortfolioRisk(portfolioId)

    res.json({
      assessment,
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('Portfolio risk assessment error:', error)
    res.status(500).json({ error: 'Risk assessment failed' })
  }
})

// Add position endpoint
app.post('/api/risk/add-position', (req, res) => {
  try {
    const { portfolioId, currency, amount, baseCurrency, positionType, maturityDate, hedgeRatio } = req.body

    if (!portfolioId || !currency || !amount || !baseCurrency || !positionType) {
      return res.status(400).json({
        error: 'portfolioId, currency, amount, baseCurrency, and positionType required'
      })
    }

    const position: CurrencyPosition = {
      currency,
      amount,
      baseCurrency,
      positionType,
      maturityDate,
      hedgeRatio
    }

    riskAssessmentEngine.addPosition(portfolioId, position)

    res.json({
      success: true,
      message: 'Position added successfully',
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('Add position error:', error)
    res.status(500).json({ error: 'Failed to add position' })
  }
})

// Portfolio summary endpoint
app.get('/api/risk/portfolio-summary/:portfolioId', (req, res) => {
  try {
    const { portfolioId } = req.params

    const summary = riskAssessmentEngine.getPortfolioSummary(portfolioId)

    res.json({
      summary,
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('Portfolio summary error:', error)
    res.status(500).json({ error: 'Failed to get portfolio summary' })
  }
})

console.log('Currency Risk Assessment Engine initialized')

Hedging Strategy Automation System


// Advanced hedging strategy automation for currency risk management
interface HedgingStrategy {
  strategyId: string
  name: string
  description: string
  type: 'static' | 'dynamic' | 'option_based' | 'forward_based'
  parameters: {
    targetHedgeRatio: number
    rebalanceFrequency: 'daily' | 'weekly' | 'monthly'
    triggerThreshold: number
    maxPosition: number
  }
  currencies: string[]
  status: 'active' | 'inactive' | 'paused'
  performance: {
    pnl: number
    sharpeRatio: number
    maxDrawdown: number
    winRate: number
  }
}

interface HedgePosition {
  positionId: string
  strategyId: string
  instrument: 'forward' | 'option' | 'swap' | 'futures'
  currencyPair: string
  notional: number
  strike?: number
  expiry: number
  hedgeDirection: 'long' | 'short'
  entryPrice: number
  currentPrice?: number
  pnl: number
  status: 'open' | 'closed' | 'expired'
}

interface RebalancingDecision {
  strategyId: string
  action: 'rebalance' | 'close' | 'open' | 'maintain'
  reason: string
  targetPositions: {
    currencyPair: string
    targetHedgeRatio: number
    currentHedgeRatio: number
    requiredAdjustment: number
  }[]
  expectedImpact: {
    cost: number
    riskReduction: number
    liquidityImpact: number
  }
}

class HedgingStrategyAutomation {
  private strategies: Map<string, HedgingStrategy> = new Map()
  private positions: Map<string, HedgePosition> = new Map()
  private marketData: Map<string, MarketData> = new Map()
  private portfolioExposures: Map<string, Record<string, number>> = new Map()

  constructor() {
    this.initializeDefaultStrategies()
    this.startAutomatedRebalancing()
  }

  // Create custom hedging strategy
  createStrategy(strategy: Omit<HedgingStrategy, 'strategyId' | 'performance'>): string {
    const strategyId = `strategy_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`

    const newStrategy: HedgingStrategy = {
      ...strategy,
      strategyId,
      performance: {
        pnl: 0,
        sharpeRatio: 0,
        maxDrawdown: 0,
        winRate: 0
      }
    }

    this.strategies.set(strategyId, newStrategy)

    console.log(`Created hedging strategy: ${strategy.name} (${strategyId})`)

    return strategyId
  }

  // Execute hedging strategy for portfolio
  async executeStrategy(strategyId: string, portfolioId: string): Promise<HedgePosition[]> {
    const strategy = this.strategies.get(strategyId)
    if (!strategy || strategy.status !== 'active') {
      throw new Error(`Strategy ${strategyId} not found or inactive`)
    }

    const portfolioExposure = this.portfolioExposures.get(portfolioId) || {}
    const newPositions: HedgePosition[] = []

    for (const currency of strategy.currencies) {
      if (!portfolioExposure[currency]) continue

      const exposure = portfolioExposure[currency]
      const requiredHedge = this.calculateRequiredHedge(exposure, strategy)

      if (Math.abs(requiredHedge) > strategy.parameters.triggerThreshold) {
        const hedgePosition = await this.createHedgePosition(strategy, currency, requiredHedge)
        if (hedgePosition) {
          newPositions.push(hedgePosition)
          this.positions.set(hedgePosition.positionId, hedgePosition)
        }
      }
    }

    return newPositions
  }

  private calculateRequiredHedge(exposure: number, strategy: HedgingStrategy): number {
    const currentHedgeRatio = this.getCurrentHedgeRatio(strategy.strategyId, Object.keys({ exposure })[0])
    const requiredHedgeRatio = strategy.parameters.targetHedgeRatio

    return exposure * (requiredHedgeRatio - currentHedgeRatio)
  }

  private getCurrentHedgeRatio(strategyId: string, currency: string): number {
    const strategyPositions = Array.from(this.positions.values())
      .filter(p => p.strategyId === strategyId && p.currencyPair.includes(currency))

    if (strategyPositions.length === 0) return 0

    const totalHedgeNotional = strategyPositions.reduce((sum, pos) => sum + pos.notional, 0)
    // In production, get actual portfolio exposure for this currency

    return totalHedgeNotional / 1000000 // Simplified calculation
  }

  private async createHedgePosition(
    strategy: HedgingStrategy,
    currency: string,
    requiredHedge: number
  ): Promise<HedgePosition | null> {
    try {
      const marketData = this.marketData.get(`USD/${currency}`)
      if (!marketData) return null

      const positionId = `hedge_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`

      // Determine hedge instrument based on strategy type
      const instrument = this.selectHedgeInstrument(strategy, currency, requiredHedge)

      const hedgePosition: HedgePosition = {
        positionId,
        strategyId: strategy.strategyId,
        instrument,
        currencyPair: `USD/${currency}`,
        notional: Math.abs(requiredHedge),
        strike: instrument === 'option' ? marketData.ask * (1 + (Math.random() - 0.5) * 0.1) : undefined,
        expiry: Date.now() + this.getExpiryTimeframe(strategy.parameters.rebalanceFrequency),
        hedgeDirection: requiredHedge > 0 ? 'long' : 'short',
        entryPrice: marketData.ask,
        pnl: 0,
        status: 'open'
      }

      return hedgePosition

    } catch (error) {
      console.error('Failed to create hedge position:', error)
      return null
    }
  }

  private selectHedgeInstrument(strategy: HedgingStrategy, currency: string, requiredHedge: number): HedgePosition['instrument'] {
    switch (strategy.type) {
      case 'option_based':
        return 'option'
      case 'forward_based':
        return 'forward'
      case 'dynamic':
        // Dynamic selection based on market conditions
        return Math.abs(requiredHedge) > 100000 ? 'swap' : 'forward'
      default:
        return 'forward'
    }
  }

  private getExpiryTimeframe(frequency: string): number {
    const timeframes = {
      'daily': 24 * 60 * 60 * 1000,
      'weekly': 7 * 24 * 60 * 60 * 1000,
      'monthly': 30 * 24 * 60 * 60 * 1000
    }

    return timeframes[frequency as keyof typeof timeframes] || timeframes.daily
  }

  // Automated rebalancing system
  private startAutomatedRebalancing(): void {
    // Run rebalancing every hour
    setInterval(() => {
      this.performAutomatedRebalancing()
    }, 60 * 60 * 1000)
  }

  private async performAutomatedRebalancing(): Promise<void> {
    const activeStrategies = Array.from(this.strategies.values())
      .filter(s => s.status === 'active')

    for (const strategy of activeStrategies) {
      try {
        const decision = await this.generateRebalancingDecision(strategy.strategyId)

        if (decision.action === 'rebalance') {
          await this.executeRebalancing(decision)
        } else if (decision.action === 'close') {
          await this.closePositions(decision.targetPositions.map(p => p.currencyPair))
        }

      } catch (error) {
        console.error(`Rebalancing failed for strategy ${strategy.strategyId}:`, error)
      }
    }
  }

  private async generateRebalancingDecision(strategyId: string): Promise<RebalancingDecision> {
    const strategy = this.strategies.get(strategyId)
    if (!strategy) {
      throw new Error(`Strategy ${strategyId} not found`)
    }

    const currentPositions = Array.from(this.positions.values())
      .filter(p => p.strategyId === strategyId && p.status === 'open')

    const targetPositions = []
    let action: RebalancingDecision['action'] = 'maintain'
    let reason = 'No rebalancing required'

    // Check if rebalancing is needed based on current hedge ratios
    for (const currency of strategy.currencies) {
      const currentHedgeRatio = this.getCurrentHedgeRatio(strategyId, currency)
      const targetHedgeRatio = strategy.parameters.targetHedgeRatio
      const deviation = Math.abs(currentHedgeRatio - targetHedgeRatio)

      if (deviation > strategy.parameters.triggerThreshold) {
        action = 'rebalance'
        reason = `Hedge ratio deviation in ${currency}: ${deviation.toFixed(3)}`

        targetPositions.push({
          currencyPair: `USD/${currency}`,
          targetHedgeRatio,
          currentHedgeRatio,
          requiredAdjustment: targetHedgeRatio - currentHedgeRatio
        })
      }
    }

    // Check for position limits
    if (currentPositions.length >= strategy.parameters.maxPosition) {
      action = 'close'
      reason = 'Maximum position limit reached'
    }

    return {
      strategyId,
      action,
      reason,
      targetPositions,
      expectedImpact: {
        cost: 100, // Simplified cost calculation
        riskReduction: 0.1,
        liquidityImpact: 0.05
      }
    }
  }

  private async executeRebalancing(decision: RebalancingDecision): Promise<void> {
    for (const target of decision.targetPositions) {
      if (target.requiredAdjustment > 0.01) {
        // Open new hedge position
        const strategy = this.strategies.get(decision.strategyId)
        if (strategy) {
          await this.createHedgePosition(strategy, target.currencyPair.split('/')[1], target.requiredAdjustment * 1000000)
        }
      } else if (target.requiredAdjustment < -0.01) {
        // Reduce existing position
        await this.reduceHedgePosition(target.currencyPair, Math.abs(target.requiredAdjustment))
      }
    }
  }

  private async closePositions(currencyPairs: string[]): Promise<void> {
    for (const pair of currencyPairs) {
      const positions = Array.from(this.positions.values())
        .filter(p => p.currencyPair === pair && p.status === 'open')

      for (const position of positions) {
        position.status = 'closed'
        position.pnl = (position.currentPrice || position.entryPrice) - position.entryPrice
      }
    }
  }

  private async reduceHedgePosition(currencyPair: string, reductionAmount: number): Promise<void> {
    const positions = Array.from(this.positions.values())
      .filter(p => p.currencyPair === currencyPair && p.status === 'open')
      .sort((a, b) => a.notional - b.notional) // Close smallest positions first

    let remainingReduction = reductionAmount

    for (const position of positions) {
      if (remainingReduction <= 0) break

      const closeAmount = Math.min(position.notional, remainingReduction)
      position.notional -= closeAmount
      remainingReduction -= closeAmount

      if (position.notional === 0) {
        position.status = 'closed'
      }
    }
  }

  private initializeDefaultStrategies(): void {
    const defaultStrategies: Omit<HedgingStrategy, 'strategyId' | 'performance'>[] = [
      {
        name: 'Conservative Forward Hedge',
        description: 'Conservative hedging using forward contracts',
        type: 'forward_based',
        parameters: {
          targetHedgeRatio: 0.8,
          rebalanceFrequency: 'weekly',
          triggerThreshold: 0.1,
          maxPosition: 50
        },
        currencies: ['EUR', 'GBP', 'JPY'],
        status: 'active'
      },
      {
        name: 'Dynamic Option Strategy',
        description: 'Dynamic hedging using options for flexibility',
        type: 'option_based',
        parameters: {
          targetHedgeRatio: 0.6,
          rebalanceFrequency: 'daily',
          triggerThreshold: 0.05,
          maxPosition: 30
        },
        currencies: ['EUR', 'GBP', 'CHF'],
        status: 'active'
      }
    ]

    defaultStrategies.forEach(strategy => {
      this.createStrategy(strategy)
    })
  }

  // Update market data
  updateMarketData(currency: string, data: MarketData): void {
    this.marketData.set(`USD/${currency}`, data)

    // Update position prices
    const relevantPositions = Array.from(this.positions.values())
      .filter(p => p.currencyPair === `USD/${currency}` && p.status === 'open')

    relevantPositions.forEach(position => {
      position.currentPrice = data.ask
      position.pnl = (data.ask - position.entryPrice) * position.notional * (position.hedgeDirection === 'long' ? 1 : -1)
    })
  }

  // Update portfolio exposure
  updatePortfolioExposure(portfolioId: string, exposures: Record<string, number>): void {
    this.portfolioExposures.set(portfolioId, exposures)
  }

  // Get strategy performance
  getStrategyPerformance(strategyId: string): HedgingStrategy['performance'] | null {
    const strategy = this.strategies.get(strategyId)
    return strategy ? strategy.performance : null
  }

  // Get active hedge positions
  getActivePositions(strategyId?: string): HedgePosition[] {
    return Array.from(this.positions.values())
      .filter(p => p.status === 'open' && (!strategyId || p.strategyId === strategyId))
  }

  // Generate hedging report
  generateHedgingReport(strategyId?: string): {
    totalStrategies: number
    activePositions: number
    totalNotional: number
    pnl: number
    strategies: Array<{
      strategyId: string
      name: string
      performance: HedgingStrategy['performance']
      activePositions: number
    }>
  } {
    const strategies = strategyId
      ? [this.strategies.get(strategyId)].filter(Boolean) as HedgingStrategy[]
      : Array.from(this.strategies.values())

    const strategyReports = strategies.map(strategy => {
      const positions = this.getActivePositions(strategy.strategyId)
      const totalNotional = positions.reduce((sum, pos) => sum + pos.notional, 0)

      return {
        strategyId: strategy.strategyId,
        name: strategy.name,
        performance: strategy.performance,
        activePositions: positions.length
      }
    })

    const allPositions = this.getActivePositions(strategyId)
    const totalNotional = allPositions.reduce((sum, pos) => sum + pos.notional, 0)
    const pnl = allPositions.reduce((sum, pos) => sum + pos.pnl, 0)

    return {
      totalStrategies: strategies.length,
      activePositions: allPositions.length,
      totalNotional,
      pnl,
      strategies: strategyReports
    }
  }
}

// Initialize hedging strategy automation
const hedgingAutomation = new HedgingStrategyAutomation()

// Create hedging strategy endpoint
app.post('/api/hedging/create-strategy', (req, res) => {
  try {
    const { name, description, type, parameters, currencies, status } = req.body

    if (!name || !type || !parameters || !currencies) {
      return res.status(400).json({
        error: 'name, type, parameters, and currencies required'
      })
    }

    const strategyId = hedgingAutomation.createStrategy({
      name,
      description,
      type,
      parameters,
      currencies,
      status: status || 'active'
    })

    res.json({
      success: true,
      strategyId,
      message: 'Hedging strategy created successfully',
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('Create hedging strategy error:', error)
    res.status(500).json({ error: 'Failed to create strategy' })
  }
})

// Execute hedging strategy endpoint
app.post('/api/hedging/execute-strategy', async (req, res) => {
  try {
    const { strategyId, portfolioId } = req.body

    if (!strategyId || !portfolioId) {
      return res.status(400).json({ error: 'strategyId and portfolioId required' })
    }

    const positions = await hedgingAutomation.executeStrategy(strategyId, portfolioId)

    res.json({
      success: true,
      positions: positions.map(p => p.positionId),
      count: positions.length,
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('Execute hedging strategy error:', error)
    res.status(500).json({ error: 'Failed to execute strategy' })
  }
})

// Hedging report endpoint
app.get('/api/hedging/report/:strategyId?', (req, res) => {
  try {
    const { strategyId } = req.params

    const report = hedgingAutomation.generateHedgingReport(strategyId)

    res.json({
      report,
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('Hedging report error:', error)
    res.status(500).json({ error: 'Failed to generate report' })
  }
})

console.log('Hedging Strategy Automation System initialized')

VaR Models and Stress Testing


Value-at-Risk (VaR) quantifies potential losses over a time horizon at a confidence level.


VaR Calculation Methods


  • Historical simulation: rank historical returns, pick percentile
  • Parametric (variance-covariance): assume normal distribution, use z-score
  • Monte Carlo: simulate price paths, aggregate outcomes
  • Expected Shortfall (CVaR): average loss beyond VaR threshold

Stress Testing Scenarios


  • Historical: 2008 crisis, Brexit, COVID-19 market stress
  • Hypothetical: parallel shift in all rates, correlation breakdown
  • Reverse stress: what moves cause X% portfolio loss?
  • Sensitivity: delta, gamma, vega analysis per currency

Model Validation


  • Backtesting: compare VaR predictions vs actual losses
  • Kupiec test: count exceptions, test if frequency matches confidence
  • Christoffersen test: independence of exceptions
  • Model recalibration: adjust parameters based on recent performance

Hedging Instruments


Choose instruments based on cost, complexity, and effectiveness.


Forward Contracts


  • Lock in exchange rate for future delivery
  • No upfront cost (except margin)
  • Perfect hedge for known future cash flows
  • Risk: counterparty default, early termination costs

Currency Options


  • Right (not obligation) to exchange at strike price
  • Premium paid upfront
  • Asymmetric payoff: limit downside, keep upside
  • Greeks: delta (price sensitivity), gamma (delta change), theta (time decay)

Currency Swaps


  • Exchange principal amounts, then swap back at maturity
  • Fixed vs floating rate exposure
  • Cross-currency basis risk
  • Collateral posting requirements

Natural Hedging


  • Match revenue/expense currencies
  • Net exposure calculation
  • Operational hedging through pricing
  • Geographic diversification

Regulatory Compliance


Currency risk management must comply with financial regulations.


Basel III/IV Requirements


  • Market risk capital: VaR + stressed VaR + IRC
  • CVA capital for counterparty credit risk
  • Leverage ratio: Tier 1 capital / total exposure
  • Liquidity coverage ratio (LCR)

IFRS 9 Hedge Accounting


  • Hedge effectiveness testing: 80-125% range
  • Documentation requirements
  • Prospective and retrospective effectiveness
  • Discontinuation triggers

MiFID II (EU)


  • Best execution for FX transactions
  • Transaction reporting
  • Product governance
  • Client categorization

Operational Controls


Implement controls to prevent operational losses.


Position Limits


  • Per currency exposure limits
  • Concentration limits (% of portfolio)
  • VaR limits (daily loss tolerance)
  • Stop-loss triggers

Approval Workflows


  • Trade authorization matrix
  • Escalation procedures
  • Segregation of duties
  • Regular limit reviews

Monitoring and Reporting


  • Real-time P&L monitoring
  • Daily risk reports
  • Exception reporting
  • Regulatory submissions

Conclusion


Effective currency risk management combines quantitative models, appropriate hedging instruments, and robust operational controls. Start with VaR-based limits, implement natural hedging where possible, and use derivatives for residual exposure.


Implement comprehensive currency risk management with our VaR models, hedging automation, and compliance reporting tools.

Tags:risk-managementhedgingvolatilityfinancial-protection