I have a simple backtest of below EA:
void OnTick()
{
double rsi = iRSI( Symbol(), PERIOD_M5, 14, PRICE_CLOSE, 0 );
int day = TimeDay( TimeCurrent() );
int hour = TimeHour( TimeCurrent() );
int min = TimeMinute( TimeCurrent() );
if ( day == 7
&& hour >= 9
&& hour < 11
) {
Print( Symbol(), " / ", PERIOD_M5, " rsi: ", (string) rsi );
}
}
However, the backtest log seems does not match with show in the chart as this image:
http://i.imgur.com/PRhtvQD.png
Could you please give some explanation?
Q : "Could you please give some explanation?"
Sure, your code calculates & updates a printed RSI(14)-value (per-tick)
Kindly notice, that the previous bar 08:55 has finished with RSI(14)-value well above the HLINE ~ 30% (if in doubts, one can initially Print( iRSI( Symbol(), PERIOD_M5, 14, PRICE_CLOSE, 1 ) ); where you will see the "previous"-bar value numerically.
From about that value ( above ~ 30% ) the newly opened bar [0] will start to "develop" the actual RSI(14)-value, inside the new bar. So, initially, the values will "move" and the graph plots / redraws the line ( we can visualise each such change as a dot, marker or a Hi/Lo-range ), which is THE REASON, why we finally see a blue line fallen to the position, where the Close[0] has "finished" upon exiting of the bar under review (the 09:00 one, at about the 09:04:59:9999 time).
Related
My question is in two closely related parts:
Given the entry price and stop loss, how can I calculate my lot size so that 2.5% of my current account balance would be risked on trades?
Also in cases where the 2.5% lot size is not a tradable lot size, say 0.013 and 0.018, how can I round the lot size already calculated in 1. to the closest tradable lot size 0.01 (for 0.013) and 0.02 (for 0.018)?
I know how to calculate the number of pips between my entry price and stop loss:
double DiffInPips = MathAbs(NormalizeDouble(stopLoss-openPrice,Digits)/Point);
I believe it is needed to solve this, but not sure how to arrive at the desired lot sizes in both of the above.
Calculating the risk-exposed part of your equity is a trivial but not on-topic here, so let me here focus on the programming, solving the item 2:
double NormalizeLotsToTRADE( const double aLotSizeREQUESTED ) // DEMO CODE
{
double aMinSIZE = MarketInfo( _Symbol, MODE_MINLOT ),
aMaxSIZE = MarketInfo( _Symbol, MODE_MAXLOT ),
aFixSTEP = MarketInfo( _Symbol, MODE_LOTSTEP );
return( MathMin( aMaxSIZE, // never > MAXLOT
MathMax( aMinSIZE, // never < MINLOT
( aMinSIZE // ~ min + steps
+ aFixSTEP * MathFloor( ( aLotSizeREQUESTED
- aMinSIZE
)
/ aFixSTEP
)
)
)
)
);
}
For a case your Risk-Manager is not so strict on your risk-modeling caveats and permit you to go into "closest" rounding, may use MathRound() instead of risk-management strict using of MathFloor().
I need to do somthing like this
if ( iAO( Symbol(),PERIOD_M1, 0) <= iAO( Symbol(), PERIOD_M5, 0) )
{
....
}
But iAO( Symbol(), PERIOD_M5, 0) does not work when my chart timeframe is M1 (It return 0 always).
Is it possible to obtain the real returned value of this function in M1?
UPDATE
I found out that the problem is something related with the bars number at the different time frames. something like this:
int BM1 = iBars(NULL,PERIOD_M1);
where
int BM5 = BM1/5;
or
int BM5 = iBars(NULL,PERIOD_BM5);
So, if i do this it does works if i'm in timeframe M1.
int i, n=0, Counted_bars;
Counted_bars=IndicatorCounted();
i=Bars-Counted_bars-1;
while(i>=0)
{
if ( iAO( Symbol(),PERIOD_M1, i) <= iAO( Symbol(), PERIOD_M5, i/5) )
{
...
}
i--;
}
But it only works when i'm programing a indicator. It does not works in a Expert Advisor. ¿Any idea?
Sirs,
In connection with another problem, I am trying to create an array whose contents are the previous hourly closing values of the EURUSD. I have code as follows:
void Trade()
{
double longThresh = this.longThreshold;
double longTP = this.longTakeProfit;
double longSL = this.longStopLoss;
double shortThresh = this.shortThreshold;
double shortTP = this.shortTakeProfit;
double shortSL = this.shortStopLoss;
int dummyIndex = 0;
Print( "Triggered reload of stack data for trading routine" );
this.stackArray[0] = iClose( "EURUSD", PERIOD_H1, 1 );
this.stackArray[1] = iClose( "EURUSD", PERIOD_H1, 2 );
this.stackArray[2] = iClose( "EURUSD", PERIOD_H1, 3 );
this.stackArray[3] = iClose( "EURUSD", PERIOD_H1, 4 );
this.stackArray[4] = iClose( "EURUSD", PERIOD_H1, 5 );
this.stackArray[5] = iClose( "EURUSD", PERIOD_H1, 6 );
this.stackArray[6] = iClose( "EURUSD", PERIOD_H1, 7 );
this.stackArray[7] = iClose( "EURUSD", PERIOD_H1, 8 );
this.PrintStackArray();
}
The function above is actually an object method. The Object is instantiated, and a do-while loop causes the method above to be re-executed every hour at the five minute mark.
The problem is that when the code above executes an hour later, the PrintStackArray() output indicates that the iClose() function is not keeping up with new candlesticks every hour.
To put it another way, if the code were to execute at 5:05, it would give the same output as it would at 6:05, and in turn give identical output at 7:05.
I cannot for the life of me figure out why re-executing the iClose() functions does not update the array with the new candlestick values. Despite over two weeks of tinkering with this issue, I cannot force my EA to update and recognize new candlestick values.
This may happen uder such condition,that the code was being run without a live-feed of events from market, using just a localhost time-bound triggered Object method invocation ( which was not disclosed as an MCVE above ) thus forever showing the same time-series data head, which under such conditions simply get no live-feed updates, yielding the same [1,2,3,..] values forever:
if ( !IsConnected() )
{ Print( "No connection!" );
return( 0 );
}
may validate your EA state against a live server.
I'm attempting to modify my market orders to breakeven the position when the position get 100 pips to the good. This also accounts for the StopLevels which are around 20-30 pips for my broker. It checks the param's via a "for(){...} loop" function
The MagicNumber is the timeframe number for the chart it is on (i.e. 240=4H, 60=1H) I don't set a TakeProfit price & initially no StopLoss price.
The EA is not adding a SL to be equal to the opening price when the trade reaches 100 pip in profit (plus stoplevels). Profit points reaches well over 130 points.
My code is below for a OP_SELL order - any help would be appreciated. Regards, Todd
/*Global Declarations*/
double pnlPoints;
double price, sl, tp;
double point;
int stopLevel;
int breakeven;
double newSL;
/*Local Declaratons*/
pnlPoints = 0;
point = MarketInfo( Symbol(), MODE_POINT );
stopLevel = int( MarketInfo( Symbol(), MODE_STOPLEVEL )
+ MarketInfo( Symbol(), MODE_SPREAD )
);
sl = NormalizeDouble( OrderStopLoss(), Digits );
tp = OrderTakeProfit();
breakeven = 100;
for( int s = OrdersTotal() - 1; s >= 0; s-- )
{ if ( ( OrderSelect( s, SELECT_BY_POS, MODE_TRADES ) ) == true )
price = MarketInfo( Symbol(), MODE_ASK );
newSL = NormalizeDouble( OrderOpenPrice(), Digits );
pnlPoints = ( OrderOpenPrice() - price ) / point;
if ( OP_SELL == OrderType() )
if ( Period() == OrderMagicNumber() )
if ( stopLevel < ( newSL - price ) / point )
if ( breakeven < pnlPoints )
if ( newSL != sl )
ModSell = OrderModify( OrderTicket(),
OrderOpenPrice(),
newSL,
tp,
buycolor
);
else if ( ModBuy == false )
{ Print( "OrderModify failed with error #",
GetLastError()
);
}
}
For the moment being,refine the codeandadd self-debuging / tracing code
After OrderModify() use a self-debugging / journaling Print( StringFormat( ... ) ) to document all instructed values used in the actual OrderModify() call and also the remote-execution ( { server-side | StrategyTester } ) reported issues.
The current code does not enter into such self-diagnostics and ModSell is not inspected at all, ModBuy is inspected only at uncertain conditions / by-coincidence at some future visit of the for(){...} code-execution path to a part after newSL == sl ( and all above stated conditions are just by chance met too )
Next, check an assigned value of tp
As stated above,
/*Local Declarations*/
...
tp = OrderTakeProfit();
which introduces a reasonable doubt, that re-using of this ( inherently uncertain value, as no one knows, which OrderSelect() was the last one that set a db.Pool pointer to decide, from which record from the db.Pool this veryOrderTakeProfit() would accidentally read ( if any record is present in db.Pool already ) inside the whole for(){...} traversing the db.Pool records will not meet conditions for setting properly a TakeProfit price in the next series of OrderModify() calls.
This seems to be the root cause, or a source of unhandled exceptions to the valid, Broker-compliant, OrderModify() values.
Try this:
if (newSL != sl ) {
ModSell = OrderModify( OrderTicket(),
OrderOpenPrice(),
OrderOpenPrice(),
0,
OrderExpiration(),
clrRed
);
if(ModBuy == false )
Print( "OrderModify failed with error #", GetLastError());
}
Then check the Expert-tab for error-message if it fails to set the stop.
Also, you need to take note that StopLoss will ONLY occur if you are on the right chart-timeframe; Otherwise, it won't even get into the if-statements.
I am totally drain out as the second if statement couldn't be executed.
My original idea was when volatility is in a range of 90 - 110, the program will send one and only one order. And it will wait and see till the volatility reaches in a range of 111 - 150, and then it will send the second order.
If I don't use a bool function here, the program will send countless order when the range is reached.
Could someone please help me?
if ( TodayMaxVolatilityPercentage >= 90.0
&& ( dayTrend == 1 )
&& orderOpened == false
)
{
Print( "Entered if clause" );
// Print( "Today volatility percentage is: ", TodayMaxVolatilityPercentage + "%" );
// ticket: Returns number of the ticket assigned to the order by the trade server or -1 if it fails.
ticket = OrderSend( Symbol(),
OP_SELL,
0.3,
Bid,
3,
0 * MyPoint,
30 * MyPoint,
NULL,
MagicNumber,
0,
Blue
);
Print( "Order is opened on", OrderOpenTime()+" at price: ", OrderOpenPrice() );
Print( "trend number is ",dayTrend );
if ( ticket > 0 )
{
if ( TakeProfit > 0 ) TheTakeProfit = Bid - TakeProfit * MyPoint;
OrderSelect( ticket, SELECT_BY_TICKET ); // bool value
/* OrderModify( OrderTicket(),
OrderOpenPrice(),
0,
NormalizeDouble( TheTakeProfit, Digits ),
0,
Green
);
*/
}
orderOpened = true;
if ( TodayMaxVolatilityPercentage >= 110.0 ) orderOpened = false;
}
if ( TodayMaxVolatilityPercentage >= 110.0
&& ( dayTrend == 1 )
&& orderOpened == false
)
{
Print( "Entered second if clause" );
// ticket: Returns number of the ticket assigned to the order by the trade server or -1 if it fails.
ticket = OrderSend( Symbol(),
OP_SELL,
0.3,
Bid,
3,
0 * MyPoint,
30 * MyPoint,
NULL,
MagicNumber,
0,
Blue
);
if ( ticket > 0 )
{
if ( TakeProfit > 0 ) TheTakeProfit = Bid - TakeProfit * MyPoint;
OrderSelect( ticket, SELECT_BY_TICKET ); // bool value
/* OrderModify( OrderTicket(),
OrderOpenPrice(),
0,
NormalizeDouble( TheTakeProfit, Digits ),
0,
Green
);
*/
}
orderOpened = true;
}
A hidden show-stopper:
By design, the first successful OrderSend() returns a value you assign into an ticket = OrderSend(...).
The devil is hidden in detail.
[MQL4-Help] says:
Returns number of the ticket assigned to the order by the trade server or -1 if it fails.
So the first successful OrderSend() ticket# returned is 0 ( in StrategyTester, a real MT4/Server rather runs into high numbers drawn from it's db.pool of tickets ).
Thus the second if ( ticket > 0 ) will never let you in.
It is common to rather use if ( ticket > EMPTY ) so as to also clarify the intention and use symbolic instead of a -1 integer constant.