股票量化:赫茲量化系統(tǒng)定量和可視化分析測試器報告
為了能夠執(zhí)行該項目,我們首先需要改進之前在第二部分里研究的圖形用戶界面。 第三部分里執(zhí)行的所有代碼改進,都直接與 OLAP 引擎有關(guān)。 但可視化相關(guān)部分卻并未執(zhí)行升級。 這就是我們要做的工作,用來自第二篇文章里的 OLAPGUI 交易報告分析器作為本文的測試任務(wù)。 我們還將統(tǒng)一圖形部分,如此便可以輕松地將其應(yīng)用到任何新的其他應(yīng)用領(lǐng)域,尤其是計劃中的優(yōu)化結(jié)果分析器。
因為 Y 軸顯示的不是選擇器(其值四舍五入到立方單元大?。@示的是以秒為單位的匯總持續(xù)值,所以這么大的數(shù)字難以理解。 為了解決此問題,我們嘗試把秒數(shù)除以當前時間幀柱線的持續(xù)時間。 在此情況下,這些值將代表柱線的數(shù)量。 為此,我們需要將某個標志傳遞給 CGraphicInPlot 類,進而會傳遞給處理坐標軸的 CAxis 類。 改變操作模式的標志可能很多。 因此,在文件 Plot.mqh 中為它們保留一個名為 AxisCustomizer 的特殊新類。
?class AxisCustomizer ?{ ? ?public: ? ? ?const CGraphicInPlot *parent; ? ? ?const bool y; // true for Y, false for X ? ? ?const bool periodDivider; ? ? ?const bool hide; ? ? ?AxisCustomizer(const CGraphicInPlot *p, const bool axisY, ? ? ? ?const bool pd = false, const bool h = false): ? ? ? ?parent(p), y(axisY), periodDivider(pd), hide(h) {} ?};
潛在地,要把各種標簽顯示功能添加到該類之中。 但于此刻,它僅存儲坐標軸類型(X 或 Y)的符號,和少數(shù)邏輯選項,例如 periodDivider 和 '隱藏'。 第一個選項意味著值應(yīng)除以 PeriodSeconds()。 第二個選項將在以后講述。
該類的對象通過特殊方法注入 CGraphicInPlot 當中:
?class CGraphicInPlot: public CGraphic ?{ ? ?... ? ? ?void InitAxes(CAxis &axe, const AxisCustomizer *custom = NULL); ? ? ?void InitXAxis(const AxisCustomizer *custom = NULL); ? ? ?void InitYAxis(const AxisCustomizer *custom = NULL); ?}; ? ?void CGraphicInPlot::InitAxes(CAxis &axe, const AxisCustomizer *custom = NULL) ?{ ? ?if(custom) ? ?{ ? ? ?axe.Type(AXIS_TYPE_CUSTOM); ? ? ?axe.ValuesFunctionFormat(CustomDoubleToStringFunction); ? ? ?axe.ValuesFunctionFormatCBData((AxisCustomizer *)custom); ? ?} ? ?else ? ?{ ? ? ?axe.Type(AXIS_TYPE_DOUBLE); ? ?} ?} ? ?void CGraphicInPlot::InitXAxis(const AxisCustomizer *custom = NULL) ?{ ? ?InitAxes(m_x, custom); ?} ? ?void CGraphicInPlot::InitYAxis(const AxisCustomizer *custom = NULL) ?{ ? ?InitAxes(m_y, custom); ?}
若此類對象尚未創(chuàng)建且未傳遞給圖形類時,標準庫將按常規(guī)方式顯示為 AXIS_TYPE_DOUBLE 數(shù)字。
在此,我們用標準庫的方式來自定義坐標軸上的標簽:軸類型設(shè)置為等于 AXIS_TYPE_CUSTOM,且通過 ValuesFunctionFormatCBData 傳遞指向 AxisCustomizer 的指針。 進而,它由 CGraphic 基類傳遞給 CustomDoubleToStringFunction 標簽繪制函數(shù)(在上述代碼中調(diào)用 ValuesFunctionFormat 設(shè)置)。 當然,我們需要 CustomDoubleToStringFunction 函數(shù),該函數(shù)早前曾以簡化形式實現(xiàn),沒有 AxisCustomizer 類對象(CGraphicInPlot 圖表充當設(shè)置對象)。
?string CustomDoubleToStringFunction(double value, void *ptr) ?{ ? ?AxisCustomizer *custom = dynamic_cast<AxisCustomizer *>(ptr); ? ?if(custom == NULL) return NULL; ? ? ? ?// check options ? ?if(!custom.y && custom.hide) return NULL; // case of X axis and "no marks" mode ? ? ? ?// in simple cases return a string ? ?if(custom.y) return (string)(float)value; ? ? ? ? ?const CGraphicInPlot *self = custom.parent; // obtain actual object with cache ? ?if(self != NULL) ? ?{ ? ? ?... // retrieve selector mark for value ? ?} ?}
AxisCustomizer 定制對象存儲在 CPlot 類中,CPlot 類是一個 GUI 控件(繼承自 CWndClient),且是 CGraphicInPlot 的容器:
?class CPlot: public CWndClient ?{ ? ?private: ? ? ?CGraphicInPlot *m_graphic; ? ? ?ENUM_CURVE_TYPE type; ? ? ? ? ? ?AxisCustomizer *m_customX; ? ? ?AxisCustomizer *m_customY; ? ? ?... ? ? ? ?public: ? ? ?void InitXAxis(const AxisCustomizer *custom = NULL) ? ? ?{ ? ? ? ?if(CheckPointer(m_graphic) != POINTER_INVALID) ? ? ? ?{ ? ? ? ? ?if(CheckPointer(m_customX) != POINTER_INVALID) delete m_customX; ? ? ? ? ?m_customX = (AxisCustomizer *)custom; ? ? ? ? ?m_graphic.InitXAxis(custom); ? ? ? ?} ? ? ?} ? ? ?... ?};