Menggunakan Moving Average EA di MetaTrader 5 untuk Trading yang Lebih Efisien

Mike 2013.12.24 17:03 103 0 0
Lampiran

Moving Average EA adalah salah satu alat yang disertakan dalam paket standar dari MetaTrader 5. EA ini merupakan contoh sistem trading yang memanfaatkan indikator Moving Average untuk melakukan trading.

File EA bernama Moving Average.mq5 dapat ditemukan di folder "terminal_data_folder\MQL5\Experts\Examples\Moving Average". EA ini adalah contoh penggunaan indikator teknikal, fungsi riwayat trading, dan kelas trading dari Standard Library. EA ini juga dilengkapi dengan sistem manajemen uang yang berdasarkan hasil trading.

Ayo kita lihat struktur dari Expert Advisor ini dan cara kerjanya.

1. Properti EA

//+------------------------------------------------------------------+
//|                                              Moving Averages.mq5 |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2009-2013, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

Lima baris pertama berisi komentar, diikuti tiga baris berikutnya yang mengatur properti dari program MQL5 (hak cipta, tautan, versi) menggunakan direktif preprocessor #property.

Ketika Anda menjalankan Expert Advisor, informasi ini akan ditampilkan di tab "Common":


Gambar 1. Parameter Umum dari Moving Average EA

1.2. File yang Disertakan

Selanjutnya, direktif #include memberi tahu compiler untuk menyertakan file "Trade.mqh".

File ini merupakan bagian dari Standard Library, yang berisi kelas CTrade untuk akses mudah ke fungsi trading.

#include <Trade\Trade.mqh>

Nama file yang disertakan dituliskan dalam tanda kurung "<>;", sehingga jalurnya diatur relatif terhadap direktori: "terminal_data_folder\Include".

1.3 Input

Selanjutnya adalah tipe, nama, nilai default, dan komentar. Perannya ditunjukkan pada Gambar 2.

input double MaximumRisk        = 0.02;    // Risiko Maksimum dalam persentase
input double DecreaseFactor     = 3       // Faktor penurunan
input int    MovingPeriod       = 12      // Periode Moving Average
input int    MovingShift        = 6       // Shift Moving Average

Parameter MaximumRisk dan DecreaseFactor akan digunakan untuk manajemen uang, MovingPeriod dan MovingShift mengatur periode dan shift dari indikator Moving Average yang akan digunakan untuk memeriksa kondisi trading.

Text dalam komentar di baris parameter input, bersama dengan nilai default, akan ditampilkan di tab "Options" sebagai pengganti nama parameter input:


Gambar 2. Parameter Input dari Moving Average EA

1.4. Variabel Global

Selanjutnya, variabel global ExtHandle dideklarasikan. Ini akan digunakan untuk menyimpan handle dari indikator Moving Average.

//---
int   ExtHandle=0;

Diikuti dengan enam fungsi. Tujuan masing-masing fungsi dijelaskan dalam komentar sebelum badan fungsi:

  1. TradeSizeOptimized() - Menghitung ukuran lot optimal;
  2. CheckForOpen() - Memeriksa kondisi pembukaan posisi;
  3. CheckForClose() - Memeriksa kondisi penutupan posisi;
  4. OnInit() - Fungsi inisialisasi Expert;
  5. OnTick() - Fungsi tick Expert;
  6. OnDeinit() - Fungsi deinisialisasi Expert;

Tiga fungsi terakhir adalah fungsi penanganan peristiwa; tiga fungsi pertama adalah fungsi layanan yang dipanggil dalam kode mereka.

2. Fungsi Penanganan Peristiwa

2.1. Fungsi inisialisasi OnInit()

Fungsi OnInit() dipanggil sekali saat pertama kali Expert Advisor dijalankan. Biasanya, dalam handler peristiwa OnInit(), EA dipersiapkan untuk beroperasi: parameter input diperiksa, indikator dan parameter diinisialisasi, dan lain-lain. Jika ada kesalahan kritis, ketika pekerjaan lebih lanjut tidak berarti, fungsi ini keluar dengan kode pengembalian INIT_FAILED.

//+------------------------------------------------------------------+
//| Fungsi inisialisasi Expert                                   |
//+------------------------------------------------------------------+
int OnInit(void)
  {
//---
   ExtHandle=iMA(_Symbol,_Period,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE);
   if(ExtHandle==INVALID_HANDLE)
     {
      printf("Error creating MA indicator");
      return(INIT_FAILED);
     }
//---
   return(INIT_SUCCEEDED);
  }

Karena trading EA didasarkan pada indikator Moving Average, dengan memanggil iMA() indikator Moving Average dibuat dan handle-nya disimpan dalam variabel global ExtHandle.

Jika terjadi kesalahan, OnInit() keluar dengan kode pengembalian INIT_FAILED - ini adalah cara yang benar untuk menyelesaikan operasi EA/indikator dalam kasus inisialisasi yang tidak berhasil.

2.2. Fungsi OnTick()

Fungsi OnTick() dipanggil setiap kali kutipan baru diterima untuk simbol grafik yang dijalankan EA ini.

//+------------------------------------------------------------------+
//| Fungsi tick Expert                                             |
//+------------------------------------------------------------------+
void OnTick(void)
  {
//---
   if(PositionSelect(_Symbol))
      CheckForClose();
   else
      CheckForOpen();
//---
  }

Fungsi PositionSelect() digunakan untuk menentukan apakah ada posisi terbuka untuk simbol saat ini.

Jika ada posisi terbuka, fungsi CheckForClose() dipanggil, yang menganalisis keadaan pasar saat ini dan menutup posisi terbuka, jika tidak, CheckForOpen() dipanggil, yang memeriksa kondisi masuk pasar dan membuka posisi baru jika kondisi tersebut terjadi.

2.3. Fungsi deinisialisasi OnDeInit()

OnDeInit() dipanggil ketika EA dihapus dari grafik. Jika program menempatkan objek grafis selama operasi, objek tersebut dapat dihapus dari grafik.

//+------------------------------------------------------------------+
//| Fungsi deinisialisasi Expert                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+

Dalam kasus ini, tidak ada tindakan yang dilakukan selama deinisialisasi Expert Advisor.

3. Fungsi Layanan

3.1. Fungsi TradeSizeOptimized()

Fungsi ini menghitung dan mengembalikan nilai ukuran lot optimal untuk membuka posisi dengan tingkat risiko yang ditentukan dan hasil trading.

//+------------------------------------------------------------------+
//| Menghitung ukuran lot optimal                                     |
//+------------------------------------------------------------------+
double TradeSizeOptimized(void)
  {
   double price=0.0;
   double margin=0.0;
//--- Menghitung ukuran lot
   if(!SymbolInfoDouble(_Symbol,SYMBOL_ASK,price))
      return(0.0);
   if(!OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,margin))
      return(0.0);
   if(margin<=0.0)
      return(0.0);

   double lot=NormalizeDouble(AccountInfoDouble(ACCOUNT_FREEMARGIN)*MaximumRisk/margin,2);
//--- menghitung panjang dari serangkaian trading yang kalah berturut-turut
   if(DecreaseFactor>0)
     {
      //--- meminta seluruh riwayat trading
      HistorySelect(0,TimeCurrent());
      //--
      int    orders=HistoryDealsTotal();  // total jumlah transaksi
      int    losses=0                    // jumlah transaksi kalah dalam seri

      for(int i=orders-1;i>=0;i--)
        {
         ulong ticket=HistoryDealGetTicket(i);
         if(ticket==0)
           {
            Print("HistoryDealGetTicket failed, no trade history");
            break;
           }
         //--- memeriksa simbol transaksi
         if(HistoryDealGetString(ticket,DEAL_SYMBOL)!=_Symbol)
            continue;
         //--- memeriksa profit
         double profit=HistoryDealGetDouble(ticket,DEAL_PROFIT);
         if(profit>0.0)
            break;
         if(profit<0.0)
            losses++;
    }
      //---
      if(losses>1)
         lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
     }
//--- normalisasi dan memeriksa nilai yang diperbolehkan dari volume trading
   double stepvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
   lot=stepvol*NormalizeDouble(lot/stepvol,0);

   double minvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   if(lot<minvol)
      lot=minvol;

   double maxvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
   if(lot>maxvol)
      lot=maxvol;
//--- mengembalikan nilai volume trading
   return(lot);
  }

Fungsi SymbolInfoDouble() digunakan untuk memeriksa ketersediaan harga untuk simbol saat ini, selanjutnya fungsi OrderCalcMargin() digunakan untuk meminta margin yang diperlukan untuk menempatkan order (dalam hal ini order beli). Ukuran lot awal ditentukan dari nilai margin yang diperlukan untuk menempatkan order, margin bebas dari akun (AccountInfoDouble(ACCOUNT_FREEMARGIN)) dan nilai risiko maksimum yang diizinkan yang ditentukan dalam parameter input MaximumRisk.

Jika nilai parameter input DecreaseFactor positif, transaksi dalam riwayat dianalisis dan ukuran lot disesuaikan dengan mempertimbangkan informasi tentang serangkaian transaksi kalah maksimal: ukuran lot awal dikalikan dengan ukuran (1-losses/DecreaseFactor).

Selanjutnya, volume trading "dibulatkan" ke nilai yang merupakan kelipatan dari langkah volume minimum (stepvol) untuk simbol saat ini. Juga, nilai minimum (minvol) dan maksimum (maxvol) dari volume trading diminta, dan jika nilai lot keluar dari batas yang diizinkan, maka disesuaikan. Akibatnya, fungsi ini mengembalikan nilai volume trading yang dihitung.

3.2. Fungsi CheckForOpen()

CheckForOpen() digunakan untuk memeriksa kondisi pembukaan posisi dan membukanya ketika kondisi trading terjadi (dalam hal ini saat harga melintasi moving average).

//+------------------------------------------------------------------+
//| Memeriksa kondisi pembukaan posisi                               |
//+------------------------------------------------------------------+
void CheckForOpen(void)
  {
   MqlRates rt[2];
//--- salin nilai harga
   if(CopyRates(_Symbol,_Period,0,2,rt)!=2)
     {
      Print("CopyRates of ",_Symbol," failed, no history");
      return;
     }
//--- Trading hanya pada tick pertama dari bar baru
   if(rt[1].tick_volume>1)
      return;
//--- Dapatkan nilai saat ini dari indikator Moving Average 
   double   ma[1];
   if(CopyBuffer(ExtHandle,0,0,1,ma)!=1)
     {
      Print("CopyBuffer from iMA failed, no data");
      return;
     }
//--- memeriksa sinyal
   ENUM_ORDER_TYPE signal=WRONG_VALUE;

      if(rt[0].open>ma[0] && rt[0].close<ma[0])
      signal=ORDER_TYPE_SELL    // kondisi jual
     else
       {
         if(rt[0].open<ma[0] && rt[0].close>ma[0])
           signal=ORDER_TYPE_BUY  // kondisi beli
     }
//--- pemeriksaan tambahan
      if(signal!=WRONG_VALUE)
         if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
           if(Bars(_Symbol,_Period)>100)
             {
            CTrade trade;
            trade.PositionOpen(_Symbol,signal,TradeSizeOptimized(),
                               SymbolInfoDouble(_Symbol,signal==ORDER_TYPE_SELL ? SYMBOL_BID:SYMBOL_ASK),
                               0,0);
           }
//---
  }

Ketika trading menggunakan moving average, Anda perlu memeriksa apakah harga melintasi moving average. Menggunakan fungsi CopyRates(), dua nilai harga saat ini disalin ke dalam array struktur rt[], rt[1] sesuai dengan bar saat ini, rt[0] - bar yang telah selesai.

Baru dimulai dengan memeriksa volume tick dari bar saat ini, jika sama dengan 1, maka bar baru telah dimulai. Perlu dicatat bahwa metode ini untuk mendeteksi bar baru mungkin gagal dalam beberapa kasus (ketika kutipan datang secara berkelompok), sehingga fakta dari dimulainya pembentukan bar baru harus dilakukan dengan menyimpan dan membandingkan waktu kutipan saat ini (lihat IsNewBar).

Nilai saat ini dari indikator Moving Average diminta menggunakan fungsi CopyBuffer() dan disimpan dalam array ma[] yang hanya memiliki satu nilai. Program kemudian memeriksa apakah harga telah melintasi moving average dan melakukan pemeriksaan tambahan (jika trading menggunakan EA dimungkinkan dan ada bar dalam riwayat). Jika berhasil, posisi yang sesuai untuk simbol tersebut dibuka dengan memanggil metode PositionOpen() dari objek trading (instance dari CTrade).

Harga pembukaan posisi ditentukan dengan memanggil fungsi SymbolInfoDouble() yang mengembalikan harga Bid atau Ask tergantung pada nilai dari variabel signal. Volume posisi ditentukan dengan memanggil TradeSizeOptimized() yang telah dijelaskan di atas.

3.3. Fungsi CheckForClose()

CheckForClose() memeriksa kondisi untuk menutup posisi dan menutupnya jika kondisi untuk menutupnya terjadi.

//+------------------------------------------------------------------+
//| Memeriksa kondisi penutupan posisi                              |
//+------------------------------------------------------------------+
void CheckForClose(void)
  {
   MqlRates rt[2];
//--- Salin nilai harga
   if(CopyRates(_Symbol,_Period,0,2,rt)!=2)
     {
      Print("CopyRates of ",_Symbol," failed, no history");
      return;
     }
//--- Trading hanya pada tick pertama dari bar baru
   if(rt[1].tick_volume>1)
      return;
//--- dapatkan nilai saat ini dari indikator Moving Average
   double   ma[1];
   if(CopyBuffer(ExtHandle,0,0,1,ma)!=1)
     {
      Print("CopyBuffer from iMA failed, no data");
      return;
     }
//--- dapatkan tipe posisi yang dipilih sebelumnya menggunakan PositionSelect()
   bool signal=false;
   long type=PositionGetInteger(POSITION_TYPE);

   if(type==(long)POSITION_TYPE_BUY   && rt[0].open>ma[0] && rt[0].close<ma[0])
      signal=true;
   if(type==(long)POSITION_TYPE_SELL  && rt[0].open<ma[0] && rt[0].close>ma[0])
      signal=true;
//--- pemeriksaan tambahan
   if(signal)
      if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
         if(Bars(_Symbol,_Period)>100)
           {
            CTrade trade;
            trade.PositionClose(_Symbol,3);
           }
//---
  }

Algoritma dari fungsi CheckForClose() mirip dengan algoritma CheckForOpen(). Tergantung pada arah posisi terbuka saat ini, kondisi penutupannya diperiksa (harga melintasi MA ke bawah untuk beli atau ke atas untuk jual). Posisi terbuka ditutup dengan memanggil metode PositionClose() dari objek trading (instance dari CTrade).

4. Backtesting

Nilai terbaik dari parameter dapat ditemukan menggunakan Strategy Tester pada terminal MetaTrader 5.

Contohnya, saat mengoptimalkan parameter MovingPeriod dalam interval 2012.01.01-2013.08.01, hasil terbaik diperoleh dengan MovingPeriod=45:

Hasil Backtesting dari Moving Average Expert Advisor

Hasil Backtesting dari Moving Average Expert Advisor

Kesimpulan:

Expert Advisor Moving Average yang disertakan dalam paket standar dari MetaTrader 5 adalah contoh penggunaan indikator teknikal, fungsi riwayat trading, dan kelas trading dari Standard Library. Selain itu, EA ini juga mencakup sistem manajemen uang yang berdasarkan hasil trading.


Daftar
Komentar 0