如果未做特别说明,文中的程序都是 Python3 代码。

QuantLib 金融计算——数学工具之优化器

载入模块

import QuantLib as ql
import scipy print(ql.__version__)
1.12

概述

在量化金融的模型校准过程中,最重要的工具是对函数 \(f : R^n \to R\) 的优化器。通常遇到的最优化问题是一个最小二乘问题。例如,寻找一个模型的参数使得某些损失函数最小化。

quantlib-python 中的最优化计算委托给 Optimizer 类,用户需要配置合适的参数以描述最优化问题,需要注意的是 Optimizer 对象默认求解的是某个函数“最小化”问题。

Optimizer

Optimizer 类的构造函数不接受参数,求解最优化问题的方式也非常简单,仅需调用 solve 函数即可:

solve(function,
c,
m,
e,
iv)
  • function:函数或函数对象,返回一个浮点数,所接受的参数是若干独立的浮点数;
  • cConstraint 对象,描述优化问题的约束条件;
  • mOptimizationMethod 对象,优化算法引擎;
  • eEndCriteria 对象,描述优化问题的终止条件;
  • ivArray 对象,优化计算的初始值。

solve 函数返回一个 Array 对象,存储找到的最小值点。

Constraint

quantlib-python 提供的具体约束条件均继承自 Constraint 类,有如下几种:

  • NoConstraint:无约束
  • PositiveConstraint:要求所有参数为正数
  • BoundaryConstraint:要求所有参数在某个区间内
  • CompositeConstraint:要求所有参数同时满足两个约束条件
  • NonhomogeneousBoundaryConstraint:对每个参数分别约束,要求其在某个区间内

OptimizationMethod

quantlib-python 提供的具体优化算法均继承自 OptimizationMethod 类,有如下几种:

  • LevenbergMarquardt:Levenberg-Marquardt 算法,实现基于 MINPACK;
  • Simplex:单纯形法;
  • ConjugateGradient:共轭梯度法;
  • SteepestDescent:最速下降法;
  • BFGS:Broyden-Fletcher-Goldfarb-Shanno 算法;
  • DifferentialEvolution:微分进化算法;
  • GaussianSimulatedAnnealing:高斯模拟退火算法;
  • MirrorGaussianSimulatedAnnealing:镜像高斯模拟退火算法;
  • LogNormalSimulatedAnnealing:对数高斯模拟退火算法。

EndCriteria

最优化计算通常是一个迭代过程,我们需要定义一个终止条件以引导最优化计算结束,否则可能一直计算下去。终止条件由 EndCriteria 类参数化,其构造函数如下

EndCriteria(maxIteration,
maxStationaryStateIterations,
rootEpsilon,
functionEpsilon,
gradientNormEpsilon)
  • maxIteration:整数,最大迭代次数;
  • maxStationaryStateIterations:整数,稳定点(函数值和根同时稳定)的最大迭代次数;
  • rootEpsilon:浮点数,当前根与最新根的绝对差小于 rootEpsilon 时停止计算;
  • functionEpsilon:浮点数,当前函数值与最新函数值的绝对差小于 functionEpsilon 时停止计算;
  • gradientNormEpsilon:浮点数,当前梯度与最新梯度差的范数小于 gradientNormEpsilon 时停止计算;

注意,对于每种优化器来讲,并不是所有参数多是必须的。

示例

Rosenbrock 问题

我们以 Rosenbrock 函数(也简称为香蕉函数)为例测试优化器,这是一个经典的优化问题。函数定义如下:

\[f(x,y) = (1-x)^2 + 100(y-x^2)^2
\]

最小值点落在 \((x,y)=(1, 1)\),此时的函数值 \(f(x,y)=0\)。

首先定义 Rosenbrock 函数,注意,每个参数是独立的浮点数。

def RosenBrockFunction(x0, x1):
res = (1 - x0) * (1 - x0) + 100.0 * (x1 - x0 * x0) * (x1 - x0 * x0) return res

接着,配置优化器,并测试 SimplexConjugateGradient 算法。初始值设定为 \((x, y) = (0.1, 0.1)\),最优化类型为“无约束”的。

例子 1

def testOptimizer1():
maxIterations = 1000
minStatIterations = 100
rootEpsilon = 1e-8
functionEpsilon = 1e-9
gradientNormEpsilon = 1e-5 myEndCrit = ql.EndCriteria(
maxIterations,
minStatIterations,
rootEpsilon,
functionEpsilon,
gradientNormEpsilon) constraint = ql.NoConstraint() solver1 = ql.Simplex(0.1)
solver2 = ql.ConjugateGradient() minimize = ql.Optimizer() min1 = minimize.solve(
function=RosenBrockFunction,
c=constraint,
m=solver1,
e=myEndCrit,
iv=ql.Array(2, 0.1)) min2 = minimize.solve(
function=RosenBrockFunction,
c=constraint,
m=solver2,
e=myEndCrit,
iv=ql.Array(2, 0.1)) print('{0:<30}{1}'.format('Root Simplex', min1))
print('{0:<30}{1}'.format('Root ConjugateGradient', min2))
print('{0:<40}{1}'.format(
'Min F Value Simplex',
RosenBrockFunction(min1[0], min1[1])))
print('{0:<40}{1}'.format(
'Min F Value ConjugateGradient',
RosenBrockFunction(min2[0], min2[1]))) testOptimizer1()
Root Simplex                  [ 1; 1 ]
Root ConjugateGradient [ 0.998904; 0.995025 ]
Min F Value Simplex 2.929205541302239e-17
Min F Value ConjugateGradient 0.0007764961476745887

校准问题

下面虚拟一个模型校准问题。假设已知 4 个看涨期权的价格 \(C_1 , C_2 , C_3 , C_4\),以及对应的敲定价 \(K_i\),未知量是股票价格 \(S_0\) 和波动率 \(\sigma\),通过解决下面的最小二乘问题来求解出 \((\sigma, S_0)\),

\[f(\sigma, S_0) = \sum_{i=1}^4 (C(K_i, \sigma, S_0) - C_i)^2
\]

首先定义损失函数(函数对象),

class CallProblemFunction(object):
def __init__(self,
rd, rf, tau, phi,
K1, K2, K3, K4,
C1, C2, C3, C4):
self.rd_ = rd
self.rf_ = rf
self.tau_ = tau
self.phi_ = phi
self.K1_ = K1
self.K2_ = K2
self.K3_ = K3
self.K4_ = K4
self.C1_ = C1
self.C2_ = C2
self.C3_ = C3
self.C4_ = C4 @staticmethod
def blackScholesPrice(spot, strike,
rd, rf,
vol, tau,
phi):
domDf = scipy.exp(-rd * tau)
forDf = scipy.exp(-rf * tau)
fwd = spot * forDf / domDf
stdDev = vol * scipy.sqrt(tau) dp = (scipy.log(fwd / strike) + 0.5 * stdDev * stdDev) / stdDev
dm = (scipy.log(fwd / strike) - 0.5 * stdDev * stdDev) / stdDev res = phi * domDf * (fwd * norm.cdf(phi * dp) - strike * norm.cdf(phi * dm)) return res def values(self,
x0,
x1):
res = ql.Array(4)
res[0] = self.blackScholesPrice(
x0, self.K1_, self.rd_, self.rf_, x1, self.tau_, self.phi_) - self.C1_
res[1] = self.blackScholesPrice(
x0, self.K2_, self.rd_, self.rf_, x1, self.tau_, self.phi_) - self.C2_
res[2] = self.blackScholesPrice(
x0, self.K3_, self.rd_, self.rf_, x1, self.tau_, self.phi_) - self.C3_
res[3] = self.blackScholesPrice(
x0, self.K4_, self.rd_, self.rf_, x1, self.tau_, self.phi_) - self.C4_ return res def __call__(self,
x0,
x1):
tmpRes = self.values(x0, x1) res = tmpRes[0] * tmpRes[0]
res += tmpRes[1] * tmpRes[1]
res += tmpRes[2] * tmpRes[2]
res += tmpRes[3] * tmpRes[3] return res

例子 2

def testOptimizer2():
spot = 98.51
vol = 0.134
K1 = 87.0
K2 = 96.0
K3 = 103.0
K4 = 110.0
rd = 0.002
rf = 0.01
phi = 1
tau = 0.6 C1 = CallProblemFunction.blackScholesPrice(
spot, K1, rd, rf, vol, tau, phi)
C2 = CallProblemFunction.blackScholesPrice(
spot, K2, rd, rf, vol, tau, phi)
C3 = CallProblemFunction.blackScholesPrice(
spot, K3, rd, rf, vol, tau, phi)
C4 = CallProblemFunction.blackScholesPrice(
spot, K4, rd, rf, vol, tau, phi) optFunc = CallProblemFunction(
rd, rf, tau, phi, K1, K2, K3, K4, C1, C2, C3, C4) maxIterations = 1000
minStatIterations = 100
rootEpsilon = 1e-5
functionEpsilon = 1e-5
gradientNormEpsilon = 1e-5 myEndCrit = ql.EndCriteria(
maxIterations,
minStatIterations,
rootEpsilon,
functionEpsilon,
gradientNormEpsilon) startVal = ql.Array(2)
startVal[0] = 80.0
startVal[1] = 0.20 constraint = ql.NoConstraint()
solver = ql.BFGS() minimize = ql.Optimizer() min1 = minimize.solve(
function=optFunc,
c=constraint,
m=solver,
e=myEndCrit,
iv=startVal) print('Root', min1)
print('Min Function Value', optFunc(min1[0], min1[1]))
Root [ 98.51; 0.134 ]
Min Function Value 5.979965971506814e-22

QuantLib 金融计算——数学工具之优化器的更多相关文章

  1. QuantLib 金融计算——数学工具之求解器

    目录 QuantLib 金融计算--数学工具之求解器 概述 调用方式 非 Newton 算法(不需要导数) Newton 算法(需要导数) 如果未做特别说明,文中的程序都是 Python3 代码. Q ...

  2. QuantLib 金融计算——数学工具之数值积分

    目录 QuantLib 金融计算--数学工具之数值积分 概述 常见积分方法 高斯积分 如果未做特别说明,文中的程序都是 Python3 代码. QuantLib 金融计算--数学工具之数值积分 载入模 ...

  3. QuantLib 金融计算——数学工具之插值

    目录 QuantLib 金融计算--数学工具之插值 概述 一维插值方法 二维插值方法 如果未做特别说明,文中的程序都是 Python3 代码. QuantLib 金融计算--数学工具之插值 载入模块 ...

  4. QuantLib 金融计算——数学工具之随机数发生器

    目录 QuantLib 金融计算--数学工具之随机数发生器 概述 伪随机数 正态分布(伪)随机数 拟随机数 HaltonRsg SobolRsg 两类随机数的收敛性比较 如果未做特别说明,文中的程序都 ...

  5. QuantLib 金融计算

    我的微信:xuruilong100 <Implementing QuantLib>译后记 QuantLib 金融计算 QuantLib 入门 基本组件之 Date 类 基本组件之 Cale ...

  6. QuantLib 金融计算——高级话题之模拟跳扩散过程

    目录 QuantLib 金融计算--高级话题之模拟跳扩散过程 跳扩散过程 模拟算法 面临的问题 "脏"的方法 "干净"的方法 实现 示例 参考文献 如果未做特别 ...

  7. QuantLib 金融计算——基本组件之 Currency 类

    目录 QuantLib 金融计算--基本组件之 Currency 类 概述 构造函数 成员函数 如果未做特别说明,文中的程序都是 python3 代码. QuantLib 金融计算--基本组件之 Cu ...

  8. QuantLib 金融计算——收益率曲线之构建曲线(2)

    目录 QuantLib 金融计算--收益率曲线之构建曲线(2) YieldTermStructure 问题描述 Piecewise** 分段收益率曲线的原理 Piecewise** 对象的构造 Fit ...

  9. QuantLib 金融计算——随机过程之概述

    目录 QuantLib 金融计算--随机过程之概述 框架 用法与接口 如果未做特别说明,文中的程序都是 Python3 代码. QuantLib 金融计算--随机过程之概述 载入模块 import Q ...

随机推荐

  1. C#多线程数据分布加载

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  2. mybatis小工具

    1.其实也不算是针对mybatis的其他都可以用 lombok 2.mybatis的小插件,可以快速定位到mapper.xml和接口之间 mybatisx

  3. Under-sampling

    Under sampling    When the signal frequency is high, and the tester frequency can’t catch the signal ...

  4. Please do not register multiple Pages in undefined.js 小程序报错的几种解决方案

    Wed Jun 27 2018 09:25:43 GMT+0800 (中国标准时间) Page 注册错误,Please do not register multiple Pages in undefi ...

  5. 09 Finding a Motif in DNA

    Problem Given two strings ss and tt, tt is a substring of ss if tt is contained as a contiguous coll ...

  6. linux 进程通信之 管道和FIFO

    进程间通信:IPC概念 IPC:Interprocess Communication,通过内核提供的缓冲区进行数据交换的机制. IPC通信的方式: pipe:管道(最简单) fifo:有名管道 mma ...

  7. EJB3.0 EJB开发消息驱动bean

    (7)EJB3.0 EJB开发消息驱动bean JMS 一: Java消息服务(Java Message Service) 二:jms中的消息 消息传递系统的中心就是消息.一条 Message 由三个 ...

  8. Buffer Pool--SQL Server:Buffer Manager 对象

    --============================================================== --参考链接:http://technet.microsoft.com ...

  9. 10-06 Linux的基本命令以及一些简单的通配符说明

    Shell的通配符 主要用于模式匹配,如:文件名匹配,路径名搜索,字符查找等.常用的有:'*','?','[]' '*':代表任意长度的字串. '?':代表单个任意字符 '[]':代表模式串匹配的字符 ...

  10. ADO.NET操作SQL Server:数据库操作类(未封装)

    1.添加数据 /// <summary> /// 添加数据 /// </summary> /// <param name="newEntity"> ...