手机版

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

阅读 :
外_汇_邦 WaiHuiBang.com

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

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

2. 一个仓位

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

举一个简单的例子,一个来自于 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);
}


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

现在让我们解决下一个任务。

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

外_汇_邦 WaiHuiBang.com
本文标题:外汇EA:简单的订单管理(一) - MT4平台MQL4编程学习
本文地址:https://www.waihuibang.com/fxschool/autotrading/mql4/40634.html

相关文章

  • MT4中有哪些常用的快捷键?
    MT4中有哪些常用的快捷键?

    MT4是市场行情接收软件,由迈达克软件公司发布,提供免费试用,那么,MT4中有哪些常用的快捷键? Ctrl+M - 市场报价Ctrl+N - 导航Ctrl+T - 帐号终端Ctrl+D - 数据窗口Ctrl+G - 网格Ctrl+L - 成交量Ctrl+O - 选项Ctrl+F -...

    MQL4编程学习
  • MT4编程初级手册(7):条件判断语句

    一、if判断语句 if判断语句很常用,使用起来也比较简单。 规则:如果小括号中的条件成立则执行大括号中的语句;如果不成立则跳过大括号,执行后面的语句。 例如: if(condition==1){ a=b+1; } 我们在编写报警指标的...

    MQL4编程学习
  • 关于金融智能(EA)交易的使用

      我们经过编写评测、逆向分析、反编译千款智能交易EA后,发现评测及使用金融智能EA需要注意以下几点:   EA的视觉偏差:   人体通过视觉所观测的事物是立体化、多样化的,能达到“所见即所得”的状态,而计算机语言...

    MQL4编程学习
  • MQL编程时循环结构中break、continue、return和exit的区别
    MQL编程时循环结构中break、continue、return和exit的区别

    break语句的使用场合主要是switch语句和循环结构。在循环结构中使用break语句,如果执行了break语句,那么就退出循环,接着执行循环结构下面的第一条语句。如果在多重嵌套循环中使用break语句,当执行break语句的时候,退出的是它所在的循环结构,对外层循环没有任何影响。如果循环结构里有switch语句,并且在switch语句中使用了break语句,当执行switch语句中的break语句时,仅退出switch语句,不会退出外面的循环结构。通过图3-17,读者可以很直观地了解break语句的使...

    MQL4编程学习
  • 外汇EA智能交易软件是什么东西?

    一、外汇EA软件是什么? 答:智能交易系统软件的全称是Expert Advisor,简称EA,是一个全自动的交易工具,智能交易系统软件是用来对交易过程完全自动化,免除交易商连续对市场进行日常烦琐的监护,也免除交易员的盯盘操作。许多...

    MQL4编程学习
你可能感兴趣