外_匯_邦 WaiHuiBang.com
一、均線穿越交易系統EA詳解MT4平台自帶了一個自動交易的EA指標,那就是Moving Average ,下面詳細解釋該系統每條語句的功能說明,以便深入認識EA的編程內核。www.emoneybtc.com
//+-----------------------------------------------------------------------------+
//| Moving Average.mq4 |
//| Copyright 2005-2014, MetaQuotes Software Corp. |
//| http://www.mql4.com |
//+-----------------------------------------------------------------------------+
#property copyright "2005-2014, MetaQuotes Software Corp."
#property link "http://www.mql4.com"
#property description "Moving Average sample expert advisor"
#define MAGICMA 20131111
// 宏定義命令#define用法,定義本EA操作的訂單的唯一標識號碼,由此可以實現在同一賬戶上多系統操作,各操作EA的訂單標識碼不同,就不會互相誤操作。凡是EA皆不可缺少,非常非常重要!
//--- Inputs
input double Lots =0.1; // 每單的交易量
input double MaximumRisk =0.02; // 本系統最大風險系數,即可以動用總資金的2%
input double DecreaseFactor=3; // 下跌因子
input int MovingPeriod =12; // 均線的計算周期=12,為MA必須的參數之一
input int MovingShift =6; // 均線轉移量=6,為MA必須的參數之一
// input 確定從外部程序輸入的變量, 會直接顯現輸入數據窗口。數列本身不能作為外部變量。
注意:iMA中的MovingShift(均線偏移量)是指均線指標在圖上繪制時向左、右移動的K線個數,主要為了使圖中結果更好看,並不會對MA的計算數值產生變化。其中,該參數為正時,代表向右移動;為負值,則代表向左移動。
//+------------------------------------------------------------------+
//| Calculate open positions |
//| 自定義函數(返回-整數型數據) 倉單查詢與統計 |
//+------------------------------------------------------------------+
int CalculateCurrentOrders(string symbol) // 函數作用:計算當前持倉單的數量
{
int buys=0,sells=0;
// 定義兩個局部變量,整數型,buys——多單數,sells——空單數,用於訂單的統計
//----
for(int i=0;i<OrdersTotal();i++) // 計次循環(i=0至訂單數目,i=i+1)- 循環檢測當前的訂單隊列
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break; // 如果 沒有本系統交易的倉單類型,則跳出循環
if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA) //如果持倉單貨幣對是當前貨幣對 且持倉單編號是本系統編號時判斷這個訂單是不是當前EA操作的,避免EA誤操作其他程序控制的持倉單。
{
if(OrderType()==OP_BUY) buys++; // 如果 倉單類型=多單,則:在多單數上加1;
if(OrderType()==OP_SELL) sells++; // 如果 倉單類型=空單,則,在空單數上加1。
}
}
// ---- return orders volume-返回訂單數目
if(buys>0) return(buys); // 如果 多單>0,則返回(多單數)
else return(-sells); // 否則,返回(-空單數)
// 本函數返回查詢計算結束時的持倉單的個數,這種模式返回是假設不存在鎖單的。
}
//+------------------------------------------------------------------+
//| Calculate optimal lot size |
//| 自定義函數(返回-小數型數據) 資金管理 |
//+------------------------------------------------------------------+
double LotsOptimized() //開倉量計算函數(根據要求計算出訂單交易量,小數型)
{
double lot=Lots; // 定義局部變量los 小數型
int orders=HistoryTotal(); // history orders total 歷史平倉單數(已平倉)
int losses=0; // number of losses orders without a break-虧損單
//---- select lot size
lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/1000.0,1);
//計算 開倉下單量=帳戶可用資金*最大風險系數(=2%)/1000.0,並將結果保留小數點1位
(通過風險系數的計算獲得當前入場單應該采用的交易量,除以1000是因為大多貨幣對匯價都在這個附近。)
//---- calcuulate number of losses orders without a break-計算虧損單數目
if(DecreaseFactor>0) // 如果 下跌因子(=3)>0
{
for(int i=orders-1;i>=0;i--) // 計次循環(i=歷史平倉單數-1,到i=0, 遞減1)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false)
{
Print("Error in history!");
break;
}
// 如果 沒有本系統交易記錄,輸出“無交易歷史!”
if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue; // 如果 訂單的貨幣對不是當前貨幣對,或者 訂單類型為掛單時,繼續運行
// 訂單類型為整數型,0-BUY,1-SELL,2-BUYLIMT,3-BUYSTOP,4-SELLLIMT,5-SELLSTOP,其中“>OP_SELL”代表掛單
if(OrderProfit()>0) break; // 如果 盈利單數目>0,跳出循環
if(OrderProfit()<0) losses++; // 如果 盈利單數目<0,則在:虧損單數上加1
}
if(losses>1)
lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
// 如果 虧損單數>1時,則重新計算下單量,並保留小數點後1位,其計算公式為:下單量=(lot-lot*losses/DecreaseFactor(=3))。
}
//---- return lot size-返回下單量
if(lot<0.1) lot=0.1; // 如果 算出的交易量小於0.1手,則 取交易量為0.1手
return(lot); // 返回(下單量)
}
//+------------------------------------------------------------------+
//| Check for open order conditions |
//| 自定義函數(無返回值) 開倉策略 |
//+------------------------------------------------------------------+
void CheckForOpen() // 開倉檢查(判斷開倉條件及其處理)
{
double ma; // 定義局部變量ma為小數型
int res; // 定義局部變量res為整數型
//---- go trading only for first tiks of new bar ---- 只有在新K線的首次報價時執行
if(Volume[0]>1) return;
// 如果當前K線的成交價次數大於1時,返回
(不是K線的開盤時間點,即當前k線還沒收盤確定,則直接返回;否則,如果是K線第一個成交價,則向下繼續運行)
// ---- get Moving Average – 獲取均線數值
ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0);
// 獲取當前以收盤價為基准計算出的均線數值
iMA(NULL,0,12,6,MOD_SMA,PRICE_CLOSE,0)
// ---- sell conditions-賣出條件
if(Open[1]>ma && Close[1]<ma) // 如果前1根K線下穿均線(即K線的開盤價大於均線值、收盤價小於均線值)
{
res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA,0,Red);
// 發送倉單(當前貨幣對,賣出方向,開倉量計算(),買價,滑點=3,無止損,無止贏,訂單編號,標上紅色箭頭)
return; // 返回
}
// ---- buy conditions - 買入條件
if(Open[1]<ma && Close[1]>ma) // 如果前1根K線上穿均線(即K線的開盤價小於均線值、收盤價大於均線值)
{
res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue);
// 發送倉單(當前貨幣對,買入方向,開倉量計算(),賣價,滑點=3,無止損,無止贏,訂單編號,標上藍色箭頭)
return; // 返回
}
//----
}
//+------------------------------------------------------------------+
//| Check for close order conditions |
//| 自定義函數(無返回值) 平倉策略 |
//+------------------------------------------------------------------+
void CheckForClose() // 平倉檢查(判斷平倉條件及其處理)
{
double ma; // 定義局部變量ma小數型
//---- 只在一個k收盤另一個新出現時交易
if(Volume[0]>1) return; // 如果當前K線的成交價次數>1時,則返回
//---- get Moving Average // 獲取均線數值
ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0);
// 獲取當前以收盤價為基准計算出的均線數值
for(int i=0;i<OrdersTotal();i++) // 計次循環(變量i=1至定單總數,每次遞增1)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break; // 如果 沒有本系統所交易的倉單時,跳出循環
if(OrderMagicNumber()!=MAGICMA || OrderSymbol()!=Symbol()) continue;
// 如果 倉單編號不是本系統編號,或者 倉單貨幣對不是當前貨幣對時,繼續選擇
if(OrderType()==OP_BUY) // 如果是多單
{
if(Open[1]>ma && Close[1]<ma)
{
if(!OrderClose(OrderTicket(),OrderLots(),Bid,3,White));
// 如果第1根K線開盤價下穿均線(即開盤價高於均價而收盤價低於均價),則進行多頭平倉(倉單編號,持倉數量,買價,滑點=3,用白色箭頭顯示)
Print("OrderClose error ",GetLastError());
}
break; // 跳出循環
}
if(OrderType()==OP_SELL) // 如果是空單
{
if(Open[1]<ma && Close[1]>ma)
{
if(!OrderClose(OrderTicket(),OrderLots(),Ask,3,White))
// 如果第1根K線開盤價上穿均線(即開盤價低於均價而收盤價高於均價),則進行空頭平倉(倉單編號,持倉數量,賣價,滑點=3,用白色箭頭顯示)
Print("OrderClose error ",GetLastError());
}
break; // 跳出循環
}
}
//----
}
//+------------------------------------------------------------------+
//| OnTick function |
//+------------------------------------------------------------------+
void OnTick() //主程序—-每次成交價所驅動的運算過程
{
//--- check for history and trading 對交易歷史進行檢查
if(Bars<100 || IsTradeAllowed()==false)
return;
// 如果K線數少於100根,或者如果允許智能交易交易=假時,返回
//--- calculate open orders by current symbol 計算當前貨幣對的開倉訂單
if(CalculateCurrentOrders(Symbol())==0) CheckForOpen(); // 如果 計算出當前貨幣對開倉訂單數=0 (即沒有倉單),則進行開倉檢查。
else CheckForClose(); // 否則(即當前已經有倉單時),則進行平倉檢查。
//---
}
//+------------------------------------------------------------------+
二、本EA策略分析根據本EA系統的源代碼可以分析出:它使用的策略如下:
1、技術指標:12期均線系統;
2、滑點數:3個點;
3、開平倉法則:K線上穿均線時,無持倉單,則開多單;有空單時,則平空單;
K線下穿均線時,無持倉單,則開空單;有多單時,則平多單。
4、圖上標識:開多倉時,在圖中標示紅色箭頭;平倉時,則標示白色箭頭;
開空倉時,在圖中標未藍色箭頭;平倉時,則標示白色箭頭。
三、該系統在模擬交易中的結果分析以上對該EA系統進行了詳細的解析,從中可以看出EA系統的基本結構與相關策略。下面是該EA在模擬盤中1分鐘K線圖EURUSD(歐元對美元)中的開倉、平倉結果圖。在該系統的模擬交易過程中,基本上體現了本策略的操作思想,其中四個下單中,兩個空單和兩個多單,如下圖所示。
外_匯_邦 WaiHuiBang.com