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