/// <summary> /// To calculate trade profitability. If the trade was already processed earlier, previous information returns. /// </summary> /// <param name="trade">Trade.</param> /// <returns>Information on new trade.</returns> public PnLInfo Process(ExecutionMessage trade) { if (trade == null) { throw new ArgumentNullException(nameof(trade)); } var closedVolume = 0m; var pnl = 0m; var volume = trade.SafeGetVolume(); var price = trade.GetTradePrice(); _unrealizedPnL = null; lock (_openedTrades.SyncRoot) { if (_openedTrades.Count > 0) { var currTrade = _openedTrades.Peek(); if (_openedPosSide != trade.Side) { while (volume > 0) { if (currTrade == null) { currTrade = _openedTrades.Peek(); } var diff = currTrade.Second.Min(volume); closedVolume += diff; pnl += GetPnL(currTrade.First, diff, _openedPosSide, price); volume -= diff; currTrade.Second -= diff; if (currTrade.Second != 0) { continue; } currTrade = null; _openedTrades.Pop(); if (_openedTrades.Count == 0) { break; } } } } if (volume > 0) { _openedPosSide = trade.Side; _openedTrades.Push(RefTuple.Create(price, volume)); } RealizedPnL += _multiplier * pnl; } return(new PnLInfo(trade, closedVolume, pnl)); }
public void TestSynchronizedStack() { SynchronizedStack<string> stack = new SynchronizedStack<string>(); stack.Push("one"); stack.Push("two"); Assert.IsTrue(stack.Count == 2); foreach (string name in stack) { Assert.IsTrue(stack.Contains(name)); } string peeked = stack.Peek(); Assert.AreEqual(peeked, stack.Pop()); Assert.IsTrue(stack.Count == 1); stack.Clear(); Assert.IsTrue(stack.Count == 0); }