muse-lang 0.6.3
Mini language for data analysis of asset management.
Requires Python: >=3.8

# 资管行业金融服务微语言设计

[TOC]

### 1 写在前面

​	本文档是一种人机交互语言的描述和概念设计文档。我们致力于设计出这样一种人机交互语言：

1. <u>服务于泛资产管理行业的微语言(Mini-language)</u>：语言中定义了资管行业特定的术语和场景，无法直接应用于其他行业和领域；
2. <u>非全图灵机(Complete-Turing)的描述型(Descriptive)语言</u>：每个场景描述针对特定金融对象、特定时间维度、特定指标集，没有判断条件、循环条件等全图灵语言必要的语法支持；
3. <u>业务人员能直接使用的语言</u>：语言设计的根本原则为简洁、丰富的场景表现力及卓越性能，这些特性允许无计算机及编程背景的业务人员可直接使用该语言开展工作；

### 2 为什么再发明一门新语言

​	我们已经有太多的人机交互语言了，为什么还要费力气再发明一个呢？你能保证这个比其他别的语言好？首先我们绝对没有足够的自信、勇气和时间，再发明一种像Python一样具有广泛用途的全图灵语言。我们只是聚焦在泛资管行业，针对该行业内特定场景和数据对象，创造一种描述型的微语言。这门语言应该解决如下特定问题：

- 提高金融指标提取和数据计算的抽象级，从而高效的使用、整合指标库、算法库和标签库等基础资源
- 将特定场景，如合规限额指标计算、压测指标计算、全面风险监控的指标描述、指标计算方式统一，降低开发、测试和维护的成本

### 3 语言构成

​	我们规定本语言运行的最小逻辑单元称为一个“<u>**计算场景（Logic Cell）**</u>”。一个计算场景中，包含特定如下组成部分（下图演示了一个计算场景的处理过程）：

1. 金融对象(Object): 用不同类型对象标签过滤金融对象，此类金融对象包括 产品、资产、主体、交易等
2. 时间维度(Time): 该维度将作用于整个计算场景，常见的时间维度定义包括开始日、结束日、时间频率、日历类型等，
3. 金融指标(Metric): 金融对象下特定的金融指标，不同金融对象应该通过指标库已经定义了不同的指标集
4. 场景下指标(Indicator)：使用金融对象(Object)、时间维度(Time)、金融指标(Indicator)这三个维度，可以唯一确定该计算场景下所需的数据集合，将金融函数(Function)和四则运算作用于该特定数据集合，计算出场景下特定指标
5. 监控规则(Rule)：在场景特定指标下进行监控规则判断，最终得到规则判断后的场景结果

以下结构在最高抽象级定义了语言中一个计算场景的完整语言结构：

```python
时间维度定义(Time)
Function(四则运算(Object.Metric)) 四则运算 Function(四则运算(Object.Metric))
监控规则(Rule)
```

以下章节分别就时间维度、金融对象、金融指标、金融函数及监控规则的设计展开进行详细论述。

### 4 时间维度(Time)

#### 4.1 时间维度概念

​	时间维度是金融模型及指标计算的重要维度。从数据结果的时间性质上看，时间维度有两种表现形式，一种为时间序列数据，一种为时点截面数据。为了保证体系和应用的一致性，该语言中将时点数据当成一种特殊形式的时序数据处理。在一个<u>**计算场景(Logic Cell)**</u>中，只能有且只有一个时间维度定义，该时间维度将应用于同一计算场景的金融对象标签筛选、金融指标提取及金融函数处理等环节。

#### 4.2 时间维度定义

- 开始日期 = 字符串 ｜  时间函数
  - 字符串格式为：‘YYYY-MM-dd’，表示年-月-日信息
  - 时间函数可选择：平台日(), 近1月(), 近3月(), 近半年(), 近1年(), 近3年()，后续可根据情况添加时间函数
  - 如果不定义开始日期，开始日期的默认值为 – 平台日()
- 结束日期 = 字符串 ｜  时间函
  - 字符串格式为：‘YYYY-MM-dd’，表示年-月-日信息
  - 时间函数可选择：平台日(), 近1月(), 近3月(), 近半年(), 近1年(), 近3年()，后续可根据情况添加时间函数
  - 如果不定义结束日期，结束日期的默认值为 – 平台日()
- 时序频率 = ‘数字 + 时间频率字母’
  - 时序频率表示在开始日和结束日之间，时点出现的频率，最终影响统计期间的数据样本数量
  - 时间频率字母包括：D(自然日), B(工作日-根据交易日历计算), MS(月初), ME(月末), QS(季初), QE(季末), YS(年初), YE(年末)
- 交易日历 = 字符串
  - 字符串指定交易日历，如果不定义交易日历则默认为系统指定交易日历

#### 4.3 示例应用

> 计算场景要求定义如下时间维度：以当前日期为基础，近3个月，提取每月月初数据

```python
开始日期 = 近3月(平台日())
结束日期 = 平台日()
时序频率 = '1MS'
交易日历 = '交易所交易日历'
# 假设平台日为2024-06-01，该时间维度定义将得到如下时序点
# ['2024-03-01', '2024-04-01', '2024-05-08']
```



### 5 金融对象(Object)

#### 5.1 金融对象概念

​	金融对象特指资产管理行业创建、使用、维护的业务对象，此类对象包括但不限于，产品(组合), 资产，主体、交易、指令等。在一个计算场景中(Logic Cell)中需要首先指定生成相关指标的金融对象。目前语言中支持的金融对象，包括产品、资产、主体，未来可以根据需求增加其他相关金融对象的支持。

#### 5.2 金融对象标签

​	不同的金融对象通过不同类型的“标签”进行筛选和过滤。一个标签实际是不同金融对象要素的逻辑规则的集合，例如通过如下逻辑规则，我们可以定义一个1年内到期且主体评级为AAA级的债券资产标签。金融对象的标签库在数据平台统一配置和管理，注意在语言内部不进行标签的定义，但需要内置关键字以便直接使用标签来过滤金融对象。

```python
# 1年内到期且主体评级为AAA级的债券资产标签定义如下
资产.资产大类 == '债券' and 资产.剩余天数 < 365 and 资产.主体评级 == 'AAA' 
# 定期开放型公募理财产品标签定义如下
产品.募集类型 == '公开募集' and 产品.开放方式 == '定期开放'
```

#### 5.3 使用标签函数筛选金融对象

##### 5.3.1 "产品“标签筛选产品

###### 调用方法

$$
产品([产品标签1, 产品标签2, ..., 产品标签n], 去重=True)
$$

###### 输入参数

- **标签列表**：列表中的每个元素表示一个产品类标签，每个标签之间的关系为并集关系；当标签列表为空[]时，表示获取所有有效产品列表
- **去重**：当通过标签列表选择的产品有重复（同一个产品在不同的标签中），该参数表示是否将重复的产品去掉。当在整体角度进行统计，不能有重复的情况下，可以将去重设置成True；当关心产品标签的各标签维度统计正确时，可以将去重设置为False。

###### 输出结果

- 二维表格数据，返回符合相应产品标签要求的产品列表。该二维表包括3列，分别为产品代码、产品简称及产品标签。以下为输出示例(日期列根据计算场景中时间维度定义自动获得)：

| 产品代码 | 产品简称 | 产品标签  | 日期       |
| -------- | -------- | --------- | ---------- |
| P001     | 产品1    | 产品标签1 | YYYY-MM-dd |
| P002     | 产品2    | 产品标签2 | YYYY-MM-dd |
| P00n     | 产品n    | 产品标签n | YYYY-MM-dd |

###### 示例应用

> 获取所有开放式公募产品

```python
产品(['开放式公募产品'])
```

> 获取所有固收和权益类产品，且不去重其中重复的产品

```python
产品(['固收类产品', '权益类产品'], 去重=False)
```

##### 5.3.2 “资产”标签筛选资产

###### 调用方法

$$
资产([资产标签1,...,资产标签n], 穿透=False, 去重=True)\ in \ 产品([产品标签1, 产品标签2, ..., 产品标签n], 去重=True)
$$

> [!NOTE]
>
> 当一个金融对象同另外的金融对象有包含关系时，例如一个资产通过持仓包含于一个产品时，可使用关键字**in**来描述此种包含关系，且包含关系可以进行嵌套。

###### 输入参数

- **标签列表**：列表中的每个元素表示一个资产类标签，每个标签之间的关系为并集关系；当标签列表为空[]时，表示获取所有当前持仓的资产列表
- **去重**：当通过标签列表选择的资产有重复（同一个资产在不同的标签中），该参数表示是否将重复的资产去掉。当在整体角度进行统计，不能有重复的情况下，可以将去重设置成True；当关心资产标签的各标签维度统计正确时，可以将去重设置为False。
- **穿透**：True为穿透获取资产，False为不穿透获取资产；默认值为False

###### 输出结果

- 二维表格数据，返回符合相应资产标签要求的资产列表。该二维表原生包括3列，分别为资产代码、资产简称及资产标签。如果使用in关键字关联了产品选择，则会多出产品筛选的相关字段。以下为输出示例(日期列根据计算场景中时间维度定义自动获得，且用in关键字关联了相关产品)：

| 资产代码 | 资产简称 | 资产标签  | 产品代码 | 产品简称 | 产品标签  | 日期       |
| -------- | -------- | --------- | -------- | -------- | --------- | ---------- |
| A001     | 资产1    | 资产标签1 | P001     | 产品1    | 产品标签1 | YYYY-MM-dd |
| A002     | 资产2    | 资产标签2 | P002     | 产品2    | 产品标签2 | YYYY-MM-dd |
| A003     | 资产3    | 资产标签3 | P00n     | 产品n    | 产品标签n | YYYY-MM-dd |

###### 示例应用

> 获取现金管理类产品中的固定期限银行存款（穿透后）

```python
资产(['固定期限银行存款'], 穿透=True) in 产品(['现金管理类产品'])
```

> 获取现金管理类产品中的现金、国债、中央银行票据、政策性金融债及5个交易日内到期的金融工具(穿透前)

```python
资产(['现金', '国债', '中央银行票据', '政策性金融债', '5个交易日内到期的金融工具']) in 产品(['现金管理类产品'])
```

##### 5.3.3 “主体”标签筛选主体

###### 调用方法

$$
主体([资产标签n,...,主体标签n], 穿透=False, 去重=True)\ in \ 产品([产品标签1, 产品标签2, ..., 产品标签n], 去重=True)
$$

> [!NOTE]
>
> 主体对于不同的金融资产具有不同的含义，例如债券资产的主体为债券发行人，公募基金的主体为基金公司，资产支持证券的主体为实际信用承担方，银行存款的主体是相应的商业银行。在数据处理阶段，应该将每种资产类型的主体统一进行维护和管理。在本语言中，不包括主体的定义和维护部分。

###### 输入参数

- **标签列表**：列表中的每个元素表示一个资产类标签或主体类标签，每个标签之间的关系为并集关系；当标签列表为空[]时，表示获取所有当前持仓的主体列表
- **去重**：当通过标签列表选择的资产有重复（同一个主体在不同的标签中），该参数表示是否将重复的主体去掉。当在整体角度进行统计，不能有重复的情况下，可以将去重设置成True；当关心主体标签的各标签维度统计正确时，可以将去重设置为False。
- **穿透**：True为穿透获取资产，False为不穿透获取资产；默认值为False

###### 输出结果

- 二维表格数据，返回符合相应资产标签要求的主体列表。该二维表原生包括3列，分别为主体代码、主体简称及主体标签。如果使用in关键字关联了产品选择，则会多出产品筛选的相关字段。以下为输出示例(日期列根据计算场景中时间维度定义自动获得，且用in关键字关联了相关产品)：

| 主体代码 | 主体简称 | 主体标签  | 产品代码 | 产品简称 | 产品标签  | 日期       |
| -------- | -------- | --------- | -------- | -------- | --------- | ---------- |
| A001     | 主体1    | 资产标签1 | P001     | 产品1    | 产品标签1 | YYYY-MM-dd |
| A002     | 主体2    | 资产标签2 | P002     | 产品2    | 产品标签2 | YYYY-MM-dd |
| A003     | 主体3    | 资产标签3 | P00n     | 产品n    | 产品标签n | YYYY-MM-dd |

###### 示例应用

> 获取所有开放式公募产品下的公募证券投资基金的管理人（穿透后）

```python
主体(['公募证券投资基金'], 穿透=True) in 产品(['现金管理类产品'])
```

> 获取现金管理类产品中的发行银行主体信用评级为AAA的银行存款和同业存单

```python
# 资产标签、主体标签和产品标签使用in关键字的嵌套使用
资产(['银行存款', '同业存单'], 穿透=True) in (主体(['信用评级AAA主体'], 穿透=True) in 产品(['现金管理类产品']))
```

### 6 金融指标(Metric)

#### 6.1 金融指标概念

​	金融指标是指在金融指标库中定义，创建并维护的具有相关业务用途的数据。产品、资产、主体等不同类型的金融对象，有同该金融对象相对应的指标集合定义。同时金融指标也具有相应的时间维度，在同一计算场景(Logic Cell)中定义时间维度，将作用于该计算场景中的所有指标。特别注意，所有参与计算的金融指标都应为数值类指标。

#### 6.2 金融指标提取

###### 调用方法

$$
(使用标签提取的金融资产).指标名称
$$

> [!NOTE]
>
> (使用标签提取的金融资产) - 即为章节5中使用标签提取相应金融对象的操作

###### 输出结果

- 二维表格数据，返回符合相应金融对象的要素信息，同时增加指标列。日期列根据计算场景中时间维度定义自动获得。以下示例为如下语言代码的示例输出：

```python
(资产(['AAA级信用债']) in 产品(['固收产品'])).修正久期
```

| 资产代码 | 资产简称 | 资产标签    | 产品代码 | 产品简称  | 产品标签 | 日期       | 修正久期 |
| -------- | -------- | ----------- | -------- | --------- | -------- | ---------- | -------- |
| A001     | 信用债1  | AAA级信用债 | P001     | 固收产品1 | 固收产品 | YYYY-MM-dd | 3.2      |
| A002     | 信用债2  | AAA级信用债 | P001     | 固收产品1 | 固收产品 | YYYY-MM-dd | 1.1      |
| A003     | 信用债3  | AAA级信用债 | P002     | 固收产品2 | 固收产品 | YYYY-MM-dd | 0.8      |

###### 示例应用

> 提取现金管理类产品的净资产

```python
(产品(['现金管理类产品'])).净资产
```

> 获取现金管理类产品中主体评级低于AAA信用债的持仓市值(穿透后)

```python
(资产(['主体评级低于AAA信用债'], 穿透=True) in 产品(['现金管理类产品'])).持仓市值
```

### 7 金融函数(Function)

#### 7.1 金融函数概念

​	金融函数指内置于语言中，作用于金融指标集合，产生最终业务结果的可被反复使用的业务函数。金融函数包括三大类，1、一般统计函数；2、聚合函数；3、特定金融函数。三类函数可以根据具体情况嵌套使用。以下章节分别对三类函数做详细介绍。

#### 7.2 一般统计函数

##### 7.2.1 求和函数：sum()

###### 调用方法

$$
sum(指标计算过程)
$$

> [!NOTE]
>
> 指标计算过程请参考第5、6章

###### 输出结果

​	指标求和后的数值

###### 示例应用

> 计算所有信用债资产在所有现金管理类产品中的总持仓市值(不穿透)

```python
sum((资产(['信用债']) in 产品(['现金管理类产品'])).持仓市值)
```

> 计算所有信用债资产在所有现金管理类产品中的持仓占比(穿透后)

```python
sum((资产(['信用债']) in 产品(['现金管理类产品']), 穿透=True).持仓市值) / sum(产品(['现金管理类产品']).净资产)
```



##### 7.2.2 求平均函数：mean()

###### 调用方法

$$
mean(指标计算过程)
$$

输出结果

​	指标平均数

###### 示例应用

> 计算所有主体评级为AAA级的债券在所有现金管理类产品中的平均持仓市值(不穿透)

```python
mean((资产(['AAA信用债']) in 产品(['现金管理类产品'])).持仓市值)
```

##### 7.2.3 求中位数：median()

###### 调用方法

$$
median(指标计算过程)
$$

输出结果

​	指标中位数

###### 示例应用

> 计算所有主体评级为AAA级的债券在所有现金管理类产品中的持仓中位数(不穿透)

```python
median((资产(['AAA信用债']) in 产品(['现金管理类产品'])).持仓市值)
```

##### 7.2.4 求最大值：max()

###### 调用方法

$$
max(指标计算过程)
$$

输出结果

​	指标最大值

###### 示例应用

> 计算所有主体评级为AAA级的债券在所有现金管理类产品中的修正久期最大值(不穿透)

```python
max((资产(['AAA信用债']) in 产品(['现金管理类产品'])).修正久期)
```

##### 7.2.5 求最小值：min()

###### 调用方法

$$
min(指标计算过程)
$$

输出结果

​	指标最小值

###### 示例应用

> 计算所有主体评级为AAA级的债券在所有现金管理类产品中的存续天数最小值(不穿透)

```python
min((资产(['AAA信用债']) in 产品(['现金管理类产品'])).存续天数)
```

##### 7.2.6 统计个数：count()

###### 调用方法

$$
count(指标计算过程)
$$

输出结果

​	指标个数

###### 示例应用

> 计算所有主体评级为AAA级的债券在所有现金管理类产品中的资产个数(不穿透)

```python
count((资产(['AAA信用债']) in 产品(['现金管理类产品'])))
```

##### 7.2.7 排序：sort()

###### 调用方法

$$
sort(指标计算过程, 升序=True)
$$

###### 输入参数

- 升序：如果升序为True，表示排序以指标值进行升序排列；如果升序为False，表示排序以指标值进行降序排列；默认为升序排列

###### 输出结果

​	根据指标排序后的二维表结构数据

###### 示例应用

> 计算所有主体评级为AAA级的债券在所有现金管理类产品中的持仓市值进行升序排列(不穿透)

```python
sort((资产(['AAA信用债']) in 产品(['现金管理类产品'])).持仓市值)
```

##### 7.2.8 获取前几或后几名：limit()

###### 调用方法

$$
limit(指标计算过程, 名次)
$$

###### 输入参数

- 名次：正整数表示排名前N名；负整数表示排名后N名

###### 输出结果

​	根据指标名次的结果筛选后的二维表结构

###### 示例应用

> 计算所有主体评级为AAA级的债券在所有现金管理类产品中的持仓市值前5名资产(不穿透)

```python
limit(sort((资产(['AAA信用债']) in 产品(['现金管理类产品'])).持仓市值, 升序=False), 5)
```

#### 7.3 聚合类函数

​	除了在原始指标直接进行统计函数操作外，在不同业务场景根据不同金融对象本身或金融对象对应的标签进行聚合操作，将原始指标降维处理是非常有用的操作。本语言通过内置的聚合类函数(agg)完成相关的数据处理。

##### 7.3.1 调用方法

$$
agg(指标计算过程, [分组列表], 聚合方法)
$$

##### 7.3.2 输入参数

- 指标计算过程: 参考第5、6章的相关章节，且指标计算过程可为多次函数调用和四则运算的嵌套调用过程
- 分组列表：
  - 产品类指标聚合可包含[‘产品’, ‘产品标签’]
  - 资产类指标聚合可包含[‘资产’, ‘资产标签’, ‘产品’, ‘产品标签’]
- 聚合方法：‘sum’ - 将指标分组求和；‘mean’ - 将指标分组求平均; ‘count’-将指标分组求个数；‘max’ - 将指标分组求最大值; ‘min’ - 将指标分组求最小值; 其他内置金融函数（详见7.4节）: period_return – 期间收益率; compound_ann_return - 复利年化收益率; single_ann_return - 单利年化收益率;

##### 7.3.3 输出结果

​	根据不同分组列表及指标计算结果将二维表降为成分组计算后的数据结构。属性列仅保留分组列表中的内容，指标列将为各分组后的计算结果。

##### 7.3.3 示例应用

> 单个现金管理类产品中现金、国债、中央银行票据，政策性金融债券的市值总占比(穿透前)

```python
agg(资产(['现金', '国债', '中央银行票据', '政策性金融债券']) in 产品(['现金管理类产品']).持仓市值, ['产品'], 'sum') 
/ 产品(['现金管理类产品']).净资产
```

> 统计现金、国债、信用债在总体公募理财产品中的持仓市值占比

```python
agg(资产(['现金', '国债', '信用债']) in 产品(['公募理财产品']).持仓市值, ['资产标签'], 'sum') 
/ sum(产品(['公募理财产品']).净资产)
```

> 统计股票、债券、公募基金、SPV资产在固收类和权益类产品中的市值占比情况

```python
agg(资产(['股票', '债券', '公募基金', 'SPV资产']) in 产品(['固收类', '权益类']).持仓市值, ['产品标签', '资产标签'], 'sum') 
/ agg(产品(['固收类', '权益类']).净资产, ['产品标签'], 'sum')
```

> 计算单个每只产品的债券久期

```python
agg(资产(['债券']).久期 * 资产(['债券']).持仓市值, ['产品'], 'sum')
/ 产品([]).净资产
```

#### 7.4 特定金融函数

​	本章只描述了期间收益率、复利年化收益率、单利年化收益率 3个金融函数。未来可以将金融函数原子化，以扩展方式不断集成进语言。

##### 7.4.1 期间收益率函数：period_return()

###### 调用方法

$$
period\_return(指标计算过程)
$$

###### 输入参数

- 指标计算过程: 参考第5、6章的相关章节，且指标计算过程可为多次函数调用和四则运算的嵌套调用过程

###### 输出结果

​	根据日期计算期间的复利收益率

###### 示例应用

> 计算所有理财产品近一个月的期间收益率

```python
开始日期 = 近一月(平台日())
结束日期 = 平台日()
period_return(产品([]).日收益率)
```

> ##### 计算所有固收类产品投资的信用债近3个月的期间收益率

```python
开始日期 = 近三月(平台日())
结束日期 = 平台日()
# 定义中间变量以免重复代码
a = 资产(['信用债']) in 产品(['固收类'])
period_return(agg(a.持仓市值 + a.现金流出 - a.现金流入 - 前一日市值, ['资产标签'], 'sum') / agg(a.前一日市值, ['资产标签'], 'sum'))
```

##### 7.4.2 复利年化收益率函数：compound_ann_return()

###### 调用方法

$$
compound\_ann\_return(指标计算过程)
$$

###### 输入参数

- 指标计算过程: 参考第5、6章的相关章节，且指标计算过程可为多次函数调用和四则运算的嵌套调用过程

###### 输出结果

​	根据日期计算期间的复利年化收益率

###### 示例应用

> 计算所有理财产品近一个月的年化收益率

```python
开始日期 = 近一月(平台日())
结束日期 = 平台日()
compound_ann_return(产品([]).日收益率)
```

> ##### 计算所有固收类产品投资的信用债近3个月的复利年化收益率

```python
开始日期 = 近三月(平台日())
结束日期 = 平台日()
# 定义中间变量以免重复代码
a = 资产(['信用债']) in 产品(['固收类'])
compound_ann_return(agg(a.持仓市值 + a.现金流出 - a.现金流入 - 前一日市值, ['资产标签'], 'sum') / agg(a.前一日市值, ['资产标签'], 'sum'))
```

##### 7.4.3 复利年化收益率函数：single_ann_return()

###### 调用方法

$$
single\_ann\_return(指标计算过程)
$$

###### 输入参数

- 指标计算过程: 参考第5、6章的相关章节，且指标计算过程可为多次函数调用和四则运算的嵌套调用过程

###### 输出结果

​	根据日期计算期间的单利年化收益率

###### 示例应用

> 计算所有理财产品近一个月的年化收益率

```python
开始日期 = 近一月(平台日())
结束日期 = 平台日()
single_ann_return(产品([]).日收益率)
```

> ##### 计算所有固收类产品投资的信用债近3个月的单利年化收益率

```python
开始日期 = 近三月(平台日())
结束日期 = 平台日()
# 定义中间变量以免重复代码
a = 资产(['信用债']) in 产品(['固收类'])
single_ann_return(agg(a.持仓市值 + a.现金流出 - a.现金流入 - 前一日市值, ['资产标签'], 'sum') / agg(a.前一日市值, ['资产标签'], 'sum'))
```

### 8 监控规则(Rule)

文档的3、4、5、6、7章定义和描述了本语言的主体部分。由于金融指标的计算往往需要在最终结果基础上施加一定的监控检验规则，以达到指标监控的业务要求。

#### 8.1 监控规则定义

​	监控规则是一组由 ‘监控规则’:‘监控结果’ 构成的字典。其中监控规则是一个字符串，接受 >, <, =, >=, <=, or, and和数值的逻辑运算；监控结果则为符合某一监控规则情况下得到的监控结果。

#### 8.2 监控规则示意

> 单只现金管理类产品的现金、国债、中央银行票据、政策性金融债券的投资占比, 小于5%为违规；小于10%为预警

```python
监控规则 = {'< 0.05': '违规', '< 0.1': '预警'}
agg((资产(['现金','国债', '中央银行票据', '政策性金融债券']) in 产品(['现金管理类'])).持仓市值, ['产品'], 'sum')
/ 产品(['现金管理类']).净资产
```

运行完上述计算场景后，应得到如下结果二维表

| 产品代码 | 产品简称  | 指标值 | 监控规则 | 监控结果 |
| -------- | --------- | ------ | -------- | -------- |
| P001     | 现金产品1 | 0.02   | < 0.05   | 违规     |
| P002     | 现金产品2 | 0.06   | < 0.1    | 预警     |



### 9 语言应用示例

​	本章将综合运用本语言的基本语法、原语、结构解决实际的业务问题。为了使读者及语言的实现人员更了解本语言的细节，本章将根据使用业务场景的不同，分别针对《合规限额指标》、《压力测试》、《全面风险监测》展开示例及用本语言的相应解决步骤。

#### 9.1 合规限额指标示例

> （穿透前）单只开放式公募理财产品持有的现金或者国债、中央银行票据和政策性金融债券占该理财产品资产净值的比例不得低于5%

```python
agg((资产(['现金'，'国债', '中央银行票据', '政策性金融债券']) in 产品(['现金管理类'])).持仓市值, ['产品'], 'sum')
/ 产品(['现金管理类']).净资产
监控规则 = {'< 0.05': '违规'}
```

> （穿透后）单只混合类产品资产投资权益类资产的比例不得高于80%

```python
agg((资产(['权益类资产'], 穿透=True) in 产品(['混合类产品'])).持仓市值, ['产品'], 'sum') / 产品(['混合类产品']).净资产
监控规则 = {'> 0.8': '违规'}
```

> （穿透后）全部开放式公募产品投资单一上市公司发行的股票占可流通股票的比例不得超过15%

```python
agg((主体(['股票'], 穿透=True) in 产品(['开放式公募产品']).持仓数量), ['主体'], 'sum') / (主体(['股票']).流通股数量
监控规则 = {'> 0.15': '违规'}
```

> (穿透后)每只现金管理类产品投资于同一机构发行的债券及其作为原始权益人的资产支持证券的比例合计不得超过该产品资产净值的10%

```python
agg(主体(['债券', '资产支持化证券'], 穿透=True) in 产品(['现金管理类']).持仓市值, ['产品'], 'sum') / 产品(['现金管理类']).净资产
监控规则 = {'> 0.1': '违规'}
```

> (穿透后)每只现金管理类产品投资于主体信用评级为AAA的同一商业银行的银行存款、同业存单占该产品资产净值的比例合计不得超过20%

```python
agg((主体(['主体评级为AAA']) in (资产(['银行存款', '同业存单']), 穿透=True) in 产品(['现金管理类']))).持仓市值, ['产品'], 'sum') 
/ 产品(['现金管理类']).净资产
监控规则 = {'> 0.2': '违规'}
```

> (穿透后)每只现金管理类产品的杠杆水平不得超过120%

```python
agg((资产([], 穿透=True) in 产品(['现金管理类'])).持仓市值, ['产品'], 'sum') / 产品(['现金管理类'])).净资产
监控规则 = {'> 1.2': '违规'}
```

#### 9.2 压力测试示例

> 每只产品内AAA级信用债的持仓占比、久期及轻度情景下的损失金额

```python
# 为反复使用，定义一个资产的中间变量
asset = 资产(['AAA信用债'])
占比 = agg(asset.持仓市值, ['产品']， 'sum') / 产品().净资产
久期 = agg(asset.持仓市值 * asset.修正久期, ['产品']， 'sum') / 产品([]).净资产
# 下面的"风险因子轻度值"，需要压测提供相应的函数获取某承压因子下的因子值
轻度损失 = agg(-1 * asset.持仓市值 * asset.修正久期 * 风险因子轻度值, ['产品']， 'sum') 
```

#### 9.3 全面风险监控指标示例

> 近3个月破净产品列表

```python
开始日期 = 近N月(平台日(), 3)
结束日期 = 平台日()
agg(产品([]).单位净值, ['产品'], 'min') - 1
监控规则 = {'< 0': '破净', '>=0': '正常'}
```

> 计算所有现金管理类产品7日年化收益率

```python
开始日期 = 近N天(平台日(), 7)
结束日期 = 平台日()
agg(产品(['现金管理类']).万份收益 / 10000, ['产品'], 'single_ann_return')
```

> 统计定开型产品前10大债券持仓主体

```python
limit(sort(agg((主体(['债券']) in 产品(['定开型产品'])).持仓市值, ['主体'], 'sum') / sum(产品(['定开型产品'])).净资产), 升序=False),10)
```

> 用开市法计算，每个固收+产品中股票和债券大类的近3个月持仓收益率

```python
开始日期 = 近N月(平台日(), 3)
结束日期 = 平台日()
a = 资产(['债券', '股票']) in 产品(['固收+'])
period_return(agg(a.持仓市值 + a.现金流出 - a.现金流入 - 前一日市值, ['产品', '资产标签'], 'sum') 
              / agg(a.前一日市值, ['产品', '资产标签'], 'sum'))
```

> 用开市法计算，所有固收+产品中股票和债券大类的近1个月持仓收益率

```python
开始日期 = 近N月(平台日(), 1)
结束日期 = 平台日()
a = 资产(['债券', '股票']) in 产品(['固收+'])
period_return(agg(a.持仓市值 + a.现金流出 - a.现金流入 - 前一日市值, ['资产标签'], 'sum') / agg(a.前一日市值, ['资产标签'], 'sum'))
```

### 10 写在后面

​	这篇设计文档写到这里，我是无比激动的。这门语言使用极其有限的语法、原语及操作符，充分整合了数据平台在指标库、标签库、算法库的积累，使提取、计算、自定义指标的逻辑精炼的整合到了一起，我现在不住的嘴角上扬。我希望这门微语言能在技术实现阶段，保持其语法的简洁，同时以最大性能的方式予以实现，实现这门语言的同学请格外加油！在这门语言开发和实施完毕，稳定运行后，其实在他之上还有无限的可能。因为其语法几乎接近业务语言，我们可以考虑使用自然语言识别技术(NLP)，将需求和业务人员的文字和描述转化为该语言的语法提取和计算数据，这将是系统交互的一次革命。想象一下，当业务人员对着屏幕说“请帮我用开市法计算，所有固收+产品中股票和债券大类的近1个月持仓收益率”，系统将实时翻译、提取并计算数据，将是多么有意思的场面！

​	写了这么多，突然想起来我还没有给这门语言起个名字呢。脑海中有两个名字备选，读者可以给我点建议。

1、**<u>仓颉（jié)</u>**：这个和我一贯起名的风格相似，比如白泽、观星，都是中国风这一挂的。之所以叫仓颉，源于仓颉造字的神话传说。出自《淮南子·本经训》：“昔者苍颉作书，而天雨粟，鬼夜哭。”
2、<u>**Muse(缪斯)**</u>：（[希腊语](https://zh.wikipedia.org/wiki/希臘語)：Μουσαι、[拉丁语](https://zh.wikipedia.org/wiki/拉丁語)：Muses）是[希腊神话](https://zh.wikipedia.org/wiki/希臘神話)主司[艺术](https://zh.wikipedia.org/wiki/藝術)与[科学](https://zh.wikipedia.org/wiki/科學)的九位古老文艺[女神](https://zh.wikipedia.org/wiki/女神)的总称。这属于希腊神话一挂的命名，这也是我大学时办过的一本杂志的名字，所以记忆犹新。