Professional Strategy Overview: Envelope 2.mq4
This script is an automated trading system designed for the MetaTrader 4 platform. It utilizes a trend-following and mean-reversion logic based on "Envelopes"—a technical indicator that creates a price corridor around a Moving Average.
The logic can be broken down into four primary components: Position Sizing, Entry Logic, Trade Management, and Order Cleanup.
1. Intelligent Position Sizing (Risk Management)
Before opening any trades, the script calculates the optimal lot size based on two factors:
- Account Balance: It looks at your available margin to ensure trade sizes stay within a predefined risk percentage.
- Loss Recovery: The script reviews your trading history. If it detects a string of recent losses without an intervening profit, it automatically reduces the lot size for new trades. This is a "safety brake" designed to protect the account during a losing streak by shrinking the position size until performance stabilizes.
2. Entry Conditions and Logic
The script monitors the market using an Upper Envelope (Buy Zone) and a Lower Envelope (Sell Zone). It seeks to place six specific pending orders: three Buy Stop orders and three Sell Stop orders.
- Time Constraints: The script only places new orders during a specific window of the day (defined by the "Time Open" and "Time Close" settings).
- The Setup: If the current market price is positioned between the upper and lower envelopes, the script identifies potential breakout points:
- Buy Stops: It places three separate buy orders at the Upper Envelope price. Each of these has a different Take Profit target (First, Second, and Third TP).
- Sell Stops: It places three separate sell orders at the Lower Envelope price. Similarly, each has its own unique Take Profit target.
- Unique Identification: The script assigns specific identification numbers (Magic Numbers) to these orders to keep track of which "slot" is filled and which are still available.
3. Dynamic Trade Management (Trailing Stop Loss)
Once a trade is activated (triggered by the market hitting the pending price), the script begins active management:
- Trailing Mechanism: The script tracks the Moving Average or the opposite Envelope (depending on your settings) to act as a "moving floor" for your profit.
- Profit Protection: As the price moves in your favor, the script automatically updates the Stop Loss price to follow the indicator. This ensures that if the market suddenly reverses, you "lock in" some of the gains made during the trend.
- Delay Buffer: It includes a small pause (10 seconds) between adjustments to prevent the system from making rapid, unnecessary modifications to the orders.
4. Order Maintenance and Cleanup
The script performs "housekeeping" to keep the trading screen clean and ensure old data doesn't interfere with new trades:
- Expiration: If a pending order is not triggered by the specified "Time Close," the script automatically deletes it.
- Status Tracking: The script constantly checks if trades have been closed or completed. Once a trade is finished, it clears that specific "slot," making it available for the script to place a new order in the next valid trading window.
/*-----------------------------+
| |
| Shared by www.Aptrafx.com |
| |
+------------------------------*/
//+------------------------------------------------------------------+
//| Envelope 2.mq4 |
//| tageiger |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "tageiger"
#property link "http://www.metaquotes.net"
//---- input parameters
extern int EnvelopePeriod =144;
extern int EnvTimeFrame =0; //envelope time frame: 0=chart,60=1hr,240=4hr, etc.
extern int EnvMaMethod =1; //0=sma,1=ema,2=smma,3=lwma.
extern double EnvelopeDeviation =1;
extern int TimeOpen =0;
extern int TimeClose =23;
extern double FirstTP =89.0;
extern double SecondTP =144.0;
extern double ThirdTP =233.0;
extern double Lots =0.1;
extern double MaximumRisk =0.14;
extern double DecreaseFactor =3;
extern int MaElineTSL =0;//0=iMA trailing stoploss 1=Opposite Envelope TSL
int b1,b2,b3,s1,s2,s3;
double TSL =0;
//+------------------------------------------------------------------+
//| Calculate optimal lot size |
//+------------------------------------------------------------------+
double LotsOptimized()
{
double lot=Lots;
int orders=HistoryTotal(); // history orders total
int losses=0; // number of losses orders without a break
//---- select lot size
lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/1000.0,1);
//---- calcuulate number of losses orders without a break
if(DecreaseFactor>0)
{
for(int i=orders-1;i>=0;i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; }
if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;
//----
if(OrderProfit()>0) break;
if(OrderProfit()<0) losses++;
}
if(losses>1) lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
}
//---- return lot size
if(lot<0.1) lot=0.1;
return(lot);
}
int start()
{
int p=0;p=EnvelopePeriod;
int etf=0;etf=EnvTimeFrame;
int mam=0;mam=EnvMaMethod;
double d=0;d=EnvelopeDeviation;
double btp1,btp2,btp3,stp1,stp2,stp3;
double bline=0,sline=0,ma=0;
int cnt, ticket, total;
ma=iMA(NULL,etf,p,0,mam,PRICE_CLOSE,0);
bline=iEnvelopes(NULL,etf,p,mam,0,PRICE_CLOSE,d,MODE_UPPER,0);
sline=iEnvelopes(NULL,etf,p,mam,0,PRICE_CLOSE,d,MODE_LOWER,0);
total=OrdersTotal();
if(OrdersTotal()==0)
{b1=0;b2=0;b3=0;s1=0;s2=0;s3=0;}
if(OrdersTotal()>0)
{
//Print("Total Orders:",OrdersTotal());
//Print(b1," ",b2," ",b3," ",s1," ",s2," ",s3);
for(cnt=0;cnt<total;cnt++)
{
OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);
if(OrderMagicNumber()==2)
{b1=OrderTicket(); }
if(OrderMagicNumber()==4)
{b2=OrderTicket(); }
if(OrderMagicNumber()==6)
{b3=OrderTicket(); }
if(OrderMagicNumber()==1)
{s1=OrderTicket(); }
if(OrderMagicNumber()==3)
{s2=OrderTicket(); }
if(OrderMagicNumber()==5)
{s3=OrderTicket(); }
}
}
if(b1==0)
{
if(Hour()>TimeOpen && Hour()<TimeClose)
{
if(bline>Close[0] && sline<Close[0])
{
btp1=(NormalizeDouble(bline,4))+(FirstTP*Point);
ticket=OrderSend(Symbol(),
OP_BUYSTOP,
LotsOptimized(),
(NormalizeDouble(bline,4)),
0,
(NormalizeDouble(sline,4)),
btp1,
"",
2,
TimeClose,
Aqua);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
{
b1=ticket;
Print(ticket);
}
else Print("Error Opening BuyStop Order: ",GetLastError());
return(0);
}
}
}
}
if(b2==0)
{
if(Hour()>TimeOpen && Hour()<TimeClose)
{
if(bline>Close[0] && sline<Close[0])
{
btp2=(NormalizeDouble(bline,4))+(SecondTP*Point);
ticket=OrderSend(Symbol(),
OP_BUYSTOP,
LotsOptimized(),
(NormalizeDouble(bline,4)),
0,
(NormalizeDouble(sline,4)),
btp2,
"",
4,
TimeClose,
Aqua);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
{
b2=ticket;
Print(ticket);
}
else Print("Error Opening BuyStop Order: ",GetLastError());
return(0);
}
}
}
}
if(b3==0)
{
if(Hour()>TimeOpen && Hour()<TimeClose)
{
if(bline>Close[0] && sline<Close[0])
{
btp3=(NormalizeDouble(bline,4))+(ThirdTP*Point);
ticket=OrderSend(Symbol(),
OP_BUYSTOP,
LotsOptimized(),
(NormalizeDouble(bline,4)),
0,
(NormalizeDouble(sline,4)),
btp3,
"",
6,
TimeClose,
Aqua);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
{
b3=ticket;
Print(ticket);
}
else Print("Error Opening BuyStop Order: ",GetLastError());
return(0);
}
}
}
}
if(s1==0)
{
if(Hour()>TimeOpen && Hour()<TimeClose)
{
if(bline>Close[0] && sline<Close[0])
{
stp1=NormalizeDouble(sline,4)-(FirstTP*Point);
ticket=OrderSend(Symbol(),
OP_SELLSTOP,
LotsOptimized(),
(NormalizeDouble(sline,4)),
0,
(NormalizeDouble(bline,4)),
stp1,
"",
1,
TimeClose,
HotPink);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
{
s1=ticket;
Print(ticket);
}
else Print("Error Opening SellStop Order: ",GetLastError());
return(0);
}
}
}
}
if(s2==0)
{
if(Hour()>TimeOpen && Hour()<TimeClose)
{
if(bline>Close[0] && sline<Close[0])
{
stp2=NormalizeDouble(sline,4)-(SecondTP*Point);
ticket=OrderSend(Symbol(),
OP_SELLSTOP,
LotsOptimized(),
(NormalizeDouble(sline,4)),
0,
(NormalizeDouble(bline,4)),
stp2,
"",
3,
TimeClose,
HotPink);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
{
s2=ticket;
Print(ticket);
}
else Print("Error Opening SellStop Order: ",GetLastError());
return(0);
}
}
}
}
if(s3==0)
{
if(Hour()>TimeOpen && Hour()<TimeClose)
{
if(bline>Close[0] && sline<Close[0])
{
stp3=NormalizeDouble(sline,4)-(ThirdTP*Point);
ticket=OrderSend(Symbol(),
OP_SELLSTOP,
LotsOptimized(),
(NormalizeDouble(sline,4)),
0,
(NormalizeDouble(bline,4)),
stp3,
"",
5,
TimeClose,
HotPink);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
{
s3=ticket;
Print(ticket);
}
else Print("Error Opening SellStop Order: ",GetLastError());
return(0);
}
}
}
}
for(cnt=0;cnt<total;cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()==OP_BUY)
{
if(MaElineTSL==0) {TSL=NormalizeDouble(ma,4); }
if(MaElineTSL==1) {TSL=NormalizeDouble(sline,4); }
if(Close[0]>OrderOpenPrice())
{
if((Close[0]>sline) && (TSL>OrderStopLoss()))
{
double bsl;bsl=TSL;
OrderModify(OrderTicket(),
OrderOpenPrice(),
bsl,
OrderTakeProfit(),
0,//Order expiration server date/time
Green);
Sleep(10000);
}
}
}
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()==OP_SELL)
{
if(MaElineTSL==0) {TSL=NormalizeDouble(ma,4); }
if(MaElineTSL==1) {TSL=NormalizeDouble(bline,4); }
if(Close[0]<OrderOpenPrice())
{
if((Close[0]<bline) && (TSL<OrderStopLoss()))
{
double ssl;ssl=TSL;
OrderModify(OrderTicket(),
OrderOpenPrice(),
ssl,
OrderTakeProfit(),
0,//Order expiration server date/time
Red);
Sleep(10000);
}
}
}
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(Hour()==TimeClose && OrderType()==OP_BUYSTOP)
{
OrderDelete(OrderTicket());
if(OrderTicket()==b1) {b1=0; return;}
if(OrderTicket()==b2) {b2=0; return;}
if(OrderTicket()==b3) {b3=0; return;}
}
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(Hour()==TimeClose && OrderType()==OP_SELLSTOP)
{
OrderDelete(OrderTicket());
if(OrderTicket()==s1) {s1=0; return;}
if(OrderTicket()==s2) {s2=0; return;}
if(OrderTicket()==s3) {s3=0; return;}
}
OrderSelect(b1,SELECT_BY_TICKET);
if(OrderClosePrice()>0) {b1=0;}
OrderSelect(b2,SELECT_BY_TICKET);
if(OrderClosePrice()>0) {b2=0;}
OrderSelect(b3,SELECT_BY_TICKET);
if(OrderClosePrice()>0) {b3=0;}
OrderSelect(s1,SELECT_BY_TICKET);
if(OrderClosePrice()>0) {s1=0;}
OrderSelect(s2,SELECT_BY_TICKET);
if(OrderClosePrice()>0) {s2=0;}
OrderSelect(s3,SELECT_BY_TICKET);
if(OrderClosePrice()>0) {s3=0;}
}
}
Comments