保宁皂几个味道:简单的订单管理-2

来源:百度文库 编辑:中财网 时间:2024/04/27 22:05:28
简单的订单管理-002
2009-07-13 00:46
//+------------------------------------------------------------------+
//| 如果执行达到此点, |
//| 说明没有挂单和开仓。 |
//+------------------------------------------------------------------+
//---- 放置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 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
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);
}
最初的和修改后的程序之间的不同是非常明显的 — 控制建仓的代码块变得更简单易懂。
现在轮到最复杂的智能交易程序了,它允许在同一时间无限制的新建多个仓位。
4. 控制所有仓位
现在需要有足够的变量来存储定单的信息,为此我们可以创建一些数组来实现这个目的。鉴于此,这个程序的功能将几乎和前面一样:
开始时所有的数组归零; 在所有的定单里搜索,找到符合需要的信号和MagicNumber值后,将这些信息存储在数组中; 为了使可用性更强,必须添加一个全局变量来记录智能交易程序的定单个数 — 这在访问数组时会很有用。
让我们立即开始编写该函数:
// 智能交易的全部定单总量变量将会存储:
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);
}
如果 _MagicNumber 设为 0, 智能交易程序将显示手动建仓的列表:

5. 总结
最后,我想来比较一下使用函数与否在搜索定单时的速度。为此,我们用相同的版本来连续测试 “Every tick” 模式10次(用_MagicNumber最优化),用 MetaTrader 软件来计算时间 — 时间时自己计算的。
结果如下:
智能交易
10 测试的时间 (mm:ss)
CrossMACD_beta
(不包含函数)07:42
CrossMACD11:37
DoublePending_beta
(不包含函数)08:18
DoublePending09:42
正如你的表格里看到的,使用函数的智能交易程序稍稍慢了一点,这作为使源代码简单易懂的代价,应该还算合理。
无论如何,每个人都有是否使用函数的自由。