267 lines
8.0 KiB
Markdown
267 lines
8.0 KiB
Markdown
|
|
# FX Trade Execution Flow
|
|||
|
|
|
|||
|
|
## Overview
|
|||
|
|
|
|||
|
|
The FX Engine processes foreign exchange orders through market or limit order types, calculates prices using VWAP/TWAP methods, and executes trades with proper settlement routing. This flow documents the complete order submission and execution process.
|
|||
|
|
|
|||
|
|
## Prerequisites
|
|||
|
|
|
|||
|
|
- Sovereign bank is registered and active
|
|||
|
|
- FX pair exists or can be created
|
|||
|
|
- Valid FX order (market or limit)
|
|||
|
|
- FX service operational
|
|||
|
|
- Market data available (for market orders)
|
|||
|
|
|
|||
|
|
## Visual Flow Diagram
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────┐
|
|||
|
|
│ FX Order │
|
|||
|
|
│ Request │
|
|||
|
|
└──────┬──────┘
|
|||
|
|
│
|
|||
|
|
│ 1. Get/Create Pair
|
|||
|
|
▼
|
|||
|
|
┌─────────────────────────┐
|
|||
|
|
│ Get or Create FX Pair │
|
|||
|
|
│ - Lookup by pair code │
|
|||
|
|
│ - Create if not exists │
|
|||
|
|
└──────┬──────────────────┘
|
|||
|
|
│
|
|||
|
|
│ 2. Calculate Price
|
|||
|
|
▼
|
|||
|
|
┌─────────────────────────┐
|
|||
|
|
│ Calculate Price │
|
|||
|
|
│ - Market: getMarketPrice│
|
|||
|
|
│ - Limit: use limitPrice │
|
|||
|
|
└──────┬──────────────────┘
|
|||
|
|
│
|
|||
|
|
│ 3. Create Trade
|
|||
|
|
▼
|
|||
|
|
┌─────────────────────────┐
|
|||
|
|
│ Create FX Trade Record │
|
|||
|
|
│ - Trade ID │
|
|||
|
|
│ - Pair, amount, price │
|
|||
|
|
│ - Order type │
|
|||
|
|
│ - Status: pending │
|
|||
|
|
└──────┬──────────────────┘
|
|||
|
|
│
|
|||
|
|
│ 4. Execute Trade
|
|||
|
|
▼
|
|||
|
|
┌─────────────────────────┐
|
|||
|
|
│ Execute Trade │
|
|||
|
|
│ - Update status │
|
|||
|
|
│ - Set executed time │
|
|||
|
|
└──────┬──────────────────┘
|
|||
|
|
│
|
|||
|
|
│ 5. Complete
|
|||
|
|
▼
|
|||
|
|
┌─────────────┐
|
|||
|
|
│ Trade │
|
|||
|
|
│ Executed │
|
|||
|
|
└─────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Step-by-Step Process
|
|||
|
|
|
|||
|
|
### Step 1: Get or Create FX Pair
|
|||
|
|
1. Receive FX order with:
|
|||
|
|
- Sovereign bank ID
|
|||
|
|
- FX pair code (e.g., "OMF/USD")
|
|||
|
|
- Order type (MARKET or LIMIT)
|
|||
|
|
- Amount
|
|||
|
|
- Limit price (if LIMIT order)
|
|||
|
|
- Settlement mode
|
|||
|
|
2. Parse pair code to extract base and quote currencies
|
|||
|
|
3. Lookup FX pair by pair code
|
|||
|
|
4. If pair doesn't exist:
|
|||
|
|
- Create new FX pair record
|
|||
|
|
- Set base currency
|
|||
|
|
- Set quote currency
|
|||
|
|
- Set pair code
|
|||
|
|
- Set pricing method: `VWAP` (default)
|
|||
|
|
- Set status: `active`
|
|||
|
|
5. Return FX pair (existing or newly created)
|
|||
|
|
|
|||
|
|
**Code Reference**: `src/core/fx/fx.service.ts:22-147`
|
|||
|
|
|
|||
|
|
### Step 2: Calculate Price
|
|||
|
|
1. Determine price based on order type:
|
|||
|
|
- **MARKET order**: Get current market price
|
|||
|
|
- Call `getMarketPrice(pair)`
|
|||
|
|
- In production: fetch from market data feeds
|
|||
|
|
- Currently: returns mock price based on pair
|
|||
|
|
- **LIMIT order**: Use provided limit price
|
|||
|
|
- Verify limit price is provided
|
|||
|
|
- Use limit price directly
|
|||
|
|
2. If MARKET order and price unavailable:
|
|||
|
|
- Throw error "Market price not available"
|
|||
|
|
3. If LIMIT order and limit price missing:
|
|||
|
|
- Throw error "Invalid order type or missing limit price"
|
|||
|
|
|
|||
|
|
**Code Reference**: `src/core/fx/fx.service.ts:29-37`
|
|||
|
|
|
|||
|
|
### Step 3: Create FX Trade Record
|
|||
|
|
1. Generate unique trade ID: `FX-{uuid}`
|
|||
|
|
2. Create FX trade record:
|
|||
|
|
- Trade ID
|
|||
|
|
- Sovereign bank ID
|
|||
|
|
- FX pair ID
|
|||
|
|
- Base currency (from pair)
|
|||
|
|
- Quote currency (from pair)
|
|||
|
|
- Trade type: `SPOT` (default)
|
|||
|
|
- Quantity: order amount
|
|||
|
|
- Price: calculated price
|
|||
|
|
- Order type: MARKET or LIMIT
|
|||
|
|
- Initiator entity: sovereign bank ID
|
|||
|
|
- Settlement mode: from order
|
|||
|
|
- Status: `pending`
|
|||
|
|
- Timestamp: current time
|
|||
|
|
3. Store trade in database
|
|||
|
|
4. Return trade ID and status
|
|||
|
|
|
|||
|
|
**Code Reference**: `src/core/fx/fx.service.ts:39-62`
|
|||
|
|
|
|||
|
|
### Step 4: Execute Trade
|
|||
|
|
1. Lookup trade by trade ID
|
|||
|
|
2. Verify trade exists and is in `pending` status
|
|||
|
|
3. Update trade record:
|
|||
|
|
- Status: `executed`
|
|||
|
|
- Executed at: current timestamp
|
|||
|
|
4. Map trade to FxTrade type
|
|||
|
|
5. Return executed trade details
|
|||
|
|
|
|||
|
|
**Code Reference**: `src/core/fx/fx.service.ts:67-87`
|
|||
|
|
|
|||
|
|
### Step 5: Market Price Calculation (for MARKET orders)
|
|||
|
|
1. Parse pair to extract base and quote currencies
|
|||
|
|
2. Get market price:
|
|||
|
|
- In production: fetch from market data feeds
|
|||
|
|
- Use VWAP (Volume Weighted Average Price) or TWAP (Time Weighted Average Price)
|
|||
|
|
- Currently: return mock prices for known pairs
|
|||
|
|
3. Return price as string
|
|||
|
|
|
|||
|
|
**Code Reference**: `src/core/fx/fx.service.ts:92-105`
|
|||
|
|
|
|||
|
|
### Step 6: VWAP/TWAP Calculation (optional)
|
|||
|
|
1. **VWAP Calculation**:
|
|||
|
|
- Get trade history for pair within time window (default 3600s)
|
|||
|
|
- Calculate: `VWAP = Σ(price × volume) / Σ(volume)`
|
|||
|
|
- Return VWAP price
|
|||
|
|
2. **TWAP Calculation**:
|
|||
|
|
- Get price history for pair within time window
|
|||
|
|
- Calculate: `TWAP = Σ(price × time_weight) / Σ(time_weight)`
|
|||
|
|
- Return TWAP price
|
|||
|
|
|
|||
|
|
**Code Reference**: `src/core/fx/fx.service.ts:110-123`
|
|||
|
|
|
|||
|
|
## Error Handling
|
|||
|
|
|
|||
|
|
### Error: Invalid Order Type
|
|||
|
|
- **Detection**: Order type not MARKET or LIMIT
|
|||
|
|
- **Action**: Throw validation error
|
|||
|
|
- **Recovery**: Correct order type, retry
|
|||
|
|
|
|||
|
|
### Error: Missing Limit Price
|
|||
|
|
- **Detection**: LIMIT order without limit price
|
|||
|
|
- **Action**: Throw error "Invalid order type or missing limit price"
|
|||
|
|
- **Recovery**: Provide limit price, retry
|
|||
|
|
|
|||
|
|
### Error: Market Price Unavailable
|
|||
|
|
- **Detection**: MARKET order but price unavailable
|
|||
|
|
- **Action**: Throw error "Market price not available"
|
|||
|
|
- **Recovery**: Wait for market data, retry, or use limit order
|
|||
|
|
|
|||
|
|
### Error: Trade Not Found
|
|||
|
|
- **Detection**: Trade ID doesn't exist
|
|||
|
|
- **Action**: Throw error "FX trade not found"
|
|||
|
|
- **Recovery**: Verify trade ID, retry
|
|||
|
|
|
|||
|
|
### Error: Trade Already Executed
|
|||
|
|
- **Detection**: Trade status is not `pending`
|
|||
|
|
- **Action**: Return existing trade (idempotent)
|
|||
|
|
- **Recovery**: Use existing trade result
|
|||
|
|
|
|||
|
|
## Integration Points
|
|||
|
|
|
|||
|
|
### Related Services
|
|||
|
|
- **FX Service**: `src/core/fx/fx.service.ts`
|
|||
|
|
- **Market Data Service**: (in production - external feeds)
|
|||
|
|
- **Settlement Service**: For trade settlement routing
|
|||
|
|
- **SIRE Routing**: For optimal settlement path
|
|||
|
|
|
|||
|
|
### API Endpoints
|
|||
|
|
- `POST /api/v1/fx/orders` - Submit FX order
|
|||
|
|
- `POST /api/v1/fx/trades/:tradeId/execute` - Execute trade
|
|||
|
|
- `GET /api/v1/fx/trades/:tradeId` - Get trade details
|
|||
|
|
- `GET /api/v1/fx/pairs/:pairCode/price` - Get market price
|
|||
|
|
|
|||
|
|
### Database Models
|
|||
|
|
- `FxTrade` - FX trade records
|
|||
|
|
- `FxPair` - FX pair definitions
|
|||
|
|
|
|||
|
|
## Performance Metrics
|
|||
|
|
|
|||
|
|
- **Pair Lookup/Creation**: < 10ms target
|
|||
|
|
- **Price Calculation**: < 20ms target (market data dependent)
|
|||
|
|
- **Trade Creation**: < 10ms target
|
|||
|
|
- **Trade Execution**: < 10ms target
|
|||
|
|
- **Total End-to-End**: < 50ms target
|
|||
|
|
- **Throughput**: 20,000+ orders/second
|
|||
|
|
- **Availability**: 99.99% uptime target
|
|||
|
|
|
|||
|
|
## Security Considerations
|
|||
|
|
|
|||
|
|
### Order Validation
|
|||
|
|
- Verify sovereign bank is active
|
|||
|
|
- Validate order parameters
|
|||
|
|
- Check amount limits
|
|||
|
|
|
|||
|
|
### Price Verification
|
|||
|
|
- Market prices from trusted sources
|
|||
|
|
- Limit prices validated against market
|
|||
|
|
- Price manipulation detection
|
|||
|
|
|
|||
|
|
### Trade Execution
|
|||
|
|
- Idempotent execution (can retry safely)
|
|||
|
|
- Trade status tracking
|
|||
|
|
- Audit trail for all trades
|
|||
|
|
|
|||
|
|
## Testing Scenarios
|
|||
|
|
|
|||
|
|
### Happy Path - Market Order
|
|||
|
|
1. Valid market order request
|
|||
|
|
2. FX pair exists or created
|
|||
|
|
3. Market price available
|
|||
|
|
4. Trade created successfully
|
|||
|
|
5. Trade executed successfully
|
|||
|
|
|
|||
|
|
### Happy Path - Limit Order
|
|||
|
|
1. Valid limit order request
|
|||
|
|
2. FX pair exists or created
|
|||
|
|
3. Limit price provided
|
|||
|
|
4. Trade created successfully
|
|||
|
|
5. Trade executed successfully
|
|||
|
|
|
|||
|
|
### Error Scenarios
|
|||
|
|
1. Invalid order type
|
|||
|
|
2. Missing limit price
|
|||
|
|
3. Market price unavailable
|
|||
|
|
4. Trade not found
|
|||
|
|
5. Trade already executed
|
|||
|
|
|
|||
|
|
### Edge Cases
|
|||
|
|
1. Maximum order amount
|
|||
|
|
2. Minimum order amount
|
|||
|
|
3. New FX pair creation
|
|||
|
|
4. Concurrent orders for same pair
|
|||
|
|
5. Price calculation during high volatility
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**Related Flows**:
|
|||
|
|
- [SSU Mint Burn Flow](./ssu-mint-burn-flow.md)
|
|||
|
|
- [FX/SSU Integration Flow](./fx-ssu-integration-flow.md)
|
|||
|
|
- [GSS Settlement Flow](./gss-settlement-flow.md)
|
|||
|
|
|