2015年Python金融风控服务器架构回顾

2016/1/31 posted in  干货 天书

2015年,我们完成了以下的事情:

  1. 建立了一套自适应的风险监控系统。
    1. 监控主要二级市场数据,并且给出相应的VaR评估。包括沪深300,上证,深成指数,创业指数,金融指数等重要指数
    2. 采用大数据及机器学习算法去自适应快速变化的市场
    3. 2015年6.18日至2016年3月份的开始的3次股灾当中表现非常良好
  2. 完成了全基金市场的评价体系
    1. 完成了国内全部公募基金的业绩评价体系,监控了3200只基金产品
    2. 建立了国内的二级市场基金筛选体系,可以自动进行筛选和风控报警
    3. 完成了响应式的风险和估值引擎。

其中,我们的风险管理服务器在2015年金融风控服务经历了3个大的阶段

阶段一: 静态脚本时期

该时期的主要目标是解决金融产品的风险特性因子计算,参数筛选,模型建立。这个阶段的风控服务器主要任务是寻找模型,确定参数,以及数据回测。

该阶段服务架构图如下:
阶段一

由于当时金融数据部门本身的服务器编写能力不强,因此,初期为了快速搭建起相应的金融产品统一参数系统,于是采用了R语言当作脚本语言的方式计算每一只产品每一天的参数并将数据存储于一个临时的数据库。这样做的方便之处在于前台服务器可以一次性的取出所需参数。但是在使用过程中我们发现如下问题:

  1. 脚本的运行速度不够快。单一种类产品参数运行完毕最少需要15分钟。
  2. 金融数据复杂多变,经常性出现缺值,更改参数的情况。但是由于本身更新脚本的机制问题,不能实时的将最新的数据反映出来,并且定时任务为了避开软件使用高峰,采用凌晨以及上午9点更新数据,导致参数并不能及时反映产品最新情况,会造成半日至一日的延迟。并且如果数据源的数据进行更新以及修改,导致必须重新清理整个历史数据,工程巨大,长期读写生产数据库也是正常服务器不应出现的问题,因此必须采用实时响应式的处理数据。

为了满足复杂多变和数据及时性的问题,必须用实时计算服务来代替静态脚本+临时数据库的架构,因此进入第二个时期,动态响应式金融风控服务器

阶段二:动态响应式金融风控服务器

该阶段的最终架构如下:

阶段二

在建立上面的服务器时,考虑了公司发展,因此要求服务器必须满足以下几点:

  1. 快速扩展,方便部署
  2. 架构必须承受C10K以上的响应压力
  3. 数据必须实时计算用以保证金融重要参数的更新及稳定情况
  4. 必须灵活的查询历史计算记录及请求记录

需要进行新的技术选型。
先对公司本身的IT技术进行梳理

  1. 金融分析人员R语言熟练掌握
  2. 数据人员C++熟悉数值计算
  3. 分析人员数据库只能实现简单的增删改查,简单的事物处理
  4. 原本的服务器开发人员采用java作为服务器语言,但是java并不适合快速的大量的数据,金融模型的更新及开发

可见,公司本身并没有相应的金融服务器搭建及处理经验。但是为了快速的迁移以及满足未来的需求。必须采用一种金融工程,数据分析,服务器都可通用以及学习成本较低的语言。因此在进行大量的调查后,Python被选为金融服务器开发的首选语言。

Python具有以下特点:

  1. 语法简洁(用Pandas,numpy基本可以无缝迁移R代码)
  2. 极易扩展
  3. 数据挖掘工具丰富,与最新的Tenser Flow,MXNeT工具api丰富,数据爬虫方便使用
  4. 具有丰富的服务器开发库及处理能力

选定语言之后,需要开始搭建进行服务器框架设计。以实际操作当中,服务器设计应当如下:

RiskServer

一开始的python架构选型当中,我们对比了几个中文文档比较多的框架:
Django,Flask,Bottle,Tornado
大家可以看看对比。

功能测试:
http://python.jobbole.com/81396/

简单的性能测试:
http://www.vimer.cn/2014/06/python%E5%B8%B8%E7%94%A8web%E6%A1%86%E6%9E%B6%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95djangoflaskbottletornado.html

加之网上也有有大量的关于他们对比的文章,刚开始的Python不熟悉,于是采用轻量级Flask进行开发。

2个礼拜后,第一版测试的服务器产生,已经可以实时响应产品和策略的风控参数请求。进行性能测试。使用apache benchmark(“简称ab”)测试,结果惨不忍睹。

由于金融算法本身的复杂性以及巨大的计算量,核心的算法大概80-150ms处理完毕。经过ab测试发现一旦加大并发量,就会造成大量的服务延时。后来上网大量的查阅帖子,发现了一个巨大的问题,也是很多帖子一直在讨论的“异步,非阻塞”问题。 异步就是同一个服务器,在接受请求后立刻返回信息,然后再处理完成后回调接口,通知前台服务任务信息。阻塞问题就是同一个接口在上一个没有处理完的情况下能否继续接受请求。这两个问题也许在简单的博客系统,CMS下不会产生太大的问题,但是金融风控服务器必须考虑到这些问题,用以确保参数的正常访问。

必须找到相应的解决办法。

阶段三:大规模分布式实时计算风控服务器

该阶段方案如下:
stage3

在一开始的过程中,采用的折中方式是:

Flask+Tornado

但是在性能测试时发现一个重大问题:单纯的将tornado当作Http服务器使用,并不能发挥其最特色的非阻塞模型和框架,以上的方式只是发挥了http的通信服务器功能。

因此,采用如上方式,也并不能有效解决阻塞的问题,该挂起的请求还是挂起。

所以,必须从根源下手:
那就是发挥tornado 的特色,必须使用他的异步非阻塞的能力。tornado采用asynchronous IO的网络模型的方式申请资源,以便解决其宣称的异步,非阻塞问题。

取一段知乎很好的评价:

作者:KJ(Kan Jia)
直达链接

  1. 轻框架,从web.py开始,flask,bottle这些都是轻框架,tornado则是轻框架的代表
  2. 高性能异步框架,直接基于ioloop写东西,你就觉得tornado不仅仅是web框架了
  3. 队列服务器,我们实现一个两级tornado服务器模型,前面的负责web分配和并发,后面负责单线程高cpu计算,轻松解决了单线程高运算量的block问题WSGI功能可以忽略不计了理解了tornado的特性之后,我们发现唯一需要和tornado配合的就是nginx,既可以做负载均衡,又可以挡住静态文件请求。除此以外你还需要个mysql,试试torndb。使用tornado可以大大的减少web系统中使用的组件数量,用最少的代码量和极其精简的架构实现你的系统。

此过程不表,反正就是查文档吧~~~

解决问题之后,用ab测试,通过检测。
1秒轻松4000+以上的响应

分布式的部署架构可以参考下图:

DistributeServer

这样,我们就可以方便的进行运营维护和拓展了。极大地减少了运维压力

更多的问题:能否更快呢?

经过长时间的测试,并通过通过分析服务流程(pyprofile)发现金融服务器的瓶颈一般出现在如下地方:

  1. 数据库的读取和写入
    这一部分的瓶颈一般是因为数据库的水平扩容性不高,本身分布式的数据库就是一大技术难题。这里放上阿里巴巴大牛沈询的资源帖链接分布式数据库的原理与实践,里面有很多的具体的数据库瓶颈的原理与解决实践。其中现在我们在方案3里使用的DRDS就是阿里巴巴在解决双11时巨大的并发吞吐数据库时的方案。

  2. 实时金融数据接口的延迟和丢包
    这一部分其实是一个相当简单的问题。哈哈,既然找到了问题所在,那么花钱啊!买同位托管服务器啊!更好的网络供应商啊!

  3. 单次模型计算量的复杂程度
    在金融交易系统当中稳定性会是首先考量的对象,但是金融风控服务器当中,实时响应的计算结果确实更为重要的因素。比如实时响应的蒙特卡洛模拟结果,实时响应的大规模基于特定分布的随机数更能决定这个风控质量。
    因此在搭建风控服务系统的时候需要考虑更多的CPU性能极限。首选说到性能,会有很多人对于python 的性能过于担心。给大家看几个互相喷的帖子
    在大型项目上,Python 是个烂语言吗?
    Python 不能利用多核的问题以后能被解决吗?
    ……
    此类帖子数不胜数,我就不贴多了。

    不管别的领域对于Python这门语言的看法,至少在量化风控领域我是这么看的:

    1. 首先这个领域就是一个新兴领域,本身业界能熟悉从底层编译原理又到金融模型算法,又到机器学习都精通的人员并不多。因此需要一种能迅速适应和连接各大数据和金融领域的语言。(虽然作为R语言的坚定支持者,但是不得不承认R语言的服务器模块实在没有特别好用的东西)
    2. 这个领域处于一个尚未完全具有行业标准的状态,各大公司的风控系统,这里特指金融风控(财务内控不包含在内)都在建立最适合自己的管理方式
    3. 既然产品形态多变,需求多变,那就必须寻找到最适合这种变化又能最少的开发人员去上手,那么Python就是最好的选择。这个在我们公司的语言选择上就尤其突出。
    4. 本身Python语言如果对其数据结构和算法相应的熟悉一点,将关键的部分使用C或者C++完成。那些批判速度慢的人不要总是写一个20万次For循环来批判python的处理速度。为什么不用numpy的向量计算?其作为粘合剂语言的特性可以迅速的搭建一套大杀器般的多功能系统。如果很多人是个坚定地喷子,那么我还是建议你自己干嘛干嘛去吧。有瞎喷的时间可以优化很多东西。在方案3当中,我们目前采取的方法是应用CUDA将核心的随机数模块,深度学习在GPU当中完成。
    5. GIL。这个问题不该你去考虑,有这瞎想的时间,关键点已经用C++完成了。

    当你完成了以上的关键点优化,python是可以比较完美的解决核心层面的计算问题的。而且不要过早优化!!!

    过早优化是罪恶之源 ---Donald Knuth。

前期开发应该把注意力放在功能实现以及代码的可读性和可维护性上来。这样,你的新鲜模型才能获得更好的维护和更新。

最后,说一点实践当中的自己的想法和今后的展望。

今天这个帖子总算完成了,羊年的任务硬是被各种推后到了猴年,不过幸亏没有拖到“马月”。

  1. 风控领域本身是个非常郁闷的行业。就和安全一样,不出事大家觉得浪费成本,出了事怪你咋不提前把他们的手管住…………而且,个人感觉也就是2015年开始,金融行业才开始逐渐意识到风控的重要性。从p2p跑路,股灾,票据大案,呵呵,一年将风控领域的三大风险都显示的淋漓尽致。因此,我还是坚信,金融领域最重要的东西就是风控,甭管投资策略和经营模式的多么日新月异,核心就一个问题:怎么做风控?
  2. 这个领域有了越来越多的关注人士,无论是大牛也好还是刚毕业的学生也好,大家共勉。
  3. 对于2015年的工作还算是满意,我们完成了数据方面的问题。但是毕竟创业,总希望做得更好。希望在2016年可以进行可视化,并获得更多的客户订单
  4. 路漫漫其修远兮,吾将上下而求索。