//+------------------------------------------------------------------+
//| TradeByATR.mq5 |
//| Copyright 2018, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property description "\"Patlayıcı\" mum yönünde uzman danışman alım-satım örneği"
#property description "\"Patlayıcı\" mum k*ATR'ı aşan bir beden ölçüsü vardır"
#property description "\"Revers\" parametresi sinyal yönünü tersine çevirir"
input double lots=0.1; // lot cinsinden hacim
input double kATR=3; // ATR'daki sinyal mum uzunluğu
input int ATRperiod=20; // ATR gösterge zaman aralığı
input int holdbars=8; // pozisyonu açık tutmak için gereken bar sayısı
input int slippage=10; // izin verilebilir kayma miktarı
input bool revers=false; // sinyali tersine döndür?
input ulong EXPERT_MAGIC=0; // Uzman danışmanın MagicNumber'ı
//--- ATR gösterge yönetimini depolamak için
int atr_handle;
//--- burada son ATR değerini ve mum bedenini saklayacağız
double last_atr,last_body;
datetime lastbar_timeopen;
double trade_lot;
//+------------------------------------------------------------------+
//| Uzman danışman başlatma fonksiyonu |
//+------------------------------------------------------------------+
int OnInit()
{
//--- global değişkenleri başlat
last_atr=0;
last_body=0;
//--- doğru hacmi ayarlama
double min_lot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
trade_lot=lots>min_lot? lots:min_lot;
//--- ATR gösterge yönetimini oluştur
atr_handle=iATR(_Symbol,_Period,ATRperiod);
if(atr_handle==INVALID_HANDLE)
{
PrintFormat("%s: iATR oluşturulamadı, hata kodu %d",__FUNCTION__,GetLastError());
return(INIT_FAILED);
}
//--- başarılı uzman danışman başlatma
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Uzman danışman sonlandırma fonksiyonu |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- uzman danışman sonlandırma kodunu bildir
Print(__FILE__,": Sonlandırma neden kodu = ",reason);
}
//+------------------------------------------------------------------+
//| Uzman danışman fiyat(tick/tik) fonksiyonu |
//+------------------------------------------------------------------+
void OnTick()
{
//--- alım-satım sinyali
static int signal=0; // +1 alış sinyali anlamına gelmektedir, -1 satın sinyali anlamına gelmektedir
//--- 'holdbars' bar miktarından daha önce açılmış eski pozisyonları kontrol et ve kapat
ClosePositionsByBars(holdbars,slippage,EXPERT_MAGIC);
//--- yeni bir barı kontrol et
if(isNewBar())
{
//--- sinyal varlığını kontrol et
signal=CheckSignal();
}
//--- eğer bir netleştirme pozisyonu açıksa, sinyali atla - kapanana kadar bekle
if(signal!=0 && PositionsTotal()>0 && (ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_NETTING)
{
signal=0;
return; // NewTick olay yöneticisinden çık ve yeni bir bar görünene kadar piyasaya girme
}
//--- bir hedging hesabı için, her bir pozisyon ayrı ayrı tutulur ve kapatılır
if(signal!=0)
{
//--- alış sinyali
if(signal>0)
{
PrintFormat("%s: Alış sinyali! Revers=%s",__FUNCTION__,string(revers));
if(Buy(trade_lot,slippage,EXPERT_MAGIC))
signal=0;
}
//--- satış sinyali
if(signal<0)
{
PrintFormat("%s: Satış sinyali! Revers=%s",__FUNCTION__,string(revers));
if(Sell(trade_lot,slippage,EXPERT_MAGIC))
signal=0;
}
}
//--- OnTick fonksiyon sonlandırma
}
//+------------------------------------------------------------------+
//| Yeni bir alım-satım sinyali kontrol et |
//+------------------------------------------------------------------+
int CheckSignal()
{
//--- 0, sinyal yok anlamına gelmektedir
int res=0;
//--- sondan bir önceki tam barın ATR değerini elde et (bar indeksi 2'dir)
double atr_value[1];
if(CopyBuffer(atr_handle,0,2,1,atr_value)!=-1)
{
last_atr=atr_value[0];
//--- son kapanan barın verilerini bir dizi MqlRates'e ilet
MqlRates bar[1];
if(CopyRates(_Symbol,_Period,1,1,bar)!=-1)
{
//--- son kapanan barın beden ölçüsünü hesapla
last_body=bar[0].close-bar[0].open;
//--- eğer son barın bedeni (index 1 olan bar) bir önceki ATR değerini aşarsa (indeks 2'deki bar), bir alım-satım sinyali alınır
if(MathAbs(last_body)>kATR*last_atr)
res=last_body>0?1:-1; // yükselen mum için pozitif değer
}
else
PrintFormat("%s: Son bar elde edilemedi! Hata",__FUNCTION__,GetLastError());
}
else
PrintFormat("%s: ATR gösterge değeri alınamadı! Hata",__FUNCTION__,GetLastError());
//--- eğer ters alım-satım modu etkinse
res=revers?-res:res; // eğer gerekliyse sinyali tersine çevir (1 yerine -1'i geri döndür ve -1 yerine de 1'i geri döndür)
//--- bir alım-satım sinyal değerini geri döndür
return (res);
}
//+------------------------------------------------------------------+
//| Yeni bir bar göründüğünde 'true'yu geri döndür |
//+------------------------------------------------------------------+
bool isNewBar(const bool print_log=true)
{
static datetime bartime=0; // mevcut barın açılış zamanını sakla
//--- sıfır indeksli barın açılış zamanını elde et
datetime currbar_time=iTime(_Symbol,_Period,0);
//--- eğer açılış zaman bilgisi değişirse, yeni bir bar gelmiş demektir
if(bartime!=currbar_time)
{
bartime=currbar_time;
lastbar_timeopen=bartime;
//--- yeni barın açılış zamanı verilerini günlükte göster
if(print_log && !(MQLInfoInteger(MQL_OPTIMIZATION)||MQLInfoInteger(MQL_TESTER)))
{
//--- yeni barın açılış zamanı bilgisine sahip bir mesaj göster
PrintFormat("%s: yeni bar %s %s üzerinde %s de açıldı",__FUNCTION__,_Symbol,
StringSubstr(EnumToString(_Period),7),
TimeToString(TimeCurrent(),TIME_SECONDS));
//--- son fiyat(tik) hakkındaki verileri elde et
MqlTick last_tick;
if(!SymbolInfoTick(Symbol(),last_tick))
Print("SymbolInfoTick() başarısız oldu, hata = ",GetLastError());
//--- son fiyat zamanını milisaniye olarak kadar göster
PrintFormat("Son fiyat %s.%03d taydı",
TimeToString(last_tick.time,TIME_SECONDS),last_tick.time_msc%1000);
}
//--- yeni bir bar var
return (true);
}
//--- yeni bir bar yok
return (false);
}
//+------------------------------------------------------------------+
//| Belirtilen hacimle, piyasa fiyatından alış yap |
//+------------------------------------------------------------------+
bool Buy(double volume,ulong deviation=10,ulong magicnumber=0)
{
//--- piyasa fiyatından alış yap
return (MarketOrder(ORDER_TYPE_BUY,volume,deviation,magicnumber));
}
//+------------------------------------------------------------------+
//| Belirtilen hacimle, piyasa fiyatından satış yap |
//+------------------------------------------------------------------+
bool Sell(double volume,ulong deviation=10,ulong magicnumber=0)
{
//--- piyasa fiyatından alış yap
return (MarketOrder(ORDER_TYPE_SELL,volume,deviation,magicnumber));
}
//+------------------------------------------------------------------+
//| Bar sayısı ile hesaplanan açık tutma süresine göre pozisyonu kapat
//+------------------------------------------------------------------+
void ClosePositionsByBars(int holdtimebars,ulong deviation=10,ulong magicnumber=0)
{
int total=PositionsTotal(); // açık pozisyonların sayısı
//--- tüm açık pozisyonları ara
for(int i=total-1; i>=0; i--)
{
//--- pozisyon parametreleri
ulong position_ticket=PositionGetTicket(i); // pozisyon bileti
string position_symbol=PositionGetString(POSITION_SYMBOL); // sembol
ulong magic=PositionGetInteger(POSITION_MAGIC); // pozisyon MagicNumber'ı
datetime position_open=(datetime)PositionGetInteger(POSITION_TIME); // pozisyon açılış zamanı
int bars=iBarShift(_Symbol,PERIOD_CURRENT,position_open)+1; // kaç bar önce pozisyon açıldı
//--- eğer bir pozisyonun ömrü, MagicNumber ve sembol eşleşirken, halihazırda fazlaysa
if(bars>holdtimebars && magic==magicnumber && position_symbol==_Symbol)
{
int digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // ondalık basamak sayısı
double volume=PositionGetDouble(POSITION_VOLUME); // pozisyon hacmi
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // pozisyon türü
string str_type=StringSubstr(EnumToString(type),14);
StringToLower(str_type); // doğru mesaj formatı için metin kutusunu küçült
PrintFormat(" #%I64u %s %s %.2f pozisyonunu kapat",
position_ticket,position_symbol,str_type,volume);
//--- emir türünü belirle ve alım-satım isteğini gönder
if(type==POSITION_TYPE_BUY)
MarketOrder(ORDER_TYPE_SELL,volume,deviation,magicnumber,position_ticket);
else
MarketOrder(ORDER_TYPE_BUY,volume,deviation,magicnumber,position_ticket);
}
}
}
//+------------------------------------------------------------------+
//| Bir alım-satım isteği hazırla ve gönder |
//+------------------------------------------------------------------+
bool MarketOrder(ENUM_ORDER_TYPE type,double volume,ulong slip,ulong magicnumber,ulong pos_ticket=0)
{
//--- yapıların bildirimi ve başlatımı
MqlTradeRequest request={};
MqlTradeResult result={};
double price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
if(type==ORDER_TYPE_BUY)
price=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
//--- istek parametreleri
request.action =TRADE_ACTION_DEAL; // İşlem türü
request.position =pos_ticket; // kapanıyorsa, pozisyon bileti
request.symbol =Symbol(); // sembol
request.volume =volume; // hacim
request.type =type; // emir türü
request.price =price; // alım-satım fiyatı
request.deviation=slip; // fiyattan izin verilen sapma
request.magic =magicnumber; // emir MagicNumber'ı
//--- bir istek gönder
if(!OrderSend(request,result))
{
//--- başarısızlık verilerini görüntüle
PrintFormat("OrderSend %s %s %.2f %.5f de hata %d",
request.symbol,EnumToString(type),volume,request.price,GetLastError());
return (false);
}
//--- başarılı operasyonu bildir
PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
return (true);
}
|