using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.Serialization; using System.Threading.Tasks; using MarketData.Utils; namespace MarketData.MarketDataModel { public class EquityPriceShocks : List { public static EquityPriceShocks CreateEquityPriceShocks(Price latestPrice, OptionsParams optionsParams) { EquityPriceShocks equityPriceShocks = new EquityPriceShocks(); int[] shocks = { 50, 25, 15, 10, 0, -5, -10, -15, -25, -50 }; for (int index = 0; index < shocks.Length; index++) { EquityPriceShock equityPriceShock = new EquityPriceShock(); equityPriceShock.Rank = shocks[index]; if (equityPriceShock.Rank > 0) equityPriceShock.PriceShock = "+" + Utility.FormatNumber(equityPriceShock.Rank, 0, false).ToString() + "%"; else if (equityPriceShock.Rank < 0) equityPriceShock.PriceShock = Utility.FormatNumber(equityPriceShock.Rank, 0, false) + "%"; else equityPriceShock.PriceShock = "+-" + Utility.FormatNumber(equityPriceShock.Rank, 0, false) + "%"; equityPriceShock.Premium = optionsParams.Premium; equityPriceShock.Rank /= 100.00; equityPriceShock.MarketPrice = latestPrice.Close + (latestPrice.Close * equityPriceShock.Rank); equityPriceShock.StrikePrice = optionsParams.Strike; // We expect the option to be excercises because the strike price is more favorable than market price // price our gain loss as if we had purchased at prevailing market price and then sold at the strike price if (optionsParams.Strike < equityPriceShock.MarketPrice) { equityPriceShock.PositionGL = (equityPriceShock.StrikePrice * optionsParams.Shares) - (latestPrice.Close * optionsParams.Shares); equityPriceShock.TransactionGL = equityPriceShock.Premium + equityPriceShock.PositionGL; equityPriceShock.ExpectedOutcome = "Option will be assigned."; } else // We expect the option to go un-excercised because the stock can be purchased in the open market more cheaply than at our strike price // price our gain/loss as if we had purchased at prevailing market prie and then sold at the shock price { equityPriceShock.PositionGL = (equityPriceShock.MarketPrice * optionsParams.Shares) - (latestPrice.Close * optionsParams.Shares); equityPriceShock.TransactionGL = equityPriceShock.Premium + equityPriceShock.PositionGL; equityPriceShock.ExpectedOutcome = "Option will not be assigned."; } equityPriceShocks.Add(equityPriceShock); } return equityPriceShocks; } } public class EquityPriceShock { public String PriceShock { get; set; } public double Rank { get; set; } public double MarketPrice { get; set; } public double StrikePrice { get; set; } public double Premium { get; set; } public double PositionGL { get; set; } public double TransactionGL { get; set; } public String ExpectedOutcome { get; set; } } [Serializable] public class OptionsParams { private int contracts; private double shares; public static int CONTRACT_SIZE = 100; public String Symbol { get; set; } public String CompanyName { get; set; } public double Cashdown { get; set; } public DateTime ExpirationDate { get; set; } public double Bid { get; set; } public double Strike { get; set; } public double OpenInterest { get; set; } public double Volume { get; set; } public double Shares { get { return shares; } } public int Contracts { get { return contracts; } set { contracts = value; shares = contracts * 100.00; } } public double MarketPrice { get; set; } public double Premium { get; set; } public double Volatility { get; set; } public int VolatilityDays { get; set; } public static String Header { get { StringBuilder sb = new StringBuilder(); sb.Append("Symbol").Append(","); sb.Append("CompanyName").Append(","); sb.Append("Cashdown").Append(","); sb.Append("ExpirationDate").Append(","); sb.Append("Bid").Append(","); sb.Append("Strike").Append(","); sb.Append("OpenInterest").Append(","); sb.Append("Shares").Append(","); sb.Append("Contracts").Append(","); sb.Append("MarketPrice").Append(","); sb.Append("Premium").Append(","); sb.Append("Volatility").Append(","); sb.Append("VolatilityDays"); return sb.ToString(); } } public override String ToString() { StringBuilder sb = new StringBuilder(); sb.Append("\"").Append(Symbol).Append("\"").Append(","); sb.Append("\"").Append(CompanyName).Append("\"").Append(","); sb.Append("\"").Append(Utility.FormatCurrency(Cashdown)).Append("\"").Append(","); sb.Append("\"").Append(Utility.DateTimeToStringMMHDDHYYYY(ExpirationDate)).Append("\"").Append(","); sb.Append("\"").Append(Utility.FormatCurrency(Bid)).Append("\"").Append(","); sb.Append("\"").Append(Utility.FormatCurrency(Strike)).Append("\"").Append(","); sb.Append("\"").Append(Utility.FormatNumber(OpenInterest,0,true)).Append("\"").Append(","); sb.Append("\"").Append(Utility.FormatNumber(Shares)).Append("\"").Append(","); sb.Append("\"").Append(Utility.FormatNumber(Contracts,0,true)).Append("\"").Append(","); sb.Append("\"").Append(Utility.FormatCurrency(MarketPrice)).Append("\"").Append(","); sb.Append("\"").Append(Utility.FormatCurrency(Premium)).Append("\"").Append(","); sb.Append("\"").Append(Utility.FormatCurrency(Volatility)).Append("\"").Append(","); sb.Append("\"").Append(Utility.FormatNumber(VolatilityDays,0,false)).Append("\""); return sb.ToString(); } } public class MoneyType { public enum MoneyTypeEnum { AtTheMoney, InTheMoney, OutOfTheMoney, Unset }; public MoneyTypeEnum moneyType = MoneyTypeEnum.Unset; public MoneyType() { moneyType = MoneyTypeEnum.Unset; } public MoneyType(double currentPrice, double strikePrice) { SetMoney(currentPrice, strikePrice); } public MoneyType.MoneyTypeEnum Money { get { return moneyType; } set { moneyType = value; } } public void SetMoney(double currentPrice, double strikePrice) { double upperPrice = strikePrice + .15; double lowerPrice = strikePrice - .15; if (currentPrice <= upperPrice && currentPrice >= lowerPrice) { Money = MoneyTypeEnum.AtTheMoney; } else if (strikePrice < currentPrice) Money = MoneyTypeEnum.InTheMoney; else Money = MoneyTypeEnum.OutOfTheMoney; } public override string ToString() { switch (Money) { case MoneyTypeEnum.AtTheMoney: return "At The Money"; case MoneyTypeEnum.InTheMoney: return "In The Money"; case MoneyTypeEnum.OutOfTheMoney: return "Out Of The Money"; default: return "Unset"; } } } // ******************************************************************************************************************************************************************* // ************************************************************** P U T C A L L R A T I O C A L C U L A T O R *********************************************** // ******************************************************************************************************************************************************************* public class PutCallRatioHelper { protected class StrikeExpiryKey { public StrikeExpiryKey(double strike,DateTime expiration) { Expiration=expiration; Strike=strike; } public DateTime Expiration{get;set;} public double Strike{get;set;} public override int GetHashCode() { StringBuilder sb=new StringBuilder(); sb.Append(Expiration.ToShortDateString()).Append(Utility.FormatCurrency(Strike)); return sb.ToString().GetHashCode(); } public override bool Equals(object obj) { return Equals(obj as StrikeExpiryKey); } public bool Equals(StrikeExpiryKey obj) { return obj.ToString().Equals(ToString()); } public override String ToString() { StringBuilder sb=new StringBuilder(); sb.Append(Expiration.ToShortDateString()).Append(Utility.FormatCurrency(Strike)); return sb.ToString(); } } private PutCallRatioHelper() { } public static void CalculatePutCallRatios(Options options) { Dictionary putOptions=new Dictionary(); Dictionary callOptions=new Dictionary(); foreach(Option option in options) { StrikeExpiryKey strikeExpiryKey=new StrikeExpiryKey(option.Strike,option.Expiration); if(option.Type.Equals(OptionTypeEnum.CallOption)&&!callOptions.ContainsKey(strikeExpiryKey))callOptions.Add(strikeExpiryKey,option); else if(!putOptions.ContainsKey(strikeExpiryKey))putOptions.Add(strikeExpiryKey,option); } foreach(Option option in options) { if(option.Volume==0) { option.PutCallRatio=double.NaN; option.CallPutRatio=double.NaN; continue; } StrikeExpiryKey strikeExpiryKey=new StrikeExpiryKey(option.Strike,option.Expiration); if(option.Type.Equals(OptionTypeEnum.PutOption)) // put options { Option callOption=null; option.CallPutRatio=double.NaN; if(!callOptions.ContainsKey(strikeExpiryKey)) { option.PutCallRatio=double.NaN; continue; } callOption=callOptions[strikeExpiryKey]; if(0==callOption.Volume) { option.PutCallRatio=double.NaN; continue; } option.PutCallRatio=(double)option.Volume/(double)callOption.Volume; } else // call options { Option putOption=null; option.PutCallRatio=double.NaN; if(!putOptions.ContainsKey(strikeExpiryKey)) { option.CallPutRatio=double.NaN; continue; } putOption=putOptions[strikeExpiryKey]; if(0==putOption.Volume) { option.CallPutRatio=double.NaN; continue; } option.CallPutRatio=(double)option.Volume/(double)putOption.Volume; } } } } // ******************************************************************************************************************************************************************* public enum OptionTypeEnum { CallOption, PutOption }; public class Options : List