Senin, 17 Desember 2012

Bagian 10 - Money Management

http://www.forexindo.com/forum/tutorial-mql4/7518-bagian-10-money-management.html

pada tutorial kali ini saya akan coba menambahkan money management pada sebuah ea.
ea yang akan diutak-atik adalah ea standard metatrader yaitu "MACD Sample".
saya akan mencoba supaya setiap ordernya hanya menggunakan 1% dari balance. jadi kalau total ordernya ada 5 bersamaan berarti margin yang terpakai cuma 5%.

"misalnya balance kita 10.000 maka 1% nya berarti 100 usd. nah di sini kita akan menghitung 100 usd itu berapa lot."

supaya settingan persen nya bisa diubah sesuai keinginan, maka pertama kita tambahkan extern input seperti ini:
Code:
extern int Risk=1; // dalam percent
extern double lotDigit=1; //berapa decimal lot yang diijinkan. kalau fxopen 1 digit.
untuk menghitung persentase margin, kita juga harus mengetahui berapa margin yang dibutuhkan untuk order 1 lot,
untuk itu akan kita definisikan seperti ini:
Code:
double margin=MarketInfo(Symbol(), MODE_MARGINREQUIRED) ;
nah sekarang kita masuk dalam code MM nya, yaitu menghitung berapa lot untuk order 1 persen dari balance.
Code:
double LotSize()
{
double lot=0;
lot=NormalizeDouble((AccountBalance()*Risk/100)/margin, lotDigit) ; // di sini kita sudah mendapatkan nilai lotnya
if (lot>MarketInfo(Symbol(),MODE_MAXLOT)) { lot=MarketInfo(Symbol(),MODE_MAXLOT); } // di sini di filter supaya jika lotnya lebih besar dari batas maximum lot yang ditentukan broker, maka lotnya diubah sesuai batas maximum lot
if (lot<MarketInfo(Symbol(),MODE_MINLOT)) { lot=MarketInfo(Symbol(),MODE_MINLOT); } // di sini juga di filter supaya jika lotnya lebih kecil dari batas minimum yang sudah ditentukan oleh broker, maka lotnya diubah sesuai batas minimum tersebut
return (lot);
}
selanjutnya tinggal mengaplikasikan kode2 di atas ke dalam EA MACD Sample.
semua perintah ordersend dalam ea tersebut, bagian lotnya diubah jadi LotSize() untuk memanggil fungsi MoneyManagement yang sudah kita buat di atas
contoh yang ini
Code:
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green);
diubah jadi
Code:
ticket=OrderSend(Symbol(),OP_BUY,LotSize(),Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green);


code finalnya seperti ini:



//+------------------------------------------------------------------+
//|                                                  MACD Sample.mq4 |
//|                      Copyright © 2005, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+

extern double TakeProfit = 50;
extern double Lots = 0.1;
extern double TrailingStop = 30;
extern double MACDOpenLevel=3;
extern double MACDCloseLevel=2;
extern double MATrendPeriod=26;
extern int Risk=1; // dalam percent
extern double lotDigit=1; //berapa decimal lot yang di ijinkan. kalau fxopen 1 digit.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
  {
   double MacdCurrent, MacdPrevious, SignalCurrent;
   double SignalPrevious, MaCurrent, MaPrevious;   
   int cnt, ticket, total;
// initial data checks
// it is important to make sure that the expert works with a normal
// chart and the user did not make any mistakes setting external 
// variables (Lots, StopLoss, TakeProfit, 
// TrailingStop) in our case, we check TakeProfit
// on a chart of less than 100 bars
   if(Bars<100)
     {
      Print("bars less than 100");
      return(0);  
     }
   if(TakeProfit<10)
     {
      Print("TakeProfit less than 10");
      return(0);  // check TakeProfit
     }
// to simplify the coding and speed up access
// data are put into internal variables
   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);

   total=OrdersTotal();
   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)
        {
         ticket=OrderSend(Symbol(),OP_BUY,LotSize(),Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green);
         if(ticket>0)
           {
            if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("BUY order opened : ",OrderOpenPrice());
           }
         else Print("Error opening BUY order : ",GetLastError()); 
         return(0); 
        }
      // check for short position (SELL) possibility
      if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && 
         MacdCurrent>(MACDOpenLevel*Point) && MaCurrent<MaPrevious)
        {
         ticket=OrderSend(Symbol(),OP_SELL,LotSize(),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);
     }
   // it is important to enter the market correctly, 
   // but it is more important to exit it correctly...   
   for(cnt=0;cnt<total;cnt++)
     {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if(OrderType()<=OP_SELL &&   // check for opened position 
         OrderSymbol()==Symbol())  // check for symbol
        {
         if(OrderType()==OP_BUY)   // long position is opened
           {
            // should it be closed?
            if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious &&
               MacdCurrent>(MACDCloseLevel*Point))
                {
                 OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
                 return(0); // exit
                }
            // check for trailing stop
            if(TrailingStop>0)  
              {                 
               if(Bid-OrderOpenPrice()>Point*TrailingStop)
                 {
                  if(OrderStopLoss()<Bid-Point*TrailingStop)
                    {
                     OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green);
                     return(0);
                    }
                 }
              }
           }
         else // go to short position
           {
            // should it be closed?
            if(MacdCurrent<0 && MacdCurrent>SignalCurrent &&
               MacdPrevious<SignalPrevious && MathAbs(MacdCurrent)>(MACDCloseLevel*Point))
              {
               OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // close position
               return(0); // exit
              }
            // check for trailing stop
            if(TrailingStop>0)  
              {                 
               if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
                 {
                  if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0))
                    {
                     OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red);
                     return(0);
                    }
                 }
              }
           }
        }
     }
   return(0);
  }
double LotSize()
{
   double margin=MarketInfo(Symbol(), MODE_MARGINREQUIRED);
   double lot=0;   
   lot=NormalizeDouble((AccountBalance()*Risk/100)/margin, lotDigit) ; // di sini kita sudah mendapatkan nilai lotnya
   if (lot>MarketInfo(Symbol(),MODE_MAXLOT)) { lot=MarketInfo(Symbol(),MODE_MAXLOT); } // di sini di filter supaya jika lotnya lebih besar dari batas maximum, maka lotnya diubah sesuai batas maximum lot
   if (lot<MarketInfo(Symbol(),MODE_MINLOT)) { lot=MarketInfo(Symbol(),MODE_MAXLOT); } // di sini di filter supaya jika lotnya lebih kecil dari batas minimum yang sudah ditentukan oleh broker, maka lotnya diubah sesuai batas minimum tersebut
   return (lot);
}

// the end.


Bagian 9 - Implementasi Custom Indikator


http://www.forexindo.com/forum/tutorial-mql4/1104-bagian-9-implementasi-custom-indikator.html

iCustom

Jika anda memiliki indikator sendiri, dan ingin membuat EA berdasarkan indikator tersebut, maka ada 2 solusi yang bisa dipakai.

1) menggunakan function iCustom()
2) mengembed algoritma indikator ke EA nya

menggunakan iCustom lebih simpel dan rapi daripada mengembed algoritma indikator ke dalam EA (karena EA nya nanti jadi panjang codingnya)..

fungsi lengkapnya :

Code:
double iCustom( string symbol, int timeframe, string name, ..., int mode, int shift)
ok, sebagai contoh, gw punya indikator range1 (gw attach ex4 nya). indikator ini menampilkan bar range seperti ini :



nah, gw mau mengimplementasikan nilai dari indikator ini (range=absolute(high-low)) ke EA gw. 

kita pake aja contoh EA yang di bagian 8.

7) Posisi baru dibuka kalau sedang tidak ada posisi, dan juga tidak trade di hari Jumat (gw tambahi rulenya)
gw tambahi jadi

7) Posisi baru dibuka kalau sedang tidak ada posisi, dan juga tidak trade di hari Jumat, dan range candle jam sekarang dan jam sebelumnya tidak boleh lebih dari 100 pip.
nah, gimana caranya untuk mendapatkan nilai dari iCustom..

contoh sekarang, custom indikatornya bernama range1.ex4 (ada di folder expert/indicator)

maka, syntaxnya begini :

[code]
double range0, range1=0;
range0=iCustom(Symbol(),0,"range1",0,0); //range pada candle jam sekarang
range1=iCustom(Symbol(),0,"range1",0,1); //range pada candle jam sebelom sekarang
[code]

sedangkan di EA nya, asalnya :

Code:
bool bolehTrade()
{
//kalau jumat, EA ga trade ; atau kalau ada order terbuka, EA juga ga trade
if (DayOfWeek()==5 || OrdersTotal()>0) { return (false); } else { return(true); }
}
ditambahi jadi begini

Code:
bool bolehTrade()
{
//kalau jumat, EA ga trade ; atau kalau ada order terbuka, EA juga ga trade
//klo range diatas 100 untuk candle sekarang dan sebelomnya, juga ga trade
range0=iCustom(Symbol(),0,"range1",0,0); //range pada candle jam sekarang
range1=iCustom(Symbol(),0,"range1",0,1); //range pada candle jam sebelom sekarang
if (DayOfWeek()==5 || OrdersTotal()>0 || range0>100 || range1>100 ) { return (false); } else { return(true); }
}
gampang kan 

pada iCustom :
Symbol() = symbol dimana ea dipasang
0 = timeframe dimana ea dipasang (kalau mau fix 30 menit, ya isi aja PERIOD_M30)
range1 = nama ex4 custom indikatornya (range1.ex4)
0 = mode
0,1 (paling belakang) = shift (penjelasannya ada di bagian fungsi indikator)

mode

Mode dalam iCustom itu untuk memilih mendapatkan nilai dari buffer yang mane (buffer 0-7)

kebetulan indikator range1 tadi cuman 1 kluaran outputnya, jadi ya pilih mode 0



contoh indikator yang kasih keluaran 6 output : (gw ambil dari indikator member di bagian 8)



maka klo mo ambil nilai DownTrendLine misalnya, ya mode nya diisi 5

Code:
iCustom(Symbol(),0,"namaindi",........(inputan).....,5,0)
nah, kebetulan juga indikator range1 tadi tidak ada inputan, bagaimana klo indikatornya ada inputan, seperti yang di bagian 8 (Bagian 8 - Menyusun EA)



nah.... jadi begitu 
paramater2 inputannya ditaruh seperti itu (garis2 biru) (moga2 ngerti klo liat gambarnya)...
terus mode yang gw maksud itu untuk mendapatkan nilai yang gw kasih garis ijo

iCustom ini cukup luas penerapannya.. tapi basicnya ya seperti contoh2 diatas..

klo ada pertanyaan silakan di post..

http://ea.dwim.web.id


//|                                                     @DwiMalistyo |
//| http://ea.dwim.web.id |
//+------------------------------------------------------------------+
#property copyright "@DwiMalistyo"
#property link "http://ea.dwim.web.id"

/*-- Parameter ini ditampilkan di EA dan bisa diubah --*/
extern int TakeProfit = 10; // Nilai TP setiap OP di EA Martingale ini
extern int PipStep = 10; // Jarak pip dimana akan buka OP baru
extern int Slippage = 3; // Apa itu slippage ? Googling sendiri ya..
extern double Lots = 0.1; // Nilai lots awal, nantinya akan digandakan setiap step
extern double Multiply = 2.0; // Nilai pengali setiap step OP baru
extern int MaxTrade = 11; // Banyak OP maksimal yang boleh dijalankan
extern bool UseTime = TRUE; // Pilihan apakah memakai waktu bekerjanya EA ?
extern int HourStart = 18; // Waktu mulai EA bekerja
extern int HourEnd = 24; // Waktu akhir EA bekerja

/*-- Parameter ini tidak ditampilkan di EA --*/
string EAName = "EA DwiM Martingale2MA ver 1.0"; // Nama EA, untuk ditampilkan di layar
string EAComment = "DwiM"; // Variabel ini akan kita masukkan di setiap OP sebagai Comment
int EAMagicNumber = 8095; // Magic Number
double SetPoint = 0; // Variabel SetPoint untuk kode digit broker 4 atau 5


//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----

SetBroker();

//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----

//----
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----

int iTrade=0;

double SMA18=0, EMA200=0;

SMA18=iMA(NULL, 0, 18, 0, MODE_SMA, PRICE_CLOSE, 0 );
EMA200=iMA(NULL, 0, 200, 0, MODE_EMA, PRICE_CLOSE, 0);

Comment(EAName); // Tampilkan Nama EA di layar

/* -- Jika tidak ada OP sama sekali, maka jalankan fungsi berikut --*/
/* -- Disinilah tempat anda memasukkan koding indikator untuk memicu OP --*/
if(OrdersTotal()==0)
{

if((Bid > SMA18) && (SMA18 > EMA200))
{
/*-- Order Buy --*/
OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, 0, Ask+TakeProfit*SetPoint, EAComment, EAMagicNumber);

}
else if((Ask < SMA18) && (SMA18 < EMA200))
{
/*-- Order Sell --*/
OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, 0, Bid-TakeProfit*SetPoint, EAComment, EAMagicNumber);
}

}


/* -- Inilah Fungsi Martingale. Jika ada OP yang salah, maka lakukan martingale --*/
if(OrdersTotal()>=1)
{
GoMartingale();
}


//----
return(0);
}
//+------------------------------------------------------------------+

/*--agar EA bisa running di Broker 4 Digit atau 5 Digit--*/
void SetBroker()
{
if (Digits==3 || Digits==5) // Perintah untuk broker 5 Digits
{SetPoint=Point*10;}
else // Perintah untuk broker 4 Digits
{SetPoint=Point;}
}

void GoMartingale()
{
int iCount = 0;
double LastOP = 0;
double LastLots = 0;
bool LastIsBuy = FALSE;
int iTotalBuy = 0;
int iTotalSell = 0;
int Spread=0;

Spread= MarketInfo(Symbol(), MODE_SPREAD);


for(iCount=0;iCount<OrdersTotal();iCount++)
{

OrderSelect(iCount,SELECT_BY_POS,MODE_TRADES);

if(OrderType()==OP_BUY && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(LastOP==0) {LastOP=OrderOpenPrice();}
if(LastOP>OrderOpenPrice()) {LastOP=OrderOpenPrice();}
if(LastLots<OrderLots()) {LastLots=OrderLots();}
LastIsBuy=TRUE;
iTotalBuy++;

/* Bila mencapai batas OP maksimal, jangan tambah OP lagi */
if(iTotalBuy==MaxTrade) {return(0);}
}

if(OrderType()==OP_SELL && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(LastOP==0) {LastOP=OrderOpenPrice();}
if(LastOP<OrderOpenPrice()) {LastOP=OrderOpenPrice();}
if(LastLots<OrderLots()) {LastLots=OrderLots();}
LastIsBuy=FALSE;
iTotalSell++;

/* Bila mencapai batas OP maksimal, jangan tambah OP lagi */
if(iTotalBuy==MaxTrade) {return(0);}
}

}

/* Jika arah Price adalah DOWNTREND...., Periksa nilai Bid (*/
if(LastIsBuy)
{
if(Bid<=LastOP-(Spread*SetPoint)-(PipStep*SetPoint))
{
OrderSend(Symbol(), OP_BUY, Multiply*LastLots, Ask, Slippage, 0, Ask+TakeProfit*SetPoint, EAComment, EAMagicNumber);
ModifyTP();
LastIsBuy=FALSE;
return(0);
}
}
/* Jika arah Price adalah Sell...., Periksa nilai Ask (*/
else if(!LastIsBuy)
{
if(Ask>=LastOP+(Spread*SetPoint)+(PipStep*SetPoint))
{
OrderSend(Symbol(), OP_SELL, Multiply*LastLots, Bid, Slippage, 0, Bid-TakeProfit*SetPoint, EAComment, EAMagicNumber);
ModifyTP();
return(0);
}
}

}

/*-- Fungsi ModifyTP ini untuk mengubah semua OP agar TP di titik yang sama --*/
void ModifyTP()
{
int iCount=0;
double NewTP=0;

/*- Ambil nilai Take Profit dari Order terakhir -*/
for(iCount=0;iCount<OrdersTotal();iCount++)
{

OrderSelect(iCount,SELECT_BY_POS,MODE_TRADES);

/*-- Kalau OP-nya adalah BUY, ambil nilai TP yang paling kecil. Jadikan TP bersama --*/
if(OrderType()==OP_BUY && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(NewTP==0) {NewTP=OrderTakeProfit();}
if(NewTP>OrderTakeProfit()) {NewTP=OrderTakeProfit();}

}

/*-- Kalau OP-nya adalah SELL, ambil nilai TP yang paling besar. Jadikan TP bersama --*/
if(OrderType()==OP_SELL && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(NewTP==0) {NewTP=OrderTakeProfit();}
if(NewTP<OrderTakeProfit()) {NewTP=OrderTakeProfit();}
}

}

/*- Ubah semua nilai OP TakeProfit dengan yang baru (2x lipat) -*/
for(iCount=0;iCount<OrdersTotal();iCount++)
{

OrderSelect(iCount,SELECT_BY_POS,MODE_TRADES);

/*- Kalau semua OP adalah BUY, maka ubahlah TP mereka -*/
if(OrderType()==OP_BUY && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
OrderModify(OrderTicket(), OrderLots(), 0, NewTP, 0);
}

/*- Kalau semua OP adalah SELL, maka ubahlah TP mereka -*/
if(OrderType()==OP_SELL && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
OrderModify(OrderTicket(), OrderLots(), 0, NewTP, 0);
}

}

EA DwiM Martingale2MA.mq4


//+------------------------------------------------------------------+
//| EA DwiM Martingale2MA.mq4 |
//| @DwiMalistyo |
//| http://ea.dwim.web.id |
//+------------------------------------------------------------------+
#property copyright "@DwiMalistyo"
#property link "http://ea.dwim.web.id"

/*-- Parameter ini ditampilkan di EA dan bisa diubah --*/
extern int TakeProfit = 10; // Nilai TP setiap OP di EA Martingale ini
extern int PipStep = 10; // Jarak pip dimana akan buka OP baru
extern int Slippage = 3; // Apa itu slippage ? Googling sendiri ya..
extern double Lots = 0.1; // Nilai lots awal, nantinya akan digandakan setiap step
extern double Multiply = 2.0; // Nilai pengali setiap step OP baru
extern int MaxTrade = 11; // Banyak OP maksimal yang boleh dijalankan
extern bool UseTime = TRUE; // Pilihan apakah memakai waktu bekerjanya EA ?
extern int HourStart = 18; // Waktu mulai EA bekerja
extern int HourEnd = 24; // Waktu akhir EA bekerja

/*-- Parameter ini tidak ditampilkan di EA --*/
string EAName = "EA DwiM Martingale2MA ver 1.0"; // Nama EA, untuk ditampilkan di layar
string EAComment = "DwiM"; // Variabel ini akan kita masukkan di setiap OP sebagai Comment
int EAMagicNumber = 8095; // Magic Number
double SetPoint = 0; // Variabel SetPoint untuk kode digit broker 4 atau 5

//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----

SetBroker();

//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----

//----
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----

int iTrade=0;

double SMA18=0, EMA200=0;

SMA18=iMA(NULL, 0, 18, 0, MODE_SMA, PRICE_CLOSE, 0 );
EMA200=iMA(NULL, 0, 200, 0, MODE_EMA, PRICE_CLOSE, 0);

Comment(EAName); // Tampilkan Nama EA di layar

/* -- Jika tidak ada OP sama sekali, maka jalankan fungsi berikut --*/
/* -- Disinilah tempat anda memasukkan koding indikator untuk memicu OP --*/
if(OrdersTotal()==0)
{

if((Bid > SMA18) && (SMA18 > EMA200))
{
/*-- Order Buy --*/
OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, 0, Ask+TakeProfit*SetPoint, EAComment, EAMagicNumber);

}
else if((Ask < SMA18) && (SMA18 < EMA200))
{
/*-- Order Sell --*/
OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, 0, Bid-TakeProfit*SetPoint, EAComment, EAMagicNumber);
}

}


/* -- Inilah Fungsi Martingale. Jika ada OP yang salah, maka lakukan martingale --*/
if(OrdersTotal()>=1)
{
GoMartingale();
}


//----
return(0);
}
//+------------------------------------------------------------------+

/*--agar EA bisa running di Broker 4 Digit atau 5 Digit--*/
void SetBroker()
{
if (Digits==3 || Digits==5) // Perintah untuk broker 5 Digits
{SetPoint=Point*10;}
else // Perintah untuk broker 4 Digits
{SetPoint=Point;}
}

void GoMartingale()
{
int iCount = 0;
double LastOP = 0;
double LastLots = 0;
bool LastIsBuy = FALSE;
int iTotalBuy = 0;
int iTotalSell = 0;
int Spread=0;

Spread= MarketInfo(Symbol(), MODE_SPREAD);


for(iCount=0;iCount<OrdersTotal();iCount++)
{

OrderSelect(iCount,SELECT_BY_POS,MODE_TRADES);

if(OrderType()==OP_BUY && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(LastOP==0) {LastOP=OrderOpenPrice();}
if(LastOP>OrderOpenPrice()) {LastOP=OrderOpenPrice();}
if(LastLots<OrderLots()) {LastLots=OrderLots();}
LastIsBuy=TRUE;
iTotalBuy++;

/* Bila mencapai batas OP maksimal, jangan tambah OP lagi */
if(iTotalBuy==MaxTrade) {return(0);}
}

if(OrderType()==OP_SELL && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(LastOP==0) {LastOP=OrderOpenPrice();}
if(LastOP<OrderOpenPrice()) {LastOP=OrderOpenPrice();}
if(LastLots<OrderLots()) {LastLots=OrderLots();}
LastIsBuy=FALSE;
iTotalSell++;

/* Bila mencapai batas OP maksimal, jangan tambah OP lagi */
if(iTotalBuy==MaxTrade) {return(0);}
}

}

/* Jika arah Price adalah DOWNTREND...., Periksa nilai Bid (*/
if(LastIsBuy)
{
if(Bid<=LastOP-(Spread*SetPoint)-(PipStep*SetPoint))
{
OrderSend(Symbol(), OP_BUY, Multiply*LastLots, Ask, Slippage, 0, Ask+TakeProfit*SetPoint, EAComment, EAMagicNumber);
ModifyTP();
LastIsBuy=FALSE;
return(0);
}
}
/* Jika arah Price adalah Sell...., Periksa nilai Ask (*/
else if(!LastIsBuy)
{
if(Ask>=LastOP+(Spread*SetPoint)+(PipStep*SetPoint))
{
OrderSend(Symbol(), OP_SELL, Multiply*LastLots, Bid, Slippage, 0, Bid-TakeProfit*SetPoint, EAComment, EAMagicNumber);
ModifyTP();
return(0);
}
}

}

/*-- Fungsi ModifyTP ini untuk mengubah semua OP agar TP di titik yang sama --*/
void ModifyTP()
{
int iCount=0;
double NewTP=0;

/*- Ambil nilai Take Profit dari Order terakhir -*/
for(iCount=0;iCount<OrdersTotal();iCount++)
{

OrderSelect(iCount,SELECT_BY_POS,MODE_TRADES);

/*-- Kalau OP-nya adalah BUY, ambil nilai TP yang paling kecil. Jadikan TP bersama --*/
if(OrderType()==OP_BUY && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(NewTP==0) {NewTP=OrderTakeProfit();}
if(NewTP>OrderTakeProfit()) {NewTP=OrderTakeProfit();}

}

/*-- Kalau OP-nya adalah SELL, ambil nilai TP yang paling besar. Jadikan TP bersama --*/
if(OrderType()==OP_SELL && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(NewTP==0) {NewTP=OrderTakeProfit();}
if(NewTP<OrderTakeProfit()) {NewTP=OrderTakeProfit();}
}

}

/*- Ubah semua nilai OP TakeProfit dengan yang baru (2x lipat) -*/
for(iCount=0;iCount<OrdersTotal();iCount++)
{

OrderSelect(iCount,SELECT_BY_POS,MODE_TRADES);

/*- Kalau semua OP adalah BUY, maka ubahlah TP mereka -*/
if(OrderType()==OP_BUY && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
OrderModify(OrderTicket(), OrderLots(), 0, NewTP, 0);
}

/*- Kalau semua OP adalah SELL, maka ubahlah TP mereka -*/
if(OrderType()==OP_SELL && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
OrderModify(OrderTicket(), OrderLots(), 0, NewTP, 0);
}

}
}

Mengambil nilai indikator tanpa index buffer


http://www.forexindo.com/forum/tutorial-mql4/12842-mengambil-nilai-indikator-tanpa-index-buffer.html


Sebelumnya sudah di bahas bagaimana membaca nilai indikator dengan index buffer di Bagian 9 - Implementasi Custom Indikator, tetapi tidak semua indikator memiliki index buffer. nah disini saya akan coba bahas bagaimana mengambil nilainya dengan menggunakan "objectget".

pada contoh saat ini saya akan coba membuat ea menggunakan indicator camarilla
setelah di attach ke chart akan tampil gambar indicatornya seperti ini



sebelum masuk ke coding kita harus mengetahui dulu nama-nama dari object yang akan kita gunakan. dalam kasus ini yang kita butuhkan nama dari garis-garis H3 Long, L4 Short, H3 Short dan H4 Long. untuk mengetahui namanya, klik kanan di dalam chart lalu pilih "Object List" akan tampil seperti gambar berikut.

di atas kita sudah bisa melihat nama dari object2 yang kita butuhkan, yaitu:
L3 Long = L3 Line
L4 Short Breakout = L4 Line
H3 Short = H3 Line
H4 Long Brekaout = H4 Line

selanjutnya buka metaeditor untuk coding.
kita akan mengambil harga dari garis-garis horisontal camarilla tersebut dengan objectget.
formatnya
Code:
double ObjectGet(string name, int index);
string name = nama objectnya
int index = value yang akan diambil dari object tersebut. mis: waktu,harga,warna, dll.
karena kita akan mengambil harganya maka untuk "index"nya kita gunakan "OBJPROP_PRICE1".

maka kita codingkan seperti berikut
Code:
double beli=ObjectGet("l3 line",OBJPROP_PRICE1); // Level dimana kita akan melakukan order buy
double sl_beli=ObjectGet("l4 line",OBJPROP_PRICE1); // Level StopLoss untuk posisi buy
double jual=ObjectGet("h3 line",OBJPROP_PRICE1); // Level dimana kita akan melakukan order sell
double sl_jual=ObjectGet("h4 line",OBJPROP_PRICE1); // level stoploss untuk posisi sell
dari code di atas kita sudah mendapatkan harga dari masing2 garis-garis camarilla tersebut. selanjutnya kita akan coding perintah order dengan system :

-Buy di level L3 Long, Stop Loss L4 Short Breakout
-Sell di level H3 Short, Stop Loss H4 Long Breakout

Code:
if (OrdersTotal()<1) // code untuk hanya melakukan order jika tidak ada order aktif. sehingga hanya ada satu transaksi.
{
if (Bid+1*Point >= beli && Bid-1*Point <= beli) OrderSend(Symbol(),0,0.1,Ask,3,sl_beli,jual,0,0,0,0);
else if (Bid+1*Point >= jual && Bid-1*Point <= jual) OrderSend(Symbol(),1,0.1,Bid,3,sl_jual,beli,0,0,0,0);
}
mungkin ada yang bertanya kenapa saya tidak gunakan
"if (bid==beli)" atau "if (bid==jual)" yang codenya lebih pendek dan simple. tapi pada prakteknya kalau kita gunakan code itu maka seringkali saat harga bid sudah menyentuh garis, EA nya tidak melakukan order. sehingga saya gunakan code di atas yang lebih mudah mendeteksi harga yang sama.

ok ea kita sudah selesai, code selengkapnya seperti ini

Code:
int start()
{
double beli=ObjectGet("l3 line",OBJPROP_PRICE1); // Level dimana kita akan melakukan order buy
double sl_beli=ObjectGet("l4 line",OBJPROP_PRICE1); // Level StopLoss untuk posisi buy
double jual=ObjectGet("h3 line",OBJPROP_PRICE1); // Level dimana kita akan melakukan order sell
double sl_jual=ObjectGet("h4 line",OBJPROP_PRICE1); // level stoploss untuk posisi sell

if (OrdersTotal()<1)
{
if (Bid+1*Point >= beli && Bid-1*Point <= beli) OrderSend(Symbol(),0,0.1,Ask,3,sl_beli,jual,0,0,0,0);
else if (Bid+1*Point >= jual && Bid-1*Point <= jual) OrderSend(Symbol(),1,0.1,Bid,3,sl_jual,beli,0,0,0,0);
}
return(0);
}
kelemahan dari mengambil harga indikator berdasarkan objectget adalah saat kita menjalankan EA ini maka indicatornya juga harus di attach ke chart. karena EA tersebut mencari objectnya di chart tersebut.

Detailed Statement

iseng2 backtest dari januari bisa capai 100%. untuk lebih lanjut mengenai bagaimana cara optimize EA bisa ikut seminar diSeminar Advance Pengenalan, Penggunaan dan Optimasi Expert Advisor/ Robot Trading

Silahkan reply thread ini jika ada yang ingin ditanyakan mengenai "objectget" 
Last edited by chandrawg; 15 March 2011 at 11:17.



===========================================================
kasus :


Keterangan gbr yg sy lingkarin : 
- Kalau actual < forecast => warnanya merah
- Nah berarti kita bisa mengambil dari perubahan warnanya

Misal begini :
double obj;
int start()
obj = ObjectGet("xxxxxxx",OBJPROP_COLOR);
IF (DoubleToStr(obj,0) == "255") // Warna merah
maka harga turun........

Jumat, 07 Desember 2012

Studi Kasus: Koding Simple EA Martingale

http://indo.mt5.com/showthread.php?9497-%26%239668%3B%26%231769%3B%26%239679%3B%26%231757%3B%26%239679%3B%26%231769%3B%26%239658%3B-Studi-Kasus-Koding-Simple-EA-Martingale.



 Studi Kasus: Koding Simple EA Martingale.

 Salam profit untuk trader-trader yang baik hati di Forum MT5.

Dear moderator dan admin, mudah-mudahan tidak bosan dengan ulah si newbie nekat ini. Kali ini saya mohon ijinnya sekali lagi untuk membuka thread baru mengenai coding-codingan EA buat pemula. Mumpung lagi libur akhir tahun, ada sedikit waktu untuk bongkar pasang EA dan meramaikan forum. Mudah-mudahan thread ini bermanfaat untuk rekan-rekan.

Pertama kali saya mohon maaf kepada teman-teman yang sering mengirim email dan PM kepada saya. Terus terang email dari teman-teman banyak sekali. Ada yang bertanya soal coding indikator, coding EA, ada yang minta settingan, ada yang minta EA-nya dijebol proteksinya dan lain-lainlah. Karena saya masih kerja fulltime maka tidak semua email bisa direspons. Tapi jangan patah semangat ya, kalau saya sempat pasti akan dibalas. Doakan saya bisa trading fulltime, jadi kita bisa diskusi sambil ngopi bareng kapan aja.

Thread kali ini membahas pertanyaan teman-teman yang sering ditanyakan di email. Yaitu minta codingan Martingale jika misalnya OP-nya salah arah. "Gan, tulung donk. Tambahin codingan di EA ane, jadi kalo misalnya OP-nya salah maka akan dimartiyem". Email seperti ini bukan cuma sekali dua kali. Lama-lama jadi inget pepatahnya master Givonly untuk memberi kail dan bukan memberi ikan. Jadi mungkin sebaiknya kita buatkan saja thread simple untuk membahas codingan Martingale sederhana. Jadi kapan saja teman-teman memerlukan, tinggal copy coding ini ke EA-nya. Kutak-kutik sedikit, dan bisa langsung dijalankan.

Mohon jangan berharap terlalu banyak dari thread ini. Namanya juga thread simple. Jangan berharap hasilnya bisa dibandingkan dengan (misalnya) EA Sejuta Umat yang sudah tersohor di dunia persilatan Forex. Disini saya mencoba membuat coding yang sangat simple dan sederhana, hanya untuk proses belajar teman-teman yang sedang getol mengutak-utik coding EA. Harapannya hanya untuk memotivasi teman-teman yang siang-malam berjuang menekuni dunia programming EA. Biar tambah semangat. Semoga para programmer EA kita akan membawa nama harum bagi nusa dan bangsa di kancah internasional. Amin.

Untuk para master EA, mohon dukungannya agar thread ini rame. Terus terang saya memimpikan trader dan programmer EA Indonesia tidak kalah pamor sama bangsa sebelah. Mari kita bersatu hati saling mengisi satu sama lain. Kritikan dan saran saya nantikan untuk memperbaiki diri saya. Terima kasih.

*Pidato pak Lurah sudah selesai, yang mau nge-klik thanks di bawah ini tidak usah malu dan ragu-ragu*

--------------------------------------------------------------

Apa itu Martingale ?

Menurut Wikipedia, Martingale adalah strategi betting yang mulai populer di Perancis pada abad ke 18. Strateginya adalah bertaruh hanya pada satu sisi koin, dan jika kalah maka dia akan bertaruh pada sisi koin yang sama sambil melipatgandakan taruhannya. Demikian terus-menerus dia akan bertaruh pada satu sisi koin itu dengan melipatgandakan taruhannya. Harapannya adalah dengan sekali kemenangan dia akan merecover semua kerugian sebelumnya.

Dunia Forex mirip situasi betting Perancis ini. Sebab ada sisi koin "buy" dan sisi koin "sell". Para trader yang berpengalaman menggunakan martingale sangat yakin ketangguhan martingale ini. Kata mereka, "Apa yang naik, pasti akan turun. Dan apa yang turun, pasti akan naik". Jadi betting Martingale Perancis cocok diterapkan di dalam Forex. Saya sendiri masih jantungan dengan strategi martingale, dan sementara ini hanya senang membuatkan coding buat teman-teman saja.

Langsung saja kita masuk lebih dalam. Saya mendapat gambar dari thread yang pernah dibuat master Tenyom Goreng di forum ini sbb (mohon ijin ya master) :

riset martingale...bisakah sistem ini menjauh sejauh mungkin dari margin call
http://indo.mt5.com/showthread.php?779-riset-martingale


Dari gambar di atas, kita akan membuat coding sederhana EA Martingale. Dimana nanti strateginya adalah EA akan membuka lagi posisi OP yang salah (floating minus) yang jaraknya senilai PipStep. Sementara lot-nya akan digandakan 2 kali. Dan nilai semua TP akan digeser mengikuti nilai TP dari OP yang terakhir.

Jadi dari EA Simple Martingale ini kita akan menemukan fungsi-fungsi sebagai berikut :

1. Fungsi Pemicu sebagai trigger OP pertama :Ini terserah strategi teman-teman, hanya untuk OP pertama saja. Misalnya teman-teman memakai cross 2 buah MA untuk OP buy atau sell.

2. Fungsi GoMartingale : Fungsi ini memeriksa apakah ada OP yang salah ? Jika ya, maka akan dibuat OP baru searah dengan OP semula. Dengan lot yang digandakan.

3. Fungsi Modifikasi TP : Di dalam fungsi ini, semua OP martingale akan dimodifikasi TP-nya.

*Istirahat sebentar ya, nanti kita lanjutkan*

----------------------------------------------------------------
 Ini adalah contoh strategi gabungan MA dan Martingale. Kita lihat gambar di bawah.

Ada garis SMA 18 Close (warna merah) dan garis EMA200 Close (warna putih). Strateginya adalah :

- Kalau price berada di atas SMA18, dan SMA18 berada di atas EMA200, maka BUY dengan TP 10 pip.

- Kalau price berada di bawah SMA18, dan SMA18 berada di bawah EMA200, maka SELL dengan TP 10 pip.

- Jika order salah arah, lakukan martingale dengan PipStep 10 pip.



Sistem ini seperti diduga, akan berjalan terus-menerus. Bila satu OP sudah mengenai TP, maka dia akan OP lagi. Begitu seterusnya. Bila arahnya salah, OP-nya akan ditambah dengan OP Martingale.

EA ini akan berjalan dengan agresif, terus-menerus. Saat ini untuk studi, kita tidak membatasi dengan coding waktu. Biarkan EA berjalan 24 jam.

---------------------------------------------------------------

EA Martingale2MA

Kita akan mulai dengan coding variabel-nya, sbb

Code:
//+------------------------------------------------------------------+
//| EA DwiM Martingale2MA.mq4 |
//| @DwiMalistyo |
//| http://ea.dwim.web.id |
//+------------------------------------------------------------------+
#property copyright "@DwiMalistyo"
#property link "http://ea.dwim.web.id"

/*-- Parameter ini ditampilkan di EA dan bisa diubah --*/
extern int TakeProfit = 10; // Nilai TP setiap OP di EA Martingale ini
extern int PipStep = 10; // Jarak pip dimana akan buka OP baru
extern int Slippage = 3; // Apa itu slippage ? Googling sendiri ya..
extern double Lots = 0.1; // Nilai lots awal, nantinya akan digandakan setiap step
extern double Multiply = 2.0; // Nilai pengali setiap step OP baru
extern int MaxTrade = 11; // Banyak OP maksimal yang boleh dijalankan
extern bool UseTime = TRUE; // Pilihan apakah memakai waktu bekerjanya EA ?
extern int HourStart = 18; // Waktu mulai EA bekerja
extern int HourEnd = 24; // Waktu akhir EA bekerja

/*-- Parameter ini tidak ditampilkan di EA --*/
string EAName = "EA DwiM Martingale2MA ver 1.0"; // Nama EA, untuk ditampilkan di layar
string EAComment = "DwiM"; // Variabel ini akan kita masukkan di setiap OP sebagai Comment
int EAMagicNumber = 8095; // Magic Number
double SetPoint = 0; // Variabel SetPoint untuk kode digit broker 4 atau 5
Yang terpenting dari variable di atas adalah :

TakeProfit, yaitu 10 pip.
PipStep, yaitu 10 pip.
Multiply, ini adalah angka pengali. Biasa diisi 2x atau 1.7x. Tergantung strategi martingalenya.
- MaxTrade, ini adalah batas maksimal OP martingale yang akan dibuat oleh EA.

Baiklah, sekarang kita masuk ke coding indikatornya. Kalau agan-agan mengikuti thread Studi Kasus yang pertama, banyak contoh coding dengan memakai indikator MA disana.

Langsung saja ke aplikasinya :
 Code:
int start()
{
//----

int iTrade=0;

double SMA18=0, EMA200=0;

SMA18=iMA(NULL, 0, 18, 0, MODE_SMA, PRICE_CLOSE, 0 );
EMA200=iMA(NULL, 0, 200, 0, MODE_EMA, PRICE_CLOSE, 0);

Comment(EAName); // Tampilkan Nama EA di layar

/* -- Jika tidak ada OP sama sekali, maka jalankan fungsi berikut --*/
/* -- Disinilah tempat anda memasukkan koding indikator untuk memicu OP --*/
if(OrdersTotal()==0)
{

if((Bid > SMA18) && (SMA18 > EMA200))
{
/*-- Order Buy --*/
OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, 0, Ask+TakeProfit*SetPoint, EAComment, EAMagicNumber);

}
else if((Ask < SMA18) && (SMA18 < EMA200))
{
/*-- Order Sell --*/
OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, 0, Bid-TakeProfit*SetPoint, EAComment, EAMagicNumber);
}

}

}
Coding di atas adalah pemicu dari OP. Jika price berada di atas SMA18 dan SMA18 berada di atas EMA200 maka BUY. Demikian pula sebaliknya.

Dalam coding di atas, saya usahakan menuliskan banyak comment agar mudah dipahami oleh rekan trader yang baru belajar EA.

Sekarang kita masuk ke coding martingalenya.

---------------------------------------------------------

Fungsi GoMartingale dan Fungsi ModifyTP

Mengulang penjelasan di awal, ada 2 fungsi di EA Simple ini. Yaitu GoMartingale dan ModifyTP.

Fungsi GoMartingale penampakannya adalah sbb. Ini dibuat sesimple mungkin dalam satu fungsi. Tugas fungsi ini adalah memeriksa apakah OP-nya salah arah. Jika salah arah, maka fungsi akan membuat satu OP lagi searah dengan sebelumnya, dengan lot yang sudah dilipatduakan.

Code:
void GoMartingale()
{
int iCount = 0;
double LastOP = 0;
double LastLots = 0;
bool LastIsBuy = FALSE;
int iTotalBuy = 0;
int iTotalSell = 0;
int Spread=0;

Spread= MarketInfo(Symbol(), MODE_SPREAD);


for(iCount=0;iCount<OrdersTotal();iCount++)
{

OrderSelect(iCount,SELECT_BY_POS,MODE_TRADES);

if(OrderType()==OP_BUY && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(LastOP==0) {LastOP=OrderOpenPrice();}
if(LastOP>OrderOpenPrice()) {LastOP=OrderOpenPrice();}
if(LastLots<OrderLots()) {LastLots=OrderLots();}
LastIsBuy=TRUE;
iTotalBuy++;

/* Bila mencapai batas OP maksimal, jangan tambah OP lagi */
if(iTotalBuy==MaxTrade) {return(0);}
}

if(OrderType()==OP_SELL && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(LastOP==0) {LastOP=OrderOpenPrice();}
if(LastOP<OrderOpenPrice()) {LastOP=OrderOpenPrice();}
if(LastLots<OrderLots()) {LastLots=OrderLots();}
LastIsBuy=FALSE;
iTotalSell++;

/* Bila mencapai batas OP maksimal, jangan tambah OP lagi */
if(iTotalBuy==MaxTrade) {return(0);}
}

}

/* Jika arah Price adalah DOWNTREND...., Periksa nilai Bid (*/
if(LastIsBuy)
{
if(Bid<=LastOP-(Spread*SetPoint)-(PipStep*SetPoint))
{
OrderSend(Symbol(), OP_BUY, Multiply*LastLots, Ask, Slippage, 0, Ask+TakeProfit*SetPoint, EAComment, EAMagicNumber);
ModifyTP();
LastIsBuy=FALSE;
return(0);
}
}
/* Jika arah Price adalah Sell...., Periksa nilai Ask (*/
else if(!LastIsBuy)
{
if(Ask>=LastOP+(Spread*SetPoint)+(PipStep*SetPoint))
{
OrderSend(Symbol(), OP_SELL, Multiply*LastLots, Bid, Slippage, 0, Bid-TakeProfit*SetPoint, EAComment, EAMagicNumber);
ModifyTP();
return(0);
}
}

}
Fungsi yang kedua, adalah ModifyTP.

Untuk memahami fungsi ini, saya berikan gambaran sbb. Ini saya ambil dari penjelasan Wikipedia mengenai Martingale Betting di Perancis.

Kalau ada OP1 senilai 0.1 salah arah, maka akan dibuat OP2 dengan lot 2x lipat. Nah, karena OP1 dianggap gagal -- maka TP dari OP1 dan TP dari OP2 disamakan. Yaitu sama-sama di titik TP-nya OP2.

Kalau ada 3 OP Martingale, maka TP-nya disamakan semua senilai TP OP yang ke-3
Kalau ada 4 OP Martingale, maka TP-nya disamakan semua senilai TP OP yang ke-4
Demikian seterusnya.

Mohon maaf untuk master martingale, saya memahami bahwa banyak varian martingale di luar sana. Coding ini hanya membahas salah satu varian martingale. Yang penting teman-teman bisa coding dulu. Masalah variannya nanti tergantung keinginan mereka kalau sudah mahir di coding.

Nah, fungsi ModifyTP ini menyamakan TP di satu titik. Sehingga jika TP ini kena, maka semua OP martingale akan tertutup dengan hasil balance bertambah. Memang ada OP awal yang loss, tapi karena OP selanjutnya lot-nya ditambah, maka jika kena TP ini hasil akhirnya akan menambah balance. Silakan dicoba.

Code:
/*-- Fungsi ModifyTP ini untuk mengubah semua OP agar TP di titik yang sama --*/
void ModifyTP()
{
int iCount=0;
double NewTP=0;

/*- Ambil nilai Take Profit dari Order terakhir -*/
for(iCount=0;iCount<OrdersTotal();iCount++)
{

OrderSelect(iCount,SELECT_BY_POS,MODE_TRADES);

/*-- Kalau OP-nya adalah BUY, ambil nilai TP yang paling kecil. Jadikan TP bersama --*/
if(OrderType()==OP_BUY && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(NewTP==0) {NewTP=OrderTakeProfit();}
if(NewTP>OrderTakeProfit()) {NewTP=OrderTakeProfit();}

}

/*-- Kalau OP-nya adalah SELL, ambil nilai TP yang paling besar. Jadikan TP bersama --*/
if(OrderType()==OP_SELL && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(NewTP==0) {NewTP=OrderTakeProfit();}
if(NewTP<OrderTakeProfit()) {NewTP=OrderTakeProfit();}
}

}

/*- Ubah semua nilai OP TakeProfit dengan yang baru (2x lipat) -*/
         for(iCount=0;iCount<OrdersTotal();iCount++)
{

OrderSelect(iCount,SELECT_BY_POS,MODE_TRADES);

/*- Kalau semua OP adalah BUY, maka ubahlah TP mereka -*/
if(OrderType()==OP_BUY && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
OrderModify(OrderTicket(), OrderLots(), 0, NewTP, 0);
}

/*- Kalau semua OP adalah SELL, maka ubahlah TP mereka -*/
if(OrderType()==OP_SELL && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
OrderModify(OrderTicket(), OrderLots(), 0, NewTP, 0);
}

}
}

--------------------------------------------

Coding Lengkap

Baiklah, sekarang kita gabungkan coding lengkap dari EA Simple Martingale ini. Nama EA-nya saya sebut saja EA Martingale2MA.


//+------------------------------------------------------------------+
//| EA DwiM Martingale2MA.mq4 |
//| @DwiMalistyo |
//| http://ea.dwim.web.id |
//+------------------------------------------------------------------+
#property copyright "@DwiMalistyo"
#property link "http://ea.dwim.web.id"

/*-- Parameter ini ditampilkan di EA dan bisa diubah --*/
extern int TakeProfit = 10; // Nilai TP setiap OP di EA Martingale ini
extern int PipStep = 10; // Jarak pip dimana akan buka OP baru
extern int Slippage = 3; // Apa itu slippage ? Googling sendiri ya..
extern double Lots = 0.1; // Nilai lots awal, nantinya akan digandakan setiap step
extern double Multiply = 2.0; // Nilai pengali setiap step OP baru
extern int MaxTrade = 11; // Banyak OP maksimal yang boleh dijalankan
extern bool UseTime = TRUE; // Pilihan apakah memakai waktu bekerjanya EA ?
extern int HourStart = 18; // Waktu mulai EA bekerja
extern int HourEnd = 24; // Waktu akhir EA bekerja

/*-- Parameter ini tidak ditampilkan di EA --*/
string EAName = "EA DwiM Martingale2MA ver 1.0"; // Nama EA, untuk ditampilkan di layar
string EAComment = "DwiM"; // Variabel ini akan kita masukkan di setiap OP sebagai Comment
int EAMagicNumber = 8095; // Magic Number
double SetPoint = 0; // Variabel SetPoint untuk kode digit broker 4 atau 5


//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----

SetBroker();

//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----

//----
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----

int iTrade=0;

double SMA18=0, EMA200=0;

SMA18=iMA(NULL, 0, 18, 0, MODE_SMA, PRICE_CLOSE, 0 );
EMA200=iMA(NULL, 0, 200, 0, MODE_EMA, PRICE_CLOSE, 0);

Comment(EAName); // Tampilkan Nama EA di layar

/* -- Jika tidak ada OP sama sekali, maka jalankan fungsi berikut --*/
/* -- Disinilah tempat anda memasukkan koding indikator untuk memicu OP --*/
if(OrdersTotal()==0)
{

if((Bid > SMA18) && (SMA18 > EMA200))
{
/*-- Order Buy --*/
OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, 0, Ask+TakeProfit*SetPoint, EAComment, EAMagicNumber);

}
else if((Ask < SMA18) && (SMA18 < EMA200))
{
/*-- Order Sell --*/
OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, 0, Bid-TakeProfit*SetPoint, EAComment, EAMagicNumber);
}

}


/* -- Inilah Fungsi Martingale. Jika ada OP yang salah, maka lakukan martingale --*/
if(OrdersTotal()>=1)
{
GoMartingale();
}


//----
return(0);
}
//+------------------------------------------------------------------+

/*--agar EA bisa running di Broker 4 Digit atau 5 Digit--*/
void SetBroker()
{
if (Digits==3 || Digits==5) // Perintah untuk broker 5 Digits
{SetPoint=Point*10;}
else // Perintah untuk broker 4 Digits
{SetPoint=Point;}
}

void GoMartingale()
{
int iCount = 0;
double LastOP = 0;
double LastLots = 0;
bool LastIsBuy = FALSE;
int iTotalBuy = 0;
int iTotalSell = 0;
int Spread=0;

Spread= MarketInfo(Symbol(), MODE_SPREAD);


for(iCount=0;iCount<OrdersTotal();iCount++)
{

OrderSelect(iCount,SELECT_BY_POS,MODE_TRADES);

if(OrderType()==OP_BUY && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(LastOP==0) {LastOP=OrderOpenPrice();}
if(LastOP>OrderOpenPrice()) {LastOP=OrderOpenPrice();}
if(LastLots<OrderLots()) {LastLots=OrderLots();}
LastIsBuy=TRUE;
iTotalBuy++;

/* Bila mencapai batas OP maksimal, jangan tambah OP lagi */
if(iTotalBuy==MaxTrade) {return(0);}
}

if(OrderType()==OP_SELL && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(LastOP==0) {LastOP=OrderOpenPrice();}
if(LastOP<OrderOpenPrice()) {LastOP=OrderOpenPrice();}
if(LastLots<OrderLots()) {LastLots=OrderLots();}
LastIsBuy=FALSE;
iTotalSell++;

/* Bila mencapai batas OP maksimal, jangan tambah OP lagi */
if(iTotalBuy==MaxTrade) {return(0);}
}

}

/* Jika arah Price adalah DOWNTREND...., Periksa nilai Bid (*/
if(LastIsBuy)
{
if(Bid<=LastOP-(Spread*SetPoint)-(PipStep*SetPoint))
{
OrderSend(Symbol(), OP_BUY, Multiply*LastLots, Ask, Slippage, 0, Ask+TakeProfit*SetPoint, EAComment, EAMagicNumber);
ModifyTP();
LastIsBuy=FALSE;
return(0);
}
}
/* Jika arah Price adalah Sell...., Periksa nilai Ask (*/
else if(!LastIsBuy)
{
if(Ask>=LastOP+(Spread*SetPoint)+(PipStep*SetPoint))
{
OrderSend(Symbol(), OP_SELL, Multiply*LastLots, Bid, Slippage, 0, Bid-TakeProfit*SetPoint, EAComment, EAMagicNumber);
ModifyTP();
return(0);
}
}

}

/*-- Fungsi ModifyTP ini untuk mengubah semua OP agar TP di titik yang sama --*/
void ModifyTP()
{
int iCount=0;
double NewTP=0;

/*- Ambil nilai Take Profit dari Order terakhir -*/
for(iCount=0;iCount<OrdersTotal();iCount++)
{

OrderSelect(iCount,SELECT_BY_POS,MODE_TRADES);

/*-- Kalau OP-nya adalah BUY, ambil nilai TP yang paling kecil. Jadikan TP bersama --*/
if(OrderType()==OP_BUY && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(NewTP==0) {NewTP=OrderTakeProfit();}
if(NewTP>OrderTakeProfit()) {NewTP=OrderTakeProfit();}

}

/*-- Kalau OP-nya adalah SELL, ambil nilai TP yang paling besar. Jadikan TP bersama --*/
if(OrderType()==OP_SELL && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
if(NewTP==0) {NewTP=OrderTakeProfit();}
if(NewTP<OrderTakeProfit()) {NewTP=OrderTakeProfit();}
}

}

/*- Ubah semua nilai OP TakeProfit dengan yang baru (2x lipat) -*/
for(iCount=0;iCount<OrdersTotal();iCount++)
{

OrderSelect(iCount,SELECT_BY_POS,MODE_TRADES);

/*- Kalau semua OP adalah BUY, maka ubahlah TP mereka -*/
if(OrderType()==OP_BUY && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
OrderModify(OrderTicket(), OrderLots(), 0, NewTP, 0);
}

/*- Kalau semua OP adalah SELL, maka ubahlah TP mereka -*/
if(OrderType()==OP_SELL && OrderSymbol()==Symbol() && OrderComment()==EAComment && OrderMagicNumber()==EAMagicNumber)
{
OrderModify(OrderTicket(), OrderLots(), 0, NewTP, 0);
}

}
}

 Kita akan coba melakukan backtesting sbb di bawah.

Kita lihat pada gambar, bahwa jika price berada di atas kedua MA, maka OP akan buy. Tapi price turun terus, sehingga GoMartingale akan membuat OP baru dalam jarak PipStep yaitu 10 pip.

Perhatikan juga, bahwa selain membuat OP Martingale, nilai TP dimodifikasi seperti garis merah, yaitu senilai TP OP yang terakhir. Sehingga jika OP terakhir ini (buy paling bawah) kena TP - akibatnya semua OP akan terhapus dan balance akan bertambah.




 Sip deh teman-teman. EA Simple Martingale-nya sudah selesai. Simple banget kan ?

Hehehe...memang itulah tujuannya. Maksudnya agar coding EA ini bisa di-copy paste, dan dimasukkan ke dalam coding EA teman-teman yang menggunakan strategi martingale.

Sekian dulu penjelasannya. Kita kelak akan melanjutkan thread ini dengan kasus-kasus coding Martingale lain. Tentunya yang sederhana saja ya. Agar visi misi thread ini bisa tercapai. Silakan jika ada masukan, saran dan kritik dari rekan-rekan trader, dan juga master-master EA di Forum MT5.

Salam hangat.