Unrealized P&L

Created at 08 May 2013, 16:29
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
TA

tasr1r1

Joined 25.12.2012

Unrealized P&L
08 May 2013, 16:29


Is it possible to develop a robot which can close multiple position based on total current  'Unrealized P&L'?

 

i.e. the bot is running on multile pairs. I would like the bot to close all active trading once the total 'Unrealized P&L' is USD30

 

 

 

 


@tasr1r1
Replies

cAlgo_Fanatic
09 May 2013, 17:04

Yes, given that the currency of your account is in USD. You can calculate the profit of all positions of the account as well as close all positions of the account:

var netProfit = 0.0;

foreach (var openedPosition in Account.Positions)
{
    netProfit += openedPosition.NetProfit;               
}

if(netProfit >= 30.0) 
{
    foreach (var openedPosition in Account.Positions)
    {
        Trade.Close(openedPosition);
    }
}




@cAlgo_Fanatic

tasr1r1
20 May 2013, 14:27

thanks... but i must admit im learning the coding from scratch and cant figure out the error

 

would be great if somebody dont mind to give full coding for the above as start


@tasr1r1

damon153058
21 May 2013, 18:46

How to combine?

        	       var netProfit = 0.0;

foreach (var openedPosition in Account.Positions)
{
    netProfit += openedPosition.NetProfit;               
}

if(netProfit <= 100.0) 
{
    foreach (var openedPosition in Account.Positions)
    {
        Trade.Close(openedPosition);
    }
    Stop(); // Stop the robot
} 
using System;
using cAlgo.API;

namespace cAlgo.Robots
{
    [Robot("Robot Forex")]
    public class RobotForex : Robot
    {
        [Parameter(DefaultValue = 10000, MinValue = 10000)]
        public int FirstLot { get; set; }

		[Parameter("Take_Profit", DefaultValue = 180, MinValue = 10)]
        public int TakeProfit { get; set; }
        
        [Parameter("Tral_Start", DefaultValue = 50)]
        public int Tral_Start { get; set; }
        
        [Parameter("Tral_Stop", DefaultValue = 50)]
        public int Tral_Stop { get; set; }

		[Parameter(DefaultValue = 300)]
        public int PipStep { get; set; }

		[Parameter(DefaultValue = 5, MinValue = 2)]
        public int MaxOrders { get; set; }
        
        private Position position;
		private bool RobotStopped;
		private int LotStep=10000;
		
        protected override void OnStart()
        {
            
        }

        protected override void OnTick()
        {
        double Bid=Symbol.Bid;
        double Ask=Symbol.Ask;
        double Point=Symbol.PointSize;      
        
        	if(Trade.IsExecuting) return;
        	if(Account.Positions.Count > 0 && RobotStopped) return;
        	else RobotStopped = false;

        	if(Account.Positions.Count == 0) 
        		SendFirstOrder(FirstLot);
        	else
        		ControlSeries();
        		
           foreach (var position in Account.Positions)
            {
            	if(position.SymbolCode == Symbol.Code)
            	{
            	
            		if(position.TradeType == TradeType.Buy)	
            		{
            		if (Bid-GetAveragePrice(TradeType.Buy)>=Tral_Start*Point)
            		if (Bid-Tral_Stop*Point>=position.StopLoss)
            		Trade.ModifyPosition(position, Bid-Tral_Stop*Point, position.TakeProfit);
            		}
            			
            		if(position.TradeType == TradeType.Sell)	
            		{
            		if (GetAveragePrice(TradeType.Sell)-Ask>=Tral_Start*Point)
            		if (Ask+Tral_Stop*Point<=position.StopLoss || position.StopLoss==0)
            		Trade.ModifyPosition(position, Ask+Tral_Stop*Point, position.TakeProfit);
            		}
            	}
             }        		
        }

        protected override void OnError(Error CodeOfError)
        {
            if(CodeOfError.Code == ErrorCode.NoMoney)
            {
            	RobotStopped = true;
            	Print("ERROR!!! No money for order open, robot is stopped!");
            }
            else if(CodeOfError.Code == ErrorCode.BadVolume)
            {
            	RobotStopped = true;
            	Print("ERROR!!! Bad volume for order open, robot is stopped!");
            }
        }
        
        private void SendFirstOrder(int OrderVolume)
        {
        	int Signal = GetStdIlanSignal();
        	if(!(Signal < 0))
        		switch(Signal)
        		{
        			case 0:
        				Trade.CreateBuyMarketOrder(Symbol, OrderVolume);
        			break;
        			case 1:
        				Trade.CreateSellMarketOrder(Symbol, OrderVolume);
        			break;
        		}
        }
        
        protected override void OnPositionOpened(Position openedPosition)
        {
			double? StopLossPrice = null;
            double? TakeProfitPrice = null;
			
			if(Account.Positions.Count == 1)
			{
				position = openedPosition;
				if( position.TradeType == TradeType.Buy)
		        	TakeProfitPrice = position.EntryPrice + TakeProfit * Symbol.PointSize;
				if( position.TradeType == TradeType.Sell)
	                TakeProfitPrice = position.EntryPrice - TakeProfit * Symbol.PointSize;
			}
			else
                switch(GetPositionsSide())
                {
                	case 0:
		                TakeProfitPrice = GetAveragePrice(TradeType.Buy) + TakeProfit * Symbol.PointSize;
                	break;
                	case 1:
		                TakeProfitPrice = GetAveragePrice(TradeType.Sell) - TakeProfit * Symbol.PointSize;
                	break;
                }

			for(int i = 0; i < Account.Positions.Count; i++)
        	{
				position = Account.Positions[i];
				if(StopLossPrice != null || TakeProfitPrice != null)
					Trade.ModifyPosition(position, position.StopLoss, TakeProfitPrice);
			}
        }

        private double GetAveragePrice(TradeType TypeOfTrade)
        {
        	double Result = Symbol.Bid;
			double AveragePrice = 0;
  			long Count = 0;

			for(int i = 0; i < Account.Positions.Count; i++)
			{
				position = Account.Positions[i];
				if(position.TradeType == TypeOfTrade)
   				{
   					AveragePrice += position.EntryPrice * position.Volume;
   					Count += position.Volume;
   				}
   			}
  			if(AveragePrice > 0 && Count > 0)
    			Result = AveragePrice / Count;
        	return Result;
        }

        private int GetPositionsSide()
        {
        	int Result = -1;
        	int i, BuySide = 0, SellSide = 0;
        	
        	for(i = 0; i < Account.Positions.Count; i++)
        	{
        		if(Account.Positions[i].TradeType == TradeType.Buy) BuySide++;
        		if(Account.Positions[i].TradeType == TradeType.Sell) SellSide++;
        	}
        	if(BuySide == Account.Positions.Count) Result = 0;
        	if(SellSide == Account.Positions.Count) Result = 1;
        	return Result;
        }
        
        private void ControlSeries()
        {
        	int _pipstep, NewVolume, Rem;
        	int BarCount = 25;
        	int Del = MaxOrders - 1;
        	
        	if(PipStep == 0)
        		_pipstep = GetDynamicPipstep(BarCount, Del);
        	else
        		_pipstep = PipStep;
        	
            if(Account.Positions.Count < MaxOrders)
	            switch(GetPositionsSide())
    	        {
    	          	case 0:
			        	if(Symbol.Ask < FindLastPrice(TradeType.Buy) - _pipstep * Symbol.PointSize)
			        	{
			        		NewVolume = Math.DivRem((int)(FirstLot + FirstLot*Account.Positions.Count), LotStep, out Rem) * LotStep;
    	    				if(!(NewVolume < LotStep))
	    	    				Trade.CreateBuyMarketOrder(Symbol, NewVolume);
			        	}
    	           	break;
    	           	case 1:
			        	if(Symbol.Bid > FindLastPrice(TradeType.Sell) + _pipstep * Symbol.PointSize)
			        	{
			        		NewVolume = Math.DivRem((int)(FirstLot + FirstLot*Account.Positions.Count), LotStep, out Rem) * LotStep;
    	    				if(!(NewVolume < LotStep))
    	    					Trade.CreateSellMarketOrder(Symbol, NewVolume);
			        	}
    	           	break;
    	        }
        }
        
        private int GetDynamicPipstep(int CountOfBars, int Del)
        {
        	int Result;
        	double HighestPrice = 0, LowestPrice = 0;
        	int StartBar = MarketSeries.Close.Count - 2 - CountOfBars;
        	int EndBar = MarketSeries.Close.Count - 2;
        	
        	for(int i = StartBar; i < EndBar; i++)
        	{
        		if(HighestPrice == 0 && LowestPrice == 0)
				{        		
        			HighestPrice = MarketSeries.High[i];
        			LowestPrice = MarketSeries.Low[i];
        			continue;
        		}
        		if(MarketSeries.High[i] > HighestPrice) HighestPrice = MarketSeries.High[i];
        		if(MarketSeries.Low[i] < LowestPrice) LowestPrice = MarketSeries.Low[i];
        	}
        	Result = (int)((HighestPrice - LowestPrice) / Symbol.PointSize / Del);
        	return Result;
        }
        
        private double FindLastPrice(TradeType TypeOfTrade)
        {
			double LastPrice = 0;

			for(int i = 0; i < Account.Positions.Count; i++) 
			{
		        position = Account.Positions[i];
		        if(TypeOfTrade == TradeType.Buy)
		        	if(position.TradeType == TypeOfTrade) 
          			{
	           			if(LastPrice == 0)
	           			{
	           				LastPrice = position.EntryPrice;
	           				continue;
	           			}
            			if(position.EntryPrice < LastPrice)
              				LastPrice = position.EntryPrice;
          			}
		        if(TypeOfTrade == TradeType.Sell)
		        	if(position.TradeType == TypeOfTrade) 
          			{
	           			if(LastPrice == 0)
	           			{
	           				LastPrice = position.EntryPrice;
	           				continue;
	           			}
            			if(position.EntryPrice > LastPrice)
              				LastPrice = position.EntryPrice;
          			}
          	}
          	return LastPrice;
        }
        
        private int GetStdIlanSignal()
        {
        	int Result = -1;
        	int LastBarIndex = MarketSeries.Close.Count - 2;
        	int PrevBarIndex = LastBarIndex - 1;
        	
        	if(MarketSeries.Close[LastBarIndex] > MarketSeries.Open[LastBarIndex])
				if(MarketSeries.Close[PrevBarIndex] > MarketSeries.Open[PrevBarIndex])
					Result = 0;
        	if(MarketSeries.Close[LastBarIndex] < MarketSeries.Open[LastBarIndex])
				if(MarketSeries.Close[PrevBarIndex] < MarketSeries.Open[PrevBarIndex])
					Result = 1;
        	return Result;
        }
    }
}





@damon153058

cAlgo_Fanatic
22 May 2013, 17:41

RE:
tasr1r1 said:

thanks... but i must admit im learning the coding from scratch and cant figure out the error

 

would be great if somebody dont mind to give full coding for the above as start

You can post the error message and we will help you out with the code.


@cAlgo_Fanatic

cAlgo_Fanatic
22 May 2013, 17:43

To combine the above code, place the first in the OnTick event of the second.


@cAlgo_Fanatic

damon153058
22 May 2013, 18:28

RE:
cAlgo_Fanatic said:

To combine the above code, place the first in the OnTick event of the second.

I still do not know how to combine two kinds of code?

Please help


@damon153058

cAlgo_Fanatic
23 May 2013, 09:23

In cAlgo click on New in the Robots list. A new code file will be created in the text editor with some initial code.  You need to copy and paste the code provided in the second post in the OnTick method where it says:

        protected override void OnTick()
        {
            // Put your core logic here
        }

Paste the code within the curly brackets {}.

Please see these help pages to get started:

http://help.spotware.com/calgo

http://help.spotware.com/calgo/cbots/create-edit

http://help.spotware.com/calgo/videos


@cAlgo_Fanatic

damon153058
23 May 2013, 10:27

RE:
cAlgo_Fanatic said:

In cAlgo click on New in the Robots list. A new code file will be created in the text editor with some initial code.  You need to copy and paste the code provided in the second post in the OnTick method where it says:

        protected override void OnTick()
        {
            // Put your core logic here
        }

Paste the code within the curly brackets {}.

Please see these help pages to get started:

http://help.spotware.com/calgo

http://help.spotware.com/calgo/cbots/create-edit

http://help.spotware.com/calgo/videos

You misunderstood what I meant

I need to insert in my program, both for


@damon153058

valizario
11 Jun 2013, 20:41

Please help!

Hi. Thanks a lot for this topic!

It really helped me. The robot works very well. It closes multiple positions based on total current  'Unrealized P&L'.

But please help - what command should I add to the code so the robot also cancel all stop orders left???

 

Thank you


@valizario

cAlgo_Fanatic
12 Jun 2013, 10:05

RE: Please help!
valizario said:

Hi. Thanks a lot for this topic!

It really helped me. The robot works very well. It closes multiple positions based on total current  'Unrealized P&L'.

But please help - what command should I add to the code so the robot also cancel all stop orders left???

 

Thank you

To delete pending orders you can loop through Account.PendingOrders in a similar way and delete.

foreach (var pendingOrder in Account.PendingOrders)
{
    Trade.DeletePendingOrder(pendingOrder);
}




@cAlgo_Fanatic

7023423
09 Aug 2013, 08:41

RE:

cAlgo_Fanatic said:

Yes, given that the currency of your account is in USD. You can calculate the profit of all positions of the account as well as close all positions of the account:

var netProfit = 0.0;

foreach (var openedPosition in Account.Positions)
{
    netProfit += openedPosition.NetProfit;               
}

if(netProfit >= 30.0) 
{
    foreach (var openedPosition in Account.Positions)
    {
        Trade.Close(openedPosition);
    }
}


 

Hi cAlgo Fanatic,

I saw this conversation and it works good, but due to the commission which will be applied after the close, final netProfit amount becomes less than what I set up.

So how can I solve this problem by applying the commission on the exit?

Thank you for your help in advance.


@7023423

cAlgo_Fanatic
09 Aug 2013, 11:59

RE: RE:


Hi cAlgo Fanatic,

I saw this conversation and it works good, but due to the commission which will be applied after the close, final netProfit amount becomes less than what I set up.

So how can I solve this problem by applying the commission on the exit?

Thank you for your help in advance.

Please clarify your question. The net profit is equal to the gross profit minus the commission.

If you like to close the positions on the event that the robot stops you can add the code to the OnStop() method.


@cAlgo_Fanatic

7023423
09 Aug 2013, 19:02

RE: RE: RE:

cAlgo_Fanatic said:


Hi cAlgo Fanatic,

I saw this conversation and it works good, but due to the commission which will be applied after the close, final netProfit amount becomes less than what I set up.

So how can I solve this problem by applying the commission on the exit?

Thank you for your help in advance.

Please clarify your question. The net profit is equal to the gross profit minus the commission.

If you like to close the positions on the event that the robot stops you can add the code to the OnStop() method.

I mean for example if(netProfit >= 30.0) if I setup like this, robot close all opened position when total sum of unrealized P&L equal or greater than $30.

so I expected to have $30 net profit, but because of the commission when robot close the position, my actual net profit becomes $30 minus one side commission(closing).

I think unrealized P&L does already deduct the commission when I open the position(one side), but not including the upcoming commission from the closing the trades.

Thank you,


@7023423

cAlgo_Fanatic
13 Aug 2013, 09:21

You need to change the code in the foreach loop to this: 

netProfit += openedPosition.NetProfit + openedPosition.Commissions;

 


@cAlgo_Fanatic

7023423
14 Aug 2013, 12:12

RE:

cAlgo_Fanatic said:

You need to change the code in the foreach loop to this: 

netProfit += openedPosition.NetProfit + openedPosition.Commissions;

 

Hi cAlgo Fanatic,

Thank you for the reply and I changed the code 

netProfit += openedPosition.NetProfit; --> netProfit += openedPosition.NetProfit + openedPosition.Commissions;

but then result was even worse than before. If I setup to close all positions when my unrealized P&L equal or greater than $100, my actual net profit after the closing all my positions, it becomes $100 minus my full commission(round trip commission),

Is it because commission is negative number?

It will be great if you can help me again.

Thank you.


@7023423

cAlgo_Fanatic
14 Aug 2013, 15:42

Could you give an example of what you need?

 

 

 


@cAlgo_Fanatic

7023423
15 Aug 2013, 02:21

RE:

cAlgo_Fanatic said:

Could you give an example of what you need?

Hi cAlgo Fanatic,

I want to close all my multiple open positions all together at the same time when my total unrealized P&L meets my profit or stop loss targets.

For example, when I open or have 100k EUR/USD buy, 100k GBP/USD buy, and 100K USD/JPY sell now, I want to close all of my open positions when unrealized P&L from all three positions become either $300 or -$300.

Below is my coding, but below coding is only for the profit target and also when I setup for $300 for example, my net profit after the closing becomes $300 minus one side commissions.

It will be great if you can add the function for the stop loss target and solve the commission issue.

Thank you so much for your help.

 

using System;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Requests;
using cAlgo.Indicators;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC)]
    public class AAC : Robot
    {
        protected override void OnStart()
        {
            // Put your initialization logic here
        }
        protected override void OnTick()
        {
            var netProfit = 0.0;
foreach (var openedPosition in Account.Positions)
{
    netProfit += openedPosition.NetProfit;              
}
if(netProfit >= 300.0) 
{
    foreach (var openedPosition in Account.Positions)
    {
        Trade.Close(openedPosition);
    }
}
        }
        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}


@7023423

cAlgo_Fanatic
16 Aug 2013, 16:04 ( Updated at: 21 Dec 2023, 09:20 )

When the number circled in red, which is equal to the net profit minus the commission (23.16 -15 =11.16) will be greater than 300 or less than -300, then the position will close.

protected override void OnTick()
{
    var netProfit = 0.0;
    foreach (var openedPosition in Account.Positions)
    {
        netProfit += openedPosition.NetProfit + openedPosition.Commissions;
    }
    ChartObjects.DrawText("a", netProfit.ToString(), StaticPosition.BottomLeft);
    if (Math.Abs(netProfit) >= 300.0)
    {
        foreach (var openedPosition in Account.Positions)
        {
            Trade.Close(openedPosition);
        }
    }
}

 


@cAlgo_Fanatic

7023423
22 Aug 2013, 12:04 ( Updated at: 21 Dec 2023, 09:20 )

RE:

cAlgo_Fanatic said:

When the number circled in red, which is equal to the net profit minus the commission (23.16 -15 =11.16) will be greater than 300 or less than -300, then the position will close.

protected override void OnTick()
{
    var netProfit = 0.0;
    foreach (var openedPosition in Account.Positions)
    {
        netProfit += openedPosition.NetProfit + openedPosition.Commissions;
    }
    ChartObjects.DrawText("a", netProfit.ToString(), StaticPosition.BottomLeft);
    if (Math.Abs(netProfit) >= 300.0)
    {
        foreach (var openedPosition in Account.Positions)
        {
            Trade.Close(openedPosition);
        }
    }
}

 

Hi cAlgo Support,

Thank you for the reply. This one works perfect.

Just one more question (or request), what if I want to set up different amount for the profit side and stop loss side?

I simply added one more if phrase....if (NetProfit <= -200) but didn't work.

Please help me.


@7023423

tradermatrix
22 Aug 2013, 16:32 ( Updated at: 21 Dec 2023, 09:20 )

RE: RE:

coolutm said:

cAlgo_Fanatic said:

When the number circled in red, which is equal to the net profit minus the commission (23.16 -15 =11.16) will be greater than 300 or less than -300, then the position will close.

protected override void OnTick()
{
    var netProfit = 0.0;
    foreach (var openedPosition in Account.Positions)
    {
        netProfit += openedPosition.NetProfit + openedPosition.Commissions;
    }
    ChartObjects.DrawText("a", netProfit.ToString(), StaticPosition.BottomLeft);
    if (Math.Abs(netProfit) >= 300.0)
    {
        foreach (var openedPosition in Account.Positions)
        {
            Trade.Close(openedPosition);
        }
    }
}

 

Hi cAlgo Support,

Thank you for the reply. This one works perfect.

Just one more question (or request), what if I want to set up different amount for the profit side and stop loss side?

I simply added one more if phrase....if (NetProfit <= -200) but didn't work.

Please help me.

{
            var netProfit = 0.0;
            foreach (var openedPosition in Account.Positions)
            {
                netProfit += openedPosition.NetProfit + openedPosition.Commissions;
            }
            ChartObjects.DrawText("a", netProfit.ToString(), StaticPosition.BottomLeft);
            if ((Math.Abs(netProfit) >= 200.0) || (Math.Abs(netProfit) <= -200))
            {
                foreach (var openedPosition in Account.Positions)
                {
                    Trade.Close(openedPosition);
                }
            }
        }


@tradermatrix

tradermatrix
22 Aug 2013, 17:16

excusez moi ,mais il me semble que cette méthode est plus juste:

   protected override void OnTick()
        {
            var netProfit = 0.0;
            foreach (var openedPosition in Account.Positions)
            {
                netProfit += openedPosition.NetProfit + openedPosition.Commissions;
            }
            ChartObjects.DrawText("a", netProfit.ToString(), StaticPosition.BottomLeft);
            {
                if (Account.Equity - Account.Balance > 300 || Account.Equity - Account.Balance < - 200)
                {
                    foreach (var position in Account.Positions)
                    {
                        Trade.Close(position);
                    }
                }
            }
        }
    }
}
 

 


@tradermatrix

atrader
29 Aug 2013, 15:41 ( Updated at: 21 Dec 2023, 09:20 )

RE: RE: RE:

tradermatrix said:

coolutm said:

cAlgo_Fanatic said:

When the number circled in red, which is equal to the net profit minus the commission (23.16 -15 =11.16) will be greater than 300 or less than -300, then the position will close.

protected override void OnTick()
{
    var netProfit = 0.0;
    foreach (var openedPosition in Account.Positions)
    {
        netProfit += openedPosition.NetProfit + openedPosition.Commissions;
    }
    ChartObjects.DrawText("a", netProfit.ToString(), StaticPosition.BottomLeft);
    if (Math.Abs(netProfit) >= 300.0)
    {
        foreach (var openedPosition in Account.Positions)
        {
            Trade.Close(openedPosition);
        }
    }
}

 

Hi cAlgo Support,

Thank you for the reply. This one works perfect.

Just one more question (or request), what if I want to set up different amount for the profit side and stop loss side?

I simply added one more if phrase....if (NetProfit <= -200) but didn't work.

Please help me.

{
            var netProfit = 0.0;
            foreach (var openedPosition in Account.Positions)
            {
                netProfit += openedPosition.NetProfit + openedPosition.Commissions;
            }
            ChartObjects.DrawText("a", netProfit.ToString(), StaticPosition.BottomLeft);
            if ((Math.Abs(netProfit) >= 200.0) || (Math.Abs(netProfit) <= -200))
            {
                foreach (var openedPosition in Account.Positions)
                {
                    Trade.Close(openedPosition);
                }
            }
        }

Math.Abs() means the absolute or positive value. Therefore the second part of the condition 

 if ((Math.Abs(netProfit) >= 200.0) || (Math.Abs(netProfit) <= -200))

will always be false.

 

 


@atrader

cAlgo_Fanatic
29 Aug 2013, 15:52

RE: RE:

coolutm said:

 Support,

Thank you for the reply. This one works perfect.

Just one more question (or request), what if I want to set up different amount for the profit side and stop loss side?

I simply added one more if phrase....if (NetProfit <= -200) but didn't work.

Please help me.

 if ( netProfit >= 300.0) || netProfit <= -200 )

 


@cAlgo_Fanatic

renerpz
18 Sep 2014, 23:06

RE: Please help!

hello friend can  you send me the code already modify i ve been having problems with the errors  ill appreciate the help  

Hi. Thanks a lot for this topic!

It really helped me. The robot works very well. It closes multiple positions based on total current  'Unrealized P&L'.

But please help - what command should I add to the code so the robot also cancel all stop orders left???

 

Thank you

 


@renerpz