Select positions only by symbol in thread-safe mode
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)
Replies
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
PanagiotisCharalampous
18 Feb 2019, 11:39
Hi Igor,
Is this what you are looking for?
Best Regards,
Panagiotis
@PanagiotisCharalampous