type=EXPERT_ADVISOR
#header#
#property copyright "#copyright#"
#property link "#link#"
#extern_variables#
// constant "off market"
#define OP_BALANCE 6
// settings for trading
extern int TradeDay = 0;
extern bool ReversDay = false;
// trading system reverse
extern bool ReversTradeSignal = false;
// trading frequency settings
extern bool TradeSignalEveryTick = false;
extern int TradeSignalBarPeriod = 0;
// order modification settings
extern bool ModifyMarketOrderEveryTick = false;
extern bool ModifyPendingEveryTick = false;
extern int ModifyMarketBarPeriod = 0;
extern int ModifyPendingBarPeriod = 0;
//
extern int Slippage = 3; // slippage
extern int ExpertMagicNumber = 0; // specify the necessary number
double Tickets[][9];// array to store information about "friendly" orders:
// Tickets[][0] - ticket number
// Tickets[][1] - order type
// Tickets[][2] - lots
// Tickets[][3] - open price
// Tickets[][4] - Stop Loss
// Tickets[][5] - TakeProfit
// Tickets[][6] - MagicNumber
// Tickets[][7] - expiration time
// Tickets[][8] - open time
//
double newSL_and_TP[][5];// array to store the new values of SL and TP
// newSL_and_TP[][0] - ticket number to control
// newSL_and_TP[][1] - new value of SL
// newSL_and_TP[][2] - new value of TP
// newSL_and_TP[][3] - new open price (for pending orders)
// newSL_and_TP[][4] - 0 for open orders and 1 for pending orders)
string CommentsTicket[100][2]; //array of symbols and comments on orders, 100 lines would be enough
// CommentsTicket[][0] - symbol name
// CommentsTicket[][1] - comment on the order
//+-----------------------------------------------------------------------------+
//| if the period is not specified correctly, it returns the current period |
//+-----------------------------------------------------------------------------+
int getCorrectTimeFrame(int period)
{
int res=period;
//----
switch (period)
{
case PERIOD_D1: break; // permitted timeframe, do nothing
case PERIOD_H4: break; // permitted timeframe, do nothing
case PERIOD_H1: break; // permitted timeframe, do nothing
case PERIOD_M30: break; // permitted timeframe, do nothing
case PERIOD_M15: break; // permitted timeframe, do nothing
case PERIOD_M5: break; // permitted timeframe, do nothing
case PERIOD_M1: break; // permitted timeframe, do nothing
default: res=Period(); // wrong timeframe, set by default
}
//----
return(res);
}
//+------------------------------------------------------------------+
//| it produces a message about EA settings |
//+------------------------------------------------------------------+
void StartMessage()
{
int i=0;
string currString="";
string array[3];
//----
array[0]=StringConcatenate("Expert Advisor ",WindowExpertName()," has the following settings:");
if (TradeSignalEveryTick)
array[1]="1)trade signals are taken at every tick; ";
else
array[1]=StringConcatenate("1)trade signals are taken at every bar with the period of ",TradeSignalBarPeriod," minutes;");
if (TradeDay==0) // trade day is not specified
array[2]="2)everyday's trading is allowed; ";
else
{
if (ReversDay) // trading isn't allowed on the given day
array[2]=StringConcatenate("2)trading is allowed on all days except day number ",TradeDay);
else // trading is allowed only on the given day
array[2]=StringConcatenate("2)trading is allowed only on day number ",TradeDay);
}
for ( i=0;i<3;i++) currString=StringConcatenate(currString,"\n",array[i]);
Comment(currString);
for (i=2;i>=0;i--) Print(array[i]);
//----
}
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
TradeSignalBarPeriod=getCorrectTimeFrame(TradeSignalBarPeriod);
StartMessage(); // remind the EA settings
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| trade signals producing function |
//+------------------------------------------------------------------+
int yourFunction(int workPeriod)
{
int res=OP_BALANCE;
//----
// here there must be your code for producing trade signals considering timeframe workPeriod)
//----
return (res);
}
//+------------------------------------------------------------------+
//| receive a trade signal |
//+------------------------------------------------------------------+
// tradeDay - day of the week we trade on, if it is equal to zero, we trade every day
//
// useReversTradeDay - if it is equal to 'true', then trading days are considered as non-trading days
//
// everyTick - if it is equal to 'true', then the function calculates a signal at every tick
//
// period - if everyTick==false, then it is calculated as soon as a new bar with this period appears
int getTradeSignal(int tradeDay, // usually equal to 0
bool useReversTradeDay,// usually equal to 'false'
bool everyTick, // signal is calculated at every tick
int period // period of work for indicators and signals
)
{
int signal=OP_BALANCE;
//----
if (tradeDay!=0) // days of the week will be considered
{
// day we don't trade on
if (useReversTradeDay && tradeDay==DayOfWeek()) return(signal);
// trade on all days except the day equal to 'tradeDay'
if (!useReversTradeDay && tradeDay!=DayOfWeek()) return(signal);
}
if (!everyTick) // if we don't take trade signals at every tick
{ // and have no new bar at the timeframe of 'period' minutes
if (!isNewBar(period)) return(signal); // then exit with an empty signal
}
// Fill yourFunction() with your code/algorithm
signal=yourFunction(period);
//----
return(signal);
}
//+-----------------------------------------------------------------------+
//| It returns the sign of appearance of a new bar with the given period |
//+-----------------------------------------------------------------------+
bool isNewBar(int timeFrame)
{
bool res=false;
// array contains the open time of the current (zero) bar
// on 7 (Seven) timeframes
static datetime _sTime[7];
int i=6;
switch (timeFrame)
{
case 1 : i=0; break;
case 5 : i=2; break;
case 15 : i=3; break;
case 30 : i=4; break;
case 60 : i=5; break;
case 240: break;
case 1440:break;
default: timeFrame = 1440;
}
//----
if (_sTime[i]==0 || _sTime[i]!=iTime(Symbol(),timeFrame,0))
{
_sTime[i] = iTime(Symbol(),timeFrame,0);
res=true;
}
//----
return(res);
}
//+----------------------------------------------------------------------+
//| It returns 'true', if a Global Variable with this ticket is available|
//+----------------------------------------------------------------------+
bool isOurOrder(int ticket)
{
bool res=false;
// we don't use global variables in the test mode!
if (IsTesting()) return(true);// immediately return a positive result
int temp;
//----
for (int i=0;i<5;i++)
{
if (GlobalVariableCheck(WindowExpertName()+"_ticket_"+i))
{// this global variable is available
temp=GlobalVariableGet(WindowExpertName()+"_ticket_"+i);
if (temp==ticket)
{ // found a GV with the value equal to 'ticket'
res=true; // it means that the order is "friendly"
break;
}
}
}
//----
return(res);
}
//+------------------------------------------------------------------+
//| It prepares an array of "friendly" orders |
//+------------------------------------------------------------------+
void PrepareTickets(double & arrayTickets[][9], string & comm[][2],int MN)
{
int count=0; // counter of filling
// let's make the array size large enough in order not to allocate memory every time
ArrayResize(arrayTickets,20);
//----
int total=OrdersTotal();
for (int i=0;iOP_SELL) newOpen=getNewOpenPricePending(type,lots,openPrice,oldSL,oldTP);
if (newSL>0 || newTP>0 || newOpen>0)
{
sizeSL_TP=ArrayRange(arraySL_TP,0);
arraySL_TP[sizeSL_TP][0] = arrayTickets[i][0]; // ticket
if (newSL>0) arraySL_TP[sizeSL_TP][1] = newSL; // new level of SL
else arraySL_TP[sizeSL_TP][1] = arrayTickets[i][4];
if (newTP>0) arraySL_TP[sizeSL_TP][2] = newTP; // new level of TP
else arraySL_TP[sizeSL_TP][2] = arrayTickets[i][5];
if (newOpen>0)arraySL_TP[sizeSL_TP][3] = newOpen; // new open price
else arraySL_TP[sizeSL_TP][3] = arrayTickets[i][3];
if (type>OP_SELL) arraySL_TP[sizeSL_TP][4]=1; // market order
else arraySL_TP[sizeSL_TP][4]=0; // market order
}
}
//----
return;
}
//+------------------------------------------------------------------+
//| It calculates the data for opening a new order |
//+------------------------------------------------------------------+
void CalculateNewMarketValues(int trSignal,
int & marketType,
double & marketLots,
double & marketSL,
double & marketTP,
string & marketcomment
)
{
// if there is no trade signal, then exit
if (trSignal==OP_BALANCE) return;
marketType =-1; // this means that we won't open anything
marketLots = 0;
marketSL = 0;
marketTP = 0;
marketcomment = "";
//----
// insert your code to calculate all parameters
//----
return;
}
//+------------------------------------------------------------------+
//| It calculates the data for placing a pending order |
//+------------------------------------------------------------------+
void CalculateNewPendingValues(int trSignal,
int & pendingType,
double & pendingOpenPrice,
double & pendingLots,
double & pendingSL,
double & pendingTP,
string & pendingComment)
{
// if there is no trade signal, then exit
if (trSignal==OP_BALANCE) return;
pendingType = -1;
pendingOpenPrice = 0;
pendingLots = 0;
pendingSL = 0;
pendingTP = 0;
pendingComment = 0;
//----
//insert your code to calculate all parameters
//----
return;
}
//+------------------------------------------------------------------+
//| Modification of market orders |
//+------------------------------------------------------------------+
void ModifyMarkets(bool Revers,
bool ModifyEveryTick,
int ModifyBarPeriod,
double newSL_and_TP[][])
{
int i,type,ticket,size=ArrayRange(newSL_and_TP,0);
if (size==0) return; // nothing to modify, exit
bool res;
//----
if (!ModifyEveryTick )// if every-tick modification is prohibited
{
if (!isNewBar(ModifyBarPeriod)) return; // no new bar appears
}
if (!Revers) // direct order of working
{
for (i=0;iOP_SELL) continue;
if (Revers) // reverse the type of a market order
{
if (type==OP_BUY) type=OP_SELL; else type=OP_BUY;
}
// here we will decide the fate of each open order
// whether to keep it open or to add it to the array of orders to be closed
if (type==OP_BUY)
{
//
// code that allows us to retain buying
// as an example
if (signal==OP_BUY) continue;
}
if (type==OP_SELL)
{
//
// code that allows us to retain selling
// as an example
if (signal==OP_SELL) continue;
}
closeSize=ArrayRange(ticketsClose,0);
ArrayResize(ticketsClose,closeSize+1);
ArrayResize(lots,closeSize+1);
ticketsClose[closeSize][0] = arrayTickets[i][0]; // ticket #
ticketsClose[closeSize][1] = arrayTickets[i][1]; // order type
// here we will specify the amount of lots to be closed
lots[closeSize] = arrayTickets[i][2]; // volume to be closed
// you can close them partly, then you should rewrite the upper line
}
//----
return;
}
//+------------------------------------------------------------------+
//| prepare an array of tickets for deletion of pending orders |
//+------------------------------------------------------------------+
void PrepareTicketsToDelete(int signal, bool Revers, int & ticketsDelete[],double arrayTickets[][9])
{
int size=ArrayRange(arrayTickets,0);
//----
if (size==0) return;
ArrayResize(ticketsDelete,0);
int i,type,ticket,deleteSize;
for (i=0;i