//+------------------------------------------------------------------+
//| Simple S&R.mq4 |
//| Copyright © 2008, LEGRUPO |
//| http://www.legrupo.com |
//| Version: 1.3 |
//| History: |
//| 1.0 => Release version to the public |
//| 1.1 => fixes on this releases: |
//| 1) StopLoss bug fixed; |
//| 2) Now the EA close the open and pending orders on the |
//| end of the day, you just need to see when day ends |
//| on your broker. InterbankFX is GMT, so it is 0 on them |
//| 3) You don't need to manage the MagicNumber anymore |
//| 1.2 => Added Money Management feature; |
//| 1.3 => Added HMA filter to stop big drawndown |
//| 1.4 |
//| 1.5 => Tinashe B Chipomho (tinashechipomho@gmail.com) |
//| Refactored Indicator code, added first strategy (hedging) |
//| Code is broken down into reusable units |
//| Fixed issues with 1.4 |
//| Controls orders from previous day |
//| |
//| |
//| |
//| |
//| |
//| |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, LEGRUPO"
#property link "http://www.legrupo.com"
#include <WinUser32.mqh>
#include <stderror.mqh>
#include <stdlib.mqh>
#include <Logging.mqh>
#include <MoneyManagement.mqh>
#include <Trading.mqh>
#include <FiboPivotPoints.mqh>
//define various trading strategies
//these strategies are there to minimize the drawdown.
//various suggestions have been put forward by the team.
#define STRATEGY_NONE 0
#define STRATEGY_HEDGING 1
#define STRATEGY_MEGA_TREND 2
extern string _ = "Risk/Profit Management ";
extern double Trading.Risk = 10.0; // risk in percentage % (10% of risk in this case)
extern double Trading.LotSize = 0.1;
extern int Trading.Slippage = 3;
extern int Trading.StopLoss = 100;
extern int Trading.FlexPips = 8; //if the price reach within this range of the prescribed take profit
//we can close the position.
extern string __ = "Money Management ";
extern bool MoneyManagement.Enabled = false;
extern string ___ = "Account Information ";
extern bool Account.Type.IsMicro = false;
extern string ____ = "Trailing Stop Management ";
extern int TrailingStopMode = 0;
extern bool TimeSpecific = false;
extern string _____ = "Strategy Types: Which strategy to do you want to use? 0 means none ";
extern int StrategyIndex = 1;
extern string ______ = "Simple Hedging Strategy: Adjust if your strategy index is 1";
extern double Strategy.Hedging.LotSize = 0;
extern double Strategy.Hedging.TrailingStop = 15;
extern double Strategy.Hedging.Slippage = 1;
extern double Strategy.Hedging.TrailingMode = 1;
/*
extern string _HMA = " HMA Indicator Settings ";
string HMA_Name = "Mega trend";
extern int HMA_Period = 33;
extern int HMA_Mode = 3;
*/
int ExpertID=1844;
int MagicNumber = 1844; //magic number
string BASEFILENAME = "Fxi_Alpha_EA";
string BuyComment = "Simple R & S BUY";
string SellComment = "Simple R & S SELL";
bool StartOfDayProcessed = false;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init(){
//create magic number
MagicNumber = MakeMagicNumber();
//set up logging filename and logging level.
SetLogFilename(BASEFILENAME+"."+Symbol()+".log");
SetLogLevel(LOG_DEBUG); //we need to use the debug for now
//when its production ready we swicth to LOG_ERROR or LOG_FATAL
LogDebug("Starting "+BASEFILENAME);
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit(){
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start(){
//----
double prices[];
GetCurrentFiboPivotPoints(prices);
double pivot = prices[FIBO_LEVEL_PIVOT];
double r3 = prices[FIBO_LEVEL_R3];
double r2 = prices[FIBO_LEVEL_R2];
double r1 = prices[FIBO_LEVEL_R1];
double s1 = prices[FIBO_LEVEL_S1];
double s2 = prices[FIBO_LEVEL_S2];
double s3 = prices[FIBO_LEVEL_S3];
if (prices[0]==0.0){
}
if (prices[0]==0.0){
LogWarn("There was an error getting the Pivot prices.");
return (-1);
}
if(MoneyManagement.Enabled) {
Trading.LotSize = DefineLotSize(Trading.Risk,Trading.LotSize,Account.Type.IsMicro); //Adjust the lot size total
}
//Print("Pivot="+pivot+", S1="+s1+", S2="+s2+", S3="+s3+", R1="+r1+", R2="+r2+", R3="+r3);
double takeprofit = 0;
int ticket = -1; //default ticket number.
double stoploss = Trading.StopLoss * Point; //default stop loss level.
double servers_min_stop = MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT);
datetime TimeToEndOfDay = StrToTime(TimeToStr(TimeCurrent(),TIME_DATE)+" 23:55");
//the last 5mintues of the trading hour of the day are purely for
//cleaning up pending orders and getting ready for the new day.
//any other time let do business.
datetime StartOfDay1 = StrToTime(TimeToStr(TimeCurrent(),TIME_DATE)+" 00:01");
datetime StartOfDay2 = StrToTime(TimeToStr(TimeCurrent(),TIME_DATE)+" 00:30");
if (TimeCurrent()<=TimeToEndOfDay){
//if we dont have a sell order at R3 place one.
if ( HasSellOrder(r3,MagicNumber,Trading.Slippage)!= true) {
//open a sell order at r3
takeprofit = s1+MathMin(Trading.FlexPips*Point, servers_min_stop);
stoploss = r3+MathMax(Trading.StopLoss * Point,servers_min_stop);
ticket = PlaceResistanceOrder(r3,pivot, Trading.LotSize, stoploss, takeprofit ,TimeToEndOfDay);
}
//if we dont have a sell order at R2 place one.
if ( HasSellOrder(r2,MagicNumber,Trading.Slippage)!= true) {
//open a sell order at r2
takeprofit = s1+MathMin(Trading.FlexPips*Point, servers_min_stop);
stoploss = r3+MathMax(Trading.StopLoss * Point,servers_min_stop);
ticket = PlaceResistanceOrder(r2,pivot, Trading.LotSize, stoploss, takeprofit ,TimeToEndOfDay);
}
//if we dont have a sell order at R1 place one.
if ( HasSellOrder(r1,MagicNumber,Trading.Slippage)!= true) {
//open a sell order at r1
takeprofit = s1+MathMin(Trading.FlexPips*Point, servers_min_stop);
stoploss = r3+MathMax(Trading.StopLoss * Point,servers_min_stop);
ticket = PlaceResistanceOrder(r1,pivot, Trading.LotSize, stoploss, takeprofit ,TimeToEndOfDay);
}
//if we dont have a sell order at S3 place one.
if ( HasBuyOrder(s3,MagicNumber,Trading.Slippage)!= true) {
//open a buy order at s3
takeprofit = r1-MathMax(Trading.FlexPips*Point, servers_min_stop);
stoploss = s3-MathMax(Trading.StopLoss * Point,servers_min_stop);
ticket = PlaceSupportOrder(s3,pivot, Trading.LotSize, stoploss, takeprofit ,TimeToEndOfDay);
}
//if we dont have a sell order at S2 place one.
if ( HasBuyOrder(s2,MagicNumber,Trading.Slippage)!= true) {
//open a buy order at s2
takeprofit = r1-MathMax(Trading.FlexPips*Point, servers_min_stop);
stoploss = s2-MathMax(Trading.StopLoss * Point,servers_min_stop);
ticket = PlaceSupportOrder(s2,pivot, Trading.LotSize, stoploss, takeprofit ,TimeToEndOfDay);
}
//if we dont have a sell order at S1 place one.
if ( HasBuyOrder(s1,MagicNumber,Trading.Slippage)!= true) {
//open a sell order at s1
takeprofit = r1-MathMax(Trading.FlexPips*Point, servers_min_stop);
stoploss = s1-MathMax(Trading.StopLoss*Point, servers_min_stop);
ticket = PlaceSupportOrder(s1,pivot, Trading.LotSize, stoploss, takeprofit ,TimeToEndOfDay);
}
//now correct the OrderTakeProfit for left over orders, even if it means making a loss.
//implement various strategies.
ImplementStrategy(StrategyIndex, prices);
}
//we want to execute previous orders only during the start of the
//day or when we haven't already done so.
if (((TimeCurrent()>StartOfDay1) && (TimeCurrent()<StartOfDay2))|| (!StartOfDayProcessed) ){
StartOfDayProcessed = true;
AdjustPreviousOrders(prices);
}
//TrackOrders(TrailingStopMode, MagicNumber, Symbol());
return(0);
}
/**
* Now implement the Trading strategy defined by index.
*
*/
void ImplementStrategy(int index, double prices[]){
switch (index){
case STRATEGY_HEDGING:
SimpleHedging(prices);
return;
case STRATEGY_MEGA_TREND:
MegaTrend(prices);
return;
default:
return;
}
}
/**
* Yesterday or Last week's orders are a pain in the neck.
* we need to close them as quickly as possible. If at all we get chance
* to close them at BE we can do it.
**/
void AdjustPreviousOrders(double prices[]){
int total = OrdersTotal()-1;
int today = TimeDayOfWeek(Time[0]), orderDay=-1;
double buytakeprofit=0,selltakeprofit=0;
double servers_min_stop = MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT);
//move the takeprofit to s1 even if it means a losing t/p
selltakeprofit = MathMin(Ask,prices[FIBO_LEVEL_S1]);
//move the takeprofit to s1 even if it means a losing t/p
buytakeprofit = MathMax(Bid,prices[FIBO_LEVEL_R1]);
for(;total>=0; total--){
if (OrderSelect(total,SELECT_BY_POS,MODE_TRADES)!=true)
continue;
if (OrderSymbol()!= Symbol())
continue;
if (OrderMagicNumber()!= MagicNumber)
continue;
if ((OrderType()!=OP_BUY) && (OrderType()!=OP_SELL))
continue;
//process only yesterday's or last week's orders.
orderDay = TimeDayOfWeek(OrderOpenTime());
if ( (orderDay < today) ||
((today==1) && ((orderDay==5)||(orderDay==6)) )
){
//we can close it at break even if its possible.
//if (OrderProfit()==0.0){
// LogInfo("Closing yesterday/last week order at break even.");
// PartiallyClose(OrderType(),OrderTicket(),OrderLots(), OrderOpenPrice(), OrderTakeProfit(),Slippage);
//}
if ((OrderType()==OP_BUY) && (OrderTakeProfit()!=buytakeprofit) ){
//also make sure the takeprofit is valid.
//if its not an invalid stop error can be generated.
LogInfo("A buy order from yesterday or last week is present: OrderTicket="+OrderTicket()+", OrderProfit="+OrderProfit()+", OrderType="+OrderType2String(OrderType())+", OrderOpenPrice="+OrderOpenPrice());
LogInfo("Buy Order, new takeprofit calculated to be "+ buytakeprofit+" and the current price is "+ Bid);
if (!ModifyOrder(OrderTicket(), OrderOpenPrice(),OrderStopLoss(),buytakeprofit, 0,CLR_NONE))
LogError("Failed to modify an old order. "+ ErrorDescription(GetLastError()));
}
else if ((OrderType()==OP_SELL) && (OrderTakeProfit()!=selltakeprofit)){
//also make sure the takeprofit is valid.
//if its not an invalid stop error can be generated.
LogInfo("A sell order from yesterday or last week is present: OrderTicket="+OrderTicket()+", OrderProfit="+OrderProfit()+", OrderType="+OrderType2String(OrderType())+", OrderOpenPrice="+OrderOpenPrice());
LogInfo("Sell Order, new takeprofit calculated to be "+ selltakeprofit+" and the current price is "+ Ask);
if (!ModifyOrder(OrderTicket(), OrderOpenPrice(),OrderStopLoss(),selltakeprofit, 0,CLR_NONE))
LogError("Failed to modify an old order. "+ ErrorDescription(GetLastError()));
}
}
}
}
/**
* In this function place only buy orders.
*/
int PlaceSupportOrder(double price, double pivot, double lots, double stoploss, double takeprofit, datetime expiration){
LogDebug("");
LogDebug("PlaceSupportOrder():Start");
int ticket = -1;
RefreshRates();
double servers_min_stop = MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT);
int cmd = OP_BUYLIMIT;
//if the price is within + or - Slippage*Point simply buy.
if ( (((Trading.Slippage*Point) + Ask) >= price) &&
((Ask-(Trading.Slippage*Point) ) <= price) ){
cmd = OP_BUY;
LogInfo("Support Order at "+price+" is placed at market price.");
LogInfo("SupportOrder: "+ OrderType2String(cmd)+" Price["+Ask+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]");
ticket = CreateOrder(cmd, lots, NormalizeDouble(Ask,Digits),
NormalizeDouble(stoploss,Digits), NormalizeDouble(takeprofit,Digits),
BuyComment, MagicNumber, Trading.Slippage,expiration);
}
else if (MathAbs(Ask-price) > servers_min_stop){
//if the price is too close to the stoplevel there is
//nothing much we can do
if (Ask < price)
cmd = OP_BUYSTOP;
LogInfo("SupportOrder: "+ OrderType2String(cmd)+" Price["+price+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]");
ticket = CreateOrder(cmd, lots, NormalizeDouble(price,Digits),
NormalizeDouble(stoploss,Digits), NormalizeDouble(takeprofit,Digits),
BuyComment, MagicNumber, Trading.Slippage,expiration);
}
LogDebug("PlaceSupportOrder():End");
LogDebug("");
return (ticket);
}
/**
* In this function place only sell orders.
*/
int PlaceResistanceOrder(double price, double pivot, double lots, double stoploss, double takeprofit, datetime expiration){
int ticket = -1;
RefreshRates();
double servers_min_stop = MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT);
int cmd = OP_SELLLIMIT;
if ( (((Trading.Slippage*Point) + Bid) >= price) &&
((Bid-(Trading.Slippage*Point) ) <= price) ){
LogInfo("Opening a sell order at market price.");
LogInfo("ResistanceOrder: "+ OrderType2String(cmd)+" Price["+price+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]");
ticket = CreateOrder(cmd, lots, NormalizeDouble(Ask,Digits),
NormalizeDouble(stoploss,Digits), NormalizeDouble(takeprofit,Digits),
SellComment, MagicNumber, Trading.Slippage,expiration);
}
else if (MathAbs(Bid-price) > servers_min_stop){
//if the price is too close to the stoplevel there is
//nothing much we can do
if (Bid > price)
cmd = OP_SELLSTOP;
LogInfo("ResistanceOrder: "+ OrderType2String(cmd)+" Price["+price+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]");
ticket = CreateOrder(cmd, lots, NormalizeDouble(price,Digits),
NormalizeDouble(stoploss,Digits), NormalizeDouble(takeprofit,Digits),
SellComment, MagicNumber, Trading.Slippage,expiration);
}
return (ticket);
}
//+------------------------------------------------------------------+
//| Make Magic Number |
//+------------------------------------------------------------------+
int MakeMagicNumber(){
int SymbolCode = 0;
int PeriodCode = 0;
//---- Symbol Code
if( StringSubstr(Symbol(),0,6) == "AUDCAD") { SymbolCode = 1000; }
else if( StringSubstr(Symbol(),0,6) == "AUDJPY") { SymbolCode = 2000; }
else if( StringSubstr(Symbol(),0,6) == "AUDNZD") { SymbolCode = 3000; }
else if( StringSubstr(Symbol(),0,6) == "AUDUSD") { SymbolCode = 4000; }
else if( StringSubstr(Symbol(),0,6) == "CHFJPY") { SymbolCode = 5000; }
else if( StringSubstr(Symbol(),0,6) == "EURAUD") { SymbolCode = 6000; }
else if( StringSubstr(Symbol(),0,6) == "EURCAD") { SymbolCode = 7000; }
else if( StringSubstr(Symbol(),0,6) == "EURCHF") { SymbolCode = 8000; }
else if( StringSubstr(Symbol(),0,6) == "EURGBP") { SymbolCode = 9000; }
else if( StringSubstr(Symbol(),0,6) == "EURJPY") { SymbolCode = 1000; }
else if( StringSubstr(Symbol(),0,6) == "EURUSD") { SymbolCode = 1100; }
else if( StringSubstr(Symbol(),0,6) == "GBPCHF") { SymbolCode = 1200; }
else if( StringSubstr(Symbol(),0,6) == "GBPJPY") { SymbolCode = 1300; }
else if( StringSubstr(Symbol(),0,6) == "GBPUSD") { SymbolCode = 1400; }
else if( StringSubstr(Symbol(),0,6) == "NZDJPY") { SymbolCode = 1500; }
else if( StringSubstr(Symbol(),0,6) == "NZDUSD") { SymbolCode = 1600; }
else if( StringSubstr(Symbol(),0,6) == "USDCAD") { SymbolCode = 1700; }
else if( StringSubstr(Symbol(),0,6) == "USDCHF") { SymbolCode = 1800; }
else if( StringSubstr(Symbol(),0,6) == "USDJPY") { SymbolCode = 1900; }
//---- Period Code
if( TimeSpecific ){
if( Period() == PERIOD_M1 ) { PeriodCode = 10; }
else if( Period() == PERIOD_M5 ) { PeriodCode = 20; }
else if( Period() == PERIOD_M15 ){ PeriodCode = 30; }
else if( Period() == PERIOD_M30 ){ PeriodCode = 40; }
else if( Period() == PERIOD_H1 ) { PeriodCode = 50; }
else if( Period() == PERIOD_H4 ) { PeriodCode = 60; }
else if( Period() == PERIOD_D1 ) { PeriodCode = 70; }
else if( Period() == PERIOD_W1) { PeriodCode = 80; }
else if( Period() == PERIOD_MN1 ){ PeriodCode = 90; }
}
else
PeriodCode = 0;
return(ExpertID+SymbolCode+PeriodCode);
}
double CountOpenLots(int type){
int total = OrdersTotal()-1;
double lots = 0.0;
for(;total>=0;total--){
if (OrderSelect(total,SELECT_BY_POS,MODE_TRADES)!=true)
continue;
if (OrderSymbol()!= Symbol())
continue;
if (OrderMagicNumber()!= MagicNumber)
continue;
if (OrderType()!=type)
continue;
lots = lots + OrderLots();
}
return (lots);
}
/** ============================= STRATEGIES ================================= **/
//Simple hedging strategy.
void SimpleHedging(double prices[]){
//if the prices breaks the R3 and S3 barrier we need to be ready and place some buy order sell stop orders.
//with a very tight stop loss
int mn = MagicNumber+STRATEGY_HEDGING;
double r3 = prices[FIBO_LEVEL_R3];
double s3 = prices[FIBO_LEVEL_S3];
string HedgeBuyComment ="(Hedge) "+BuyComment;
string HedgeSellComment ="(Hedge) "+SellComment;
int ticket = -1;
double buylots = Strategy.Hedging.LotSize;
double selllots = Strategy.Hedging.LotSize;
if (buylots <=0.0){
//hedge all open buy positions.
buylots = CountOpenLots(OP_SELL);
}
if (selllots <=0.0){
//hedge all open buy positions.
selllots = CountOpenLots(OP_BUY);
}
//if the lot size is zero or less, the user wants to cover all the open sell or buy positions
if ( (Ask >= r3 ) &&
(Ask <= (r3+(Strategy.Hedging.Slippage*Point)) )
){
//we should place a buy order at this Resistance level 3
//if one is not already there.
if ((!HasBuyOrder(r3,mn,Strategy.Hedging.Slippage)) && (!HasClosedBuyOrder(r3,mn,Strategy.Hedging.Slippage)) ){
LogDebug("Price reached near the R3 level, R3="+r3+", Price="+Ask);
LogInfo("Opening a buy order at R3, Lots="+buylots+", Price="+Ask+", StopLoss="+ prices[FIBO_LEVEL_R2]+"");
ticket = CreateOrder(OP_BUY,buylots,Ask,
prices[FIBO_LEVEL_R2], 0,
HedgeBuyComment,mn,Strategy.Hedging.Slippage,0);
if (ticket<=0)
LogError("Failed to open buy order (Hedge). "+ ErrorDescription(GetLastError()));
}
}
if ( (Bid >= s3 ) &&
(Bid <= (s3+(Strategy.Hedging.Slippage*Point)) )
){
//we should place a buy order at this Resistance level 3
//if one is not already there.
if (!HasSellOrder(s3,mn,Strategy.Hedging.Slippage) && (!HasClosedSellOrder(s3,mn,Strategy.Hedging.Slippage)) ){
LogDebug("Price reached near the S3 level, S3="+s3+", Price="+Bid);
LogInfo("Opening a buy order at S3, Lots="+selllots+", Price="+Bid+", StopLoss="+ prices[FIBO_LEVEL_S2]+"");
ticket = CreateOrder(OP_SELL,selllots,Bid,
prices[FIBO_LEVEL_S2], 0,
HedgeSellComment,mn,Strategy.Hedging.Slippage,0);
if (ticket<=0)
LogError("Failed to open sell order (Hedge). " + ErrorDescription(GetLastError()));
}
}
double params [];
ArrayResize(params,1);
params[0]=Strategy.Hedging.TrailingStop;
TrackOrders(Strategy.Hedging.TrailingMode, mn, Symbol(),params);
}
//___________________________________________________________________________________________//
//use mega trend indicator values
void MegaTrend(double prices[]){
LogWarn("Mega trend Strategy is not yet implemented.");
}
Comments