Financial Trading Platform

Scenario: High-Frequency Trading System

Building a trading platform with:

  • Real-time market data streaming
  • Order execution with microsecond precision
  • Risk management and compliance
  • Complex calculations with BigNumber
  • Audit trail for all operations

CLAUDE.md for Financial Systems

## Financial Trading Platform Architecture
 
### Type Safety for Financial Data
```typescript
// Use branded types for financial values
type Brand<K, T> = K & { __brand: T };
 
type USD = Brand<number, 'USD'>;
type EUR = Brand<number, 'EUR'>;
type BTC = Brand<number, 'BTC'>;
 
// Prevent mixing currencies at compile time
function convertCurrency<TFrom extends number, TTo>(
  amount: TFrom,
  rate: number,
  toCurrency: (value: number) => TTo
): TTo {
  return toCurrency(amount * rate);
}
 
// Price types with precision
interface Price {
  value: bigint; // Store as smallest unit (cents, satoshis)
  decimals: number;
  currency: Currency;
}
 
class PriceCalculator {
  static fromString(value: string, currency: Currency): Price {
    const decimals = CURRENCY_DECIMALS[currency];
    const [whole, fraction = ''] = value.split('.');
    const paddedFraction = fraction.padEnd(decimals, '0');
    const bigintValue = BigInt(whole + paddedFraction);
    
    return { value: bigintValue, decimals, currency };
  }
  
  static toString(price: Price): string {
    const str = price.value.toString();
    const whole = str.slice(0, -price.decimals) || '0';
    const fraction = str.slice(-price.decimals).padStart(price.decimals, '0');
    return `${whole}.${fraction}`;
  }
  
  static add(a: Price, b: Price): Price {
    if (a.currency !== b.currency) {
      throw new Error('Cannot add different currencies');
    }
    return {
      value: a.value + b.value,
      decimals: a.decimals,
      currency: a.currency,
    };
  }
}
 
// Order types with validation
interface Order {
  id: string;
  userId: string;
  symbol: TradingSymbol;
  side: 'buy' | 'sell';
  type: OrderType;
  status: OrderStatus;
  quantity: bigint;
  price?: Price; // Optional for market orders
  stopPrice?: Price; // For stop orders
  timeInForce: TimeInForce;
  createdAt: Date;
  updatedAt: Date;
  executions: Execution[];
}
 
enum OrderType {
  MARKET = 'MARKET',
  LIMIT = 'LIMIT',
  STOP = 'STOP',
  STOP_LIMIT = 'STOP_LIMIT',
}
 
enum TimeInForce {
  GTC = 'GTC', // Good Till Cancelled
  IOC = 'IOC', // Immediate or Cancel
  FOK = 'FOK', // Fill or Kill
  DAY = 'DAY',
}
 
// Market data streaming
interface MarketData {
  symbol: TradingSymbol;
  bid: Price;
  ask: Price;
  last: Price;
  volume24h: bigint;
  high24h: Price;
  low24h: Price;
  timestamp: bigint; // nanoseconds
}
 
interface OrderBook {
  symbol: TradingSymbol;
  bids: OrderBookLevel[];
  asks: OrderBookLevel[];
  timestamp: bigint;
  sequenceNumber: bigint;
}
 
interface OrderBookLevel {
  price: Price;
  quantity: bigint;
  orderCount: number;
}

High-Performance Order Matching Engine

export class OrderMatchingEngine {
  private orderBooks = new Map<string, OrderBook>();
  private orderIndex = new Map<string, Order>();
  private sequenceNumber = 0n;
  
  async submitOrder(order: Order): Promise<OrderResult> {
    const timestamp = process.hrtime.bigint();
    
    // Validate order
    const validation = this.validateOrder(order);
    if (!validation.valid) {
      return {
        success: false,
        error: validation.error,
        timestamp,
      };
    }
    
    // Risk check
    const riskCheck = await this.checkRisk(order);
    if (!riskCheck.passed) {
      return {
        success: false,
        error: `Risk check failed: ${riskCheck.reason}`,
        timestamp,
      };
    }
    
    // Match order
    const result = this.matchOrder(order);
    
    // Audit log
    await this.auditLog({
      action: 'ORDER_SUBMITTED',
      orderId: order.id,
      userId: order.userId,
      details: order,
      result,
      timestamp,
    });
    
    return result;
  }
  
  private matchOrder(order: Order): OrderResult {
    const book = this.orderBooks.get(order.symbol);
    if (!book) {
      return {
        success: false,
        error: 'Invalid symbol',
        timestamp: process.hrtime.bigint(),
      };
    }
    
    const executions: Execution[] = [];
    let remainingQuantity = order.quantity;
    
    if (order.type === OrderType.MARKET) {
      // Match against opposite side of book
      const levels = order.side === 'buy' ? book.asks : book.bids;
      
      for (const level of levels) {
        if (remainingQuantity === 0n) break;
        
        const fillQuantity = remainingQuantity > level.quantity 
          ? level.quantity 
          : remainingQuantity;
          
        executions.push({
          id: this.generateExecutionId(),
          orderId: order.id,
          price: level.price,
          quantity: fillQuantity,
          timestamp: process.hrtime.bigint(),
          liquidity: 'taker',
        });
        
        remainingQuantity -= fillQuantity;
        level.quantity -= fillQuantity;
      }
    }
    
    // Update order status
    if (remainingQuantity === 0n) {
      order.status = OrderStatus.FILLED;
    } else if (remainingQuantity < order.quantity) {
      order.status = OrderStatus.PARTIALLY_FILLED;
    }
    
    // Broadcast market data update
    this.broadcastMarketData(order.symbol, book);
    
    return {
      success: true,
      order,
      executions,
      timestamp: process.hrtime.bigint(),
    };
  }
  
  private async checkRisk(order: Order): Promise<RiskCheckResult> {
    // Implement risk checks
    const checks = await Promise.all([
      this.checkPositionLimits(order),
      this.checkBuyingPower(order),
      this.checkDailyLossLimit(order),
      this.checkSymbolRestrictions(order),
    ]);
    
    const failed = checks.find(check => !check.passed);
    
    return failed || { passed: true };
  }
}
 
// WebSocket market data streaming
export class MarketDataStreamer {
  private subscribers = new Map<string, Set<WebSocket>>();
  private dataBuffer = new Map<string, MarketData[]>();
  private flushInterval: NodeJS.Timer;
  
  constructor(private flushIntervalMs = 100) {
    this.flushInterval = setInterval(() => this.flush(), flushIntervalMs);
  }
  
  subscribe(symbol: string, ws: WebSocket): void {
    if (!this.subscribers.has(symbol)) {
      this.subscribers.set(symbol, new Set());
    }
    this.subscribers.get(symbol)!.add(ws);
    
    // Send snapshot
    const snapshot = this.getSnapshot(symbol);
    if (snapshot) {
      ws.send(JSON.stringify({
        type: 'snapshot',
        symbol,
        data: snapshot,
      }));
    }
  }
  
  publish(data: MarketData): void {
    if (!this.dataBuffer.has(data.symbol)) {
      this.dataBuffer.set(data.symbol, []);
    }
    this.dataBuffer.get(data.symbol)!.push(data);
  }
  
  private flush(): void {
    for (const [symbol, updates] of this.dataBuffer) {
      if (updates.length === 0) continue;
      
      // Aggregate updates
      const aggregated = this.aggregate(updates);
      
      // Send to subscribers
      const subscribers = this.subscribers.get(symbol);
      if (subscribers) {
        const message = JSON.stringify({
          type: 'update',
          symbol,
          data: aggregated,
        });
        
        for (const ws of subscribers) {
          if (ws.readyState === WebSocket.OPEN) {
            ws.send(message);
          }
        }
      }
    }
    
    // Clear buffer
    this.dataBuffer.clear();
  }
  
  private aggregate(updates: MarketData[]): MarketData {
    // Return the latest update with aggregated volume
    const latest = updates[updates.length - 1];
    const totalVolume = updates.reduce(
      (sum, update) => sum + update.volume24h,
      0n
    );
    
    return {
      ...latest,
      volume24h: totalVolume,
    };
  }
}

Compliance and Audit System

interface AuditLog {
  id: string;
  timestamp: bigint;
  userId: string;
  action: AuditAction;
  details: Record<string, unknown>;
  ipAddress: string;
  userAgent: string;
  result: 'success' | 'failure';
  errorMessage?: string;
}
 
enum AuditAction {
  LOGIN = 'LOGIN',
  LOGOUT = 'LOGOUT',
  ORDER_SUBMITTED = 'ORDER_SUBMITTED',
  ORDER_CANCELLED = 'ORDER_CANCELLED',
  ORDER_MODIFIED = 'ORDER_MODIFIED',
  WITHDRAWAL_REQUESTED = 'WITHDRAWAL_REQUESTED',
  DEPOSIT_RECEIVED = 'DEPOSIT_RECEIVED',
  KYC_SUBMITTED = 'KYC_SUBMITTED',
  SETTINGS_CHANGED = 'SETTINGS_CHANGED',
}
 
export class ComplianceEngine {
  async checkCompliance(
    user: User,
    action: ComplianceAction
  ): Promise<ComplianceResult> {
    const checks = [
      this.checkKYCStatus(user),
      this.checkJurisdiction(user),
      this.checkSanctions(user),
      this.checkTradingRestrictions(user, action),
    ];
    
    const results = await Promise.all(checks);
    const failed = results.filter(r => !r.passed);
    
    return {
      passed: failed.length === 0,
      failures: failed,
      timestamp: new Date(),
    };
  }
  
  private async checkKYCStatus(user: User): Promise<ComplianceCheck> {
    if (!user.kycVerified) {
      return {
        passed: false,
        reason: 'KYC verification required',
        code: 'KYC_REQUIRED',
      };
    }
    
    if (user.kycExpiry && user.kycExpiry < new Date()) {
      return {
        passed: false,
        reason: 'KYC verification expired',
        code: 'KYC_EXPIRED',
      };
    }
    
    return { passed: true };
  }
  
  private async checkSanctions(user: User): Promise<ComplianceCheck> {
    // Check against sanctions lists
    const sanctioned = await this.sanctionsService.check({
      name: user.name,
      dateOfBirth: user.dateOfBirth,
      country: user.country,
    });
    
    if (sanctioned) {
      await this.flagAccount(user.id, 'SANCTIONS_HIT');
      
      return {
        passed: false,
        reason: 'User flagged by sanctions screening',
        code: 'SANCTIONS_HIT',
      };
    }
    
    return { passed: true };
  }
}

## Critical Implementation Considerations

1. **Precision is Everything**: Use BigInt for all financial calculations
2. **Audit Everything**: Log every action with immutable timestamps
3. **Type Safety**: Branded types prevent currency mixing errors
4. **Performance**: Optimize hot paths, use message buffering
5. **Compliance First**: Build compliance checks into the core flow

## Security Patterns

- Implement rate limiting per user
- Use message signing for WebSocket connections
- Encrypt sensitive data at rest
- Implement circuit breakers for external services
- Regular security audits and penetration testing

## Related Resources

- [[docs/reference/templates/fullstack-typescript|Full-Stack TypeScript Template]]
- [FIX Protocol](https://www.fixtrading.org/)
- [MiFID II Compliance](https://www.esma.europa.eu/policy-rules/mifid-ii-and-mifir)

## 🧭 Quick Navigation

[← Real-Time Collaboration](real-time-collaboration) | [Back to Scenarios](../index) | [Healthcare Platform →](healthcare-platform)