如果未做特别说明,文中的程序都是 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. 【转载】RHEL / CentOS 7 用 Yum 安裝 MySQL 5.6

    久久未更新... 换好工作出去玩耍了一趟, 现在安装机器啦~ 装一个mysql 到centos 7, 一次转载一篇文章, 记录下: 原文地址:http://www.phpini.com/mysql/r ...

  2. 441. Arranging Coins

    static int wing=[]() { std::ios::sync_with_stdio(false); cin.tie(NULL); ; }(); class Solution { publ ...

  3. mysql 开通远程连接

    使用localhost好用,但是改成ip地址后不好用,执行sql语句做如下修改: update user set host = '%' where user = 'root'; flush privi ...

  4. canvas基础API

    1.路径绘图: 把“钢笔”移动到画布的某个位置上 ctx.moveTo(x,y) 把“钢笔”连线到画布的某个位置上 ctx.lineTo(x,y) 描边路径的api ctx.stroke() 填充路径 ...

  5. C++笔记16之const的用法总结

    const主要是为了程序的健壮型,减少程序出错. 最基本的用法: const int a=100; b的内容不变,b只能是100也就是声明一个int类型的常量(#define b =100) int  ...

  6. Spring AOP 简单入门笔记 (转)

    分享一个自己写的最为简单的Spring AOP的应用,其实,本人也是学习Spring不久,只是把一些个人的理解分享下,供参考.可能很多人刚开始不太理解到底啥是AOP,其实它也是相对 OOP来说的,类似 ...

  7. 【MVC】输出HTML内容,不输出HTML标签

    第一种方式: @Html.Raw("内容") 第二种方式 @(new HtmlString("<h1>abcd</h1>")) 第三种方 ...

  8. IOC容器之Autofac

    讲到IOC容器,就必须提到DIP(依赖倒置原则). DIP是OOD(面向对象设计)的一个重要思想,在该原则上引申出了\IOC(控制反转)\DI(依赖注入)\IOC容器. 居然讲到IOC容器,当然我们要 ...

  9. .Net 数据缓存浅析

    目录 1场景出发 1.1数据请求 1.2优化改进 2缓存 3缓存进阶 3.1缓存清除 3.2有效性 3.3线程安全 4适用场景和优劣 4.1适用场景 4.2优劣 5结语 1场景出发 1.1数据请求 小 ...

  10. Asp.NetCore取配置信息

    本文简单介绍Asp.NetCore取自定义配置信息的方法,要取配置信息首先得有配置文件. 1, 本例新建了一个TimeOut.json配置文件,和其对应的一个TimeOut类 2, 首先在Startu ...