I have a simple BUY order that, when the Take Profit and Stoploss are in points (ie: Ask+10*_Point), operates correctly. But when I change the take profit and stop loss from points to my own calculated values (CL_OP), the BUY order is not placing trades. How can I solve the issue:
input int _Hour =16;
input int _Minute =30;
bool NewBar()
{
static datetime OldTime = 0;
if(OldTime < Time[0])
{
OldTime = Time[0];
return(true);
}
else
{
return(false);
}
}
void OnTick()
{
int Hour_Int = Hour();
int Minute_Int = Minute();
double CL_OP = (Close[1] - Open[1]);
bool LastBearHiLoEngulf = (Close[1] < Open[1] && High[1] > High[2] && Low[1] < Low[2] );
if(NewBar())
if(OrdersTotal()==0)
// Apply signals on Buy opportunities
if( Hour_Int == _Hour && Minute_Int == _Minute && LastBearHiLoEngulf == TRUE)
{
int buyticket = OrderSend
(
Symbol(), // all symbols
OP_BUY, // Buy without delay
1, // 1 Microlots
Ask, // for market price
3, // 3 pips slippage
Ask - CL_OP, // Stop Loss - 1000*_Point
Ask + CL_OP , // Take profitworks with 100*_Point
"Buy LastBearHiLoEngulf Target: ", // comment
144, // Magic number
0, // no experiation day
Green // draw green arrow
);
}
}
double CL_OP = (Close[1] - Open[1]);
CL_OP is not a normal price to open trade. Actually, it is the Size of the Candle 1!
It should be something like this:
double CL_OP = Close[1] + (Close[1] - Open[1]);
I have these functions to select the last opened order and the last closed order to retrieve multiple data points. This works, however if one or more orders open simultaneously or close simultaneously, it only picks up one order.
Find Last Opened Order
datetime LastOrderOpenTime = 0;
void SelectMostRecentOpened(int magic_number)
{
for(int i=OrdersHistoryTotal();i>=0;i--)
{
if(OrderSelect(i,SELECT_BY_TICKET,MODE_HISTORY)
&& OrderSymbol()==_Symbol
&& OrderMagicNumber() == magic_number
&& OrderOpenTime() > LastOrderOpenTime)
{
...Fill a two dimensional array with data from the selected order
}
LastOrderOpenTime = OrderOpenTime();
}
}
Find Last Closed Order
datetime LastOrderCloseTime = 0;
void SelectMostRecentClosed(int magic_number)
{
for(int i=OrdersHistoryTotal();i>=0;i--)
{
if(OrderSelect(i,SELECT_BY_TICKET,MODE_HISTORY)
&& OrderSymbol()==_Symbol
&& OrderMagicNumber() == magic_number
&& OrderCloseTime() > LastOrderCloseTime)
{
for(int x = ARRAYSIZE - 1; x>=0 ; x--)
{
double OrderTICKET = OrderTicket();
if(OrderTICKET == Prev_OrderTicket) continue;
if(OrderTICKET == Array_Orders[x, Arr_orderTICKET])
{
...Add data retrieved at orderclose to the same dataslot in the array
based off OrderTicket() to retrieve at a later date. i.e OrderOpenTime(),
OrderProfit() etc.
}
Prev_OrderTicket = OrderTicket();
LastOrderCloseTime = OrderCloseTime();
}
}
}
Each Magic Number per trade is different but still I cannot pick up more than one trade at a time. Any help would be appreciated.
I have the following code in mql4 and it is partially working but having an issue with order tracking.
int ticket;
void OnTick(){
... not included code, setting variables, etc ...
if(tenkan_sen < kijun_sen){
comment += "\nSHORT!";
if(OrderSelect(ticket,SELECT_BY_TICKET) && OrderType() == OP_BUY){
if(OrderClose(OrderTicket(),OrderLots(),Bid,1000,clrCrimson)){
ticket = 0;
}
}
if(ticket <= 0){
// need to set stoploss and takeprofit prices
double short_tp = current_close - (atr*6);
double short_sl = current_close + (atr*2);
ticket = OrderSend(_Symbol,OP_SELL,0.01,Bid,1000,short_sl,short_tp,"This is a sell",1,0,clrPink);
}
} else if(tenkan_sen > kijun_sen){
comment += "\nLONG!";
if(OrderSelect(ticket,SELECT_BY_TICKET) && OrderType() == OP_SELL){
if(OrderClose(OrderTicket(),OrderLots(),Ask,1000,clrPink)){
ticket = 0;
}
}
if(ticket <= 0){
// need to set stoploss and take profit prices
double long_tp = current_close + (atr*6);
double long_sl = current_close - (atr*2);
ticket = OrderSend(_Symbol,OP_BUY,0.01,Ask,1000,long_sl,long_tp,"This is a buy",1,0,clrCrimson);
}
}
}
This was previously based on the logic of closing the previous position upon opening the last position, it was working as expected before I added the sl and tp values. I am not sure how I should reset the ticket variable to 0 in the event of a sl or tp, or if there is a different way I should be handling this.
I've take a break since I posted this and have read through half of the C programming book I'm studying (Harvard cs50 book). I should be able to solve this by now, yet am unable.
The program runs in a continuous loop, no matter what integer is entered; prints "Good for you..." ad infinitum.
Example code:
//example 3 version2 from chapter 11, beginner programming in c
#include <cs50.h>
#include <stdio.h>
int main ()
{
int prefer;
printf("On a scale from 1 to 10, how happy are you?\n");
scanf(" %d", &prefer);
while(prefer >= 1 || prefer <= 10)
//goal is for program to run while entered int "prefer" is between 1 - 10
if (prefer > 10)
{
printf("Oh really, now? Can't follow simple directions, can you?\n");
printf("want to try that again? 1 through 10...?\n");
scanf(" %d", &prefer);
}
else if (prefer >= 8)
{
printf("Good for you!\n");
}
else if (prefer <= 5)
{
printf("Cheer up : )\n");
}
else if (prefer <= 3)
{
printf("Cheer up, Buttercup!\n");
}
else
{
printf("Get in the RIVER with that attitude!\n");
}
return 0;
}
Operator < and && are binary operators. When we use them, it compares the left and right side values. The above while would look like this.
while(prefer <= 10 && prefer > 0);
There are Bollinger Bands with three RSI running in the basement.
I want to do a check on the signal in such a way that when 3 RSI struck the zone of the upper Bbands, there was a signal down and vice versa:
int start(){
double ma, stdev;
int i, limit, count=IndicatorCounted();
if(count<0) return(0);
limit=Bars-count;
if(limit>1) limit=Bars-1;
for(i=limit; i>=0; i--) {
RSI[i] =iRSI(Symbol(),Period(),rsi_period, PRICE_CLOSE,i);
RSI2[i]=iRSI(Symbol(),Period(),rsi_period_2,PRICE_CLOSE,i);
RSI3[i]=iRSI(Symbol(),Period(),rsi_period_3,PRICE_CLOSE,i);
}
for(i=limit; i>=0; i--) {
ma=iMAOnArray(RSI3,0,bb_period,0,0,i); // midle line
stdev=iStdDevOnArray(RSI3,0,bb_period,0,0,i); // dev
BBUP[i]=ma+bb_dev*stdev; // up line
BBDOWN[i]=ma-bb_dev*stdev; // down line
UP[i]=0;
DOWN[i]=0;
}
if(limit<Bars-1) limit++;
for(i=limit; i>0; i--) {
if(RSI[i] <= BBDOWN[i] && RSI[i+1] > BBDOWN[i+1] && RSI2[i] <= BBDOWN[i] && RSI2[i+1] > BBDOWN[i+1] && RSI3[i] <= BBDOWN[i] && RSI3[i+1] > BBDOWN[i+1]){
DOWN[i] = iLow(_Symbol, _Period, i);
}
if(RSI[i] >= BBUP[i] && RSI[i+1] < BBUP[i+1] &&W RSI2[i] >= BBUP[i] && RSI2[i+1] < BBUP[i+1] && RSI3[i] >= BBUP[i] && RSI3[i+1] < BBUP[i+1]){
UP[i]= iHigh(_Symbol, _Period, i);
}
}
The whole problem is that I have very crooked signals.
Appear where they should not be, and there is no where to be.
THE BEST PRACTICE:
Step 0: Let's first agree in written WHAT is the actual TARGET:
If the TARGET is to compute & paint on GUI the Bollinger Bands on RSI3[] values, the best way to do this is to use:
UPPER[i] = iBandsOnArray( RSI3, // ArrayAsSeries[]
array_calculation_depth, // reduce overheads
BB_MA_period, // BBands period
BB_StDev_MUL, // how many sigmas
BB_Zero_Shift, // #DEFINE BB_Zero_Shift 0
MODE_UPPER, // BBands upper line
i // shifting operator[i]
);
This way one may efficiently produce each of the { MODE_UPPER | MODE_MAIN | MODE_LOWER } Bollinger Bands lines here, consistently generated over dimension-less RSI3[] data, thus protecting the sense of any additive operations in signal-composition(s) with other, dimension-less data, as in { RSI2[], RSI[] }.
Step 1: visually check the lines to validate any signal-conditions:
Given the GUI shows lines accordingly, one may try to compose signal-conditions. The "hot"-bar [0] is a live-bar, where novice may encounter tricking signalling situations, if not handled with due professional care.
Step 2: implement signal-conditions in code:
Only after Step 0) & 1) took place and both meet one's own prior expectations, any code starts to make sense to get built.
From MQL4 docs https://docs.mql4.com/indicators/imaonarray
Unlike iMA(...), the iMAOnArray() function does not take data by
symbol name, timeframe, the applied price. The price data must be
previously prepared. The indicator is calculated from left to right.
To access to the array elements as to a series array (i.e., from right
to left), one has to use the ArraySetAsSeries() function.
RSI3 is currently orientated right to left (0 is most recent time point, limit is furthest element).
Same issue with iStdDevOnArray()
Fix those issues and it should work as you want. Whether there is any value in drawing Bollinger bands on RSI is another matter
Update
The function ArraySetAsSeries() can be used to swap the array between left-to-right and right-to-left
When you first initialise the RSI arrays ( in the OnInit() ) tell MetaTrader Terminal that they are timeseries.
ArraySetAsSeries(RSI1,True);
ArraySetAsSeries(RSI2,True);
ArraySetAsSeries(RSI3,True);
Then in main body, add ArraySetAsSeries(RSI3,False); before your second for loop to swap the array orientation. Then ArraySetAsSeries(RSI3,True); after the loop to restore the array orientation.
for(i=limit; i>=0; i--) {
RSI[i ] = iRSI(Symbol(),Period(),rsi_period,PRICE_CLOSE,i);
RSI2[i] = iRSI(Symbol(),Period(),rsi_period_2,PRICE_CLOSE,i);
RSI3[i] = iRSI(Symbol(),Period(),rsi_period_3,PRICE_CLOSE,i);
}
ArraySetAsSeries(RSI3,False);
for(i=limit; i>=0; i--) {
ma=iMAOnArray(RSI3,0,bb_period,0,0,i); // midle line
stdev=iStdDevOnArray(RSI3,0,bb_period,0,0,i); // dev
BBUP[i]=ma+bb_dev*stdev; // up line
BBDOWN[i]=ma-bb_dev*stdev; // down line
UP[i]=0;
DOWN[i]=0;
}
ArraySetAsSeries(RSI3,True);
if(limit<Bars-1) limit++;
for(i=limit; i>0; i--) {
if( RSI[i] <= BBDOWN[i] &&
RSI[i+1] > BBDOWN[i] &&
RSI2[i] <= BBDOWN[i] &&
RSI2[i+1] > BBDOWN[i] &&
RSI3[i] <= BBDOWN[i] &&
RSI3[i+1] > BBDOWN[i]) {
DOWN[i] = iLow(_Symbol, _Period, i);
}
if( RSI[i] >= BBUP[i] &&
RSI[i+1] < BBUP[i+1] &&
RSI2[i] >= BBUP[i] &&
RSI2[i+1] < BBUP[i+1] &&
RSI3[i] >= BBUP[i] &&
RSI3[i+1] < BBUP[i+1]) {
UP[i]= iHigh(_Symbol, _Period, i);
}
}
Basic indicator structure
You need to go through the MQL4 Documentation and learn the proper structure of an indicator. There needs to be an OnInit() function where you initialise values. Then an OnCalculate() function where you fill the indicator buffers.
//+-----------------------------------------------------------------+
//| Custom indicator initialization function |
//+-----------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
ArraySetAsSeries(RSI3,True);
//---
return(INIT_SUCCEEDED);
}
//+-----------------------------------------------------------------+
//| Custom indicator iteration function |
//+-----------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime& time[],
const double& open[],
const double& high[],
const double& low[],
const double& close[],
const long& tick_volume[],
const long& volume[],
const int& spread[])
{
// Do your calculations here
//--- return value of prev_calculated for next call
return(rates_total);
}
If you use iBandsOnArray() to calculate Bollinger bands you won't need to swap the array direction after it is set in OnInit()
If the indicator is compiling but crashing, you will need to debug it. Simplest way is to look at the errors in the log and add PrintFormat() statements throughout your code so you can see what the indicator is doing at different points and see where it crashes.