在金融领域,合约的估值计算是个常见需求。几百万个合约,由于到期时间和期限长短不同,计算时往往对应不同的利率。合约匹配利率,最常见的做法是通过循环语句对每一个合约做计算。而 DolphinDB 中,可以通过强大的表连接函数,将需要的信息关联后,再通过 SQL向量编程 进行计算。该优化方法相比循环的方法,性能提升超 400 倍

本文包含的主要内容有:外汇掉期估值的计算逻辑及数据准备、开发环境配置、外汇掉期估值的普通实现和优化实现等。

本文中的脚本在 DolphinDB 1.30.18/2.00.6 及以上版本的环境中测试通过。


1. 外汇掉期估值的计算逻辑及数据准备

1.1 外汇掉期估值的计算逻辑

本次的计算整体逻辑如下图:

本次外汇掉期估值计算的逻辑,参考中国外汇交易中心2019年4月2日在官网推出的外汇掉期估值服务中的估值算法,即通过掉期曲线计算当日的远端全价汇率折算,并与约定交易的全价汇率生成的现金流轧差得到净值,再用当日的 Shibor3M(Shanghai Interbank Offered Rate) 利率互换收盘曲线进行贴现,最后得到合约净额的贴现值即为合约估值。

1.2 数据准备

外汇掉期估值的计算需要用到掉期曲线利率以及利率互换曲线两张表。以上两张表的数据直接采集于2021年12月14日中国外汇掉期USD.CNY外汇掉期曲线及Shibor3M利率互换行情曲线。

数据结构分别为:

  • USD.CNY外汇掉期曲线:
name typeString comment
Date DATE 日期
timeminute MINUTE 时间
currencyPair STRING 货币对
termToMaturity STRING 期限品种
swapRate_Pips DOUBLE 掉期点
exchangeRate DOUBLE 全价汇率
maturityDate DATE 远端起息日
  • Shibor3M利率互换行情曲线:
name typeString comment
Maturity STRING 标准期限
buying_rate DOUBLE 报买(%)
average_rate DOUBLE 均值(%)
selling_rate DOUBLE 报卖(%)

本教程用到的合约数据为自行模拟的100万个不同到期期限的合约数据,数据结构为:

name typeString comment
contract_no INT 合约编号
contract_date DATE 合约日
trade_date DATE 近端起息日
maturity_date DATE 远端起息日
buy_sell STRING 买卖方向
period STRING 期限
near_leg_currency STRING 近端交易货币
near_leg_amount INT 交易量
near_leg_spot_rate DOUBLE 近端掉期全价汇率
far_leg_currency STRING 远端清算货币
far_leg_spot_rate DOUBLE 远端掉期全价汇率

上述利率数据以及模拟合约数据的脚本请参阅数据准备脚本。

2. 开发环境配置

2.1 DolphinDB server服务器环境

  • CPU 类型:Intel(R) Xeon(R) Silver 4216 CPU @ 2.10GHz
  • 逻辑 CPU 总数:8
  • 内存:64GB
  • OS:64位 CentOS Linux 7 (Core)

2.2 DolphinDB server部署

  • server版本:1.30.18 或 2.00.6
  • server部署模式:单节点
  • 配置文件:dolphindb.cfg
localSite=localhost:8848:local8848
mode=single
maxMemSize=64
maxConnections=512
workerNum=8
localExecutors=7
newValuePartitionPolicy=add
webWorkerNum=2
dataSync=1

单节点部署教程:单节点部署

3. 外汇掉期估值的普通实现

由于每一个合约有不同的起息日和合约期限,因此会对应不同的互换利率以及全价汇率。普通的实现方法是自定义一个包含估值计算逻辑的函数,通过循环语句,将每个合约与对应利率进行计算。

包含三表的估值函数定义如下:

def valuationDtmRate(today, swap_rate, IR_swap, maturity_date,far_leg_spot_rate, near_leg_amount){target_swap_rate_next = select * from swap_rate where Date=today, currencyPair = `USD.CNY, maturityDate >=maturity_date limit 1target_swap_rate_prev = select * from swap_rate where Date=today, currencyPair = `USD.CNY, maturityDate <=maturity_date order by maturityDate desc limit 1tartget_IR_swap = select * from IR_swap where Maturity in (target_swap_rate_prev.termToMaturity[0],target_swap_rate_next.termToMaturity[0])fex = target_swap_rate_prev.exchangeRate +(maturity_date - target_swap_rate_prev.maturityDate)\ (target_swap_rate_next.maturityDate-target_swap_rate_prev.maturityDate) * (target_swap_rate_next.exchangeRate - target_swap_rate_prev.exchangeRate)sir = tartget_IR_swap.selling_rate[0] + (maturity_date - target_swap_rate_prev.maturityDate)\ (target_swap_rate_next.maturityDate-target_swap_rate_prev.maturityDate) * ( tartget_IR_swap.selling_rate[1] -  tartget_IR_swap.selling_rate[0])dicount_factor = exp(-sir \ 100 * (maturity_date-today)\365)valuation = (fex - far_leg_spot_rate) * dicount_factor * near_leg_amountreturn valuation
}

由于涉及到多表间的信息提取,函数看起来会相对复杂。做完这一步之后,就可以对所有的合约进行循环计算。100万个合约在测试环境下做计算耗时约3分20秒。

for循环写法的代码示例如下:

today = 2021.12.14
k = array(DOUBLE, 0)
for (x in fx_contract){k.append!(valuationDtmRate(today, swap_rate, IR_swap,x.maturity_date, x.far_leg_spot_rate, x.near_leg_amount))
}
result = fx_contract join table(k as valuation)

或用loop函数的写法示例如下:

k = loop(valuationDtmRate{today, swap_rate, IR_swap},fx_contract.maturity_date, fx_contract.far_leg_spot_rate, fx_contract.near_leg_amount).flatten()
result = fx_contract join table(k as valuation)

利用多线程并行计算,可以在同样的计算逻辑上做进一步优化,将原本的单线程循环改成多线程并行计算,最后将结果进行拼接。DolphinDB 提供了 ploop/peach 函数,可以很方便的把这类循环语句内存计算转换成多线程任务。

此例用了8个并行度做计算,最后耗时大约20秒:

k = ploop(valuationDtmRate{today, swap_rate, IR_swap},fx_contract.maturity_date, fx_contract.far_leg_spot_rate, fx_contract.near_leg_amount).flatten()
result = fx_contract join table(k as valuation)

注意: ploop/ peach 的并行度由配置文件中的 localExecutors 控制,默认值是 CPU 内核数减1。在批流一体的因子实现中,不建议使用  ploop/ peach 并行加速。具体并行策略可以参考因子最佳实践中的 并行计算章节。

4. 外汇掉期估值的优化实现

DolphinDB 中提供了许多表关联函数,故原本的两张小表 swap_rate 和 IR_rate 以及合约大表,可以先通过表关联函数将有效信息提取出来,继而直接通过 SQL 做计算即可。如此一来,避免了循环语句重复消耗资源,也减少了代码的开发量。

做外汇掉期估值计算时,可以用 equal join , asof join 及 window join 将需要的远端利率等信息通过三表关联得到,代码如下:

today = 2021.12.14
tmp = select * from ej(swap_rate,IR_swap,`termToMaturity, `Maturity) where Date = today
res_aj=aj(fx_contract,tmp, `maturity_date, `maturityDate)
res_wj=wj(res_aj,tmp, 0d:366d,<[first(termToMaturity) as next_termToMaturity, first(exchangeRate) as next_exchangeRate, first(maturityDate) as next_maturityDate,first(buying_rate) as next_buying_rate, first(average_rate) as next_average_rate, first(selling_rate) as next_selling_rate]>, `maturity_date, `maturityDate)

由于关联后的信息可以在一张表( res_wj )中得到,故计算逻辑也可以得到简化,可以直观地翻译原公式逻辑进行向量化计算:

def valuationSQL(exchangeRate,maturity_date, maturityDate, next_maturityDate, next_exchangeRate, far_leg_spot_rate, selling_rate, next_selling_rate,today, near_leg_amount){return (exchangeRate + (maturity_date - maturityDate)\ (next_maturityDate-maturityDate) * (next_exchangeRate - exchangeRate) - far_leg_spot_rate) * exp(-(selling_rate +  (maturity_date - maturityDate)\ (next_maturityDate-maturityDate) * (next_selling_rate - selling_rate))\100 * (maturity_date-today)\365) * near_leg_amount
}

用优化后的表关联逻辑做外汇掉期估值计算,整体耗时只需0.5秒左右,性能相比最初提升了超400倍。

timer{today = 2021.12.14tmp = select * from ej(swap_rate,IR_swap,`termToMaturity, `Maturity) where Date = todayres_aj=aj(fx_contract,tmp, `maturity_date, `maturityDate)res_wj=wj(res_aj,tmp, 0d:366d,<[first(termToMaturity) as next_termToMaturity, first(exchangeRate) as next_exchangeRate, first(maturityDate) as next_maturityDate,first(buying_rate) as next_buying_rate, first(average_rate) as next_average_rate, first(selling_rate) as next_selling_rate]>, `maturity_date, `maturityDate)result = select contract_no,contract_date,trade_date,maturity_date,buy_sell, period, near_leg_currency, near_leg_amount, near_leg_spot_rate, far_leg_currency, far_leg_spot_rate, valuationSQL(exchangeRate,maturity_date, maturityDate, next_maturityDate, next_exchangeRate, far_leg_spot_rate, selling_rate, next_selling_rate,today, near_leg_amount) as valuation from res_wj
}

5. 总结

对于需要用到多表数据计算的任务,用循环语句的方式性能较差。建议先用 DolphinDB 优化的 asof join 等表关联函数将需要的信息提取asof join 等表关联函数亦支持分布式关联,对于存储于数据库中的分布式表也可以多线程并行关联,性能卓越。计算部分建议使用 SQL 向量化编程的方式做计算,不仅可以减少代码开发量(基本可以直观地翻译计算公式),也避免了循环语句重复消耗 CPU 资源。

6. 代码附录

数据准备脚本

外汇掉期估值的优化实现脚本

完整优化过程

性能提升400倍丨外汇掉期估值计算优化案例相关推荐

  1. 性能提升30倍丨基于 DolphinDB 的 mytt 指标库实现

    MyTT 是一个简单易用的 Python 库,它将通达信.同花顺.文华麦语言等指标公式最简化移植到了 Python 中,实现的常见指标包括 MACD.RSI.BOLL.ATR.KDJ.CCI.PSY ...

  2. nginx php7提速,nginx+php7-fpm 性能提升几倍跟踪实践结果并优化

    nginx+php7-fpm 性能提升几倍跟踪实践结果并优化 nginx+php7-fpm 性能提升几倍,跟踪实践结果并优化 历史ubuntu服务器使用的apache+php5,现在使用nginux+ ...

  3. 大叔也说并行和串行`性能提升N倍(N由操作系统位数和cpu核数决定)

    并行是.net4.5主打的技术,同时被封装到了System.Threading.Tasks命名空间下,对外提供了静态类Parallel,我们可以直接使用它的静态方法,它可以并行一个委托数组,或者一个I ...

  4. Nacos 2.0 性能提升十倍,贡献者 80% 以上来自阿里之外

    来源 | 阿里巴巴云原生公众号 3 月 20 日,Nacos 2.0 正式发布.Nacos 是阿里巴巴在 2018 年开源的一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台,也可以理解为 ...

  5. Hologres揭秘:优化COPY,批量导入性能提升5倍+

    简介:揭秘Hologres优化COPY的技术原理,实现批量导入性能提升5倍+ Hologres(中文名交互式分析)是阿里云自研的一站式实时数仓,这个云原生系统融合了实时服务和分析大数据的场景,全面兼容 ...

  6. 重磅官宣:Nacos2.0性能提升10倍

    简介:​Nacos2.0 作为一个跨代版本,彻底解决了 Nacos1.X 的性能问题,将性能提升了 10 倍. 作者:席翁 继 Nacos 1.0 发布以来,Nacos 迅速被成千上万家企业采用,并构 ...

  7. 重磅官宣:Nacos2.0发布,性能提升10倍

    简介: ​Nacos2.0 作为一个跨代版本,彻底解决了 Nacos1.X 的性能问题,将性能提升了 10 倍. 作者:席翁 继 Nacos 1.0 发布以来,Nacos 迅速被成千上万家企业采用,并 ...

  8. SQLite性能提升10倍的Web数据库

    作者 | James Long 译者 | 弯月 出品 | CSDN(ID:CSDNnews) 最近我开发了一款名为absurd-sql的SQLite后端.在这款工具的帮助下,你无需将整个数据库加载到内 ...

  9. 本周AI热点回顾:百度推出全球首个mRNA疫苗不稳定性解决方案、性能提升20倍:英伟达GPU旗舰A100

    01 百度推出全球首个mRNA疫苗不稳定性解决方案LinearDesign 新冠疫情爆发后,RNA设计领域世界知名专家.斯坦福大学生物化学系Rhiju Das教授关注到疫苗研发存在的一个非常棘手的问题 ...

最新文章

  1. python实现随机森林、逻辑回归和朴素贝叶斯的新闻文本分类
  2. 网络数据注入工具HexInject
  3. .NET小笔记之程序集
  4. QT5 中文乱码问题
  5. c语言课程设计作业摇一摇,口才星教案第二册.doc
  6. oppo专用计算机,OPPO手机助手
  7. android 写字体投影,android-给字体设置投影
  8. django上传文件到服务器,如何用django将文件上传到服务器?
  9. 重学Java 8新特性 | 第1讲——我们为什么要学习Java 8新特性?
  10. ubuntu 12.04下Trackpoint 小红点灵敏度和速度调整
  11. 杀死一只知更鸟 影评
  12. 一款好用的手机云便签APP和电脑云便签软件
  13. python 微信撤回消息
  14. Hadoop生态圈:19个让大象飞起来的工具!
  15. JS Event Propagation (bubbling and capture)
  16. 为什么微信显示这个android设备,微信显示安卓手机型号在哪设置
  17. 计算机考研 东华大学,2017考研:计算机科学与技术专业考研院校推荐之东华大学...
  18. 跟这台计算机连接的一个USB设备运行不正常,Windows无法识别
  19. 自定义View中,四个参数的构造函数,其最后两个参数的含义
  20. 计算机单词正确的打开方式是怎样的?

热门文章

  1. 图片解码python
  2. HTTP协议,Servlet
  3. git 撤销全部的commit_git 撤消操作所有
  4. 密码学上的commitment
  5. 加速“碳中和”丨PIX自动驾驶签约亿利生物,联合打造荒漠植树无人车
  6. “百合杯“表彰典礼即将于电影频道播出
  7. linux下搭建vsftp锁定根目录,Linux下创建ftp用户并锁定根目录
  8. 计算机工作健康危害,电脑对健康的危害有哪些 这些危害勿轻视
  9. 世上最详细的git原理解释
  10. 有了这 27 个Linux 技巧,让你工作效率翻倍!