public void TotalPnlLongIsTheSumOfRealizedAndUnrealizedPnlForShortPositions() { var trade = new Trade(); var date = new DateTime(2000, 1, 1); trade.Orders = new List<Order> { new Order { Instrument = _inst, Quantity = -10, FXRateToBase = 1, Price = 100, BuySell = "BUY", TradeDate = date }, new Order { Instrument = _inst, Quantity = 5, FXRateToBase = 1, Price = 95, BuySell = "SELL", TradeDate = date } }; var tracker = new TradeTracker(trade, 1); foreach (Order o in trade.Orders) { tracker.AddOrder(o); } var data = new Dictionary<int, TimeSeries> { { 1, TimeSeriesGenerator.GenerateData(date, date, 90) } }; foreach (TimeSeries ts in data.Values) { ts.ProgressTo(date); } tracker.Update(date, data, null); Assert.AreEqual(5 * 5 + 10 * 5, tracker.TotalPnL); Assert.AreEqual(5 * 5 + 10 * 5, tracker.TotalPnlShort); }
public void UpdateStats(Trade trade, bool skipCollectionLoad = false) { var tradeEntry = Context.Entry(trade); if (!skipCollectionLoad && //used to bypass annoyances w/ automated testing tradeEntry.State != EntityState.Added && tradeEntry.State != EntityState.Detached) //trade entry state check, otherwise the load is meaningless and will cause a crash { tradeEntry.Collection(x => x.Orders).Load(); tradeEntry.Collection(x => x.CashTransactions).Load(); tradeEntry.Collection(x => x.FXTransactions).Load(); } DateTime openDate = DetermineStartingDate(trade, Context); //Dates trade.DateOpened = openDate; if (trade.Open) { trade.DateClosed = null; } else { SetClosingDate(trade); } TradeTracker tracker = TradeSim.SimulateTrade(trade, Context, Datasourcer, _optionsCapitalUsageMultiplier); tracker.SetTradeStats(trade); }
public TradeViewModel(Trade trade, IDataSourcer dataSourcer, IDBContext context) : base(null) { context.Trades .Where(x => x.ID == trade.ID) .Include(x => x.Strategy) .Include(x => x.Orders) .Include("Orders.Instrument") .Include("Orders.Currency") .Include(x => x.CashTransactions) .Include("CashTransactions.Instrument") .Include("CashTransactions.Currency") .Include(x => x.FXTransactions) .Include("FXTransactions.FunctionalCurrency") .Include("FXTransactions.FXCurrency") .Load(); Trade = trade; Tracker = TradeSim.SimulateTrade(trade, context, dataSourcer, Properties.Settings.Default.optionsCapitalUsageMultiplier); }
/// <summary> /// Simulate the trade and update its stats. Does not save to db. /// </summary> /// <param name="trade"></param> /// <returns></returns> public async Task UpdateStats(Trade trade) { DateTime openDate = DetermineStartingDate(trade); //Dates trade.DateOpened = openDate; if (trade.Open) { trade.DateClosed = null; } else { SetClosingDate(trade); } TradeTracker tracker = await TradeSim.SimulateTrade(trade, _contextFactory, _dataSourcer, _settings.OptionsCapitalUsageMultiplier); tracker.SetTradeStats(trade); }
public void TotalPnlLongIsTheSumOfRealizedAndUnrealizedPnlForCurrencyPositions() { var trade = new Trade(); var date = new DateTime(2000, 1, 1); var fxCurrency = new Currency { ID = 2, Name = "CAD" }; trade.FXTransactions = new List<FXTransaction> { new FXTransaction { FXCurrency = fxCurrency, Quantity = 1000, Proceeds = 1500, Cost = -1500 }, new FXTransaction { FXCurrency = fxCurrency, Quantity = -500, Proceeds = -850, Cost = 850 }, }; var tracker = new TradeTracker(trade, 1); foreach (FXTransaction fxt in trade.FXTransactions) { tracker.AddFXTransaction(fxt); } var data = new Dictionary<int, TimeSeries> { { 2, TimeSeriesGenerator.GenerateData(date, date, 1.55m) } }; foreach (TimeSeries ts in data.Values) { ts.ProgressTo(date); } tracker.Update(date, new Dictionary<int, TimeSeries>(), data); Assert.AreEqual(100 + 500 * (1.55m - 1.5m), tracker.TotalPnL); }
public void TodaysPnlResetsEvenWhenTrackerIsNotOpen() { var trade = new Trade(); var date = new DateTime(2000, 1, 1); trade.Orders = new List<Order> { new Order { Instrument = _inst, Quantity = -10, FXRateToBase = 1, Price = 100, BuySell = "BUY", TradeDate = date }, new Order { Instrument = _inst, Quantity = 5, FXRateToBase = 1, Price = 95, BuySell = "SELL", TradeDate = date } }; var tracker = new TradeTracker(trade, 1); foreach (Order o in trade.Orders) { tracker.AddOrder(o); } var data = new Dictionary<int, TimeSeries> { { 1, TimeSeriesGenerator.GenerateData(date, date.AddDays(1), 90) } }; foreach (TimeSeries ts in data.Values) { ts.ProgressTo(date); } tracker.Update(date, data, null); Assert.AreEqual(5 * 5 + 10 * 5, tracker.TodaysPnL); data[1].ProgressTo(date.AddDays(1)); tracker.Update(date.AddDays(1), data, null); Assert.AreEqual(0, tracker.TodaysPnL); }
public void AddingOrderInForeignCurrencyResultsInFxPositionAddition() { var trade = new Trade(); var date = new DateTime(2000, 1, 1); var eur = new Currency { ID = 2, Name = "EUR" }; trade.Orders = new List<Order> { new Order { Instrument = _inst, Quantity = 10, FXRateToBase = 1.5m, Multiplier = 1, Price = 100, BuySell = "BUY", TradeDate = date, Currency = eur, CurrencyID = 2 }, }; var tracker = new TradeTracker(trade, 1); foreach (Order o in trade.Orders) { tracker.AddOrder(o); } Assert.IsTrue(tracker.CurrencyPositions.ContainsKey(2)); Assert.IsTrue(tracker.CurrencyPositions[2].Quantity == -10 * 100); Assert.IsTrue(tracker.CurrencyPositions[2].CostBasis == 1.5m); }
public void AddingCashTransactionInForeignCurrencyResultsInFxPositionAddition() { var trade = new Trade(); var date = new DateTime(2000, 1, 1); var eur = new Currency { ID = 2, Name = "EUR" }; var ct = new CashTransaction { InstrumentID = 1, Currency = eur, CurrencyID = 2, Amount = 50, FXRateToBase = 1.5m, Instrument = _inst, TransactionDate = date, AssetCategory = AssetClass.Stock }; trade.CashTransactions = new List<CashTransaction> { ct }; var tracker = new TradeTracker(trade, 1); foreach (CashTransaction c in trade.CashTransactions) { tracker.AddCashTransaction(c); } Assert.IsTrue(tracker.CurrencyPositions.ContainsKey(2)); Assert.IsTrue(tracker.CurrencyPositions[2].Quantity == 50); Assert.IsTrue(tracker.CurrencyPositions[2].CostBasis == 1.5m); }
public static async Task <TradeTracker> SimulateTrade(Trade trade, IContextFactory contextFactory, IDataSourcer dataSourcer, decimal optionsCapitalUsageMultiplier) { var tracker = new TradeTracker(trade, optionsCapitalUsageMultiplier); //starting and ending dates DateTime startDate = trade.DateOpened; DateTime endDate; if (!trade.Open && trade.DateClosed != null) { endDate = trade.DateClosed.Value.Date; } else { using (var dbContext = contextFactory.Get()) { var lastSummary = dbContext.EquitySummaries.OrderByDescending(x => x.Date).First(); endDate = lastSummary.Date.Date; } } var orders = trade.Orders == null ? new List <Order>() : trade.Orders.OrderBy(x => x.TradeDate).ToList(); var cashTransactions = trade.CashTransactions == null ? new List <CashTransaction>() : trade.CashTransactions.OrderBy(x => x.TransactionDate).ToList(); var fxTransactions = trade.FXTransactions == null ? new List <FXTransaction>() : trade.FXTransactions.OrderBy(x => x.DateTime).ToList(); //Grab the data Dictionary <int, TimeSeries> data = await GetInstrumentData(trade, dataSourcer, startDate, endDate); Dictionary <int, TimeSeries> fxData = GetFXData(trade, contextFactory); DateTime currentDate = startDate.Date; //Loop through the dates while (currentDate <= endDate) { //Progress time series to current date foreach (TimeSeries ts in data.Values) { ts.ProgressTo(currentDate); } foreach (TimeSeries ts in fxData.Values) { ts.ProgressTo(currentDate); } //Add orders while (orders.Count > 0 && orders[0].TradeDate.Date <= currentDate) { tracker.AddOrder(orders[0]); orders.RemoveAt(0); } //Add cash transactions while (cashTransactions.Count > 0 && cashTransactions[0].TransactionDate.Date <= currentDate) { tracker.AddCashTransaction(cashTransactions[0]); cashTransactions.RemoveAt(0); } //add fx transactions while (fxTransactions.Count > 0 && fxTransactions[0].DateTime.Date <= currentDate) { tracker.AddFXTransaction(fxTransactions[0]); fxTransactions.RemoveAt(0); } tracker.Update(currentDate, data, fxData); if (orders.Count == 0 && cashTransactions.Count == 0 && fxTransactions.Count == 0 && !tracker.Open) { break; } currentDate = currentDate.AddDays(1); } return(tracker); }
public static TradeTracker SimulateTrade(Trade trade, IDBContext context, IDataSourcer dataSourcer, decimal optionsCapitalUsageMultiplier) { var tracker = new TradeTracker(trade, optionsCapitalUsageMultiplier); //starting and ending dates DateTime startDate = trade.DateOpened; DateTime endDate; if(!trade.Open && trade.DateClosed != null) { endDate = trade.DateClosed.Value.Date; } else { var lastSummary = context.EquitySummaries.OrderByDescending(x => x.Date).First(); endDate = lastSummary.Date.Date; } var orders = trade.Orders == null ? new List<Order>() : trade.Orders.OrderBy(x => x.TradeDate).ToList(); var cashTransactions = trade.CashTransactions == null ? new List<CashTransaction>() : trade.CashTransactions.OrderBy(x => x.TransactionDate).ToList(); var fxTransactions = trade.FXTransactions == null ? new List<FXTransaction>() : trade.FXTransactions.OrderBy(x => x.DateTime).ToList(); //Grab the data Dictionary<int, TimeSeries> data = GetInstrumentData(trade, dataSourcer, startDate, endDate); Dictionary<int, TimeSeries> fxData = GetFXData(trade, context); DateTime currentDate = startDate.Date; //Loop through the dates while (currentDate <= endDate) { //Progress time series to current date foreach (TimeSeries ts in data.Values) { ts.ProgressTo(currentDate); } foreach (TimeSeries ts in fxData.Values) { ts.ProgressTo(currentDate); } //Add orders while (orders.Count > 0 && orders[0].TradeDate.Date <= currentDate) { tracker.AddOrder(orders[0]); orders.RemoveAt(0); } //Add cash transactions while (cashTransactions.Count > 0 && cashTransactions[0].TransactionDate.Date <= currentDate) { tracker.AddCashTransaction(cashTransactions[0]); cashTransactions.RemoveAt(0); } //add fx transactions while (fxTransactions.Count > 0 && fxTransactions[0].DateTime.Date <= currentDate) { tracker.AddFXTransaction(fxTransactions[0]); fxTransactions.RemoveAt(0); } tracker.Update(currentDate, data, fxData); if (orders.Count == 0 && cashTransactions.Count == 0 && fxTransactions.Count == 0 && !tracker.Open) break; currentDate = currentDate.AddDays(1); } return tracker; }