量化交易软件:交易员的正则表达式

概论正则表达式 是一种基于指定范式来处理文本的特殊工具和语言。多重 元字符和规则由正则表达式的语法定义。 它们能够执行两个主要功能:

编辑切换为居中
在字符串里搜索范式;
替换发现的范式。
当创建由于正则表达式的范式时, 如前所述, 会使用特殊字符, 元字符和字符类 (集合)。这意味着正则表达式是一个规则字符串, 且所有非特殊 (非保留) 字符 均被认为是规则的。 在一个字符串里搜索指定的范式是通过正则表达式处理器来执行的。在 .NET 框架里, 当然, 同样在 RegularExpressions 库 MQL5 版本 里, 正则表达式处理器将会回溯正则表达式。它是传统 NFA (非确定有限自动机) 的变种, 如同类似的应用 Perl, Python, Emacs 和 Tcl。它用来替换在字符串中发现的匹配范式。 1. 正则表达式基础 元字符是特殊 字符, 就像 MQL5 和 C# 的管理序列一般, 指定操作的命令及管理序列。这些 字符会有前置的反斜线 (\), 而且它们的每一个都有特殊目的。 下表中的 MQL5 和 C# 正则表达式元字符, 根据其含义分组。1.1. 字符类:
字符
描述
举例
匹配
[...]
在中括号里指示的所有字符
[a-z]
源字符串里可能存在的所有小写英文字母
[^...]
未在中括号里指示的所有字符
[^0-9]
源字符串里可能存在的除了数字的所有字符
.
除了换行或者其它 Unicode 分隔符之外的所有字符
ta.d
在 "trade" 字符串里的 "trad"
\w
所有非空格符, 制表符等等的单词
\w
在 "MQL 5" 字符串里的 "M","Q","L","5"
\W
所有不是单词的字符
\W
在 "MQL 5" 字符串里的 " ", "."。
\s
来自 Unicode 集合的所有空白符
\w\s
在 "MQL 5" 字符串里的 "L "
\S
来自 Unicode 集合的所有非空白符请注意这个 \w 和 \S 字符不一样
\S
在 "MQL 5" 字符窜里的"M", "Q", "L", "5", "."
\d
所有的 ASCII 数字。等效于 [0-9]
\d
在 "MQL 5." 里的 "5"
1.2. 重复字符:
字符
描述
举例
匹配
{n,m}
对应先前的范式, 重复不少于 n 或不多于 m 次
s{2,4}
"Press", "ssl", "progressss"
{n,}
对应先前的范式, 重复 n 或多于 m 次
s{1,}
"ssl"
{n}
与先前的范式精确匹配 n 个实例
s{2}
"Press", "ssl", 但不包括 "progressss"
?
与先前的范式对应零个或一个实例;先前的范式并非强制性的
等效于 {0,1}
+
与先前的范式对应一个或多个实例
等效于 {1,}
*
与先前的范式对应零个或多个实例
等效于 {0,}
1.3. 选择正则表达式的字符:
字符
描述
举例
匹配
|
对应于左侧子表达式, 或右侧子表达式 (模拟逻辑操作 OR)。
1(1|2)0
在 "100, 110, 120, 130" 字符串里的"110", "120"
(...)
分组。在单一的整体里的分组元素, 可以使用字符 *, +, ?, |, 等等。还应记住, 对应于该组的字符在子序列链表中还要用到。
(?:...)
仅有分组。在单一整体里的分组元素, 但不会记忆对应于该组的字符。
1.4. 正则表达式的定位字符:
字符
描述
举例
匹配
^
对应一个字符串表达式的开始, 或在多字符串搜索当中的字符串开始。
^Hello
"Hello, world", 但不是 "Ok, Hello world" 因为单词"Hello" 在此字符串里没有位于开始
$
对应一个字符串表达式的结尾, 或在多字符串搜索当中的字符串结尾。
Hello$
"World, Hello"
\b
对应于单词边界, 即对应于 \w 和 \W 字符的之间位置或在 \w 字符和字符串开始或结束之间。
\b(my)\b
在字符串 "Hello my world" 当中, 单词 "my" 被选中
有关正则表达式元素更多的信息, 请参阅 微软 官方网站上的文章。 2. MQL5 实现的正则表达式的功能 2.1. 第三方文件存储在内部文件夹 为了让 用于 MQL5 的正则表达式 更佳接近 .Net 的源代码, 它也需要传递第三方文件的一小部分。它们全被存储在 Internal 文件夹, 这也许是很有趣的。 让我们靠近些来看看 Internal 文件夹的内容。
Generic — 此文件夹所包含的文件实现严格的类型化集合, 枚举和它们的接口。更多详尽描述提供如下。
TimeSpan — 文件用来实现 TimeSpan 结构, 它提供一个时间间隔。
Array.mqh — 在此文件里实现了具有若干静态方法的 Array 类, 用来操作数组。例如: 排序, 二叉树检索, 接收枚举, 接收元素索引, 等等。
DynamicMatrix.mqh — 此文件有两个实现多维动态数组的主类。这些是范式类, 因此, 适合标准类型和指针类。
IComparable.mqh — 文件实现 IComparable 接口, 这是支持类型化集合的一些方法所必要的。
Wrappers.mqh — 查找哈希码的标准类型和方法的封套。
Generic 已实现了三个严格类型化的集合:
List<T> 体现为严格类型化的可索引对象列表。支持通过列表搜索, 排序以及于其它列表的操作。
Dictionary<TKey,TValue> 体现为关键字和数值的集合。
LinkedList<T> 体现为双链列表。
赫兹量化来看看 TradeHistoryParsing 智能交易程序中 List<T> 的用例。此 EA 从 .html 文件里读取所有交易历史, 并依据所选列和记录进行过滤。交易历史有两个表格构成: 成交和订单。类 OrderRecord 和 DealRecord 分别解读来自 Orders 和 Trades 表格的每一笔记录 (元组)。所以, 每一列可以表现为其记录的列表: List<OrderRecord*>*m_list1 = new List<OrderRecord*>(); List<DealRecord*>*m_list2 = new List<DealRecord*>(); 由于 List<T> 类支持排序方法, 这意味着 T 类型对象必须要在它们之间逐一比较。换言之, 为这个类型实现了<,>,== 操作符。对于标准元素这没问题, 但如果我们需要创建 List<T>, 此处 T 指明自定义类, 则我们会得到错误。有两种方式来处理这个问题。首先, 赫兹量化可以在我们的类中明确地重载比较运算符。另一种解决方案是编写 IComparable 接口的子类。第二种选择在实现时相当快捷, 然而, 它破坏了正确的排序。当有必要对自定义类进行排序的情况下, 赫兹量化必须重载所有比较运算符。此外, 建议实现继承。 这只是 List<T> 类的功能之一。更多信息提供如下。Dictionary<TKey,TValue> — 具有唯一关键字及其相关数值集合的一种字典。若干数值可以同时赋予一个关键字。关键字类型和数值可在用户创建对象阶段确定。如同从描述里可见, 类 Dictionary<TKey,TValue> 十分适合哈希表的角色。为了提升 Dictionary<TKey,TValue> 的操作速度, 您应当创建一个新的类, 作为 IEqualityComparer<T> 的子类, 并重载两个函数:
bool Equals(T x,T y) — 函数返回 true, 如果 x 等于 y, 以及 false — 如果反之。
int GetHashCode(T obj) — 函数返回一个对象 obj 的哈希码。
在 MQL5 的 RegularExpressions 库里, 这个功能用于所有以字符串作为关键字的字典。 实现 StringEqualityComparer: class StringEqualityComparer : public IEqualityComparer<string> { public: //--- 方法: //+------------------------------------------------------------------+ //| 判断指定对象是否相等。 | //+------------------------------------------------------------------+ virtual bool Equals(string x,string y) { if(StringLen(x)!=StringLen(y)){ return (false); } else { for(int i=0; i<StringLen(x); i++) if(StringGetCharacter(x,i)!=StringGetCharacter(y,i)){ return (false); } } return (true); } int GetHashCode(string obj) { return (::GetHashCode(obj)); } }; 现在, 当创建属于 Dictionary<TKey,TValue> 类, 以字符串为关键字的新对象时, 我们将发送指针到 StringEqualityComparer 对象作为其构造器的参数: Dictionary<string,int> *dictionary= new Dictionary<string,int>(new StringEqualityComparer);LinkedList<T> 是 一个数据结构 包括一定数量的元素。每个元素包括一个信息部分, 和两个指向前一个和随后一个对象的指针。所以, 相邻两个元素互指彼此。列表的节点通过 LinkedListNode<T> 对象实现。在每个节点里都有标准设定, 其中包括数值, 指向列表和相邻节点的指针。

编辑
此外, 上述所有提及的三个集合均实现了枚举器。Enumerator 是一个广义的 IEnumerator<T> 接口。IEnumerator<T> 可以实现集合的全旁通, 无论其结构。 为了获取枚举器, 赫兹量化必须从对象里调用 GetEnumerator() 方法, 其类中实现了 IEnumerable 接口: List<int>* list = new List<int>(); list.Add(0); list.Add(1); list.Add(2); IEnumerator<int> *en = list.GetEnumerator(); while(en.MoveNext()) { Print(en.Current()); } delete en; delete list; 在此例中, 我们迭代整个列表并输出每个数值。所有这些可以通过分配一个简单的 for 循环来实现, 但经常地, 使用枚举的方法更方便。事实上, 当创建 Dictionary<TKey,TValue> 的迭代之时, 这个解决方案十分适合。 2.2. MQL5 的 RegularExpressions 库功能1. 为了在我们的项目里包括所有正则表达式的功能, 以下部分必须要加入: #include <RegularExpressions\Regex.mqh>2. 由于在 MQL5 里缺乏名称空间, 因此, internal 访问修饰符, 赫兹量化可以访问到库中所有的内部类和方法。事实上, 当使用正则表达式操作时, 这些没必要考虑。 对于正则表达式操作, 以下的类将是我们感兴趣的:
Capture — 提供子表达式中一个成功记录的结果。
CaptureCollection — 提供由一个分组作出的记录集合。
Group — 提供单独记录分组的结果。
GroupCollection — 返回单一搜索匹配的记录分组集合。
Match — 提供来自单独正则表达式匹配的结果。
MatchCollection — 呈现在输入字符串当中通过正则表达式迭代发现的与范式成功匹配的集合。
Regex — 代表不变的正则表达式。
除了以上提到的类, 赫兹量化还将使用:
MatchEvaluator — 每次正则表达式发现匹配时要调用的表述方法指针。
RegexOptions — 当正则表达式指定参数时使用的枚举表述值。
RegexOptions — 来自 .Net 源枚举的不完整拷贝, 包括以下元素:
参数
描述
None
参数未指定。
IgnoreCase
匹配搜索不区分大小写。
Multiline
指定多行模式。
ExplicitCapture
未覆盖没有名称的分组。仅有效选择 — 明确命名或具有格式的有数分组 (?<名称> 子表达式)。
Singleline
指定单行模式。
IgnorePatternWhitespace
不破坏顺序从范式里删除空白符, 并启用带有 "#" 字符标记的注释。
RightToLeft
指定搜索将从右向左执行, 而非从左向右。
Debug
指定程序使用调试器操作。
ECMAScript
启用表达式的 ECMAScript 兼容行为。此数值仅能配合 IgnoreCase 和 Multiline 使用。
这些选项可用于创建新的 Regex 类对象, 或当调用其静态方法时。