using System; using System.Collections.Generic; using MarketData.MarketDataModel; using MarketData.Utils; using System.Linq; using MarketData.Generator.Interface; namespace MarketData.Generator.CMTrend { public class Position : IPosition { public Position() { CurrentPrice=double.NaN; } public Position(Position position) { Symbol=position.Symbol; PurchaseDate=position.PurchaseDate; SellDate=position.SellDate; Shares=position.Shares; PurchasePrice=position.PurchasePrice; CurrentPrice=position.CurrentPrice; R=position.R; C=position.C; PositionRiskPercentDecimal=position.PositionRiskPercentDecimal; InitialStopLimit=position.InitialStopLimit; TrailingStopLimit=position.TrailingStopLimit; Volume=position.Volume; Volatility=position.Volatility; LastStopAdjustment=position.LastStopAdjustment; Comment=position.Comment; } public static Position Clone(Position position) { Position clonedPosition=new Position(); clonedPosition.Symbol=position.Symbol; clonedPosition.PurchaseDate=position.PurchaseDate; clonedPosition.SellDate=position.SellDate; clonedPosition.Shares=position.Shares; clonedPosition.PurchasePrice=position.PurchasePrice; clonedPosition.CurrentPrice=position.CurrentPrice; clonedPosition.R=position.R; clonedPosition.C=position.C; clonedPosition.PositionRiskPercentDecimal=position.PositionRiskPercentDecimal; clonedPosition.InitialStopLimit=position.InitialStopLimit; clonedPosition.TrailingStopLimit=position.TrailingStopLimit; clonedPosition.Volume=position.Volume; clonedPosition.Volatility=position.Volatility; clonedPosition.LastStopAdjustment=position.LastStopAdjustment; clonedPosition.Comment=position.Comment; return clonedPosition; } public String Symbol { get; set; } public DateTime PurchaseDate { get; set; } public DateTime SellDate { get; set; } public double Shares { get; set; } // This is actual shares (round down P to the nearest whole number) public double PurchasePrice { get; set; } public double CurrentPrice { get; set; } // When the position is sold the current price will hold the sell price public double Exposure { get { return Shares*PurchasePrice; } } // Derived public double MarketValue { get { return Shares*CurrentPrice; } } // Derived public double GainLoss { get { return MarketValue-Exposure; } } // Derived public double GetGainLoss(Price currentPrice) { return (Shares*currentPrice.Close)-Exposure; } // get the gain loss based upon the given price public double GainLossPcnt { get { return (MarketValue-Exposure)/Exposure; } } // Derived public double PositionRiskPercentDecimal { get; set; } // (i.e.) .06 = 6% public double R { get; set; } // PositionRiskPercentDecimal*PurchasePrice public double C { get; set; } // AvailableCash * TotalRiskPercentDecimal public double P { get { return C/R; } } // Derived. This is the number of shares to buy according to risk limits public double TrailingStopLimit { get; set; } // This is the trailing stop limit. public double InitialStopLimit { get; set; } // This is the initial stop limit. public DateTime LastStopAdjustment { get; set; } public double TotalRiskExposure { get { return R*Shares; } } // This is the total risk in dollars that we are exposed to public double RMultiple { get { return (CurrentPrice-PurchasePrice)/R; } } // Derived. public String RMultipleAsString { get { return Utility.FormatNumber(RMultiple,2,false)+"R"; } } // Derived. public double Volatility { get; set; } public long Volume { get; set; } public String Comment { get; set; } public virtual NVPCollection ToNVPCollection() { NVPCollection nvpCollection=new NVPCollection(); nvpCollection.Add(new NVP("Symbol",Symbol.ToString())); nvpCollection.Add(new NVP("PurchaseDate",PurchaseDate.ToString())); nvpCollection.Add(new NVP("SellDate",SellDate.ToString())); nvpCollection.Add(new NVP("Shares",Shares.ToString())); nvpCollection.Add(new NVP("PurchasePrice",PurchasePrice.ToString())); if(!double.IsNaN(CurrentPrice)) nvpCollection.Add(new NVP("CurrentPrice",CurrentPrice.ToString())); if(!double.IsNaN(Exposure)) nvpCollection.Add(new NVP("Exposure",Exposure.ToString())); if(!double.IsNaN(MarketValue)) nvpCollection.Add(new NVP("MarketValue",MarketValue.ToString())); if(!double.IsNaN(GainLoss)) nvpCollection.Add(new NVP("GainLoss",GainLoss.ToString())); if(!double.IsNaN(GainLossPcnt)) nvpCollection.Add(new NVP("GainLossPcnt",GainLossPcnt.ToString())); if(!double.IsNaN(PositionRiskPercentDecimal)) nvpCollection.Add(new NVP("PositionRiskDecimal",PositionRiskPercentDecimal.ToString())); if(!double.IsNaN(R)) nvpCollection.Add(new NVP("R",R.ToString())); if(!double.IsNaN(C)) nvpCollection.Add(new NVP("C",C.ToString())); if(!double.IsNaN(C)) nvpCollection.Add(new NVP("P",P.ToString())); if(!double.IsNaN(InitialStopLimit)) nvpCollection.Add(new NVP("InitialStopLimit",InitialStopLimit.ToString())); if(!double.IsNaN(TrailingStopLimit)) nvpCollection.Add(new NVP("TrailingStopLimit",TrailingStopLimit.ToString())); if(!double.IsNaN(TotalRiskExposure)) nvpCollection.Add(new NVP("TotalRiskExposure",TotalRiskExposure.ToString())); if(!double.IsNaN(RMultiple)) nvpCollection.Add(new NVP("RMultiple",RMultipleAsString)); if(!double.IsNaN(Volatility)) nvpCollection.Add(new NVP("Volatility",Volatility.ToString())); nvpCollection.Add(new NVP("Volume",Volume.ToString())); nvpCollection.Add(new NVP("LastStopAdjustment",LastStopAdjustment.ToString())); if(null!=Comment) nvpCollection.Add(new NVP("Comment",Comment)); return nvpCollection; } public static Position FromNVPCollection(NVPCollection nvpCollection) { Position position=new Position(); NVPDictionary nvpDictionary=nvpCollection.ToDictionary(); position.Symbol=nvpDictionary["Symbol"].Get(); position.PurchaseDate=nvpDictionary["PurchaseDate"].Get(); position.SellDate=nvpDictionary["SellDate"].Get(); position.Shares=nvpDictionary["Shares"].Get(); position.PurchasePrice=nvpDictionary["PurchasePrice"].Get(); if(nvpDictionary.ContainsKey("CurrentPrice")) position.CurrentPrice=nvpDictionary["CurrentPrice"].Get(); if(nvpDictionary.ContainsKey("R")) position.R=nvpDictionary["R"].Get(); if(nvpDictionary.ContainsKey("C")) position.C=nvpDictionary["C"].Get(); if(nvpDictionary.ContainsKey("PositionRiskDecimal")) position.PositionRiskPercentDecimal=nvpDictionary["PositionRiskDecimal"].Get(); if(nvpDictionary.ContainsKey("InitialStopLimit")) position.InitialStopLimit=nvpDictionary["InitialStopLimit"].Get(); if(nvpDictionary.ContainsKey("TrailingStopLimit")) position.TrailingStopLimit=nvpDictionary["TrailingStopLimit"].Get(); if(nvpDictionary.ContainsKey("Volatility")) position.Volatility=nvpDictionary["Volatility"].Get(); if(nvpDictionary.ContainsKey("Volume")) position.Volume=nvpDictionary["Volume"].Get(); if(nvpDictionary.ContainsKey("LastStopAdjustment")) position.LastStopAdjustment=nvpDictionary["LastStopAdjustment"].Get(); if(nvpDictionary.ContainsKey("Comment")) position.Comment=nvpDictionary["Comment"].Get(); return position; } public void Display() { if(Utility.IsEpoch(SellDate)&&double.IsNaN(CurrentPrice)) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17},{18},{19},{20},{21}", Symbol, Shares, Utility.DateTimeToStringMMHDDHYYYY(PurchaseDate), Utility.AddQuotes(Utility.FormatCurrency(PurchasePrice)), Utility.AddQuotes(Utility.FormatCurrency(InitialStopLimit)), Utility.AddQuotes(Utility.FormatCurrency(TrailingStopLimit)), Utility.AddQuotes(Utility.DateTimeToStringMMHDDHYYYY(LastStopAdjustment)), Utility.AddQuotes(Utility.FormatNumber(Volatility,2)), Utility.AddQuotes(Utility.FormatNumber(Volume,0)), Utility.AddQuotes(Utility.FormatCurrency(R)), Utility.AddQuotes(Utility.FormatNumber(PositionRiskPercentDecimal,3)), Utility.AddQuotes(Utility.FormatCurrency(C)), Utility.AddQuotes(Utility.FormatCurrency(TotalRiskExposure)), Utility.AddQuotes(Utility.FormatNumber(RMultiple,3)), Utility.AddQuotes(RMultipleAsString), Utility.IsEpoch(SellDate)?"N/A":Utility.DateTimeToStringMMHDDHYYYY(SellDate), "N/A", Utility.AddQuotes(Utility.FormatCurrency(Exposure)), "N/A", "N/A", "N/A", null==Comment?"":Comment )); } else { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17},{18},{19},{20},{21}", Symbol, Shares, Utility.DateTimeToStringMMHDDHYYYY(PurchaseDate), Utility.AddQuotes(Utility.FormatCurrency(PurchasePrice)), Utility.AddQuotes(Utility.FormatCurrency(InitialStopLimit)), Utility.AddQuotes(Utility.FormatCurrency(TrailingStopLimit)), Utility.IsEpoch(LastStopAdjustment)?"N/A":Utility.DateTimeToStringMMHDDHYYYY(LastStopAdjustment), Utility.AddQuotes(Utility.FormatNumber(Volatility,2)), Utility.AddQuotes(Utility.FormatNumber(Volume,0)), Utility.AddQuotes(Utility.FormatCurrency(R)), Utility.AddQuotes(Utility.FormatNumber(PositionRiskPercentDecimal,3)), Utility.AddQuotes(Utility.FormatCurrency(C)), Utility.AddQuotes(Utility.FormatCurrency(TotalRiskExposure)), Utility.AddQuotes(Utility.FormatNumber(RMultiple,3)), Utility.AddQuotes(RMultipleAsString), Utility.IsEpoch(SellDate)?"N/A":Utility.DateTimeToStringMMHDDHYYYY(SellDate), Utility.AddQuotes(Utility.FormatCurrency(CurrentPrice)), Utility.AddQuotes(Utility.FormatCurrency(Exposure)), Utility.AddQuotes(Utility.FormatCurrency(MarketValue)), Utility.AddQuotes(Utility.FormatCurrency(GainLoss)), Utility.FormatPercent(GainLossPcnt), null==Comment?"":Comment )); } } public static void DisplayHeader() { MDTrace.WriteLine(LogLevel.DEBUG,"Symbol,Shares,Purchase Date,Purchase Price,Initial Stop Limit,Trailing Stop Limit,Last Stop Adjustment,Volatility,Volume,R,PositionRiskPercentDecimal,C,TotalRiskExposure,RMultiple,RMultipleString,Sell Date,Sell Price,Exposure,Market Value,Gain Loss,Gain Loss(%),Comment"); } } // **************************************************************************************************************************************************************** public class Positions:List { public Positions() { } public Positions(Positions positions) { if(null==positions) return; foreach(Position position in positions) Add(position); } public Positions(List positions) { if(null==positions) return; foreach(Position position in positions) Add(position); } public Positions(Position position) { if(null==position) return; Add(position); } public void Add(Positions positions) { if(null==positions) return; foreach(Position position in positions) Add(position); } public int PositionsOn(DateTime purchaseDate) { return this.Count(x => x.PurchaseDate.Equals(purchaseDate)); } public double GetExposure() { Positions openPositions=new Positions(this.Where(x => Utility.IsEpoch(x.SellDate)).ToList()); return (from Position position in openPositions select position.PurchasePrice*position.Shares).Sum(); } public double GetMarketValue() { Positions closedPositions=new Positions(this.Where(x => !Utility.IsEpoch(x.SellDate)).ToList()); if(null==closedPositions||0==closedPositions.Count) return 0.00; return closedPositions.Select(x => x.CurrentPrice*x.Shares).Sum(); } public List GetSymbols() { return (from Position position in this select position.Symbol).Distinct().ToList(); } public double GetGainLoss() { Positions closedPositions=new Positions(this.Where(x => !Utility.IsEpoch(x.SellDate)).ToList()); if(null==closedPositions||0==closedPositions.Count) return 0.00; double totalMarketValue=closedPositions.Select(x => x.Shares*x.CurrentPrice).Sum(); double totalExposure=closedPositions.Select(x => x.Shares*x.PurchasePrice).Sum(); return totalMarketValue-totalExposure; } public double GetGainLossPercent() { Positions closedPositions=new Positions(this.Where(x => !Utility.IsEpoch(x.SellDate)).ToList()); if(null==closedPositions||0==closedPositions.Count) return 0.00; double totalMarketValue=closedPositions.Select(x => x.Shares*x.CurrentPrice).Sum(); double totalExposure=closedPositions.Select(x => x.Shares*x.PurchasePrice).Sum(); return (totalMarketValue-totalExposure)/totalExposure; } public NVPCollections ToNVPCollections() { NVPCollections nvpCollections=new NVPCollections(); foreach(Position position in this) { nvpCollections.Add(position.ToNVPCollection()); } return nvpCollections; } public static Positions FromNVPCollections(NVPCollections nvpCollections) { Positions positions=new Positions(); foreach(NVPCollection nvpCollection in nvpCollections) { positions.Add(Position.FromNVPCollection(nvpCollection)); } return positions; } public void AddFromNVPCollection(NVPCollection nvpCollection) { Add(Position.FromNVPCollection(nvpCollection)); } public void DisplayTop(int count=10) { Positions positions=new Positions(this.OrderByDescending(x => x.GainLossPcnt).Take(count).ToList()); Position.DisplayHeader(); for(int index=0;index x.GainLossPcnt).Take(count).ToList()); Position.DisplayHeader(); for(int index=0;index