There can be a conflict when your terminal updates, besides the proposed function isn't correct the one you show is already one that is part of the new beta.
Here is a dirty fix that uses the CopyClose method:
//+------------------------------------------------------------------+//| GonzalonV3.mq5 |//| Copyright 2018, Marco vd Heijden, MetaQuotes Software Corp. |//| https://www.mql5.com |//+------------------------------------------------------------------+#property copyright"Copyright 2018, Marco vd Heijden, MetaQuotes Software Corp."#property link"https://www.mql5.com"#property version"3.00"#define EXPERT_MAGIC 9876548staticinputint TP=0;// Take profit 0 = Nonestaticinputint SL=0;// Stop Loss 0 = Nonedouble close[],a,b,c;
bool direction;
//+------------------------------------------------------------------+//| Expert initialization function |//+------------------------------------------------------------------+intOnInit()
{
//---//---return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+//| Expert deinitialization function |//+------------------------------------------------------------------+voidOnDeinit(constint reason)
{
//---
}
//+------------------------------------------------------------------+//| Expert tick function |//+------------------------------------------------------------------+voidOnTick()
{
int count=CopyClose(Symbol(),PERIOD_D1,1,21,close);
//for(int i=count-1;i>0;i--){Print("Bar: "+IntegerToString(i)+" Close: "+DoubleToString(close[i]));}//--- a variable has the maximum value of the close of the past 20 days (4 weeks)
a=close[ArrayMaximum(close,0,WHOLE_ARRAY)];
//Print("a: "+DoubleToString(a));//--- b variable has the minimum value of the close of the past 20 days (4 weeks)
b=close[ArrayMinimum(close,0,WHOLE_ARRAY)];
//Print("b: "+DoubleToString(b));//--- c variable is daily closedouble close2[];
int count2=CopyClose(Symbol(),PERIOD_D1,0,1,close2);
if(count2==1)
{
c=close2[0];
}//c=iClose(Symbol(),PERIOD_D1,0);// new method..//Print("c: "+DoubleToString(c));//--- When daily close is above a, short trade is closed and long trade is opened if(c>a)
{
if(direction==0)
{
CloseAll();
Long();
direction=1;
}
}
//--- When daily close is below b, long trade is closed and short trade is openedif(c<b)
{
if(direction==1)
{
CloseAll();
Short();
direction=0;
}
}
//---if(PositionsTotal()==0)
{
if(c>a)
{
Long();
direction=1;
}
if(c<b)
{
Short();
direction=0;
}
}
}
//+------------------------------------------------------------------+//| Opening Buy position |//+------------------------------------------------------------------+void Long()
{
//--- declare and initialize the trade request and result of trade requestMqlTradeRequest request={0};
MqlTradeResult result={0};
//--- parameters of request
request.action =TRADE_ACTION_DEAL; // type of trade operation
request.symbol =Symbol(); // symbol
request.volume =0.01; // volume
request.type =ORDER_TYPE_BUY; // order type
request.price =SymbolInfoDouble(Symbol(),SYMBOL_ASK); // price for opening
request.deviation=5; // allowed deviation from the price
request.magic =EXPERT_MAGIC; // MagicNumber of the orderif(TP!=0)
{
request.tp=SymbolInfoDouble(Symbol(),SYMBOL_ASK)+TP*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
}
if(SL!=0)
{
request.sl=SymbolInfoDouble(Symbol(),SYMBOL_BID)-SL*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
}
//--- send the requestif(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code//--- information about the operationPrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
}
//+------------------------------------------------------------------+//| Opening Sell position |//+------------------------------------------------------------------+void Short()
{
//--- declare and initialize the trade request and result of trade requestMqlTradeRequest request={0};
MqlTradeResult result={0};
//--- parameters of request
request.action =TRADE_ACTION_DEAL; // type of trade operation
request.symbol =Symbol(); // symbol
request.volume =0.01; // volume
request.type =ORDER_TYPE_SELL; // order type
request.price =SymbolInfoDouble(Symbol(),SYMBOL_BID); // price for opening
request.deviation=5; // allowed deviation from the price
request.magic =EXPERT_MAGIC; // MagicNumber of the orderif(TP!=0)
{
request.tp=SymbolInfoDouble(Symbol(),SYMBOL_BID)-TP*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
}
if(SL!=0)
{
request.sl=SymbolInfoDouble(Symbol(),SYMBOL_ASK)+SL*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
}
//--- send the requestif(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code//--- information about the operationPrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
}
//+------------------------------------------------------------------+//| Closing all positions |//+------------------------------------------------------------------+void CloseAll()
{
//--- declare and initialize the trade request and result of trade requestMqlTradeRequest request;
MqlTradeResult result;
int total=PositionsTotal(); // number of open positions //--- iterate over all open positionsfor(int i=total-1; i>=0; i--)
{
//--- parameters of the orderulong position_ticket=PositionGetTicket(i); // ticket of the positionstring position_symbol=PositionGetString(POSITION_SYMBOL); // symbol int digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // number of decimal placesulong magic=PositionGetInteger(POSITION_MAGIC); // MagicNumber of the positiondouble volume=PositionGetDouble(POSITION_VOLUME); // volume of the positionENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // type of the position//--- output information about the positionPrintFormat("#%I64u %s %s %.2f %s [%I64d]",
position_ticket,
position_symbol,
EnumToString(type),
volume,
DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN),digits),
magic);
//--- if the MagicNumber matchesif(magic==EXPERT_MAGIC)
{
//--- zeroing the request and result valuesZeroMemory(request);
ZeroMemory(result);
//--- setting the operation parameters
request.action =TRADE_ACTION_DEAL; // type of trade operation
request.position =position_ticket; // ticket of the position
request.symbol =position_symbol; // symbol
request.volume =volume; // volume of the position
request.deviation=5; // allowed deviation from the price
request.magic =EXPERT_MAGIC; // MagicNumber of the position//--- set the price and order type depending on the position typeif(type==POSITION_TYPE_BUY)
{
request.price=SymbolInfoDouble(position_symbol,SYMBOL_BID);
request.type =ORDER_TYPE_SELL;
}
else
{
request.price=SymbolInfoDouble(position_symbol,SYMBOL_ASK);
request.type =ORDER_TYPE_BUY;
}
//--- output information about the closurePrintFormat("Close #%I64d %s %s",position_ticket,position_symbol,EnumToString(type));
//--- send the requestif(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code//--- information about the operation PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
//---
}
}
}
//+------------------------------------------------------------------+
This one should work for you.
But you might want to add trailing or some other whistles and bells..
I downloaded the latest version of MetaTrader 5 and it works. I have been testing the strategy, and I have found that it doesn't work exactly like it should. For example, in the attached pic, you can see the trades are being executed at different hours of the day. Since this strategy acts exactly at the time the day finishes, all the trades should be executed at the same time, which should be around 23:00 hour (Madrid GMT). I have been through the code but I didn't find anything that could explain this. Would it be possible for you to have a look Marco?
//--- When daily close is above a, short trade is closed and long trade is opened
and
//--- When daily close is below b, long trade is closed and short trade is opened
Now understand that the daily close is equal to the bid price for the entire day, until the candle closes.
This means that if somewhere, during the day, the bid price goes either over A or below B, there will be a swap in direction.
So as a result you need to specifically state that it may only trigger upon a new candle arrival.
Luckily this can be achieved by adding a few lines of code.
//+------------------------------------------------------------------+//| GonzalonV4.mq5 |//| Copyright 2018, Marco vd Heijden, MetaQuotes Software Corp. |//| https://www.mql5.com |//+------------------------------------------------------------------+#property copyright"Copyright 2018, Marco vd Heijden, MetaQuotes Software Corp."#property link"https://www.mql5.com"#property version"4.00"#define EXPERT_MAGIC 9876548staticinputint period=20;// Period (in days)staticinputint TP=0;// Take profit 0 = Nonestaticinputint SL=0;// Stop Loss 0 = Nonedouble close[],a,b,c;
bool direction;
datetime time;//+------------------------------------------------------------------+//| Expert initialization function |//+------------------------------------------------------------------+intOnInit()
{
//---
// time=iTime(_Symbol,PERIOD_D1,0);//---return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+//| Expert deinitialization function |//+------------------------------------------------------------------+voidOnDeinit(constint reason)
{
//---
}
//+------------------------------------------------------------------+//| Expert tick function |//+------------------------------------------------------------------+voidOnTick()
{
if(time!=iTime(_Symbol,PERIOD_D1,0))
{
int count=CopyClose(Symbol(),PERIOD_D1,1,period+1,close);
//for(int i=count-1;i>0;i--){Print("Bar: "+IntegerToString(i)+" Close: "+DoubleToString(close[i]));}//--- a variable has the maximum value of the close of the past 20 days (4 weeks)
a=close[ArrayMaximum(close,0,WHOLE_ARRAY)];
//Print("a: "+DoubleToString(a));//--- b variable has the minimum value of the close of the past 20 days (4 weeks)
b=close[ArrayMinimum(close,0,WHOLE_ARRAY)];
//Print("b: "+DoubleToString(b));//--- c variable is daily closedouble close2[];
int count2=CopyClose(Symbol(),PERIOD_D1,0,1,close2);
if(count2==1)
{
c=close2[0];
}
//c=iClose(Symbol(),PERIOD_D1,0);// new method..//Print("c: "+DoubleToString(c));//--- When daily close is above a, short trade is closed and long trade is opened if(c>a)
{
if(direction==0)
{
CloseAll();
Long();
direction=1;
}
}
//--- When daily close is below b, long trade is closed and short trade is openedif(c<b)
{
if(direction==1)
{
CloseAll();
Short();
direction=0;
}
}
//---if(PositionsTotal()==0)
{
if(c>a)
{
Long();
direction=1;
}
if(c<b)
{
Short();
direction=0;
}
}
time=iTime(_Symbol,PERIOD_D1,0);
}
}
//+------------------------------------------------------------------+//| Opening Buy position |//+------------------------------------------------------------------+void Long()
{
//--- declare and initialize the trade request and result of trade requestMqlTradeRequest request={0};
MqlTradeResult result={0};
//--- parameters of request
request.action =TRADE_ACTION_DEAL; // type of trade operation
request.symbol =Symbol(); // symbol
request.volume =0.01; // volume
request.type =ORDER_TYPE_BUY; // order type
request.price =SymbolInfoDouble(Symbol(),SYMBOL_ASK); // price for opening
request.deviation=5; // allowed deviation from the price
request.magic =EXPERT_MAGIC; // MagicNumber of the orderif(TP!=0)
{
request.tp=SymbolInfoDouble(Symbol(),SYMBOL_ASK)+TP*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
}
if(SL!=0)
{
request.sl=SymbolInfoDouble(Symbol(),SYMBOL_BID)-SL*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
}
//--- send the requestif(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code//--- information about the operationPrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
}
//+------------------------------------------------------------------+//| Opening Sell position |//+------------------------------------------------------------------+void Short()
{
//--- declare and initialize the trade request and result of trade requestMqlTradeRequest request={0};
MqlTradeResult result={0};
//--- parameters of request
request.action =TRADE_ACTION_DEAL; // type of trade operation
request.symbol =Symbol(); // symbol
request.volume =0.01; // volume
request.type =ORDER_TYPE_SELL; // order type
request.price =SymbolInfoDouble(Symbol(),SYMBOL_BID); // price for opening
request.deviation=5; // allowed deviation from the price
request.magic =EXPERT_MAGIC; // MagicNumber of the orderif(TP!=0)
{
request.tp=SymbolInfoDouble(Symbol(),SYMBOL_BID)-TP*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
}
if(SL!=0)
{
request.sl=SymbolInfoDouble(Symbol(),SYMBOL_ASK)+SL*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
}
//--- send the requestif(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code//--- information about the operationPrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
}
//+------------------------------------------------------------------+//| Closing all positions |//+------------------------------------------------------------------+void CloseAll()
{
//--- declare and initialize the trade request and result of trade requestMqlTradeRequest request;
MqlTradeResult result;
int total=PositionsTotal(); // number of open positions //--- iterate over all open positionsfor(int i=total-1; i>=0; i--)
{
//--- parameters of the orderulong position_ticket=PositionGetTicket(i); // ticket of the positionstring position_symbol=PositionGetString(POSITION_SYMBOL); // symbol int digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // number of decimal placesulong magic=PositionGetInteger(POSITION_MAGIC); // MagicNumber of the positiondouble volume=PositionGetDouble(POSITION_VOLUME); // volume of the positionENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // type of the position//--- output information about the positionPrintFormat("#%I64u %s %s %.2f %s [%I64d]",
position_ticket,
position_symbol,
EnumToString(type),
volume,
DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN),digits),
magic);
//--- if the MagicNumber matchesif(magic==EXPERT_MAGIC)
{
//--- zeroing the request and result valuesZeroMemory(request);
ZeroMemory(result);
//--- setting the operation parameters
request.action =TRADE_ACTION_DEAL; // type of trade operation
request.position =position_ticket; // ticket of the position
request.symbol =position_symbol; // symbol
request.volume =volume; // volume of the position
request.deviation=5; // allowed deviation from the price
request.magic =EXPERT_MAGIC; // MagicNumber of the position//--- set the price and order type depending on the position typeif(type==POSITION_TYPE_BUY)
{
request.price=SymbolInfoDouble(position_symbol,SYMBOL_BID);
request.type =ORDER_TYPE_SELL;
}
else
{
request.price=SymbolInfoDouble(position_symbol,SYMBOL_ASK);
request.type =ORDER_TYPE_BUY;
}
//--- output information about the closurePrintFormat("Close #%I64d %s %s",position_ticket,position_symbol,EnumToString(type));
//--- send the requestif(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code//--- information about the operation PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
//---
}
}
}
//+------------------------------------------------------------------+
Thank you very much Marco. Sorry for the misunderstanding, I thought that "when daily close is above a" clearly indicated that the trade would only be executed when the daily candle close (which represents the last value of the day) was above a (which was the maximum of the previous 20 daily candles close). I am glad that now it is clear :)
I have been testing your code and it seems to work quite well. I decided to take it to my Oanda real account, and I found out that Oanda doesn't support MT5. Now I have the following options:
- Change to a broker that supports MT5
- Try to develop a similar code in MT4 (which is supported by Oanda)
- Try to develop a similar code in Oanda Algorithm Lab (which is powered by QuanConnect)
Since you have helped me so much, I am going to ask for your advice again :)
*If you are happy with your current broker i would stick with them.
*It's not hard to convert this code to MQL4.
*I don't know Oanda Algo but i know that it can sometimes be hard to replicate certain things in other platforms.
On another note this Version 4 can still be improved think about adding a trailingstop and for example dynamic lotsizing to maximize profits.
I coded this thing because your strategy lack's the use of indicator's which makes it very special.
Thanks for your reply Marco, I agree on the fact that if I am happy with my broker, I should stick with them.
Regarding the trailingstop, I did many simulations in Trading View with different variations of the strategy, including setting take profits, setting trailingstops, varying the number of days taken into account for the trade decision, etc. And this was the most profitable version based on historical data. That's why I am trying to implement it with auto trading.
I also simulated other strategies, many of them with indicators, and no one of them had the profitability of this strategy. It looks like sometimes simpler is better.
I know I have asked you a lot already, but I am not sure if it would be possible for you to code this strategy in MQL4?
//+------------------------------------------------------------------+//| GonzalonV4.mq4 |//| Copyright 2018, Marco vd Heijden, MetaQuotes Software Corp. |//| https://www.mql5.com |//+------------------------------------------------------------------+#property copyright"Copyright 2018, Marco vd Heijden, MetaQuotes Software Corp."#property link"https://www.mql5.com"#property version"1.00"#property strict#define EXPERT_MAGIC 9876548staticinputint period=20;// Period (in days)staticinputint TP=0;// Take profit 0 = Nonestaticinputint SL=0;// Stop Loss 0 = Nonestaticinputdouble lotsize=0.01;// Lotsizedouble close[],a,b,c;
bool direction;
datetime time;
//+------------------------------------------------------------------+//| Expert initialization function |//+------------------------------------------------------------------+intOnInit()
{
//---// time=iTime(_Symbol,PERIOD_D1,0); //---return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+//| Expert deinitialization function |//+------------------------------------------------------------------+voidOnDeinit(constint reason)
{
//---
}
//+------------------------------------------------------------------+//| Expert tick function |//+------------------------------------------------------------------+voidOnTick()
{
if(time!=iTime(_Symbol,PERIOD_D1,0))
{
int count=CopyClose(Symbol(),PERIOD_D1,1,period+1,close);
//for(int i=count-1;i>0;i--){Print("Bar: "+IntegerToString(i)+" Close: "+DoubleToString(close[i]));}//--- a variable has the maximum value of the close of the past 20 days (4 weeks)
a=close[ArrayMaximum(close,0,WHOLE_ARRAY)];
//Print("a: "+DoubleToString(a));//--- b variable has the minimum value of the close of the past 20 days (4 weeks)
b=close[ArrayMinimum(close,0,WHOLE_ARRAY)];
//Print("b: "+DoubleToString(b));//--- c variable is daily closedouble close2[];
int count2=CopyClose(Symbol(),PERIOD_D1,0,1,close2);
if(count2==1)
{
c=close2[0];
}
//c=iClose(Symbol(),PERIOD_D1,0);// new method..//Print("c: "+DoubleToString(c));//--- When daily close is above a, short trade is closed and long trade is opened if(c>a)
{
if(direction==0)
{
CloseAll();
Long();
//direction=1;
}
}
//--- When daily close is below b, long trade is closed and short trade is openedif(c<b)
{
if(direction==1)
{
CloseAll();
Short();
//direction=0;
}
}
//---if(OrdersTotal()==0)
{
if(c>a)
{
Long();
//direction=1;
}
if(c<b)
{
Short();
//direction=0;
}
}
time=iTime(_Symbol,PERIOD_D1,0);
}
}
//+------------------------------------------------------------------+//| Opening Buy position |//+------------------------------------------------------------------+void Long()
{
double tp=0;
if(TP!=0){tp=MarketInfo(Symbol(),MODE_ASK)+TP*MarketInfo(Symbol(),MODE_POINT);}
double sl=0;
if(SL!=0){sl=MarketInfo(Symbol(),MODE_BID)-SL*MarketInfo(Symbol(),MODE_POINT);}
{
if(OrdersTotal()==0)
{
int ticket=OrderSend(Symbol(),OP_BUY,lotsize,MarketInfo(Symbol(),MODE_ASK),3,sl,tp,"Buy-Gonzalon",EXPERT_MAGIC,0,clrRed);
{
if(ticket>0)
{
direction=1;
}
}
}
}
}
//+------------------------------------------------------------------+//| Opening Sell position |//+------------------------------------------------------------------+void Short()
{
double tp=0;
if(TP!=0){tp=MarketInfo(Symbol(),MODE_BID)-TP*MarketInfo(Symbol(),MODE_POINT);}
double sl=0;
if(SL!=0){sl=MarketInfo(Symbol(),MODE_ASK)+SL*MarketInfo(Symbol(),MODE_POINT);}
{
if(OrdersTotal()==0)
{
int ticket=OrderSend(Symbol(),OP_SELL,lotsize,MarketInfo(Symbol(),MODE_BID),3,sl,tp,"Sell-Gonzalon",EXPERT_MAGIC,0,clrRed);
{
if(ticket>0)
{
direction=0;
}
}
}
}
}
//+------------------------------------------------------------------+//| Closing all positions |//+------------------------------------------------------------------+void CloseAll()
{
for(int i=OrdersTotal();i>=0;i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if(OrderMagicNumber()==EXPERT_MAGIC)
{
if(OrderType()==OP_BUY)
{
bool result=OrderClose(OrderTicket(),OrderLots(),MarketInfo(Symbol(),MODE_BID),3,clrGold);
{
if(result==0)
{
time=0;
}
}
}
if(OrderType()==OP_SELL)
{
bool result=OrderClose(OrderTicket(),OrderLots(),MarketInfo(Symbol(),MODE_ASK),3,clrGold);
{
if(result==0)
{
time=0;
}
}
}
}
}
}
}
//+------------------------------------------------------------------+
Alright here you go.
I wrote it rather quickly so there are no checks for min and max levels.
Consider it pseudocode, if you really want it rock solid it will need some additional work.
I did a quick test with default settings TP=0 SL=0;
MT4:
In any case as with the previous one it needs dynamic lotsizing to boost performance.
I have been checking the results obtained with your code (MT4 one), and I am afraid the code is not working 100% as per the strategy guidelines. For example, on the pic attached, you can see how the bar circled in red (4 April 2018) should have been the signal to close current short trade and open a long one, since its close is above the close of the previous 20 daily bars (you can easily check it on the graph). That means that there should be a buy order on the opening on the next daily candle (5 April 2018), but as you can see on the results, the buy order was filled on 16th April 2018, several days later.
Would it be possible for you to have a look and let me know?
Please open a demo account on MetaQuotes-Demo server.
After this your terminal will update to the newest version that allows the use of these functions.
Wait, I declared iTime function, as the code I read had done so.
so I don't need to declare these functions ? (MT5 , build 1870)
There can be a conflict when your terminal updates, besides the proposed function isn't correct the one you show is already one that is part of the new beta.
Please read here about the new function being added: https://www.mql5.com/en/forum/257568
Here is a dirty fix that uses the CopyClose method:
This one should work for you.
But you might want to add trailing or some other whistles and bells..
You know, add some magic.
I downloaded the latest version of MetaTrader 5 and it works. I have been testing the strategy, and I have found that it doesn't work exactly like it should. For example, in the attached pic, you can see the trades are being executed at different hours of the day. Since this strategy acts exactly at the time the day finishes, all the trades should be executed at the same time, which should be around 23:00 hour (Madrid GMT). I have been through the code but I didn't find anything that could explain this. Would it be possible for you to have a look Marco?
Thanks!
Well you did not specify that anywhere.
You said and i quote:
Now understand that the daily close is equal to the bid price for the entire day, until the candle closes.
This means that if somewhere, during the day, the bid price goes either over A or below B, there will be a swap in direction.
So as a result you need to specifically state that it may only trigger upon a new candle arrival.
Luckily this can be achieved by adding a few lines of code.
Thank you very much Marco. Sorry for the misunderstanding, I thought that "when daily close is above a" clearly indicated that the trade would only be executed when the daily candle close (which represents the last value of the day) was above a (which was the maximum of the previous 20 daily candles close). I am glad that now it is clear :)
I have been testing your code and it seems to work quite well. I decided to take it to my Oanda real account, and I found out that Oanda doesn't support MT5. Now I have the following options:
- Change to a broker that supports MT5
- Try to develop a similar code in MT4 (which is supported by Oanda)
- Try to develop a similar code in Oanda Algorithm Lab (which is powered by QuanConnect)
Since you have helped me so much, I am going to ask for your advice again :)
Thanks!
*If you are happy with your current broker i would stick with them.
*It's not hard to convert this code to MQL4.
*I don't know Oanda Algo but i know that it can sometimes be hard to replicate certain things in other platforms.
On another note this Version 4 can still be improved think about adding a trailingstop and for example dynamic lotsizing to maximize profits.
I coded this thing because your strategy lack's the use of indicator's which makes it very special.
*If you are happy with your current broker i would stick with them.
*It's not hard to convert this code to MQL4.
*I don't know Oanda Algo but i know that it can sometimes be hard to replicate certain things in other platforms.
On another note this Version 4 can still be improved think about adding a trailingstop and for example dynamic lotsizing to maximize profits.
I coded this thing because your strategy lack's the use of indicator's which makes it very special.
Thanks for your reply Marco, I agree on the fact that if I am happy with my broker, I should stick with them.
Regarding the trailingstop, I did many simulations in Trading View with different variations of the strategy, including setting take profits, setting trailingstops, varying the number of days taken into account for the trade decision, etc. And this was the most profitable version based on historical data. That's why I am trying to implement it with auto trading.
I also simulated other strategies, many of them with indicators, and no one of them had the profitability of this strategy. It looks like sometimes simpler is better.
I know I have asked you a lot already, but I am not sure if it would be possible for you to code this strategy in MQL4?
Again, thanks a lot.
Yes but i have some more tasks too i will try to find a spare minute.
Alright here you go.
I wrote it rather quickly so there are no checks for min and max levels.
Consider it pseudocode, if you really want it rock solid it will need some additional work.
I did a quick test with default settings TP=0 SL=0;
MT4:
In any case as with the previous one it needs dynamic lotsizing to boost performance.
Here is the result for the MT5 version:
As you can see very similar results.
jaja, I love the no indicators pic :D
I have been checking the results obtained with your code (MT4 one), and I am afraid the code is not working 100% as per the strategy guidelines. For example, on the pic attached, you can see how the bar circled in red (4 April 2018) should have been the signal to close current short trade and open a long one, since its close is above the close of the previous 20 daily bars (you can easily check it on the graph). That means that there should be a buy order on the opening on the next daily candle (5 April 2018), but as you can see on the results, the buy order was filled on 16th April 2018, several days later.
Would it be possible for you to have a look and let me know?
Thanks again for all your help!