第 6 章 · 02 多资产支持 Securities 14 类 本节摘要:本节钻取 Lean 的多资产层—— 下约 4.3 万行代码、14 个资产子目录。从股票(Equity)、外汇(Forex)、差价合约(Cfd)、加密货币(Crypto)及其期货(CryptoFuture),到期权(Option)、期货(Future)及其期权(FutureOption)、指数(Index)、指数期权(IndexOption),每类资产各有自己的 BuyingPower(保证金)、Volatility(波动率)、Positions(持仓)、Fees(手续费)配置。
本节摘要:本节钻取 Lean 的多资产层——
Common/Securities下约 4.3 万行代码、14 个资产子目录。从股票(Equity)、外汇(Forex)、差价合约(Cfd)、加密货币(Crypto)及其期货(CryptoFuture),到期权(Option)、期货(Future)及其期权(FutureOption)、指数(Index)、指数期权(IndexOption),每类资产各有自己的 BuyingPower(保证金)、Volatility(波动率)、Positions(持仓)、Fees(手续费)配置。统一的入口是Security对象——Securities[name]返回它,内含价格缓存 Cache、持仓 Holdings、交易所时段 Exchange,以及 FeeModel/FillModel/BuyingPowerModel/VolatilityModel 等可替换模型。SecurityService 是工厂,根据 Symbol 的 SecurityType 实例化对应的子类并装上默认模型。各资产还有特有数据类型(Option 有 OptionChain、Future 有 FutureChain)。读完本节,你理解了 Lean "一套引擎,14 类资产" 的抽象根基。
内容来源:原项目源码
Common/Securities/目录结构、Security.cs、SecurityService.cs、Common/Data/Market/OptionChain.cs、FuturesChain.cs,精读并套用体系化模板。
⚠️ 注意:本节是资产层的"地图",重点是 Security 对象结构 + 各资产配置差异,不展开每个模型内部算法(那是后续章节)。
阅读完本节,你应当能够:
Security 对象的关键成员(Cache/Holdings/Exchange/FeeModel 等)。Common/Securities 下一级子目录(ls 实测):
Cfd/ Forex/ FutureOption/ Option/ Crypto/ Future/ Index/ IndexOption/ CryptoFuture/ Positions/ Volatility/ Interfaces/ CurrencyConversion/ Equity/
按资产类别归类的 14 个核心子目录(部分共用基础设施如 Volatility/Positions/Interfaces):
| 资产子目录 | SecurityType | 代表标的 |
|---|---|---|
| Equity | 股票 | AAPL、MSFT |
| Forex | 外汇 | EURUSD、USDJPY |
| Cfd | 差价合约 | GER30(德指 CFD) |
| Crypto | 加密现货 | BTCUSD |
| CryptoFuture | 加密期货 | BTCUSD perp |
| Future | 期货 | ES、CL |
| FutureOption | 期货期权 | ES 期权 |
| Option | 股票期权 | AAPL 期权 |
| Index | 指数 | SPX |
| IndexOption | 指数期权 | SPX 期权 |
💡 钻取要点:之所以拆这么多子目录,是因为每类资产的"交易规则"差异巨大——股票 T+股数、外汇按手数、期货按合约乘数、期权要算希腊值。每类资产目录里都有自己的
XxxCache/XxxHolding/XxxExchange/XxxBuyerPowerModel等,继承通用基类后覆写差异部分。
每个资产子目录核心都在解决四件事:
PatternDayTradingMarginModel(美股 PDT 规则)、FutureMarginModel、OptionMarginModel。Volatility/ 下,Option 用 BlackScholes 推导的 IVolatilityModel,股票常用 RelativeStandardDeviationVolatilityModel。Positions/ 目录定义持仓抽象。股票持仓是简单股数,期权持仓还要带希腊值贡献。IFeeModel 接口,各券商费率不同,可通过 SetFeeModel() 替换(如 InteractiveBrokersFeeModel)。Common/Securities/Security.cs:47:
47 public class Security : DynamicObject, ISecurityPrice 93 public Symbol Symbol { get; } 183 public SecurityCache Cache { get; set; } // 价格缓存(最新价/历史) 193 public SecurityHolding Holdings { get; set; } // 持仓(数量/均价/盈亏) 204 public SecurityExchange Exchange { get; set; } // 交易所时段(开收盘) 220 public IFeeModel FeeModel { get; set; } // 手续费模型 229 public IFillModel FillModel { get; set; } // 成交模型(模拟滑点) 247 public ISecurityPortfolioModel PortfolioModel { get; set; } 256 public IBuyingPowerModel BuyingPowerModel { get; set; } // 保证金/购买力 265 public IBuyingPowerModel MarginModel { get; set; } // 保证金别名 283 public ISettlementModel SettlementModel { get; set; } // 资金结算 292 public IVolatilityModel VolatilityModel { get; set; } // 波动率 305 public ISecurityDataFilter DataFilter { get; set; } // 异常 tick 过滤
对照官方文档图 Documentation/4-security-object.jpg:Securities["AAPL"] 返回的 Security 对象包含——价格(走 Cache)、持仓(走 Holdings)、属性(走一系列 Model)。所有 Model 都是接口,可随时 SetFeeModel()/SetVolatilityModel()/SetBuyingPowerModel() 替换。
Security.cs:327 还有一个动态访问入口:
327 public dynamic Data { get; } // 动态访问缓存中的各类数据
Data 是 dynamic,允许算法里 Securities["AAPL"].Data.Dividend 这种写法,运行时按缓存里的实际类型派发。
Security.cs 的两个核心聚合:
183 public SecurityCache Cache { get; set; } // 缓存最近一个数据点 193 public SecurityHolding Holdings { get; set; } // 持仓对象 510 public virtual bool HoldStock => Holdings.HoldStock; // 是否持仓 541 public virtual decimal Leverage => Holdings.Leverage; // 杠杆
Securities["AAPL"].Price 实际走 Cache 的最新值。各资产子类有特化版本:EquityCache/EquityHolding、ForexHolding、OptionHolding(带希腊值)等,继承基类加字段。
Common/Securities/SecurityService.cs:31:
31 public class SecurityService : ISecurityService
它的 Create 方法是工厂——根据 Symbol 的 SecurityType 实例化对应子类并装上默认模型。SecurityService.cs:106-173 关键分派逻辑:
106 if (symbol.SecurityType == SecurityType.Base && ...) ... // 自定义 Base 113 if (symbol.ID.SecurityType == SecurityType.Forex) ... 118 if (symbol.ID.SecurityType == SecurityType.Crypto && ...) ... 127 symbol.SecurityType, 146 if (symbol.SecurityType != SecurityType.Cfd) ... // CFD 货币推导 165 bool hasDataTypes = ...; 168 sessionDataTypes = SubscriptionManager.DefaultDataTypes()[symbol.SecurityType]; 173 switch (symbol.ID.SecurityType) // 装配默认模型
Create 干三件事:
QuantConnect.Securities.Equity.Equity,Option → Option,以此类推。部分资产有"链式"数据类型,只有该资产才有:
| 资产 | 特有数据类型 | 文件 |
|---|---|---|
| Option | OptionChain / OptionContract | Common/Data/Market/OptionChain.cs |
| Future | FuturesChain / FuturesContract | Common/Data/Market/FuturesChain.cs |
| 期权/期货 | Greeks(希腊值) | Common/Data/Market/Greeks.cs |
OptionChain.cs:27:
27 public class OptionChain : BaseChain<OptionContract, OptionContracts>
FuturesChain.cs:26:
26 public class FuturesChain : BaseChain<FuturesContract, FuturesContracts>
两者都继承 BaseChain<TContract, TContracts>——一个泛型的"合约链"容器。算法里 OnData(OptionChains chains) 拿到的就是当天可交易的全部期权合约,按到期日/行权价组织。
💡 钻取要点:这种"链 + 合约"抽象让期权/期货能用同一套 API:遍历 chain 找符合行权价/到期日的合约,然后像普通 Security 一样下单。
BaseContract定义了通用合约字段(到期日、行权价、乘数),特化类再加各自字段。
算法里的典型用法:
// AddData / AddEquity 后,Securities 字典里就有 var aapl = Securities["AAPL"]; // 拿到 Security 对象 var price = aapl.Price; // 走 Cache var holding = aapl.Holdings.Quantity; // 走 Holdings var fee = aapl.FeeModel; // 拿到 FeeModel aapl.SetFeeModel(new InteractiveBrokersFeeModel()); // 替换手续费
Securities 是 SecurityManager(继承自 Dictionary<Symbol, Security>)。无论什么资产,通过 Securities[symbol] 拿到的都是同一个 Security 接口——这就是 Lean "一套引擎,14 类资产"的统一抽象。
BaseChain<T> 泛型容器。Securities[symbol] 返回 Security,所有资产一个接口。SetFeeModel()/SetVolatilityModel() 等让用户灵活定制券商行为。下一节,我们看动态选股——UniverseSelection 如何根据条件在运行中增删标的。