每個(gè)腳本或EA都是在各自獨(dú)立的線程中運(yùn)行。所有指標(biāo)在圖形接口線程中工作。在圖形接口線程中也進(jìn)行了滴答數(shù)的處理和歷史同步。自定義指標(biāo)在主接口線程中工作。如果使用iCustom()函數(shù)調(diào)用了自定義指標(biāo),則該指標(biāo)在調(diào)用它的程序的線程中工作。庫(kù)(導(dǎo)入)函數(shù)也在調(diào)用程序線程中工作。
在運(yùn)行EAr時(shí),請(qǐng)確保它所在實(shí)際的交易環(huán)境能夠訪問(wèn)所需符號(hào)和周期的歷史,并在終端和服務(wù)器之間同步數(shù)據(jù)。對(duì)于所有這些過(guò)程,終端提供不超過(guò)5秒的啟動(dòng)延遲,之后EA將使用可用數(shù)據(jù)啟動(dòng)。因此,如果與服務(wù)器沒(méi)有連接,這可能會(huì)導(dǎo)致EA啟動(dòng)延遲。
下表包含MQL4程序的簡(jiǎn)要總結(jié):
(程序 運(yùn)行 注意事項(xiàng))
腳本
一個(gè)單獨(dú)的線程,腳本的線程數(shù)量等于腳本的數(shù)量
循環(huán)腳本不能中斷其他程序的運(yùn)行
EA
一個(gè)單獨(dú)的線程,EA的線程數(shù)量等于EA的數(shù)量
循環(huán)的EA不能中斷其他程序的運(yùn)行
指標(biāo)
所有指標(biāo)共享終端圖形接口線程的資源
一個(gè)指標(biāo)的無(wú)限循環(huán)將會(huì)停止終端的工作
在將程序附加到圖表后,程序被上傳到客戶端內(nèi)存中,全局變量也被初始化。如果類類型的某個(gè)全局變量有構(gòu)造函數(shù),那么在初始化全局變量時(shí)將調(diào)用該構(gòu)造函數(shù)。
之后,程序?qū)⒌却齺?lái)自客戶機(jī)終端的事件。每個(gè)mql4程序應(yīng)該至少有一個(gè)事件處理程序,否則將不會(huì)執(zhí)行加載的程序。事件處理程序具有預(yù)定義的名稱、參數(shù)和返回類型。
(類型 /函數(shù)名 /參數(shù) /應(yīng)用程序 /說(shuō)明)
int OnInit() 用于EA,指標(biāo)和腳本的初始化事件處理程序。
無(wú)參數(shù)
/它允許使用void返回類型。
void OnDeinit()函數(shù) 用于EA,指標(biāo)和腳本
const int的原因 /
Deinit 事件處理器
void OnStart()函數(shù)
無(wú)參數(shù)
用于腳本/ 開(kāi)始事件處理器
int OnCalculate()函數(shù) 用于指標(biāo)
參數(shù)有:
const int rates_total,
const int prev_calculated,
const datetime &Time[],
const double &Open[],
const double &High[],
const double &Low[],
const double &Close[],
const long &TickVolume[],
const long &Volume[],
const int &Spread[]
/ 指標(biāo)處理和價(jià)格
void/ OnTick() 用于EA
無(wú)參數(shù)
新的Tick事件處理程序。當(dāng)正在處理新標(biāo)記接收的事件時(shí),沒(méi)有收到其他此類事件。
void OnTimer() 用于EA和指標(biāo)
無(wú)參數(shù)
計(jì)時(shí)器事件處理程序
double OnTester() 用于EA
無(wú)參數(shù)
測(cè)試發(fā)生器
void OnChartEvent() 用于EA和指標(biāo)
參數(shù)有:
const int id,
const long &lparam,
const double &dparam,
const string &sparam
圖表事件發(fā)生器
客戶端向相應(yīng)的開(kāi)放圖表發(fā)送新事件。事件也可以由圖表(圖表事件)或mql4程序(自定義事件)生成。通過(guò)設(shè)置CHART_EVENT_OBJECT_CREATE 和CHART_EVENT_OBJECT_DELETE圖表屬性,可以啟用或禁用在圖表上創(chuàng)建或刪除圖形對(duì)象的事件的生成。每個(gè)MQL4程序和每個(gè)圖表都有自己的事件隊(duì)列,其中添加了所有新傳入的事件。
程序只從運(yùn)行它的圖表中接收事件。所有事件都按照接收到的順序依次處理。如果隊(duì)列已經(jīng)有一個(gè)NewTick事件,或者這個(gè)事件正在被處理,那么新的NewTick事件不會(huì)被放在MQL4程序的隊(duì)列中。類似地,如果ChartEvent已經(jīng)加入隊(duì)列,或者正在處理此事件,則不會(huì)加入此類新事件。計(jì)時(shí)器事件的處理方式是相同的——如果計(jì)時(shí)器事件在隊(duì)列中或正在處理中,那么新計(jì)時(shí)器事件不會(huì)加入隊(duì)列。
事件隊(duì)列有一個(gè)有限但足夠大的大小,因此對(duì)于編寫(xiě)良好的程序來(lái)說(shuō),隊(duì)列溢出是不可能的。在隊(duì)列溢出的情況下,在不排隊(duì)的情況下丟棄新事件。
不建議使用無(wú)限循環(huán)來(lái)處理事件。此規(guī)則的例外可能只有僅處理單個(gè)啟動(dòng)事件的腳本。
庫(kù)不處理任何事件。
指標(biāo)、腳本和EA是用MQL4編寫(xiě)的可執(zhí)行程序。它們是為不同類型的任務(wù)而設(shè)計(jì)的。因此,對(duì)于某些函數(shù)的使用有一些限制,這取決于程序的類型。
在指標(biāo)中禁止具備以下功能:
OrderSend();
SendFTP();
Sleep();
ExpertRemove();
MessageBox().
EA和腳本中禁止為指標(biāo)設(shè)計(jì)的所有功能:
SetIndexBuffer();
IndicatorSetDouble();
IndicatorSetInteger();
IndicatorSetString().
庫(kù)不是一個(gè)獨(dú)立的程序,它是在MQL4程序上下文中執(zhí)行的,MQL4程序稱為:腳本、指示器或?qū)<翌檰?wèn)。因此,上述限制適用于被調(diào)用的庫(kù)。
指標(biāo)裝卸
在以下情況下加載指標(biāo):
指標(biāo)附在圖表上;
終端啟動(dòng)(如果指標(biāo)在終端關(guān)閉前附在圖表上);
加載模板(如果模板中指定了附圖的指標(biāo);
更改概要文件(如該指標(biāo)附于其中一個(gè)概要文件圖表);
更改圖表的符號(hào)及/或時(shí)間表,該指標(biāo)及/或時(shí)間表已附于圖表上;
在成功地重新編譯指標(biāo)后(如果指標(biāo)附加到圖表上);
指標(biāo)輸入?yún)?shù)的變化。
在下列情況下卸載指標(biāo):
從圖表中分離指標(biāo)時(shí);
終端關(guān)機(jī)(如果指標(biāo)附有圖表);
加載模板(如果指標(biāo)附加到圖表上);
附有指標(biāo)的圖表的結(jié)束;
更改概要文件(如指標(biāo)附于已更改概要文件的圖表之一);
更改圖表的指標(biāo)及/或時(shí)間表,該指標(biāo)及/或時(shí)間表已附于圖表上;
指標(biāo)輸入?yún)?shù)的變化。
在以下情況下加載EA:
將EA附加到圖表時(shí);
終端啟動(dòng)(如果EA在終端關(guān)閉前附在圖表上);
加載模板(如果模板中指定了附在圖表上的EA);
更改配置文件(如果將EA附加到配置文件圖表之一);
連接到帳戶,即使帳戶編號(hào)相同(如果EA在服務(wù)器上的終端授權(quán)之前附加到圖表中)。
EA在以下情況下被卸載:
將EA從圖表中刪除時(shí);
如果一個(gè)新的EA被附加到一個(gè)圖表上,如果另一個(gè)EA已經(jīng)被附加,這個(gè)EA將被卸載。
終端關(guān)閉(如果EA附在圖表上);
加載模板(如果將EA附加到圖表中);
圖表的結(jié)尾,EA附在圖表上。
個(gè)人資料的更改(如EA附于已更改個(gè)人資料的圖表之一);
更改連接終端的帳戶(如果在服務(wù)器上的終端授權(quán)之前將EA附加到圖表上);
調(diào)用ExpertRemove()函數(shù)。
如果一個(gè)圖表的指標(biāo)或時(shí)框附加了EA,則不會(huì)加載或卸載EA。在這種情況下,客戶機(jī)終端隨后在舊的指標(biāo)/時(shí)框上調(diào)用OnDeinit()處理程序,在新符號(hào)/時(shí)框上調(diào)用OnInit()(如果是這樣的話),全局變量和靜態(tài)變量的值不會(huì)被重置。所有在初始化完成之前接收到的事件(OnInit()函數(shù))都被跳過(guò)。
為了更好地了解EA操作,我們建議編譯以下EA的代碼,并執(zhí)行加載/卸載、模板更改、符號(hào)更改、時(shí)框更改等操作:
加載和卸載腳本
腳本附加到圖表后立即加載,完成操作后立即卸載。
當(dāng)程序被卸載(從圖表中刪除)時(shí),客戶端終端執(zhí)行全局變量的反初始化并刪除事件隊(duì)列。在這種情況下,反初始化意味著所有字符串類型變量的重置、動(dòng)態(tài)數(shù)組對(duì)象的重新分配以及調(diào)用它們的析構(gòu)函數(shù)(如果它們是可用的)
輸入?yún)?shù)和源代碼編譯
如果在圖表上啟動(dòng)的程序的源代碼被成功地重新編譯,它的前一個(gè)版本將從圖表中刪除,新的編譯副本將被執(zhí)行。
如果重新編譯后輸入?yún)?shù)集沒(méi)有更改,則應(yīng)用先前指定的參數(shù)值。否則,使用默認(rèn)值。
在以下情況下,在編輯源代碼時(shí)考慮要更改mql4程序輸入?yún)?shù)集:
改變了參數(shù)的數(shù)量;
改變了參數(shù)的順序;
參數(shù)名稱已更改;
一個(gè)或多個(gè)參數(shù)的類型已經(jīng)更改。
更改任何參數(shù)的默認(rèn)值不被認(rèn)為是輸入?yún)?shù)集的更改。
輸入?yún)?shù)集清楚地標(biāo)識(shí)了終端執(zhí)行系統(tǒng)中的程序。如果此集合不變,則認(rèn)為可執(zhí)行文件的新版本保留了程序的整個(gè)邏輯和功能。
如果輸入?yún)?shù)集發(fā)生了更改,終端將認(rèn)為新的可執(zhí)行文件與之前在圖表上啟動(dòng)的程序不兼容。因此,啟動(dòng)新的重新編譯程序時(shí),輸入?yún)?shù)集具有默認(rèn)值。
在其他情況下(包括更改任何參數(shù)的默認(rèn)值時(shí)),在重新編譯之后應(yīng)用先前指定的參數(shù)。
在任何編譯之后都會(huì)調(diào)用OnInit()預(yù)定義函數(shù)。它的目的是正確初始化程序的所有全局變量和靜態(tài)變量。在OnInit()事件處理程序中應(yīng)該正確使用程序的輸入?yún)?shù)值。