您现在的位置: 比特财富网 >> 财经 >  >> 外匯
外匯EA:簡單的訂單管理(一)
外_匯_邦 WaiHuiBang.com

1. 介紹
每個智能交易程序裡都有一段代碼是控制建倉的。www.emoneybtc.com它在所有的定單中不斷搜索,通過信息選擇倉位,然後進行修改和關閉。這段代碼看上去都差不多,並且往往具有相同的功能。這就是為什麼這段經常被重復的代碼可以從程序中提取出來成為函數,從而使程序更易寫更簡潔。首先,我們按功能把任務分成三個步驟 — 這三個步驟其實是三種智能交易程序:

[*]智能交易程序在同一時間只能新建一個倉位[*]智能交易程序在同一時間可以新建每個類型的一個倉位(比如, 多頭和空頭的倉位)[*]智能交易程序可以同時新建多個倉位

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
  • 上一个财经:
  • 下一个财经:
    • 解析止損重要性及做法

      止損是在外匯交易過程中自然產生的,並非刻意做作,它是投資者保護自己的一種本能反應,是在外匯交易中保護自己的重要手段。其最終的目的是保存實力,

    • 博時合惠貨幣A和余額寶哪個好?穩健理財產品的超強對決!

      博時合惠貨幣A在支付寶財富中的基金中可以買到,這款產品是在2017年7月1日上線支付寶的,那麼,博時合惠貨幣A和余額寶哪個好?同樣

    • 趨勢投資者善用“喚醒效應”來賺錢

        希臘遭遇金融危機時,整個投資市場都處於恐慌情緒中。2012年10月,兩家大公司突然宣布將設在希臘的區域總部搬至其他國家,頓時

    • 美團優選自提點怎麼申請?

      最佳答案: 美團優選自提點申請方法非常簡單,只需要通過微信小程序或者美團官網提交申請就可以了,需要的

    • 如何省錢辦婚禮?

      最佳答案: 在辦婚禮的時候想要省錢,可以在三個方面做嘗試:1、在舉辦婚禮的時候,避開五月到十月份,因

      風險提示:比特財富網的各種信息資料僅供參考,不構成任何投資建議,不對任何交易提供任何擔保,亦不構成任何邀約,不作為任何法律文件,投資人據此進行投資交易而產生的後果請自行承擔,本網站不承擔任何責任,理財有風險,投資需謹慎。
    比特財富網 版權所有 © www.emoneybtc.com