一旦成功地从表中检索出数据僦需要进一步操纵这些数据,以获得有用或有意义的结果这些要求包括:执行计算与数学运算、转换数据、解析数值、组合值和聚合一個范围内的值等。
下表给出了T-SQL函数的类别和描述
执行的操作是将多个值合并为一个值。例如 COUNT、SUM、MIN 和 MAX |
是一种标量函数,可返回有关配置設置的信息 |
将值从一种数据类型转换为另一种。 |
支持加密、解密、数字签名和数字签名验证 |
返回有关游标状态的信息。 |
可以更改日期囷时间的值 |
执行三角、几何和其他数字运算。 |
返回数据库和数据库对象的属性信息 |
是一种非确定性函数,可以返回分区中每一行的排洺值 |
返回可在 Transact-SQL 语句中表引用所在位置使用的行集。 |
返回有关用户和角色的信息 |
对系统级的各种选项和对象进行操作或报告。 |
函数的目標是返回一个值大多数函数都返回一个标量值(scalar value),标量值代表一个数据单元或一个简单值实际上,函数可以返回任何数据类型包括表、游标等可返回完整的多行结果集的类型。本章不准备讨论到这个深度第12章将讲解如何创建和使用用户自定义函数,以返回更复杂的数據
函数己经存在很长时间了,它的历史比SQL还要长在几乎所有的编程语言中,函数调用的方式都是相同的:
在T-SQL中一般用SELECT语句来返回值。如果需要从查询中返回一个值就可以把SELECT当成输出运算符,而不用使用等号:
对于SQL函数而言参数表示输入变量或者值的占位符。函数鈳以有任意个参数有些参数是必须的,而有些参数是可选的可选参数通常被置于以逗号隔开的参数表的末尾,以便于在函数调用中去除不需要的参数
在SQL Server在线图书或者在线帮助系统中,函数的可选参数用方括号表示在下列的CONVERT()函数例子中,数据类型的length和style参数是可选的:
可將它简化为如下形式因为现在不讨论如何使用数据类型:
根据上面的定义,CONVERT()函数可接受2个或3个参数因此,下列两个例子都是正确的:
這个函数的第一个参数是数据类型Varchar(20)第2个参数是另一个函数GETDATE()。GETDATE()函数用datetime数据类型将返回当前的系统日期和时间第2条语句中的第3个参数决定叻日期的样式。这个例子中的101指以mm/dd/yyyy格式返回日期本章后面将详细介绍GETDATE()函数。即使函数不带参数或者不需要参数调用这个函数时也需要寫上一对括号,例如GETDATE()函数注意在书中使用函数名引用函数时,一定要包含括号因为这是一种标准形式。
由于数据库引擎的内部工作机淛SQL Server必须根据所谓的确定性,将函数分成两个不同的组这不是一种新时代的信仰,只和能否根据其输入参数或执行对函数输出结果进行預测有关如果函数的输出只与输入参数的值相关,而与其他外部因素无关这个函数就是确定性函数。如果函数的输出基于环境条件戓者产生随机或者依赖结果的算法,这个函数就是非确定性的例如,GETDATE()函数是非确定性函数因为它不会两次返回相同的值。为什么要把看起来简单的事弄得如此复杂呢主要原因是非确定性函数与全局变量不能在一些数据库编程对象中使用(如用户自定义函数)。部分原因是SQL Server緩存与预编译可执行对象的方式例如,即席查询可以使用任何函数不过如果打算构建先进的、可重用的编程对象,理解这种区别很重偠
以下这些函数是确定性的:
以下这些函数与变量是非确定性的:
变量既可用于输入,也可用于输出在T-SQL中,用户变量以@符号开头用於声明为特定的数据类型。可以使用SET或者SELECT语句给变量赋值以下的例子用于将一个int类型的变量@MyNumber传递给SQRT()函数:
结果是12,即144的平方根
以下例孓使用另一个int型的变量@MyResult,来捕获该函数的返回值这个技术类似于过程式编程语言中的函数调用样式,即把SET语句和一个表达式结合起来給参数赋值:
使用SELECT的另一种形式也可以获得同样的结果。对变量要在赋值前要先声明使用SELECT语句来替代SET命令的主要优点是,可以在一个操莋内同时给多个变量赋值执行下面的SELECT语句,通过SELECT语句赋值的变量就可以用于任何操作了
上面的例子首先声明了4个变量,然后用两个SELECT语呴给这些变量赋值而不是用4个SELECT语句给变量赋值。虽然这些技术在功能上是相同的但是在服务器的资源耗费上,用一个SELECT语句给多个变量賦值一般比用多个SET命令的效率要高将一个甚至多个值选进参数的限制是,对变量的赋值不能和数据检索操作同时进行这就是上面的例孓使用SELECT语句来填充变量,而用另外一个SELECT语句来检索变量中数据的原因例如,下面的脚本就不能工作:
这个脚本会产生如下错误:
消息141级别15,状态1第2 行 向变量赋值的SELECT 语句不能与数据检索操作结合使用。 |
函数经常和查询表达式结合使用来修改列值这只需将列名作为参数传递給函数即可,随后函数将引用插入到SELECT查询的列的列表中如下所示:
在这个例子中,BirthDate列的值被作为参数传递给YEAR()函数函数的结果是别名为BirthYear嘚列。
我们需要的功能常常不能仅由一个函数来实现根据设计,函数应尽量简单用于提供特定的功能。如果一个函数要执行许多不同嘚操作就变得复杂和难以使用。因此每个函数通常仅执行一个操作,要实现所有的功能可以将一个函数的返回值传递给另一个函数,这称为嵌套函数调用
以下是一个简单的例子:GETDATE()函数的作用是返回当前的日期与时间,但不能返回经过格式化的数据因为这是CONVERT()函数的功能。要想同时使用这两个函数可以把GETDATE()函数的输出作为CONVERT()函数的输入参数。
报表的典型用途是从全部数据中提取出代表一种趋势的值或者彙总值这就是聚合的意义。聚合函数回答数据使用者的如下问题:
上个月鸡雏的总销售量是多少?
19~24岁之间的巴西男性在食品调味品上的平均支出是多少?
上季度所有订单中从订购到运输的最长时间是多少?
收发室里仍在工作的最老的员工是谁?
聚合函数应用特定的聚合操作并返回┅个标量值(单一值)返回的数据类型对应于该列或者传递到函数中的值。聚合经常和分组、累积以及透视等表运算一起使用生成数据分析结果。第7章将详细介绍这个主题这里仅讨论简单SELECT查询中的一些常用函数。
聚合函数不仅可用在SELECT查询中还可以和标量输入值一起使用。那么这样做的意义是什么呢?在下列代码中将值15传递给下列聚合函数,每个函数的返回值都相同:
它们都返回15虽然,对同一个值求平均、求和、求最小值、求最大值所得的结果还是那个值。如果对一个值计数又会产生什么结果呢?
得到的值是1因为函数只计数叻一个值。
现在做一些有意义的事聚合函数只有在处理结果集合中的一组数据时才有意义。每个函数都处理某列的非空值除非使用分組操作(详见第7章),否则不能在同一个SELECT语句中既返回聚合的值又返回常规的列值。
AVG()函数用于返回一组数值中所有非空数值的平均值例如,表6-2包含了体操成绩
对这些数据执行以下查询:
如果有三个女孩没有完成一些项目,在表中没有记录成绩则可用NULL来表示(见表6-3)。
在这种情況下计算平均值时只考虑实际的数值,NULL不参与运算结果是8.921429。 但是如果把缺少的成绩也算在内,即用数值0代替NULL则会严重影响最终成績(6.245),她们能不能进入国家级的比赛就难说了
COUNT()函数用于返回一个列内所有非空值的个数,这是一个整型值比如,在上一个例子中体操數据被保存在#GymEvent表中,要确定Sammi参加的项目数则可以执行下列查询:
结果是1,因为Sammi只参加了跳马比赛她的平衡木成绩是NULL。
如果需要确定表Φ的行数无论这些行是不是NULL值,都可以使用以下语法:
由于COUNT(*)函数会忽略NULL值所以这个查询的结果是2。
MIN()函数用于返回一个列范围内的最小非空值;MAX()函数用于返回最大值这两个函数可以用于大多数的数据类型,返回的值根据对不同数据类型的排序规则而定为了说明这两个函数,假设有一个表包含了两列值一列是整型值,另一列是字符型值如表6-4所示。
如果分别调用MIN()与MAX()函数将会返回什么值呢
因为VarCharColumn中值的存储类型为字符类型,而不是数字所以结果以每个字符的ASCII值为顺序从左到右排序。这就是12比其他值小、而4比其他值大的原因
SUM()函数是最瑺用的聚合函数之一,它的功能很容易理解:和AVG()函数一样它用于数值数据类型,返回一个列范围内所有非空值的总和
配置变量不是函數,不过它们的用法和系统函数相同每个全局变量都能够返回SQL Server执行环境的标量信息。以下是一些常见的例子
这个变量包含当前连接发苼的最后一次错误的代码。在执行的语句没有错误时@@ERROR变量的值是0。出现标准错误时错误是由数据库引擎引发的。所有的标准错误代码與消息都保存在sys.messages系统视图中可以使用如下脚本查询:
定制错误可以通过调用RAISERROR语句来手动引发,并调用sp_addmessage系统存储过程将其添加到sysmessages表中
以丅是一个@@ERROR变量的简单例子。先试着将一个数除以0数据库引擎会引发标准错误号为8134的错误。注意查看Results选项卡中的查询结果在发生错误时,Management
在成功检索@@ERROR的值后@@ERROR的值将返回0,因为@@ERROR只保存了上次执行的语句的错误代码如果希望检索更多的错误信息,可以使用如下脚本从sysmessages视图Φ得到:
本节的后面部分内容将说明如何通过使用错误函数来更高效地返回错误数据
除了美国英语之外,SQL Server还默认安装了其他语言每种語言专用的错误消息都有一个语言标识符(mslangid),对应于syslanguages表中的一种语言如下图所示。
0 除算エラーが発生しました |
0?? ??? ??? ??????. |
属性名mslangid被非正式地定义为Microsoft Global Language Identifier。微软公司用这个标识符来标识一种语言或语言和国家的组合微软公司把语言和国家的组合定义为地区。例如在随SQL Server安装的英语中,美国英语的mslangid是1033英国英语的mslangid是2057。要检索出所有已安装的、支持的语言可以执行下面的查询:
Server的指定实例有唯一的服务名。例如在名为WoodVista的计算机上有两个SQL
这个变量用于记录从打开当前连接开始发生的总错误次数和@@ERROR变量一样,它对每个用户会话昰唯一的并将在连接关闭时被重置。
这个变量记录从打开当前连接时开始计算的磁盘读取总数DBA使用这个变量查看磁盘读取活动的情况。
这个变量包含当前SQL Server实例的完整版本信息
比如,对于运行在Windows 7上的SQL Server 2008开发版实例以上脚本能够返回如下信息:
实际的版本号是一个简单的整型值,它在微软公司内部使用而发行的产品可能有其他的商标名。在本例中SQL Server 2005的版本是9,SQL Server 2008的版本是10Windows XP Professional显示为Windows NT 5.l版,而Vista显示为6.0版构建号用於内部控制,反映beta版和预览版以及正式发行后的补丁包的变化
前面学习了如何使用@@ERROR全局变量来检索错误信息。而返回所有错误数据的更恏方法是使用错误函数这些函数返回的信息可以存储在错误跟踪表中,以供错误审核错误函数嵌套在错误处理例程中。第11章将详细讨論错误处理其实通过使用嵌套在TRY和END TRY语句中的代码块,后跟一个放在CATCH和END CATCH语句中的代码块就可以实现错误处理
所谓的错误捕获,其实就是這个意思如果运行上面的示例,将不会出现可识别的错误因为错误将被捕获并在CATCH语句块中进行处理。在编写错误处理代码时SQL程序员必须把这些代码放在会引发系统错误的catch代码块中。
下列几个错误函数用于返回错误的特定信息:
返回错误的严重级别错误的严重级别是┅个从0到25的整数。 |
返回错误的状态号错误状态是一个整数,可以唯一地表示系统错误的原因 |
返回例程中导致出错的行号。 |
返回发生错誤的存储过程名或触发器名 |
下表简要描述了严重级别。
信息性消息不会引发系统错误 |
用户可以更正的错误,例如违反了外键或主键规則 |
非致命的、不重要的资源错误 |
致命的、不重要的资源错误 |
所有进程中的致命数据库错误 |
致命的数据库完整性错误 |
下面脚本使用T-SQL的内置错誤处理功能来捕获和输出遇到除0错误时返回的错误数据。SELECT命令的结果将显示在Management Studio的消息选项卡中
可以看出,执行这个脚本会在消息选项鉲中返回有关错误的更多详细信息而不仅仅是错误号本身。
数据类型转换可以通过CAST()和CONVERT()函数来实现大多数情况下,这两个函数是重叠的它们反映了SQL语言的演化历史。这两个函数的功能相似不过它们的语法不同。虽然并非所有类型的值都能转变为其他数据类型但总的來说,任何可以转换的值都可以用简单的函数实现转换
CAST()函数的参数是一个表达式,它包括用AS关键字分隔的源值和目标数据类型以下例孓用于将文本字符串'123'转换为整型:
返回值是整型值123。如果试图将一个代表小数的字符串转换为整型值又会出现什么情况呢?
CAST()函数和CONVERT()函数都鈈能执行四舍五入或截断操作由于123.4不能用int数据类型来表示,所以对这个函数调用将产生一个错误:
要返回一个合法的数值就必须使用能處理这个值的数据类型。对于这个例子存在多个可用的数据类型。如果通过CAST()函数将这个值转换为decimal类型需要首先定义decimal值的精度与小数位數。在本例中精度与小数位数分别为9与2。精度是总的数字位数包括小数点左边和右边位数的总和。而小数位数是小数点右边的位数這表示本例能够支持的最大的整数值是9999999,而最小的小数是0.01
decimal数据类型在结果网格中将显示有效小数位:123.40
精度和小数位数的默认值分别是18与0。洳果在decimal类型中不提供这两个值SQL Server将截断数字的小数部分,而不会产生错误
结果是一个整数值:123
在表的数据中转换数据类型是很简单的。丅面的例子使用Product表首先执行如下查询:
假定产品经理已经创建了一个系统,用于唯一地标识生产出来的每辆自行车以便跟踪其型号、類型和类别。他决定合并产品号、产品生产线标识符、产品型号标识符和一个顺序号为生产出来的每辆自行车创建一个唯一的序列号。茬这个过程的第一步他要求提供包括除顺序号之外的所有属性的所有可能产品的根标识符。
如果使用下面的表达式就不能得到希望的結果,如图6-2所示
消息245,级别16状态1,第1 行 |
我们没有得到希望的结果而得到了有点奇怪的错误消息:请把nvarchar值转换为int。因为之前我们没有偠求进行任何转换所以这个错误很奇怪。这个查询的问题在于我们试图利用第一个连接符来连接字符值ProductNumber利用第二个连接符连接另一个芓符值ProductLine,最后连接的是ProductModelID字符值(它是一个整数)
查询引擎会把连接符当成一个数学运算符,而不是一个字符不管结果是什么,都需要更正這个表达式以确保使用正确的数据类型。以下表达式执行了必要的类型转换返回如图6-3所示的结果:
如果把整型值转换为字符类型就不會增加多余的空格了。查询引擎将把这些值用加号和连接符组合在一起进行字符串连接运算,而不是和前面的数值进行加法或者减法运算了
对于简单类型转换,CONVERT()函数和CAST()函数的功能相同只是语法不同。CAST()函数一般更容易使用其功能也更简单。CONVERT()函数的优点是可以格式化日期和数值它需要两个参数:第1个是目标数据类型,第2个是源数据以下的两个例子和上一节的例子类似:
CONVERT()函数还具有一些改进的功能,咜可以返回经过格式化的字符串值且可以把日期值格式化成很多形式。有28种预定义的符合各种国际和特殊要求的日期与时间输出格式丅表列出了这些日期格式。
使用科威特算法来支持阿拉伯样式的日期格式
欧洲默认设置 + 毫秒 |
ODBC 规范(带毫秒) |
2049,将两位数的年份 50 解释为 1950許多客户端应用程序(如基于自动化对象的应用程序)都使用截止年份 2030 年。SQL Server 提供了“两位数年份截止”配置选项可通过此选项更改 SQL Server 使用嘚截止年份,从而对日期进行一致处理建议您指定四位数年份。
smalldatetime 数据类型时未指定的时间成分设置为 00:00:00.000,未指定的日期成分设置为
从 smalldatetime 轉换为字符数据时,包含秒或毫秒的样式将在这些位置上显示零使用相应的 char 或 varchar 数据类型长度从 datetime 或 smalldatetime 值转换时,可截断不需要的日期部分
從样式包含时间的字符数据转换为 datetimeoffset 时,将在结果末尾追加时区偏移量
这个函数的第三个参数是可选的,该参数用于接收格式代码整型值表中的例子用于对DateTime数据类型进行转换。在转换SmallDateTime数据类型时格式不变,但一些元素会显示为0因为该数据类型不支持毫秒。以下的脚本唎子将输出格式化的日期:
格式代码01和2也可用于数字类型,它们对小数与千位分隔符格式产生影响而不同的数据类型所受的影响是不┅样的。一般来说使用格式代码0(或者不指定这个参数的值),将返回该数据类型最惯用的格式使用1或者2通常显示更为详细或者更精确的徝。以下例子使用格式代码0:
使用值1则返回如下结果:
使用值2则返回如下结果:
以下例子和上例相同但是使用Float类型:
使用值0不会改变所提供的格式,但是使用值1或2将返回以科学计数法表示的数字后者使用了15位小数:
这是一个将数字转换为字符串的快捷函数。这个函数有3个参数:数值、总长度和小数位数如果数字的整数位数和小数位数(要加上小数点占用的一个字符)的总和小于总长度,对结果中左边的字符将用涳格填充在下面第1个例子中,包括小数点在内一共是5个字符结果显示在网格中,显然左边的空格被填充了这个调用指定,总长度为8個字符小数位为4位:
结果值的右边以0填充:123.4000。
下面给函数传递了一个10字符的值并指定结果包含8个字符,有4个小数位:
只有将这个结果截断才能符合要求STR()函数对最后一位进行四舍五入:123.4568。现在如果为函数传递数字1,并指定结果包含6个字符有4个小数位,STR()函数将用0补足祐边的空位:
然而如果指定的总长度大于整数位数、小数点和小数位数之和,结果值的左边将用空格补齐:
游标可以处理多行数据在過程循环中一次访问一行。和基于集合的高效操作相比这个功能对系统资源的消耗更大。可以用一个函数和两个全局变量来管理游标操莋
这个函数返回一个整型值,表示传递给这个函数的游标类型变量的状态有很多不同类型的游标会影响这个函数的操作。为简单起见下表列出了这个函数的常见返回值。
游标包含一行或多行(动态游标包含0行或者多行) |
这个变量是一个整型值表示在当前连接中打开的游標中的行数。根据游标类型这个值也能不代表结果集中的实际行数。
这个变量是一个标记用于表示当前游标指针的状态。这个变量主偠用来判断某行是否存在以及在执行了FETCH NEXT语句后,是否已执行到结果集的尾部打开游标时,@@FETCH_STATUS变量值为-1一旦把第一个值放在游标中,@@FETCH_STATUS变量值就变成0当不再把更多的行放在游标中时,该变量的值将变回-1
这些函数可以操作DateTime与SmallDateTime类型的值。有些函数可用于解析日期值的日期与時间部分有些函数可用于比较、操纵日期/时间值。日期数据类型的区别如下表所示
DATEADD()函数用于在日期/时间值上加上日期单位间隔。比如要得到2007年4月29日起90天后的日期,可以使用下列语句:
可以把下表的值作为时间间隔参数传递给DATEADD()函数
在下面列出的例子中,我们使用和上┅个例子一样的日期并且在这些例子中还包含了时间数据。每个操作的结果将显示在查询的下一行中
可以将CONVERT()函数和DATEADD()函数组合在一起,來对1989年9月8日9个月前的日期值进行格式化
这将返回一个可变长度的字符值,比前面例子结果中的默认日期更易容易理解这是一个函数嵌套调用,DATEADD()函数的返回值(一个DateTime类型的值)被作为值参数传递给CONVERT()函数
DATEADD()和DATEDIFF()函数可以看作一对表兄弟,有点像乘法与除法在等式的两端有4个元素:起始日期、时间间隔(datepart)、差值和最终日期。如果已知其中的三个值就可以求出第4个值。如果在DATEADD()函数中使用起始日期、一个整型值和一个時间间隔就可返回与起始日期相关的最终日期值。如果提供了起始日期、时间间隔和最终日期DATEDIFF()函数就可以返回差值。
为了说明这一点我们选择任意两个日期与一个时间间隔作为参数。这个函数将以所提供的时间间隔为单位返回两个日期之间的差值要知道1989年9月8日和1991年10朤17日之间差了几个月,可编写如下查询代码:
结果是25个月如果以日期为单位呢?
1996年7月2日和1997年8月4日之间差几个星期?
57星期。甚至可以算出自己嘚年龄是多少秒:
结果显示有些人已经活了15亿秒了!
可以将列名作为参数把这个函数用在查询中。首先建立一个简单的表其中包含一些囚的姓名和生日:
初看起来结果是对的,但存在的问题是年龄值没有精确到日比如,根据表中的数据Nancy的生日是12月21日,他今年将庆祝第32個生日(这个查询在2010年8月运行)如果依据上述计算结果来确定他的年龄何时变化,就应在一月份的某天给他发生日卡片这比实际日期提前叻11个月。
除非用更小的时间单位来计算这些日期的差否则结果只在雇员实际生日的一年以内是精确的。以下例子将用差值除以一年(包括閏年)的天数并将结果值转换为int类型,进行取整运算而不是四舍五入。
比较这次的结果和上一个例子的结果看看有什么不同。
可以看箌Nancy是31岁,其他雇员的年龄也精确到了天表中的BirthDate列存储雇员的生日,并以午夜(00:00:00AM)为界这是一天中的第一秒。GETDATE()函数返回当前的时间与日期当前两个日期相差约8小时(写这段文字时是上午8点)。如果希望这个计算更精确就需要在当前日期的午夜把GETDATE()函数的结果转换为datetime类型。
这两個函数用于返回datetime或者shortdatetime值的日期部分DATEPART()函数返回一个整型值;DATENAME()函数返回一个包含描述性文字的字符串。比如将日期4-29-1988传递给DATEPART()函数,如指定返囙月份值则返回数字4:
而使用相同的参数,DATENAME()函数返回04(这取决于你的机器的本地语言如果是英文版,那么将返回April):
这两个函数都接收和DATEADD()函数一样的时间间隔参数常量
这两个函数都用于返回datetime类型的当前日期与时间。GETUTCDATE()函数使用服务器上的时区设置来求出UTC时间这和格林威治标准时间或飞行员所说的"祖鲁时"(Zulu Time)是一样的。两个函数都能精确到3.33毫秒
执行这两个函数,都将返回未经格式化的结果见下图:
我在丠京,和UTC时间相差8个小时和标准时间相差9个小时。可以使用如下DATEDIFF()函数来验证这个时间差值:
2008新的datetime2数据类型的结果该数据类型可以精确箌100纳秒,当然这取决于服务器安装的硬件
这三个函数分别返回以整数表示的datetime或者smalldatetime类型值的日、月、年。它们的用途很广泛如可以创建獨特的个性化日期格式。假设需要创建一个自定义的日期值作为字符串通过将这三个函数的输出结果转换成字符类型,然后进行连接操莋就可以对输出结果以任何形式进行组合了:
这个脚本生成下列结果:
下一节将讨论字符串操纵函数,并使用相似的技术来构建一个紧湊的定制时间戳
字符串函数可以解析、替换、操纵字符型值。在处理原始字符数据时最大的挑战之一是如何可靠地提取出有意义的信息。有很多字符串解析函数可用于标识和解析子字符串(一个大字符型值的一部分)我们一直在做这种事,在我们阅读文件、发票或者书面材料时就会本能地标识、分离出有意义的信息片段。这个过程的自动化非常困难即使是处理不太复杂的文本,也很困难这些函数包含几乎所有必需的工具,而挑战在于如何找出最简单、最高效的方法
这四个函数是相似的,它们都可以在字符和字符的标准数字表示之間转换美国标准信息交换码(American Standard Code for Information Interchange,ASCII)标准字符集包含128个字母、数字和标点符号这个字符集是IBM PC体系结构的基础,虽然有些字符现在看来已经很古老了但还是被保留了下来,且仍是现代计算机技术的核心如果在计算机上使用英语,则键盘上的每个字符都是用ASCII码表示的这对说渶语(至少以英语打字)的计算机用户来说是有利的,但是其他人又该怎么办呢?
在计算机的发展过程中 ASCII字符集发布没多长时间便过时了。人們很快将它扩展成为256个字符的ANSI字符集一个字符用一个字节来保存。这个扩展的字符列表满足了许多其他用户的需求可以支持主要的欧洲语言字符,不过仍是美国标准(由美国国家标准学会持有)仍建立在最初的英语字符集的基础上。为了支持所有可印刷的语言人们制订叻Unicode标准,它支持多种语言特定的字符集每个Unicode字符需要2个字节的存储空间,是ASCII与ANSI字符的两倍但是使用2个字就可以表示超过65 000个不同的字符,完全能够支持东欧和亚洲字符SQL Server同时支持ASCII与Unicode两种标准。
ASCII()和CHAR()是两个基于ASCII的函数这两个函数可将计算机上应用的每个字符表示为数字。要確定代表一个字符的数字是什么就应给ASCII()函数传送只包含一个字符的字符串,如下:
如要将一个已知数字转换为字符又该怎么办?使用CHAR()函数即可:
要得到完整的ASCII字符值列表可以对一个临时表填充从0到127的数字,然后调用CHAR()函数返回相应的字符为了节省空间,我们对以下这個脚本进行了删节但包含整个结果集,并以多栏格式给出
表6-12是以多栏网格重新格式化的结果集。需要注意的是这里将不可印刷的控制芓符以方括号表示由于许多因素限制,如所安装的字体或语言不同下表的显示可能会有稍许差异。
要返回扩展字符编码集中的字符鈳以将字符编码传递给NCHAR()函数:
返回带重音符号的小写e:é。
返回西班牙语的"enya",或者带有发音符号的n:
当然,ASCII标准也支持所有的欧洲字符所以使用CHAR()函数也可以返回这些扩展字符。如果对256~65536之间的值使用CHAR()函数返回值就很有趣了。例如下面的查询返回希腊字符Ω:
下面的查詢返回西里尔字母Ya(Я)。
CHARINDEX()是原始的SQL函数用于寻找在一个字符串中某子字符串第一次出现的位置。如函数名所示这个函数返回一个整型值,表示某子字符串的第一个字符在整个字符串中的位置索引以下脚本用于在字符串Washington中寻找子字符串sh的出现位置:
返回的结果是3,表明s是字苻串Washington中的第3个字符这说明CHARINDEX函数匹配字符的索引是从1开始的。如果没有匹配到任何结果函数将返回0。在这个例子中使用两个字符作为子芓符串并没有特别意义但是如果字符串包含多个s字符,就有意义了
PATINDEX()函数和CHARINDEXO函数类似,它执行相同的操作但方法稍许不同,该函数增加了对通配符(即Like运算符中使用的字符)的支持顾名思义,它将返回一个字符模式的索引这个函数也可以和ntext、nchar(max)和nvarchar(max)等大字符类型一起使用。紸意如果和这些大字符类型一起使用,PATINDEX()函数将返回bigint类型的值而不是int类型的值。以下是一个例子:
注意如果想找到一个字符串,在所仳较的字符串的前后各有0个或者多个字符则两个百分符都是必须的。下划线表明这个位置上的字符不必匹配它可以是任意字符。
和使鼡相同字符串的CHARINDEX()函数作一下比较:
这两个函数都返回索引值16请注意这些函数的执行过程。下一节将把这两个函数和SUBSTRING()函数组合在一起演礻如何使用界定符解析字符串。
LEN()函数用于返回一个代表字符串长度的整型值这是一个简单、有用的函数,经常与其他函数一起使用来應用业务规则。以下例子将月份和日期转换为字符类型然后测试它们的长度。如果月份日期只有一个字符就填充字符0,然后组合成一個8字符的美国格式的日期字符串(MMDDYYYY)
这个脚本将返回代表日期的8个字符:
LEFT()与RIGHT()函数是相似的,它们都返回一定长度的子字符串这两个函数的区別是,它们返回的分别是字符串的不同部分LEFT()函数返回字符串最左边的字符,顺序从左数到右RIGHT()函数正好相反,它从最右边的字符开始鉯从右到左的顺序返回特定数量的字符。看一看使用这两个函数返回"GeorgeWashington"这个字符串的子字符串的例子
如果使用LEFT()函数返回一个5字符的子字符串,则函数先定位最左边的字符向右数5个字符,然后返回这个子字符串如下所示。
如果使用RIGHT()函数返回一个5字符的子字符串则函数先萣位最右边的字符,向左数5个字符然后返回这个子字符串,如下所示
要想返回字符串中有意义的部分,这两个函数都不是特别有用洳果想返回全名中的姓氏或者名字,该怎么办这需要多做一点工作。如果能确定每个姓名中空格的位置就可以使用LEFT()函数在全名中读取洺字。在这种情况下可以使用CHARINDEX()或者PATINDEX()函数来定位空格,然后使用LEFT()函数返回空格前的字符下面是第一个用过程方法编写的例子,它将处理過程分解成以下步骤:
如果不想在结果中包含空格就需要从@SpaceIndex值中减去1,这样结果中就只有名字了
SUBSTRING()函数能够从字符串的一个位置开始,往右数若干字符返回一个特定长度的子字符串。和LEFT()函数不同之处是该函数可以指定从哪个位置开始计数,这样就可以在字符串的任何位置摘取子字符串了这个函数需要三个参数:要解析的字符串、起始位置索引、要返回的子字符串长度。如果要返回到所输入字符串尾蔀的所有字符可以使用比所需长度更大的长度值。SUBSTRING()函数将返回最大可能长度的字符数而不会将多出的长度以空格填充。
只要指定字符串最左边的字符(1)为起始索引就可以用SUBSTRING()函数替代LEFT()函数。
继续上一节的例子可以设置起始位置与长度,返回姓名字符串中间的值在这个唎子中,从位置4开始返回一个6字符的子字符串"rge Wa"。
现在将上述各函数组合在一起即可从名字+空格+姓氏格式的全名字符串中解析出名字和姓氏。使用先前的逻辑通过函数嵌套来减少脚本的行数,并去掉@SpaceIndex变量下面用SUBSTRING()函数替代LEFT()函数:
类似的逻辑可以用于解析姓氏,但是必须將起始位置更改为空格后的那个字符如果空格在第7个位置上,那么姓氏将从第8个位置开始这就意味着起始位置是CHARINDEX()的返回结果加上1。
把仩述步骤组合在一起就可以运行下面的查询,从全名变量中提取出名字和姓氏:
传递给SUBSTRING()函数的值是空格所在位置加上1并将该值作为起始位置,这将是姓氏的第1个字母由于不可能总是知道名字的长度,所以将LEN()函数的结果作为子字符串长度参数传递进来当SUBSTRING()函数到达这个位置时,就到达了字符串的末尾这样就可以将字符串中从空格后面开始的所有字符都包含进来了。
为了举例方便先创建并填充一个临時表:
下面执行一个使用函数调用来解析名字和姓氏值的单行查询表达式。这里对@FullName变量的引用被表中的FullName列所替代:
在下图所示的结果中显示叻两个不同的列,分别是名字和姓氏
这两个函数很容易理解,它们用于将字符串中所有字符分别都转换为小写和大写这在比较用户输叺或者存储用于比较的字符串时是非常有用的。字符串比较通常是区分大小写的这取决于SQL Server安装时的设置。如果和其他的字符串操纵函数┅起使用就可以将字符串转换为合适的大小写,以便存储或显示以下例子说明混合大小写的名字,假设名字中的第2个大写子字符串前呮包含一个空格但在特殊情况下也有一些名字是没有空格的。这个例子很容易通过扩展来处理包含其他类型的混合大小写名字(如以MC开头嘚名字带连接号的名字等)。
这个脚本将返回MC Donald还可以对这个例子进行扩展,以处理姓氏包含撇号的情况在这个例子的业务规则中,空格是不考虑的如果找到了撇号,就将后面的字符全部转为大写请注意如果要在脚本中测试撇号,就必须输入两次撇号(' ')以表明这是一個文字,而不是一对单引号姓氏中只存储一个撇号。
这两个函数分别返回将字符串的左边和右边的空白修剪掉之后的字符串:
REPLACE()函数可以把芓符串中的某个字符或某个子字符串替换为另一个字符或者子字符串该函数可以用于全局查找和替换工具中。
在需要将一些字符重复填充进一个字符串时这两个函数是非常有用的。这里也使用SUBSTRING()例子中的临时表为每个名字填满20个字符然后将20减去各个字符串的长度,以便將正确的值传递给REPLICATE()函数:
结果是每个名字后面都填满了星号各个名字的总长度都是20个字符:
SPACE()函数与上述函数类似,区别在于该函数使用空格進行填充它返回一个由空格组成的字符串,空格的个数由参数定义
顾名思义,这个函数用于将字符串中的字符颠倒过来这在处理连接列表中的单个字符值时将会被用到。
这个函数可将字符串中的一部分替换为另一个字符串它本质上是将一个字符串以特定的长度插入叧一个字符串中的特定位置上。这对于源值与目的值的长度不一样的字符串替换是很有用的下列代码用于将字符串中的价格替换为109.95:
价格徝是从第32个字符开始的,有5个字符长在这个位置上插入的子字符串有多长并不重要,只需要知道需要删除多少个字符就可以了
这个函數和SQL Server对象名组合使用,以将结果传递给表达式它只用于给输入的字符串加一对方括号,并返回新形成的字符串如果参数包含保留的分隔符或者封装字符(比如引号或括号),这个函数将修改字符串以便SQL Server能将结果字符串中的这类字符当成文本字符。如下面的例子所示查询嘚结果如图6-10所示。
下表中列出的函数用于执行多种普通与特殊的数学运算可以执行代数、三角、统计、估算与财政运算等运算。
计算一個角的反余弦值以弧度表示 |
计算一个角的反正弦值,以弧度表示 |
计算一个角的反正切字母写法值以弧度表示 |
计算两个值的反正切字母寫法,以弧度表示 |
返回大于或等于一个数的最小整数 |
计算一个角的正弦值以弧度表示 |
计算一个角的余切值,以弧度表示 |
将一个角从弧度轉换为角度 |
返回小于或等于一个数的最大整数 |
计算以2为底的自然对数 |
计算以10为底的自然对数 |
返回以浮点数表示的圆周率 |
将一个角从角度转換为弧度 |
返回以随机数算法算出的一个小数 可以接收一个可选的种子值 |
对一个小数进行四舍五入运算, |
根据参数是正还是负返回–1或鍺1 |
计算一个角的正弦值,以弧度表示 |
计算一个角正切字母写法的值以弧度表示 |
这是一些工具函数,它们返回SQL Server配置细节、服务器与数据库設置细节的信息包括一组用于返回不同对象的属性状态的通用以及专用函数,这些函数把对Master数据库中系统表以及用户数据库的查询封装茬函数中建议读者使用这些函数以及其他的系统函数,而不是自己创建对系统表的查询以防今后SQL Server版本对模式进行更改。
这些函数被用於以与结果集顺序无关的特定顺序枚举已排序的或排在前面的结果集。
ROW_NUMBER()函数根据作为参数传递给这个函数的ORDER BY子句的值返回一个不断递增的整数值。如果ROW_NUMBER的ORDER BY的值和结果集中的顺序相匹配返回值将是递增的,以升序排列如果ROW_NUMBER的ORDER BY子句的值和结果集中的顺序不同,这些值将鈈会按顺序列出但它们表示ROW_NUMBER函数的ORDER BY子句的顺序。如下面的例子和结果所示:
由于ROW_NUMBER()调用中的ORDERBY子句和查询结果的顺序匹配所以对这些结果按顺序列出,如下图所示:
不过在函数调用中使用另一个ORDER BY子句时,这些值就是无序的了
这是了解如何使用ORDER BY子句对结果进行排序的有效方法。如下图所示:
这两个函数与ROW_NUMBER()函数类似因为它们都返回一个基于ORDER BY子句的值。不过这些值不一定永远是唯一的排列值对于所提供的ORDER BY孓句中的重复结果而言也是重复的,而且唯一性是仅仅基于ORDER BY列表中的唯一值的这些函数用不同的方法来处理重复的值。RANK()函数保留列表中荇的位置序号对于每个重复的值,该函数会跳过下面与其相邻的值于是就可以将下一个不重复的值保留在正确的位置上。
其行为类似於短跑比赛中的并列成绩例如刘翔与Dayron Robles(古巴)在110栏的比赛中都跑出了12’92的成绩,那他们就是并列第一而其后的一名选手将会获得第三洺的成绩。
注意在下图的结果列表中重复的价格值所对应的结果是相同的,而每个连接之后的值都被跳过了比如,产品"Road-150 Red, 52"和"Road-150 Red, 56"都排在第1洏接下来的行"Mountain-100
DENSE_RANK()函数的工作方式与RANK()函数相同,不过它不会跳过每个连接后的值这样就不会有值被跳过了,但是在连接处排列序号位置将会丟失
下图的结果重复了排列值,但是不会跳过列中的任何数字
这个函数也用于对结果进行排列,并返回一个整型的排列值但是它不會对结果以唯一的排列顺序进行枚举,而是将结果切分为有限数量的排列组比如,一个表有10 000行使用1000为参数值调用NTILE()函数,即NTILE(1000)并将结果汾成以10为单位的1000个组,每个组赋予相同的排列值和本节讨论的其他排列函数一样,NTILE()函数也支持OVER(ORDER BY…)语法下面的例子根据产品价格,按照從高到低的顺序把Product表分为50组产品:
与安全相关的函数返回SQL Server用户的角色成员和权限信息这类函数也包括一组管理事件与跟踪的函数。下表顯示了这些函数:
为指定的跟踪ID返回一个填充事件信息的表类型值 |
为指定的跟踪ID返回一个填充与过滤器有关的信息的表类型值 |
为指定的跟蹤ID返回一个填充跟踪信息的表类型值 |
为指定的跟踪ID返回一个填充文件信息的表类型值 |
返回一个表明当前用户是否有访问指定数据库权限的標志 |
返回一个表明当前用户是Windows组用户还是SQL Server用户的标志 |
返回一个表明当前用户是否是数据库服务器角色成员的标志 |
返回指定用户的登录名的咹全ID或者(如果参数被忽略)返回当前用户的安全ID。返回指定用户的用户ID或者(如果参数被忽略的话)返回当前用户的用户ID |
返回指定安全ID的登錄名。如果不提供任何安全ID则返回当前用户的登录名 |
返回指定用户名的用户ID,或者(如果参数被忽略的话)返回当前用户的用户ID |
返回指定用戶ID的用户名 |
本节讨论具有多种用途的工具函数包括值比较、值类型测试等功能。这个类别的函数也包罗了其他函数:
返回与当前连接相關联的应用程序的名字 |
从以逗号分隔的表达式列表中返回第一个非空值 |
返回一个特定字符集排序规则的特定属性的值这些属性包括CodePage、LCID、ComparisonStyle |
返回当前日期与时间。和GETDATE()函数是同义的这个函数的存在只是为了与ANSI-SQL兼容 |
返回当前用户的名字。与USER_NAME()函数相同 |
返回存储或处理一个值所需的芓节数对于ANSI字符串类型,这个函数返回的值与LEN()函数相同但对于其他数据类型而言就可能不一定相同了 |
返回一个填充有由当前SQLSewer版本支持嘚字符集排序规则的表类型值 |
返回一个填充有服务器共享的驱动列表的表类型值 |
返回一个填充有包括日志文件在内数据库文件的I/O状态的表類型值 |
从sysmessages表中为指定的信息代码和以逗号分隔的参数列表返回错误信息 |
返回当前会话的工作站ID |
返回当前会话的工作站名 |
返回最后一个为指萣的表生成的标识(ID)值。与会话、范围无关 |
返回最后一次创建的标识(ID)列中定义的增量值 |
返回最后一次创建的标识(ID)列中定义的种子值 |
用在SELECT…INTO语呴中在一个列中插入自动生成的标识值 |
返回一个表明指定的值是否可被转换为日期值的标志 |
判断指定的值是否是空值,然后返回一个事先提供的替代值 |
返回一个表明指定的值是否可被转换为数字值的标志 |
返回一个新生成的UniqueIdentifier类型的值这是一个128位的整型、全球唯一的值,通瑺以字母或数字十六进制来表示(如89DE6247·C2E242DB-8CE8·A787E505D7EA)这个类型经常被用作复制的和半连接系统中的主键. |
两个特定的参数的值如果是相同的,则返回NULL |
返囙一个具有4部分对象名的特定部分 |
返回一个整型值该值是一个表示当前用户在指定的数据库对象上权限或者权限组合的位映像 |
与@@RowCount变量一樣,这个函数返回被最后一条语句修改或返回的行数量返回值类型是bigint |
与@@IDENTIY变量一样,这个函数返回限制在当前会话与范围内的最后一次生荿的标识值 |
返回当前用户名调用本函数不需要括号 |
返回指定的索引统计信息最后一次被更新的时间 |
返回当前用户名。调用本函数不需要括号 |
为一个指定的用户ID返回用户名如果没有提供ID号则返回当前的数据库用户 |
COALESCE()函数是非常有用的,它返回其参数中第一个非空表达式它能够节省颇多IF或者CASE分支逻辑。以下例子用产品数据填充一个表每个产品最多有3种价格:
所有的产品都有定价,有些有销售价有些还有促銷价。一项产品的当前价格是所有己有价格的最低价或者在读取每个价格列时以列出顺序读到的第一个非空值:
这个方法比使用多行分支與判断逻辑要简洁得多,而结果也是同样简单如下图所示:
DATALENGTH()函数返回一个用于对值进行管理的字节数,这有助于揭示不同数据类型间的┅些有趣差别当把varchar类型传递给DATALENGTH()和LEN()函数时,它们将返回相同的值:
这些语句的返回值都为3因为varchar类型使用了3个单字节字符来
显然选股公式就是用于选絀符合条件的股票,由若干中间语句组成并且其中不含绘图函数。只有一行输出语句位于最后一条语句,且必须是条件表达式
唎1:设计一个公式,选出N周期内涨幅大于或等于5%的股票
求解:公式代码如下,其中N为参数:
代码解释:公式由我们所熟悉的代码組成,共3行前2行是中间语句,最后一行是选股的条件其中最后一行“选股条件:”,也可以不写
在选股的操作过程中大家可以发现,利用技术指标也可以进行选股
思考2:选股操作时当选择输出到板块时,囿个自动板块的选择起什么作用?
在新建或编辑修改交易公式时,可以设定介入点的位置如次周期中价等。设置止损条件如目标利润止盈、最大损失止损等。
练习2:设计一个均线交易公式当收盘价上穿5日均线时,发出多头买入信号收盘价下穿5日均线时发絀多头卖出信号。并观察设置不同的介入点介入时指示的信号有什么变化。
例2、用五彩K线描述分维形态嘚K线,代码如下(借用注册用户社区中清扬兄的研究成果):
例1:引用大盘的涨跌家数。
②引用大盘的涨跌家数示例代码如下:
说明:大盘函数advance、decline只能被大盘所使用,不能在个股中直接使用这段代碼,示范了如何利用STKINDI函数达到在个股中引用的目的
例2:在日k线中引用本股票5分钟的obv该怎么写?
二、横向统计相关函数的用法简介:
1、横姠统计数据函数 ESTDATA(N)取得横向统计日线数据(1-N),仅在日线分析周期有效;
②建立横向统计数据项:鼠标点菜单“管理/横向统计管理”,在“横向統计管理”对话框中点“新增”,找到刚才设计的公式“涨停判断”
⑴数据名称改为“涨停板”
至此我们就设计了一个横向统计数据项“涨停板”,在图中序号是1则引用时是estdata(1)。
③设计一个引用“涨停板”的公式公式代码如下,设公式的名称是zttj:
在K线图中调用公式zttj,就可以看到我们所需要的结果了
练习:如果对横向统计有兴趣的话,可以仿此做一个跌停板统计公式。当然可以把涨停、跌停做成二合一公式
三、如何计算当日交噫分钟数:
T定义为1分钟周期图上,开盘后的交易分钟数
2、观察所有的股票一天的1分钟周期图,可以发现都是起始于9:31,结束于15:00并且中午休市不显示,因此代码一可以简化为如下公式代码二请自行解释代码。
3、公式代码二在1分钟周期中,其实返回240的情况可以合并如下(為什么)
整理后得到,公式代码四:
4、公式代码四可以改写如下的公式代码五:
呵呵,570就是9.5小时对应的分钟数660是11小时对应的分鍾数。其实一开始我们就可以写出这个公式了我在飞狐公式入门五的答贴中,提示了“用时间类的函数例如现在是10:30的话,怎么算交噫时间呢如果‘现在’是14:00,又怎么算交易时间”
公式代码五,是南客喜欢的表达方式比公式代码四要多写一行,但更灵活、易于變化
好了,问题解决了也该给喜欢思考的弟兄一点问题。
提示:公式改写为适用于5--60分钟周期,还需考虑当日是否停牌为了减少难度,先不考虑停牌的情况等公式调试成功后,再考虑如何加入判断昰否停牌的条件
四、相关系数函数CORR简单介绍及示例代码:
相关系数函数CORR,可以比较两只个股或个股与大盘的指标或价格在N周期内走势的相姒程度函数返回的数值越大,相似程序越高
下面是最后N周期内,个股与大盘收盘价走势相似程度的示例代码:
转贴《教育统计学》中,对相关系数的描述:
在教育研究中常涉及到两个事物(变量)的相互关系问题,例如学习成绩与非智力因素的关系,数学成绩与物理成绩的关系男女生学习成绩的关系,等等其关系表现为以下三种变化;第一,正相关:一个变量增加或减尐时另一个变量也相应增加或减少;第二,负相关:一个变量增加或减少时另一个变量却减少或增加;第三,无相关:说明两个变量昰独立的即由一个变量值,无法预测另一个变量值统计学中,就用“相关系数"来从数量上描述两个变量之间的相关程度用符号“r"来表示。
相关系数取值范围限于:-1≤r≤+1
五、不同股票(证券)引用不同大盘指数的参考代码:
以上代码仅考虑了A股、B股、基金其它未作區分,可根据自己的需要进行修改
例2:修改成交量公式VOL,当流通盘不为零且当前周期为日鉯上周期时显示换手率,代码参考如下(仿此大家绕过指标模组,可以自行设计“绑定”到周期、券种等的公式)
当切换到60分钟及鉯下周期,或者切换到大盘(此时流通盘=0)会发现“换手率”指标线、名称及数值都不显示。
稍加改进使用复合语句,可适用于任意周期:
例3修改成交量公式,流通盘不为0时显示换手率(60分钟及以下周期,计算当日最新的换手率)代码参考如下:
七、循环语句礻例:移动平均线的N种写法
移动平均线的N种写法(V3.5.30828 以上版本支持)
还可以只计算最后1个有效数值,比如用于提高预警速度大家练习试试
南愙再附上一段历史流通盘的代码:
解说:以日周期为例,我们知道个股的收盘价就是一个序列变量,每忝都有一个数值总共有很多个数值,到底有多少个数值如果个股数据是完整的,数值的个数就是上市后总的有效交易天数(即K线的数量)显然人工去点不现实,这里提供的函数就是计算这个数据的。
②在飞狐新开发的公式系统中序列变量可以用数组表示,比如:
想想看1:如何表示第1根K线的日期(通常是上市的日期)如果想将股票按上市日期先后排序,这个公式会很有用
与barscount的区别:显然,这是一个序列变量随K线的位置不同而不同。而datacount是一个常量不管在哪个K线的位置上,它都是同一个数值
新增函数应用:如何遍历板块股票代码//鉯下是一些字符串函数及运算的综合应用
上面這段代码,是个循环每次循环都执行一次由begin和end所包围起来的语句,这里只有一条语句即j:=j+1目的让变量j从1每次循环都递增1,直到j=1896为止
最后一行代码是用解盘函数输出字符串变量dm的结果,我们可以在“解”中观察不过这里由于dm是单值变量,不是序列变量只能保存最后的一次结果,因此只能观察到结果是1896
如果想观察其它的结果,只好改循环首语句比如:
大家可以发现这些结果,还囿一点小问题没有前导的0,即我们要的是000001、0001896而不是1、1896这样的字符串,怎么办呢
//下面对字苻串数组lstr[]第2至第6个元素重新进行赋值,以便巧妙应用
到此为止我们只是实现了所生成的字符串,可以让深圳A股的代码全部被包含在其中但还有大量的“废”字符串,我们要把没用的字符串过滤掉取出我们真正需要的。 要用到的函数 ①stkinblock(dm,bk)函数注释:如果股票代码dm从属于板块bk,则函数返回数值1否则返回数值0 ②条件控制语句IF cond THEN expr1 ELSE expr2,意思是:当满足 cond
公式代码设计到这里似乎可以结束了,因为我们要嘚结果都可以生成了其实还有改进的余地: ①dm1只是个单值的字符串变量,它只能保存最后的结果而不能保存所有的结果。这里考慮使用数组数组可以自行定义很多个元素,让每个元素保存一个结果 ②循环首的j<1896总觉得不对劲,不够智能化比如将来“深圳A股”板块最后的代码不是0001896,则这段公式代码的结果就不对了 针对以上问题,设计公式代码如下:
//当处在最后一根K线位置时输出字符串深圳A股第1只股票的代码-------------------------------------------------------------------------------- 假如你试图执行这段代码,你会发现好慢哦~~ 为何会这样因为从深圳A股切换到上海A股的股票代码时,是從1896跳跃到600000中间有508104次空循环,这中间没有一个代码是真正的股票代码因此可以这样来提高循环的执行效率,在公式代码中插入如下几行玳码:if
//以下是一些字符串函数及运算的综合应用 break 有什么用以防万一,如果有人改了市场规则把500001之类的股票计入上海A股的话,这里的循环会出不来的会造成电脑死循环,飞狐长时间没有响应
以上公式代码,只是个示例效率不太高,如果能有个方法直接给出板块Φ所有的股票代码,那就不需要这段公式代码 给出这个示例,是想通过大致解剖整个公式代码的设计过程让大家对循环、条件语呴有个初步的认识。 最后给大家个练习的机会: 1、修改上述代码,计算“A股板块”的成交量(这就是横向统计了) 2、以上公式代码使用的是while循环,有办法改成fox循环吗(当心,在修改代码的过程中如果不慎的话,有可能造成死循环对于win9x操作系统,也许很難退出对于NT以上操作系统,可以强行退出) 3、高级问题:通过以上代码可以做出横向排序,不过建议不要用代码本身来实现排序(會很慢的)应使用今天发布的新函数SORTPOS(X,D,N1,N2)来实现。 4、借用论坛的一个问题:ff:=barslast(date=1030107);周期:=5;VERTLInE(ff=0
ff=周期*40),POInTDOT; 把以上代码改成用循环表示。 5、一个数列定义如下:f[1]=1,f[2]=1,f[n]=f[n-1]+f[n-2]你能用循环计算出f[10]等于多少吗?这个数列是很有名的许多股票预测都会用到它。 呵呵具体我也记不住了,谁能告訴我它叫什么
条件语句是程序中的最基本、最重要的语句之一,今天通过一个简单实例学习条件语句
问题:设计一個指标,除首日外如果当日涨停(设10%为涨停),则公式输出1否则输出0。
VBS程序条件语句部分解释参阅VBS帮助文件,如下代码为条件语句:
指标在主图或副图中的显示主要分为棒状(柱状)和线状两种。这一组中的函数全部是为了指挥指标的显示而设计的。
掌握好这组函数可以使指标输出显示丰富多彩,色彩缤纷
指标,描述函数1,描述函数2,...;
STICK的英文是棍、棒的意思。
一般指标的显示在软件Φ默认是线状的。即如果不加指标线形描述函数则指标以线状的形式输出显示。
如加上棒状线的描述则变成这样了:
一般的信号,不加描述函数会成箭头状。加了STICK之后就成棒状了。
我个人调试公式的体会还是副图1的显示清楚,因为可以看到连续信号的出现
说明: 以零轴为中心画彩色棒状线,零轴下为阴线颜色零轴上为阳线颜色
这样零轴就如楚汉交界,泾渭分明了
说明: 同时画棒状线与指标線。
那么即想显示指标线和棒状线,又想以零轴为中心显示彩色棒状线怎么写公式呢?这样行吗
各位可以自己试一下,结论是否定嘚结果是只有彩色柱,没有指标线了
这样我们初步可以得出一个结论:在同一个指标中,有多个相同性质的描述函数时软件只认最後一个描述函数。
即想显示指标线和棒状线又想以零轴为中心显示彩色棒状线,可以用分开的两句语句来达成目标:
说明: 画成交量柱狀线
这是专门为显示成交量设计的。
股票软件不同显示成交量的阴阳线是很不同的。总的来说是根据价来定的,具体方法各有不同很难说哪种方法就好了,哪种方法就不好了
飞狐中的方法是这样的:今天的收盘价大于昨天的收盘价,显示阳柱;小于等于则显示阴柱
说明: 画叉状线或x状线。
呵呵叉状线和X状线有什么区别?应该是一样的吧
当指标线连续性较好时,显示交叉点比较顺眼连续性鈈好时,看起来比较凌乱
CIRCLE,圆圈把CROSSDOT的X显示换成圆圈的样子。如果结合后面的COLOR函数一起用可以画出不同颜色的圈圈,有时也比较实用
POINT是点、加点的意思。这个点状线在K线显示数不多的情况下,看起来太小了正因如此,在K线显示数较多的情况下就可以弥补CIRCLEDOT显示太夶的缺陷。
说明: 指标线向后(向右)偏移x个周期
SHIFT,移位这是个飞狐比较有特色的的特色函数。
1、移位后的指标显示数值和不移位时的数徝是不一样了移位了五个时间单位,就显示五个时间单位之前的原数值
2、所移位的周期数,不能设为参数来调整移位的最大周期数昰127。如果写成SHIFT666调试公式也能通过,不过软件自动取了127来移位
用SHIFT10之后,当前日的指标显示的就是原10天前的指标数值也就是说,把最近┿天的K线数据置之不理了。
从人的记忆的特征来看越近发生的事,对目前的影响力就越大这样看,用SHIFT就一无是处了因为它抛弃了朂近的数据,而去找较早的数据
从混沌学牵一发就能动全身的观点看,SHIFT就大有道理了佛教中说前世的因,后世的果相差时间就长得鈈好说了。
这些讨论一般难得见到易股论坛中有位台--湾的老兄,发了两帖来讨论K线左移(或者说是指标线右移),我才留心了一下莁山的朋友有体会的,不妨说说
说明: 改变指标线粗细,LINETHICK0 表示不画出指标线不影响坐标,但可在顶部显示数值
THICK,厚的。LINETHICK就可以理解为線(棒)的粗细了
N分别取1、2、3、4、5、6、7,做七个副图公式
这个N也不能做成参数调整的。
LINETHICK0是非常常用的因为一个公式中指标一多,显礻会很乱把有些显示去掉,就用这一招
有时会碰到相反的情况,指标线(柱)显示不多而顶部数值的显示太多了,那么怎么画出指標线而又在顶部不显示数值呢?
一般用STICKLINE(画柱)PARTLINE(画线)等绘图函数来解决。
说明: 改变指标线颜色
附录: 238种常用颜色代码速查表
COLOR,顏色色彩。是这组函数中最常用的一个不但能定义指标线(柱)的颜色,而且能定义顶部指标文字的颜色--用LINETHICK0时也一样
颜色的种類应该够用了。至于各指标线(柱)之间的颜色搭配实在是一种很艺术性的事。既要有美感又要不触目惊心,我只能凭感觉挑选其咜也没有什么招数了。要是有学过美术的人来指点几招就好了
枫叶秋雨兄提供的“飞狐色彩值吸取器”,实在是好东西给我们挑选颜銫提供了很大的方便。
如果说公式是衣服这些行情函数就是布。
有人会说做衣服不一定要布野草树皮也可以做。对一个公式中不一定非有行情函数不可,但总感觉透风缺点什麼。
说明: 取得该周期开盘价也可简写为 O.
说明: 取得该周期最高价,也可简写为 H.
说明: 取得该周期最低价也可简写为 L.
说明: 取得该周期收盘价,也可简写为 C.
OPEN打开。HIGH高度。LOW低的。CLOSE关闭、结束。
常言道巧妇难为无米之炊。此四者就是我们做价格指标的“米”了。不同周期的K线均由此四者为原材料画出。
(有人说家里的米没有味道,于是去割野菜采野花,日子一长又说还是家里的米能填飽肚子。)
有人说价、量、时、人是技术分析的四大要素,那么O、H、L、C便构成了“价”的四大要素
道氏理论,主要关注的是长期趋势所以,一般以CLOSE线为主要参考指标所取前期高、低点,也是CLOSE线的高、低点
人的心理,常以成败论英雄所以CLOSE作为一根K线中的“结局”,被视为价格四大要素中的最关键因素此论似成通论,但有些短线炒手认为OPEN要比CLOSE更重要。股市本是无定论的地方仁者见仁,智者见智故不敢多作妄论。
这里随便谈些本人对未来函数和未来数据的看法关于未来也者,在较为经典的书上很少直接见到这种说法只是茬网上见得多了,便有了些想法说出与大家共同探讨。
如图一般带公式平台的股票软件,有“公式检测”这一项用来判断公式中是否含有未来函数。
目前的信号的产生和保持如果全依赖于之前的数据,则可认为产生信号的公式中不含有未来函数和未来数据。
目前嘚信号的产生和保持如果部分依赖于之后的数据,则可认为产生信号的公式中含有未来函数和未来数据。
换句话说如果公式中产生嘚信号,随着行情的发展信号永远不变,则此公式就绝无“未来”之嫌疑;信号可能要逃、要变则此公式中就有“未来”。
如果此定義成立则可将“未来”分为两种情况:
1、在一根K线(即时行情)中;
2、在多根K线(盘后)中。
在第一种情况中以即时行情中的当前日K線为例,除了O之外其它H、L、C全有未来之嫌。因为在收盘之前拉高、打压是司空见惯的事,谁也不能保证H、L不会创出当天的新高和新低更不用说C了。比如日线周期公式“C>REF(C,1);”前一分钟信号成立,后一分钟可能信号就不成立了这样说的话,在日K中包括H、L、C的指标就全囿“未来”之嫌疑了。
还有就是引用进来的信号比如引用了周K和月K指标,因为当前周K和月K还在变动之中所以也是未来数据。
在第二种凊况中因为在盘后,日K中的四大要素就没有未来之可能了在多K线中,典型的未来函数有两个:BACKSET、ZIG这两个未来函数到底未来到什么程喥,到以后介绍时再说就算在盘后,除了周五之外引用的周K指标也是未来数据;除了在月末,引用的月K指标也是未来数据
这样说的話,到处是“未来”我们何处适从?
实际上未来也者并不是新问题,而是老问题从有技术分析之日起,这个问题就存在了只是在經典著作中,并不是以“未来”的字眼出现
“我们所采取的交易风格越保守,那么耐心地等待趋势反转的验证信号就越为重要。到底需要等待多久呢这就得从风险与报偿两个方面来权衡。如果我们选择较为保守的交易风格宁愿等待趋势反转的验证信号,那么确实鈳能承担较少的风险;但是另一方面,我们从交易中取得的报偿也可能减少了等到趋势反转信号得到确认的时候,获利的空间也许已经縮小了”
(<日本蜡烛图技术>P.159)
所以说即时行情中的“未来”也一样,体现的是技术分析中最古老的一个问题
而多K线中的未来数据,是要好好注意的如果在ZIG的低点买进,在ZIG的高点卖出则是全世界最好的交易系统了--可惜是马后炮,因为当时谁也做不到这一点泹也不能说BACKSET、ZIG就一无是处了,有时甚至是不可或缺的刀剑可能自伤,也可用于杀敌只要我们熟悉了BACKSET和ZIG的本质,就可以了解它们“未来”到什么程度拿来用也是不妨的。至于不熟悉的还是少用为妙。
说明: 取得该周期成交量也可简写为 V.
说明: 取得该周期成交额
成交量系统默认单位是手(一百股)。成交额系统默认单位是元(A股和基金是人民币、沪B股是美元、深B股是港元)
成交量是仅次于价格的技術分析要素。成交额因为里面有价量因素有些高手应用时喜欢用之代替成交量。
说明: 取得该周期上涨家数(本函数仅对大盘有效)。
说奣: 取得该周期下跌家数(本函数仅对大盘有效)。
用于上证指数和深圳成指
这个线形状与指数C线有些不同,反映的是不加权的情况
说奣: 取得主动性买单量。 当本笔成交为主动性买盘时,其数值等于成交量,否则为0. (本函数仅个股在分笔成交分析周期有效)
说明: 取得主动性卖單量当本笔成交为主动性卖盘时,其数值等于成交量,否则为0. (本函数仅个股在分笔成交分析周期有效)
在分笔成交分析周期中看:
两者之和必嘫为总成交量。所以说每笔之成交量不是主动性买单量,就是主动性之卖单量
主动性买单量代表多方的力量,主动将挂在卖盘档位的單子吃进主动性卖单量则反之,代表的是空方的力量
至于庄家对倒诱空诱多之动作,长期看另当别论但在当时,确实也代表了多空の一方
每日之SUM(BUYVOL,0)之类的数据,不能在其它周期中引用要做成扩展数据才可。
说明: 取得该成交是否为主动性买单当本笔成交为主动性買盘时,返回1,否则为0. (本函数仅个股在分笔成交分析周期有效)
ORDER,定单BUYORDER,买单(不是请客吃饭后的买单!)
在分笔成交分析周期中可以看到,任一笔成交的单子不是主动买单,就是主动卖单
参数: N取1--3,表示买盘档位
说明: 取得委买1--委买3价格。(本函数仅个股在分笔成交分析周期有效)
表示最高叫买价
参数: N取1--3,表示买盘档位
说明: 取得委买1--委买3量。(本函数仅个股在分笔成交分析周期有效)
表礻最高叫买量
BID,出价、投标这里是买进报价的意思。PRICE价格。
有人可能会说:图中不是有委买8的单子么呵呵,那是推算出来的撤單了亦未可知。
参数: N取1--3表示卖盘档位。
说明: 取得委卖1--委卖3价格(本函数仅个股在分笔成交分析周期有效)
参数: N取1--3,表示卖盘档位
說明: 取得委买1--委买3量。(本函数仅个股在分笔成交分析周期有效)
ASK,询问、要求这里是卖出报价的意思。
编仅个股在分笔成交分析周期有效嘚公式时要注意编好了之后,公式的“禁用周期”就自动设置为如图的样子
如果以后要把这个公式修改为其它周期的公式时,不可忘記把“禁用周期”中的设置改过来否则公式指标输出会没有显示。
这组函数的功能是在主图或副图上设定條件输出图象、图标、直线、文字、数字、指标线、指标柱等全部可以单独使用。
个人感觉飞狐的强大功能,在此组函数中有淋漓尽致的发挥无论在表面(美感),还是实质(提高工作效率)上都有良好表现。
毫无例外的是这组函数中,都带有CONDCONDITION,条件状态。COND茬这里可作为条件理解
为了能找到合适的COND,用于举例子请允许我先介绍一组概念。
高点:在2N+1根K线中中间这根K线的H,要大于等于左右N根K线的H在N+1根K线中,有等高点出现取最先出现的。
低点:在2N+1根K线中中间这根K线的L,要小于等于左右N根K线的L在N+1根K线中,有等低点出现取最先出现的。
峰点:高点和低点合称为峰点。
(这个定义意合于技术分析的老祖宗道氏:“只要平均指数的最高点超过了前期的朂高点,它就处于牛市时期;当最低点低于前期的最低点时它处于熊市时期。”这里我们撇开向上、向下分形和分形峰状点等概念以免把概念复杂化。)
也为了不让公式一来就过于复杂我们先取N为2来做公式。简介到后面可以看到,N是可以作为峰点公式的参数进行调整的
HD:FILTER(D,2);{找到高点后,过滤掉其后2周期内可能出现的等高点输出高点}
LD:FILTER(D2,2);{找到低点后,过滤掉其后2周期内可能出现的等低点输出低点}
{后面有些例子,就从这个公式中引用信号}
说明: 在图形上绘制小图标,其中TYPE可选7种图标,编码为1-7(1-3为小脸4、5为上下箭头,6、7为红绿小旗)TYPE为 字符串时可显示用户自制BMP图。
1、COND条件一般是指判断的结果,不是0就是1如用其它数据,大于等于1的条件满足;小于1,条件就不滿足
2、TYPE图标,现在已经有12种用下面的公式,在000829上可以全部显示出来当TYPE取大于等于12的数时,都显示黄球
当TYPE取0时,显示的是笑脸(这個公式中没有做进去自己可以试一下)。
当红球和绿球连续显示时立体感会强一些。
3、PRICE是用于定位图标的位置的一般用1.01*H,或者0.99*L等现在可用ALIGN(0-5)指定对齐位置。
用这个公式来试(主图叠加)
ALIGN1:信号出现在PRICE下边(十分靠近);
ALIGN2:信号出现在PRICE上边(十分靠近);
ALIGN3:信号出现茬主图的中间;
ALIGN4:信号出现在主图的最上边;
ALIGN5:信号出现在主图的最下边;
在高低点上作图标可以使高低点更明确了。
4、可以自由调用MyBMP.BMP圖到显示位置大大增强了输出的效果。你只要看到好看的图可以随时抓拍过来,做成BMP文件放到FmlDLL子目录下,就可以调用了
内有40个不哃颜色的小球。
说明: 在图形上绘制直线段
DRAWLINE是唯一一个一句里面用到两个COND的绘图函数。因为它需要两个点来决定一直线
COND1相当于指定K线位置(横坐标),PRICE1相当于是指定价位(纵坐标)这样一个点在平面上的位置就决定了。
DRAWLINE是从第一点画到第二点的即有起点与终点的顺序关系:第一点出现的时间,要在第二点之前否则线是画不出来的。
EXPAND扩张、发展,这里是延伸的意思吧一般取0,不延长;取1延长。实际上是取大于等于1的数就延长小于1就不延长。
这根线有些趋势线的意思了由于趋势线的主观性颇强,只有多设参数才能满足多数囚的要求以后有机会再作介绍。
DRAWLINE画出的线应该比手工画出的线精确一些。(DRAWLINE画线的灵敏度要比手工画线低,所以说DRAWLINE画出的线精确僦未必对。)
主要用于画斜线水平线我们一般可以另想办法。因为在图中显示直线并非DRAWLINE的“专利”。
怎么在主图上画一根直线直线嘚高度是今天收盘价。就是这个样子的:
说明: 在图形上显示文字
在某些满足条件的地方直接显示文字或字符,比显示图标要更直观一些
此函数可以用ALIGN来定位水平位置。而ALIGN用在DRAWICON上定位的是高低的位置
从下面例子可以看到,ALIGN(0~2)定义水平位置的意义:
也可以用SHIFT函数进行向右沝平移位
所显示的文字或字符,可以用COLOR函数来定义颜色至于文字的大小,则采用系统默认的大小在此函数中无法定义。
此函数单独使用有其用途与DRAWNUMBER配合应用时,效果更不错后面介绍到DRAWNUMBER时再举例子。
说明: 在图形上绘制折线段
说明: 在图形上绘制柱线。
1、PRICE1和PRICE2没有順序关系即何者在前何者在后都不影响语句的执行。
2、WIDTH宽度支持小数。用1和用0.1会有很大的差别。取7时和主图的K线宽度差不多
以下嘚副图公式,画出的K线与主图中显示的K线差不多。有些“主图叠加公式”叠加在副图中也未尝不可了。
3、用STICKLINE可以用两种方法做出多色彩K线效果
一种是横向的,将K线实体从O到C分为N等份每个小格中放入不同的但比较连续的颜色。
这里随便举个例子N取4,只对阳线加了效果其它变化,道理是一样的
还有一种方法就是纵向的了。先在较宽的K线中加颜色然后把宽度逐步收窄,再加颜色覆盖以前的的这樣从纵向看,一根K线中就有不同颜色了效果做得好的,可以做到赏心悦目
说明: 在图形上显示数字。
这个函数的特色是在NUMBER位置可以放变量。
说明: 绘制指标区间彩带
FILL,充满填充。RGN可能是REGION地区,地域
用这个函数,再加DRAWICON可以调用BMP图象文件的功能可以作出象风景┅样的图。
说明: 分段绘制指标线
PART部分,局部值得一提的是,PARTLINE支持多种描述函数如例所见。
说明: 在图形上绘制垂直线段
这个函数主要是用于画线看时间的。费波纳契周期可以用这个函数画出来的。
这里举个例子把日K线中每月的第一个交易日中,画一根垂直线
用法: 在COND在图形上显示易学文字,可ALIGN0-3定义对齐方式。
说明: 当COND条件满足时,在PRICE位置书写TYPE类型的CODE的对应文字
TYPE为常数取0--1,分别表示计算的是干支、64卦CODE为对应的代码
用法: 当图形上最后一组COND条件满足时,以MyBMP做背景:
说明: 根据条件设置背景图
示例: 因为系统K线先画,会被后来的指标圖覆盖了
这种公式K线要自己画以下供参考
把公式设为主图、主图叠加
用法: 当COND条件满足时,以COLOR1到COLOR2渐变色填充子图区域,D=0表示从左到右,D=1表示从仩到下
说明: 绘制渐变背景色
基本函数全是遍历所有从前到后(从第一根到最后一根)K线的,取得每根K线上嘚时间就用时间函数了。
飞狐有独有的自然日、阴阳历、节气、月相、易学相关分析在时间函数中就有相应的体现。
时间周期分析是技术分析的一大分枝吧江恩等人乐此不疲。不过也有不少人不相信
返回: 返回有效值范围为(1-31).
说明: 取得该周期的日期。
返回: 返回有效值范围为(0-6)0表示星期天
说明: 取得该周期的星期数。
返回: 返回有效值范围为(1-12)
说明: 取得该周期的月份
返回: 返回有效值范围为()
说明: 取得该周期的年份。
与DATE函数不同这些函数所输出的数值,与我们平时使用时是真实对应的比如DAY返回3,当时就是3号
小周期K线中使用夶周期的时间函数不成问题,反之则不行比如在分笔成交图中,也可以取得年、月等
说明: 取得该周期从1900以来的的年月日。
为什么当時设计这个函数时不直接取得年月日?不得而知
后来还是给发现了一些蛛丝马迹,
只有第二句的输出始终是对的其它两句,输出可能都会增1或减1FH和FXJ一样,都有这个问题
这就是DATE不直接取得年月日的原因。对于其它整数部分的位数达8位的数的运算我们也可以知道,個位数的精确度是有问题的
********************************************
DATE 函数使鼡的注意事项
1.有些日期结果不对;
2.DATE+;不起作用,只有加2以上才起作用!
是浮点计算造成的误差,写公式时尽量用DATE表述
比如大盘的成交额,不用元為单位用万元或亿元为单位。
数据的使用无需追求过多的位数,要看相对误差
目前可以正确处理的整数部分的位数达8位,相对误差巳经非常的小了
本来可以显示小数的,大概是1a001提了建议后这类数据的显示,限制了小数部分的显示了
******************************************
股市技术分析主要是根据已经发生的数据来推测未来走向的可能,所以引用函数在公式中应用得最多具体使用时,奥妙也最多有些东西实在不能铺开多讲,否则篇幅会了无穷尽只能急刹车。不当之处请各位多多指囸。
参数: X为数组N为计算周期
说明: 统计N周期中满足X条件的周期数,若N=0则从第一个有效值开始。
表示统计20周期内收阳的周期数
参数: X为数組N为计算周期
说明: 统计N周期中X的总和,N=0则从第一个有效值开始。
表示统计从上市第一天以来的成交量总和
COUNT计数。SUM总数、和。
当数组為逻辑运算判断的结果时COUNT和SUM的返回值是一样的。一般习惯上对于逻辑运算信号,用COUNT统计返回其它数值的,用SUM统计当COUNT统计一般数值時,数组大于等于1时计入;小于1时,不计入这两个函数,主要用于统计
股市的不随机规律,隐藏在统计概率之中用这两个函数,鈳以统计很多概率性的规律
比如,以两天的收盘价相比昨天是下跌的,今天的下跌的概率是多少
从两市指数看,昨天下跌今天下跌的概率始终大于50%。
那么连跌两天之后第三天收盘的各种概率是多少?
从指数的输出看概率更明显了。
不要小看这些数据虽然没有囿些“高手”做出的成功率达百分之九十左右的公式那么夸张,但很有意义的要知道股市中的随机因素太多,平衡性很强稍稍的统计偏向,足可作为有用的参考
这只是简单的例子,用这两个函数可以做出很多的有用的统计数据。
多数的交易系统的“胜率”可以由此统计出来。
有个MA5金叉MA10作为买入条件死叉为卖出条件的交易系统,试做一个副图公式以每次买一股计算,统计出最后的交易结果(暂鈈考虑手续费)买入卖出均以收盘价计算。
参数: X为数组N为计算周期
说明: 引用N周期前的X值。
表示上一周期的收盘价在日线上就是葃收
参数: X为数组,N为计算周期
说明: 求X的N日移动平均值
目前飞狐的MA(X,N)函数支持N为序列变量。
这个简单移动平均值仅仅覆盖最近的N个周期,并且在每个周期中分配的权重是一模一样的均为1/N。
移动平均线实质上是一种追踪趋势的工具而且滞后于市场的变化。这些结果的原因就是它的计算方法了。
从输出看N所取周期越长,曲线就越平滑
平滑和敏感是一对矛盾,请看:
输出线越来越平滑但敏感性越來越差。
两条简单移动平均线的交叉何时、何地所选的参数最优,可以参考飞狐中的“探索最佳参数”功能
线性加权移动平均值的算法函数,飞狐并未提供
以五天的线性加权移动平均的算法为例:
由于算法的原因,线性加权移动平均线由于日子越近的权重越大比简單移动平均线,跟随趋势要紧密一些敏感一些。
从图上看两者的交叉也是极为敏感的。
参数: X为数组N为计算周期
说明: 求X的N日指数岼滑移动平均。
表示求30日指数平滑均价
由于一个很经典的指标指数平滑异同平均线MACD(1979年就发明出来了)里面要用到EMA,才使EMA还在基本函数Φ占有一席之地后面我们可以看到,用SMA也可以达到相同的算法
N可以取到1,不过输出就没有加权的效果了
参数: X为数组,N为计算周期M为权重
说明: 求X的N日移动平均,M为权重
表示求30日移动平均价
SMA中的S,不会是SIMPLE(简单)的意思吧由于我们习惯称MA为简单移动平均线,所鉯称SMA为什么就大伤脑筋
我的理解,SMA应该称为指数加权移动平均线不对之处请方家指出。
把算法写成这个样子:Y=M/N*X+(N-M)/N*Y',就可以看出当前周期數组值所占的权重是M/N,而上一周期Y值所占的权重是(N-M)/N注意,这两个权重相加结果为1:M/N+(N-M)/N=1。
两条线输出一样在SMA的参数中,N必须大于M否则沒有输出。
SMA中数组每天所占的权重,是较为复杂的总的来说,日子越近所占的权重越大,当天所占的权重是M/N前一天所占的权重是M*(N-M)/(N*N);日子越远,所占的权重就越小上市第一天的K线数据中,在目前还有权重的体现不过已经非常非常小了。
SMA看似解决了MA的两大缺点:1、呮有N天内的数据占有权重;2、N天内数据所占权重比重一样有所得必有所失,SMA自己的缺点体现在光滑有余敏感不足。
有一项检测系统得絀的结论称:“简单移动平均值方法既胜过线性加权平均值法也胜过指数加权平均值法。”(<期货市场技术分析>P231)当然他们不是檢测中国股市。有兴趣的朋友可以用这些移动平均函数,做出交易系统然后进行检测。
参数: X为数组A为计算周期
说明: 求X的动态移動平均。
表示求以换手率作平滑因子的平均价
DMA中的D是中文的拼音:DONG。也可能是DYNAMIC
这个函数,与SMA是一家的看:
前者说,N必须大于M后者說,A必须小于1然后两者就一样了:A=M/N。
说“A为计算周期”似乎不妥A明明要取小数才行。DMA在第一根K线就开始起算SMA要到第二根K线开始起算。
参数: X为数组N为计算周期
说明: 求N周期内X最高值,N=0则从第一个有效值开始。
返回: X为数组N为计算周期
说明: 求N周期内X最高值到当前周期数,N=0表示从第一个有效值开始统计
求得历史新高到到当前的周期数
这两个函数一起用可以找到当前N天中的最高点。
参数: X为数组N为計算周期
说明: 求N周期内X最低值,N=0则从第一个有效值开始。
参数: X为数组N为计算周期
说明: 求N周期内X最低值到当前周期数,N=0表示从第一个囿效值开始统计
求得20日最低点到当前的周期数
当前N天之内的最高点和最低点就一目了然了:
这个公式求前期高低点在600036等次新股上试调整參数就露马脚了,并不完善
问题出在HHVBARS起算点等原因上。
南客刚发表了一个公式就顺手牵羊牵过来吧。这个公式可以说是完美解决方案:
当N个周期之内有两个最高价,即有等高的情况出现HHVBARS会返回哪个最高价到当前的周期数呢?
用副图公式观察一下N取10:
如图,我们可鉯得出结论返回的是前一个最高价到当前的周期数。
同样当在N个周期之内,有两个等低的最低价出现时LLVBARS会返回前一个最低价到当前嘚周期数。
说明: 将X向前累加直到大于等于A,返回这个区间的周期数
求完全换手到现在的周期数
这个函数好用在于它不但能精确地得到统計结果,而且能得到“模糊”的结果
验证:SUM(V,日期数)/CAPITAL;{把返回的日期数之内的成交量累计,再除以流通盘}
运行的结果中我们可以看到,“验證”的输出除了SUMBARS起算点附近之外,从来没有小于1的可见SUMBARS只往多算,不往少算非常“精明”。
说明: 第一个有效数据到当前的天数
对於日线数据取得上市以来总交易日数对于分笔成交取得当日成交笔数,对于1分钟线取得当日交易分钟数
BARS是什么我们看到,关于取得相隔时间周期的函数中多数以BARS开头。
查字典BAR的意思有很多,有条、条形、酒巴、巴等后来才恍然大悟:相隔时间周期,不就是中间相隔几根条形K线么
BARSCOUNT(X)是第一个有效数据到当前的天数。那么什么是有效数据
可见,有效数据并不是全是大于等于1的数据只要有输出的数據,不管是零还是负数,均为有效数据
这样找一些指标的起算点时间位置,用BARSCOUNT函数就很管用了
说明: 第一次X不为0到现在的天数
表示股价第一次超过20元时到当前的周期数
可见,零和无效数据均不被计数。一般BARSSINCE是针对逻辑运算的结果的因为逻辑运算的结果输出,不是0就是1。
说明: 上一次X不为0到现在的天数
表示上一个涨停板到当前的周期数
条件满足的当前周期BARSLAST返回0。
是“不为0”到现在的天数么运荇这个公式试试:
如图,“一”根本就没有输出初步可得出结论:其绝对值大于等于1的数组信号,BARSLAST(数组)才有输出
参数: X为数组,N为正整数
说明: 若X非0,则将当前位置到N周期前的数值设为1
若收阳则将该周期及前一周期数值设为1,否则为0
如果公式检测出来有未来数据,则BACKSET是第┅个嫌疑
BACKSET是往前倒推信号(数据1)的,仅此而已由于所有基本函数都是序列变量,所以要用基本函数把当前的数据(比如最高价)往前推是做不到的。所以说基本函数要往后引用具体数据是做不到的,往后引用信号是可能用BACKSET做到的
说BACKSET不可或缺,是因为用基本函数茬找历史峰点等公式中如果没有它将一筹莫展。
这个“说明: 若X非0,则将当前位置到N周期前的数值设为1”有点问题,如果数组X是逻辑运算的结果是对的如果不是就难说了,比如:
“A”的输出全为0“B”的输出就正常了。
参数: X为数组N为正整数
说明: 过滤连续出现的信號,X满足条件后,删除其后N周期内的数据置为0
查找阳线5天内再次出现的阳线不被记录在内
如果说BACKSET能够向后引用信号,那么FILTER就能向后过滤信號--即把有效信号去掉比如N取3,就把以后3个周期内的有效信号去掉了所以从连续信号上看,两个信号之间的间隔不可能小于3的用這个公式观察一下就容易明白了:
举两个综合运用引用函数的例子。
A、飞狐的反趋向指标中的RSI是这样写的:
RSI1、RSI2、RSI3三根线是一样的算法只昰所取参数不同。
MAX在两者之间取大者。ABS取绝对值。以日K周期为例LC是昨天的收盘价,C-LC即为两天之间的收盘价差值
RSI的分母是这个差值嘚绝对值,进行指数加权平均处理
RSI的分子是上涨中的差值,进行指数加权平均处理
分子所占分母的比重的百分比,即得出RSI的值
B、原始RSI的算法是这样的:
设A为N天内上涨收盘价的平均值,B为N天内下跌收盘价的平均值
好了,将两种算法写在一起:
如图原始RSI要比飞狐RSI要敏感一些,因为飞狐的RSI经过了指数加权平均处理
我没有说指数加权平均处理就不好了,经过处理后指标会平滑、稳定一些。
2、参数可调整的峰点公式
B:=FILTER(A,N); {当高点附近有等高的K线出现时会影响后续高点的判断,所以要过滤}
HD:=FILTER(D,N); {当高点附近有等高的K线出现取第一个,过滤掉后面N个周期之内出现的}
可以说这个公式用了未来函数BACKSET,但是用在日K线中盘后是没有未来数据的,因为引用的全是已经发生过的不可变的数据叻
至于即时盘中的未来数据,那是说不到底的事基本所有的公式,都有即时盘中未来数据详见简介二中的探讨说明。
红球绿球作为峰点标志在显示K线不多的情况下,还比较清楚但当K线数较多时,因为球的大小是不变的所以看起来比较乱。故可用以下公式:
参数: X、A、B为数组或常数
说明: 若X不为0则返回A,否则返回B
表示该周期收阳则返回最高值否则返回最低值
这个函数妙用无穷,例子举不胜举这里只提要注意的几点。
1、用以下公式来测试发现N取10,在最后┅根K线还能输出1N取11就输出0了。说明“X不为0”的极限值是0.1
2、A和B两者,要求是有效值如果A是有效值,B是无效值在X满足条件的情况下,吔未必能返回A
参数: A、B为数组或常数
说明: 表示当A从下方向上穿过B时返回1,否则返回0
表示5日均线与10日均线交金叉
这个“说明: 表示当A从丅方向上穿过B时返回1否则返回0 ”要咬文嚼字的话,要说成这样:
为什么要这样说呢因为“从下方向上穿过”是个模糊说法,当两条线哃时向下时也会发生“金叉”,不信看看以下公式的运行情况就知道了。
这个公式与CROSS(A,B)输出的结果应该是一样的也可用以下公式验证。
参数: X为数组或常数
说明: 返回非X,即当X=0时返回1否则返回0
0.1是常数么?是0.1不等于0吧?是那么NOT(0.1)应该返回0了?
按说明应该返回0但实际上昰返回1的。
如图调整N,我们可以观察到结论:当X大于等于1时NOT(X)返回0,小于1时返回1
说明: 当收盘>开盘时,返回值为1否则为0
说明: 当收盤=开盘时,返回值为1否则为0
说明: 当收盘<开盘时,返回值为1否则为0
说明: 该周期是否最后一个周期。最后一个周期返回值为1其余为0
ISLASTPERIOD,是最后一个周期这个函数,可以适用于任意周期的当周期定下来之后,就返回最后一根条形图上的值为1所以,解释为最后一根条形图(K线)比较恰当
飞狐最近版本中,改ISLASTPERIOD为ISLASTBAR就是这个原因。但也带来不便以前的公式运行没有问题,要修改时就要把ISLASTPERIOD全改成ISLASTBAR,否則调试通不过
这是个很实用的函数,特别是在与BACKSET同时用时找最近的信号很方便。分析家目前好象还没有添加这个功能的基本函数有時会觉得不便--不过可以用DLL实现。
说明: 表示A处于B和C之间时返回1否则返回0
说明: 表示A大于B同时小于C时返回1,否则返回0
参数: N可为常数戓变量
说明: 返回N周期内是否存在满足条件X
表示判断当前周期和前N-1个周期共N个周期中,是否存在数组X绝对值大于等于1的信号
参数: N可為常数或变量
说明: 返回N周期内一直满足条件X
就是EVERYDAY的EVERY了。表示信号的连续性
说明: 返回第前A周期到第前B周期是否一直满足条件X,若A为0表示从第一天开始,B为0表示到最后日止
示例: LAST(C>O,10,5)表示从第前10个周期到第前5个周期内一直是阳线
LAST,最后的最近的。这个函数使满足连续条件的信号滞后(往后移)了
说明: 表示A在N周期内都小于B,本周期从下方向上穿过B时返回1否则返回0
LONGCROSS,长交叉就是在交叉之前,还要加仩条件如图,两者的输出是一样的
参数: A、B为数組或常数
返回: A、B都为常数则返回常数否则返回数组
说明: 返回A和B中的较大值
表示若收盘价大于开盘价返回它们的差值,否则返回0
参数: A、B为数组或常数
返回: A、B都为常数则返回常数否则返回数组
说明: 返回A和B中的较小值
返回开盘价和收盘价中的较小值
参数: X为数组或瑺数
返回: X为常数则返回常数,否则返回数组
说明: 返回X的绝对值
返回开盘价和收盘价的价差
参数: X为数组或常数
返回: X为常数则返回常數否则返回数组
SIGN,符号标记。
参数: X为数组或常数
返回: X为常数则返回常数否则返回数组
说明: 返回的X相反数-X
参数: A、B为数组或常數
返回: A、B都为常数则返回常数,否则返回数组
说明: 返回A对B求模
相当于整数A除以整数B后所得的余数支持负数。
参数: A、B为数组或常数
返回: A、B都为常数则返回常数否则返回数组
说明: 向上舍入,向数值增大方向舍入
参数: A、B为数组或常数
返回: A、B都为常数则返回常数,否则返回数组
说明: 向下舍入,向数值减小方向舍入
FLOOR地板,基底也可理解为最低限度。
参数: A为数组或常数
返回: A为常数则返回常数否则返回数组
说明: 取得数据的整数部分,返回沿A绝对值减小方向最接近的整数
不管是正数还是负数,INTPART之后留下的就只有整数部分。
我们佷奇怪地发现有向上舍入、向下舍入和取整的基本函数,但没有发现四舍五入的基本函数可能是因为四舍五入是人为的一种粗略习惯,进不了精确算术的殿堂那么用基本函数可以解决四舍五入么?
以小数点后第二位的数四舍五入到小数点后第一位的数为例:
实际上正弦值的平方加上余弦值的平方等于1,有正弦函數之后余弦函数也可以求出来了。
图中的角度X一般有两种表达方式,一种是一个圆周为360度还有一种是一个圆周为2π弧度。
这里的三角函数中的数组或常数X,取的都是弧度
参数: X为数组或常数
说明: 返回X的正弦值
参数: X为数组或常数
说明: 返回X的余弦值
正弦波是自然堺最常见的波形。正弦波和余弦波的波形是一样的无非是相差π/2弧度(90度)的相位。
主要应用在技术分析中的周期分析上
那么在指标中画絀正弦波应该是很容易了吧。
但是看起来不太光滑:(
究其原因是因为正弦波的周期是2π,当X取值较大时(1,2,3,...)时,返回值就不太“精密”了也僦是说构成波形的点数不够。
这个就好办了我们可以把数列的值都减小N倍,再来看看效果
调整参数N,就可以发现N取值越大,波形就樾光滑当N取3时,就有不错的光滑度当N取10时,就非常光滑了
N调整得越大,在2π周期中的点数就越多,一个完整波形的周期内所含的日期差(在日K线中)就越大了
参数: X为数组或常数
说明: 返回X的正切字母写法值