mirror of
https://github.com/rithsila/MT5-EA-Sniper-Strategy.git
synced 2026-08-16 12:18:11 +00:00
416 lines
26 KiB
Plaintext
416 lines
26 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| MidNightAngel.mq5 |
|
|
//| Copyright 2022, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2022, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
#property version "1.00"
|
|
|
|
#include <Nkanven\MidNightAngel\Parameters.mqh> // EA paramters
|
|
#include <Nkanven\MidNightAngel\LotSizeCal.mqh> // Lot size calculator
|
|
|
|
ulong ticket=0;
|
|
double profit;
|
|
datetime time;
|
|
string symbol;
|
|
long type;
|
|
long entry;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
//---
|
|
|
|
//---
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
//---
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
//---
|
|
//---
|
|
datetime ht = TimeCurrent();
|
|
TimeToStruct(ht, dt);
|
|
|
|
SymbolInfoTick(_Symbol,last_tick);
|
|
/*storeEquity();
|
|
HasTodayClosingPosition();
|
|
if(FileIsExist(filename))
|
|
{
|
|
//Compare stored balance and actual balance
|
|
if(getStoredBalance() > AccountInfoDouble(ACCOUNT_BALANCE))
|
|
{
|
|
IsLosing=true;
|
|
}
|
|
else
|
|
{
|
|
IsLosing=false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
storeEquity();
|
|
}*/
|
|
CheckSpread();
|
|
|
|
if(dt.hour == 0)
|
|
{
|
|
Print("It's trading time. History sum ", checkHistory());
|
|
for(int i=0; i<ArraySize(gStandardRisk); i++)
|
|
{
|
|
if(checkHistory() == gStandardRisk[i])
|
|
{
|
|
gBuyPositioning = STANDARD_BUY;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for(int i=0; i<ArraySize(gOneSL); i++)
|
|
{
|
|
if(checkHistory() == gOneSL[i])
|
|
{
|
|
gBuyPositioning = TWO_SL_BUY;
|
|
break;
|
|
}
|
|
}
|
|
if(gTwoSL == checkHistory())
|
|
{
|
|
gBuyPositioning = THREE_SL_BUY;
|
|
}
|
|
if(checkHistory()==0)
|
|
{
|
|
gBuyPositioning = STANDARD_BUY;
|
|
}
|
|
Print("Verify buy ", PositionsTotal()==0 && HasTodayClosingPosition());
|
|
//if(PositionsTotal()==0 && !HasTodayClosingPosition())
|
|
if(PositionsTotal()==0 && !HasTodayClosingPosition() && IsSpreadOK)
|
|
{
|
|
switch(gBuyPositioning)
|
|
{
|
|
case STANDARD_BUY:
|
|
Print("Buy standard entry");
|
|
ExecuteEntry(InpDefaultSize);
|
|
break;
|
|
case TWO_SL_BUY:
|
|
Print("Buy One SL entry");
|
|
ExecuteEntry(InpOneSlSize);
|
|
break;
|
|
case THREE_SL_BUY:
|
|
Print("Buy Two SL entry");
|
|
ExecuteEntry(InpTwoSlSize);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
Comment("Hour ", dt.hour, " Hour is true", " Balance is actually = ", AccountInfoInteger(ACCOUNT_LOGIN), " File ", FileIsExist(filename));
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//Check and return if the spread is not too high
|
|
void CheckSpread()
|
|
{
|
|
//Get the current spread in points, the (int) transforms the double coming from MarketInfo into an integer to avoid a warning when compiling
|
|
long SpreadCurr=(int)Spread;
|
|
Print("Spread ", Spread);
|
|
if(SpreadCurr<=InpMaxSpread)
|
|
{
|
|
IsSpreadOK=true;
|
|
}
|
|
else
|
|
{
|
|
IsSpreadOK=false;
|
|
}
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void storeEquity()
|
|
{
|
|
|
|
string terminal_data_path=TerminalInfoString(TERMINAL_DATA_PATH);
|
|
printf(" terminal_data_path ", terminal_data_path);
|
|
int filehandle=FileOpen(filename,FILE_WRITE|FILE_TXT,",");
|
|
if(filehandle!=INVALID_HANDLE)
|
|
{
|
|
FileWrite(filehandle,DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE)));
|
|
FileClose(filehandle);
|
|
//Print("The file must be created in the folder "+terminal_data_path+"\\"+subfolder);
|
|
}
|
|
else
|
|
Print("File open failed, error ",GetLastError());
|
|
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
double getStoredBalance()
|
|
{
|
|
int balance;
|
|
struct Table
|
|
{
|
|
int line;
|
|
datetime date;
|
|
string symbol;
|
|
double price;
|
|
|
|
};
|
|
|
|
Table table[];
|
|
|
|
int i=0;
|
|
|
|
short delimiter=',';
|
|
int fileHandle = FileOpen(filename,FILE_READ|FILE_ANSI,delimiter);
|
|
|
|
if(fileHandle==INVALID_HANDLE)
|
|
Alert("could not open file, error: "+(string)GetLastError());
|
|
|
|
if(fileHandle!=INVALID_HANDLE)
|
|
{
|
|
while(FileIsEnding(fileHandle) == false)
|
|
{
|
|
|
|
|
|
ArrayResize(table,ArraySize(table) +1);
|
|
table[i].line = (int) FileReadNumber(fileHandle);
|
|
/* table[i].date = FileReadDatetime(fileHandle);
|
|
table[i].symbol = FileReadString(fileHandle);
|
|
table[i].price = FileReadNumber(fileHandle);*/
|
|
i++;
|
|
|
|
}
|
|
|
|
FileClose(fileHandle);
|
|
|
|
}
|
|
for(i=0; i<ArraySize(table); i++)
|
|
{
|
|
balance = table[i].line;
|
|
}
|
|
|
|
return balance;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool HasTodayClosingPosition()
|
|
{
|
|
datetime timeStart = TimeCurrent() - PeriodSeconds(PERIOD_D1);
|
|
time =(datetime)HistoryDealGetInteger(ticket,DEAL_TIME);
|
|
int totalClosed = 0;
|
|
|
|
printf(TimeToString(timeStart));
|
|
HistorySelect(timeStart,TimeCurrent());
|
|
uint total=HistoryDealsTotal();
|
|
|
|
for(uint i=0; i<total; i++)
|
|
{
|
|
//--- essaye de récuperer le ticket des transactions
|
|
if((ticket=HistoryDealGetTicket(i))>0)
|
|
{
|
|
if(TimeToString(time, TIME_DATE) == TimeToString(TimeCurrent(), TIME_DATE))
|
|
{
|
|
totalClosed += 1;
|
|
}
|
|
Print("TIMES ", TimeToString(time, TIME_DATE)," ", TimeToString(TimeCurrent(), TIME_DATE));
|
|
}
|
|
}
|
|
|
|
Print("Total closed today ", totalClosed);
|
|
if(totalClosed > 0)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
int checkHistory()
|
|
{
|
|
|
|
uint total=HistoryDealsTotal();
|
|
int outCount=0;
|
|
int j=1;
|
|
|
|
for(uint i=total; i>0; i--)
|
|
{
|
|
//--- essaye de récuperer le ticket des transactions
|
|
if((ticket=HistoryDealGetTicket(i))>0)
|
|
{
|
|
//--- récupère les propriétés des transactions
|
|
time =(datetime)HistoryDealGetInteger(ticket,DEAL_TIME);
|
|
symbol=HistoryDealGetString(ticket,DEAL_SYMBOL);
|
|
type =HistoryDealGetInteger(ticket,DEAL_TYPE);
|
|
entry =HistoryDealGetInteger(ticket,DEAL_ENTRY);
|
|
profit=HistoryDealGetDouble(ticket,DEAL_PROFIT);
|
|
|
|
if(entry == DEAL_ENTRY_OUT)
|
|
{
|
|
|
|
if(j==1)
|
|
{
|
|
if(profit > 0)
|
|
{
|
|
outCount+= 1;
|
|
}
|
|
else
|
|
{
|
|
outCount-= 1;
|
|
}
|
|
}
|
|
|
|
if(j==2)
|
|
{
|
|
if(profit > 0)
|
|
{
|
|
outCount+= 1;
|
|
}
|
|
else
|
|
{
|
|
outCount-= 2;
|
|
}
|
|
}
|
|
|
|
if(j==3)
|
|
{
|
|
if(profit > 0)
|
|
{
|
|
outCount+= 1;
|
|
}
|
|
else
|
|
{
|
|
outCount-= 3;
|
|
}
|
|
}
|
|
j+=1;
|
|
Print("date ", TimeToString(time), " type ", entry, " profit ", profit);
|
|
}
|
|
}
|
|
}
|
|
return outCount;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//Execute entry if there is an entry signal
|
|
void ExecuteEntry(double LotMultiplier)
|
|
{
|
|
int Operation;
|
|
double OpenPrice=0;
|
|
double StopLossPrice=0;
|
|
double TakeProfitPrice=0;
|
|
|
|
Print("In buy execution");
|
|
Operation=ORDER_TYPE_BUY; //Set the operation to BUY
|
|
OpenPrice=last_tick.ask; //Set the open price to Ask price
|
|
//If the Stop Loss is fixed and the default stop loss is set
|
|
if(InpStopLossMode==SL_FIXED && InpDefaultStopLoss>0)
|
|
{
|
|
StopLossPrice=OpenPrice-InpDefaultStopLoss*Point();
|
|
}
|
|
//If the Stop Loss is automatic
|
|
if(InpStopLossMode==SL_AUTO)
|
|
{
|
|
//Set the Stop Loss to the custom stop loss price
|
|
//StopLossPrice=last_tick.ask-((last_tick.ask-sell_level));
|
|
StopLossPrice=iLow(Symb, PERIOD_CURRENT, 3);
|
|
}
|
|
//If the Take Profix price is fixed and defined
|
|
if(InpTakeProfitMode==TP_FIXED && InpDefaultTakeProfit>0)
|
|
{
|
|
TakeProfitPrice=OpenPrice+InpDefaultTakeProfit*Point();
|
|
}
|
|
//If the Take Profit is automatic
|
|
if(InpTakeProfitMode==TP_AUTO)
|
|
{
|
|
//Set the Take Profit to the custom take profit price
|
|
TakeProfitPrice=OpenPrice+((OpenPrice-StopLossPrice)*InpTakeProfitPercent);
|
|
}
|
|
//Normalize the digits for the float numbers
|
|
|
|
OpenPrice=NormalizeDouble(OpenPrice,Digits());
|
|
StopLossPrice=NormalizeDouble(StopLossPrice,Digits());
|
|
TakeProfitPrice=NormalizeDouble(TakeProfitPrice,Digits());
|
|
|
|
//Submit the order
|
|
SendOrder(Operation,Symbol(),OpenPrice,StopLossPrice,TakeProfitPrice, LotMultiplier);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//Send Order Function adjusted to handle errors and retry multiple times
|
|
void SendOrder(int Command, string Instrument, double OpenPrice, double SLPrice, double TPPrice, double Multiplier)
|
|
{
|
|
MqlTradeRequest request= {};
|
|
MqlTradeResult result= {};
|
|
//Calculate the position size, if the lot size is zero then exit the function
|
|
double SLPoints=0;
|
|
Print("Stop loss ", SLPrice, " Open price ", OpenPrice);
|
|
//If the Stop Loss price is set then find the points of distance between open price and stop loss price, and round it
|
|
if(SLPrice>0)
|
|
SLPoints=MathCeil(MathAbs(OpenPrice-SLPrice)/_Point);
|
|
//Call the function to calculate the position size
|
|
|
|
Print("Stop loss en point ", SLPoints, " Point ", _Point);
|
|
LotSizeCalculate(SLPoints);
|
|
//If the position size is zero then exit and don't submit any orderInit
|
|
|
|
Print("Stop loss en point ", SLPoints);
|
|
if(LotSize==0)
|
|
return;
|
|
|
|
if(gBuyPositioning == TWO_SL_BUY || gBuyPositioning == THREE_SL_BUY)
|
|
{
|
|
SLPrice=SLPrice-InpDefaultTakeProfit*Point();
|
|
}
|
|
|
|
request.action =TRADE_ACTION_DEAL; // type de l'opération de trading
|
|
request.symbol =Instrument; // symbole
|
|
request.volume =LotSize*Multiplier; // volume de 0.1 lot
|
|
request.type =Command; // type de l'ordre
|
|
request.price =SYMBOL_TRADE_EXECUTION_MARKET; // prix d'ouverture
|
|
request.sl =NormalizeDouble(SLPrice,Digits());
|
|
request.tp =NormalizeDouble(TPPrice,Digits());
|
|
request.type_filling =ORDER_FILLING_FOK;
|
|
request.deviation =InpSlippage; // déviation du prix autorisée
|
|
//Submit the order
|
|
|
|
if(!OrderSend(request,result))
|
|
PrintFormat("OrderSend erreur %d",GetLastError()); // en cas d'erreur d'envoi de la demande, affiche le code d'erreur
|
|
//--- informations de l'opération
|
|
PrintFormat("retcode=%u transaction=%I64u ordre=%I64u",result.retcode,result.deal,result.order);
|
|
|
|
if(result.retcode == TRADE_RETCODE_DONE && result.deal != 0)
|
|
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|