319 righe
Nessun fine linea
21 KiB
MQL5
319 righe
Nessun fine linea
21 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| EMAFilteredL1.mq5 |
|
|
//| Copyright 2000-2026, MetaQuotes Ltd. |
|
|
//| http://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2000-2026, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
#property version "1.00"
|
|
//--- best EMA parameters for EURUSD,H1,2025
|
|
input int FastEMA = 29; // Fast EMA
|
|
input int SlowEMA = 101; // Slow EMA
|
|
//--- trade volume
|
|
input double TradeLot = 0.1; // Lot size
|
|
//--- L1 filter parameters
|
|
input int L1TotalBars = 1000; // Total bars for L1 filter
|
|
input bool L1FilterOpen = false; // Use filter for Open
|
|
input bool L1FilterClose = false; // Use filter for Close
|
|
input double L1CoefLambda = 0.2; // Lambda in lambda_max units
|
|
//--- save statistics
|
|
input bool SaveStatistics = false; // Save statistics to file
|
|
//---
|
|
#define EMA_MAGIC 1234503
|
|
#include <Trade\Trade.mqh>
|
|
CTrade ExtTrade;
|
|
int ExtHandle = INVALID_HANDLE;
|
|
bool ExtHedging = false;
|
|
int FastHandle, SlowHandle;
|
|
string ExtStrategyName="EMA";
|
|
string ExtStrategyFileName="";
|
|
//+------------------------------------------------------------------+
|
|
//| Check new bar |
|
|
//+------------------------------------------------------------------+
|
|
bool IsNewBar()
|
|
{
|
|
static datetime last_time=0;
|
|
datetime t[1];
|
|
|
|
if(CopyTime(_Symbol,_Period,0,1,t)>0)
|
|
{
|
|
if(t[0]!=last_time)
|
|
{
|
|
last_time=t[0];
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| CheckTrendL1 |
|
|
//+------------------------------------------------------------------+
|
|
double CheckTrendL1()
|
|
{
|
|
int max_bars=L1TotalBars;
|
|
MqlRates rates_data[];
|
|
ArrayResize(rates_data,max_bars);
|
|
ArraySetAsSeries(rates_data,false);
|
|
if(CopyRates(_Symbol,_Period,0,max_bars,rates_data) != max_bars)
|
|
{
|
|
Print("CopyRates failed for L1Trend");
|
|
return 0;
|
|
}
|
|
//--- prepare data (close prices vector)
|
|
int data_count=max_bars;
|
|
vector<double> data_close;
|
|
data_close.Resize(data_count);
|
|
for(int i=0; i<data_count; i++)
|
|
data_close[i] = rates_data[i].close;
|
|
//--- calculate L1 filter
|
|
vector<double> data_filtered;
|
|
data_filtered.Resize(data_count);
|
|
double dp=0.0;
|
|
bool res=data_close.L1TrendFilter(data_filtered,L1CoefLambda,true);
|
|
if(res)
|
|
dp = data_filtered[data_count-1] - data_filtered[data_count-2];
|
|
//---
|
|
return dp;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| GetTradeSignal (2EMA crossover) |
|
|
//+------------------------------------------------------------------+
|
|
bool GetTradeSignal(ENUM_ORDER_TYPE &signal)
|
|
{
|
|
signal=WRONG_VALUE;
|
|
//---
|
|
double fast[],slow[];
|
|
ArrayResize(fast,2);
|
|
ArrayResize(slow,2);
|
|
//---
|
|
ArraySetAsSeries(fast,true);
|
|
ArraySetAsSeries(slow,true);
|
|
//---
|
|
if(CopyBuffer(FastHandle,0,1,2,fast)!=2)
|
|
return false;
|
|
//---
|
|
if(CopyBuffer(SlowHandle,0,1,2,slow)!=2)
|
|
return false;
|
|
//---
|
|
if(fast[1]<slow[1] && fast[0]>slow[0])
|
|
signal=ORDER_TYPE_BUY;
|
|
if(fast[1]>slow[1] && fast[0]<slow[0])
|
|
signal=ORDER_TYPE_SELL;
|
|
//---
|
|
return true;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| CheckForOpen |
|
|
//+------------------------------------------------------------------+
|
|
void CheckForOpen()
|
|
{
|
|
ENUM_ORDER_TYPE signal;
|
|
//---
|
|
if(!GetTradeSignal(signal) || signal==WRONG_VALUE)
|
|
return;
|
|
//---
|
|
if(L1FilterOpen)
|
|
{
|
|
double dp=CheckTrendL1();
|
|
//---
|
|
if(signal==ORDER_TYPE_BUY && dp<0)
|
|
return;
|
|
if(signal==ORDER_TYPE_SELL && dp>0)
|
|
return;
|
|
}
|
|
//---
|
|
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) || Bars(_Symbol,_Period)<L1TotalBars)
|
|
return;
|
|
//---
|
|
double price=(signal==ORDER_TYPE_BUY)
|
|
? SymbolInfoDouble(_Symbol,SYMBOL_ASK)
|
|
: SymbolInfoDouble(_Symbol,SYMBOL_BID);
|
|
//---
|
|
ExtTrade.PositionOpen(_Symbol,signal,TradeLot,price,0,0);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| CheckForClose |
|
|
//+------------------------------------------------------------------+
|
|
void CheckForClose()
|
|
{
|
|
//--- check position
|
|
if(!PositionSelect(_Symbol))
|
|
return;
|
|
//--- check position magic
|
|
if(PositionGetInteger(POSITION_MAGIC)!=EMA_MAGIC)
|
|
return;
|
|
//--- check trade signal
|
|
ENUM_ORDER_TYPE signal;
|
|
if(!GetTradeSignal(signal))
|
|
return;
|
|
//---
|
|
long type=PositionGetInteger(POSITION_TYPE);
|
|
bool close_signal=false;
|
|
//---
|
|
if(type==POSITION_TYPE_BUY && signal==ORDER_TYPE_SELL)
|
|
close_signal=true;
|
|
//---
|
|
if(type==POSITION_TYPE_SELL && signal==ORDER_TYPE_BUY)
|
|
close_signal=true;
|
|
//--- check L1 filter
|
|
if(L1FilterClose)
|
|
{
|
|
double dp = CheckTrendL1();
|
|
if(type == POSITION_TYPE_BUY && dp > 0)
|
|
{
|
|
close_signal = false;
|
|
PrintFormat("Close BUY signal cancelled by L1 trend dp=%.5f", dp);
|
|
}
|
|
if(type == POSITION_TYPE_SELL && dp < 0)
|
|
{
|
|
close_signal = false;
|
|
PrintFormat("Close SELL signal cancelled by L1 trend dp=%.5f", dp);
|
|
}
|
|
}
|
|
//---
|
|
if(close_signal)
|
|
ExtTrade.PositionClose(_Symbol,3);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| SelectPosition |
|
|
//+------------------------------------------------------------------+
|
|
bool SelectPosition()
|
|
{
|
|
bool res = false;
|
|
if(ExtHedging)
|
|
{
|
|
uint total = PositionsTotal();
|
|
for(uint i=0; i<total; i++)
|
|
{
|
|
string sym = PositionGetSymbol(i);
|
|
if(sym == _Symbol && PositionGetInteger(POSITION_MAGIC)==EMA_MAGIC)
|
|
{
|
|
res = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(PositionSelect(_Symbol))
|
|
res = (PositionGetInteger(POSITION_MAGIC)==EMA_MAGIC);
|
|
}
|
|
return res;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
ExtHedging = (AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING);
|
|
ExtTrade.SetExpertMagicNumber(EMA_MAGIC);
|
|
ExtTrade.SetMarginMode();
|
|
ExtTrade.SetTypeFillingBySymbol(_Symbol);
|
|
//--- prepare indicators
|
|
FastHandle=iMA(_Symbol,_Period,FastEMA,0,MODE_EMA,PRICE_CLOSE);
|
|
SlowHandle=iMA(_Symbol,_Period,SlowEMA,0,MODE_EMA,PRICE_CLOSE);
|
|
if(FastHandle==INVALID_HANDLE || SlowHandle==INVALID_HANDLE)
|
|
return INIT_FAILED;
|
|
//--- prepare filename
|
|
ExtStrategyFileName=PrepareStrategyFileName(ExtStrategyName);
|
|
//--- delete old file if exists
|
|
if(FileIsExist(ExtStrategyFileName))
|
|
FileDelete(ExtStrategyFileName);
|
|
//---
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| PrepareStrategyFileName |
|
|
//+------------------------------------------------------------------+
|
|
string PrepareStrategyFileName(string strategy_name)
|
|
{
|
|
int v=0;
|
|
if(L1FilterOpen)
|
|
v=v | 1;
|
|
//---
|
|
if(L1FilterClose)
|
|
v=v | 2;
|
|
//---
|
|
string filename=IntegerToString(v)+"_"+strategy_name+"_"+_Symbol+".txt";
|
|
return filename;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Save account statistics to file |
|
|
//+------------------------------------------------------------------+
|
|
void SaveAccountStatistics()
|
|
{
|
|
//--- check file name
|
|
if(ExtStrategyFileName=="")
|
|
return;
|
|
//---
|
|
int file=FileOpen(ExtStrategyFileName,FILE_WRITE|FILE_READ|FILE_TXT|FILE_SHARE_WRITE|FILE_ANSI);
|
|
if(file==INVALID_HANDLE)
|
|
{
|
|
Print("File open error: ",GetLastError());
|
|
return;
|
|
}
|
|
//--- append
|
|
FileSeek(file,0,SEEK_END);
|
|
//--- account data
|
|
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
|
|
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
|
|
double margin = AccountInfoDouble(ACCOUNT_MARGIN);
|
|
double free_margin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
|
|
double margin_lvl = AccountInfoDouble(ACCOUNT_MARGIN_LEVEL);
|
|
//--- volume
|
|
double volume=0.0;
|
|
if(PositionSelect(_Symbol))
|
|
volume=PositionGetDouble(POSITION_VOLUME);
|
|
//--- time
|
|
datetime t[1];
|
|
if(CopyTime(_Symbol,_Period,0,1,t)<=0)
|
|
{
|
|
FileClose(file);
|
|
return;
|
|
}
|
|
double current_close[1];
|
|
if(CopyClose(_Symbol,_Period,0,1,current_close)<=0)
|
|
{
|
|
FileClose(file);
|
|
return;
|
|
}
|
|
string line=StringFormat("%s;%.2f;%.2f;%.2f;%.2f;%.2f;%.2f;%f",TimeToString(t[0],TIME_DATE|TIME_SECONDS),
|
|
balance,equity,margin,free_margin,margin_lvl,volume,current_close[0]);
|
|
//---
|
|
FileWrite(file,line);
|
|
//---
|
|
FileClose(file);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert OnTick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
//--- trade only at new bar
|
|
if(!IsNewBar())
|
|
return;
|
|
//--- check trade conditions
|
|
if(SelectPosition())
|
|
CheckForClose();
|
|
else
|
|
CheckForOpen();
|
|
//--- save account statistics
|
|
if(SaveStatistics)
|
|
SaveAccountStatistics();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
//--- save account statistics
|
|
if(SaveStatistics)
|
|
SaveAccountStatistics();
|
|
//--- release indicator handles
|
|
if(FastHandle!=INVALID_HANDLE)
|
|
IndicatorRelease(FastHandle);
|
|
//---
|
|
if(SlowHandle!=INVALID_HANDLE)
|
|
IndicatorRelease(SlowHandle);
|
|
}
|
|
//+------------------------------------------------------------------+ |