首页学院交易策略EA智能交易文章详细

外汇EA:简单的订单管理(一)

外汇网2021-06-17 09:42:20 75
汇外网 - 全球专业的黄金外汇门户导航行情资讯网站

1. 介绍

每个智能交易程序里都有一段代码是控制建仓的。它在所有的定单中持续搜索,通过信息选择仓位,然后执行修改和关闭。这段代码看上去都差不多,而且往往具有相同的功能。这就是为何这段经常被重复的代码可以从程序中提取出来形成函数,进而使程序更易写更简洁。首先,我们按功能把任务分成三个步骤 — 这三个步骤其实是三种智能交易程序:

[*]智能交易程序在与一时间只能新建一个仓位[*]智能交易程序在与一时间可以新建每个类型的一个仓位(比如, 多头和空头的仓位)[*]智能交易程序可以同期新建多个仓位

2. 一个仓位

只新建一个仓位有很多中策略。该种控制代码块非常简单,但写出来也会耗费适当的时间和精力。

举一个简单的例子,一个来自于 MACD 线交叉点(信号线和基础线)的建仓信号,简化它的控制代码块,程序如下: 复制代码

extern int _MagicNumber = 1122;

int start()

{

//---- 记住指标值做分析报告

double MACD_1 = iMACD(Symbol(), 0, 12, 26, 9, PR洲际交易所_CLOSE,

MODE_MAIN, 1 );

double MACD_2 = iMACD(Symbol(), 0, 12, 26, 9, PR洲际交易所_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

int start()

{

int _GetLastError = 0;

// 记住开仓的参数(假使可用)

OneOrderInit( _MagicNumber );

//---- 记住指标值用作分析

double MACD_1 = iMACD(Symbol(), 0, 12, 26, 9, PR洲际交易所_CLOSE,

MODE_MAIN, 1 );

double MACD_2 = iMACD(Symbol(), 0, 12, 26, 9, PR洲际交易所_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);

}

如你所见,这段智能交易的程序显得更紧凑更易读。这是一个简单例子。

当下让我们处理下一个任务。

3. 每个类型的一个仓位

我们需要一个更复杂的智能交易程序来达到一部分其它的功能。此程序能够新建很多不同类型的仓位,并执行操作。下方是该种程序的规则:

[*]该程序运行时将设置两个待办定单: 在出售价+20点设置购入止损,在购入价+20点设置出售止损;[*]当一个定单导致,其他务必被取消;[*]建仓务必伴随跟踪止损;[*]当仓位受于止损或盈利被关闭后,将被又一次起步,也就是说两个待办定单将被设置。

程序如下:复制代码

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;

}

}

//---- 假使我们有两个挂单交易,退出

//---- 等候他们开启

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) - 错误 #/",

_GetLastError );

continue;

}

// 假使对于目前的货币对没有开仓

// 忽视它

if ( OrderSymbol() != Symbol() ) continue;

// 假使 MagicNumber 不等于 _MagicNumber,

// 忽视这个仓位

if ( OrderMagicNumber() != _MagicNumber ) continue;

// 取决于仓位的类型,

// 更改变量值:

switch ( OrderType() )

{

//----假使BUY仓位开仓,

case OP_BUY:

{

// 假使 SellStop定单还没有删除,

// 删除:

if ( SellStopOrder > 0 )

{

if ( !OrderDelete( SellStopOrder ) )

{

Alert(OrderDelete Error #/", GetLastError());

return(-1);

}

}

// 检测止损被移动:

// 假使跟踪止损的大小不是很小,

if(TrailingStop > MarketInfo( Symbol(),

MODE_STOPLEVEL ) )

{

// 假使赢利点胜过跟踪止损点,

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 错误 #/",

GetLastError());

return(-1);

}

}

}

}

// 假使没有开仓仓位,退出

// 无事可做

return(0);

}

// 下一个单元格与BUY 仓位的单元个一样

// 这就是我们不能在单元格上标注的原因...

case OP_SELL:

{

if ( BuyStopOrder > 0 )

{

if ( !OrderDelete( BuyStopOrder ) )

{

Alert(/"OrderDelete 错误 #/",

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);

}

}

}

//+------------------------------------------------------------------+

//| 假使实施高达此点, |

//| 表明没有挂单和开仓。 |

//+------------------------------------------------------------------+

//---- 放置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);

}

标签:

随机快审展示
加入快审,优先展示

加入VIP