Files
marketdata/MarketDataLib/Generator/CMTrend/CMTPositions.cs
2025-02-10 07:57:00 -05:00

311 lines
16 KiB
C#

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<String>();
position.PurchaseDate=nvpDictionary["PurchaseDate"].Get<DateTime>();
position.SellDate=nvpDictionary["SellDate"].Get<DateTime>();
position.Shares=nvpDictionary["Shares"].Get<double>();
position.PurchasePrice=nvpDictionary["PurchasePrice"].Get<double>();
if(nvpDictionary.ContainsKey("CurrentPrice")) position.CurrentPrice=nvpDictionary["CurrentPrice"].Get<double>();
if(nvpDictionary.ContainsKey("R")) position.R=nvpDictionary["R"].Get<double>();
if(nvpDictionary.ContainsKey("C")) position.C=nvpDictionary["C"].Get<double>();
if(nvpDictionary.ContainsKey("PositionRiskDecimal")) position.PositionRiskPercentDecimal=nvpDictionary["PositionRiskDecimal"].Get<double>();
if(nvpDictionary.ContainsKey("InitialStopLimit")) position.InitialStopLimit=nvpDictionary["InitialStopLimit"].Get<double>();
if(nvpDictionary.ContainsKey("TrailingStopLimit")) position.TrailingStopLimit=nvpDictionary["TrailingStopLimit"].Get<double>();
if(nvpDictionary.ContainsKey("Volatility")) position.Volatility=nvpDictionary["Volatility"].Get<double>();
if(nvpDictionary.ContainsKey("Volume")) position.Volume=nvpDictionary["Volume"].Get<int>();
if(nvpDictionary.ContainsKey("LastStopAdjustment")) position.LastStopAdjustment=nvpDictionary["LastStopAdjustment"].Get<DateTime>();
if(nvpDictionary.ContainsKey("Comment")) position.Comment=nvpDictionary["Comment"].Get<String>();
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<Position>
{
public Positions()
{
}
public Positions(Positions positions)
{
if(null==positions) return;
foreach(Position position in positions) Add(position);
}
public Positions(List<Position> 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<String> 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<positions.Count;index++)
{
Position position=positions[index];
position.Display();
}
}
public void DisplayBottom(int count=10)
{
Positions positions=new Positions(this.OrderBy(x => x.GainLossPcnt).Take(count).ToList());
Position.DisplayHeader();
for(int index=0;index<positions.Count;index++)
{
Position position=positions[index];
position.Display();
}
}
public void Display()
{
Position.DisplayHeader();
for(int index=0;index<Count;index++)
{
Position position=this[index];
position.Display();
}
MDTrace.WriteLine(LogLevel.DEBUG,"****************************************************************************************************************************");
}
}
}