作用域锁投资组合
Scoped Lock Portfolio
题目详情
在量化交易中,配对交易策略需要跨多资产同时执行订单。当执行引擎并发处理成交回调时,组合持仓必须原子更新以维持准确的风险视图。
任务:实现 ScopedPortfolioLock 类,使用 scoped lock 保护多标持仓更新。当收到成交回调时,锁定所有相关标的的持仓,原子更新后释放。支持死锁检测和超时机制。
英文原题
In quantitative trading, pair trading strategies require simultaneous execution of orders across multiple assets. When execution engines process fill callbacks concurrently, portfolio positions must be updated atomically to maintain an accurate risk profile and prevent race conditions. Utilizing scoped locks ensures thread-safe updates across overlapping asset pairs while avoiding deadlocks caused by arbitrary lock acquisition orders.
Task
Implement the Portfolio class to manage positions for 1
解析
问题分析
std::scoped_lock (C++17) 可以同时锁定多个互斥锁并自动释放,避免手动 lock/unlock 顺序错误导致的死锁。在持仓更新中,需同时锁定多个账户的互斥锁以原子地更新相关头寸。
实现
class Portfolio {
std::unordered_map<std::string, std::mutex> mutexes_;
std::unordered_map<std::string, double> positions_;
public:
void transfer(const std::string& from, const std::string& to, double amount) {
std::scoped_lock lk(mutexes_[from], mutexes_[to]); // C++17: 原子锁定多锁
positions_[from] -= amount;
positions_[to] += amount;
if (positions_[from] < 0) throw std::runtime_error("Overdraft");
}
};复杂度与边界
- 时间复杂度:transfer O(1)(假设已获取锁)
- 空间复杂度:O(账户数)
- 边界条件:(1) from == to 时 scoped_lock 应处理重复锁 (2) 大额转账需先检查风控限额 (3) 异常时 scoped_lock 自动回滚
英文解析
Analysis
`std::scoped_lock` (C++17) can simultaneously lock multiple mutexes and automatically release them, avoiding manual lock/unlock ordering errors that cause deadlocks. In portfolio updates, multiple account mutexes must be locked simultaneously for atomic position transfers.
Solution
class Portfolio {
std::unordered_map<std::string, std::mutex> mutexes_;
std::unordered_map<std::string, double> positions_;
public:
void transfer(const std::string& from, const std::string& to, double amount) {
std::scoped_lock lk(mutexes_[from], mutexes_[to]); // C++17: atomic multi-lock
positions_[from] -= amount;
positions_[to] += amount;
if (positions_[from] < 0) throw std::runtime_error("Overdraft");
}
};Complexity & Edge Cases
- Time complexity: transfer O(1) (assuming locks acquired)
- Space complexity: O(account count)
- Edge cases: (1) from == to: scoped_lock handles re-locking (2) Large transfers need risk limit check first (3) Exception: scoped_lock auto-rolls back on throw
Key Considerations
- Lock ordering: Multi-asset portfolio operations must acquire locks in consistent order (e.g., by asset ID) to prevent deadlock between concurrent portfolio operations
- Lock granularity: Lock entire portfolio for cross-asset operations; lock individual position for single-asset updates — granularity choice balances concurrency vs simplicity
- RAII enforcement: scoped_lock automatically releases on scope exit; never hold portfolio lock across async operations or I/O — minimize lock hold duration
- Deadlock detection: In debug mode, track lock acquisition graph; detect potential deadlock cycles before they occur at runtime