Create Opposite position after certain pips

Created at 25 Oct 2021, 14:28
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!
VE

velu130486

Joined 08.11.2019 Blocked

Create Opposite position after certain pips
25 Oct 2021, 14:28


Dear All,

I am not a developer, however I am learning Cbot coding based on the sample bots available in this forum. I have Cbot which opens the order based on buy or sell signal similar to Grid Bot and the stop loss is calculated based on ATR, 15 M timeframe.

My question is how to create the opposite order when the position pip is more than -5 ATR value

For ex I have 0.02 Lot EURUSD Sell position open, once the position pips are more than -5 ATR I would like to create a opposite Order (i.e.) 0.02 Lot EURUSD Buy Position

 protected override void OnBar()
        {
                createopposite();
        }       
void createopposite()
        {
            foreach (var pos in Positions)
            {
                var sym = pos.SymbolName;
                var type = pos.TradeType;
                var cmd = pos.Comment;
                var ov = pos.VolumeInUnits;
                double atr = ATR[sym].Result.LastValue;

                if (type == TradeType.Buy && pos.Pips <= -5 * atr)
                {
                    ExecuteMarketOrder(TradeType.Sell, sym, ov, "EA", 0, 0, "Opposite");
                }
                if (type == TradeType.Sell && pos.Pips <= -5 * atr)
                {
                    ExecuteMarketOrder(TradeType.Buy, sym, ov, "EA", 0, 0, "Opposite");
                }
            }
        }

I created the above function, however in the backtesting it creates multiple "opposite" position and that makes my Ctrader window crash. So could you please support to modify the function create a 1 opposite position whenever the position pips more than -5 ATR

Thanks and Regards

R. Vadivelan


Replies

amusleh
26 Oct 2021, 09:15

Hi,

You should use OnTick not OnBar, and the issue with your code is that you are opening multiple opposite positions for a single position, try this:

using System;
using System.Linq;
using cAlgo.API;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        protected override void OnTick()
        {
            CreateOpposite();
        }

        private void CreateOpposite()
        {
            var positionsCopy = Positions.ToArray();

            foreach (var pos in positionsCopy)
            {
                var comment = string.Format("Opposite_{0}", pos.Id);

                if (Positions.Any(position => string.Equals(position.Comment, comment, StringComparison.OrdinalIgnoreCase)))
                {
                    continue;
                }

                var sym = pos.SymbolName;
                var type = pos.TradeType;
                var cmd = pos.Comment;
                var ov = pos.VolumeInUnits;
                double atr = ATR[sym].Result.LastValue;

                if (type == TradeType.Buy && pos.Pips <= -5 * atr)
                {
                    ExecuteMarketOrder(TradeType.Sell, sym, ov, "EA", 0, 0, comment);
                }
                if (type == TradeType.Sell && pos.Pips <= -5 * atr)
                {
                    ExecuteMarketOrder(TradeType.Buy, sym, ov, "EA", 0, 0, comment);
                }
            }
        }
    }
}

I use comment to prevent opening multiple opposite positions for a single position, each position will have only one opposite position.


@amusleh

velu130486
26 Oct 2021, 09:58 ( Updated at: 21 Dec 2023, 09:22 )

RE:

Hi Ahmad,

Thanks for your quick reply and I try your code in backtest but still lot of positions are opened as below picture.

Could you please help to fix it.

Thanks and Regards

R. Vadivelan

amusleh said:

Hi,

You should use OnTick not OnBar, and the issue with your code is that you are opening multiple opposite positions for a single position, try this:

using System;
using System.Linq;
using cAlgo.API;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        protected override void OnTick()
        {
            CreateOpposite();
        }

        private void CreateOpposite()
        {
            var positionsCopy = Positions.ToArray();

            foreach (var pos in positionsCopy)
            {
                var comment = string.Format("Opposite_{0}", pos.Id);

                if (Positions.Any(position => string.Equals(position.Comment, comment, StringComparison.OrdinalIgnoreCase)))
                {
                    continue;
                }

                var sym = pos.SymbolName;
                var type = pos.TradeType;
                var cmd = pos.Comment;
                var ov = pos.VolumeInUnits;
                double atr = ATR[sym].Result.LastValue;

                if (type == TradeType.Buy && pos.Pips <= -5 * atr)
                {
                    ExecuteMarketOrder(TradeType.Sell, sym, ov, "EA", 0, 0, comment);
                }
                if (type == TradeType.Sell && pos.Pips <= -5 * atr)
                {
                    ExecuteMarketOrder(TradeType.Buy, sym, ov, "EA", 0, 0, comment);
                }
            }
        }
    }
}

I use comment to prevent opening multiple opposite positions for a single position, each position will have only one opposite position.

 


amusleh
27 Oct 2021, 08:20

Hi,

The code I posted opens an opposite position for each of your bot positions based on given condition.

What do you mean by lots of positions? do you want to set a maximum position number?

If you can tell us what exactly you want to implement on your cBot then I will be able to help you.


@amusleh

velu130486
27 Oct 2021, 09:24 ( Updated at: 27 Oct 2021, 10:28 )

RE:

Hi Ahmad,

Sorry I made the mistake in ATR Calculation, after fixed it your code works fine. Thanks for your support.

Since you said earlier we can't modify the comment after the position is opened, how to match the original position and opposite position.

For ex in original position comment is blank, whereus the opposite position we have comment "Opposite_XX", How to match these 2 positions.

Another question is Once the opposite position is created for, I would like to modify the position to increase or decrease volume to maintain the proper hedging.

 

Thanks and Regards

R. Vadivelan

amusleh said:

Hi,

The code I posted opens an opposite position for each of your bot positions based on given condition.

What do you mean by lots of positions? do you want to set a maximum position number?

If you can tell us what exactly you want to implement on your cBot then I will be able to help you.

 


amusleh
27 Oct 2021, 11:56

Hi,

The original position ID is on the comment of opposite position, so you can match them by using the opposite position comment and the original position ID.

To get original position ID from opposite position you can split its comment with "_", the second value will be ID, then parse the ID with long.Parse and then you can compare it with original position ID for matching.

            foreach (var pos in positionsCopy)
            {
				// if position comment is empty then skip it
				if (string.IsNullOrWhiteSpace(pos.Comment)) continue;
				
				var commentSplit = pos.Comment.Split('_');
				
				if (commentSplit.Length < 2) continue;
				
				var originalPositionIdString = commentSplit[1];
				
				long originalPositionId;
				
				if (!long.TryParse(originalPositionIdString, out originalPositionId)) continue;
				
				var originalPosition = Positions.FirstOrDefault(position => position.Id == originalPositionId);
				
				if (originalPosition == null) continue;
				
				// Now you have the original position on originalPosition variable
            }

 


@amusleh

velu130486
27 Oct 2021, 13:13

RE:

Thanks Ahmad for your immediate support and it is very much appreciated.

I will try to work around based on your coding.

Thanks and Regards

R. Vadivelan

amusleh said:

Hi,

The original position ID is on the comment of opposite position, so you can match them by using the opposite position comment and the original position ID.

To get original position ID from opposite position you can split its comment with "_", the second value will be ID, then parse the ID with long.Parse and then you can compare it with original position ID for matching.

            foreach (var pos in positionsCopy)
            {
				// if position comment is empty then skip it
				if (string.IsNullOrWhiteSpace(pos.Comment)) continue;
				
				var commentSplit = pos.Comment.Split('_');
				
				if (commentSplit.Length < 2) continue;
				
				var originalPositionIdString = commentSplit[1];
				
				long originalPositionId;
				
				if (!long.TryParse(originalPositionIdString, out originalPositionId)) continue;
				
				var originalPosition = Positions.FirstOrDefault(position => position.Id == originalPositionId);
				
				if (originalPosition == null) continue;
				
				// Now you have the original position on originalPosition variable
            }