mcSimulate

首发版本:3.00.6.4

语法

mcSimulate(evolve, initialState, timeGrid, numPaths, [numFactors=1], [params=NULL], [options=NULL])

详情

根据用户定义的状态演化函数生成完整模拟路径。函数负责生成标准正态伪随机驱动、处理随机因子相关性,并按时间网格推进状态。支持多状态、多因子、对偶变量和批次执行。

注:
  • 本函数不调用目标函数,也不计算估计值、样本方差、标准误或置信区间。

  • 当前仅支持单节点 CPU 执行,不支持 GPU 或跨节点分布式调度。

  • 参数、回调或任一批次执行失败时,整次调用失败,不返回部分路径或随机数。

参数

evolve 函数定义,指定自定义随机过程状态演化,函数签名固定为:evolve(t, state, dt, noise, params)。

参数 类型与形式 说明
t DOUBLE 标量 指定当前时间节点 timeGrid[i]。
state DOUBLE 矩阵 指定当前批次所有路径的当前状态,形状为 batchPathCount × stateDim。
dt DOUBLE 标量 指定当前时间步长度,等于相邻两个时间点之差 timeGrid[i+1] - timeGrid[i]。
noise DOUBLE 矩阵

指定当前批次的随机驱动,形状为 batchPathCount × numFactors。

  • 未指定 "corr" 时,符合标准正态分布: noise i , j ∼ N ( 0 , 1 ) \textit{noise}_{i,j} \sim N(0,1) ;
  • 指定 "corr" 时,每条路径在同一时间步的随机因子满足用户指定的相关矩阵。
params ANY 调用 mcSimulate 传入的自定义参数 params。

其中:

  • batchPathCount 为当前批次实际包含的路径数;
  • stateDim 为状态维度,等于 initialState 的元素个数,标量对应 1;
  • numFactors 为调用 mcSimulate 传入的 numFactors 参数。

evolve 每批、每个时间步调用一次,返回 batchPathCount × stateDim 的 DOUBLE 矩阵。

initialState 数值标量或向量,指定随机过程的初始状态,即 timeGrid 第一个时间点的初始状态。指定为标量时表示单状态过程,指定为向量则表示多状态过程。

timeGrid 数值向量,指定模拟时间网格。至少包含两个非 NULL 的有限数值,且严格递增。支持非等间隔时间网格。

numPaths 正 INT 或 LONG 标量,指定模拟路径总数。启用对偶变量时,必须为大于 2 的偶数。

numFactors 可选参数, INT 标量,指定每个时间步输入状态演化函数的随机因子数,默认值为 1,必须大于 0。随机因子数与状态维度相互独立。

params 可选参数, ANY 类型对象,默认值为 NULL。指定用户自定义参数对象,传递给 evolve 函数。同一次模拟中的回调应将其作为只读对象使用。

options 可选参数,字典(STRING, ANY),默认值为 NULL。支持以下键:

键 类型与形式 默认值 说明
"randomMethod" STRING "pseudo" 指定随机采样方法。当前仅支持 "pseudo",即 Pseudo Random Monte Carlo,生成标准正态伪随机驱动。
"seed" INT / LONG 自动生成 指定随机种子。未指定时由系统自动生成,并在返回结果字段 seed 中给出实际值。
"corr" 数值矩阵 NULL 指定随机因子之间的相关矩阵,维度为 numFactors × numFactors。必须对称、正定、对角线元素为 1,且不包含 NULL、NaN 或 Inf。系统在模拟开始前完成相关性分解,并将相关化后的标准正态随机驱动传入 evolve。相关性作用于随机因子,而非直接作用于状态变量。
"antithetic" BOOL false 指定是否启用对偶变量法(Antithetic Variates)。指定为 true 时启用对偶变量法,numPaths 必须为偶数且仍表示最终有效路径数,系统将基础随机驱动 Z 与 -Z 成对用于模拟。
"batchSize" INT / LONG 自动确定 指定每批有效路径数,必须大于 0,用于控制批量计算粒度和内存占用。最后一个 batch 的路径数可以小于 "batchSize"。若 batchSize > numPaths,按单批次执行。启用对偶模式时,必须为偶数。
"returnRandomNumbers" BOOL false 指定是否返回实际传入 evolve 的随机驱动。指定为 true 时结果额外包含 "randomNumbers" 键,其中已包含 Antithetic 配对和 "corr" 相关性变换后的结果。
"parallel" BOOL true 指定是否允许不同批次在本机 CPU 上并行执行。指定为 false 时串行执行。当前仅支持单节点 CPU 并行;不支持 GPU backend 和跨节点分布式调度。

返回值

返回一个字典,包含完整模拟路径以及模拟信息:

键 类型与形式 说明
"paths" ANY 向量 完整模拟路径。长度为 size(timeGrid),每个元素是 numPaths × stateDim 的 DOUBLE 矩阵。按时间顺序排列,第一个元素为初始状态矩阵,最后一个元素为终值状态矩阵。
"timeGrid" DOUBLE 向量 实际使用的时间网格
"numPaths" LONG 标量 实际生成的路径数
"numFactors" INT 标量 随机因子数
"seed" LONG 标量 实际使用的随机种子
"randomMethod" STRING 标量 当前固定为 "pseudo"
"randomNumbers" ANY 向量 实际传入状态演化函数的随机驱动。指定 returnRandomNumbers=true 时输出,长度等于 size(timeGrid) - 1,每个元素是 numPaths × numFactors 的 DOUBLE 矩阵。

例子

例 1. 生成几何布朗运动路径及随机驱动

本例用 12 个等长时间步模拟 8 条价格路径,并指定 returnRandomNumbers = true 取回每一步的随机驱动。

def gbmEvolve(t, state, dt, noise, p) {
    mu = (p["r"] - p["q"] - 0.5 * p["sigma"] * p["sigma"]) * dt
    return state * exp(mu + p["sigma"] * sqrt(dt) * noise)
}
p = dict(STRING, DOUBLE)
p["r"] = 0.03
p["q"] = 0.0
p["sigma"] = 0.20
opt = dict(STRING, ANY)
opt["seed"] = 7
opt["batchSize"] = 8
opt["returnRandomNumbers"] = true
sim = mcSimulate(gbmEvolve, 100.0, 0..12 / 12.0, 8, 1, p, opt)
[size(sim["paths"]), shape(sim["paths"][0]), size(sim["randomNumbers"]), flatten(sim["paths"][12][, 0])]
// output: [13, [8, 1], 12, [86.07027033006177, 95.76439369271459, 70.83725029862133, 124.81301557000361, 99.78994602443282, 131.41412372603514, 90.4951917379586, 86.17040506214356]]

例 2. 生成两个相关因子的对偶随机驱动

相关矩阵指定因子间相关系数为 0.5,使用两个状态和两个因子。返回随机驱动的前两行为一组对偶配对,逐因子相加为 0。

def factorEvolve(t, state, dt, noise, params) {
    return state + sqrt(dt) * noise
}
options = dict(keyType=STRING, valueType=ANY)
options["seed"] = 11
options["batchSize"] = 6
options["antithetic"] = true
options["corr"] = matrix(1.0 0.5, 0.5 1.0)
options["returnRandomNumbers"] = true
result = mcSimulate(evolve=factorEvolve, initialState=0.0 0.0,
    timeGrid=0.0 1.0, numPaths=6, numFactors=2, options=options)
noise = result["randomNumbers"][0]
[noise[0, 0] + noise[1, 0], noise[0, 1] + noise[1, 1]]
// output: [0, 0]

例 3. 一次模拟中同时给多个行权价报价

报价单上要同时报三档行权价。重复调用 monteCarlo 会重复模拟,而 mcSimulate 只模拟一次,把终值状态加工成三列样本后交给 mcEstimate 汇总——三档报价天然基于同一批路径,估计值之间的协方差也可直接使用。

def gbmEvolve(t, state, dt, noise, p) {
    return state * exp((p["rate"] - 0.5 * p["volatility"] * p["volatility"]) * dt + p["volatility"] * sqrt(dt) * noise)
}
p = dict(STRING, ANY)
p["rate"] = 0.03
p["volatility"] = 0.2
options = dict(STRING, ANY)
options["seed"] = 42
options["batchSize"] = 5000
simulation = mcSimulate(gbmEvolve, 100.0, 0..12 / 12.0, 50000, 1, p, options)
terminal = simulation["paths"][size(simulation["paths"]) - 1][, 0]
discount = exp(-p["rate"])
samples = discount * matrix(max(terminal - 90.0, 0.0), max(terminal - 100.0, 0.0), max(terminal - 110.0, 0.0))
estimate = mcEstimate(samples)
[estimate["estimate"], estimate["stdError"]]
// output: [[15.411808417905474, 9.397343043691492, 5.253868707329098], [0.075506895272312, 0.06270845678671, 0.048590695510175]]

例 4. 多状态过程的输出结构

模型自检时想确认方差路径始终非负、状态维度是否按列排列。多状态过程的每个路径切片是 numPaths × stateDim 矩阵,第 0 列是价格,第 1 列是方差。

def hestonEvolve(t, state, dt, noise, p) {
    variance = max(state[, 1], 0.0)
    nextSpot = state[, 0] * exp((p["rate"] - 0.5 * variance) * dt + sqrt(variance * dt) * noise[, 0])
    nextVariance = max(variance + p["kappa"] * (p["theta"] - variance) * dt + p["xi"] * sqrt(variance * dt) * noise[, 1], 0.0)
    return matrix(nextSpot, nextVariance)
}
p = dict(STRING, ANY)
p["rate"] = 0.03
p["kappa"] = 2.0
p["theta"] = 0.04
p["xi"] = 0.5
corrMatrix = matrix(1.0 0.0, 0.0 1.0)
corrMatrix[0, 1] = -0.7
corrMatrix[1, 0] = -0.7
options = dict(STRING, ANY)
options["seed"] = 42
options["batchSize"] = 5000
options["corr"] = corrMatrix
simulation = mcSimulate(hestonEvolve, 100.0 0.04, 0..12 / 12.0, 20000, 2, p, options)
spotPath = simulation["paths"][size(simulation["paths"]) - 1]
[size(simulation["paths"]), rows(spotPath), cols(spotPath), avg(spotPath[, 1])]
// output: [13, 20000, 2, 0.044645538557127]

相关函数: monteCarlo, mcEstimate