private double CalculateSpreadDiscount(NetPositionDTO currContract, NetPositionDTO nextContract, int spreadIndex) { double totalDiscount = 0; if (Math.Sign(nextContract.NetContracts) != Math.Sign(currContract.NetContracts))//we have a spread { double netSpread = Math.Min(Math.Abs(currContract.NetContracts), Math.Abs(nextContract.NetContracts)); if (netSpread != 0) { DailySettlementPrice DSP1 = DailySettlementPrices.Where(x => x.Symbol == currContract.Symbol).FirstOrDefault(); DailySettlementPrice DSP2 = DailySettlementPrices.Where(x => x.Symbol == nextContract.Symbol).FirstOrDefault(); if (spreadIndex == 1)//1-wide spread { totalDiscount += netSpread * Config.MarginPct * Config.OneWideCalDisc * (DSP1.Price.Value + DSP2.Price.Value); } else if (spreadIndex == 2)//2-wide spread { totalDiscount += netSpread * Config.MarginPct * Config.TwoWideCalDisc * (DSP1.Price.Value + DSP2.Price.Value); } else if (spreadIndex >= 3)//3-wide spread or wider { totalDiscount += netSpread * Config.MarginPct * Config.ThreeWideCalDisc * (DSP1.Price.Value + DSP2.Price.Value); } ; currContract.NetContracts -= (currContract.NetContracts > 0) ? netSpread : (-1 * netSpread); nextContract.NetContracts -= (nextContract.NetContracts > 0) ? netSpread : (-1 * netSpread); } } return(totalDiscount); }
protected double CalculateCalendarMarginDiscounts(NetPositionDTO[] netPositionsArr, string assetClass) { double totalDiscount = 0; int spreadIndex = 1; NetPositionDTO[] assetClassNetPositionsArr = netPositionsArr.Where(x => x.AssetClass == assetClass).ToArray(); for (int i = 0; i < assetClassNetPositionsArr.Length; i++) { for (int j = 0; j < assetClassNetPositionsArr.Length; j++) { NetPositionDTO currContract = assetClassNetPositionsArr.OrderBy(x => x.MaturityDate).ToArray()[j]; if ((j + spreadIndex) < assetClassNetPositionsArr.Length) { NetPositionDTO nextContract = assetClassNetPositionsArr.OrderBy(x => x.MaturityDate).ToArray()[j + spreadIndex]; totalDiscount += CalculateSpreadDiscount(currContract, nextContract, spreadIndex); } } spreadIndex += 1; } return(totalDiscount); }
private NetPositionDTO BuildNewPosition(TradeDTO execution) { NetPositionDTO position = new NetPositionDTO() { Symbol = execution.Symbol, NetContracts = execution.Side == TradeDTO._TRADE_BUY ? execution.ExecutionSize : -1 * execution.ExecutionSize, PositionExposure = execution.Side == TradeDTO._TRADE_BUY ? NetPositionDTO._LONG : NetPositionDTO._SHORT, OpenPrice = execution.ExecutionPrice }; return(position); }
public static NetPositionDTO[] GetMatchingCounterparties(NetPositionDTO mySide, SecurityMasterRecord[] securities, UserRecord[] users, ClientPosition[] positions) { List <string> firmList = new List <string>(); foreach (UserRecord user in users.Where(x => x.FirmId != mySide.FirmId)) { if (!firmList.Contains(user.FirmId)) { firmList.Add(user.FirmId); } } List <NetPositionDTO> possibleCounterparties = new List <NetPositionDTO>(); foreach (string firmId in firmList) { NetPositionDTO opSide = GetNetPositionsToSettl(securities, users, positions, firmId, mySide.Symbol); if (opSide != null && Math.Sign(mySide.NetContracts) != Math.Sign(opSide.NetContracts)) { possibleCounterparties.Add(opSide); } } //imperfect algo to match counterparites double acum = 0; List <NetPositionDTO> matchingCounterparties = new List <NetPositionDTO>(); foreach (NetPositionDTO opSide in possibleCounterparties.OrderBy(x => Math.Abs(x.NetContracts))) { acum += Math.Abs(opSide.NetContracts); matchingCounterparties.Add(opSide); if (acum >= mySide.NetContracts) { break; } } return(matchingCounterparties.ToArray()); }
public double?CalculateIncrementalVariationMargin(NetPositionDTO prevNetContracts, double prevDSP, double?todayDSP, List <TradeDTO> todayTrades) { if (prevNetContracts == null || todayTrades == null || !todayDSP.HasValue) { return(null); } double prevPAndL = prevNetContracts.NetContracts > 0 ? prevNetContracts.NetContracts * (todayDSP.Value - prevDSP) : prevNetContracts.NetContracts * (prevDSP - todayDSP.Value); foreach (TradeDTO trade in todayTrades) { double currPAndL = trade.ExecutionSize > 0 ? trade.ExecutionSize * (todayDSP.Value - trade.ExecutionPrice) : trade.ExecutionSize * (trade.ExecutionPrice - todayDSP.Value); prevPAndL += currPAndL; } return(prevPAndL); }
public double?CalculateIncrementalProfitsAndLosses(NetPositionDTO prevNetContracts, double prevDSP, double?currentPrice, List <TradeDTO> todayTrades) { if (prevNetContracts == null || todayTrades == null || !currentPrice.HasValue) { return(null); } double prevPAndL = prevNetContracts.NetContracts > 0 ? prevNetContracts.NetContracts * (currentPrice.Value - prevDSP) : prevNetContracts.NetContracts * (prevDSP - currentPrice.Value); foreach (TradeDTO trade in todayTrades) { double currPAndL = trade.Side == TradeDTO._TRADE_BUY ? trade.ExecutionSize * (currentPrice.Value - trade.ExecutionPrice) : trade.ExecutionSize * (trade.ExecutionPrice - currentPrice.Value); prevPAndL += currPAndL; } return(prevPAndL); }
protected static void ProcessIncrementalPandL() { string symbol = ConfigurationManager.AppSettings["SymbolToConsider"]; double?currentPrice = (double?)Convert.ToDouble(ConfigurationManager.AppSettings["CurrentPrice"]); double prevDSP = Convert.ToDouble(ConfigurationManager.AppSettings["PrevDSP"]); double netContracts = Convert.ToDouble(ConfigurationManager.AppSettings["NetContracts"]); string csvFile = ConfigurationManager.AppSettings["InputFile"]; //List<TradeDTO> trades = ExecutionsLoader.GetTrades(csvFile); List <TradeDTO> trades = GetSimplePAndLScenarios(); NetPositionDTO prevNetPosition = new NetPositionDTO() { NetContracts = netContracts, Symbol = symbol }; PortfolioCalculator calc = new PortfolioCalculator(); double?profitsAndLosses = calc.CalculateIncrementalProfitsAndLosses(prevNetPosition, prevDSP, currentPrice, trades); double?varMargin = calc.CalculateIncrementalVariationMargin(prevNetPosition, prevDSP, null, trades); Console.WriteLine(string.Format(" Incremental P&L for symbol {0}:{1}", symbol, profitsAndLosses)); Console.WriteLine(string.Format(" Incremental Variation Margin for symbol {0}:{1}", symbol, varMargin)); }
public double CalculateTotalProfitsAndLosses(List <TradeDTO> executions, double currentPrice) { ValidateExecutions(executions); double pandL = 0; List <NetPositionDTO> positions = new List <NetPositionDTO>(); foreach (TradeDTO execution in executions) { if (positions.Count == 0) { //First trade-> first position positions.Add(BuildNewPosition(execution)); } else { double tradeSize = execution.GetSignedExecutionSize(); foreach (NetPositionDTO openPos in positions.Where(x => x.NetContracts != 0)) { if (Math.Abs(tradeSize) != 0) { if (openPos.IsCoverOrFlipping(execution)) //The execution is in the opposite direction of this position { if (Math.Abs(openPos.NetContracts) > Math.Abs(tradeSize)) //Partially Covered { double covered = execution.GetSignedExecutionSize(tradeSize); tradeSize = 0; pandL += (-1 * covered) * (execution.ExecutionPrice - openPos.OpenPrice); openPos.NetContracts += covered; openPos.UpdateExposure(); } else//Fully Covered or flipped { tradeSize += openPos.NetContracts; double covered = openPos.NetContracts; pandL += covered * (execution.ExecutionPrice - openPos.OpenPrice); openPos.NetContracts = 0; openPos.UpdateExposure(); } } else// We have a trade in the same direction of the available positions { positions.Add(BuildNewPosition(execution)); tradeSize = 0; break; } } } if (Math.Abs(tradeSize) != 0) { execution.ExecutionSize = Math.Abs(tradeSize); positions.Add(BuildNewPosition(execution)); tradeSize = 0; //we flipped the position (LONG-> SHORT, SHORT-> LONG) } positions = positions.Where(x => x.NetContracts != 0).ToList(); } } //Now the open position NetPositionDTO currOpenPos = positions.Where(x => x.NetContracts != 0).FirstOrDefault(); if (currOpenPos != null) { pandL += currOpenPos.NetContracts * (currentPrice - currOpenPos.OpenPrice); } return(pandL); }