Select positions only by symbol in thread-safe mode

Created at 18 Feb 2019, 00:40
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!
HE

helex93

Joined 30.08.2018

Select positions only by symbol in thread-safe mode
18 Feb 2019, 00:40


Hello,

Is there any possibility to select positions directly from Positions interface only by symbol code in thread-safe? (without copying to another list)


@helex93
Replies

PanagiotisCharalampous
18 Feb 2019, 11:39

Hi Igor,

Is this what you are looking for?

Positions.Where(x => x.SymbolCode == "EURUSD")

Best Regards,

Panagiotis


@PanagiotisCharalampous

helex93
18 Feb 2019, 12:34

No, because it is not thread-safe method.

According to https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.where linq Where method using IEnumerable, and according to cAlgo.API metadata -  Positions interface is IEnumerable

IEnumerable - not thread-safe, same problem with foreach.

Main problem -  avoid the Exception: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.

It occurs, when cBot enumeate Positions collection, and simultaneously - one or many positions is closing (for example by TakeProfit limit)


@helex93

PanagiotisCharalampous
18 Feb 2019, 12:39

Hi Igor,

If you explain to us what are you trying to do, we might be able to help you. You can use a for loop for example but I do not know what is the problem you are trying to solve.

Best Regards,

Panagiotis


@PanagiotisCharalampous

afhacker
18 Feb 2019, 12:53

RE:

helex93 said:

No, because it is not thread-safe method.

According to https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.where linq Where method using IEnumerable, and according to cAlgo.API metadata -  Positions interface is IEnumerable

IEnumerable - not thread-safe, same problem with foreach.

Main problem -  avoid the Exception: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.

It occurs, when cBot enumeate Positions collection, and simultaneously - one or many positions is closing (for example by TakeProfit limit)

You can use the lock statement or build your own thread-safe positoins collection by using  .Net thread safe collections.


@afhacker

helex93
18 Feb 2019, 14:14

RE:

Panagiotis Charalampous said:

Hi Igor,

If you explain to us what are you trying to do, we might be able to help you. You can use a for loop for example but I do not know what is the problem you are trying to solve.

Best Regards,

Panagiotis

 

Code example, where i commented, what i trying to do:

 

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Collections.Generic;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Sample_cbot : Robot
    {

        SortedSet<Position> PositionsList = new SortedSet<Position>(new PositionComparer());
        TradeResult tradeResult;
        string Label_OpenedByCbot, Label_OpenedByHand;


        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        
        protected override void OnStart()
        {
            Label_OpenedByCbot = Symbol.Code;
            Label_OpenedByHand = "";

            for (int i = 0; i < 2; i++)
            {
                tradeResult = ExecuteMarketOrder(TradeType.Buy, Symbol, 1000, Symbol.Code);

                if (tradeResult.IsSuccessful)
                {
                    PositionsList.Add(tradeResult.Position);
                }
            }

        }

        protected override void OnTick()
        {
            // Im trying to make FAST check of positions id lists equality (thread-safe)


            // --------------- fast way - NOT thread-safe sample:
            if (Enumerable.SequenceEqual(Positions.Where(p => p.SymbolCode == Symbol.Code).Select(pos => pos.Id).ToList(), PositionsList.Select(pos => pos.Id).ToList()))
            {
                // my code
            }


            // --------------- slow way - thread-safe sample:
            var CbotPositions = Positions.FindAll(Label_OpenedByCbot, Symbol).ToList(); // making copy to new list
            var HandPositions = Positions.FindAll(Label_OpenedByHand, Symbol).ToList(); // making copy to new list

            CbotPositions.AddRange(HandPositions);
            CbotPositions.Sort((x, y) => DateTime.Compare(x.EntryTime, y.EntryTime));

            if (Enumerable.SequenceEqual(CbotPositions.Select(pos => pos.Id).ToList(), PositionsList.Select(pos => pos.Id).ToList()))
            {
                // my code
            }

        }

        protected override void OnStop()
        {
        }
    }

    public class PositionComparer : IComparer<Position>
    {
        public int Compare(Position x, Position y)
        {
            return x.EntryTime.CompareTo(y.EntryTime);
        }
    }
}

 


@helex93

helex93
18 Feb 2019, 14:28

RE: RE:

afhacker said:

helex93 said:

No, because it is not thread-safe method.

According to https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.where linq Where method using IEnumerable, and according to cAlgo.API metadata -  Positions interface is IEnumerable

IEnumerable - not thread-safe, same problem with foreach.

Main problem -  avoid the Exception: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.

It occurs, when cBot enumeate Positions collection, and simultaneously - one or many positions is closing (for example by TakeProfit limit)

You can use the lock statement or build your own thread-safe positoins collection by using  .Net thread safe collections.

 

Thank you for advice, but I think it will not help in my case.


@helex93