This script is designed to automatically trade on the Forex market, specifically focusing on placing pending orders based on the previous bar's price action. Here's how it works:
1. Initial Setup and Customization:
- Copyright and Settings: The script starts with copyright information and allows you to customize various settings. These settings control things like the size of trades, how much risk to take, profit targets, and when to trade based on the time of day.
- Money Management: It includes features to automatically adjust the trade size based on your account balance or free margin, aiming to manage risk. You can turn this feature on or off.
- Profit Controls: You can set a stop-loss (the maximum amount you're willing to lose) and a take-profit level (the target profit you want to achieve) for each trade.
- Trailing Stop: The script incorporates a trailing stop feature, which automatically adjusts the stop-loss as the price moves in your favor, helping to lock in profits. There are different types of trailing stops, allowing you to choose how aggressively the stop-loss is adjusted.
- Trading Hours: You can define specific times of the day to trade or avoid trading, based on different market sessions (Asian, European, New York). This can help you focus on periods when the market is more active or avoid times when it's typically quieter.
2. Core Trading Logic:
- Calculations Based on Previous Bar: The script analyzes the high, low, and closing prices of the previous bar (the completed price candle). It calculates a "Pivot" point as the average of these three prices.
- Pending Order Placement: Based on this Pivot point, the script calculates two price levels: a "BuyPrice" and a "SellPrice". It then places two pending orders:
- A "Buy Stop" order is placed at the "BuyPrice", above the Pivot. This order will only be activated if the price rises to that level.
- A "Sell Stop" order is placed at the "SellPrice", below the Pivot. This order will only be activated if the price falls to that level.
- Order Management: The script manages open positions. At the start of each new bar, any existing open positions will be closed and any existing pending orders are deleted. This also includes managing the trailing stop, by modifying existing orders to lock in profits.
3. Risk Management and Order Modification:
- Stop-Loss and Take-Profit: When placing the pending orders, the script also sets stop-loss and take-profit levels, limiting potential losses and aiming for a target profit.
- Slippage Control: The script allows for "slippage," which is a small allowance for the difference between the requested price and the actual price when the order is executed.
- Order Modification: The script contains functions to change existing orders like moving the stop-loss in the case of a trailing stop.
4. Time-Based Filtering:
- Trading Session Control: The trading hours filter allows you to specify which market sessions to trade, ensuring the robot only places orders during certain market hours.
In Simple Terms:
The script acts like a Forex robot that automatically places buy and sell orders based on the price movement of the previous bar. It calculates key price levels and sets up pending orders, ready to be triggered if the price moves in either direction. It also includes features to manage risk (stop-loss), take profits, and adapt to changing market conditions (trailing stop). Finally, you have the control to specify when trading should happen, based on your preferred market sessions.
//+------------------------------------------------------------------+
//| BarTrader_EA.mq4 |
//| Copyright © 2008 |
//| Converted from mt3 by MrPip for yahoo group |
/*
Name := BARTRADER
Author := FAB4X
Link := http://www.FAB4X.com
Notes := Use on 15 or 30m charts
*/
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MrPip"
#include <stdlib.mqh>
extern int MagicNumberBase = 200000;
extern int BuyGap = 17;
extern int SellGap = 13;
//+---------------------------------------------------+
//|Money Management |
//+---------------------------------------------------+
extern string mm = "---Money Management---";
extern double Lots=1.0;
extern double MaxLots = 100;
extern bool UseMoneyManagement = true; // Change to false to shutdown money management controls.
extern bool BrokerIsIBFX = false;
extern string m1="Set mini and micro to false for standard account";
extern bool AccountIsMini = false;
extern bool AccountIsMicro = false;
extern string fm="UseFreeMargin = false to use Account Balance";
extern bool UseFreeMargin = false;
extern double TradeSizePercent = 7.5; // Change to whatever percent of equity you wish to risk.
extern bool BrokerPermitsFractionalLots = true;
//+---------------------------------------------------+
//|Profit controls |
//+---------------------------------------------------+
extern string st6 = "--Profit Controls--";
extern double StopLoss = 45; // Maximum pips willing to lose per position.
extern int TakeProfit = 25; // Maximum profit level achieved.
//*****************************************************
// These inputs are used by the trailing stop function
//*****************************************************
extern string tsp0 = "--Trailing Stop Types--";
extern string tsp1 = " 1 = Trail immediately";
extern string tsp2 = " 2 = Wait to trail";
extern string tsp3 = " 3 = Uses 3 levels before trail";
extern bool UseTrailingStop = false;
extern int TrailingStopType = 1; // Type 1 moves stop immediately, Type 2 waits til value of TS is reached
extern string ts2 = "Settings for Type 2";
extern double TrailingStop = 40; // Change to whatever number of pips you wish to trail your position with.
extern string ts3 = "Settings for Type 3";
extern double FirstMove = 20; // Type 3 first level pip gain
extern double FirstStopLoss = 15; // Move Stop to Breakeven
extern double SecondMove = 30; // Type 3 second level pip gain
extern double SecondStopLoss = 20; // Move stop to lock is profit
extern double ThirdMove = 40; // type 3 third level pip gain
extern double TrailingStop3 = 20; // Move stop and trail from there
extern int Slippage = 5; // Possible fix for not getting closed
extern string sm0="--Trading Hours Filter--";
extern string sm1=" Times are GMT when UseDST=false";
extern string sm2="UseTradingHours - Enter 0 for false, 1 for true";
extern int UseTradingHours = 0;
extern string sm4="TradeAsian - Enter 0 for false, 1 for true";
extern int TradeAsianMarket = 1;
extern int AsianStart = 100; // Start trades after time
extern int AsianStop = 300; // Stop trading after time
extern string sm5="Trade Europe - Enter 0 for false, 1 for true";
extern int TradeEuropeanMarket = 1;
extern int EurStart = 900; // Start trades after time
extern int EurStop = 1100; // Stop trading after time
extern string sm6="Trade NY - Enter 0 for false, 1 for true";
extern int TradeNewYorkMarket = 0;
extern int NYStart = 1300; // Start trades after time
extern int NYStop = 1500; // Stop trading after time
bool YesStop;
//+---------------------------------------------------+
//|General controls |
//+---------------------------------------------------+
int MagicNumber=0;
string setup;
double lotMM;
int TradesInThisSymbol;
double myPoint;
datetime vTime = 0;
double myHigh,myLow,myClose,Pivot,BuyPrice,SellPrice;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
MagicNumber = MagicNumberBase + func_Symbol2Val(Symbol())*100 + func_TimeFrame_Const2Val(Period());
myPoint = SetPoint(Symbol());
Slippage = Slippage*myPoint;
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----
double myStopLong, myStopShort;
double myTakeLong, myTakeShort;
// Check for valid inputs
if (CheckValidUserInputs()) return(0);
//+------------------------------------------------------------------+
//| Check for Open Position |
//+------------------------------------------------------------------+
HandleOpenPositions();
// Check if any open positions were not closed
TradesInThisSymbol = CheckOpenPositions();
//+------------------------------------------------------------------+
//| Check if OK to make new trades |
//+------------------------------------------------------------------+
// Only allow 1 trade per Symbol
if(TradesInThisSymbol > 0) {
return(0);}
YesStop = false;
if (UseTradingHours == 1)
{
YesStop = CheckTradingTimes();
if (YesStop == true)
{
Comment ("Trading has been stopped - wrong time of day");
}
else
{
Comment ("Trading has resumed - time is OK");
}
}
else
Comment ("Trading Time Filter not in use");
if (YesStop == false)
{
myHigh=High[1];
myLow=Low[1];
myClose=Close[1];
Pivot = ( myHigh+myLow+myClose )/ 3 ;
BuyPrice=Pivot+BuyGap*myPoint;
SellPrice=Pivot-SellGap*myPoint;
lotMM = GetLots();
//////////////////////////////////////////////////
// Open Trade at start of bar!
//////////////////////////////////////////////////
if (vTime != Time[0])
{
vTime = Time[0];
myStopLong = StopLong(BuyPrice,StopLoss,myPoint);
myStopLong = ValidStopLoss(Symbol(), OP_BUY, Bid, myStopLong, myPoint);
myTakeLong = TakeLong(BuyPrice,TakeProfit,myPoint);
BuyPrice = NormalizeDouble( BuyPrice, Digits);
myStopLong = NormalizeDouble( myStopLong, Digits);
myTakeLong = NormalizeDouble( myTakeLong, Digits);
OrderSend(Symbol(), OP_BUYSTOP,lotMM,BuyPrice,Slippage,myStopLong,myTakeLong, "", MagicNumber, 0, Blue);
myStopShort = StopShort(SellPrice,StopLoss,myPoint);
myStopShort = ValidStopLoss(Symbol(), OP_SELL, Ask, myStopShort, myPoint);
myTakeShort = TakeShort(SellPrice,TakeProfit,myPoint);
SellPrice = NormalizeDouble( SellPrice, Digits);
myStopShort = NormalizeDouble( myStopShort, Digits);
myTakeShort = NormalizeDouble( myTakeShort, Digits);
OrderSend(Symbol(), OP_SELLSTOP,lotMM,SellPrice,Slippage,myStopShort,myTakeShort, "", MagicNumber, 0,Red);
}
}
//----
return(0);
}
//+------------------------------------------------------------------+
//| Functions beyond this point should not need to be modified |
//| Eventually will be placed in include file |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Check Open Position Controls |
//+------------------------------------------------------------------+
int CheckOpenPositions()
{
int cnt, NumPositions;
int NumBuyTrades, NumSellTrades; // Number of buy and sell trades in this symbol
NumBuyTrades = 0;
NumSellTrades = 0;
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);
}
//+------------------------------------------------------------------+
//| Handle Open Positions |
//| Check if any open positions need to be closed or modified |
// Close Order after each bar!
//+------------------------------------------------------------------+
int HandleOpenPositions()
{
int cnt;
bool YesClose;
double pt;
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 (vTime != Time[0])
{
CloseOrder(OrderTicket(),OrderLots(),Bid);
}
else
{
if (UseTrailingStop)
{
HandleTrailingStop(OP_BUY,OrderTicket(),OrderOpenPrice(),OrderStopLoss(),OrderTakeProfit());
}
}
}
if(OrderType() == OP_SELL)
{
if (vTime != Time[0])
{
CloseOrder(OrderTicket(),OrderLots(),Ask);
}
else
{
if(UseTrailingStop)
{
HandleTrailingStop(OP_SELL,OrderTicket(),OrderOpenPrice(),OrderStopLoss(),OrderTakeProfit());
}
}
}
if (OrderType()==OP_BUYSTOP || OrderType()==OP_SELLSTOP)
{
if (vTime != Time[0]) OrderDelete(OrderTicket(),Brown);
}
}
}
//+------------------------------------------------------------------+
//| Close Open Position Controls |
//| Try to close position 3 times |
//+------------------------------------------------------------------+
void CloseOrder(int ticket,double numLots,double close_price)
{
int CloseCnt, err;
// try to close 3 Times
CloseCnt = 0;
while (CloseCnt < 3)
{
if (OrderClose(ticket,numLots,close_price,Slippage,Violet))
{
CloseCnt = 3;
}
else
{
err=GetLastError();
Print(CloseCnt," Error closing order : (", err , ") " + ErrorDescription(err));
if (err > 0) CloseCnt++;
}
}
}
//*****************************************************
// This function is used by the trailing stop function
//*****************************************************
//+------------------------------------------------------------------+
//| Modify Open Position Controls |
//| Try to modify position 3 times |
//+------------------------------------------------------------------+
void ModifyOrder(int ord_ticket,double op, double price,double tp, color mColor)
{
int CloseCnt, err;
CloseCnt=0;
while (CloseCnt < 3)
{
if (OrderModify(ord_ticket,op,price,tp,0,mColor))
{
CloseCnt = 3;
}
else
{
err=GetLastError();
Print(CloseCnt," Error modifying order : (", err , ") " + ErrorDescription(err));
if (err>0) CloseCnt++;
}
}
}
//+------------------------------------------------------------------+
//| 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;
if (type == OP_BUY)
{
myBid = MarketInfo(Symbol(),MODE_BID);
switch(TrailingStopType)
{
case 1: pt = myPoint*StopLoss;
if(myBid-os > pt) ModifyOrder(ticket,op,myBid-pt,tp, Aqua);
break;
case 2: pt = myPoint*TrailingStop;
if(myBid-op > pt && os < myBid - pt) ModifyOrder(ticket,op,myBid - pt,tp, Aqua);
break;
case 3: if (myBid - op > FirstMove * myPoint)
{
TS = op + FirstMove*myPoint - FirstStopLoss * myPoint;
if (os < TS)
{
ModifyOrder(ticket,op,TS,tp, Aqua);
}
}
if (myBid - op > SecondMove * myPoint)
{
TS = op + SecondMove*myPoint - SecondStopLoss * myPoint;
if (os < TS)
{
ModifyOrder(ticket,op,TS,tp, Aqua);
}
}
if (myBid - op > ThirdMove * myPoint)
{
TS = myBid - TrailingStop3*myPoint;
if (os < TS)
{
ModifyOrder(ticket,op,TS,tp, Aqua);
}
}
break;
}
return(0);
}
if (type == OP_SELL)
{
myAsk = MarketInfo(Symbol(),MODE_ASK);
switch(TrailingStopType)
{
case 1: pt = myPoint*StopLoss;
if(os - myAsk > pt) ModifyOrder(ticket,op,myAsk+pt,tp, Aqua);
break;
case 2: pt = myPoint*TrailingStop;
if(op - myAsk > pt && os > myAsk+pt) ModifyOrder(ticket,op,myAsk+pt,tp, Aqua);
break;
case 3: if (op - myAsk > FirstMove * myPoint)
{
TS = op - FirstMove * myPoint + FirstStopLoss * myPoint;
if (os > TS)
{
ModifyOrder(ticket,op,TS,tp, Aqua);
}
}
if (op - myAsk > SecondMove * myPoint)
{
TS = op - SecondMove * myPoint + SecondStopLoss * myPoint;
if (os > TS)
{
ModifyOrder(ticket,op,TS,tp, Aqua);
}
}
if (op - myAsk > ThirdMove * myPoint)
{
TS = myAsk + TrailingStop3 * myPoint;
if (os > TS)
{
ModifyOrder(ticket,op,TS,tp, Aqua);
}
}
break;
}
}
return(0);
}
//+------------------------------------------------------------------+
//| Get number of lots for this trade |
//+------------------------------------------------------------------+
double GetLots()
{
double lot;
if(UseMoneyManagement == true)
{
lot = LotsOptimized();
}
else
{
lot = Lots;
}
// Use at least 1 micro lot
if (AccountIsMicro == true)
{
if (lot < 0.01) lot = 0.01;
if (lot > MaxLots) lot = MaxLots * 100;
if (BrokerIsIBFX == true) lot = lot * 10;
return(lot);
}
// Use at least 1 mini lot
if(AccountIsMini == true)
{
if (lot < 0.1) lot = 0.1;
if (lot > MaxLots) lot = MaxLots;
if (BrokerIsIBFX == true) lot = lot * 10;
return(lot);
}
// Standard account
if( BrokerPermitsFractionalLots == false)
{
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;
// Use at least 1 mini lot
if(lot<0.1) lot=0.1;
if (lot > MaxLots) lot = MaxLots;
}else
{
if (lot < 1.0) lot = 1.0;
if (lot > MaxLots) lot = MaxLots;
}
return(lot);
}
// Return true if time is not in session for trading
bool CheckOutsideSession( int StartHour, int EndHour, int ct)
{
if(StartHour<=EndHour)
{
if(ct < StartHour || ct > EndHour) return(true) ;
}
else
{
if(ct > EndHour && ct < StartHour) return(true) ;
}
return(false) ;
}
bool CheckTradingTimes()
{
bool StopTrading;
int ct;
ct = Hour() * 100 + Minute();
StopTrading = true;
// Check trading Asian Market
if (TradeAsianMarket == 1)
{
StopTrading = CheckOutsideSession(AsianStart, AsianStop, ct);
}
if (StopTrading == true)
{
// Check trading European Market
if (TradeEuropeanMarket == 1)
{
StopTrading = CheckOutsideSession(EurStart, EurStop, ct);
}
}
if (StopTrading == true)
{
// Check trading New York Market
if (TradeNewYorkMarket == 1)
{
StopTrading = CheckOutsideSession(NYStart, NYStop, ct);
}
}
return(StopTrading);
}
double StopLong(double price,int stop, double mPoint)
{
if(stop==0)
return(0);
else
return(price-(stop*mPoint));
}
double StopShort(double price,int stop, double mPoint)
{
if(stop==0)
return(0);
else
return(price+(stop*mPoint));
}
double TakeLong(double price,int take, double mPoint)
{
if(take==0)
return(0);
else
return(price+(take*mPoint));
}
double TakeShort(double price,int take, double mPoint)
{
if(take==0)
return(0);
else
return(price-(take*mPoint));
}
double ValidStopLoss(string mySymbol, int type, double price, double SL, double mPoint)
{
double minstop;
if (SL < 0.1) return(SL);
minstop = MarketInfo(mySymbol,MODE_STOPLEVEL);
if (type == OP_BUY)
{
if((price - SL) < minstop*mPoint) SL = price - minstop*mPoint;
}
if (type == OP_SELL)
{
if((SL-price) < minstop*mPoint) SL = price + minstop*mPoint;
}
return(SL);
}
//+------------------------------------------------------------------+
//| CheckValidUserInputs |
//| Check if User Inputs are valid for ranges allowed |
//| return true if invalid input, false otherwise |
//| Also display an alert for invalid input |
//+------------------------------------------------------------------+
bool CheckValidUserInputs()
{
if (CheckTrailingStopType(TrailingStopType))
{
Alert("TrailingStopType( 1 to 3) You entered ",TrailingStopType);
return(true);
}
}
//+------------------------------------------------+
//| Check for valid TrailingStopType |
//| |
//| return true if invalid, false if OK |
//+------------------------------------------------+
bool CheckTrailingStopType(int stop_type)
{
if (stop_type < 0 ) return(true);
if (stop_type > 3) return(true);
return(false);
}
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=="NZDJPY") return(15);
if(mySymbol=="NZDUSD") return(16);
if(mySymbol=="USDCAD") return(17);
if(mySymbol=="USDCHF") return(18);
if(mySymbol=="USDJPY") return(19);
Comment("unexpected Symbol");
return(999);
}
//+------------------------------------------------------------------+
//| 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);
}
}
double SetPoint(string mySymbol)
{
double mPoint, myDigits;
myDigits = MarketInfo (mySymbol, MODE_DIGITS);
if (myDigits < 4)
mPoint = 0.01;
else
mPoint = 0.0001;
return(mPoint);
}
//+------------------------------------------------------------------+
Comments