I want to create a function that can get random profit open position.
For example :
a profit of the Last 2 Open Position of overall Total Position
a profit of the First 3 Open Position of overall Total Position
Below function seems it only gets the First Open Position Profit :
double BuyProfit()
{
Price = 0;
datetime EarliestOrder = TimeCurrent();
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS))
{
if(OrderType() == OP_BUY && OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if(EarliestOrder > OrderOpenTime())
{
EarliestOrder = OrderOpenTime();
Price = OrderProfit()+OrderSwap()+OrderCommission();
}
}
}
}
return Price;
}
Q : "How to get a profit of Nth open position MQL4/MT4?I want to create a function that can get random profit open position."
You may take this rapid-prototype to complete your actual logic code:
double nthNetPROFIT( const int Nth ) {
if ( Nth > OrdersTotal() ) return( EMPTY );
int softCount = 0;
double nthNetProfit = EMPTY;,
for( int ii = 0; ii < OrdersTotal(); ii++ ) {
if ( OrderSelect( ii, SELECT_BY_POS ) ) {
if ( OrderType() == OP_BUY // DEPENDS ON ACTUAL LOGIC
&& OrderSymbol() == Symbol() // DEPENDS ON ACTUAL LOGIC
&& OrderMagicNumber() == MagicNumber // DEPENDS ON ACTUAL LOGIC
) {
... // DEPENDS ON ACTUAL LOGIC
if ( ++softCount == Nth ){
nthNetProfit = OrderProfit()
+ OrderSwap()
+ OrderCommission();
break;
}
}
}
return( NormalizeDouble( nthNetProfit, 2 ) );
}
Related
The following code works if it's attached to only a single pair, but if the EA is attached to multiple pairs, it also counts the result of cross pair and results in the wrong alert.
The idea of the following code is to decide if the attached pair has the last two trade ends positively. It should not count the other pair result from the history.
void Alert_if_the_last_two_ordes_for_same_pair_was_positive()
{
double profit = 0;
int orderId = -1;
datetime lastCloseTime = 0;
int cnt = OrdersHistoryTotal();
for(int i=0; i < cnt; i++)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
continue;
orderId = OrderMagicNumber();
if(OrderSymbol() == Symbol() && lastCloseTime < OrderCloseTime() && orderId == 114)
{
lastCloseTime = OrderCloseTime();
profit = OrderProfit();
}
}
double profit1 = 0;
int orderId1 = -1;
datetime lastCloseTime1 = 0;
int cnt1 = OrdersHistoryTotal()-1;
for(int i1=0; i1 < cnt1; i1++)
{
if(!OrderSelect(i1, SELECT_BY_POS, MODE_HISTORY))
continue;
orderId1 = OrderMagicNumber();
if(OrderSymbol() == Symbol() && lastCloseTime1 < OrderCloseTime() && orderId1 == 114)
{
lastCloseTime1 = OrderCloseTime();
profit1 = OrderProfit();
}
}
double profit2 = 0;
int orderId2 = -1;
datetime lastCloseTime2 = 0;
int cnt2 = OrdersHistoryTotal()-2;
for(int i2=0; i2 < cnt2; i2++)
{
if(!OrderSelect(i2, SELECT_BY_POS, MODE_HISTORY))
continue;
orderId2 = OrderMagicNumber();
if(OrderSymbol() == Symbol() && lastCloseTime2 < OrderCloseTime() && orderId2 == 114)
{
lastCloseTime2 = OrderCloseTime();
profit2 = OrderProfit();
}
}
if(profit > 0 && profit1 > 0 )
{
Alert(" profit > 0 && profit1 = up for " + Symbol());
}
I am trying to create a method that will link all Cell objects set up in a 2D array named CellGrid[,]
My question is: Since most of the code in SetDirection() is so similar, it seem there is a better way to achieve my goal.
(Side note: This is functional but the execution feels "off" )
private void SetDirection()
{
int x = 0, y = 0;
for ( int i = 0 ; i < Size * (Size - 1);)//setting all UP pointers
{
if ( i == 0 ) { x = 0; y = 1;}//initial setup
for ( x = 0 ; x < Size ; x++ )
{
CellGrid[x,y].SetPointer(CellGrid[x,y-1] , Direction.Up );
i++;
}
y++;
}
for ( int i = 0 ; i < Size * (Size - 1);) //setting all DOWN pointers
{
if ( i == 0 ) { x = 0; y = 0;}//initial setup
for ( x = 0 ; x < Size ; x++ )
{
CellGrid[x,y].SetPointer(CellGrid[x,y+1], Direction.Down);
i++;
}
y++;
}
for ( int i = 0 ; i < Size * (Size - 1);)//setting all LEFT pointers
{
if ( i == 0 ) { x = 1; y = 0;}//initial setup
for ( y = 0 ; y < Size ; y++ )
{
CellGrid[x, y].SetPointer( CellGrid[x-1,y], Direction.Left);
i++;
}
x++;
}
for ( int i = 0 ; i < Size * (Size - 1);) //setting all RIGHT pointers
{
if ( i == 0 ) { x = 0; y = 0;}//initial setup
for ( y = 0 ; y < Size ; y++ )
{
CellGrid[x, y].SetPointer( CellGrid[x+1,y], Direction.Right);
i++;
}
x++;
}
}
public void SetPointer( Cell cellRef ,GridBuilder.Direction dir)
{
switch ( dir )
{
case GridBuilder.Direction.Up:
this.Up = cellRef;
break;
case GridBuilder.Direction.Down:
this.Down = cellRef;
break;
case GridBuilder.Direction.Left:
this.Left = cellRef;
break;
case GridBuilder.Direction.Right:
this.Right = cellRef;
break;
}
}
You can indeed use one set of loops to make the links in all four directions. This is based on two ideas:
When setting a link, immediately set the link in the opposite direction between the same two cells.
When setting a link, immediately set the link between the two cells that are located in the mirrored positions -- mirrored by the main diagonal (x <--> y).
private void SetDirection() {
for (int i = 1; i < Size; i++) {
for (int j = 0; j < Size; j++) {
CellGrid[i, j].SetPointer(CellGrid[i-1, j], Direction.Left);
CellGrid[i-1, j].SetPointer(CellGrid[i, j], Direction.Right);
CellGrid[j, i].SetPointer(CellGrid[j, i-1], Direction.Up);
CellGrid[j, i-1].SetPointer(CellGrid[j, i], Direction.Down);
}
}
}
I want to find the pinbars circled in the attached image below. For the one on the right, the body is about 1/5th of the candle size and for the one on the left, let's say the body is 1/7th the size candle size and it also has a wick of 1/7th the candle size at the bottom. How can I use the iOpen(), iLow() and other similar functions to find these two types of pinbars?
Q : How can I use the iOpen(), iLow() and other similar functions to find these two types of pinbars?
May use a working template like this WasThisTheUserDefinedBearishPATTERN() function and having defined all your user-specific conditions and constants, just call if ( WasThisTheUserDefinedBearishPATTERN( aShift, 4.5, 0.1, 2000 ) ) { do_something(); } when using it for trading:
bool WasThisTheUserDefinedBearishPATTERN( const int aBarNUMBER,
const double aBody2uWICK_MUL,
const double min_FRACTION,
const double MAX_FRACTION
) {
// BAR-UPPER-wick:
double aBarUpWK = ( iHigh( _Symbol, PERIOD_CURRENT, aBarNUMBER )
- iClose( _Symbol, PERIOD_CURRENT, aBarNUMBER )
);
// BAR-body:
double aBarBODY = ( iClose( _Symbol, PERIOD_CURRENT, aBarNUMBER )
- iOpen( _Symbol, PERIOD_CURRENT, aBarNUMBER )
);
// BAR-LOWER-wick:
double aBarLoWK = ( iLow( _Symbol, PERIOD_CURRENT, aBarNUMBER )
- iClose( _Symbol, PERIOD_CURRENT, aBarNUMBER )
);
// FLAG:
bool aBearishFLAG = FALSE;
// -----------------------------------------------------------------
// USER-DEFINE-ABLE SET OF SHAPE-CONDITIONS ..... = add all that apply
// BEARISH BODY:
// has body
// has body BEARISH
// has body not more than about a lo-wick size * < min_FRACTION, MAX_FRACTION >
// has body not less than about a hi-wick size * _MUL
// -------------
if ( aBarBODY >= 0 // not BEARISH
|| aBarUpWK < aBarBODY * aBody2uWICK_MUL // not long enough UpperWICK
){
aBearishFLAG = FALSE; // (NO)
}
else { if ( aBarBODY < 0 // has BEARISH CANDLE
&& ( aBarLoWK == 0 // and may LO-WICK ZERO
|| ( aBarLoWk / aBarBODY > min_FRACTION // .GT. min-WICK-2-BODY-FRACTION
&& aBarLoWk / aBarBODY < MAX_FRACTION // .LT. MAX-WICK-2-BODY-FRACTION
)
)
){ aBearishFLAG = TRUE; } // (YES)
else { aBearishFLAG = FALSE; } // ( NO) OTHERWISE
}
return( aBearishFLAG );
}
Ex-post :
I did WasThisTheUserDefinedBearishPATTERN( aShift, 1, 1/6, 2/6 ) and was expecting it to result in something...
Besides the comment below, kindly also respect The Rules of the World of MQL4 language:
Print( "DIV( 1 / 7 ) == ", 1 / 7 ); // will show you The Rules
Print( "DIV( 1. / 7. ) == ", 1. / 7. ); // will show you The Rules
So the way I would approach this is as follows:
1) What are the characteristics of each candle I am trying to define?
a) Down or up (I prefer 1 or -1)
b) Large rejection tail relative to the body
c) Large rejection tail relative to the non-rejection tail
d) Small body relative to the rejection tail
2) How do we code this in MQL4 using predefined functions?
Let's first make a few assumptions...
First, you are wanting to define these candles in real-time so you can execute when they form.
Second, let's go off the M30 for any given Symbol().
The below function (not tested) will return a 1 when there is a buy signal, and a -1 for a sell signal, and 0 if no signal. You will need to adjust the extern variables accordingly as this is more of a science than a "one-size-fits-all". Also, you might need to use IsNewBar.
//the values below should sum to 100
extern int RTail_To_Range_Ratio = 80; //rejection tail ratio to range of candle
extern int Body_To_Range_Ratio = 10; //body size ratio to range of candle
extern int NRTail_To_Range_Ratio = 10; //non-rejection tail ratio to range of candle
int Signal()
{
//candle information
double dOpen = iOpen(Symbol(),PERIOD_M30,0);
double dHigh = iHigh(Symbol(),PERIOD_M30,0);
double dLow = iLow(Symbol(),PERIOD_M30,0);
double dClose = iClose(Symbol(),PERIOD_M30,0);
double dBody = MathAbs(dOpen - dClose);
double dRange = dHigh - dLow;
double dRTail = 0, dTail = 0;
//green candle
if(dClose > dOPen){
dRTail = dOPen - dLow;
dTail = dHigh - dClose;
//now check ratios
if((dTail / dRange) <= (NRTail_To_Range_Ratio / 100) && (dBody / dRange) <= (Body_To_Range_Ratio / 100) && (dRTail / dRange) >= (RTail_To_Range_Ratio / 100)){
return 1;
}
}
//red candle
else{
dRTail = dHigh - dOpen;
dTail = dClose - dLow;
//now check ratios
if((dTail / dRange) <= (NRTail_To_Range_Ratio / 100) && (dBody / dRange) <= (Body_To_Range_Ratio / 100) && (dRTail / dRange) >= (RTail_To_Range_Ratio / 100)){
return -1;
}
}
return 0;
}
Let me know if this solves your problem #SuperHueman.
I have written the code below that opens a buy and sell trade (a certain number of pips above and below the ask and bid price) at a specific time.
How can I close/cancel one immediately when the other is opened?
How can I close the opened trade if it's say X pips in profit or after a minute (depending on which condition is reached first)?
I'm a not too sure I've done the right thing in the code below and would really appreciate some help.
double spread = Ask-Bid;
extern datetime time;
extern int pipGap = 7;
extern int lotSize = 0.01;
extern int closeTimeInSeconds = 60;
int start() {
if (TimeCurrent() >= StrToTime(time)){
OrderSend(Symbol(),OP_BUYSTOP,lotSize, Ask + Point*pipGap, 0,0,0);
OrderSend(Symbol(),OP_SELLSTOP,lotSize, Bid - Point*pipGap, 0,0,0);
}
for(int pos = OrdersTotal()-1; pos >= 0 ; pos--) if (
OrderSelect(pos, SELECT_BY_POS)
){
int duration = TimeCurrent() - OrderOpenTime();
if (duration >= closeTimeInSeconds)
OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(),
3*Point);
}
return(0);
}
AUTOMATED NEWS TRADING
What you (#iGetIt ) are looking for is a rudimentary News Trading bot. Here's a diluted implementation for it.
In the more advanced stages, you will need to automatically download news and auto-trade base on the affected pairs, track volatility (to avoid swings), sync your PC time (Windows date/time is NOT accurate and news trading need to be synced to the millisecond level). Track your broker server response time, implement Trailing-StopLoss (for improved profit), implement slide-in-orders (multiple stop orders to catch huge spikes), calculate order-set profitability (to know when to close all the orders when price retrace), etc etc.
Anyway, here's a basic version that you can play with (based on the Bounty requirements):
Opens buy + sell stop-orders at specific time.
Configurable number of pips AWAY from current ask/bid.
Implements OCO (One Cancels the Other).
Closes executed trades with x-pip profit (aka TP level).
Closes executed or outstanding stop-orders after x-seconds.
Visual: To show that it executes in time (this is Asian time, so liquidity is low, so +- a few seconds before price ticks).
Closing: It closes automatically based on the settings.
SOURCE CODE: And this is the complete MQL4 source-code for it.
(UPDATED 15May19 1045 GMT+8) to fix bug as reported in the closing of executed orders after TTL.
//+------------------------------------------------------------------+
//| SO55930471.mq4 |
//| Copyright 2019, Joseph Lee, joseph.lee#fs.com.my |
//| TELEGRAM #JosephLee74 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, Joseph Lee, TELEGRAM #JosephLee74"
#property link "http://www.fs.com.my"
#property version "1.00"
#property strict
//-------------------------------------------------------------------
// APPLICABLE PARAMETERS
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// NEWS IMPACT SELECTION
//===================================================================
extern string vsEAComment = "Telegram #JosephLee74"; //Ego trip
extern datetime vdTradeStartInGMT = D'2019.5.14 06:00'; //When to trade (GMT)
extern int viStopOrderLevelInPip = 5; // StopOrder distance from ask/bid (pips)
extern double viFixLots = 0.01; // Lot size
extern int viStopLossInPip = 20; // StopLoss (pips)
extern int viTargetProfitInPip = 100; // TargetProfit (pips)
extern int viDeleteStopOrderAfterInSec = 30; // StopOrder TTL (sec)
extern int viDeleteOpenOrderAfterInSec = 300; // Executed Order TTL (sec)
extern int viMaxSlippageInPip = 2; // Max Slippage (pip)
//-------------------------------------------------------------------
// System Variables
//-------------------------------------------------------------------
int viMagicId = 0;
double viPipsToPrice = 0.0001;
double viPipsToPoint = 1;
int viBuyStopTicket = -1;
int viSellStopTicket = -1;
int viBuyOrderTicket = -1;
int viSellOrderTicket = -1;
string vsDisplay = "EVENT-TRADER v1.01 - ";
//-------------------------------------------------------------------
//+------------------------------------------------------------------+
//| EA Initialization function
//+------------------------------------------------------------------+
int init() {
ObjectsDeleteAll(); Comment("");
// Caclulate PipsToPrice & PipsToPoints (old sytle, but works)
if((Digits == 2) || (Digits == 3)) {viPipsToPrice=0.01;}
if((Digits == 3) || (Digits == 5)) {viPipsToPoint=10;}
viMagicId = vdTradeStartInGMT;
start();
return(0);
}
//+------------------------------------------------------------------+
//| EA Stand-Down function
//+------------------------------------------------------------------+
int deinit() {
ObjectsDeleteAll();
return(0);
}
//============================================================
// MAIN EA ROUTINE
//============================================================
int start() {
//==========================================
//MANAGE ROBOT EXPIRY
//==========================================
if( TimeCurrent() > D'2020.1.1' ) {
Comment(vsDisplay + "EXPIRED. Please contact josephfhlee74 at gmail dot com"); // Who am I kidding?
return(0);
}
ResetLastError();
// Exit the routine if it is not time to trade yet.
if(TimeGMT() < vdTradeStartInGMT) {
// Show a count-down timer to the trading time.
Comment(vsDisplay +
"[" + TimeToStr(TimeGMT()) + " GMT] " +
IntegerToString(int(vdTradeStartInGMT - TimeGMT())) + " sec to [" +
TimeToStr(vdTradeStartInGMT) + " GMT]"
);
return(0);
}
viBuyStopTicket = -1;
viSellStopTicket = -1;
viBuyOrderTicket = -1;
viSellOrderTicket = -1;
//=========================================================
//FIND *OPENED* BUY/SELL PENDING ORDERS
//---------------------------------------------------------
for( int i=OrdersTotal()-1; i>=0; i-- ) {
if(OrderSelect( i, SELECT_BY_POS, MODE_TRADES ))
if( OrderSymbol() == Symbol() )
if( OrderMagicNumber() == viMagicId) {
if( OrderType() == OP_BUYSTOP )
viBuyStopTicket = OrderTicket();
if( OrderType() == OP_SELLSTOP )
viSellStopTicket = OrderTicket();
if( OrderType() == OP_BUY )
viBuyOrderTicket = OrderTicket();
if( OrderType() == OP_SELL )
viSellOrderTicket = OrderTicket();
}
}
//=========================================================
//FIND *CLOSED* BUY/SELL ORDERS FOR THIS EVENT
//---------------------------------------------------------
for(int i=OrdersHistoryTotal()-1; i>=0; i--) {
if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
if(OrderSymbol() == Symbol())
if(OrderMagicNumber() == viMagicId) {
if( OrderType() == OP_BUYSTOP )
viBuyStopTicket = OrderTicket();
if( OrderType() == OP_SELLSTOP )
viSellStopTicket = OrderTicket();
if( OrderType() == OP_BUY )
viBuyOrderTicket = OrderTicket();
if( OrderType() == OP_SELL )
viSellOrderTicket = OrderTicket();
}
}
// The above 2 sections will ensure that each event will only be executed once.
// If orders are cancelled or closed for whatever reason, they will never be open again.
string vsVerbose = vsDisplay + "[GMT " + TimeToStr(TimeGMT()) + "] Executing ..."
"\nActive BUYSTOP: " + viBuyStopTicket +
" | Active SELLSTOP: " + viSellStopTicket +
"" +
"\nActive BUY: " + viBuyOrderTicket +
" | Active SELL: " + viSellOrderTicket;
Comment(vsVerbose);
//=========================================================
// HANDLES OCO (One-Cancels-the-Other)
//---------------------------------------------------------
// BUY Order EXISTS, cancels all SellStops
if( viBuyOrderTicket != -1 ) {
for( int i=OrdersTotal()-1; i>=0; i-- ) {
if(OrderSelect( i, SELECT_BY_POS, MODE_TRADES ))
if( OrderSymbol() == Symbol() )
if( OrderMagicNumber() == viMagicId)
if( OrderType() == OP_SELLSTOP )
OrderDelete(OrderTicket());
}
}
// SELL Order EXISTS, cancels all BuyStops
if( viSellOrderTicket != -1 ) {
for( int i=OrdersTotal()-1; i>=0; i-- ) {
if(OrderSelect( i, SELECT_BY_POS, MODE_TRADES ))
if( OrderSymbol() == Symbol() )
if( OrderMagicNumber() == viMagicId)
if( OrderType() == OP_BUYSTOP )
OrderDelete(OrderTicket());
}
}
//=========================================================
//CLOSE EXPIRED STOP/EXECUTED ORDERS
//---------------------------------------------------------
for( int i=OrdersTotal()-1; i>=0; i-- ) {
if(OrderSelect( i, SELECT_BY_POS, MODE_TRADES ))
if( OrderSymbol() == Symbol() )
if( OrderMagicNumber() == viMagicId) {
if( (OrderType() == OP_BUYSTOP) || (OrderType() == OP_SELLSTOP) )
if((TimeCurrent()-OrderOpenTime()) >= viDeleteStopOrderAfterInSec)
OrderDelete(OrderTicket());
if( (OrderType() == OP_BUY) || (OrderType() == OP_SELL) )
if((TimeCurrent()-OrderOpenTime()) >= viDeleteOpenOrderAfterInSec) {
// For executed orders, need to close them
double closePrice = 0;
RefreshRates();
if(OrderType() == OP_BUY)
closePrice = Bid;
if(OrderType() == OP_SELL)
closePrice = Ask;
OrderClose(OrderTicket(), OrderLots(), closePrice, int(viMaxSlippageInPip*viPipsToPoint), clrWhite);
}
}
}
//===================================================================
//OPEN STOP ORDERS IF NO EXISTING nor CLOSED NO BUY/SELL STOP/ORDERS
//-------------------------------------------------------------------
// Do NOT execute (place new orders) if it is past the trading window.
if(TimeGMT() >= (vdTradeStartInGMT+viDeleteStopOrderAfterInSec))
{
Comment(vsDisplay + "[" + TimeToStr(TimeGMT()) + " GMT] " + "Already passed execution time.");
return(0);
}
// Place BuyStop if not exists; and no executed-Buy order
if( (viBuyStopTicket == -1) && (viBuyOrderTicket == -1)) {
RefreshRates();
viFixLots = NormalizeDouble(viFixLots, 2);
double viPrice = NormalizeDouble(Ask + (viStopOrderLevelInPip*viPipsToPrice), Digits);
double viSL = viPrice - (viStopLossInPip*viPipsToPrice);
double viTP = viPrice + (viTargetProfitInPip*viPipsToPrice);
viBuyStopTicket = OrderSend(Symbol(), OP_BUYSTOP, viFixLots
, viPrice
, int(viMaxSlippageInPip*viPipsToPoint)
, viSL, viTP
, vsEAComment, viMagicId, 0, Blue);
if(viBuyStopTicket == -1)
Print("Error executing BuyStop [" + IntegerToString(GetLastError()) + "]." );
}
// Place SellStop if not exists; and no executed-Sell order
if( (viSellStopTicket == -1) && (viSellOrderTicket == -1) ) {
RefreshRates();
viFixLots = NormalizeDouble(viFixLots, 2);
double viPrice = NormalizeDouble(Bid - (viStopOrderLevelInPip*viPipsToPrice), Digits);
double viSL = viPrice + (viStopLossInPip*viPipsToPrice);
double viTP = viPrice - (viTargetProfitInPip*viPipsToPrice);
viSellStopTicket = OrderSend(Symbol(), OP_SELLSTOP, viFixLots
, viPrice
, int(viMaxSlippageInPip*viPipsToPoint)
, viSL, viTP
, vsEAComment, viMagicId, 0, Red);
if(viSellStopTicket == -1)
Print("Error executing SellStop [" + IntegerToString(GetLastError()) + "]." );
}
return(0);
}
#property strict
//---
input datetime InpTime1=D'2019.05.01 00:00'; //time to enter the trade, just as an example
input double InpPipsDist=10; //distance in pips to place BS&SS OCO-orders
input int InpCloseSeconds=60; //close time, seconds since main order is sent
input double InpProfitPips=1.; //profit in pips to close all.
input double InpLotSize=0.1; //lot size
input int InpMagicNumber=123456789; //magic number
// ---
#include <Arrays\ArrayObj.mqh>
bool firstOrderOpen;
double PIP;
CArrayObj *ordersList;
// ---
class C2Orders : public CObject
{
private:
int m_ticket1;
int m_ticket2;
datetime m_timeStart;//OrderOpenTime of the two tickets might be different,TimeCurrent() is used as time they are open.
bool m_activated;
void checkTicket(const int ticket) //if one order is open, another is deleted.
{
if(ticket>0 && OrderSelect(ticket,SELECT_BY_TICKET))
{
if(OrderType()<=OP_SELL)
{
if(ticket==m_ticket1)
{
if(OrderDelete(m_ticket2))
printf("%i: failed to delete#%d. error=%d",__LINE__,m_ticket2,_LastError);
m_ticket2=-1;
}
else
{
if(!OrderDelete(m_ticket1))
printf("%i: failed to delete#%d. error=%d",__LINE__,m_ticket1,_LastError);
m_ticket1=-1;
}
m_activated=true;
}
}
}
double getPnlPips(const int ticket)const
{
if(ticket>0 && OrderSelect(ticket,SELECT_BY_TICKET))
{
return (OrderProfit()>0 ? 1 : -1)*fabs(OrderOpenPrice()-OrderClosePrice());
}
return 0;
}
bool try2closeByPnl()const
{
const double pnl=getPnlPips(m_ticket1)+getPnlPips(m_ticket2);
if(pnl-InpProfitPips*PIP>0)
{
printf("%i : pnl=%.5f vs %.5f target. closing the tickets",__LINE__,pnl,InpProfitPips*PIP);
close(m_ticket1);
close(m_ticket2);
return(true);
}
return(false);
}
bool try2closeByTime()const
{
if(TimeCurrent()-m_timeStart-InpCloseSeconds>=0)
{
if(!OrderDelete(m_ticket1))printf("%i: failed to delete#%d. error=%d",__LINE__,m_ticket1,_LastError);
if(!OrderDelete(m_ticket2))printf("%i: failed to delete#%d. error=%d",__LINE__,m_ticket2,_LastError);
return(true);
}
return(false);
}
void close(const int ticket)const
{
if(ticket>0 && OrderSelect(ticket,SELECT_BY_TICKET))
{
RefreshRates();
if(OrderClose(ticket,OrderLots(),OrderClosePrice(),1))
printf("%i: failed to close#%d. error=%d",__LINE__,ticket,_LastError);
}
}
public:
C2Orders(const int ticket1,const int ticket2,const datetime time):
m_ticket1(ticket1),m_ticket2(ticket2),m_activated(false),m_timeStart(time){}
~C2Orders(){}
bool check() //returns FALSE if deleting the object
{
if(!m_activated)
{
checkTicket(m_ticket1);
checkTicket(m_ticket2);
}
if(m_activated)
{
if(try2closeByPnl())
return(false);
}
else
{
if(try2closeByTime())
return(false);
}
return true;
}
};
//+------------------------------------------------------------------+
int OnInit()
{
firstOrderOpen=false;
PIP=_Point*(_Digits%2==1 ? 10 : 1); //does not work for GOLD and indexes, good for FX.
ordersList=new CArrayObj();
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
delete(ordersList);
}
void OnTick()
{
if(!firstOrderOpen && TimeCurrent()>=InpTime1)
{
RefreshRates();
const int ticketBS=OrderSend(_Symbol,OP_BUYSTOP,InpLotSize,NormalizeDouble(Ask+InpPipsDist*PIP,_Digits),0,0,0,NULL,InpMagicNumber);
const int ticketSS=OrderSend(_Symbol,OP_SELLSTOP,InpLotSize,NormalizeDouble(Bid-InpPipsDist*PIP,_Digits),0,0,0,NULL,InpMagicNumber);
C2Orders *oco=new C2Orders(ticketBS,ticketSS,TimeCurrent());
ordersList.Add(oco);
firstOrderOpen=true;
}
if(firstOrderOpen)
{
C2Orders* oco;
for(int i=ordersList.Total()-1;i>=0;i--)//of course you have only one instance, but in real world you may need to loop over them.
{
oco=ordersList.At(i);
if(!oco.check())
ordersList.Delete(i);
}
if(ordersList.Total()==0)
ExpertRemove();//just to finish the test faster.
}
}
I'm using this code to check if orders are existing for the price buy1 and sell1 in my code.
Somehow some orders get executed twice.
Shouldn't happen because i'm checking if there is any open order with the same takeprofit.
Anyone able to see whats wrong?
bool CheckBuyOrder1(double buy1_tp){
for( int i = 0 ; i < OrdersTotal() - 1 ; i++ ) {
OrderSelect( i, SELECT_BY_POS, MODE_TRADES );
if( OrderTakeProfit() == buy1_tp && OrderComment() == "buy" )
return(true);
}
return(false);
}
bool CheckSellOrder1(double sell1_tp){
for( int i = 0 ; i < OrdersTotal() - 1 ; i++ ) {
OrderSelect( i, SELECT_BY_POS, MODE_TRADES );
if( OrderTakeProfit() == sell1_tp && OrderComment() == "sell" )
return(true);
}
return(false);
}
int totalOrders = OrdersTotal();
void OnTick()
{
if(totalOrders != OrdersTotal()){
double vbid = MarketInfo("EURUSD",MODE_BID);
double bid = NormalizeDouble(vbid, 3);
double market_buy_tp = bid;
double buy1= bid + 0.002;
double buy1_tp= bid + 0.003;
if(CheckOpenOrders1(market_buy_tp)==false && CheckBuyOrder1(buy1_tp)==false){
int ticket9=OrderSend(Symbol(),OP_BUYSTOP,Lots,buy1,MaxSlippage,0,buy1_tp,"buy",16380,0,clrGreen);
}
double market_sell_tp = bid;
double sell1 = bid - 0.003;
double sell1_tp= bid - 0.004;
if(CheckOpenOrdersSell1(market_sell_tp)==false && CheckSellOrder1(sell1_tp)==false ){
int ticket19=OrderSend(Symbol(),OP_SELLSTOP,Lots,sell1,MaxSlippage,0,sell1_tp,"sell",16380,0,clrGreen);
}
totalOrders = OrdersTotal();
}}
Whenever you try to compare an OrderTakeProfit() value with some other double - keep in mind rounding and float representation.
E.g. if you need to compare 0.10 with another double that you believe is 0.10 - you might be surprised that 0.10 is 0.09(9)6 or 0.10(0)4
That is why sometimes you might not find such an order.
double o = Point / 2; // initialize in OnInit(), declare in global vars
...
bool CheckOrderBuy( double tp ){
for ( int i = OrdersTotal() - 1; i >= 0; i-- ){
if ( !OrderSelect( i, SELECT_BY_POS ) )continue;
if ( fabs( OrderTakeProfit() - tp ) < o
&& OrderType() == OP_BUY
) return true;
}
return false;
}