最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

期貨量化交易軟件:開發(fā)回放系統(tǒng) — 市場模擬第 04 部分調(diào)整設(shè)置(II)

2023-09-04 17:18 作者:bili_45793681098  | 我要投稿

將 EA 換成指標(biāo)

這樣的修改相當(dāng)容易實現(xiàn)。 之后,赫茲量化就能夠用我們自己的 EA 來研究如何利用市場回放服務(wù),或在現(xiàn)實市場上進行交易。 例如,我們就能夠使用我在之前文章中展示的 EA。 參閱“從頭開始開發(fā)交易 EA”系列中的更多內(nèi)容。 雖然并非旨在 100% 自動化,但它可以適應(yīng)在回放服務(wù)中使用。 但是,我們把它留待將來。 此外,赫茲量化還將能夠使用“創(chuàng)建自動運行的 EA(第 01 部分):概念和結(jié)構(gòu)”系列中的一些 EA,其中我們研究過如何創(chuàng)建在全自動模式下工作的智能系統(tǒng)。

不過,赫茲量化目前的焦點不是 EA(我們將在未來探討這一點),而是其它東西。

完整的指標(biāo)代碼可以在下面看到。 它完全包括 EA 中已經(jīng)存在的功能,同時將其實現(xiàn)為指標(biāo):

#property copyright "Daniel Jose" #property indicator_chart_window #property indicator_plots 0 //+------------------------------------------------------------------+ #include <Market Replay\C_Controls.mqh> //+------------------------------------------------------------------+ C_Controls ? ? ?Control; //+------------------------------------------------------------------+ int OnInit() { ? ? ? ?IndicatorSetString(INDICATOR_SHORTNAME, "Market Replay"); ? ? ? ?Control.Init(); ? ? ? ? ? ? ? ?return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { ? ? ? ?return rates_total; } //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ? ? ? ?Control.DispatchMessage(id, lparam, dparam, sparam); } //+------------------------------------------------------------------+

唯一的區(qū)別是增加了一個短名,其最好包含在指標(biāo)中。 這部分在上面的代碼中都以高亮顯示。 通過這樣做,赫茲量化獲得了額外的優(yōu)勢:我們可以使用任何 EA 基于回放服務(wù)進行練習(xí)和訓(xùn)練。 在任何人提出可能的問題之前,我會回答它:市場回放并非策略測試器。 它是針對那些想要練習(xí)讀取市場,改善預(yù)測資產(chǎn)走勢來達成穩(wěn)定盈利的人。 市場回放并不能取代出色的 赫茲量化 策略測試器。 不過,策略測試器并不適合實施市場回放。

雖然乍一看轉(zhuǎn)換似乎沒有副作用,但這并不完全如實。 當(dāng)運行回放系統(tǒng),并由指標(biāo)替 EA 控制交易完成時,您會注意到失敗。 當(dāng)圖表時間幀變更時,指標(biāo)將從圖表中刪除,然后重新啟動。 這種刪除并重新啟動它的操作,令指示我們處于暫?;虿シ拍J降陌粹o狀態(tài)與回放系統(tǒng)的實際狀態(tài)不一致。 為了修復(fù)此問題,赫茲量化需要進行一些小的調(diào)整。 故此,我們將有以下指標(biāo)啟動代碼:

int OnInit() { ? ? ? ?u_Interprocess Info; ? ? ? ? ? ? ? ?IndicatorSetString(INDICATOR_SHORTNAME, "Market Replay"); ? ? ? ?if (GlobalVariableCheck(def_GlobalVariableReplay)) Info.Value = GlobalVariableGet(def_GlobalVariableReplay); else Info.Value = 0; ? ? ? ?Control.Init(Info.s_Infos.isPlay); ? ? ? ? ? ? ? ?return INIT_SUCCEEDED; }

代碼中添加的高亮顯示內(nèi)容可確?;胤欧?wù)的狀態(tài)與我們在圖表上看到的按鈕匹配。 控制代碼的修改非常簡單,不需要特別留意。

現(xiàn)在,以前使用 EA 的模板文件現(xiàn)在將切換到使用指標(biāo)。 這讓我們可以完全自由地在未來進行其它修改。

位置控制實現(xiàn)

在此,赫茲量化將實現(xiàn)一個控制功能,來指示我們要進入重播文件中的位置,便以開始我們的市場研究。 但這不會是一個精準(zhǔn)的所在。 起始位置將是近似值。 這并非因為不可能做這樣的事情。 與之對,指出確切的所在會容易得多。 然而,在與那些在市場上有更多經(jīng)驗的人談?wù)摬⒔涣鹘?jīng)驗時,我們發(fā)現(xiàn)了一個共識。 理想的選擇不是跳轉(zhuǎn)到我們所期望的特定走勢的確切之處,而是在接近所需走勢的所在開始回放。 換言之,在采取行動之前,您需要明白正在發(fā)生的事情。

這個思路對我來說似乎很好,所以我決定:市場回放不應(yīng)該跳到一個特定的位置點。 盡管那樣更容易實現(xiàn),但您需要轉(zhuǎn)到最近的位置點。 哪個位置點最接近,取決于每天執(zhí)行的交易數(shù)量。 赫茲量化執(zhí)行的交易越多,就越難達到確切的位置。

故此,我們將訪問附近的位置點,來搞清實際發(fā)生的情況,以便創(chuàng)建實際的交易模擬。 再次:赫茲量化不是在創(chuàng)建策略測試器。但通過這樣做,隨著時間的推移,您將從中學(xué)會判定何時走勢更安全,或何時風(fēng)險過高,且您不應(yīng)該入場交易。

此步驟中的所有工作都將在 C_Control 類中完成。 所以,現(xiàn)在我們開工吧!

我們要做的第一件事是厘定一些定義。

#define def_ButtonLeft ?"Images\\Market Replay\\Left.bmp" #define def_ButtonRight "Images\\Market Replay\\Right.bmp" #define def_ButtonPin ? "Images\\Market Replay\\Pin.bmp"

現(xiàn)在我們需要創(chuàng)建一組變量來存儲位置系統(tǒng)數(shù)據(jù)。 它們的實現(xiàn)方式如下:

struct st_00 { ? ? ? ?string ?szBtnLeft, ? ? ? ? ? ? ? ?szBtnRight, ? ? ? ? ? ? ? ?szBtnPin, ? ? ? ? ? ? ? ?szBarSlider; ? ? ? ?int ? ? posPinSlider, ? ? ? ? ? ? ? ?posY; }m_Slider;

這正是您剛剛注意到的。 我們將使用滑塊指向回放系統(tǒng)理應(yīng)啟動的大致位置。 我們現(xiàn)在有一個通用函數(shù),用于創(chuàng)建播放/暫停按鈕和滑塊按鈕。 此函數(shù)如下所示。 我認(rèn)為理解它不會有任何困難,因為它非常簡單。

inline void CreateObjectBitMap(int x, int y, string szName, string Resource1, string Resource2 = NULL) ? ? ? ? ? ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectCreate(m_id, szName, OBJ_BITMAP_LABEL, 0, 0, 0); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectSetInteger(m_id, szName, OBJPROP_XDISTANCE, x); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectSetInteger(m_id, szName, OBJPROP_YDISTANCE, y); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectSetString(m_id, szName, OBJPROP_BMPFILE, 0, "::" + Resource1); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectSetString(m_id, szName, OBJPROP_BMPFILE, 1, "::" + (Resource2 == NULL ? Resource1 : Resource2)); ? ? ? ? ? ? ? ? ? ? ? ?}

好吧,現(xiàn)在每個按鈕都將調(diào)用此函數(shù)來創(chuàng)建。 事情因此變得容易很多,并增加了代碼重用度,從而令事情更加穩(wěn)定和快速。 接下來要創(chuàng)建的是一個函數(shù),該函數(shù)將表示要在滑塊中使用的通道。 它由以下函數(shù)創(chuàng)建:

inline void CreteBarSlider(int x, int size) ? ? ? ? ? ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectCreate(m_id, m_Slider.szBarSlider, OBJ_RECTANGLE_LABEL, 0, 0, 0); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectSetInteger(m_id, m_Slider.szBarSlider, OBJPROP_XDISTANCE, x); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectSetInteger(m_id, m_Slider.szBarSlider, OBJPROP_YDISTANCE, m_Slider.posY - 4); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectSetInteger(m_id, m_Slider.szBarSlider, OBJPROP_XSIZE, size); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectSetInteger(m_id, m_Slider.szBarSlider, OBJPROP_YSIZE, 9); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectSetInteger(m_id, m_Slider.szBarSlider, OBJPROP_BGCOLOR, clrLightSkyBlue); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectSetInteger(m_id, m_Slider.szBarSlider, OBJPROP_BORDER_COLOR, clrBlack); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectSetInteger(m_id, m_Slider.szBarSlider, OBJPROP_WIDTH, 3); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectSetInteger(m_id, m_Slider.szBarSlider, OBJPROP_BORDER_TYPE, BORDER_FLAT); ? ? ? ? ? ? ? ? ? ? ? ?}

此處最奇怪的是控制通道邊界的表示。 您可以根據(jù)需要自定義此設(shè)置,以及通道的寬度,該寬度在 OBJPROP_YSIZE 屬性中設(shè)置。 但在更改此屬性的數(shù)值時,請不要忘記調(diào)整該數(shù)值,減去 m_Slider.posY,以便通道位于按鈕之間。

創(chuàng)建播放/暫停按鈕的函數(shù)現(xiàn)在如下所示:

void CreateBtnPlayPause(long id, bool state) { ? ? ? ?m_szBtnPlay = def_PrefixObjectName + "Play"; ? ? ? ?CreateObjectBitMap(5, 25, m_szBtnPlay, def_ButtonPause, def_ButtonPlay); ? ? ? ?ObjectSetInteger(id, m_szBtnPlay, OBJPROP_STATE, state); }

容易得多,不是嗎? 現(xiàn)在我們來看一下創(chuàng)建滑塊的函數(shù)。 它如下所示:

void CreteCtrlSlider(void) { ? ? ? ?u_Interprocess Info; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?m_Slider.szBarSlider = def_PrefixObjectName + "Slider Bar"; ? ? ? ?m_Slider.szBtnLeft ? = def_PrefixObjectName + "Slider BtnL"; ? ? ? ?m_Slider.szBtnRight ?= def_PrefixObjectName + "Slider BtnR"; ? ? ? ?m_Slider.szBtnPin ? ?= def_PrefixObjectName + "Slider BtnP"; ? ? ? ?m_Slider.posY = 40; ? ? ? ?CreteBarSlider(82, 436); ? ? ? ?CreateObjectBitMap(52, 25, m_Slider.szBtnLeft, def_ButtonLeft); ? ? ? ?CreateObjectBitMap(516, 25, m_Slider.szBtnRight, def_ButtonRight); ? ? ? ?CreateObjectBitMap(def_MinPosXPin, m_Slider.posY, m_Slider.szBtnPin, def_ButtonPin); ? ? ? ?ObjectSetInteger(m_id, m_Slider.szBtnPin, OBJPROP_ANCHOR, ANCHOR_CENTER); ? ? ? ?if (GlobalVariableCheck(def_GlobalVariableReplay)) Info.Value = GlobalVariableGet(def_GlobalVariableReplay); else Info.Value = 0; ? ? ? ?PositionPinSlider(Info.s_Infos.iPosShift); }

仔細查看控件的名稱,這非常重要。 當(dāng)回放系統(tǒng)處于重播狀態(tài)時,這些控件將不可用。 每次我們處于暫停狀態(tài)時,都會調(diào)用該函數(shù),從而創(chuàng)建滑塊。 請注意因為這一點,赫茲量化將捕獲終端全局變量的數(shù)值,以便正確識別和定位滑塊。

因此,我建議您不要手工對終端的全局變量執(zhí)行任何操作。 請注意另一個重要細節(jié),即頂針。 與按鈕不同,設(shè)計它時會在中心有一個錨點,便于查找。 這里我們還有另一個函數(shù)調(diào)用:

inline void PositionPinSlider(int p) { ? ? ? ?m_Slider.posPinSlider = (p < 0 ? 0 : (p > def_MaxPosSlider ? def_MaxPosSlider : p)); ? ? ? ?ObjectSetInteger(m_id, m_Slider.szBtnPin, OBJPROP_XDISTANCE, m_Slider.posPinSlider + def_MinPosXPin); ? ? ? ?ChartRedraw(); }

它將滑塊放置在某個區(qū)域中,并確保它駐留在上面的受限設(shè)置內(nèi)。

您可以想象,我們?nèi)匀恍枰獙ο到y(tǒng)進行小的調(diào)整。 每次圖表時間幀變更時,指標(biāo)都會重置,導(dǎo)致我們失去在回放系統(tǒng)中存在的實際當(dāng)前位置點。 避免這種情況的途徑之一是在初始化函數(shù)里進行一些擴充。 取這些變更的好處,我們還將添加一些其它內(nèi)容。 我們來看看初始化函數(shù)現(xiàn)在是什么樣子的:

void Init(const bool state = false) { ? ? ? ?if (m_szBtnPlay != NULL) return; ? ? ? ?m_id = ChartID(); ? ? ? ?ChartSetInteger(m_id, CHART_EVENT_MOUSE_MOVE, true); ? ? ? ?CreateBtnPlayPause(m_id, state); ? ? ? ?GlobalVariableTemp(def_GlobalVariableReplay); ? ? ? ?if (!state) CreteCtrlSlider(); ? ? ? ?ChartRedraw(); }

現(xiàn)在我們還要添加代碼,以便將鼠標(biāo)移動事件轉(zhuǎn)發(fā)到指標(biāo)。 如果不加這些,鼠標(biāo)事件就會丟失,并且不會由 MetaTrader 5 傳遞給指標(biāo)。 為了在不需要時隱藏滑塊,赫茲量化添加了一些檢查。 如果檢查到確認(rèn)應(yīng)顯示滑塊,那么它就被顯示在屏幕上。

到目前為止,我們已經(jīng)見識到了一切,您可能想知道:事件處理現(xiàn)在如何執(zhí)行? 我們會有一些超級復(fù)雜的額外代碼嗎? 好吧,處理鼠標(biāo)事件的方式?jīng)]有太大變化。 添加拖動事件并不是很復(fù)雜。 您真正要做的就是管控一些限制,以免事情失控。 而實現(xiàn)本身非常簡單。

赫茲量化來看一下處理所有這些事件的函數(shù)的代碼:DispatchMessage。 為了便于解釋,我們分部分查看代碼。 第一部分負(fù)責(zé)處理對象單擊事件。 請看下面的代碼:

void DispatchMessage(const int id, const long &lparam, const double &dparam, const string &sparam) { ? ? ? ?u_Interprocess Info; //... other local variables .... ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?switch (id) ? ? ? ?{ ? ? ? ? ? ? ? ?case CHARTEVENT_OBJECT_CLICK: ? ? ? ? ? ? ? ? ? ? ? ?if (sparam == m_szBtnPlay) ? ? ? ? ? ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Info.s_Infos.isPlay = (bool) ObjectGetInteger(m_id, m_szBtnPlay, OBJPROP_STATE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (!Info.s_Infos.isPlay) CreteCtrlSlider(); else ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ObjectsDeleteAll(m_id, def_PrefixObjectName + "Slider"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?m_Slider.szBtnPin = NULL; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Info.s_Infos.iPosShift = m_Slider.posPinSlider; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?GlobalVariableSet(def_GlobalVariableReplay, Info.Value); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ChartRedraw(); ? ? ? ? ? ? ? ? ? ? ? ?}else ? if (sparam == m_Slider.szBtnLeft) PositionPinSlider(m_Slider.posPinSlider - 1); ? ? ? ? ? ? ? ? ? ? ? ?else if (sparam == m_Slider.szBtnRight) PositionPinSlider(m_Slider.posPinSlider + 1); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break; // ... The rest of the code...

當(dāng)我們按下播放/暫停按鈕時,我們需要執(zhí)行幾個操作。 其中之一是如果我們處于暫停狀態(tài),則需創(chuàng)建一個滑塊。 如果我們退出暫停狀態(tài),并進入播放狀態(tài),則必須從圖表中隱藏控件,從而我們能不再誤碰它們。 滑塊的當(dāng)前值應(yīng)發(fā)送到終端的全局變量。 因此,回放服務(wù)可以訪問我們想要放置回放系統(tǒng)的位置對應(yīng)的百分比位置。

除了與播放/暫停按鈕相關(guān)的這些問題外,赫茲量化還需要應(yīng)對單擊滾動條的逐點移動按鈕時發(fā)生的事件。 如果我們單擊滾動條的左按鈕,滑塊的當(dāng)前值應(yīng)該減少 1。 與此類似,如果我們按下滾動條的右按鈕,控件當(dāng)前值加 1,直到最大設(shè)置限制。

這很簡單。 至少在這一部分中,應(yīng)對對象點擊消息并不難。 然而,現(xiàn)在拖動滑塊存在一個稍微復(fù)雜的問題。 為了搞清這一點,我們來看一下處理鼠標(biāo)移動事件的代碼。



期貨量化交易軟件:開發(fā)回放系統(tǒng) — 市場模擬第 04 部分調(diào)整設(shè)置(II)的評論 (共 條)

分享到微博請遵守國家法律
岑巩县| 樟树市| 广州市| 达拉特旗| 建阳市| 马关县| 定南县| 苏尼特左旗| 青铜峡市| 郴州市| 金阳县| 石河子市| 无极县| 格尔木市| 阿拉善左旗| 古蔺县| 龙陵县| 屯门区| 宣汉县| 宣威市| 巨鹿县| 义乌市| 蕲春县| 浠水县| 墨江| 石屏县| 庐江县| 恩施市| 肇庆市| 洛阳市| 辽宁省| 连城县| 白城市| 青铜峡市| 沙河市| 花莲市| 台东市| 镇赉县| 营口市| 静安区| 西宁市|