# 函数概念
通俗的讲,函数就是一个标准的生产模具,只要在使用时只需要提供相应的原材料,它就可以对应生产出相应的工件。
使用函数可以有效降低功能逻辑实现的难度,并保证功能的可靠性和准确性。PEL中提供丰富的功能函数,通过多重组合后,可以快速构建特色策略指标。
# 使用函数
无论任何人在刚接触系统函数时,多少都会有不知所措的情绪出现。因此我们从多个使用角度切入学习相关使用频率较高的函数。带领大家快速熟悉PEL函数库。
# 查找PEL函数
在金字塔的公式编辑界面下,可以打开函数列表窗口,金字塔中提供的PEL函数均在此列表中可以查询到。
查询方法
- 方式1:直接检索函数功能相关的关键词,例如:均价;
- 方式2:根据需要函数的功能,查看与功能相关的函数分组,例如:时间、字符串;
- 方式3:也可以通过论坛咨询技术人员获取相关的函数;
# K线属性函数
K线相关属性值是策略指标最为基础的函数类,绝大部分的算法操作基本都围绕它们进行展开。
函数 | 说明 |
---|---|
open | 当根K线的开盘价 |
high | 当根K线的最高价 |
low | 当根K线的最低价 |
close | 当根K线的收盘价 |
vol | 当根K线的成交量 |
amount | 当根K线的成交额 |
openint | 当根K线的持仓量 |
对于K线相关属性的函数,绝大部分用户都会对其进行一定的深度统计分析,
例如:获取指定周期范围内K线相关属性的最高价、最低价等;那么如何找到相应的函数呢?
- 我们可以直接尝试搜索关键字
最高
;经过筛选发现有多个疑似函数,那么我们可以通过直接输出相关函数的结果进行确定。
aa:DYNAINFO(5);//最高值(通过参数个数,初步能排除此函数不满足使用需求)
bb:HHV(high,5);//5周期内的最高价
cc:TOPRANGE(HIGH);//当前的最高价是多少周期内的最大值
DRAWNUMBER(1,high,high,0,COLORYELLOW);//显示每根k的最高价
2
3
4
5
6
7
通过函数说明,以及上图中的结果分析可知以下:
第一行:DYNAINFO(5)返回的是盘口的最高价,即当日的最高价;(不符合)
第三行:结合DRAWNUMBER函数输出每根k的最高价,可以判断HHV是当前k线上最近5根的最高价;(符合需求)
第五行:TOPRANGE函数求的是周期数,即当前最高价在是目前多少周期内的最大值;(不符合)
- 求取当日第一根K线的相关价格,如开盘价,最高价;
实现过程中使用的函数
- OPEN:开盘价
- HIGH:最高价
- TODAYBAR:日内当前周期下的数据数量
- VALUEWHEN(条件,数据):当指定条件成立时,获取指定的变量结果。(返回最近一次成立时的结果)
TODAY_OPEN:VALUEWHEN(TODAYBAR=1,OPEN);
TODAY_HIGH:VALUEWHEN(TODAYBAR=1,HIGH);
2
# 字符串函数
字符串是PEL语言中,重要的组成部分,例如常用的品种代码、品种名称函数的返回值都是字符串类型。常用的字符串函数如下:
函数 | 说明 |
---|---|
STKLABEL | 品种代码 |
STKNAME | 品种名称 |
MARKETLABEL | 市场代码 |
MARKETNAME | 市场名称 |
STRCMP(STR1,STR2) | 字符串比较,如果: STR1 > STR2,返回1; STR1 < STR2,返回-1, STR1 = STR2相等,返回0。 |
STRLEFT(STR,N) | 获取字符串STR左边起始N个字符 |
STRRIGHT(STR,N) | 获取字符串STR右边起始N个字符 |
STRTRIMLEFT(STR,STR1) | 剔除字符串STR起始位置中含有STR1中的单个字符 |
STRTRIMRIGHT(STR,STR1) | 剔除字符串STR末尾位置中含有STR1中的单个字符 |
STRTONUM(STR) | 将字符串STR转化成数值 |
STRLEN(STR) | 获取str字符串的长度 |
上述函数的应用场景如下:
- 判断当前品种是否为RB00合约。
//方式1: 相等返回1
code_cond1:STKLABEL='RB00';
//方式2:通过STRCMP函数,如果相等返回0
code_cond2:STRCMP(STKLABEL,'RB00');
2
3
4
5
- 获取当前期货品种的英文代码。
分析:通过观察发现品种的代码是由英文代码
+月份
组成(连续、指数和原油合约例外),并且英文代码部分的长度并不统一;那么是无法直接通过获取指定长度的字符函数得到。
由于字符串右侧的数字部分的长度基本一致。那么是否可以通过字符串总长度-数字长度
得到呢?
实现过程中使用的函数
- STKLABEL:当前品种代码
- STRLEN(STR):得到字符串的总长度
- STRLEFT(STR,N) :截取字符串左侧N个字符。
//当前品种代码的总长度
len:STRLEN(STKLABEL);
code_str:STRLEFT(STKLABEL,len-2);
//在变量章节中,了解到字符串不支持直接显示在K线变量中,需要使用输出函数处理。
EXPLAIN(1,code_str);
2
3
4
5
上面的方式在绝大部分品种上都适用,但是在原油合约上存在问题,经过观察我们发现,原油合约由于是多年份合约,所以在合约代码中含有年份(左侧的数值是4位)。知道原因后我们可以针对性的进行特殊处理。
思考:如何特殊处理原油合约?
- 客户甲观察发现国内品种,只有原油合约的的字符串长度是6位(SC+4位数字),其余合约的长度均低于6位(英文代码+2位数字);所以客户甲根据字符总长度判断减去的字符数。
//当前品种代码的总长度
len:STRLEN(STKLABEL);
//如果长度为6个字符则-4,否者则-2
offset:if(len=6,4,2);
code_str:STRLEFT(STKLABEL,len-offset);
//在变量章节中,了解到字符串不支持直接显示在K线变量中,需要使用输出函数处理。
EXPLAIN(1,code_str);
2
3
4
5
6
7
在国内市场的各个合约上验证后发现符合需求。
- 客户乙打算直接判定品种代码的前2个字符是否时
SC
。在函数列表中发现以下两个函数似乎可以满足比较需求。
STRFIND(STR,S1,N):从字符串STR的第N个字符开始查找字符串S1,返回找到的位置,若没有找到就返回0。 STRNCMP(STR1,STR2,LEN):比较STR1和STR2中前LEN个字符是否相同,相同返回0。
len:STRLEN(STKLABEL);
//STRFIND
F_index:STRFIND(STKLABEL,'SC',1);
//字符串查找
F_offset:=if(F_index<>0,4,2);
F_code_str:=STRLEFT(STKLABEL,len-F_offset);
EXPLAIN(1,code_str);
//使用STRNCMP进行判断
C_index:STRNCMP(STKLABEL,'SC',2);
//字符串比较后C_index=0时代表相等,否者是不相同
C_offset:=if(C_index=0,4,2);
C_code_str:=STRLEFT(STKLABEL,len-C_offset);
EXPLAIN(1,C_code_str);
2
3
4
5
6
7
8
9
10
11
12
13
14
在国内市场的各个合约上验证后发现也都符合需求。
- 客户丙认为直接比较完整的品种代码即可实现。
//当前品种代码的总长度
len:STRLEN(STKLABEL);
offset:if(STKLABEL='SC0000',4,2);
code_str:STRLEFT(STKLABEL,len-offset);
EXPLAIN(1,code_str);
2
3
4
5
在国内市场的各个合约上验证后发现,只在连续合约上满足需求。
- 客户丁希望提取期货类英文代码的逻辑不仅仅适用于国内品种,并且希望保证逻辑代码的通用性。他在学习适用函数时,对STRTRIMRIGHT函数的解释存在疑惑,所以对其调试后发现它的作用是剔除末尾处的指定字符,恰好符合上述的需求。
//将末尾处含有数字的字符剔除
code_str:STRTRIMRIGHT(STKLABEL,'0123456789');
EXPLAIN(1,code_str);
2
3
# 时间函数
时间处理判断是最为常用的函数类,一般情况下用于条件限制类型中,常用的时间函数如下:
函数 | 说明 |
---|---|
CURRENTDATE | 计算机日期 |
CURRENTTIME | 计算机时间 |
DATE | 当前k的日期 |
TIME | 当前k线的时间 |
WEEKDAY | 当前k线的星期 |
TIME0 | 0点以来的秒数 |
T0TOTIME | 秒数转化成时间 |
TIMETOT0 | 时间转化成秒数 |
CLOSETIME | 交易所指定的每个时段的收盘时间 (详见见函数说明) |
OPENTIME | 交易所指定的每个时段的开盘时间 (详见见函数说明) |
DYNAINFO(207) | 最新的行情时间(没有历史值) |
- 金字塔中显示的日期结果为什么不是YYYYMMDD这类标准格式? 因为金字塔中日期都是YYYYMMDD-19000000得到的,这么做的目的是为了防止初选数据越界的情况产生。所以才产生了特殊显示结果。
- 计算得到收盘前5分钟对应的时间。
分析:这种就是典型的时间加减操作,我们只要知道当前品种对应的收盘时间后,即可进行计算。 客户甲认为,使用金字塔时区后收盘时间是190000,而提前5分钟对应的时间是185500,两者差500,所以打算通过-4500实现。
实现过程中使用的函数
- CLOSETIME(N):获得指定节点的收盘时间。N=0时表示最后收盘时间。
close_time:CLOSETIME(0)-4500;
客户乙认为,时分秒的进制不同,采用甲的方式存在投机取巧,并不适用于全部情况。所以他打算将时间统一换成秒周期后再换算回时间格式。
实现过程中使用的函数
- CLOSETIME(N):获得指定节点的收盘时间。N=0时表示最后收盘时间
- TIMETOT0(X):将指定时间换算成秒数
- T0TOTIME(X):将秒数换算成时间
//将收盘时间换成秒后减去5*60s,即提前5分钟后的秒数
SCE:TIMETOT0(CLOSETIME(0))-5*60;
//将秒数转化成时间
xtime:T0TOTIME(SCE);
2
3
4
综上2种方式中,客户乙的实现过程更为通用,是比较推荐的方式。而客户甲虽然效果相同,但是代码存在局限性,并不利于后期的调整使用。
# 数学函数
数学函数主要应用在对数据进行整理等操作中。常用的数据函数如下
函数 | 说明 |
---|---|
CEILING(A) | 向上取整 |
FLOOR(A) | 向下取整 |
INTPART(A) | 取数据的整数部分 |
FRACPART(A) | 取数据的小数部分 |
MAX(A,B) | 取A、B两个数中的最大值 |
MIN(A,B) | 取A、B两个数中的最小值 |
MOD(A,B) | 取A除以b的余数 |
ROUND(A) | 将A四舍五入成整数 |
ROUNDS(A,B) | 将A四舍五入并保留B位小数 |
- 将日线按照季度划分,在每个季度的第一根位置使用竖线进行标记。
分析:我们知道一年12个月,一个季度等于3个月。通过总结规律发现,每个季度的最后一个月都能被3整除。所以我们可以考虑尝试使用mod函数实现。
实现过程中使用的函数
- MOD(A,B):取A除以b的余数
- MONTH:取得该周期的月份
- VERTLINE(COND):当COND条件满足时,绘制垂直线。
cond:mod(MONTH,3);
VERTLINE(cond=0);
2
通过观察分析,现在标记的竖线都集中在每个季度的最后一个月位置,而在每个季度的月末位置发现,当上跟k的余数是0,当根k的余数是1时,正好满足上述需求。
cond:mod(MONTH,3);
VERTLINE(ref(cond=0,1) and cond=1);
2
# 函数使用技巧
其余类型的函数不再逐一举例介绍,归根结底函数的使用技巧的提升,无非就是勤于调试输出疑问函数的结果和总结需求实现过程中的特点。希望通过前面章节中的一些方式方法,帮助新用户找到学习使用函数的灵感。