Closing one position seems to close them all with same Symbol

Created at 01 Nov 2019, 10:15
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!
FI

firemyst

Joined 26.03.2019

Closing one position seems to close them all with same Symbol
01 Nov 2019, 10:15


I've encountered an issue with cTrader where closing a position with a specific label seems to close all positions.

Example code below which reproduces the issue.

Why is every position closed when we explicitly look for positions with the specific label and trade type?

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

    /// <summary>
    /// Add 2 instances of this bot in cTrader with the Ger30 symbol. Put both instances in the M1 time frame.
    /// In one instance, select "Sell" for the parameter; for the other instance, select "Buy".
    /// Start both instances.
    /// Look at the log. Two different position labels.
    /// Now in the TradeWatch window, click the close "X" button next to the bottom-most listed position.
    /// Both positions get closed!
    /// This is NOT expected behaviour since we only close one position and expecially search for historical trades on the specific trade type and label.
    /// </summary>

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class BugBot : Robot
    {
        [Parameter("Trade Type", Group = "Trade Settings", DefaultValue = TradeType.Sell)]
        public TradeType TradeTypeForBot { get; set; }

        private string _positionLabel = "Bug bot";

        protected override void OnStart()
        {
            Positions.Closed += Positions_Closed;

            _positionLabel += TradeTypeForBot;
            Print("OnStart: Starting \"{0}\"", _positionLabel);
            TradeResult r = ExecuteMarketOrder(TradeTypeForBot, Symbol.Name, 0.1, _positionLabel, 10, null, null, false);
        }

        /// <summary>
        /// Runs when a position is closed.
        /// </summary>
        /// <param name="args"></param>
        private void Positions_Closed(PositionClosedEventArgs args)
        {
                Position p1 = args.Position;
            //Search for the specific label and trade type of this position so we don't close similar ones.
                HistoricalTrade ht = History.FindLast(p1.Label, Symbol.Name, p1.TradeType);

                if (!String.IsNullOrEmpty(p1.Label) && ht != null)
                {
                    double cp = ht.ClosingPrice;

                    Print("Closed: Position \"{0} {1}\" closed for reason {2} with {3} profit. Entry Price {4}, Closing Price {5}, StopLoss {6}", p1.Id, p1.Label, args.Reason, String.Format("{0:$#,###.00}", p1.GrossProfit), p1.EntryPrice, cp, p1.StopLoss);

                    //Close off all open positions.
                    //Make sure to only close those positions for the current Label/Symbol. 
                    foreach (Position p in Positions.FindAll(_positionLabel, Symbol.Name))
                    {
                        ClosePositionAsync(p, (TradeResult r) =>
                        {
                            if (r.IsSuccessful)
                            {
                                Print("Closed: Closed position \"{0} {1}\".", p.Id, p.Label);
                            }
                            else if (!r.IsSuccessful)
                            {
                                Print("Closed: ### WARNING! Could not close position \"{0} {1}\"!", p.Id, p.Label);
                                Print("Closed: Error message: {0}", r.Error.Value);
                            }
                        });
                    }
                    Stop();
                    return;
                }
        }

    }
}

.

 

 


@firemyst
Replies

PanagiotisCharalampous
01 Nov 2019, 11:46

Hi FireMyst,

You should add a condition in Positions_Closed to be executed only when the closed position has the same same label as _positionLabel. Else the method will be executed when positions from other instances are closed, eventually closing all positions of the account.

Best Regards,

Panagiotis


@PanagiotisCharalampous

firemyst
01 Nov 2019, 14:14

RE:

Panagiotis Charalampous said:

Hi FireMyst,

You should add a condition in Positions_Closed to be executed only when the closed position has the same same label as _positionLabel. Else the method will be executed when positions from other instances are closed, eventually closing all positions of the account.

Best Regards,

Panagiotis

Hi @Panagiotis:

I do that don't I?

Line 56.

I only get the historical position that has the same label, symbol, and tradetype as the position that was closed.

I then check to make sure it's found (eg, the historical trade isn't null).

The next if statement on line #58 will only evaluate to true if the exact matching historical trade is found.

So to me it looks like it's finding everything under the symbol, regardless of the label. Otherwise, HT would be null.

?


@firemyst

PanagiotisCharalampous
01 Nov 2019, 14:45

Hi FireMyst,

You do not check anywhere if the closed position was actually created by this instance. So if it has been created by another instance on the same symbol then the positions of this instance will be closed as well.

Best Regards,

Panagiotis


@PanagiotisCharalampous

firemyst
01 Nov 2019, 15:48

RE:

Panagiotis Charalampous said:

Hi FireMyst,

You do not check anywhere if the closed position was actually created by this instance. So if it has been created by another instance on the same symbol then the positions of this instance will be closed as well.

Best Regards,

Panagiotis

Thanks!

I found the bug thanks to your feedback. I had to change the foreach loop to the following, replacing _positionLabel with p1.Label:

foreach (Position p in Positions.FindAll(p1.Label, Symbol.Name))
{ /... }

 

 


@firemyst

PanagiotisCharalampous
01 Nov 2019, 15:54

Hi FireMyst, 

Indeed that solves the issue but in a weird way :)  What I would have done would be to exit the method if the closed position was not created by this instance. See below

        private void Positions_Closed(PositionClosedEventArgs args)
        {
                Position p1 = args.Position; 
                if(p1.Label != _positionLabel) 
                   return;

Best Regards,

Panagiotis

 

 


@PanagiotisCharalampous

firemyst
01 Nov 2019, 16:03

RE:

Panagiotis Charalampous said:

Hi FireMyst, 

Indeed that solves the issue but in a weird way :)  What I would havedone would be to exit the method if the closed position was not created by this instance. See below

        private void Positions_Closed(PositionClosedEventArgs args)
        {
                Position p1 = args.Position; 
                if(p1.Label != _positionLabel) 
                   return;

Best Regards,

Panagiotis

 

 

Nice one. I like it. I'm going to use it. Thanks! :-)


@firemyst