Example #1
0
        public void OnDayClose(DateTime todaysDate, decimal totalCapitalToday)
        {
            //update the status of each trade
            foreach (TradeTracker t in TradeTrackers.Values)
            {
                t.Update(todaysDate, _data, _fxData);
            }

            //update position stats
            foreach (var kvp in Positions)
            {
                int id = kvp.Key;

                Position p         = kvp.Value;
                decimal  fxRate    = p.Currency == null || p.Currency.ID == 1 ? 1 : _fxData[p.Currency.ID][0].Close;
                decimal? lastPrice = !_data.ContainsKey(id) || _data[id].CurrentBar < 0 ? (decimal?)null : _data[id][0].Close;
                p.GetPnL(lastPrice, fxRate);
            }

            //Capital usage and profit/loss for the day
            Capital.AddLong(Positions.Sum(x => x.Value.Capital.Long.Last()));
            Capital.AddShort(Positions.Sum(x => x.Value.Capital.Short.Last()));
            decimal todaysPnl = TradeTrackers.Sum(x => x.Value.TodaysPnL);

            _logger.Log(LogLevel.Trace, string.Format("Portfolio {0} @ {1}: Capital used: {2:0.00} P/L: {3:0.00}",
                                                      Name,
                                                      todaysDate,
                                                      Capital.TodaysCapitalGross,
                                                      todaysPnl));

            //P/L curves
            ProfitLossEquityCurve.AddChange((double)todaysPnl, todaysDate);
            ProfitLossLongEquityCurve.AddValue((double)TradeTrackers.Sum(x => x.Value.TotalPnlLong), todaysDate);
            ProfitLossShortEquityCurve.AddValue((double)TradeTrackers.Sum(x => x.Value.TotalPnlShort), todaysDate);

            //ROAC
            if (Capital.TodaysCapitalGross == 0)
            {
                _deferredPnL += todaysPnl;
                RoacEquityCurve.AddReturn(0, todaysDate);
            }
            else
            {
                RoacEquityCurve.AddReturn((double)((_deferredPnL + todaysPnl) / Capital.TodaysCapitalGross), todaysDate);
                _deferredPnL = 0;
            }

            //ROTC
            if (totalCapitalToday == 0)
            {
                RotcEquityCurve.AddReturn(0, todaysDate);
            }
            else
            {
                RotcEquityCurve.AddReturn((double)(todaysPnl / totalCapitalToday), todaysDate);
            }

            Capital.EndOfDay();
        }
Example #2
0
        public void Update(DateTime currentDate, Dictionary <int, TimeSeries> data, Dictionary <int, TimeSeries> fxData)
        {
            TodaysPnL = 0;
            if (!Open)
            {
                return;
            }

            //Update positions
            foreach (var kvp in Positions)
            {
                int id = kvp.Key;

                Position p      = kvp.Value;
                decimal  fxRate = p.Currency == null || p.Currency.ID <= 1 ? 1 : fxData[p.Currency.ID][0].Close;
                TodaysPnL += p.GetPnL(data[id].CurrentBar < 0 ? (decimal?)null : data[id][0].Close, fxRate);
            }

            //Update currency positions
            foreach (var kvp in CurrencyPositions)
            {
                int id = kvp.Key;
                if (fxData[id].CurrentBar < 0)
                {
                    continue;
                }

                CurrencyPosition p      = kvp.Value;
                decimal          fxRate = fxData[id][0].Close;
                TodaysPnL += p.Update(fxRate);
            }

            if (Positions.Any(x => x.Value.Capital.Gross.Count > 0))
            {
                Capital.AddLong(Positions.Sum(x => x.Value.Capital.Long.Last()));
                Capital.AddShort(Positions.Sum(x => x.Value.Capital.Short.Last()));
            }

            if (Capital.TodaysCapitalGross != 0)
            {
                _currentEquity *= (double)(1 + TodaysPnL / Capital.TodaysCapitalGross);
            }
#if DEBUG
            _logger.Log(LogLevel.Trace, string.Format("Trade tracker ID {0} @ {1}, todays capital usage {2:0.00}, P/L: {3:0.00}",
                                                      Trade.ID,
                                                      currentDate,
                                                      Capital.TodaysCapitalGross,
                                                      TodaysPnL));
#endif

            Capital.EndOfDay();

            _totalPnL += TodaysPnL;

            CumulativeReturns.Add(currentDate, _currentEquity);
            CumulativePnL.Add(currentDate, _totalPnL);

            Open = Positions.Values.Sum(x => x.Quantity) != 0 ||
                   CurrencyPositions.Values.Sum(x => x.Quantity) != 0 ||
                   (_ordersRemaining > 0 && _ordersRemaining < Trade.Orders.Count);
        }
Example #3
0
        public void MultiPeriodCapitalUsageIsRecordedCorrectly()
        {
            var pos = new Position(_instrument);
            var o = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o);

            Assert.AreEqual(1000, pos.Capital.TodaysCapitalGross);
            Assert.AreEqual(1000, pos.Capital.TodaysCapitalLong);
            pos.GetPnL(10, 1);

            var o2 = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o2);

            var o3 = new Order
            {
                Quantity = -200,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o3);

            pos.GetPnL(10, 1);

            Assert.AreEqual(2000, pos.Capital.Gross.Last());
            Assert.AreEqual(2000, pos.Capital.Long.Last());

            pos.GetPnL(10, 1);

            var o4 = new Order
            {
                Quantity = 150,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o4);

            pos.GetPnL(10, 1);


            List<decimal> expectedCapitalGross = new List<decimal> { 1000, 2000, 0, 1500 };
            for (int i = 0; i < expectedCapitalGross.Count; i++)
            {
                Assert.AreEqual(expectedCapitalGross[i], pos.Capital.Gross[i]);
            }
        }
Example #4
0
        public void CapitalUsageWhenEnteringAndExitingNearCloseIsCounted()
        {
            var pos = new Position(_instrument);
            var o = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1,
                TradeDate = new DateTime(2000, 1, 1, 15, 59, 0)
            };
            pos.AddOrder(o);

            var o2 = new Order
            {
                Quantity = -100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1,
                TradeDate = new DateTime(2000, 1, 1, 15, 59, 1)
            };
            pos.AddOrder(o2);

            pos.GetPnL(10, 1);

            Assert.AreEqual(1000, pos.Capital.Gross.Last());
            Assert.AreEqual(1000, pos.Capital.Long.Last());
        }
Example #5
0
        public void UnrealizedPnLReturnsDiffernceBetweenTotalAndRealizedPnL()
        {
            var pos = new Position(_instrument);
            var o = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o);

            var o2 = new Order
            {
                Quantity = -50,
                Price = 11,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o2);

            pos.GetPnL(11, 1);

            Assert.AreEqual(50, pos.UnrealizedPnL);
        }
Example #6
0
        public void PnLIsDeferredForROACCalculationsIfNoCapitalIsUsed()
        {
            var pos = new Position(_instrument);
            var c = new CashTransaction
            {
                Amount = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddCashTransaction(c);

            pos.GetPnL(10, 1);

            var o = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o);

            pos.GetPnL(10, 1);

            Assert.AreEqual(1 + (10d / (10 * 100)), pos.ROAC);
        }
Example #7
0
        public void GetPnLReturnsCorrectPnLWithBothRealizedAndUnrealizedPnL()
        {
            var pos = new Position(_instrument);
            var o = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o);

            var o2 = new Order
            {
                Quantity = -50,
                Price = 11,
                Instrument = _instrument,
                FXRateToBase = 1,
            };
            pos.AddOrder(o2);

            Assert.AreEqual(50 * 1 + 50 * 2, pos.GetPnL(12, 1));
            Assert.AreEqual(-2 * 50, pos.GetPnL(10, 1));
        }
Example #8
0
        public void GetPnLReturnsCorrectPnLIncludingFXRateChanges()
        {
            var pos = new Position(_instrument);
            var o = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o);

            Assert.AreEqual(45, pos.GetPnL(11, 0.95m));
        }
Example #9
0
        public void GetPnLReturnsCorrectPnLForShortPositions()
        {
            var pos = new Position(_instrument);
            var o = new Order
            {
                Quantity = -100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o);

            Assert.AreEqual(-100, pos.GetPnL(11, 1));
            Assert.AreEqual(100, pos.GetPnL(10, 1));
        }
Example #10
0
        public void GetPnLIncludesCommissions()
        {
            var pos = new Position(_instrument);
            var o = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1,
                Commission = -5
            };
            pos.AddOrder(o);

            Assert.AreEqual(100 - 5, pos.GetPnL(11, 1));
            Assert.AreEqual(-100, pos.GetPnL(10, 1));
        }
Example #11
0
        public void ROACValueReflectsFXRateChanges()
        {
            var pos = new Position(_instrument);
            var o = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o);

            var o2 = new Order
            {
                Quantity = -50,
                Price = 11,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o2);

            pos.GetPnL(10, 1.1m);

            Assert.AreEqual(1.1, pos.ROAC);
        }
Example #12
0
        public void ROACValueIsCorrectWithCashTransactions()
        {
            var pos = new Position(_instrument);
            var o = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o);

            var c = new CashTransaction
            {
                Amount = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddCashTransaction(c);

            pos.GetPnL(10, 1);

            Assert.AreEqual(1.01, pos.ROAC);
        }
Example #13
0
        public void ROACValueIsCorrectAfterPartialExit()
        {
            var pos = new Position(_instrument);
            var o = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o);

            var o2 = new Order
            {
                Quantity = -50,
                Price = 11,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o2);

            pos.GetPnL(10, 1);

            Assert.AreEqual(1.05, pos.ROAC);
        }
Example #14
0
        public void ROACValueIsCorrectAfterReversing()
        {
            var pos = new Position(_instrument);
            var o = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o);

            var o2 = new Order
            {
                Quantity = -150,
                Price = 11,
                Instrument = _instrument,
                FXRateToBase = 1
            };
            pos.AddOrder(o2);

            pos.GetPnL(11, 1);

            Assert.AreEqual(Math.Round(1 + (1.0 * 100) / (10 * 100 + 11 * 50), 5), Math.Round(pos.ROAC, 5));
        }
Example #15
0
        public void CapitalUsageWhenEnteringAndExitingMultipleOrdersNearCloseIsCountedWithShortPosition()
        {
            var pos = new Position(_instrument);
            decimal orderCapitalUsage = 0;

            var o = new Order
            {
                Quantity = -100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1,
                TradeDate = new DateTime(2000, 1, 1, 15, 59, 0)
            };
            orderCapitalUsage = pos.AddOrder(o);
            Assert.AreEqual(0, orderCapitalUsage);

            var o2 = new Order
            {
                Quantity = -100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1,
                TradeDate = new DateTime(2000, 1, 1, 15, 59, 1)
            };
            orderCapitalUsage = pos.AddOrder(o2);
            Assert.AreEqual(0, orderCapitalUsage);

            var o3 = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1,
                TradeDate = new DateTime(2000, 1, 1, 15, 59, 2)
            };
            orderCapitalUsage = pos.AddOrder(o3);
            Assert.AreEqual(1000, orderCapitalUsage);

            var o4 = new Order
            {
                Quantity = 100,
                Price = 10,
                Instrument = _instrument,
                FXRateToBase = 1,
                TradeDate = new DateTime(2000, 1, 1, 15, 59, 3)
            };
            orderCapitalUsage = pos.AddOrder(o4);
            Assert.AreEqual(1000, orderCapitalUsage);

            pos.GetPnL(10, 1);

            Assert.AreEqual(2000, pos.Capital.Gross.Last());
            Assert.AreEqual(2000, pos.Capital.Short.Last());
        }