//+------------------------------------------------------------------+
//| HedgeV03.mq5 |
//| Jay |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Jay"
#property link "https://www.mql5.com"
#property version "1.00"
//\[] {} ||
#include <Trade/Trade.mqh>
CTrade *trade;
input ENUM_TIMEFRAMES InpTimeframe=PERIOD_CURRENT; // Timeframe
for trend analysis
input double InpLotsize = 0.01; // Lotsize
input double InpLotMultiplier = 2; // Lotsize multiplier
input int InpPeriod = 5; // Period for market move calculation
input int InpTakeProfitPips = 50; // Take Profit in Pips
input int InpStopLossPips = 100; // Stop Loss in Pips
input int InpHedgeDistPips = 50; // Hedge Distance in Pips
input string InpTradeComment = __FILE__; // Trade Comment
input ulong InpMagicNumber = 20202020; // EA Magic Number
input int InpADXPeriod = 14; // ADX Period
input int InpADXValue = 20; // ADX tolerance limit
double takeProfit = 0;
double stopLoss = 0;
double Ask = 0;
double Bid = 0;
double openPrice=0;
double orderTP=0;
double hedgeDist=0;
double mfactor=1;
bool upTrend = false;
bool downTrend = false;
int HandleADX;
double ADXBuffer[];
static double maximumAccountBalance=0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit(){
trade = new CTrade();
trade.SetExpertMagicNumber(InpMagicNumber);
switch(_Digits){
case(4):
mfactor = 1;
break;
case(5):
mfactor = 10;
break;
default:
mfactor = 1;
break;
}
takeProfit = NormalizeDouble((InpTakeProfitPips)*mfactor*_Point, _Digits);
//orderTP = takeProfit;
orderTP = NormalizeDouble((InpTakeProfitPips*2)*mfactor*_Point, _Digits);
hedgeDist = NormalizeDouble((InpHedgeDistPips)*mfactor*_Point, _Digits);
stopLoss = NormalizeDouble(InpStopLossPips*mfactor*_Point, _Digits);
maximumAccountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
HandleADX = iADX(_Symbol,InpTimeframe, InpADXPeriod);
if(HandleADX==INVALID_HANDLE) return(INIT_FAILED);
ArraySetAsSeries(ADXBuffer, true);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
if(HandleADX!=INVALID_HANDLE) IndicatorRelease(HandleADX);
delete trade;
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick(){
//if(!NewBar()) return;
bool signalOpenBuy = false;
bool signalOpenSell = false;
bool signalCloseBuy = false;
bool signalCloseSell = false;
double sellStopPrice=0;
double buyStopPrice=0;
double totalBuyProfit = 0;
double totalSellProfit = 0;
double totalProfit = 0;
int cnt = CopyBuffer(HandleADX, 0, 0, 3, ADXBuffer);
Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
datetime now = TimeLocal();
static double todaysProfit = 0;
static string today = "";
static double todaysBalance = 0;
if(today==TimeToString(TimeLocal(),TIME_DATE)) // date has not changed yet
todaysProfit = AccountInfoDouble(ACCOUNT_EQUITY)-todaysBalance;
else{
todaysBalance = AccountInfoDouble(ACCOUNT_BALANCE); //Reset starting
balance of the day
todaysProfit = 0; //Reset today's profit to ZERO.
today = TimeToString(TimeLocal(),TIME_DATE);
}
if(maximumAccountBalance<AccountInfoDouble(ACCOUNT_BALANCE))
maximumAccountBalance=AccountInfoDouble(ACCOUNT_BALANCE);
double highestPrice=iHigh(_Symbol,InpTimeframe,1);
double lowestPrice=iLow(_Symbol,InpTimeframe,1);
double highestClose=iClose(_Symbol,InpTimeframe,1);
double lowestClose=iClose(_Symbol,InpTimeframe,1);
double avgHLC1 = (iHigh(_Symbol,InpTimeframe,1) +
iLow(_Symbol,InpTimeframe,1) + iClose(_Symbol,InpTimeframe,1))/3;
double highestAvgHLC = avgHLC1;
double lowestAvgHLC = avgHLC1;
for(int i=1; i<=InpPeriod; i++){
double avgHLC = (iHigh(_Symbol,InpTimeframe,i) +
iLow(_Symbol,InpTimeframe,i) + iClose(_Symbol,InpTimeframe,i))/3;
if(avgHLC > highestAvgHLC) highestAvgHLC=avgHLC;
if(avgHLC < lowestAvgHLC) lowestAvgHLC=avgHLC;
if(iHigh(_Symbol,InpTimeframe,i)>highestPrice) highestPrice =
iHigh(_Symbol,InpTimeframe,i);
if(iLow(_Symbol,InpTimeframe,i)<lowestPrice) lowestPrice =
iLow(_Symbol,InpTimeframe,i);
if(iClose(_Symbol,InpTimeframe,i)>highestClose) highestClose =
iClose(_Symbol,InpTimeframe,i);
if(iClose(_Symbol,InpTimeframe,i)<lowestClose) lowestClose =
iClose(_Symbol,InpTimeframe,i);
}
upTrend = false; downTrend =false;
//if(iHigh(_Symbol,InpTimeframe,0)>highestPrice &&
iClose(_Symbol,InpTimeframe,0)>highestClose) upTrend=true;
//if(iLow(_Symbol,InpTimeframe,0)<lowestPrice &&
iClose(_Symbol,InpTimeframe,0)<lowestClose) downTrend=true;
if(iHigh(_Symbol,InpTimeframe,0)>highestPrice && ADXBuffer[0]>InpADXValue)
upTrend=true;
if(iLow(_Symbol,InpTimeframe,0)<lowestPrice && ADXBuffer[0]>InpADXValue)
downTrend=true;
//if(avgHLC1>highestAvgHLC && ADXBuffer[0]>InpADXValue) upTrend=true;
//if(avgHLC1<lowestAvgHLC && ADXBuffer[0]>InpADXValue) downTrend=true;
//Fetch no. of BUY and SELL positions, open prices & lotsize of the last BUY or
SELL order
double lastBuyLot = 0;
double lastSellLot = 0;
int nBuyPositions = 0; // Number of Buy positions
int nSellPositions = 0; // Number of Sell positions
int nBuyStopOrders = 0; // Number of Buystop orders
int nSellStopOrders = 0; // Number of Sellstop orders
ulong lastBuyTicket = 0;
ulong lastSellTicket = 0;
ulong lastBuyStopTicket = 0;
ulong lastSellStopTicket = 0;
double lastBuyStopLot = 0;
double lastSellStopLot = 0;
for (int i=PositionsTotal()-1; i>=0 ; i--){
ulong myTicket = PositionGetTicket(i);
if (PositionSelectByTicket(myTicket) &&
PositionGetString(POSITION_SYMBOL)==_Symbol &&
PositionGetInteger(POSITION_MAGIC)==InpMagicNumber){
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) {
nBuyPositions++;
if (PositionGetDouble(POSITION_VOLUME) > lastBuyLot){
lastBuyLot = PositionGetDouble(POSITION_VOLUME);
lastBuyTicket = myTicket;
}
}
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL){
nSellPositions++;
if (PositionGetDouble(POSITION_VOLUME) > lastSellLot){
lastSellLot = PositionGetDouble(POSITION_VOLUME);
lastSellTicket = myTicket;
}
}
}
}
for (int i=OrdersTotal()-1; i>=0; i--){
ulong myTicket = OrderGetTicket(i);
if (OrderSelect(myTicket) && OrderGetString(ORDER_SYMBOL)==_Symbol &&
OrderGetInteger(ORDER_MAGIC)==InpMagicNumber){
if(OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_STOP){
nBuyStopOrders++;
lastBuyStopTicket = myTicket;
lastBuyStopLot=OrderGetDouble(ORDER_VOLUME_INITIAL);
}
if(OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_STOP){
nSellStopOrders++;
lastSellStopTicket = myTicket;
lastSellStopLot=OrderGetDouble(ORDER_VOLUME_INITIAL);
}
}
}
bool closeAllPositions=false;
if((PositionSelectByTicket(lastBuyTicket) &&
Ask>PositionGetDouble(POSITION_PRICE_OPEN)+takeProfit) ||
(PositionSelectByTicket(lastSellTicket) &&
Bid<PositionGetDouble(POSITION_PRICE_OPEN)-takeProfit)){
closeAllPositions = true;
}
/*
//DON'T RISK TOO MUCH MONEY
//if((MathMax(nBuyPositions, nSellPositions)>3 &&
AccountInfoDouble(ACCOUNT_PROFIT)>0) ||
AccountInfoDouble(ACCOUNT_EQUITY)<todaysBalance*0.90)
if(AccountInfoDouble(ACCOUNT_EQUITY)<todaysBalance*0.90){
Print("10% loss limit reached...... Closing all positions");
closeAllPositions=true;
}
*/
if(closeAllPositions){
ulong myTicket;
for (int i=PositionsTotal()-1; i>=0 ; i--){ //Close all open positions
myTicket = PositionGetTicket(i);
if (PositionSelectByTicket(myTicket) &&
PositionGetString(POSITION_SYMBOL)==_Symbol &&
PositionGetInteger(POSITION_MAGIC)==InpMagicNumber)
closePosition(myTicket);
}
for (int i=OrdersTotal()-1; i>=0; i--){ //Delete all pending STOP orders
myTicket = OrderGetTicket(i);
if (OrderSelect(myTicket) && OrderGetString(ORDER_SYMBOL)==_Symbol
&& OrderGetInteger(ORDER_MAGIC)==InpMagicNumber)
deletePendingOrder(myTicket);
}
//Print("Closing all positions");
return;
}
//===============================================================
================================================================
===========
double stopLotSize = 0;
double stopOpenPrice = 0;
if(nBuyPositions>0){ //Place SELLSTOP order at hedge distance below last
BUY position
if(PositionSelectByTicket(lastBuyTicket)){
if(nSellStopOrders==0) { // If no SELLSTOP order exists
stopOpenPrice = MathMin(PositionGetDouble(POSITION_PRICE_OPEN)-
hedgeDist, Bid);
if(nSellPositions==0 && nBuyPositions==1) //If there is a single BUY
order
stopLotSize = 3*PositionGetDouble(POSITION_VOLUME);
else
stopLotSize = InpLotMultiplier*PositionGetDouble(POSITION_VOLUME);
if(nSellPositions==0 || lastBuyLot>lastSellLot)
if(!
trade.SellStop(stopLotSize,stopOpenPrice,_Symbol,stopOpenPrice+stopLoss,stopO
penPrice-orderTP,0,0,InpTradeComment))
Print("SELLSTOP failed. Return code=",trade.ResultRetcode(), ". Code
description: ",trade.ResultRetcodeDescription());
}
}
}
if(nSellPositions>0) { //Place BUYSTOP order at hedge distance above last
SELL position
if(PositionSelectByTicket(lastSellTicket)){
if(nBuyStopOrders==0) { // If no BUYSTOP order exists
stopOpenPrice = MathMax(PositionGetDouble(POSITION_PRICE_OPEN)
+hedgeDist, Ask);
if(nSellPositions==1 && nBuyPositions==0) //If there is a single SELL
order
stopLotSize = 3*PositionGetDouble(POSITION_VOLUME);
else
stopLotSize = InpLotMultiplier*PositionGetDouble(POSITION_VOLUME);
if(nBuyPositions==0 || lastSellLot>lastBuyLot)
if(!trade.BuyStop(stopLotSize,stopOpenPrice,_Symbol,stopOpenPrice-
stopLoss,stopOpenPrice+orderTP,0,0,InpTradeComment))
Print("BUYSTOP failed. Return code=",trade.ResultRetcode(), ". Code
description: ",trade.ResultRetcodeDescription());
}
}
}
double initialLotsize = InpLotsize;
if(nBuyPositions==0 && nSellPositions==0){
if(OrderSelect(lastBuyStopTicket))
deletePendingOrder(lastBuyStopTicket);
if(OrderSelect(lastSellStopTicket))
deletePendingOrder(lastSellStopTicket);
//if(upTrend){
if(upTrend || lastProfitableDealType()==DEAL_TYPE_SELL){
if(!trade.Buy(initialLotsize,_Symbol, Ask, Ask-stopLoss, Ask+orderTP,
InpTradeComment))
Print("BUY trade failed. Return code=",trade.ResultRetcode(), ". Code
description: ",trade.ResultRetcodeDescription(), " Ask = ", Ask );
}
else
//if(downTrend){ //Downtrend - place a SELL order
if(downTrend || lastProfitableDealType()==DEAL_TYPE_BUY){
if(!trade.Sell(initialLotsize,_Symbol, Bid,Bid+stopLoss,Bid-orderTP,
InpTradeComment))
Print("SELL trade failed. Return code=",trade.ResultRetcode(), ". Code
description: ",trade.ResultRetcodeDescription(), " Bid = ", Bid);
}
}
Comment("\nUpTrend = ", upTrend, " DownTrend = ", downTrend, " ADX Value = ",
NormalizeDouble(ADXBuffer[0],0),
"\nTakeProfit = ", InpTakeProfitPips, " Stoploss = ", InpStopLossPips, " Hedge
Distance = " ,InpHedgeDistPips, " Initial Lotsize = ", initialLotsize,
"\nHighest avgHLC = ", NormalizeDouble(highestAvgHLC,_Digits), " lowest
avgHLC = ", NormalizeDouble(lowestAvgHLC,_Digits),
" AvgHLC1 = ", NormalizeDouble(avgHLC1,_Digits),
"\nHighest Price = ", NormalizeDouble(highestPrice,_Digits), " Lowest Price =
", NormalizeDouble(lowestPrice,_Digits),
"\n",
"\n",
"\n#Buy Positions= ", nBuyPositions, " #SELLSTOP orders = ",
nSellStopOrders, " LastBuyLot = ", lastBuyLot, " SellStop Lot = ", lastSellStopLot,
"\n#Sell Positions = ", nSellPositions, " #BUYSTOP orders = ",
nBuyStopOrders, ", LastSellLot = ", lastSellLot, " BuyStop Lot = ", lastBuyStopLot,
"\n",
"\nDate", today, " Opening Balance = ", todaysBalance, " Day's profit = ",
NormalizeDouble(todaysProfit,2),
" Profit in % - ", NormalizeDouble(todaysProfit*100/todaysBalance, 2),
"\n",
"\nAccount balance = ",
NormalizeDouble(AccountInfoDouble(ACCOUNT_BALANCE),2), " Maximum
Account Balance = ", maximumAccountBalance,
"\nAccount equity = ",
NormalizeDouble(AccountInfoDouble(ACCOUNT_EQUITY),2),
"\nAccount Profit = ",
NormalizeDouble(AccountInfoDouble(ACCOUNT_PROFIT),2),
"\nLast Profitable Deal Type = ", lastProfitableDealType(),
"\n"
);
return;
}
//======================================= CLOSE A POSITION
================================================================
===============================
void closePosition(ulong myTicket){
int Retries=0;
while(!trade.PositionClose(myTicket) && Retries <=5){
Print("Failed to close position ", myTicket, " Return
code=",trade.ResultRetcode(), ". Code description:
",trade.ResultRetcodeDescription());
Sleep(6000);
Retries++;
}
}
//======================================= DELETE BUYSTOP or
SELLSTOP orders
================================================================
==============
void deletePendingOrder(ulong myTicket){
if(!trade.OrderDelete(myTicket))
Print("Failed to delete STOP order ", myTicket, " Return
code=",trade.ResultRetcode(), ". Code description:
",trade.ResultRetcodeDescription());
}
void trailStopLoss(ulong myTicket){
double newStopLoss = 0;
if(PositionSelectByTicket(myTicket)){
double CurrentStopLoss = PositionGetDouble(POSITION_SL);
if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY){
newStopLoss = Ask-stopLoss/2;
if (CurrentStopLoss==0 || CurrentStopLoss<newStopLoss) //New stop
loss if price has gone up
if(!trade.PositionModify(myTicket,
newStopLoss,PositionGetDouble(POSITION_TP)))
Print("TrailStop - Failed to modify BUY position ", myTicket, " Return
code=",trade.ResultRetcode(), ". Code description:
",trade.ResultRetcodeDescription());
}
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
newStopLoss = Bid+stopLoss/2;
if (CurrentStopLoss==0 || CurrentStopLoss>newStopLoss) //New stop
loss if price has gone down
if(!trade.PositionModify(myTicket,newStopLoss,
PositionGetDouble(POSITION_TP)))
Print("TrailStop - Failed to modify SELL position ", myTicket, " Return
code=",trade.ResultRetcode(), ". Code description:
",trade.ResultRetcodeDescription());
}
}
}
//Find direction of last profitable trade
ENUM_DEAL_TYPE lastProfitableDealType(){
HistorySelect(TimeCurrent()-86400, TimeCurrent()); // Order history for last 24
hours.
ulong myTicket;
for(int i = HistoryDealsTotal()-1; i>=0; i--){
myTicket=HistoryDealGetTicket(i);
if(HistoryDealGetString(myTicket,DEAL_SYMBOL)==_Symbol &&
HistoryDealGetInteger(myTicket,DEAL_MAGIC)==InpMagicNumber)
if(HistoryDealGetDouble(myTicket, DEAL_PROFIT) > 0 &&
HistoryDealGetInteger(myTicket,DEAL_ENTRY)==DEAL_ENTRY_OUT) //Deal
triggered by TakeProfit
return HistoryDealGetInteger(myTicket, DEAL_TYPE);
}
return DEAL_TYPE_CORRECTION;
}