L1Trend/Experts/MACDFilteredL1.mq5

332 líneas
22 KiB
MQL5

//+------------------------------------------------------------------+
//| MACDFilteredL1.mq5 |
//| Copyright 2000-2026, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2026, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
//--- best MACD parameters for USDCHF,H1,2025
input int FastEMA = 43; // Fast EMA
input int SlowEMA = 59; // Slow EMA
input int SignalEMA = 37; // SignalEMA
//--- 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 MACD_MAGIC 1234502
#include <Trade\Trade.mqh>
int ExtHandle = INVALID_HANDLE;
bool ExtHedging = false;
CTrade ExtTrade;
string ExtStrategyName="MACD";
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(MACD) |
//+------------------------------------------------------------------+
bool GetTradeSignal(ENUM_ORDER_TYPE &signal)
{
signal = WRONG_VALUE;
double macd_main[];
double macd_signal[];
//---
ArrayResize(macd_main,2);
ArrayResize(macd_signal,2);
//---
ArraySetAsSeries(macd_main, true);
ArraySetAsSeries(macd_signal, true);
//--- buffer 0 = MACD main, buffer 1 = signal line
if(CopyBuffer(ExtHandle, 0, 1, 2, macd_main) != 2)
return false;
if(CopyBuffer(ExtHandle, 1, 1, 2, macd_signal) != 2)
return false;
//---
double main_prev = macd_main[1];
double main_last = macd_main[0];
double signal_prev = macd_signal[1];
double signal_last = macd_signal[0];
//--- MACD crossover
if(main_prev < signal_prev && main_last > signal_last)
signal = ORDER_TYPE_BUY;
else
if(main_prev > signal_prev && main_last < signal_last)
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)!=MACD_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)==MACD_MAGIC)
{
res = true;
break;
}
}
}
else
{
if(PositionSelect(_Symbol))
res = (PositionGetInteger(POSITION_MAGIC)==MACD_MAGIC);
}
return res;
}
//+------------------------------------------------------------------+
//| Expert initialization |
//+------------------------------------------------------------------+
int OnInit()
{
//--- check parameters
if(FastEMA <= 0 || SlowEMA <= 0 || SignalEMA <= 0)
{
Print("Error: MACD parameters must be positive");
return(INIT_PARAMETERS_INCORRECT);
}
if(FastEMA >= SlowEMA)
{
Print("FastEMA must be less than SlowEMA");
return(INIT_PARAMETERS_INCORRECT);
}
//---
ExtHedging = (AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING);
ExtTrade.SetExpertMagicNumber(MACD_MAGIC);
ExtTrade.SetMarginMode();
ExtTrade.SetTypeFillingBySymbol(_Symbol);
//--- prepare indicator
ExtHandle = iMACD(_Symbol, _Period,FastEMA, SlowEMA, SignalEMA,PRICE_CLOSE);
if(ExtHandle == INVALID_HANDLE)
{
Print("Failed to create MACD 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();
//---
if(ExtHandle != INVALID_HANDLE)
IndicatorRelease(ExtHandle);
}
//+------------------------------------------------------------------+