Here's a breakdown of the MQL4 script's logic in plain language:
This script is designed to automate trading in the MetaTrader 4 platform, using a strategy based on Donchian channels. Think of Donchian channels as lines on a chart that show the highest high and lowest low prices over a certain period. The script attempts to identify potential buying and selling opportunities based on these channels.
Here's how it works step by step:
-
Initialization: When the script starts, it sets up some initial parameters, such as the size of the trades (Lots), acceptable price slippage (Slippage), a magic number (Magic) to identify its own trades, and the periods for calculating the Donchian channels (LngPeriod, ShtPeriod).
-
Checking Existing Trades: The script first checks if there are any open trades placed by itself. It loops through all open orders and identifies the one with the specified Magic Number and currency pair.
-
Managing Stop Losses: If the script finds an open buy or sell order, it will check if the current stop-loss is less secure than it could be based on the recent price action. If so, the stop-loss is updated to a more secure price. Additionally, pending orders that have been in place for over three and a half days are cancelled.
-
Entry Signals:
-
Long Entry: If the current asking price (the price you'd buy at) reaches the upper Donchian Channel calculated using the LngPeriod and the ask price is higher than the moving average of the instrument, the script will place a buy order at the current ask price, as well as 3 other buy stop pending orders at set distances above it.
-
Short Entry: If the current bid price (the price you'd sell at) reaches the lower Donchian Channel calculated using the LngPeriod and the bid price is lower than the moving average of the instrument, the script will place a sell order at the current bid price, as well as 3 other sell stop pending orders at set distances below it.
-
-
Preventing Frequent Trading: The script only allows itself to execute a new trade once every 24 hours. This is to prevent the system from making multiple trades in quick succession.
-
Summary Report: It also calculates and displays the total profit or loss from all trades executed by the script with the given "magic number," as well as the number of trades that were made.
In essence, this script is a tool designed to automate a Donchian channel breakout trading strategy, attempting to buy when the price breaks above a certain high and sell when it breaks below a certain low, while also managing risk through stop-loss orders.
//+------------------------------------------------------------------+
//| Donchain counter-channel system.mq4 |
//| Copyright © 2005, MetaQuotes Software Corp. |
//| |
//+------------------------------------------------------------------+
#property copyright "by djindyfx"
#property link ""
extern double Lots =1.0;
extern int Slippage=3;
extern int Magic =20051006;
// Optimalization parameters:
extern int LngPeriod=20;
extern int ShtPeriod=10;
extern int Entry_Stop=100;
//extern int TimeFrame =PERIOD_D1; // Time frame of the Donchain indicator.
// Privete variables
datetime last_trade_time; // in order to execute maximum only one trade a day.
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ReportStrategy(int Magic)
{
int totalorders=HistoryTotal();
double StrategyProfit=0.0;
int StrategyOrders=0;
for(int j=0; j<totalorders;j++)
{ if(OrderSelect(j, SELECT_BY_POS, MODE_HISTORY) && (OrderMagicNumber()==Magic))
{
if((OrderType()==OP_BUY) || (OrderType()==OP_SELL))
{
StrategyOrders++;
StrategyProfit+=OrderProfit();
}
}
}
totalorders=OrdersTotal();
for(j=0; j<totalorders;j++)
{
if(OrderSelect(j, SELECT_BY_POS, MODE_TRADES) && (OrderMagicNumber()==Magic))
{
if((OrderType()==OP_BUY) ||(OrderType()==OP_SELL))
{
StrategyOrders++;
StrategyProfit+=OrderProfit();
}
}
}
Comment("Executed ", StrategyOrders, " trades with ", StrategyProfit," of profit");
return;
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
double stop_short;
double stop_long;
double ELong;
double EShort;
//----
bool entry_short;
bool entry_long;
bool are_we_long =false;
bool are_we_short =false;
bool are_we_PendShort = false;
bool are_we_PendLong = false;
int orders_in_trade=0;
int active_order_ticket;
//----
//Channels for Entry and Stop
// Entry Channel
ELong=High[iHighest(NULL,0,MODE_HIGH,LngPeriod,0)];
EShort=Low[iLowest(NULL,0,MODE_LOW,LngPeriod,0)];
// Stop Channel
stop_long=Low[iLowest(NULL,0,MODE_LOW,ShtPeriod,0)];
stop_short=High[iHighest(NULL,0,MODE_HIGH,ShtPeriod,0)];
ReportStrategy(Magic);
// Check current trades:
int TotalOrders=OrdersTotal();
for(int j=0;j<TotalOrders;j++)
{
OrderSelect(j, SELECT_BY_POS, MODE_TRADES);
if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
{
are_we_long =are_we_long || OrderType()==OP_BUY;
are_we_short=are_we_short || OrderType()==OP_SELL;
are_we_PendShort=are_we_PendShort || OrderType()==OP_SELLSTOP;
are_we_PendLong=are_we_PendLong || OrderType()==OP_BUYSTOP;
orders_in_trade++;
active_order_ticket=OrderTicket();
/*
// Lower channel:
stop_long=Low[iLowest(NULL,0,MODE_LOW,ShtPeriod,0)];
// Upper channel:
stop_short=High[iHighest(NULL,0,MODE_HIGH,ShtPeriod,0)];
*/
if(are_we_long && OrderType()==OP_BUY)
{
// We have long position. Check stop loss:
OrderSelect(active_order_ticket, SELECT_BY_TICKET);
if(OrderStopLoss() < stop_long)
OrderModify(active_order_ticket,OrderOpenPrice(),stop_long,OrderTakeProfit(),0,Blue);
//----
}
if(are_we_short && OrderType()==OP_SELL)
{
// We have long position. Check stop loss:
OrderSelect(active_order_ticket, SELECT_BY_TICKET);
if(OrderStopLoss() > stop_short)
OrderModify(active_order_ticket,OrderOpenPrice(),stop_short,OrderTakeProfit(),0,Blue);
//----
}
if(are_we_PendLong && OrderType() ==OP_BUYSTOP)
{
OrderSelect(active_order_ticket, SELECT_BY_TICKET);
if((TimeCurrent()- OrderOpenTime())>360*60*60)
OrderDelete(active_order_ticket);
}
if(are_we_PendShort && OrderType()==OP_SELLSTOP)
{
OrderSelect(active_order_ticket, SELECT_BY_TICKET);
if((TimeCurrent() -OrderOpenTime())>360*60*60)
OrderDelete(active_order_ticket);
}
} //not true
}// end for
if (orders_in_trade > 0)
return(0);
//Do not execute new trade for a next 24 hours.
if((TimeCurrent() - last_trade_time)<24*60*60) return(0);
double y = iMA(NULL,0,150,0,MODE_SMA,PRICE_CLOSE,0);
/*
// Upper channel:
ELong=High[iHighest(NULL,0,MODE_HIGH,LngPeriod,0)];
// lower channel:
EShort=Low[iLowest(NULL,0,MODE_LOW,LngPeriod,0)];
*/
double ELong1=ELong+50*Point;
double ELong2=ELong+100*Point;
double ELong3=ELong+150*Point;
double EShort1=EShort-50*Point;
double EShort2=EShort-100*Point;
double EShort3=EShort-150*Point;
//if(entry_long && entry_short)
//Alert("Short and long entry. Probably one of the is wrong.");
if (ELong==Ask && Ask>y)
{
OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage,stop_long/*Bid-Entry_Stop*Point*/,0, "", Magic,0, FireBrick);
Sleep(2000);
OrderSend(Symbol(), OP_BUYSTOP, Lots, ELong1, Slippage,stop_long/*Bid-Entry_Stop*Point*/,0, "", Magic,0, FireBrick);
Sleep(2000);
OrderSend(Symbol(), OP_BUYSTOP, Lots, ELong2, Slippage,stop_long /*Bid-Entry_Stop*Point*/,0, "", Magic,0, FireBrick);
Sleep(2000);
OrderSend(Symbol(), OP_BUYSTOP, Lots, ELong3, Slippage,stop_long /*Bid-Entry_Stop*Point*/,0, "", Magic,0, FireBrick);
last_trade_time=TimeCurrent();
}
if(EShort==Bid && Bid<y)
{
OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,stop_short/*Ask+Entry_Stop*Point*/,0,"",Magic,0,FireBrick);
Sleep(2000);
OrderSend(Symbol(),OP_SELLSTOP,Lots,EShort1,Slippage,stop_short/*Ask+Entry_Stop*Point*/,0,"",Magic,0,FireBrick);
Sleep(2000);
OrderSend(Symbol(),OP_SELLSTOP,Lots,EShort2,Slippage,stop_short/*Ask+Entry_Stop*Point*/,0,"",Magic,0,FireBrick);
Sleep(2000);
OrderSend(Symbol(),OP_SELLSTOP,Lots,EShort3,Slippage,stop_short/*Ask+Entry_Stop*Point*/,0,"",Magic,0,FireBrick);
last_trade_time=TimeCurrent();
}
//----
return(0);
}
//+------------------------------------------------------------------+
Comments