PerkyPro_v4

Profit factor:
0.57
Orders Execution
It automatically opens orders when conditions are reachedChecks for the total of open ordersIt can change open orders parameters, due to possible stepping strategyIt Closes Orders by itself
10 Views
0 Downloads
0 Favorites
PerkyPro_v4
/*-----------------------------+
|			       |
| Shared by www.Aptrafx.com    |
|			       |
+------------------------------*/

//+------------------------------------------------------------------+
//|                                           PerkyProNrtr_v4.mq4    |
//|                      perky Aint no turkey (most of the time)     |
//|                                                                  |
//| 10/18/2006 Robert Hill                                           |
//|                                                                  |
//|         Version 1.2                                              |
//|            Cleaned up code for easier modification and speed     |
//|            by making more modular and calling custom indicators  |
//|            only where needed.                                    |
//|                                                                  |
//|         Version 1.3                                              |
//|            Added Money Management, Trailing Stop function        |
//|             and Magic Number                                     |
//|            Added code to use correct value for StopLoss          |
//|             and to normalize all price data sent to server       |
//|            Uses current price from MarketInfo                    |
//|             instead of Bid and Ask                               |
//|                                                                  | 
//|         Version 1.4                                              |
//|            Added ability to change MA_Period for TrendEnvelopev2 |
//|                                                                  | 
//+------------------------------------------------------------------+

// Version 1.4 
#include <stdlib.mqh>
#include <stderror.mqh> 

 bool Debug = false;
//+---------------------------------------------------+
//|Account functions                                  |
//+---------------------------------------------------+
extern bool AccountIsMini = true;      // Change to true if trading mini account
//+---------------------------------------------------+
//|Money Management                                   |
//+---------------------------------------------------+
extern bool MoneyManagement = true; // Change to false to shutdown money management controls.
                                    // Lots = 1 will be in effect and only 1 lot will be open regardless of equity.
extern double TradeSizePercent = 10;      // Change to whatever percent of equity you wish to risk.
extern double Lots = 0.1;             // standard lot size. 
 double MaxLots = 100;
 
//+---------------------------------------------------+
//|Profit controls                                    |
//+---------------------------------------------------+
extern double StopLoss = 65;        // Maximum pips willing to lose per position.
extern bool UseTrailingStop = false;
extern int TrailingStopType = 2;        // Type 1 moves stop immediately, Type 2 waits til value of TS is reached
extern double TrailingStop = 25;    // Change to whatever number of pips you wish to trail your position with.
 double Margincutoff = 800;   // Expert will stop trading if equity level decreases to that level.
extern bool UseTakeProfit = false;
extern int TakeProfit = 999;          // Maximum profit level achieved.
extern int Slippage = 3;           // Possible fix for not getting filled or closed    

extern int MA_Period = 21;
 int SignalCandle=1;

//extern double BIG_JUMP=30.0;       // Check for too-big candlesticks (avoid them)
//extern double DOUBLE_JUMP=55.0;
   // Check for pairs of big candlesticks
//   extern  int ADXbarrier=24;    

    bool TradeAllowed=false;
   
double lotMM;
int MagicNumber;
string setup = "";
int totalTries = 5; 
int retryDelay = 1000;

int init() 
{
	MagicNumber = 4000 + func_Symbol2Val(Symbol())*100 + func_TimeFrame_Const2Val(Period()); 
   setup="Pro_v4 " + Symbol() + "_" + func_TimeFrame_Val2String(func_TimeFrame_Const2Val(Period()));
//  if (Period() != PERIOD_M30)
//  {
   // Alert("Please run on M30 chart");
//  }
}


bool BuySignal()
{
   double proup;

     proup  =iCustom(Symbol(),Period(),"TrendEnvelopes_v2",MA_Period,0,SignalCandle); //up
     
     if (proup<9999) return(true);
     return(false);
}


bool SellSignal()
{
   double prodown;
   
     prodown=iCustom(Symbol(),Period(),"TrendEnvelopes_v2",MA_Period,1,SignalCandle);//down 
     
     if (prodown<9999) return (true);
     return (false);
 }

bool BuyExitSignal()
{
   double proup;
   
     proup  =iCustom(Symbol(),Period(),"TrendEnvelopes_v2",MA_Period,0,SignalCandle); //up
     
     if( proup > 9999) return(true);
     return(false); 

 }

bool SellExitSignal()
{
   double prodown;
   
     prodown=iCustom(Symbol(),Period(),"TrendEnvelopes_v2",MA_Period, 1,SignalCandle);//down 
     
     if( prodown>9999) return(true);
     return(false); 
 }

 
int start()
{
   // Bar handling
datetime bartime=0;                      // used to determine when a bar has moved
int      bartick=0;                       //Tick counter
// bar counting
   if(bartime!=Time[0]) 
     {
      bartime=Time[0];
      bartick++; 
      TradeAllowed=true;
     }

// Was there a sudden jump?  Ignore it...
 // if((MathAbs(Open[1]-Open[0])/Point)>=BIG_JUMP) {
   // return(0);
 // }
 // if((MathAbs(Open[2]-Open[1])/Point)>=BIG_JUMP) {
   // return(0);
  //}
  //if((MathAbs(Open[3]-Open[2])/Point)>=BIG_JUMP) {
   // return(0);
 // }
 // if((MathAbs(Open[4]-Open[3])/Point)>=BIG_JUMP) {
   // return(0);
 // }
 // if((MathAbs(Open[5]-Open[4])/Point)>=BIG_JUMP) {
    //return(0);
  //}
  //if((MathAbs(Open[2]-Open[0])/Point)>=DOUBLE_JUMP) {
    //return(0);
  //}
 // if((MathAbs(Open[3]-Open[1])/Point)>=DOUBLE_JUMP) {
    //return(0);
 // }
  //if((MathAbs(Open[4]-Open[2])/Point)>=DOUBLE_JUMP) {
   // return(0);
 // }
 // if((MathAbs(Open[5]-Open[3])/Point)>=DOUBLE_JUMP) {
   // return(0);
 // }
   
//+------------------------------------------------------------------+
//| Check for Open Position                                          |
//+------------------------------------------------------------------+
  
  if (CheckOpenPositions() > 0) HandleOpenPositions();
  
//+------------------------------------------------------------------+
//| Check if OK to make new trades                                   |
//+------------------------------------------------------------------+


   if(AccountFreeMargin() < Margincutoff) return(0);
   
// Only allow 1 trade per Symbol

  if (CheckOpenPositions() > 0) return(0);
   
  lotMM = GetLots();
  if( TradeAllowed && BuySignal())  
  {
	  OpenBuyOrder();
     TradeAllowed=false;
     return(0);
  }
     
  if(TradeAllowed && SellSignal()) 
  {
     OpenSellOrder();
     TradeAllowed=false;
  }
  
  return(0);
}

//+------------------------------------------------------------------+
//| OpenBuyOrder                                                     |
//| If Stop Loss or TakeProfit are used the values are calculated    |
//| for each trade                                                   |
//+------------------------------------------------------------------+
void OpenBuyOrder()
{
   int ticket;
   int cnt, err, digits;
   double myStopLoss = 0, myTakeProfit = 0, myPrice = 0;
   
   myPrice = MarketInfo(Symbol(), MODE_ASK);
   myStopLoss = 0;
   if ( StopLoss > 0 ) myStopLoss = myPrice - StopLoss * Point ;
	if (myStopLoss != 0) ValidStopLoss(OP_BUY, myStopLoss); 
   myTakeProfit = 0;
   if (UseTakeProfit && TakeProfit>0) myTakeProfit = myPrice + TakeProfit * Point;
      
	// Normalize all price / stoploss / takeprofit to the proper # of digits.
   digits = MarketInfo(Symbol(), MODE_DIGITS);
	if (digits > 0) 
	{
		myPrice = NormalizeDouble(myPrice, digits);
	   myStopLoss = NormalizeDouble(myStopLoss, digits);
		myTakeProfit = NormalizeDouble(myTakeProfit, digits); 
	}
	
   
   OrderSend(Symbol(),OP_BUY,lotMM,myPrice,Slippage,myStopLoss,myTakeProfit,setup,MagicNumber,0,LimeGreen); 
	if (ticket > 0)
	{
		if (OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) 
		{
		  if (Debug) Print("BUY order opened : ", OrderOpenPrice());
		}
	}
	else
	{
		err = GetLastError();
      Print("Error opening BUY order : (" + err + ") " + ErrorDescription(err));
   }
}

//+------------------------------------------------------------------+
//| OpenSellOrder                                                    |
//| If Stop Loss or TakeProfit are used the values are calculated    |
//| for each trade                                                   |
//+------------------------------------------------------------------+
void OpenSellOrder()
{
   int ticket;
   int cnt, err, digits;
   double myStopLoss = 0, myTakeProfit = 0, myPrice = 0;
   
   myPrice = MarketInfo(Symbol(), MODE_BID);
   myStopLoss = 0;
   if ( StopLoss > 0 ) myStopLoss = myPrice + StopLoss * Point ;
	if (myStopLoss != 0) ValidStopLoss(OP_SELL, myStopLoss); 

   myTakeProfit = 0;
   if (UseTakeProfit && TakeProfit > 0) myTakeProfit = myPrice - TakeProfit * Point;
       
	// Normalize all price / stoploss / takeprofit to the proper # of digits.
	digits = MarketInfo(Symbol(), MODE_DIGITS);
	if (digits > 0) 
	{
	   myPrice = NormalizeDouble(myPrice, digits);
	   myStopLoss = NormalizeDouble(myStopLoss, digits);
	   myTakeProfit = NormalizeDouble(myTakeProfit, digits); 
	}
	
   ticket=OrderSend(Symbol(),OP_SELL,lotMM,myPrice,Slippage,myStopLoss,myTakeProfit,setup,MagicNumber,0,Red); 
	if (ticket > 0)
	{
		if (OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) 
			{
			  if (Debug) Print("SELL order opened : ", OrderOpenPrice());
			}
	}
	else
	{
			err = GetLastError();
         Print("Error opening SELL order : (" + err + ") " + ErrorDescription(err));
   }
	return(0);
}

//+------------------------------------------------------------------+
//| Check Open Position Controls                                     |
//+------------------------------------------------------------------+
int CheckOpenPositions()
{
   int cnt, total, NumPositions;
   int NumBuyTrades, NumSellTrades;   // Number of buy and sell trades in this symbol
   
   NumBuyTrades = 0;
   NumSellTrades = 0;
   total=OrdersTotal();
   for(cnt=OrdersTotal()-1;cnt>=0;cnt--)
     {
      OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES);
      if ( OrderSymbol() != Symbol()) continue;
      if ( OrderMagicNumber() != MagicNumber)  continue;
      
      if(OrderType() == OP_BUY )  NumBuyTrades++;
      if(OrderType() == OP_SELL ) NumSellTrades++;
             
     }
     NumPositions = NumBuyTrades + NumSellTrades;
     return (NumPositions);
  }
//+------------------------------------------------------------------+
//| Modify Open Position Controls                                    |
//|  Try to modify position 3 times                                  |
//+------------------------------------------------------------------+
bool ModifyOrder(int nOrderType, int ord_ticket,double op, double price,double tp, color mColor = CLR_NONE)
{
    int cnt, err;
    double myStop;
    
    myStop = ValidStopLoss (nOrderType, price);
    cnt=0;
    while (cnt < totalTries)
    {
       if (OrderModify(ord_ticket,op,myStop,tp,0,mColor))
       {
         return(true);
       }
       else
       {
          err=GetLastError();
          if (err > 1) Print(cnt," Error modifying order : (", ord_ticket , ") " + ErrorDescription(err), " err ",err);
          if (err>0) cnt++;
          Sleep(retryDelay);
       }
    }
    return(false);
}

// 	Adjust stop loss so that it is legal.
double ValidStopLoss(int cmd, double sl)
{
   
   if (sl == 0) return(0.0);
   
   double mySL, myPrice;
   double dblMinStopDistance = MarketInfo(Symbol(),MODE_STOPLEVEL)*MarketInfo(Symbol(), MODE_POINT);
   
   mySL = sl;
   
// Check if SlopLoss needs to be modified

   switch(cmd)
   {
   case OP_BUY:
      myPrice = MarketInfo(Symbol(), MODE_BID);
	   if (myPrice - sl < dblMinStopDistance) 
		mySL = myPrice - dblMinStopDistance;	// we are long
		break;
      
   case OP_SELL:
      myPrice = MarketInfo(Symbol(), MODE_ASK);
	   if (sl - myPrice < dblMinStopDistance) 
		mySL = myPrice + dblMinStopDistance;	// we are long

   }
   return(NormalizeDouble(mySL,MarketInfo(Symbol(), MODE_DIGITS)));
}


//+------------------------------------------------------------------+
//| HandleTrailingStop                                               |
//| Type 1 moves the stoploss without delay.                         |
//| Type 2 waits for price to move the amount of the trailStop       |
//| before moving stop loss then moves like type 1                   |
//| Type 3 uses up to 3 levels for trailing stop                     |
//|      Level 1 Move stop to 1st level                              |
//|      Level 2 Move stop to 2nd level                              |
//|      Level 3 Trail like type 1 by fixed amount other than 1      |
//| Possible future types                                            |
//| Type 4 uses 2 for 1, every 2 pip move moves stop 1 pip           |
//| Type 5 uses 3 for 1, every 3 pip move moves stop 1 pip           |
//+------------------------------------------------------------------+
int HandleTrailingStop(int type, int ticket, double op, double os, double tp)
{
    double pt, TS=0, myAsk, myBid;
    double bos,bop,opa,osa;
    
    switch(type)
    {
       case OP_BUY:
       {
		 myBid = MarketInfo(Symbol(),MODE_BID);
       switch(TrailingStopType)
       {
        case 1: pt = Point*StopLoss;
                if(myBid-os > pt)
                 ModifyOrder(type, ticket,op,myBid-pt,tp, Aqua);
                break;
        case 2: pt = Point*TrailingStop;
                if(myBid-op > pt && os < myBid - pt)
                 ModifyOrder(type, ticket,op,myBid-pt,tp, Aqua);
                break;
       }
       return(0);
       break;
       }
    case  OP_SELL:
    {
		myAsk = MarketInfo(Symbol(),MODE_ASK);
       switch(TrailingStopType)
       {
        case 1: pt = Point*StopLoss;
                if(os - myAsk > pt)
                 ModifyOrder(type, ticket,op,myAsk+pt,tp, Aqua);
                break;
        case 2: pt = Point*TrailingStop;
                if(op - myAsk > pt && os > myAsk+pt)
                 ModifyOrder(type, ticket,op,myAsk+pt,tp, Aqua);
                break;
       }
    }
    return(0);
    }
}

//+------------------------------------------------------------------+
//| Handle Open Positions                                            |
//| Check if any open positions need to be closed or modified        |
//+------------------------------------------------------------------+
int HandleOpenPositions()
{
   int cnt;
   
   for(cnt=OrdersTotal()-1;cnt>=0;cnt--)
   {
      OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES);
      if ( OrderSymbol() != Symbol()) continue;
      if ( OrderMagicNumber() != MagicNumber)  continue;
      
      if(OrderType() == OP_BUY)
      {
            
         if ( BuyExitSignal())
          {
               OrderClose(OrderTicket(),OrderLots(),Bid, Slippage, Violet);
          }
          else
          {
            if (UseTrailingStop)
            {
               HandleTrailingStop(OP_BUY,OrderTicket(),OrderOpenPrice(),OrderStopLoss(),OrderTakeProfit());
            }
          }
      }

      if(OrderType() == OP_SELL)
      {
          if (SellExitSignal())
          {
             OrderClose(OrderTicket(),OrderLots(),Ask, Slippage, Violet);
          }
          else
          {
             if(UseTrailingStop)  
             {                
               HandleTrailingStop(OP_SELL,OrderTicket(),OrderOpenPrice(),OrderStopLoss(),OrderTakeProfit());
             }
          }
       }
   }
}

     
//+------------------------------------------------------------------+
//| Get number of lots for this trade                                |
//+------------------------------------------------------------------+
double GetLots()
{
   double lot;
   
   if(MoneyManagement)
   {
     lot = LotsOptimized();
   }
   else
   {
     lot = Lots;
   }
   
   if(AccountIsMini)
   {
     if (lot < 0.1) lot = 0.1;
   }
   else
   {
     if (lot >= 1.0) lot = MathFloor(lot); else lot = 1.0;
   }
   if (lot > MaxLots) lot = MaxLots;
   
   return(lot);
}

//+------------------------------------------------------------------+
//| Calculate optimal lot size                                       |
//+------------------------------------------------------------------+

double LotsOptimized()
  {
   double lot=Lots;
//---- select lot size
   lot=NormalizeDouble(MathFloor(AccountFreeMargin()*TradeSizePercent/10000)/10,1);
   
  
  // lot at this point is number of standard lots
  
//  if (Debug) Print ("Lots in LotsOptimized : ",lot);
  
  // Check if mini or standard Account
  
  if(AccountIsMini)
  {
    lot = MathFloor(lot*10)/10;
    
   }
   return(lot);
  }

//+------------------------------------------------------------------+
//| Time frame interval appropriation  function                      |
//+------------------------------------------------------------------+

int func_TimeFrame_Const2Val(int Constant ) {
   switch(Constant) {
      case 1:  // M1
         return(1);
      case 5:  // M5
         return(2);
      case 15:
         return(3);
      case 30:
         return(4);
      case 60:
         return(5);
      case 240:
         return(6);
      case 1440:
         return(7);
      case 10080:
         return(8);
      case 43200:
         return(9);
   }
}

//+------------------------------------------------------------------+
//| Time frame string appropriation  function                               |
//+------------------------------------------------------------------+

string func_TimeFrame_Val2String(int Value ) {
   switch(Value) {
      case 1:  // M1
         return("PERIOD_M1");
      case 2:  // M1
         return("PERIOD_M5");
      case 3:
         return("PERIOD_M15");
      case 4:
         return("PERIOD_M30");
      case 5:
         return("PERIOD_H1");
      case 6:
         return("PERIOD_H4");
      case 7:
         return("PERIOD_D1");
      case 8:
         return("PERIOD_W1");
      case 9:
         return("PERIOD_MN1");
   	default: 
   		return("undefined " + Value);
   }
}

int func_Symbol2Val(string symbol) {
   string mySymbol = StringSubstr(symbol,0,6);
	if(mySymbol=="AUDCAD") return(1);
	if(mySymbol=="AUDJPY") return(2);
	if(mySymbol=="AUDNZD") return(3);
	if(mySymbol=="AUDUSD") return(4);
	if(mySymbol=="CHFJPY") return(5);
	if(mySymbol=="EURAUD") return(6);
	if(mySymbol=="EURCAD") return(7);
	if(mySymbol=="EURCHF") return(8);
	if(mySymbol=="EURGBP") return(9);
	if(mySymbol=="EURJPY") return(10);
	if(mySymbol=="EURUSD") return(11);
	if(mySymbol=="GBPCHF") return(12);
	if(mySymbol=="GBPJPY") return(13);
	if(mySymbol=="GBPUSD") return(14);
	if(mySymbol=="NZDUSD") return(15);
	if(mySymbol=="USDCAD") return(16);
	if(mySymbol=="USDCHF") return(17);
	if(mySymbol=="USDJPY") return(18);
	return(19);
}

 
//+------------------------------------------------------------------+

Profitability Reports

EUR/USD Jul 2025 - Sep 2025
1.25
Total Trades 462
Won Trades 48
Lost trades 414
Win Rate 10.39 %
Expected payoff 420.48
Gross Profit 985209.80
Gross Loss -790949.70
Total Net Profit 194260.10
-100%
-50%
0%
50%
100%
USD/JPY Jul 2025 - Sep 2025
1.05
Total Trades 398
Won Trades 53
Lost trades 345
Win Rate 13.32 %
Expected payoff 1.89
Gross Profit 17506.85
Gross Loss -16752.82
Total Net Profit 754.03
-100%
-50%
0%
50%
100%
USD/CAD Jul 2025 - Sep 2025
0.78
Total Trades 176
Won Trades 21
Lost trades 155
Win Rate 11.93 %
Expected payoff -7.09
Gross Profit 4472.69
Gross Loss -5719.73
Total Net Profit -1247.04
-100%
-50%
0%
50%
100%
USD/CAD Oct 2024 - Jan 2025
0.66
Total Trades 308
Won Trades 19
Lost trades 289
Win Rate 6.17 %
Expected payoff -12.21
Gross Profit 7356.71
Gross Loss -11116.59
Total Net Profit -3759.88
-100%
-50%
0%
50%
100%
GBP/USD Jul 2025 - Sep 2025
0.65
Total Trades 328
Won Trades 30
Lost trades 298
Win Rate 9.15 %
Expected payoff -14.78
Gross Profit 8842.70
Gross Loss -13690.20
Total Net Profit -4847.50
-100%
-50%
0%
50%
100%
GBP/USD Oct 2024 - Jan 2025
0.60
Total Trades 405
Won Trades 33
Lost trades 372
Win Rate 8.15 %
Expected payoff -14.08
Gross Profit 8594.20
Gross Loss -14295.80
Total Net Profit -5701.60
-100%
-50%
0%
50%
100%
EUR/USD Oct 2025 - Feb 2026
0.59
Total Trades 444
Won Trades 55
Lost trades 389
Win Rate 12.39 %
Expected payoff -12.75
Gross Profit 7985.80
Gross Loss -13647.60
Total Net Profit -5661.80
-100%
-50%
0%
50%
100%
NZD/USD Jul 2025 - Sep 2025
0.57
Total Trades 262
Won Trades 37
Lost trades 225
Win Rate 14.12 %
Expected payoff -14.80
Gross Profit 5129.20
Gross Loss -9007.50
Total Net Profit -3878.30
-100%
-50%
0%
50%
100%
AUD/USD Jul 2025 - Sep 2025
0.55
Total Trades 258
Won Trades 38
Lost trades 220
Win Rate 14.73 %
Expected payoff -15.89
Gross Profit 5031.40
Gross Loss -9130.50
Total Net Profit -4099.10
-100%
-50%
0%
50%
100%
NZD/USD Oct 2024 - Jan 2025
0.42
Total Trades 366
Won Trades 35
Lost trades 331
Win Rate 9.56 %
Expected payoff -18.07
Gross Profit 4769.70
Gross Loss -11381.50
Total Net Profit -6611.80
-100%
-50%
0%
50%
100%
GBP/AUD Jul 2025 - Sep 2025
0.34
Total Trades 987
Won Trades 32
Lost trades 955
Win Rate 3.24 %
Expected payoff -9.32
Gross Profit 4661.08
Gross Loss -13863.64
Total Net Profit -9202.56
-100%
-50%
0%
50%
100%
USD/CHF Jul 2025 - Sep 2025
0.34
Total Trades 357
Won Trades 40
Lost trades 317
Win Rate 11.20 %
Expected payoff -20.51
Gross Profit 3715.14
Gross Loss -11036.01
Total Net Profit -7320.87
-100%
-50%
0%
50%
100%
AUD/USD Oct 2025 - Feb 2026
0.18
Total Trades 699
Won Trades 38
Lost trades 661
Win Rate 5.44 %
Expected payoff -13.17
Gross Profit 2004.20
Gross Loss -11208.30
Total Net Profit -9204.10
-100%
-50%
0%
50%
100%
GBP/CAD Jul 2025 - Sep 2025
0.00
Total Trades 0
Won Trades 0
Lost trades 0
Win Rate 0.0 %
Expected payoff 0.00
Gross Profit 0.00
Gross Loss 0.00
Total Net Profit 0.00
-100%
-50%
0%
50%
100%

Comments