量化交易軟件:交易員的正則表達(dá)式

概論正則表達(dá)式 是一種基于指定范式來處理文本的特殊工具和語言。多重 元字符和規(guī)則由正則表達(dá)式的語法定義。 它們能夠執(zhí)行兩個(gè)主要功能:

編輯切換為居中
在字符串里搜索范式;
替換發(fā)現(xiàn)的范式。
當(dāng)創(chuàng)建由于正則表達(dá)式的范式時(shí), 如前所述, 會使用特殊字符, 元字符和字符類 (集合)。這意味著正則表達(dá)式是一個(gè)規(guī)則字符串, 且所有非特殊 (非保留) 字符 均被認(rèn)為是規(guī)則的。 在一個(gè)字符串里搜索指定的范式是通過正則表達(dá)式處理器來執(zhí)行的。在 .NET 框架里, 當(dāng)然, 同樣在 RegularExpressions 庫 MQL5 版本 里, 正則表達(dá)式處理器將會回溯正則表達(dá)式。它是傳統(tǒng) NFA (非確定有限自動機(jī)) 的變種, 如同類似的應(yīng)用 Perl, Python, Emacs 和 Tcl。它用來替換在字符串中發(fā)現(xiàn)的匹配范式。 1. 正則表達(dá)式基礎(chǔ) 元字符是特殊 字符, 就像 MQL5 和 C# 的管理序列一般, 指定操作的命令及管理序列。這些 字符會有前置的反斜線 (\), 而且它們的每一個(gè)都有特殊目的。 下表中的 MQL5 和 C# 正則表達(dá)式元字符, 根據(jù)其含義分組。1.1. 字符類:
字符
描述
舉例
匹配
[...]
在中括號里指示的所有字符
[a-z]
源字符串里可能存在的所有小寫英文字母
[^...]
未在中括號里指示的所有字符
[^0-9]
源字符串里可能存在的除了數(shù)字的所有字符
.
除了換行或者其它 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 集合的所有非空白符請注意這個(gè) \w 和 \S 字符不一樣
\S
在 "MQL 5" 字符竄里的"M", "Q", "L", "5", "."
\d
所有的 ASCII 數(shù)字。等效于 [0-9]
\d
在 "MQL 5." 里的 "5"
1.2. 重復(fù)字符:
字符
描述
舉例
匹配
{n,m}
對應(yīng)先前的范式, 重復(fù)不少于 n 或不多于 m 次
s{2,4}
"Press", "ssl", "progressss"
{n,}
對應(yīng)先前的范式, 重復(fù) n 或多于 m 次
s{1,}
"ssl"
{n}
與先前的范式精確匹配 n 個(gè)實(shí)例
s{2}
"Press", "ssl", 但不包括 "progressss"
?
與先前的范式對應(yīng)零個(gè)或一個(gè)實(shí)例;先前的范式并非強(qiáng)制性的
等效于 {0,1}
+
與先前的范式對應(yīng)一個(gè)或多個(gè)實(shí)例
等效于 {1,}
*
與先前的范式對應(yīng)零個(gè)或多個(gè)實(shí)例
等效于 {0,}
1.3. 選擇正則表達(dá)式的字符:
字符
描述
舉例
匹配
|
對應(yīng)于左側(cè)子表達(dá)式, 或右側(cè)子表達(dá)式 (模擬邏輯操作 OR)。
1(1|2)0
在 "100, 110, 120, 130" 字符串里的"110", "120"
(...)
分組。在單一的整體里的分組元素, 可以使用字符 *, +, ?, |, 等等。還應(yīng)記住, 對應(yīng)于該組的字符在子序列鏈表中還要用到。
(?:...)
僅有分組。在單一整體里的分組元素, 但不會記憶對應(yīng)于該組的字符。
1.4. 正則表達(dá)式的定位字符:
字符
描述
舉例
匹配
^
對應(yīng)一個(gè)字符串表達(dá)式的開始, 或在多字符串搜索當(dāng)中的字符串開始。
^Hello
"Hello, world", 但不是 "Ok, Hello world" 因?yàn)閱卧~"Hello" 在此字符串里沒有位于開始
$
對應(yīng)一個(gè)字符串表達(dá)式的結(jié)尾, 或在多字符串搜索當(dāng)中的字符串結(jié)尾。
Hello$
"World, Hello"
\b
對應(yīng)于單詞邊界, 即對應(yīng)于 \w 和 \W 字符的之間位置或在 \w 字符和字符串開始或結(jié)束之間。
\b(my)\b
在字符串 "Hello my world" 當(dāng)中, 單詞 "my" 被選中
有關(guān)正則表達(dá)式元素更多的信息, 請參閱 微軟 官方網(wǎng)站上的文章。 2. MQL5 實(shí)現(xiàn)的正則表達(dá)式的功能 2.1. 第三方文件存儲在內(nèi)部文件夾 為了讓 用于 MQL5 的正則表達(dá)式 更佳接近 .Net 的源代碼, 它也需要傳遞第三方文件的一小部分。它們?nèi)淮鎯υ?Internal 文件夾, 這也許是很有趣的。 讓我們靠近些來看看 Internal 文件夾的內(nèi)容。
Generic — 此文件夾所包含的文件實(shí)現(xiàn)嚴(yán)格的類型化集合, 枚舉和它們的接口。更多詳盡描述提供如下。
TimeSpan — 文件用來實(shí)現(xiàn) TimeSpan 結(jié)構(gòu), 它提供一個(gè)時(shí)間間隔。
Array.mqh — 在此文件里實(shí)現(xiàn)了具有若干靜態(tài)方法的 Array 類, 用來操作數(shù)組。例如: 排序, 二叉樹檢索, 接收枚舉, 接收元素索引, 等等。
DynamicMatrix.mqh — 此文件有兩個(gè)實(shí)現(xiàn)多維動態(tài)數(shù)組的主類。這些是范式類, 因此, 適合標(biāo)準(zhǔn)類型和指針類。
IComparable.mqh — 文件實(shí)現(xiàn) IComparable 接口, 這是支持類型化集合的一些方法所必要的。
Wrappers.mqh — 查找哈希碼的標(biāo)準(zhǔn)類型和方法的封套。
Generic 已實(shí)現(xiàn)了三個(gè)嚴(yán)格類型化的集合:
List<T> 體現(xiàn)為嚴(yán)格類型化的可索引對象列表。支持通過列表搜索, 排序以及于其它列表的操作。
Dictionary<TKey,TValue> 體現(xiàn)為關(guān)鍵字和數(shù)值的集合。
LinkedList<T> ?體現(xiàn)為雙鏈列表。
赫茲量化來看看 TradeHistoryParsing 智能交易程序中 List<T> 的用例。此 EA 從 .html 文件里讀取所有交易歷史, 并依據(jù)所選列和記錄進(jìn)行過濾。交易歷史有兩個(gè)表格構(gòu)成: 成交和訂單。類 OrderRecord 和 DealRecord 分別解讀來自 Orders 和 Trades 表格的每一筆記錄 (元組)。所以, 每一列可以表現(xiàn)為其記錄的列表: List<OrderRecord*>*m_list1 = new List<OrderRecord*>(); List<DealRecord*>*m_list2 = new List<DealRecord*>(); ? 由于 List<T> 類支持排序方法, 這意味著 T 類型對象必須要在它們之間逐一比較。換言之, 為這個(gè)類型實(shí)現(xiàn)了<,>,== 操作符。對于標(biāo)準(zhǔn)元素這沒問題, 但如果我們需要創(chuàng)建 List<T>, 此處 T 指明自定義類, 則我們會得到錯誤。有兩種方式來處理這個(gè)問題。首先, 赫茲量化可以在我們的類中明確地重載比較運(yùn)算符。另一種解決方案是編寫 IComparable 接口的子類。第二種選擇在實(shí)現(xiàn)時(shí)相當(dāng)快捷, 然而, 它破壞了正確的排序。當(dāng)有必要對自定義類進(jìn)行排序的情況下, 赫茲量化必須重載所有比較運(yùn)算符。此外, 建議實(shí)現(xiàn)繼承。 這只是 List<T> 類的功能之一。更多信息提供如下。Dictionary<TKey,TValue> — 具有唯一關(guān)鍵字及其相關(guān)數(shù)值集合的一種字典。若干數(shù)值可以同時(shí)賦予一個(gè)關(guān)鍵字。關(guān)鍵字類型和數(shù)值可在用戶創(chuàng)建對象階段確定。如同從描述里可見, 類 Dictionary<TKey,TValue> 十分適合哈希表的角色。為了提升 Dictionary<TKey,TValue> 的操作速度, 您應(yīng)當(dāng)創(chuàng)建一個(gè)新的類, 作為 IEqualityComparer<T> 的子類, 并重載兩個(gè)函數(shù):
bool Equals(T x,T y) — 函數(shù)返回 true, 如果 x 等于 y, 以及 false — 如果反之。
int GetHashCode(T obj) — 函數(shù)返回一個(gè)對象 obj 的哈希碼。
在 MQL5 的 RegularExpressions 庫里, 這個(gè)功能用于所有以字符串作為關(guān)鍵字的字典。 實(shí)現(xiàn) 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)); ? ? ?} ? }; ? 現(xiàn)在, 當(dāng)創(chuàng)建屬于 Dictionary<TKey,TValue> 類, 以字符串為關(guān)鍵字的新對象時(shí), 我們將發(fā)送指針到 StringEqualityComparer 對象作為其構(gòu)造器的參數(shù): Dictionary<string,int> *dictionary= new Dictionary<string,int>(new StringEqualityComparer);LinkedList<T> 是 一個(gè)數(shù)據(jù)結(jié)構(gòu) 包括一定數(shù)量的元素。每個(gè)元素包括一個(gè)信息部分, 和兩個(gè)指向前一個(gè)和隨后一個(gè)對象的指針。所以, 相鄰兩個(gè)元素互指彼此。列表的節(jié)點(diǎn)通過 LinkedListNode<T> 對象實(shí)現(xiàn)。在每個(gè)節(jié)點(diǎn)里都有標(biāo)準(zhǔn)設(shè)定, 其中包括數(shù)值, 指向列表和相鄰節(jié)點(diǎn)的指針。

編輯
此外, 上述所有提及的三個(gè)集合均實(shí)現(xiàn)了枚舉器。Enumerator 是一個(gè)廣義的 IEnumerator<T> 接口。IEnumerator<T> 可以實(shí)現(xiàn)集合的全旁通, 無論其結(jié)構(gòu)。 為了獲取枚舉器, 赫茲量化必須從對象里調(diào)用 GetEnumerator() 方法, 其類中實(shí)現(xiàn)了 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; ? 在此例中, 我們迭代整個(gè)列表并輸出每個(gè)數(shù)值。所有這些可以通過分配一個(gè)簡單的 for 循環(huán)來實(shí)現(xiàn), 但經(jīng)常地, 使用枚舉的方法更方便。事實(shí)上, 當(dāng)創(chuàng)建 Dictionary<TKey,TValue> 的迭代之時(shí), 這個(gè)解決方案十分適合。 2.2. MQL5 的 RegularExpressions 庫功能1. 為了在我們的項(xiàng)目里包括所有正則表達(dá)式的功能, 以下部分必須要加入: #include <RegularExpressions\Regex.mqh>2. 由于在 MQL5 里缺乏名稱空間, 因此, internal 訪問修飾符, 赫茲量化可以訪問到庫中所有的內(nèi)部類和方法。事實(shí)上, 當(dāng)使用正則表達(dá)式操作時(shí), 這些沒必要考慮。 對于正則表達(dá)式操作, 以下的類將是我們感興趣的:
Capture — 提供子表達(dá)式中一個(gè)成功記錄的結(jié)果。
CaptureCollection — 提供由一個(gè)分組作出的記錄集合。
Group — 提供單獨(dú)記錄分組的結(jié)果。
GroupCollection — 返回單一搜索匹配的記錄分組集合。
Match — 提供來自單獨(dú)正則表達(dá)式匹配的結(jié)果。
MatchCollection — 呈現(xiàn)在輸入字符串當(dāng)中通過正則表達(dá)式迭代發(fā)現(xiàn)的與范式成功匹配的集合。
Regex — 代表不變的正則表達(dá)式。
除了以上提到的類, 赫茲量化還將使用:
MatchEvaluator — 每次正則表達(dá)式發(fā)現(xiàn)匹配時(shí)要調(diào)用的表述方法指針。
RegexOptions — 當(dāng)正則表達(dá)式指定參數(shù)時(shí)使用的枚舉表述值。
RegexOptions — 來自 .Net 源枚舉的不完整拷貝, 包括以下元素:
參數(shù)
描述
None
參數(shù)未指定。
IgnoreCase
匹配搜索不區(qū)分大小寫。
Multiline
指定多行模式。
ExplicitCapture
未覆蓋沒有名稱的分組。僅有效選擇 — 明確命名或具有格式的有數(shù)分組 (?<名稱> 子表達(dá)式)。
Singleline
指定單行模式。
IgnorePatternWhitespace
不破壞順序從范式里刪除空白符, 并啟用帶有 "#" 字符標(biāo)記的注釋。
RightToLeft
指定搜索將從右向左執(zhí)行, 而非從左向右。
Debug
指定程序使用調(diào)試器操作。
ECMAScript
啟用表達(dá)式的 ECMAScript 兼容行為。此數(shù)值僅能配合 IgnoreCase 和 Multiline 使用。
這些選項(xiàng)可用于創(chuàng)建新的 Regex 類對象, 或當(dāng)調(diào)用其靜態(tài)方法時(shí)。