期货量化交易软件:按记录过滤
简介
有不同的过滤器:指标值、市场波动性、时间和工作日。 它们全部可以用来过滤亏损交易。 将过滤器添加至 Expert Advisor 非常容易——只要在开始程序块之前另加一个条件即可。 但是,如果要使用 EA 记录作为过滤器,应如何做呢? 如果在数次不成功的交易后关闭交易系统,则随后不会生成记录,因此没有可以分析的内容。 要解决这个问题,我们需要教会 Expert Advisor 虚拟交易,即模拟开仓、修改和平仓而无需真实交易活动。 这是本文要讲述的内容。

编辑切换为居中
试验策略
为了系统的实施,我们将在 Expert Advisor CrossMACD_DeLuxe.mq4 进行一些改动:
在每个头寸的开仓/修改/平仓点,改动将写在虚拟头寸的数组内;
添加虚拟头寸的 StopLoss 和 TakeProfit 的启动跟踪;
添加过滤标准——现实交易不会进行的条件。
我将力图详尽的描述 EA 修改的每个步骤。 如果你不感兴趣,可以下载现成的 Expert Advisor 并前往“游戏是否得不偿失?”部分。
解释虚拟头寸
出现开仓的信号。 计算 StopLoss 和 TakeProfit 参数,完全做好调用 OrderSend() 函数的准备。 我们正是在此刻开始虚拟交易——只要将所有必要参数保存在合适的变量: void OpenBuy() { int _GetLastError = 0; double _OpenPriceLevel, _StopLossLevel, _TakeProfitLevel; _OpenPriceLevel = NormalizeDouble(Ask, Digits); if(StopLoss > 0) _StopLossLevel = NormalizeDouble(_OpenPriceLevel - StopLoss*Point, Digits); else _StopLossLevel = 0.0; if(TakeProfit > 0) _TakeProfitLevel = NormalizeDouble(_OpenPriceLevel + TakeProfit*Point, Digits); else _TakeProfitLevel = 0.0; //---- open the virtual position virtOrderSend(OP_BUY, _OpenPriceLevel, _StopLossLevel, _TakeProfitLevel); if(OrderSend(Symbol(), OP_BUY, 0.1, _OpenPriceLevel, 3, _StopLossLevel, _TakeProfitLevel, "CrossMACD", _MagicNumber, 0, Green) < 0) { _GetLastError = GetLastError(); Alert("Error OrderSend № ", _GetLastError); return(-1); } } //---- Save parameters of the opened position in main variables void virtualOrderSend(int type, double openprice, double stoploss, double takeprofit) { virtTicket = 1; virtType = type; virtOpenPrice = openprice; virtStopLoss = stoploss; virtTakeProfit = takeprofit; } 可以看到,我们只用了五个变量: int virtTicket = 0; // determines, if there is an open virtual position int virtType = 0; // position type double virtOpenPrice = 0.0; // position opening price double virtStopLoss = 0.0; // position StopLoss double virtTakeProfit = 0.0; // position TakeProfit
我们任务的完成并不需要其他特征。 如果要拓展该示例的功能性,仅需添加必要的变量。
为了追踪平仓和头寸修改,我们需要更多操作。 复制 Expert Advisor 内未平仓头寸控制的程序块,并更改订单特征为虚拟: int start() { // skipped... //+------------------------------------------------------------------+ //| Control block of "virtual" positions | //+------------------------------------------------------------------+ if(virtTicket > 0) { //---- if BUY-position is open, if(virtType == OP_BUY) { //---- if MACD crossed 0-line downwards, if(NormalizeDouble(MACD_1 + CloseLuft*Point*0.1, Digits + 1) <= 0.0) { //---- close position virtOrderClose(Bid); } //---- if the signal did not change, accompany the position by // TrailingStop else { if(TrailingStop > 0) { if(NormalizeDouble(Bid - virtOpenPrice, Digits ) > 0.0) { if(NormalizeDouble( Bid - TrailingStop*Point - virtStopLoss, Digits) > 0.0 || virtStopLoss < Point) { virtStopLoss = Bid - TrailingStop*Point; } } } } } //---- if SELL position is open if(virtType == OP_SELL) { //---- if MACD crossed 0-line upwards, if(NormalizeDouble(MACD_1 - CloseLuft*Point*0.1, Digits + 1 ) >= 0.0) { //---- close the position virtOrderClose(Ask); } //---- if the signal did not change, accompany the position by // TrailingStop else { if ( TrailingStop > 0 ) { if(NormalizeDouble( virtOpenPrice - Ask, Digits ) > 0.0 ) { if(NormalizeDouble( virtStopLoss - ( Ask + TrailingStop*Point ), Digits ) > 0.0 || virtStopLoss <= Point ) { virtStopLoss = Ask + TrailingStop*Point; } } } } } } // skipped... return(0); } //---- virtual position closing function void virtOrderClose(double closeprice) { //---- Save the parameters of the closed position in the array ArrayResize(virtClosedOrders, virtClosedOrdersCount + 1); virtClosedOrders[virtClosedOrdersCount][0] = virtType; virtClosedOrders[virtClosedOrdersCount][1] = virtOpenPrice; virtClosedOrders[virtClosedOrdersCount][2] = virtStopLoss; virtClosedOrders[virtClosedOrdersCount][3] = virtTakeProfit; virtClosedOrders[virtClosedOrdersCount][4] = closeprice; virtClosedOrdersCount ++; //---- clear variables virtTicket = 0; virtType = 0; virtOpenPrice = 0.0; virtStopLoss = 0.0; virtTakeProfit = 0.0; } 可以看到,修改变为简单的将新值分配给 virtStopLoss 变量。 平仓非常困难——所有平仓订单的特征都保存在一个数组内。 随后整个虚拟记录将保存在内。 我们将从中提取平仓头寸的信息,用于进行新开仓的决策。