您现在的位置: 比特财富网 >> 财经 >  >> 外匯
EA簡明教程收集以及修改
外_匯_邦 WaiHuiBang.com

第一篇 創建新文件
1、打開 MetaEditor (如何打開自己想辦法)呵呵,如果這個都打不開,拜托下面的也不用看了。www.emoneybtc.com也許你不適合研究這個。
2、選擇文件-->新文件 打開文件創建頁面。
3、選擇第二項 客戶指標  然後點下一步。
  注:這個頁面可以創建6種文件。我們常用的有 《客戶指標》,《腳本》,《智能交易系統》三種。我們先從指標開始。
4、輸入名字,作者等等。(支持中文)暫時不添加參數。
  注:這個位置可以添加用戶變量以後講解。
5、下一步 我們先建一個主窗口指標 所以這個頁面什麼都不用操作
  注:這個位置可以添加指標“線”。以後提及。
6、點擊完成。
ok新的指標文件生成了。但還沒有任何有用的代碼。初始化代碼齊全。

//+------------------------------------------------------------------+
//|                                                  MT4指標編輯.mq4 |
//|                                                              ldj |
//|                                        [url]http://www.metaquotes.net[/url] |
//+------------------------------------------------------------------+
#property copyright "ldj"
#property link      "http://www.metaquotes.net"

#property indicator_chart_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function                        |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
//----
  return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                      |
//+------------------------------------------------------------------+
int deinit()
  {
//----
  
//----
  return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
  int    counted_bars=IndicatorCounted();
//----
  
//----
  return(0);
  }
//+------------------------------------------------------------------+
上面的就是剛剛新建的一個指標文件。
第一部分  指標注釋 只是一個說明,有沒有都不影響指標運行。
//+------------------------------------------------------------------+
//|                                                  MT4指標編輯.mq4 |
//|                                                              ldj |
//|                                        [url]http://www.metaquotes.net[/url] |
//+------------------------------------------------------------------+
這部分中前面的 “//” 兩個斜線 說明後面的是注釋語句,不參與實際運行。
第二部分  預處理語句 這部分規定了指標的窗口性質。如下:
#property copyright "ldj"
#property link      "http://www.metaquotes.net"

#property indicator_chart_window
#號表示後面是預處理語句。
property 的意思是定義mt4內部變量的性質。變量名是mt4定義好的只能用固定的變量名。
例如:版權變量 copyright 鏈接變量 link 以及指標窗口類型變量indicator_chart_window等等。
其中窗口類型變量有indicator_chart_window(主窗口)indicator_separate_window(副窗口)兩個這裡只能用一個不能兩個同時用
這部分內容一般不需要修改。
第三部分  初始化函數(加載函數)
//+------------------------------------------------------------------+
//| Custom indicator initialization function                        |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
//----
  return(0);
  }
這個函數中的代碼只在只在指標(EA)加載的時候執行一次。用於對一些變量的初始化。
去初注釋函數體為
int init()
  {
  return(0);
  }
第三部分  卸載函數
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                      |
//+------------------------------------------------------------------+
int deinit()
  {
//----
  
//----
  return(0);
  }
當去初指標(EA)的時候執行一次。用於去除一些控件。
去除注釋函數體為
int deinit()
  {
    return(0);
  }
第四部分  主函數,每當價格變化時就調用執行一次。主要執行代碼都在這裡。
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
  int    counted_bars=IndicatorCounted();
//----
  
//----
  return(0);
  }
第五部分 子函數。有些指標和EA含有子函數。我習慣寫在後面。

華麗的分割線
===================================================================
#property indicator_buffers 3
#property indicator_separate_window
#property indicator_color1 White
#property indicator_color2 Red
#property indicator_color3 Silver
double Buffer1[];
double Buffer2[];
double Buffer3[];
extern int Fast = 10;
extern int Slow = 22;
extern int Signal = 7;
int init()
  {
  SetIndexStyle(0,DRAW_LINE,0,1);
  SetIndexStyle(1,DRAW_LINE,0,1);
  SetIndexStyle(2,DRAW_HISTOGRAM,0,1);
  SetIndexBuffer(0,Buffer1);
  SetIndexBuffer(1,Buffer2);
  SetIndexBuffer(2,Buffer3);
  IndicatorShortName("MACD("+Fast+","+Slow+","+Signal+")");
  SetIndexLabel(0,"MACD_MAIN");
  SetIndexLabel(1,"MACD_SIGNAL");
  SetIndexLabel(2,"MAIN-SIGNAL");
  IndicatorDigits(Digits+2);
  return(0);
  }
int deinit()
{
return(0);
}
int start()
  {
  int limit,counted_bars=IndicatorCounted();
  if(counted_bars<0) return(-1);
  if(counted_bars>0) counted_bars--;
  limit=Bars-counted_bars;
  for(int i=0; i<limit; i++)
    {
      Buffer1=iMACD(NULL,0,Fast,Slow,Signal,PRICE_CLOSE,MODE_MAIN,i);
      Buffer2=iMACD(NULL,0,Fast,Slow,Signal,PRICE_CLOSE,MODE_SIGNAL,i);
      Buffer3=Buffer1 - Buffer2;
    }
  return(0);
  }
MACD1
下面我們來逐步實現這個指標。
我們要形成雙線MACD和一個柱狀指標。
因此我們在副圖上要形成3個指標線。
主指標
信號指標
柱狀指標
1、第一步確認指標顯示的窗口
#property indicator_separate_window
//    #property indicator_chart_window
這條代碼決定了指標在副圖窗口顯示。下面那條注釋語句表示在主圖窗口也就是K線圖上顯示。
2、預定義3個緩沖區來顯示這三個指標線
#property indicator_buffers 3
#property indicator_color1 White
#property indicator_color2 Red
#property indicator_color3 Silver
#property indicator_buffers 3 語句預定義三個指標緩存區。
#property indicator_color1 White
#property indicator_color2 Red
#property indicator_color3 Silver
這三條語句為這三個指標預定義了三種顏色。
3、定義這三個指標的數組變量。
double Buffer1[];
double Buffer2[];
double Buffer3[];
double定義一個浮點變量。因為是一組數所以要定義一個數組“[]”。
4、在init()函數中初始化這三個指標。
  SetIndexStyle(0,DRAW_LINE,0,1);
  SetIndexStyle(1,DRAW_LINE,0,1);
  SetIndexStyle(2,DRAW_HISTOGRAM,0,1);
  SetIndexBuffer(0,Buffer1);
  SetIndexBuffer(1,Buffer2);
  SetIndexBuffer(2,Buffer3);
  IndicatorShortName("MACD("+Fast+","+Slow+","+Signal+")");
  SetIndexLabel(0,"MACD_MAIN");
  SetIndexLabel(1,"MACD_SIGNAL");
  SetIndexLabel(2,"MAIN-SIGNAL");
  IndicatorDigits(Digits+2);
IndicatorBuffers(3);//定義緩沖區的數量最多八個。因為這個指標只需要三個主緩沖區。所有這個有無都可以。有些需要輔助數組就需要定義這個。以後用到的時候再提起。
SetIndexStyle(0,DRAW_LINE,0,1);//定義指標的顯示形式。DRAW_LINE標示畫線指標。
看下這個內置函數的定義
SetIndexStyle( int index, int type, int style=EMPTY, int width=EMPTY, color clr=CLR_NONE)
  index:索引號。0就是第一個指標線1就是第二個指標線。
  type: 指標類型 下面是可選參數都是MT4的標准常量。
      DRAW_LINE      = 0 畫線
      DRAW_SECTION  = 1 畫線段
      DRAW_HISTOGRAM = 2 畫柱狀圖
      DRAW_ARROW    = 3 畫箭頭符號(需要設置符號代碼)
      DRAW_ZIGZAG    = 4 畫鋸齒圖
      DRAW_NONE      = 12 不畫圖
  style:指標線型 0~4的選擇。也可以不要,默認為0。
  Width:指標線寬 1~5的選擇。也可以不要,默認為1。
  clr:  指標顏色 一般用#property indicator_color1 White語句定義。前面定義了所以我們這裡沒有定義。
SetIndexBuffer(0,Buffer1);//為定義的指標變量數組標記索引號。就是使他們一一對應。
  0號索引對應Buffer1[]變量。依此類推
IndicatorShortName("MACD("+Fast+","+Slow+","+Signal+")");//設置指標顯示的名稱,內容是用+號連接的字符串。
  就是當鼠標放在指標上所看到的指標名稱。與文件名不相關。
SetIndexLabel(0,"MACD_MAIN");//設置指標的標記。就是當鼠標放在指標線上顯示的第三行的名稱。
  這條語句的意思是0號索引對應的指標變量標記是MACD_MAIN。其他類推。
IndicatorDigits(Digits+2);//定義指標的小數點位數數值是整數。這裡Digits是MT4的預定義變量。其值為當前貨幣兌的小數位。
主函數體
int start()
  {
  int limit,counted_bars=IndicatorCounted();
  if(counted_bars<0) return(-1);
  if(counted_bars>0) counted_bars--;
  limit=Bars-counted_bars;
  for(int i=0; i<limit; i++)
    {
      Buffer1=iMACD(NULL,0,Fast,Slow,Signal,PRICE_CLOSE,MODE_MAIN,i);
      Buffer2=iMACD(NULL,0,Fast,Slow,Signal,PRICE_CLOSE,MODE_SIGNAL,i);
      Buffer3=Buffer1 - Buffer2;
    }
  return(0);
  }
1、int limit,counted_bars=IndicatorCounted();//定義兩個整形變量,並給counted_bars變量負值。
  這裡面IndicatorCounted()函數是mt4內置函數不需要參數,其返回值為已經計算過的指標數組數量。
  如果指標錯誤則這個函數會返回一個負數。
2、if(counted_bars<0) return(-1); //如果條件成立說明指標調用運行錯誤。則退出程序。
3、if(counted_bars>0) counted_bars--;//從已經計算的指標中去除最後一條。
  這條語句用來修正counted_bars使得已經計算的最後一個數值可以在接下來的運算中重新計算一次。
4、limit=Bars-counted_bars;//計算需要計算的指標數據的柱數。
  這裡需要說明。在mt4中指標數組的索引和K線的索引標記相同,是從後向前遞增的從0開使的整數。
  也就是說,最後一條K線的索引是0同時K線所對應的指標索引也是0。
  那麼倒數第2條的索引標記為1。倒數第三條的索引標記為2。
  這一點一定要理解清楚。不然寫程序的時候就會發生錯誤。
  語句中的Bars是mt4預定義變量,其值是當前圖表中K線的條數。
  這裡詳細說下為什麼有個counted_bars--;的語句,這個語句的意思是對變量counted_bars進行自減一操作。
  因為主函數是每次價格變動就會運行一次。當運行完成後。IndicatorCounted()值應該等於Bars也就是K線的條數
  如果沒有上面的自減一操作,那麼當價格變動有了新的收盤價但並沒有生成新的K線。這時候計算limit的值將=0.
  那麼下面的for循環體將不會再計算最後一條k線相對應的指標數值。
  實際上這個是需要計算的(因為有了新的收盤價)。而有了自減一的操作就可以對最有一個,也就是當前K線對應的指標值進行運算。
  (不知道能看明白不自己慢慢捉摸捉摸)。這個自減一是必需的。
5、for(int i=0; i<limit; i++) for 循環語句(因為有了前面的自減一操作,這裡limit最小等於1)
  關於for循環的運行不作解釋。各位自己找資料學習。
6、Buffer1[ i ]=iMACD(NULL,0,Fast,Slow,Signal,PRICE_CLOSE,MODE_MAIN,i); //調用MACD指標函數為Buffer1數組負值。
  看下iMACD()這個內置指標函數的定義。
  iMACD( string symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int mode, int shift)
  symbol:          貨幣標識。通用指標用NULL常量。
  timeframe:        計算所依據的圖表時間周期 。0表示依據當前圖表周期。
  fast_ema_period: 快線周期
  slow_ema_period: 慢線周期
  signal_period:  信號線周期
  applied_price:  計算所用價格模式
  mode:            指標索引模式。MACD指標有兩條線,因此這個位置有0,1兩個選擇。也可以用mt4預定義常量。
  shift:            索引號
  這裡Buffer1取macd主線數據。Buffer2取macd信號線數據。
7、Buffer3[ i ]=Buffer1[ i ] - Buffer2[ i ];//計算MACD兩條線之間的距離。
8、這裡用到了外部變量。也可以叫用戶自定義變量。這種變量在加載圖表的時候可以修改。
extern int Fast = 10;
extern int Slow = 22;
extern int Signal = 7;
extern 關鍵字說明後面定義的變量是外部變量。

華麗的分割線2
=======================================================
問答題
瞬間的光輝/bull
本帖隱藏的內容需要回復才可以浏覽

-------------------------------------------------------------------------------------------------------------------------------------------
瞬間的光輝questions

感激的沒話說呀!牛版晚上12點還回答我的問題,而且回答的那麼詳細!
牛版的解釋我認為是:所有論壇的高手中最無私最熱心幫助別人的。
為了讓更多的新手快速的入門EA,我決定做牛版帖子的追問者。牛版的帖子非常易懂,一般新手都能看懂70%,還有那30%的疑問,就由我來補問吧!

int OrderSend( string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment=NULL, int magic=0, datetime expiration=0, color arrow_color=CLR_NONE)
comment參數有什麼作用?A:這參數本意是用於記錄這個訂單的描述信息,程序只能在訂單入場的時候設定他。同時系統會在這個訂單發生止損 止贏或者拆單的時候自動修改這裡的內容。

我一直想尋找一個函數能夠返回我下的訂單是否已經被止損或止贏了,問了好多人
都是同樣的回答:OrdersTotal()<1就說明你下的訂單平倉了,換句話說就是被止損或
止贏了。但是前提是我只能同時做一單,如果我同時做好幾單呢,這怎麼判斷我下的其中
一單已經止損或止贏了。
今天看了牛版關於comment參數的解釋,有了啟發:
comment參數有什麼作用?A:這參數本意是用於記錄這個訂單的描述信息,程序只能在訂單入場的時候設定他。同時系統會在這個訂單發生止損 止贏或者拆單的時候自動修改這裡的內容。
既然訂單發生止損 止贏或者拆單的時候自動修改這裡的內容。
那我可以在下單的時候給comment賦值”on”,當訂單生成後我可以用OrderComment()
函數實時獲取它的comment值如果不等於”on”那就說明訂單已經止損或止贏了。

MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
這句中你NULL是空貨幣嗎?0代表0M嗎?NULL和0有具體意思嗎?我們自己用的時候需要具體化吧?A:Null表示當前圖形上的貨幣
牛版只回答了NULL,那0呢,是不是也代表當前當前時段呢!
呵呵!給我留作業了吧!

華麗的分割線2
=======================================================

EA的基本框架

/+------------------------------------------------------------------+
//|                          Designed by bull, China                |
//|                  Copyright 2007, bull                        |
//|                                bbs.520fx.com                        |
//+------------------------------------------------------------------+
#property  copyright "Copyright 2007 , bull, China."
#property  link      "bbs.520fx.com"
#define MAGICMA
//+------------------------------------------------------------------+
//| 注意沒有指標文件那些property                  |
//+------------------------------------------------------------------+
extern int whichmethod = 1;  //1~4 種下單方式  1 僅開倉, 2 有止損無止贏, 3 有止贏無止損, 4 有止贏也有止損
extern double TakeProfit = 100;  //止贏點數
extern  double StopLoss = 20;    //止損點數
extern double MaximumRisk    = 0.3; //資金控制,控制下單量
extern double TrailingStop =25;    //跟蹤止贏點數設置
extern  int maxOpen = 3;  //最多開倉次數限制
extern  int maxLots = 5;  //最多單倉持倉量限制
extern int bb = 0;      //非零就允許跟蹤止贏
extern double MATrendPeriod=26;//使用26均線 開倉條件參數  本例子

int i, p2, xxx,p1, res;
double Lots;
datetime lasttime;      //時間控制, 僅當一個時間周期完成才檢查條件
int init()  //初始化
{
Lots = 1;
lasttime = NULL;
return(0);
}
int deinit() { return(0); } //反初始化
//主程序
int start()
{
CheckForOpen();    //開倉 平倉 條件檢查 和操作
if (bb>0)  CTP();  //跟蹤止贏
return(0);
}
//+------下面是各子程序--------------------------------------------+
double LotsOptimized()  //確定下單量,開倉調用 資金控制
{
double lot=Lots;
int  orders=HistoryTotal();  // history orders total
int  losses=0;            // number of losses orders without a break
//MarketInfo(Symbol(),MODE_MINLOT);    相關信息
//MarketInfo(Symbol(),MODE_MAXLOT);
//MarketInfo(Symbol(),MODE_LOTSTEP);
lot=NormalizeDouble(MaximumRisk * AccountBalance()/AccountLeverage(),1);    //開倉量計算
if(lot<0.1) lot=0.1;
if(lot>maxLots) lot=maxLots;
return(lot);
}
  
//平倉持有的買單
void CloseBuy()
{
if (OrdersTotal( ) > 0 )  
{
  for(i=OrdersTotal()-1;i>=0;i--)
  {
  if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false)    break;
  if(OrderType()==OP_BUY)
  {
    OrderClose(OrderTicket(),OrderLots(),Bid,3,White);
    Sleep(5000);
  }
  }
}
}
//平倉持有的賣單
void CloseSell()
{
if (OrdersTotal( ) > 0 )  
{
  for(i=OrdersTotal()-1;i>=0;i--)
  {
  if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false)    break;
  if(OrderType()==OP_SELL)
    {
    OrderClose(OrderTicket(),OrderLots(),Ask,3,White);
    Sleep(5000);
    }
  }
}
}
//判斷是否買或賣或平倉
int buyorsell()  //在這個函數計算設置你的交易信號  這裡使用MACD 和MA 做例子
{
  double MacdCurrent, MacdPrevious, SignalCurrent;
  double SignalPrevious, MaCurrent, MaPrevious;
  MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
  MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
  SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);
  SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1);
  MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0);
  MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);
if(MacdCurrent<0 & MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious
    & MaCurrent>MaPrevious)
  return (1); // 買 Ma在上升,Macd在0線上,並且兩線上交叉
if(MacdCurrent>0 & MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious
    & MaCurrent<MaPrevious)
  return (-1); // 賣
return (0); //不交易
}
int nowbuyorsell = 0;
void CheckForOpen()
{
if (Time[0] == lasttime ) return; //每時間周期檢查一次  時間控制
lasttime = Time[0];
nowbuyorsell = buyorsell(); //獲取買賣信號

if (nowbuyorsell == 1) //買 先結束已賣的
  CloseSell();
if (nowbuyorsell == -1) //賣 先結束已買的
    CloseBuy();
if (TimeDayOfWeek(CurTime()) == 1)
  {
  if (TimeHour(CurTime()) < 3 ) return; //周一早8點前不做 具體決定於你的時區和服務器的時區  時間控制
  }
if (TimeDayOfWeek(CurTime()) == 5)
  {
  if (TimeHour(CurTime()) > 19 ) return; //周五晚11點後不做
  }

if (OrdersTotal( ) >= maxOpen) return ;  
//如果已持有開倉次數達到最大,不做
if (nowbuyorsell==0) return;  //不交易
TradeOK();  //去下單交易
}
void TradeOK()  //去下單交易
{
int error ;
if (nowbuyorsell == 1) //買
  {
    switch (whichmethod)
    {
    case 1:  res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue);break;
    case 2:  res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,Ask-StopLoss*Point,0,"",MAGICMA,0,Blue); break;
    case 3:  res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,Ask+TakeProfit*Point,"",MAGICMA,0,Blue);break;
    case 4:  res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,Ask-StopLoss*Point,Ask+TakeProfit*Point,"",MAGICMA,0,Blue);break;
    default : res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue);break;
    }
    if (res <=0)
    {
    error=GetLastError();
    if(error==134)Print("Received 134 Error after OrderSend() !! ");        // not enough money
    if(error==135) RefreshRates();  // prices have changed
    }
    Sleep(5000);
    return ;  
  }
if (nowbuyorsell == -1) //賣
  {
    switch (whichmethod)
    {
    case 1:  res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA,0,Red); break;
    case 2:  res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,Bid+StopLoss*Point,0,"",MAGICMA,0,Red); break;
    case 3:  res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,Bid-TakeProfit*Point,"",MAGICMA,0,Red); break;
    case 4:  res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,Bid+StopLoss*Point,Bid-TakeProfit*Point,"",MAGICMA,0,Red); break;
    default : res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA,0,Red); break;
    }
    if (res <=0)
    {
    error=GetLastError();
    if(error==134) Print("Received 134 Error after OrderSend() !! ");        // not enough money
    if(error==135) RefreshRates();  // prices have changed
    }
    Sleep(5000);
    return ;  
  }
}
void CTP()  //跟蹤止贏
{
bool bs = false;
for (int i = 0; i < OrdersTotal(); i++)
{
  if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false)    break;
  if (OrderType() == OP_BUY)
  {
    if ((Bid - OrderOpenPrice()) > (TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT)))    //開倉價格 當前止損和當前價格比較判斷是否要修改跟蹤止贏設置
    {
    if (OrderStopLoss() < Bid - TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT))
    {
      bs = OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT), OrderTakeProfit(),0, Green);
    }
    }
  }
  else if (OrderType() == OP_SELL)
  {
    if ((OrderOpenPrice() - Ask) > (TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT)))  //開倉價格 當前止損和當前價格比較判斷是否要修改跟蹤止贏設置

    {
    if ((OrderStopLoss()) > (Ask + TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT)))
    {    
      bs = OrderModify(OrderTicket(), OrderOpenPrice(),
        Ask + TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT), OrderTakeProfit(),0, Tan);
}
    }
  }
}
}
華麗的分割線
=====================================================================
EA中文注釋

    原帖由 白色流星 於 2007-12-1 20:58 發表
    首先我們先解讀一下系統自帶的MACDEA~這個相對簡單~
    //+------------------------------------------------------------------+
    //| MACD Sample.mq4 |
    //| ... 

extern double TakeProfit = 50;  盈利目標點數
extern double Lots = 0.1;        每單入場的手數
extern double TrailingStop = 30; 追蹤止損的點數
extern double MACDOpenLevel=3; MACD開倉的參考位置
extern double MACDCloseLevel=2; MACD出場的參考位置
extern double MATrendPeriod=26; 條件中使用的MA均線的周期數
程序最上面extern開始的這些數據都是程序參數,也就是在使用者調用的時候可以修改的部分。
這個EA是個常見的技術指標條件入場,條件出場 同時又移動止損功能的完成示意,很適合初學者研究。
先總結這個程序的基本條件的意思 以方便大家對號入座,盡快理解。
多頭入場條件:
  MACD小於0 並且 小於指定的參數MACDOpenLevel  並且 MACD訊號下下穿基准線(死叉) 並且 MA向上趨勢
多頭出場條件:
  MACD大於0 並且 大於指定的參數MACDCloseLevel 並且 MACD信號線上傳基准線(金叉)

空頭入場條件:
MACD大於0 並且 大於指定的參數MACDOpenLevel  並且 MACD訊號線上穿基准線(金叉) 並且 MA向下趨勢
空頭出場條件:
MACD小於0 並且 小於制定的參數MACDCloseLevel  並且 MACD訊號線下穿基准線(死叉)

=============================================================
有了以上的初步了解,下面開始進行EA程序基本結構的分析:
1、start()函數是最重要的執行部分,每來一個價格 此函數都自動執行一次,所以主要的邏輯結構都在這個函數裡
2、程序的基本流程都是按照以下步驟進行,我們先牢牢記住這個結構,然後再對號入座去理解程序。
    先判斷當前自身的倉位狀態,因為start函數式循環運行的,所以中間的每個步驟都會使用start函數,因此,當函數開始的時候我們首先要通過MT4的倉位操作函數獲得當前的倉位狀態,並進一步根據狀態進行不同分支的計算。
    程序開始的以下兩個部分不重要 簡單說一下:
if(Bars<100)
    {
      Print("bars less than 100");
      return(0);  
    }
以上是說如果當前圖形的K線個數少於100 則不進行運算 直接返回。這種情況一般不會出現,所以我們自己寫程序的時候可以不寫這部分。
  if(TakeProfit<10)
    {
      Print("TakeProfit less than 10");
      return(0);  // check TakeProfit
    }
以上這段意思是參數TakeProfit移動止損點數的設定如果小於10點,則發出報警,並返回不進行運算。這是為了防止亂設數值,引起後面計算的錯誤。這部分,如果程序只是我們自己使用,估計不會犯這種低級錯誤,所以寫程序的時候也可以忽略不寫。
下面這段:
  MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
  MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
  SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);
  SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1);
  MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0);
  MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);
這部分是變量賦值部分,等於提前計算出為後面用到的當前MACD數值以及MA數值,這樣提前寫出來在後面直接使用賦值後的變量就很清楚了。是很好的編程習慣。
  再下面開始最主要的程序邏輯部分,首先遇到的就是我們上面說過的通過倉位函數獲得當前狀態的部分。
total=OrdersTotal(); 通過函數獲得當前持倉單的個數,如果持倉單個數小於1,則說明是空倉狀態,那末就進行多頭和空頭的入場條件判斷,如果滿足條件則進行入場。代碼如下:
if(total<1)
    {
      // no opened orders identified
      if(AccountFreeMargin()<(1000*Lots))  這句詩判斷保證金余量是否夠下單,如果不夠則直接返回,並不進行後續入場判斷
        {
        Print("We have no money. Free Margin = ", AccountFreeMargin());
        return(0);  
        }
      // check for long position (BUY) possibility
      if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious &&
        MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious) 這句就是多頭入場條件的判斷,可以看到2個技巧,1、交叉的數學意思是“前面再下後面在上”或反之 2、MA向上趨勢 的數學意思是當前K線的MA大於上一K線的MA數值
        {
        ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green); 這是入場語句記得一定要判斷入場是否成功,因為很多服務器由於滑點或者服務器價格變動而不能入場成功,所以,要判斷入場不成功後作出提示。ticket就是定單入場是否成功的標記。
        if(ticket>0) 大於0說明入場成功
          {
            if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("BUY order opened : ",OrderOpenPrice());
          }
        else Print("Error opening BUY order : ",GetLastError()); 入場不成功,輸出不成功的系統原因。
        return(0); 這裡為什麼使用了返回呢。因為一種情況是入場成功,那末直接返回等待下一個價格到來的時候再執行start函數,另一種情況是入場不成功,則返回也是等待下一個價格到來的時候在此執行入場操作。
        }
      下面就是空單入場的判斷了,大家自己對照觀看即可
      // check for short position (SELL) possibility
      if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious &&
        MacdCurrent>(MACDOpenLevel*Point) && MaCurrent<MaPrevious)
        {
        ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,Bid-TakeProfit*Point,"macd sample",16384,0,Red);
        if(ticket>0)
          {
            if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("SELL order opened : ",OrderOpenPrice());
          }
        else Print("Error opening SELL order : ",GetLastError());
        return(0);
        }
      return(0);
    }
華麗的分割線
===================================================================================
EA中文注釋2
#property copyright "Copyright ?2007, 520FX Corp." //指標版權信息
#property link "http://www.520fx.com" //指標聯系的網站鏈接
//=====可調參數部分==============
#define Magic 20090101 //預定義的常量 Magic用於後面程序裡的開倉動作時標記在訂單裡面的一個符號,用於區別其他EA程序下的單 防止混亂
extern int N=50; //參數 後面程序裡用它作為N根K線的數量
extern int SL=100;//參數 後面程序裡下單的時候用這個設置的點數作為入場時訂單的止損價格。
extern int TrailingStop=30;//參數 後面程序裡用這個作為移動止損的點數設置
extern double 每單手數=0.1;//參數 表示後面下單的倉位的大小
extern int 滑點偏移點數=3;//參數 表示下單時 服務器端的價格與當前看到的價格相差的范圍,如果在此范圍內,則允許以服務器端的價格成交
//----全局變量===================
int Tick;//用於記錄訂單的唯一編號
double StopLost;//用於記錄止損

//========主函數部分開始============
int start()//主函數 沒來一個價格這個函數就運行一次
{
int Ticket; //局部變量 用於記錄每次下單後的狀態,用於判斷下單動作是否成功,如果不成功則做相應處理和提示
int OrderTypeNow=GetOrderTypeHolding();//通過自定義函數得到當前持倉單的交易類型 買 賣
//自定義函數中做了處理,如果沒有發現當前有持倉 則返回-1
if (OrderTypeNow==-1)//空倉階段 -1表示沒有持倉的狀態
{
if (TradeOrNo(1))//多單入場條件 自定義函數TradeOrNo(1)參數1 表示針對多單的方向進行判斷是否滿足入場條件
{
Ticket=OrderSend(Symbol(),OP_BUY,每單手數,Ask,滑點偏移點數,Ask-SL*Point,0,"",Magic,0,0);//多單入場
//Ticket表示入場動作的執行結果,如果小於0表示入場動作失敗
if(Ticket<0)
{
Print("多單入場失敗"+GetLastError());
return(0); //推出本次start函數的執行
}
}else
if (TradeOrNo(2))//空單入場條件
{
Ticket=OrderSend(Symbol(),OP_SELL,每單手數,Bid,滑點偏移點數,Bid+SL*Point,0,"",Magic,0,0);
if(Ticket<0)
{
Print("空單入場失敗"+GetLastError());
return(0);
}
}
return;
}else//===============持倉階段===========================
{
switch(OrderTypeNow)
{
case OP_BUY://多單持倉情況下,滿足空單入場條件
if (TradeOrNo(2))
{
if(OrderClose(Tick,OrderLots(),Bid,滑點偏移點數)==false)//平掉多單持倉單
{
Print("翻轉發生 多頭平倉失敗"+GetLastError());
return;
}else//平倉後,反手建立空單
{
Ticket=OrderSend(Symbol(),OP_SELL,每單手數,Bid,滑點偏移點數,Bid+SL*Point,0,"",Magic,0,0);
if(Ticket<0)
{
Print("空單反手建倉失敗"+GetLastError());
return(0);
}
}
}else //判斷移動止損
{
if (Ask>StopLost+2*TrailingStop*Point)
{
OrderModify(Tick,OrderOpenPrice(),StopLost+TrailingStop*Point,0,0,CLR_NONE);
return;
}
}
break;
case OP_SELL:
if (TradeOrNo(1))
{
if(OrderClose(Tick,OrderLots(),Ask,滑點偏移點數)==false)//平掉空單持倉單
{
Print("翻轉發生 空頭平倉失敗"+GetLastError());
return;
}else//平倉後,反手建立多單
{
Ticket=OrderSend(Symbol(),OP_BUY,每單手數,Ask,滑點偏移點數,Ask-SL*Point,0,"",Magic,0,0);
if(Ticket<0)
{
Print("多單反手建倉失敗"+GetLastError());
return(0);
}
}
}else //判斷移動止損
{
if (Bid<StopLost-2*TrailingStop*Point)
{
OrderModify(Tick,OrderOpenPrice(),StopLost-TrailingStop*Point,0,0,CLR_NONE);
return;
}
}
break;
}
return;
}

return(-1);
}
//=================自定義函數部分======================================
int GetOrderTypeHolding()//從最近持倉單提取訂單類型,如果沒有持倉單,則認為是止贏出場或程序剛開始運行返回-1
{int Type=-1;
//int temptime=0;
for(int i=OrdersTotal()-1;i>=0;i--)
{
OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic )
{
Type=OrderType();
Tick=OrderTicket();
StopLost=OrderStopLoss();
}
}
return(Type);
}
//======================================================
bool TradeOrNo(int Type)//判斷當前指定方向的入場條件是否成立
{
double NHigh=High[iHighest(Symbol(),0,MODE_HIGH,N,2)];
double NLow=Low[iLowest(Symbol(),0,MODE_LOW,N,2)];
switch(Type)
{
case 1://判斷多單入場條件是否成立
if (Close[1]>NHigh)//做多條件成立
{
return(true);
}
break;
case 2:
if (Close[1]<NLow)//做空條件成立
{
return(true);
}
break;
}
return(false);
}

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