首先,我们按功能把任务分成三个步骤 — 这三个步骤其实是三种智能交易程序:
举一个简单的例子,一个来自于 MACD 线交叉点(信号线和基础线)的建仓信号,简化它的控制代码块,程序如下:
extern int _MagicNumber = 1122; int start() { //---- 记住指标值做分析数据 double MACD_1 = iMACD(Symbol(), 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1 ); double MACD_2 = iMACD(Symbol(), 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 2 ); int _GetLastError = 0, _OrdersTotal = OrdersTotal(); //---- 在开仓位置搜索 for ( int z = _OrdersTotal - 1; z >= 0; z -- ) { // 如果在搜索中生成错误,转至下一个仓位 if ( !OrderSelect( z, SELECT_BY_POS ) ) { _GetLastError = GetLastError(); Print("OrderSelect( ", z, ", SELECT_BY_POS ) - 错误 #", _GetLastError ); continue; } // 如果当前的货币对没有开仓, // 忽略过 if ( OrderSymbol() != Symbol() ) continue; // 如果 MagicNumber不等于_MagicNumber, // 忽略这个仓位 if ( OrderMagicNumber() != _MagicNumber ) continue; //---- 如果BUY舱位开仓, if ( OrderType() == OP_BUY ) { //---- 如果MACD 遇到下降的零线, if(NormalizeDouble(MACD_1, Digits + 1) < 0.0 && NormalizeDouble( MACD_2, Digits + 1) >= 0.0) { //---- 平仓 if(!OrderClose( OrderTicket(), OrderLots(), Bid, 5, Green)) { _GetLastError = GetLastError(); Alert("错误OrderClose 鈩?", _GetLastError); return(-1); } } // 如果信号线没有改变,退出: // 开新仓位过早 else { return(0); } } //---- 如果 SELL 仓位开仓, if ( OrderType() == OP_SELL ) { //---- 如果 MACD 遇到上升的零线 if(NormalizeDouble(MACD_1, Digits + 1) > 0.0 && NormalizeDouble(MACD_2, Digits + 1 ) <= 0.0) { //---- 平仓 if(!OrderClose( OrderTicket(), OrderLots(), Ask, 5, Red)) { _GetLastError = GetLastError(); Alert( "错误 OrderClose 鈩?", _GetLastError ); return(-1); } } // 如果信号没有给便,退出: // 开新仓位过早 else return(0); } } //+------------------------------------------------------------------+ //|如果达到此点,说明没有开仓仓位 | //| 检测可能开仓 | //+------------------------------------------------------------------+ //---- 如果 MACD 遇到上升的零线, if ( NormalizeDouble( MACD_1, Digits + 1 ) > 0.0 && NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0 ) { //---- 打开 BUY 仓位 if(OrderSend( Symbol(), OP_BUY, 0.1, Ask, 5, 0.0, 0.0, "MACD_test", _MagicNumber, 0, Green ) < 0) { _GetLastError = GetLastError(); Alert( "错误 OrderSend 鈩?", _GetLastError ); return(-1); } return(0); } //---- 如果MACD 遇到下降的零线, if(NormalizeDouble( MACD_1, Digits + 1 ) < 0.0 && NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0) { //---- open a SELL position if(OrderSend( Symbol(), OP_SELL, 0.1, Bid, 5, 0.0, 0.0, "MACD_test", _MagicNumber, 0, Red ) < 0 ) { _GetLastError = GetLastError(); Alert( "错误 OrderSend 鈩?", _GetLastError ); return(-1); } return(0); } return(0); }
现在我们把代码块写成函数。这个函数能够在所有的定单中搜索出需要的,并将其信息记录在全局变量中,程序如下:
int _Ticket = 0, _Type = 0; double _Lots = 0.0, _OpenPrice = 0.0, _StopLoss = 0.0; double _TakeProfit = 0.0; datetime _OpenTime = -1; double _Profit = 0.0, _Swap = 0.0; double _Commission = 0.0; string _Comment = ""; datetime _Expiration = -1; void OneOrderInit( int magic ) { int _GetLastError, _OrdersTotal = OrdersTotal(); _Ticket = 0; _Type = 0; _Lots = 0.0; _OpenPrice = 0.0; _StopLoss = 0.0; _TakeProfit = 0.0; _OpenTime = -1; _Profit = 0.0; _Swap = 0.0; _Commission = 0.0; _Comment = ""; _Expiration = -1; for ( int z = _OrdersTotal - 1; z >= 0; z -- ) { if ( !OrderSelect( z, SELECT_BY_POS ) ) { _GetLastError = GetLastError(); Print("OrderSelect( ", z, ", SELECT_BY_POS ) -错误#", _GetLastError ); continue; } if(OrderMagicNumber() == magic && OrderSymbol() == Symbol()) { _Ticket = OrderTicket(); _Type = OrderType(); _Lots = NormalizeDouble( OrderLots(), 1 ); _OpenPrice = NormalizeDouble( OrderOpenPrice(), Digits); _StopLoss = NormalizeDouble( OrderStopLoss(), Digits); _TakeProfit = NormalizeDouble( OrderTakeProfit(), Digits); _OpenTime = OrderOpenTime(); _Profit = NormalizeDouble( OrderProfit(), 2 ); _Swap = NormalizeDouble( OrderSwap(), 2 ); _Commission = NormalizeDouble( OrderCommission(), 2 ); _Comment = OrderComment(); _Expiration = OrderExpiration(); return; } } }
如你所见,这非常简单: 一共 11 个变量,每个都储存仓位的相关信息(ticket #, type, lot size, 等等). 当函数开始运行时,这些变量被归零。作为全局变量这是必需的。函数被调用时变量也可以不归零,但我们需要的不是先前的信息,我们需要的是最近的。然后所有的仓位会以标准的方式被搜索,一旦获得需要的信号和MagicNumber 值,信息将被存储在相应的变量中。
现在我们将函数用到智能交易程序中:
extern int _MagicNumber = 1122; #include <OneOrderControl.mq4> int start() { int _GetLastError = 0; // 记住开仓的参量(如果可用) OneOrderInit( _MagicNumber ); //---- 记住指标值用作分析 double MACD_1 = iMACD(Symbol(), 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1 ); double MACD_2 = iMACD(Symbol(), 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 2 ); // 现在,代替在仓位中的搜索 // 存在开仓: if ( _Ticket > 0 ) { //----如果BUY 仓位开仓, if ( _Type == OP_BUY ) { //---- 如果MACD 遇到下降的零线, if(NormalizeDouble( MACD_1, Digits + 1 ) < 0.0 && NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0) { //---- 平仓 if(!OrderClose( _Ticket, _Lots, Bid, 5, Green)) { _GetLastError = GetLastError(); Alert( "错误 OrderClose 鈩?", _GetLastError); return(-1); } } // 如果信号没有改变,退出: // 开新仓位过早 else return(0); } //----如果 SELL 仓位开仓, if ( _Type == OP_SELL ) { //---- 如果MACD 遇到上升的零线 if(NormalizeDouble( MACD_1, Digits + 1 ) > 0.0 && NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0) { //---- 平仓 if(!OrderClose( _Ticket, _Lots, Ask, 5, Red)) { _GetLastError = GetLastError(); Alert( "错误 OrderClose 鈩?", _GetLastError); return(-1); } } // 如果信号没有改变,退出: // 开新仓位过早 else return(0); } } // 如果智能交易没有开仓 // ( _Ticket == 0 ) // 如果MACD 遇到上升的零线 if(NormalizeDouble( MACD_1, Digits + 1 ) > 0.0 && NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0) { //---- 开BUY 仓位 if(OrderSend(Symbol(), OP_BUY, 0.1, Ask, 5, 0.0, 0.0, "CrossMACD", _MagicNumber, 0, Green ) < 0) { _GetLastError = GetLastError(); Alert( "错误 OrderSend 鈩?", _GetLastError ); return(-1); } return(0); } //---- 如果MACD 遇到下降的零线 if ( NormalizeDouble( MACD_1, Digits + 1 ) < 0.0 && NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0 ) { //---- 开SELL仓位 if(OrderSend(Symbol(), OP_SELL, 0.1, Bid, 5, 0.0, 0.0, "CrossMACD", _MagicNumber, 0, Red ) < 0 ) { _GetLastError = GetLastError(); Alert( "错误 OrderSend 鈩?", _GetLastError ); return(-1); } return(0); } return(0); }
如你所见,这段智能交易的程序显得更紧凑更易读。这是一个简单例子。
我们需要一个更复杂的智能交易程序来实现一些其它的功能。此程序能够新建许多不同类型的仓位,并进行操作。以下是这种程序的规则:
程序如下:
extern int _MagicNumber = 1123; extern double Lot = 0.1; extern int StopLoss = 60; // ポイントにおけるストップロスまでの距離(0ーストップロスを無効にする) extern int TakeProfit = 100; // ポイントにおけるテイクプロフィットまでの距離(0ー無効にする) extern int TrailingStop = 50; // ポイントにおけるトレーリングストップのサイズ(0−無効にする) extern int Luft = 20; // 指値注文の設定レベルまでの距離 int start() { // 各タイプの注文のチケットを記憶する変数 int BuyStopOrder = 0, SellStopOrder = 0, BuyOrder = 0, SellOrder = 0; int _GetLastError = 0, _OrdersTotal = OrdersTotal(); // 全ての開いているポジションを取捨し、 // どのタイプのポジションがすでに開いているかを記憶します: for ( int z = _OrdersTotal - 1; z >= 0; z -- ) { //もしポジション選択時にエラーが出た場合、次に移ります if ( !OrderSelect( z, SELECT_BY_POS ) ) { _GetLastError = GetLastError(); Print("OrderSelect( ", z, ", SELECT_BY_POS ) - Error #", _GetLastError ); continue; } // もしポジションが現在のツールで開いていない場合、スキップします if ( OrderSymbol() != Symbol() ) continue; // もしMagicNumberが_MagicNumberと等しくない場合、このポジションをスキップします if ( OrderMagicNumber() != _MagicNumber ) continue; // ポジションタイプによって変数の値を変えます: switch ( OrderType() ) { case OP_BUY: BuyOrder = OrderTicket(); break; case OP_SELL: SellOrder = OrderTicket(); break; case OP_BUYSTOP: BuyStopOrder = OrderTicket(); break; case OP_SELLSTOP: SellStopOrder = OrderTicket(); break; } } //---- もし両方の指値注文がある場合、終了します //---- そのうちの1つが作動するまで待つ必要があります if ( BuyStopOrder > 0 && SellStopOrder > 0 ) return(0); // 二度目の全ての開いているポジションの取捨をします // ここではこれらを使います: _OrdersTotal = OrdersTotal(); for ( z = _OrdersTotal - 1; z >= 0; z -- ) { //もしポジション選択時にエラーが出た場合、 // 次に移ります if ( !OrderSelect( z, SELECT_BY_POS ) ) { _GetLastError = GetLastError(); Print("OrderSelect( ", z, ", SELECT_BY_POS ) - Error #", _GetLastError ); continue; } // もしポジションが現在のツールで開いていない場合、スキップします if ( OrderSymbol() != Symbol() ) continue; // もしMagicNumberが_MagicNumberと等しくない場合、このポジションをスキップします if ( OrderMagicNumber() != _MagicNumber ) continue; // ポジションタイプによって変数の値を変えます: switch ( OrderType() ) { //---- もし開いている買いポジションがある場合、 case OP_BUY: { //---- もしセルストップがまだ削除されていない場合、これを削除します: if ( SellStopOrder > 0 ) { if ( !OrderDelete( SellStopOrder ) ) { Alert( "OrderDelete Error #", GetLastError() ); return(-1); } } //---- ストップロスを移動する必要があるかをチェックしましょう: //---- もしトレーリングストップのサイズがあまり小さくない場合、 if(TrailingStop > MarketInfo( Symbol(), MODE_STOPLEVEL)) { //---- もしポジションの利益はTrailingStopポイントよりも大きい場合、 if(NormalizeDouble( Bid - OrderOpenPrice(), Digits) > NormalizeDouble( TrailingStop*Point, Digits)) { // もし新しいストップロスレベルが、 // 今のポジションのものよりも高い場合 // (もしくは、ポジションにストップロスがない場合)、 if(NormalizeDouble(Bid - TrailingStop*Point, Digits) > OrderStopLoss() || OrderStopLoss() <= 0.0 ) { //---- 注文を修正します if(!OrderModify( OrderTicket(), OrderOpenPrice(), NormalizeDouble(Bid - TrailingStop*Point,Digits), OrderTakeProfit(), OrderExpiration() ) ) { Alert("OrderModify Error #", GetLastError()); return(-1); } } } } // もしオープンポジションがある場合、終了します // これ以上することはありません return(0); } // 次のブロックは完全に // 買いポジションの処理ブロックと同じです // そのためこれに対するコメントは付けられていません case OP_SELL: { if ( BuyStopOrder > 0 ) { if ( !OrderDelete( BuyStopOrder ) ) { Alert("OrderDelete Error #", GetLastError() ); return(-1); } } if(TrailingStop > MarketInfo( Symbol(), MODE_STOPLEVEL)) { if(NormalizeDouble( OrderOpenPrice() - Ask, Digits) > NormalizeDouble(TrailingStop*Point, Digits)) { if(NormalizeDouble(Ask + TrailingStop*Point, Digits ) < OrderStopLoss() || OrderStopLoss() <= 0.0 ) { if(!OrderModify( OrderTicket(), OrderOpenPrice(), NormalizeDouble(Ask + TrailingStop*Point, Digits), OrderTakeProfit(), OrderExpiration())) { Alert("OrderModify Error #", GetLastError() ); return(-1); } } } } return(0); } } } //+------------------------------------------------------------------+ //| もし実行がこの場所に到達した場合、それは指値注文や| //| 開いているポジションがないということ | //+------------------------------------------------------------------+ //---- バイストップやセルストップを設定します: double _OpenPriceLevel, _StopLossLevel, _TakeProfitLevel; _OpenPriceLevel = NormalizeDouble( Ask + Luft*Point, 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; } if(OrderSend(Symbol(), OP_BUYSTOP, Lot, _OpenPriceLevel, 5, _StopLossLevel, _TakeProfitLevel, "", _MagicNumber ) < 0 ) { Alert( "OrderSend Error #", GetLastError() ); return(-1); } _OpenPriceLevel = NormalizeDouble( Bid - Luft*Point, 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; } if ( OrderSend ( Symbol(), OP_SELLSTOP, Lot, _OpenPriceLevel, 5, _StopLossLevel, _TakeProfitLevel, "", _MagicNumber ) < 0 ) { Alert( "OrderSend Error #", GetLastError() ); return(-1); } return(0); }
现在让我们写出可以简化控制建仓代码的函数,它必须用每个类型的定单进行搜索,然后将这些信息存储在全局变量里,程序如下:
// 在定单特性中的整体变量会被储存: int _BuyTicket = 0, _SellTicket = 0, _BuyStopTicket = 0; int _SellStopTicket = 0, _BuyLimitTicket = 0, _SellLimitTicket = 0; double _BuyLots = 0.0, _SellLots = 0.0, _BuyStopLots = 0.0; double _SellStopLots = 0.0, _BuyLimitLots = 0.0, _SellLimitLots = 0.0; double _BuyOpenPrice = 0.0, _SellOpenPrice = 0.0, _BuyStopOpenPrice = 0.0; double _SellStopOpenPrice = 0.0, _BuyLimitOpenPrice = 0.0, _SellLimitOpenPrice = 0.0; double _BuyStopLoss = 0.0, _SellStopLoss = 0.0, _BuyStopStopLoss = 0.0; double _SellStopStopLoss = 0.0, _BuyLimitStopLoss = 0.0, _SellLimitStopLoss = 0.0; double _BuyTakeProfit = 0.0, _SellTakeProfit = 0.0, _BuyStopTakeProfit = 0.0; double _SellStopTakeProfit = 0.0, _BuyLimitTakeProfit = 0.0, _SellLimitTakeProfit = 0.0; datetime _BuyOpenTime = -1, _SellOpenTime = -1, _BuyStopOpenTime = -1; datetime _SellStopOpenTime = -1, _BuyLimitOpenTime = -1, _SellLimitOpenTime = -1; double _BuyProfit = 0.0, _SellProfit = 0.0, _BuySwap = 0.0, _SellSwap = 0.0; double _BuyCommission = 0.0, _SellCommission = 0.0; string _BuyComment = "", _SellComment = "", _BuyStopComment = ""; string _SellStopComment = "", _BuyLimitComment = "", _SellLimitComment = ""; datetime _BuyStopExpiration = -1, _SellStopExpiration = -1; datetime _BuyLimitExpiration = -1, _SellLimitExpiration = -1; void OneTypeOrdersInit( int magic ) { // 变量归零: _BuyTicket = 0; _SellTicket = 0; _BuyStopTicket = 0; _SellStopTicket = 0; _BuyLimitTicket = 0; _SellLimitTicket = 0; _BuyLots = 0.0; _SellLots = 0.0; _BuyStopLots = 0.0; _SellStopLots = 0.0; _BuyLimitLots = 0.0; _SellLimitLots = 0.0; _BuyOpenPrice = 0.0; _SellOpenPrice = 0.0; _BuyStopOpenPrice = 0.0; _SellStopOpenPrice = 0.0; _BuyLimitOpenPrice = 0.0; _SellLimitOpenPrice = 0.0; _BuyStopLoss = 0.0; _SellStopLoss = 0.0; _BuyStopStopLoss = 0.0; _SellStopStopLoss = 0.0; _BuyLimitStopLoss = 0.0; _SellLimitStopLoss = 0.0; _BuyTakeProfit = 0.0; _SellTakeProfit = 0.0; _BuyStopTakeProfit = 0.0; _SellStopTakeProfit = 0.0; _BuyLimitTakeProfit = 0.0; _SellLimitTakeProfit = 0.0; _BuyOpenTime = -1; _SellOpenTime = -1; _BuyStopOpenTime = -1; _SellStopOpenTime = -1; _BuyLimitOpenTime = -1; _SellLimitOpenTime = -1; _BuyProfit = 0.0; _SellProfit = 0.0; _BuySwap = 0.0; _SellSwap = 0.0; _BuyCommission = 0.0; _SellCommission = 0.0; _BuyComment = ""; _SellComment = ""; _BuyStopComment = ""; _SellStopComment = ""; _BuyLimitComment = ""; _SellLimitComment = ""; _BuyStopExpiration = -1; _SellStopExpiration = -1; _BuyLimitExpiration = -1; _SellLimitExpiration = -1; int _GetLastError = 0, _OrdersTotal = OrdersTotal(); for ( int z = _OrdersTotal - 1; z >= 0; z -- ) { if ( !OrderSelect( z, SELECT_BY_POS ) ) { _GetLastError = GetLastError(); Print("OrderSelect(", z, ",SELECT_BY_POS) - Error #", _GetLastError ); continue; } if ( OrderMagicNumber() == magic && OrderSymbol() == Symbol() ) { switch ( OrderType() ) { case OP_BUY: _BuyTicket = OrderTicket(); _BuyLots = NormalizeDouble( OrderLots(), 1 ); _BuyOpenPrice = NormalizeDouble( OrderOpenPrice(), Digits ); _BuyStopLoss = NormalizeDouble( OrderStopLoss(), Digits ); _BuyTakeProfit = NormalizeDouble( OrderTakeProfit(), Digits ); _BuyOpenTime = OrderOpenTime(); _BuyProfit = NormalizeDouble( OrderProfit(), 2 ); _BuySwap = NormalizeDouble( OrderSwap(), 2 ); _BuyCommission = NormalizeDouble( OrderCommission(), 2 ); _BuyComment = OrderComment(); break; case OP_SELL: _SellTicket = OrderTicket(); _SellLots = NormalizeDouble( OrderLots(), 1 ); _SellOpenPrice = NormalizeDouble( OrderOpenPrice(), Digits ); _SellStopLoss = NormalizeDouble( OrderStopLoss(), Digits ); _SellTakeProfit = NormalizeDouble( OrderTakeProfit(), Digits ); _SellOpenTime = OrderOpenTime(); _SellProfit = NormalizeDouble( OrderProfit(), 2 ); _SellSwap = NormalizeDouble( OrderSwap(), 2 ); _SellCommission = NormalizeDouble( OrderCommission(), 2 ); _SellComment = OrderComment(); break; case OP_BUYSTOP: _BuyStopTicket = OrderTicket(); _BuyStopLots = NormalizeDouble( OrderLots(), 1 ); _BuyStopOpenPrice = NormalizeDouble( OrderOpenPrice(), Digits ); _BuyStopStopLoss = NormalizeDouble( OrderStopLoss(), Digits ); _BuyStopTakeProfit = NormalizeDouble( OrderTakeProfit(), Digits ); _BuyStopOpenTime = OrderOpenTime(); _BuyStopComment = OrderComment(); _BuyStopExpiration = OrderExpiration(); break; case OP_SELLSTOP: _SellStopTicket = OrderTicket(); _SellStopLots = NormalizeDouble( OrderLots(), 1 ); _SellStopOpenPrice = NormalizeDouble( OrderOpenPrice(), Digits ); _SellStopStopLoss = NormalizeDouble( OrderStopLoss(), Digits ); _SellStopTakeProfit = NormalizeDouble( OrderTakeProfit(), Digits ); _SellStopOpenTime = OrderOpenTime(); _SellStopComment = OrderComment(); _SellStopExpiration = OrderExpiration(); break; case OP_BUYLIMIT: _BuyLimitTicket = OrderTicket(); _BuyLimitLots = NormalizeDouble( OrderLots(), 1 ); _BuyLimitOpenPrice = NormalizeDouble( OrderOpenPrice(), Digits ); _BuyLimitStopLoss = NormalizeDouble( OrderStopLoss(), Digits ); _BuyLimitTakeProfit = NormalizeDouble( OrderTakeProfit(), Digits ); _BuyLimitOpenTime = OrderOpenTime(); _BuyLimitComment = OrderComment(); _BuyLimitExpiration = OrderExpiration(); break; case OP_SELLLIMIT: _SellLimitTicket = OrderTicket(); _SellLimitLots = NormalizeDouble( OrderLots(), 1 ); _SellLimitOpenPrice = NormalizeDouble( OrderOpenPrice(), Digits ); _SellLimitStopLoss = NormalizeDouble( OrderStopLoss(), Digits ); _SellLimitTakeProfit = NormalizeDouble( OrderTakeProfit(), Digits ); _SellLimitOpenTime = OrderOpenTime(); _SellLimitComment = OrderComment(); _SellLimitExpiration = OrderExpiration(); break; } } } }
现在我们将函数用到智能交易程序中:
extern int _MagicNumber = 1123; extern double Lot = 0.1; extern int StopLoss = 60; // 止损点的间距(0 - d无) extern int TakeProfit = 100; // 赢利点的间距 (0 - 无) extern int TrailingStop = 50; //追踪止损点 (0 - 无) extern int Luft = 20; // 挂单交易放置水平的间距 #include <OneTypeOrdersControl.mq4> int start() { int _GetLastError = 0; //---- 记住开仓的参量(如果可用) OneTypeOrdersInit( _MagicNumber ); //---- 如果我们两个都是挂单交易,退出 //---- 等待他们开启 if ( _BuyStopTicket > 0 && _SellStopTicket > 0 ) return(0); //---- 如果 BUY 仓位开仓 if ( _BuyTicket > 0 ) { //---- 如果SellStop 还没有删除,删除它: if ( _SellStopTicket > 0 ) { if ( !OrderDelete( _SellStopTicket ) ) { Alert( "OrderDelete 错误#", GetLastError() ); return(-1); } } //---- 检测止损被移动: //---- 如果追踪止损不是很小, if ( TrailingStop > MarketInfo( Symbol(), MODE_STOPLEVEL ) ) { //---- 如果赢利仓位超过追踪止损点, if ( NormalizeDouble( Bid - _BuyOpenPrice, Digits ) > NormalizeDouble( TrailingStop*Point, Digits ) ) { //---- 如果新止损水平超过当前仓位 //---- (或者当前仓位没有止损), if(NormalizeDouble( Bid - TrailingStop*Point, Digits ) > _BuyStopLoss || _BuyStopLoss <= 0.0 ) { //---- 修改定单 if ( !OrderModify( _BuyTicket, _BuyOpenPrice, NormalizeDouble( Bid - TrailingStop*Point, Digits ), _BuyTakeProfit, 0 ) ) { Alert( "OrderModify 错误#", GetLastError() ); return(-1); } } } } //---- 如果没有开仓仓位,退出,无事可做 return(0); } //---- 这个单元格与BUY仓位的单元格相似 //---- 这就是我们不能做标注的原因... if ( _SellTicket > 0 ) { if ( _BuyStopTicket > 0 ) { if ( !OrderDelete( _BuyStopTicket ) ) { Alert( "OrderDelete错误 #", GetLastError() ); return(-1); } } if(TrailingStop > MarketInfo( Symbol(), MODE_STOPLEVEL)) { if(NormalizeDouble( _SellOpenPrice - Ask, Digits ) > NormalizeDouble( TrailingStop*Point, Digits ) ) { if(NormalizeDouble( Ask + TrailingStop*Point, Digits ) < _SellStopLoss || _SellStopLoss <= 0.0 ) { if(!OrderModify( _SellTicket, _SellOpenPrice, NormalizeDouble( Ask + TrailingStop*Point, Digits ), _SellTakeProfit, 0 ) ) { Alert( "OrderModify Error #", GetLastError() ); return(-1); } } } } return(0); } //+------------------------------------------------------------------+ //| 如果执行达到此点, | //| 说明没有挂单和开仓。 | //+------------------------------------------------------------------+ //---- 放置 BuyStop 和 SellStop: double _OpenPriceLevel, _StopLossLevel, _TakeProfitLevel; _OpenPriceLevel = NormalizeDouble( Ask + Luft*Point, 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; if(OrderSend ( Symbol(), OP_BUYSTOP, Lot, _OpenPriceLevel, 5, _StopLossLevel, _TakeProfitLevel, "", _MagicNumber ) < 0) { Alert( "OrderSend Error #", GetLastError() ); return(-1); } _OpenPriceLevel = NormalizeDouble( Bid - Luft*Point, 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; if(OrderSend ( Symbol(), OP_SELLSTOP, Lot, _OpenPriceLevel, 5, _StopLossLevel, _TakeProfitLevel, "", _MagicNumber ) < 0 ) { Alert( "OrderSend 错误 #", GetLastError() ); return(-1); } return(0); }
现在需要有足够的变量来存储定单的信息,为此我们可以创建一些数组来实现这个目的。鉴于此,这个程序的功能将几乎和前面一样:
让我们立即开始编写该函数:
// 智能交易的全部定单总量变量将会存储: int _ExpertOrdersTotal = 0; // 定单特性的数组将会被存储: int _OrderTicket[], _OrderType[]; double _OrderLots[], _OrderOpenPrice[], _OrderStopLoss[], _OrderTakeProfit[]; double _OrderProfit[], _OrderSwap[], _OrderCommission[]; datetime _OrderOpenTime[], _OrderExpiration[]; string _OrderComment[]; void AllOrdersInit( int magic ) { int _GetLastError = 0, _OrdersTotal = OrdersTotal(); // 按照当前仓位总数改变数组的大小 // (if _OrdersTotal = 0, 改变数组总数为 1) int temp_value = MathMax( _OrdersTotal, 1 ); ArrayResize( _OrderTicket, temp_value ); ArrayResize( _OrderType, temp_value ); ArrayResize( _OrderLots, temp_value ); ArrayResize( _OrderOpenPrice, temp_value ); ArrayResize( _OrderStopLoss, temp_value ); ArrayResize( _OrderTakeProfit, temp_value ); ArrayResize( _OrderOpenTime, temp_value ); ArrayResize( _OrderProfit, temp_value ); ArrayResize( _OrderSwap, temp_value ); ArrayResize( _OrderCommission, temp_value ); ArrayResize( _OrderComment, temp_value ); ArrayResize( _OrderExpiration, temp_value ); // zeroize the arrays ArrayInitialize( _OrderTicket, 0 ); ArrayInitialize( _OrderType, 0 ); ArrayInitialize( _OrderLots, 0 ); ArrayInitialize( _OrderOpenPrice, 0 ); ArrayInitialize( _OrderStopLoss, 0 ); ArrayInitialize( _OrderTakeProfit, 0 ); ArrayInitialize( _OrderOpenTime, 0 ); ArrayInitialize( _OrderProfit, 0 ); ArrayInitialize( _OrderSwap, 0 ); ArrayInitialize( _OrderCommission, 0 ); ArrayInitialize( _OrderExpiration, 0 ); _ExpertOrdersTotal = 0; for ( int z = _OrdersTotal - 1; z >= 0; z -- ) { if ( !OrderSelect( z, SELECT_BY_POS ) ) { _GetLastError = GetLastError(); Print("OrderSelect(", z, ",SELECT_BY_POS) -错误 #", _GetLastError ); continue; } if ( OrderMagicNumber() == magic && OrderSymbol() == Symbol() ) { // 填数组 _OrderTicket[_ExpertOrdersTotal] = OrderTicket(); _OrderType[_ExpertOrdersTotal] = OrderType(); _OrderLots[_ExpertOrdersTotal] = NormalizeDouble( OrderLots(), 1 ); _OrderOpenPrice[_ExpertOrdersTotal] = NormalizeDouble( OrderOpenPrice(), Digits ); _OrderStopLoss[_ExpertOrdersTotal] = NormalizeDouble( OrderStopLoss(), Digits ); _OrderTakeProfit[_ExpertOrdersTotal] = NormalizeDouble( OrderTakeProfit(), Digits ); _OrderOpenTime[_ExpertOrdersTotal] = OrderOpenTime(); _OrderProfit[_ExpertOrdersTotal] = NormalizeDouble( OrderProfit(), 2 ); _OrderSwap[_ExpertOrdersTotal] = NormalizeDouble( OrderSwap(), 2 ); _OrderCommission[_ExpertOrdersTotal] = NormalizeDouble( OrderCommission(), 2 ); _OrderComment[_ExpertOrdersTotal] = OrderComment(); _OrderExpiration[_ExpertOrdersTotal] = OrderExpiration(); _ExpertOrdersTotal++; } } // 按照智能交易所属仓位的总量改变数组的大小 // (if _ExpertOrdersTotal = 0, 改变数组大小为 1) temp_value = MathMax( _ExpertOrdersTotal, 1 ); ArrayResize( _OrderTicket, temp_value ); ArrayResize( _OrderType, temp_value ); ArrayResize( _OrderLots, temp_value ); ArrayResize( _OrderOpenPrice, temp_value ); ArrayResize( _OrderStopLoss, temp_value ); ArrayResize( _OrderTakeProfit, temp_value ); ArrayResize( _OrderOpenTime, temp_value ); ArrayResize( _OrderProfit, temp_value ); ArrayResize( _OrderSwap, temp_value ); ArrayResize( _OrderCommission, temp_value ); ArrayResize( _OrderComment, temp_value ); ArrayResize( _OrderExpiration, temp_value ); }
代码相当简单:
extern int _MagicNumber = 0; #include AllOrdersControl.mq4> int start() { AllOrdersInit( _MagicNumber ); if ( _ExpertOrdersTotal > 0 ) { string OrdersList = StringConcatenate(Symbol(), ", MagicNumber ", _MagicNumber, ":\n"); for ( int n = 0; n _ExpertOrdersTotal; n ++ ) { OrdersList = StringConcatenate( OrdersList, "Order # ", _OrderTicket[n], ", profit/loss: ", DoubleToStr( _OrderProfit[n], 2 ), " ", AccountCurrency(), "\n" ); } Comment( OrdersList ); } return(0); }
最后,我想来比较一下使用函数与否在搜索定单时的速度。为此,我们用相同的版本来连续测试 "Every tick" 模式10次(用_MagicNumber最优化),用 MetaTrader 软件来计算时间 — 时间时自己计算的。
结果如下:智能交易 |
10 测试的时间 (mm:ss) |
CrossMACD_beta (不包含函数) |
07:42 |
CrossMACD | 11:37 |
DoublePending_beta (不包含函数) |
08:18 |
DoublePending | 09:42 |
正如你的表格里看到的,使用函数的智能交易程序稍稍慢了一点,这作为使源代码简单易懂的代价,应该还算合理。
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...