336 lines
12 KiB
C#
336 lines
12 KiB
C#
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<EquityPriceShock>
|
|
{
|
|
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<StrikeExpiryKey,Option> putOptions=new Dictionary<StrikeExpiryKey,Option>();
|
|
Dictionary<StrikeExpiryKey,Option> callOptions=new Dictionary<StrikeExpiryKey,Option>();
|
|
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<Option>
|
|
{
|
|
public Options()
|
|
{
|
|
}
|
|
public Options(List<Option> options)
|
|
{
|
|
foreach(Option option in options)Add(option);
|
|
}
|
|
}
|
|
[Serializable]
|
|
public class Option
|
|
{
|
|
private MoneyType moneyType = new MoneyType();
|
|
public DateTime Expiration { get; set; }
|
|
public String Symbol { get; set; }
|
|
public OptionTypeEnum Type { get; set; }
|
|
public double Strike { get; set; }
|
|
public double PutCallRatio{get;set;}
|
|
public double CallPutRatio{get;set;}
|
|
public Double Ratio
|
|
{
|
|
get
|
|
{
|
|
if(Type.Equals(OptionTypeEnum.CallOption))return CallPutRatio;
|
|
return PutCallRatio;
|
|
}
|
|
}
|
|
public override int GetHashCode()
|
|
{
|
|
return (Symbol+Expiration.ToShortDateString()+Utility.FormatNumber(Strike,2)+(int)Type).GetHashCode();
|
|
}
|
|
public double Last { get; set; }
|
|
public double Change { get; set; }
|
|
public double Bid { get; set; }
|
|
public double Ask { get; set; }
|
|
public long Volume { get; set; }
|
|
public double OpenInterest { get; set; }
|
|
public double OptionValue { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
public MoneyType MoneyType
|
|
{
|
|
get { return moneyType; }
|
|
set { moneyType = value; }
|
|
}
|
|
public String MoneyTypeAsString { get { return MoneyType.ToString(); } }
|
|
public int DaysToExpiration
|
|
{
|
|
get
|
|
{
|
|
return new DateGenerator().DaysBetween(Expiration, DateTime.Now);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|