how to track take profit and stoploss in mql4 - mql4

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.

Related

Why Buy order is not placed when calculated Stoploss and Take profit are used

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]);

Can't retrieve data when two or more trades either open or close simultaneously

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.

TypeError: Indexed expression has to be a type, mapping or array (is function (uint16) returns (uint256))?

Full source:https://github.com/laronlineworld/bettingMatch/blob/main/bettingMatch.sol This is a Betting Smart Contract, trying to create a mapping structure that user/wallet_address can bet on multiple matches. The problem of this betting contract is every time the user/wallet_address place a bet, the data of single mapping overwrite, how to create a mapping of value so that user/wallet_address can bet on different matches.
Place bet function:
function bet(uint16 _matchSelected, uint16 _resultSelected) public payable {
require(matchBettingActive[_matchSelected], "Betting: match voting is disabled");
//Check if the player already exist
// require(!checkIfPlayerExists(msg.sender));
//Check if the value sended by the player is higher than the min value
require(msg.value >= minimumBet);
//Set the player informations : amount of the bet, match and result selected
playerInfo[msg.sender].amountBet = msg.value;
playerInfo[msg.sender].matchSelected = _matchSelected;
playerInfo[msg.sender].resultSelected = _resultSelected;
//Add the address of the player to the players array
players.push(msg.sender);
MatchID[] storage bets = matchDetails[_matchSelected];
bets.push(MatchID(msg.sender, _matchSelected, msg.value, _resultSelected))-1;
uint16[] storage userBets = userToBets[msg.sender];
userBets.push[_matchSelected];
//Finally increment the stakes of the team selected with the player bet
if ( _resultSelected == 1){
totalBetHome[_matchSelected] += msg.value;
}
else if( _resultSelected == 2){
totalBetAway[_matchSelected] += msg.value;
}
else{
totalBetDraw[_matchSelected] += msg.value;
}
also need to sync the data in reward distribution depending of matchID distribution function:
function distributePrizes(uint16 matchFinished, uint16 teamWinner) public onlyOwner {
address[1000] memory winners;
//Temporary in memory array with fixed size. Let's choose 1000
uint256 count = 0; // This is the count for the array of winners
uint256 loserBet = 0; //This will take the value of all losers bet
uint256 winnerBet = 0; //This will take the value of all winners bet
address add;
uint256 bets;
address playerAddress;
//Check who selected the winner team
for(uint256 i = 0; i < players.length; i++){
playerAddress = players[i];
//If the player selected the winner team, we add his address to the winners array
if(playerInfo[playerAddress].matchSelected == matchFinished &&
playerInfo[playerAddress].resultSelected == teamWinner){
winners[count] = playerAddress;
count++;
}
}
//We define which bet sum is the Loser one and which one is the winner
if ( teamWinner == 1){
loserBet = totalBetAway[matchFinished] + totalBetDraw[matchFinished];
winnerBet = totalBetHome[matchFinished];
}
else if ( teamWinner == 2){
loserBet = totalBetHome[matchFinished] + totalBetDraw[matchFinished];
winnerBet = totalBetAway[matchFinished];
}
else{
loserBet = totalBetHome[matchFinished] + totalBetAway[matchFinished];
winnerBet = totalBetDraw[matchFinished];
}
//We loop through the array of winners, to give ethers to the winners
for(uint256 j = 0; j < count; j++){
//Check that the address in this fixed array is not empty
if(winners[j] != address(0))
add = winners[j];
bets = playerInfo[add].amountBet;
uint256 amountToPlayer = (bets * (10000+(loserBet*devFee/winnerBet))) / 10000;
winners[j].transfer(amountToPlayer);
}
//Reset all variables
delete playerInfo[playerAddress];
players.length = 0;
loserBet = 0;
winnerBet = 0;
//10 will be the number of matches (To improve this)
for(uint256 k = 0; k < 10; k++){
totalBetHome[k] = 0;
totalBetAway[k] = 0;
totalBetDraw[k] = 0;
}
}

How do i calculate all the profit for a certain day?

double CheckProfitSofar()
{
datetime today = iTime(_Symbol,PERIOD_D1,0);
int dDay=TimeDay(today);
int dMonth = TimeMonth(today);
int dYear = TimeYear(today);
int todayYear, todayMonth, todayDay;
datetime opnOrdTime = 0;
double opnOrdProfit =0;
double addLoss = 0;
for(int s=0 ; s<OrdersHistoryTotal(); s++)
{
if ( OrderSelect( s, SELECT_BY_POS, MODE_HISTORY ) == true )
opnOrdTime = OrderCloseTime();
todayYear=TimeYear(opnOrdTime);
todayMonth =TimeMonth(opnOrdTime);
todayDay=TimeDay(opnOrdTime);
if ( dYear==todayYear && dMonth==todayMonth && dDay==todayDay )
totalLoss_Profit += (OrderProfit() + OrderSwap() + OrderCommission());
}
Comment(dYear," ",dMonth," ",dDay," ",todayYear," ",todayMonth," ",todayDay);
return totalLoss_Profit;
}
What i want to is that i want to calculate the profit (whether +ve or -ve) for a particular day. e.g today. i used the "datetime today" to get the opening time of the first candle of today, then follows. It is not returning the accurate value. Please help out. Thanks in advance.
You just need start of that particular day received by datetime timeStart = iTime(_Symbol,PERIOD_D1,i) and end of that day datetime timeEnd=timeStart+PeriodSeconds(PERIOD_D1);. Then loop over closed deals and filter them out if OrderClosePrice() is not in range.
double getClosedPnlOfDay(const int indexDay)
{
const datetime timeStart=iTime(_Symbol,PERIOD_D1,i),
timeEnd = timeStart+PeriodSeconds(PERIOD_D1);
double result=0.;
for(int i=OrdersHistoryTotal()-1;i>=0;i--)
{
if(!OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))continue;
//filter by OrderSymbol() and OrderMagicNumber() here
if(OrderCloseTime()<timeStart || OrderCloseTime()>=timeEnd) continue;
result+=OrderProfit() + OrderCommission() + OrderSwap();
}
}

Why wont my MQL4 EA code change my open positions to breakeven?

Trying to add a StopLoss to my open market positions which also takes into account my brokers stoplevel. I have set this to add a breakeven stop loss when my trade gets to 100 points in profit.
This is the code - but its completely ignoring any order modification during my back testing.
OK this is now what I have so far, one for loop for the buy, one for the sell. I;ve also declared the "BuyMod" & "SellMod" to true as was suggested in pervious answers, as well as Normalzing prices in the OrderModify signature.
/*Breakeven Order Modification*/
bool BuyMod = true;
bool SellMod = true;
for(int b = OrdersTotal()-1;b>=0;b--)
{
if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
{
double aBidPrice = MarketInfo(Symbol(),MODE_BID);
double anOpenPrice = OrderOpenPrice();
double aNewTpPrice = OrderTakeProfit();
double aCurrentSL = OrderStopLoss();
double aNewSLPrice = anOpenPrice;
double pnlPoints = (aBidPrice - anOpenPrice)/_Point;
double stopPoints = (aBidPrice - aNewSLPrice)/_Point;
int stopLevel = int(MarketInfo(Symbol(),MODE_STOPLEVEL));
int aTicket = OrderTicket();
if(OrderType() == OP_BUY)
if(stopPoints >= stopLevel)
if(aTicket > 0)
if(pnlPoints >= breakeven)
if(aNewSLPrice != aCurrentSL)
{
BuyMod = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(aNewSLPrice,Digits),NormalizeDouble(aNewTpPrice,Digits),0,buycolor);
SendMail("Notification of Order Modification for Ticket#"+IntegerToString(OrderTicket(),10),"Good news! Order Ticket#"+IntegerToString(OrderTicket(),10)+"has been changed to breakeven");
}
}
}
for(int s = OrdersTotal()-1; s>=0; s--)
{
if(OrderSelect(s,SELECT_BY_POS,MODE_TRADES))
{
double anAskPrice = MarketInfo(Symbol(),MODE_ASK);
double anOpenPrice = OrderOpenPrice();
double aNewTpPrice = OrderTakeProfit();
double aCurrentSL = OrderStopLoss();
double aNewSLPrice = anOpenPrice;
double pnlPoints = (anOpenPrice - anAskPrice)/_Point;
double stopPoints = (aNewSLPrice - anAskPrice)/_Point;
int stopLevel = int(MarketInfo(Symbol(),MODE_STOPLEVEL));
int aTicket = OrderTicket();
if(OrderType()== OP_SELL)
if(stopPoints >= stopLevel)
if(pnlPoints >= breakeven)
if(aNewSLPrice != aCurrentSL)
if(aTicket > 0)
{
SellMod = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(aNewSLPrice,Digits),NormalizeDouble(aNewTpPrice,Digits),0,sellcolor);
SendMail("Notification of Order Modification for Ticket#"+IntegerToString(OrderTicket(),10),"Good news! Order Ticket#"+IntegerToString(OrderTicket(),10)+"has been changed to breakeven");
}
}
}
This code will not work due to several reasons:
First:The function-call signature of OrderModify() is wrong.
You might want to know, that OrderModify() call-signature requires as per MQL4 documentation to include also an OrderExpiration value in the call, even though the Order is currently not a pending order any more.
Check the documentation and the IDE tooltip, which helps one remind the order of the function call parameters.
Second:The other, less-visible reasons could be reported by GetLastError() after the OrderModify() function call returns a False as an indication of failure.

Resources