Skip to content

Risk Service

The Risk Service is responsible for pre-trade validation, real-time exposure monitoring, margin risk management, AML/FIU compliance, and liquidation trigger coordination. It acts as the gatekeeper that ensures all trading activity stays within defined risk parameters.

  • Pre-Trade Checks: Validate leverage, margin requirements, and exposure limits before orders are accepted.
  • Exposure Monitoring: Real-time tracking of per-account and per-symbol exposure in USDT terms.
  • Margin Risk: Monitor margin ratios and emit margin call / liquidation events.
  • AML / FIU Reporting: Transaction monitoring, suspicious activity detection, and FIU-IND reporting.
  • Policy Enforcement: Enforce position limits, price bands, and rate limits per risk profile.
  • Hold Management: Request balance holds via Wallet Service for flagged accounts.

The Risk Service is currently implemented as a gRPC interface consumed by the Order Service, with the actual service implementation planned as a dedicated microservice.

graph TB OrderSvc[Order Service] -->|gRPC PreTradeCheck| Risk[Risk Service] Kafka[Kafka] -->|order/wallet/position events| Risk Risk -->|gRPC| Wallet[Wallet Service] Risk -->|Events| Kafka2[Kafka] Risk -->|Stores| PG[(PostgreSQL)] Kafka2 --> Settlement[Settlement Service] Kafka2 --> AdminPanel[Admin Panel]

Called by the Order Service before accepting any order:

rpc PreTradeCheck(PreTradeRequest) returns (PreTradeResponse);
message PreTradeRequest {
string user_id = 1;
string account_id = 2;
string symbol = 3;
string side = 4;
string order_type = 5;
string quantity = 6;
string price = 7;
int32 leverage = 8;
string trace_id = 9;
}
message PreTradeResponse {
bool approved = 1;
string reject_reason = 2;
string available_margin = 3;
string required_margin = 4;
string current_exposure = 5;
string max_exposure = 6;
}

The PreTradeCheck validates:

  1. Account Status: User is not frozen, suspended, or under AML hold
  2. Leverage Limits: requested_leverage <= max_leverage_for_symbol
  3. Margin Sufficiency: available_margin >= required_initial_margin
  4. Position Limits: current_position + order_qty <= max_position_for_symbol
  5. Exposure Limits: total_exposure + order_notional <= max_total_exposure
  6. Price Bands: Order price within allowed deviation from mark price (for limit orders)
  7. Rate Limits: Account hasn’t exceeded order submission rate
FieldTypeDescription
idUUID (PK)Profile ID
user_idUUIDAccount owner
max_leverageINTMaximum allowed leverage
max_position_usdtNUMERIC(20,4)Maximum position per symbol
max_total_exposure_usdtNUMERIC(20,4)Maximum total exposure
max_order_rate_per_secINTMaximum orders per second
aml_risk_scoreNUMERIC(5,2)AML risk score (0-100)
kyc_tierENUMKYC verification tier
updated_atTIMESTAMPTZLast update
FieldTypeDescription
idUUID (PK)Snapshot ID
user_idUUIDAccount owner
symbolVARCHAR(32)Instrument symbol
long_exposure_usdtNUMERIC(20,4)Long exposure value
short_exposure_usdtNUMERIC(20,4)Short exposure value
net_exposure_usdtNUMERIC(20,4)Net exposure
margin_usedNUMERIC(20,4)Margin allocated
margin_ratioNUMERIC(10,6)Current margin ratio
captured_atTIMESTAMPTZSnapshot timestamp
FieldTypeDescription
idUUID (PK)Record ID
user_idUUIDAccount owner
transaction_typeENUMdeposit, withdrawal, trade, transfer
amountNUMERIC(20,4)Transaction amount
currencyVARCHAR(10)Currency
risk_scoreNUMERIC(5,2)Computed risk score
flaggedBOOLEANWhether transaction was flagged
flag_reasonTEXTReason for flagging
reported_to_fiuBOOLEANWhether reported to FIU-IND
created_atTIMESTAMPTZTransaction time
TopicDescription
order.command.v1Order submissions (for rate tracking)
engine.event.v1Trade executions (for exposure updates)
wallet.balance_changed.v1Balance changes (for margin monitoring)
position.update.v1Position changes (for exposure tracking)
user.created.v1New users (create risk profile)
user.kyc.updated.v1KYC changes (update risk limits)
TopicDescription
risk.violation.v1Risk limit violations detected
risk.margin_call.v1Margin call triggered
risk.liquidation.v1Liquidation trigger
risk.aml.flagged.v1AML suspicious activity flagged
risk.freeze_account.v1Account freeze requested
risk.audit.events.v1Risk audit events
  1. Order Service calls PreTradeCheck(user_id, symbol, side, qty, price, leverage)
  2. Load risk_profiles for user
  3. Load current exposure_snapshots for user
  4. Validate all rules (leverage, margin, exposure, position limits, price bands, rate)
  5. If all pass: return approved = true with margin details
  6. If any fail: return approved = false with reject_reason

Target latency: < 50ms (p95)

  1. Consume position.update.v1 events
  2. Recompute per-symbol and total exposure for the user
  3. Update exposure_snapshots
  4. If margin ratio exceeds warning threshold: emit risk.margin_call.v1
  5. If margin ratio exceeds liquidation threshold: emit risk.liquidation.v1
  1. Consume wallet.balance_changed.v1 for deposits and withdrawals
  2. Apply rule-based scoring:
    • Large transaction threshold (INR 10 lakh+)
    • Velocity: > N transactions in M hours
    • Pattern matching: structuring, round-tripping
  3. If score exceeds threshold: flag transaction, emit risk.aml.flagged.v1
  4. Compliance team reviews flagged transactions
  5. If confirmed suspicious: report to FIU-IND, freeze account
MethodEndpointDescription
POST/v1/risk/pretrade-checkManual pre-trade check (admin)
POST/v1/risk/holdPlace risk hold on account
GET/v1/risk/exposure/{user_id}Get user exposure snapshot
GET/v1/risk/aml/flaggedList flagged transactions
PUT/v1/risk/rules/{symbol}Update risk rules for symbol
MetricTarget
PreTradeCheck latency (p95)< 50 ms
Exposure update latency (p95)< 500 ms
Liquidation trigger accuracy>= 99.99%
AML false positive rate< 5%
Margin call delivery< 1 second