编译你的工程

当创建了一个工程之后,你应该对工程进行编译,来使得工程更适合你的数据分析任务。如果不适用RiskQuantLib的编译功能,仅仅适用RiskQuantLib的预置函数和数据接口,RiskQuantLib就像一辆马车,但如果开始使用编译功能,RiskQuantLib会变成一架飞机。编译是RiskQuantLib的核心概念。通过 Build,RiskQuantLib会自动生成你需要的类文件的python代码,设定好类之间的继承关系,设定类的属性类型与名称,并且规范类与类之间的接口。但在此之前,我们先约定一些术语:

Build 即编译,它会使得RiskQuantLib自动生成类相关的python源码。

Instrument 即模板类,它是你在数据分析任务中可能用到的类的名称。对于金融数据分析,Instrument 通常指的是股票,债券,或者其他金融工具,或者是利率和发债主体等。

之后我们开始编译我们的第一个工程,其中最核心的一步是告诉RiskQuantLib如何编译,即告诉RiskQuantLib类之间的继承关系。这就需要用到工程中的 config.py 文件。这两个文件在工程的根目录下。当编译完成后,大部分自动生成的代码会被写入 RiskQuantLib.Auto 文件夹下的文件中。

在上一章,我们创建了一个新的工程,它看起来像这样::

--your_project_path
  --Cache
  --Data
  --Result
  --RiskQuantLib
  --Src
  --build.bat
  --build.py
  --config.py
  --debug.bat
  --main.py

我们将介绍这个工程中每个文件或者文件夹的功能:

RiskQuantLib

RiskQuantLib 是一个文件夹,它存放了所有RiskQuantLib的源代码文件,并且作为你项目工程的一个库存在。此时这个 RiskQuantLib 库完全是本地化的,任何工程都默认引用当前工程文件夹下的 RiskQuantLib,你可以更改其中的任何代码,来确保它适用于当前的工程。这种修改不会影响其他工程。这个文件夹的内容看起来像这样::

--RiskQuantLib
  --Auto
  --Build
  --Instrument
  --InstrumentList
  --Model
  --Operation
  --Property
  --Tool
  --__init__.py
  --module.py

Src

Src 是用于存放python源代码文件的文件夹,你可以忽略这个文件夹,它的存在不会对你的项目有任何影响。或者你可以在其中存放你的项目源代码,这些代码可以被运行或者作为库导入,这和一般的文件夹没什么区别。但 Src 文件夹还提供了一种不同的方式,帮助你管理你的代码,如果你想尝试一些新的方式,它将很适合你。

简单来说,在 Src 文件夹下面的代码都可以被RiskQuantLib解析,代码的注释可以作为控制语句,控制代码的插入位置,重复,布尔逻辑等。

最简单的使用方式是用注释来控制代码的插入位置。只要目标的.py文件在RiskQuantLib文件夹下面,你就可以将代码插入这个文件中的任何位置。你可以通过使用 #-> 注释来实现这一点。

比如,你有一个模板类,名为 stock,你希望增加一个类方法,它在 name 属性的后面增加一个字符串 _hello ,然后把生成的值保存为 greeting 属性。你可以编辑文件 RiskQuantLib/Instrument/Security/Stock.stock.py 来增加这个函数:

def sayHello(self):
    self.greeting = self.name + "_hello"

一般来说,这就是我们会做的事情。但对于在 Src 文件夹下面的源代码文件,我们可以用另一种方式来实现这个目的。首先,创建一个名为 greeting.py 的文件,然后编辑它:

#->stock
def sayHello(self):
    self.greeting = self.name + "_hello"

之后关闭文件,打开终端,将工作路径更改为当前工程的路径,然后输入命令:

python build.py

回车键运行这个命令,在 greeting.py 中的函数就会被自动插入 RiskQuantLib/Instrument/Security/Stock.stock.py,这很方便,不是么?

对于那些RiskQuantLib自动生成的模板类来说,使用类名就可以让RiskQuantLib知道你想插入的代码的位置,比如 #->stock。但如果你自己编写了一个类文件,你应该使用绝对的导入路径,来告诉RiskQuantLib到底应该把代码放在哪里。比如:#->RiskQuantLib.Instrument.Security.Stock.stock

config.py

config.py 是告知RiskQuantLib如何编译生成模板类的配置文件,当运行 build.py 之后,你在此文件中声明的所有模板类都将被创建。这些模板类的python源文件位于 RiskQuantLib 文件夹中,并且处于该模板类继承的第一个父类的文件夹里。 config.py 看起来像这样:

#!/usr/bin/python
# coding = utf-8

#-|instrument: security, company, index, interest
#-|instrument: bond@security, stock@security, derivative@security, fund@security
#-|instrument: future@derivative, option@derivative

#-|instrument-DefaultInstrumentType: security@Security, company@Company, index@Index, interest@Interest
#-|instrument-DefaultInstrumentType: bond@Bond, stock@Stock, derivative@Derivative, fund@Fund
#-|instrument-DefaultInstrumentType: future@Future, option@Option

这样的声明方式或许有些令人迷惑,但如果把它写成文件树的形式,就会清楚很多,像这样:

--instrument
  --security ( DefaultInstrumentType = Security )
    --bond ( DefaultInstrumentType = Bond )
    --stock ( DefaultInstrumentType = Stock )
    --derivative ( DefaultInstrumentType = Derivative )
      --future ( DefaultInstrumentType = Future )
      --option ( DefaultInstrumentType = Option )
    --fund ( DefaultInstrumentType = Fund )
  --company ( DefaultInstrumentType = Company )
  --index ( DefaultInstrumentType = Index )
  --interest ( DefaultInstrumentType = Interest )

config.py 文件中可以使用的关键字有两类,分别是 instrumentattribute,我们来详细介绍下它们的使用方式:

instrument

你可以任意定义 instrument 关键字之后的内容,但具体的定义方式应该取决于你的数据结构。 instrument 关键字声明的内容看起来就是一条普通的python注释,唯一不同的是,这行注释必须顶行开始,且开始的几个字符必须是 #-|#-| 又称为命令注释符,命令注释符意味着这一行注释是可以控制代码的生成方式的有意义的注释。命令注释符后面可以使用的关键字有很多,这里我们使用 instrument 关键字,然后紧跟一个冒号 : 。它们中间不能有任何的空格或者其它字符。合法的命令注释行像下面这样:

#-|instrument: instrument_a

你可以使用逗号来分隔不同的模板类声明,像这样:

#-|instrument: instrument_a, instrument_b

你可以使用@符号来声明模板类的父类,像这样:

#-|instrument: instrument_a@parent_instrument_p

如果一个模板类有超过一个父类,你应该分别声明它们,像这样:

#-|instrument: instrument_a@parent_instrument_p1, instrument_a@parent_instrument_p2

config.py 文件中声明的模板类可以告诉RiskQuantLib 如何构建你的工程项目,并且自动生成相关的模板类文件,以便于你构建数据图。比如,如果你在 config.py 文件中写了以下内容:

#-|instrument: treasureBond@bond

当进行编译后,RiskQuantLib会在 RiskQuantLib.Security.Bond.TreasureBond 路径下创建 treasureBond.py。并且在 RiskQuantLib.SecurityList.BondList.TreasureBondList 路径下创建 treasureBondList.py

@之后的内容声明了新创建的模板类如何继承自那些已经存在的类。这一列中可以填充的字符串包括 Stock, Bond, Repo 等,但是:

注意:你应该继承那些已经被声明过的模板类,你可以在当前声明语句的前方或者后面声明父模板类,但父类至少应当被声明一次:

你不可以用 反斜杠 或者 / 符号来换行进行声明。如果声明过长,你应该重新使用关键字另起一条声明。比如这样:

#-|instrument: treasureBondOne@bond
#-|instrument: treasureBondTwo@bond

attribute

attribute 关键字用于声明你需要的属性的名称,以及这些属性属于哪个模板类。当运行了 build.py 后,声明的属性将会被注册并且你可以使用 set 函数族来对这些属性进行赋值。

attribute 关键字声明的内容看起来就是一条普通的python注释,唯一不同的是,这行注释必须顶行开始,且开始的几个字符必须是 #-|#-| 又称为命令注释符,命令注释符意味着这一行注释是可以控制代码的生成方式的有意义的注释。命令注释符后面可以使用的关键字有很多,这里我们使用 attribute 关键字,然后紧跟一个冒号 : 。它们中间不能有任何的空格或者其它字符。合法的命令注释行像下面这样:

#-|attribute: fund.yourAttribute

这条声明将会在 fund 模板类上添加 yourAttribute 属性。

你可以使用逗号来分隔不同的属性声明,像这样:

#-|attribute: fund.yourAttribute, stock.anotherAttribute

你可以使用@来声明当前属性的数据类型,像这样:

#-|attribute: fund.yourAttribute@number, stock.anotherAttribute@string

@后面可以填充的字符串包括 number, string, series。或者是其他任何你认为可以作为数据类型的字符串。它告诉RiskQuantLib在此属性上存储的值应该是什么数据类型。如果你使用了RiskQuantLib预置的数据类型以外的数据类型,那么当编译之后,新的模板数据类型将会被创建,它也是一个类文件,你可以在 RiskQuantLib.Property 文件夹下找到。

#-|attribute: fund.yourAttribute@my_new_data_type

数据类型告诉RiskQuantLib到底应该在这个属性上以何种方式来存储数据。如果你为 stock 模板类添加了名为sellPrice的属性,考虑到价格应该是一个数字,那么@之后应该写 number,但如果属性名为issuerName,数据类型应该是 string,如果属性名为sellPriceOfPastSixMonth,那么数据类型应该是 series

这里说的数据类型不仅仅是一个数据类型。RiskQuantLib是被设计用来进行图数据处理的。这里的数据类型也是数据图的一个终端节点类。我们会在之后的章节介绍。

注意:你应该仅仅向那些被声明过的模板类添加属性。你可以当前属性声明的前面或后面进行模板类的声明,但至少应该声明那个模板类一次。

你不可以用 反斜杠 或者 / 符号来换行进行声明。如果声明过长,你应该重新使用关键字另起一条声明。比如这样:

#-|attribute: fund.yourAttributeOne
#-|attribute: fund.yourAttributeTwo

instrument-DefaultInstrumentType

这个关键字用来为声明的模板类提供一个简称,它只是作为一个标签,没有更多的其它功能。使用它的例子如下:

#-|instrument-DefaultInstrumentType: instrument_a@another_name_of_instrument_a

instrument-ParentQuantLibClassName

这个关键字是用来声明新的模板类如何继承自QuantLib的预置类。这一列中可以填充的字符串有:Instrument, Bond 等,你需要参考QuantLib的文档来查找到底可以继承自哪些QuantLib类。使用它的例子如下:

#-|instrument-ParentQuantLibClassName: my_bond@Bond

instrument-LibraryName

这个关键字是告诉RiskQuantLib调用哪些外部库,比如numpy,pandas等。使用它的例子如下:

#-|instrument-LibraryName: instrument_a@tensorflow as tf

build.py

build.py 是用于编译整个RiskQuantLib工程的,当你已经声明了编译的规则之后,通过在终端运行如下命令来进行编译::

python build.py

注意:如果你不使用Src文件夹,或者在Src文件夹下面的源文件中不使用控制注释语句,那么通常项目只会在开始时执行一次编译,而不是在每次运行main.py的时候都执行编译,那样做是不必要的。但如果你使用控制注释语句,你可以使用下面的命令来自动编译整个工程,每当你对Src文件夹的任何文件进行修改,它都会重新编译:

python build.py -a

如果你的项目还处于活跃的开发期,那么使用调试模式是非常有必要的。在调试模式下,Src 文件夹中的代码不会被作为代码块直接插入目标源文件,他们会被当成是一个模组,直接导入到目标位置,然后动态绑定给类。这使得 Src 文件夹下面的任何源文件中的断点可以生效,以便于你直接在 Src 文件夹下面进行代码修改和调试。当然,自动编译依然可以使用,每当你对源代码进行编辑,它都会自动编译整个工程。如果想要进入自动调试模式,可以使用下面的代码:

python build.py -a -d

或者在windows系统中,你可以直接双击以下文件来打开调试模式:

debug.bat

main.py

main.py 是整个项目的入口,你可以在这个文件中开始编辑数据处理相关代码。

from RiskQuantLib.module import *

然后你可以直接使用模板类,只需要::

bondA = treasureBond('firstBond','nameOfFirstBond')

你可以直接使用set函数族来设定属性,像这样::

stockA = stock('firstStock','nameOfFirstStock')
stockA.setAnotherAttribute('valueOfAnotherAttribute')

如果需要了解更多关于 Instrument (模板类)的信息,我们将在下一章介绍。

Data

这是个用于存放数据的文件夹,默认为空。

Cache

这是个用于存放缓存的文件夹,默认为空。

Result

这是个用于存放结果的文件夹,默认为空。

build.bat

当你在 config.py 声明了所有需要的模板类和属性后,你可以双击 build.bat 来进行构建。当然,只有在windows系统中初始化的RiskQuantLib项目中才会有这个文件。

debug.bat

当你在 config.py 声明了所有需要的模板类和属性后,你可以双击 debug.bat 来进行调试。当然,只有在windows系统中初始化的RiskQuantLib项目中才会有这个文件。

调试和构建的不同之处在于,调试模式下,Src 文件下的代码会被加载成为模组,然后导入主函数运行。而构建模式下,Src 文件夹下面的代码会被当作代码块 chunk 进行分发。