This script is an automated trading system designed for the MetaTrader 4 platform. It functions as an "Expert Advisor" (EA), which means it monitors live market data and executes trades based on a specific set of logical rules without requiring manual intervention.
Core Strategy Logic
The primary goal of the script is to identify specific "dots" or signals generated by technical indicators to determine when to enter and exit the market. It relies on three distinct types of analysis to confirm its moves:
- Trend Identification: The system looks at overarching market trends using a "Mega Trend" and a "Trend Histogram." This helps the script understand if the broader market direction is currently moving up, down, or remains flat.
- Swing Analysis: It uses a specific "Swing_ZZ" indicator to identify potential turning points or momentum shifts in the price action.
- Triple Filter Integration: When enabled, the script requires all three of these components (Trend, Histogram, and Swing) to align before it considers a trade valid. This acts as a safety net to ensure that the bot doesn't enter a trade against the prevailing market flow.
Trade Execution Rules
The logic for opening and closing positions is governed by several key behaviors:
1. Entry Conditions
- Buy Signals: The script looks for specific patterns where momentum indicators align with an upward trend. If these conditions are met, it opens a "Buy" position.
- Sell Signals: Conversely, if the indicators confirm a downward trend, the script opens a "Sell" position.
- Signal Switching: To ensure smooth transitions, the bot is programmed to automatically close any existing opposing positions (e.g., closing all Sells when a Buy signal appears) before opening a new trade.
2. Trade Management & Safety
- Stop Loss and Take Profit: You can define specific price targets for profit and "safety nets" (Stop Loss) to limit potential losses automatically.
- Money Management: The script includes an intelligent calculation feature. Instead of always trading the same amount, it can calculate your position size based on your account balance, leverage, and a percentage of free margin that you choose to risk.
- Trade Delay: To avoid "fake-outs" (where a signal appears and disappears quickly), there is an option to wait for a candle to complete. This ensures the signal is "locked in" before any money is committed.
3. Dynamic Exit Logic Beyond simple profit targets, the script features a unique "Next Dot" closing logic. This allows the bot to exit a trade as soon as a counter-signal appears on the chart, allowing it to react quickly to sudden changes in market momentum.
Identification and Tracking
The script uses a unique identification system (Magic Number). It automatically assigns a specific ID based on the currency pair being traded and the timeframe you are viewing. This allows the bot to "remember" which trades it opened so that it doesn't interfere with other manual trades or other automated bots running on the same account.
//+------------------------------------------------------------------+
//| Join the dots-v1.2.1A.mq4 |
//| Copyright © 2008, LEGRUPO |
//| http://www.legrupo.com |
//| Version: 1.3 |
//| History: |
//| 1.0 => Release version to the public |
//| 1.1 => StopLoss bug fixed |
//| 1.2 => fixes on this releases: |
//| 1) More StopLoss bug fixed; |
//| 2) Now the EA close on the next oposite dot |
//| Make sure that CloseOrdersOnNextDot is true |
//|1.2.1 => Stoploss Bug fixed by Saidas |
//|1.2.1A=> Added Money Management and UseTripleIndicators filter |
//| by Azmel |
//|1.3 => Added TradeDelay switch. If enabled, it will wait for |
//| next candle and only trade if dot does not repaint. |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, LEGRUPO"
#property link "http://www.legrupo.com"
//+------------------------------------------------------------------+
//| EX4 imports |
//+------------------------------------------------------------------+
#include <stdlib.mqh>
int MagicNumber = 0;
int ticket = 0;
double Price[2];
int giSlippage;
extern int ExpertID = 994488;
extern int TakeProfit = 300;
extern double StopLoss = 50;
extern double LotSize = 0.1;
extern bool useTakeProfit = true;
extern bool useStopLoss = true;
extern bool CloseOrdersOnNextDot = true;
extern bool UseTripleIndicators = true;
extern bool TradeDelay = true;
extern bool MoneyManagement = false;
extern int PercentageToTrade = 80;
extern int AccountType = 1;
extern int Leverage = 100;
extern int Slippage = 5;
color ExitLongColor = CLR_NONE;
color ExitShortColor = CLR_NONE;
extern string BuyComment = "Join the Dots BUY";
extern string SellComment = "Join the Dots SELL";
double PricePerPip;
double DecimalCorrection;
double DecimalPlaces;
double TP;
bool BuySignal;
bool SellSignal;
bool CurrentBuyDot;
bool CurrentSellDot;
bool PreviousBuyDot;
bool PreviousSellDot;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//--- by Saidas
double SL = StopLoss*Point;//by Saidas
//---- MoneyManagement feature by Azmel
if (AccountType==0)
{
PricePerPip = 10;
DecimalCorrection = 0.5;
DecimalPlaces = 0;
}
if (AccountType==1)
{
PricePerPip = 10;
DecimalCorrection = 0.05;
DecimalPlaces = 1;
}
if (AccountType==2)
{
PricePerPip = 10;
DecimalCorrection = 0.005;
DecimalPlaces = 2;
}
if (AccountType==3)
{
PricePerPip = 1;
DecimalCorrection = 0.005;
DecimalPlaces = 2;
}
if (MoneyManagement)
{
LotSize=NormalizeDouble(((AccountFreeMargin()*PercentageToTrade*Leverage)/
(Ask*PricePerPip*1000000))-DecimalCorrection,DecimalPlaces);
}
//---- end of MoneyManagement feature.
MagicNumber = MakeMagicNumber( ExpertID, false );
double MegaTrend_up = iCustom(NULL, 0, "Mega trend",144,3,0,0,0);
double MegaTrend_down = iCustom(NULL, 0, "Mega trend",144,3,0,1,0);
double MegaTrend_buffer = iCustom(NULL, 0, "Mega trend",144,3,0,2,0);
string megatrend_direction, trendhisto_direction, swingzz_direction;
//Comment("MegaTrend_up: ",MegaTrend_up,"\nMegaTrend_down: ", MegaTrend_down, "\nMegaTrend_buffer: ",MegaTrend_buffer);
if (MegaTrend_buffer == MegaTrend_up) {
//Comment("Megatrend up");
megatrend_direction = "up";
} else if (MegaTrend_buffer == MegaTrend_down) {
//Comment("Megatrend down");
megatrend_direction = "down";
} else {
//Comment("No trend from MegaTrend");
megatrend_direction = "flat";
}
double TrendHisto_up = iCustom(NULL, 0, "Trend Histo",1500,1,0);
double TrendHisto_down = iCustom(NULL, 0, "Trend Histo",1500,2,0);
double TrendHisto_buffer = iCustom(NULL, 0, "Trend Histo",1500,0,0);
//Comment("TrendHisto_up: ",TrendHisto_up,"\nTrendHisto_down: ", TrendHisto_down, "\nTrendHisto_buffer: ",TrendHisto_buffer);
if (TrendHisto_buffer == TrendHisto_up) {
//Comment("TrendHisto up");
trendhisto_direction = "up";
} else if (TrendHisto_buffer == TrendHisto_down) {
//Comment("TrendHisto down");
trendhisto_direction = "down";
} else {
//Comment("No trend from TrendHisto");
trendhisto_direction = "flat";
}
double swingzz_up = iCustom(NULL, 0, "Swing_ZZ",2,1,0);
double swingzz_down = iCustom(NULL, 0, "Swing_ZZ",2,2,0);
double swingzz_buffer = iCustom(NULL, 0, "Swing_ZZ",2,0,0);
//Comment("swingzz_up: ",swingzz_up,"\nswingzz_down: ", swingzz_down, "\nswingzz_buffer: ",swingzz_buffer);
//---TradeDelay feature by Azmel.
//---UseTripleIndicators feature by Azmel.
if (TradeDelay)
{
if (UseTripleIndicators)
{
if (swingzz_down != 0 && megatrend_direction == "up" && trendhisto_direction == "up")
{
CurrentBuyDot=true;
}
else
{
CurrentBuyDot=false;
}
if (swingzz_up != 0 && megatrend_direction == "down" && trendhisto_direction == "down")
{
CurrentSellDot = true;
}
else
{
CurrentSellDot = false;
}
if (PreviousSellDot==true && CurrentSellDot==false)
{
SellSignal = true;
}
else
{
SellSignal = false;
}
if (PreviousBuyDot==true && CurrentBuyDot==false)
{
BuySignal = true;
}
else
{
BuySignal = false;
}
PreviousSellDot=CurrentSellDot;
PreviousBuyDot =CurrentBuyDot;
}
else
{
if (swingzz_down != 0)
{
CurrentBuyDot=true;
}
else
{
CurrentBuyDot=false;
}
if (swingzz_up != 0)
{
CurrentSellDot = true;
}
else
{
CurrentSellDot = false;
}
if (PreviousSellDot==true && CurrentSellDot==false)
{
SellSignal = true;
}
else
{
SellSignal = false;
}
if (PreviousBuyDot==true && CurrentBuyDot==false)
{
BuySignal = true;
}
else
{
BuySignal = false;
}
PreviousSellDot=CurrentSellDot;
PreviousBuyDot =CurrentBuyDot;
}
}
else
{
if (UseTripleIndicators)
{
if (swingzz_down != 0 && megatrend_direction == "up" && trendhisto_direction == "up")
{
BuySignal = true;
}
else
{
BuySignal = false;
}
if (swingzz_up != 0 && megatrend_direction == "down" && trendhisto_direction == "down")
{
SellSignal = true;
}
else
{
SellSignal = false;
}
}
else
{
if (swingzz_down != 0)
{
BuySignal = true;
}
else
{
BuySignal = false;
}
if (swingzz_up != 0)
{
SellSignal = true;
}
else
{
SellSignal = false;
}
}
}
//--- end of UseTripleIndicators feature.
//--- end of TradeDelay feature.
if (BuySignal) {
CloseShorts(MagicNumber);
//Alert("BUY");
if (CountLongs(MagicNumber)== 0 && CountShorts(MagicNumber)== 0) {
if (useStopLoss) {
SL = Bid-SL;//by Saidas
} else {
SL = 0;//by Saidas
}
if (useTakeProfit)
{
TP = Ask+TakeProfit*Point;
}
else
{
TP = 0;
}
ticket=OrderSend(Symbol(),OP_BUY,LotSize,Ask,Slippage,SL,TP,BuyComment,MagicNumber,0,CLR_NONE);//by Saidas
if(ticket<0)
{
Alert("OrderSend failed with error #",ErrorDescription(GetLastError()));
return(0);
}
}
}
if (SellSignal) {
CloseLongs(MagicNumber);
//Alert("SELL");
if (CountLongs(MagicNumber)== 0 && CountShorts(MagicNumber)== 0) {
if (useStopLoss) {
SL = Ask+SL;//by Saidas
} else {
SL = 0;//by Saidas
}
if (useTakeProfit)
{
TP = Bid-TakeProfit*Point;
}
else
{
TP = 0;
}
ticket=OrderSend(Symbol(),OP_SELL,LotSize,Bid,Slippage,SL,TP,SellComment,MagicNumber,0,CLR_NONE);//by Saidas
if(ticket<0)
{
Alert("OrderSend failed with error #",ErrorDescription(GetLastError()));
return(0);
}
}
}
if (CloseOrdersOnNextDot) {
if (swingzz_up != 0) {
CloseLongs(MagicNumber);
}
if (swingzz_down != 0) {
CloseShorts(MagicNumber);
}
}
//----
return(0);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Make Magic Number |
//+------------------------------------------------------------------+
int MakeMagicNumber( int ExpertID, bool TimeSpecific )
{
int SymbolCode = 0;
int PeriodCode = 0;
int MagicNumber = 0;
//---- Symbol Code
if( Symbol() == "AUDCAD" || Symbol() == "AUDCADm" ) { SymbolCode = 1000; }
else if( Symbol() == "AUDJPY" || Symbol() == "AUDJPYm" ) { SymbolCode = 2000; }
else if( Symbol() == "AUDNZD" || Symbol() == "AUDNZDm" ) { SymbolCode = 3000; }
else if( Symbol() == "AUDUSD" || Symbol() == "AUDUSDm" ) { SymbolCode = 4000; }
else if( Symbol() == "CHFJPY" || Symbol() == "CHFJPYm" ) { SymbolCode = 5000; }
else if( Symbol() == "EURAUD" || Symbol() == "EURAUDm" ) { SymbolCode = 6000; }
else if( Symbol() == "EURCAD" || Symbol() == "EURCADm" ) { SymbolCode = 7000; }
else if( Symbol() == "EURCHF" || Symbol() == "EURCHFm" ) { SymbolCode = 8000; }
else if( Symbol() == "EURGBP" || Symbol() == "EURGBPm" ) { SymbolCode = 9000; }
else if( Symbol() == "EURJPY" || Symbol() == "EURJPYm" ) { SymbolCode = 1000; }
else if( Symbol() == "EURUSD" || Symbol() == "EURUSDm" ) { SymbolCode = 1100; }
else if( Symbol() == "GBPCHF" || Symbol() == "GBPCHFm" ) { SymbolCode = 1200; }
else if( Symbol() == "GBPJPY" || Symbol() == "GBPJPYm" ) { SymbolCode = 1300; }
else if( Symbol() == "GBPUSD" || Symbol() == "GBPUSDm" ) { SymbolCode = 1400; }
else if( Symbol() == "NZDJPY" || Symbol() == "NZDJPYm" ) { SymbolCode = 1500; }
else if( Symbol() == "NZDUSD" || Symbol() == "NZDUSDm" ) { SymbolCode = 1600; }
else if( Symbol() == "USDCAD" || Symbol() == "USDCADm" ) { SymbolCode = 1700; }
else if( Symbol() == "USDCHF" || Symbol() == "USDCHFm" ) { SymbolCode = 1800; }
else if( Symbol() == "USDJPY" || Symbol() == "USDJPYm" ) { SymbolCode = 1900; }
//---- Period Code
if( TimeSpecific )
{
if( Period() == 1 ) { PeriodCode = 10; }
else if( Period() == 5 ) { PeriodCode = 20; }
else if( Period() == 15 ) { PeriodCode = 30; }
else if( Period() == 30 ) { PeriodCode = 40; }
else if( Period() == 60 ) { PeriodCode = 50; }
else if( Period() == 240 ) { PeriodCode = 60; }
else if( Period() == 1440 ) { PeriodCode = 70; }
else if( Period() == 10080 ){ PeriodCode = 80; }
}
else
{
PeriodCode = 0;
}
//---- Calculate MagicNumber
MagicNumber = ExpertID+SymbolCode+PeriodCode;
return(MagicNumber);
}
//+------------------------------------------------------------------+
//| Calculate concurrent Long position |
//+------------------------------------------------------------------+
int CountLongs(int MagicNumber)
{
int count=0;
int trade;
int trades=OrdersTotal();
for(trade=0;trade<trades;trade++)
{
OrderSelect(trade,SELECT_BY_POS,MODE_TRADES);
if( OrderSymbol()!=Symbol() || OrderMagicNumber() != MagicNumber )
continue;
if(OrderType()==OP_BUY)
count++;
}//for
return(count);
}
//+------------------------------------------------------------------+
//| Calculate concurrent short position |
//+------------------------------------------------------------------+
int CountShorts(int MagicNumber)
{
int count=0;
int trade;
int trades=OrdersTotal();
for(trade=0;trade<trades;trade++)
{
OrderSelect(trade,SELECT_BY_POS,MODE_TRADES);
if(OrderSymbol()!=Symbol() || OrderMagicNumber() != MagicNumber )
continue;
if(OrderType()==OP_SELL)
count++;
}//for
return(count);
}
//+------------------------------------------------------------------+
//| Close Long Position |
//+------------------------------------------------------------------+
void CloseLongs(int MagicNumber)
{
int i = OrdersTotal();
while( CountLongs(MagicNumber) != 0 && i >= 0 )
{
OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
if( OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber )
{
i--;
continue;
}
else if(OrderType()==OP_BUY || OrderType()== OP_BUYLIMIT)
{
OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,ExitLongColor);
i--;
}
}
}
//+------------------------------------------------------------------+
//| Close Short Position |
//+------------------------------------------------------------------+
void CloseShorts(int MagicNumber)
{
int i = OrdersTotal();
while( CountShorts(MagicNumber) != 0 && i >= 0 )
{
OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
if( OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber)
{
i--;
continue;
}
else if(OrderType()== OP_SELL || OrderType()==OP_SELLLIMIT )
{
OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,ExitShortColor);
}
}
}
Comments