Files
TradeBlotter/ViewModels/OptionsWorksheetViewModel.cs
2024-02-23 06:58:53 -05:00

440 lines
17 KiB
C#

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows.Input;
using System.Windows.Threading;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
using MarketData;
using MarketData.Numerical;
using MarketData.Utils;
using MarketData.MarketDataModel;
using MarketData.Generator;
using MarketData.DataAccess;
using TradeBlotter.DataAccess;
using TradeBlotter.Command;
using TradeBlotter.Model;
using TradeBlotter.Cache;
using Microsoft.Research.DynamicDataDisplay.DataSources;
namespace TradeBlotter.ViewModels
{
public class OptionsWorksheetViewModel : WorkspaceViewModel
{
private const int PRICE_FETCH_INTERVAL_MINS = 2;
private RelayCommand displayBollingerBandCommand = null;
private RelayCommand displayMovingAverageCommand = null;
private Option selectedOption = null;
private OptionsParams optionsParams = new OptionsParams() { Cashdown = 10000 };
private String companyName;
private Price underlierPrice; // this is the price as of the date this record was created.
private Price currentPrice; // this is the most recent price in the database
private ObservableCollection<EquityPriceShock> equityPriceShocksCollection = null;
private bool busyIndicator = false;
private DispatcherTimer priceTimer = null;
private Prices prices = null;
private double transactionGL;
private bool useRealPrice = false;
public OptionsWorksheetViewModel()
{
priceTimer = new DispatcherTimer();
priceTimer.Tick += new EventHandler(TimerHandler);
priceTimer.Interval = new TimeSpan(0, PRICE_FETCH_INTERVAL_MINS, 0);
base.DisplayName = "Options Worksheet";
PropertyChanged += OnViewModelPropertyChanged;
base.OnPropertyChanged("Title");
}
protected override void OnDispose()
{
if (null == priceTimer) return;
priceTimer.Stop();
}
private void TimerHandler(Object sender, EventArgs eventArgs)
{
if (null == underlierPrice) return;
Task workerTask = Task.Factory.StartNew(() =>
{
currentPrice = PriceCache.GetInstance().GetLatestPrice(underlierPrice.Symbol);
if (null == currentPrice || null==prices) return;
if (prices[0].Date.Date.Equals(currentPrice.Date.Date))
{
prices[0] = currentPrice;
}
else prices.Insert(0, currentPrice);
});
workerTask.ContinueWith((continuation) =>
{
base.OnPropertyChanged("CurrentPrice");
base.OnPropertyChanged("CurrentPriceDate");
base.OnPropertyChanged("Close");
base.OnPropertyChanged("TransactionGL");
});
}
// ******************************************************************************************** P E R S I S T E N C E ********************************************************************************************
public override bool CanPersist()
{
return true;
}
public override SaveParameters GetSaveParameters()
{
SaveParameters saveParams = new SaveParameters();
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Indent = false;
xmlWriterSettings.NewLineHandling = NewLineHandling.None;
XmlSerializer optionSerializer = new XmlSerializer(selectedOption.GetType());
StringBuilder optionString=new StringBuilder();
XmlWriter optionWriter = XmlWriter.Create(optionString, xmlWriterSettings);
optionSerializer.Serialize(optionWriter, selectedOption);
XmlSerializer underlierPriceSerializer = new XmlSerializer(typeof(Price));
StringBuilder underlierPriceString = new StringBuilder();
XmlWriter underlierPriceWriter = XmlWriter.Create(underlierPriceString, xmlWriterSettings);
underlierPriceSerializer.Serialize(underlierPriceWriter, underlierPrice);
saveParams.Add(new KeyValuePair<String, String>("Type", "TradeBlotter.ViewModels.OptionsWorksheetViewModel"));
saveParams.Add(new KeyValuePair<String, String>("Option", optionString.ToString()));
saveParams.Add(new KeyValuePair<String, String>("CompanyName", companyName));
saveParams.Add(new KeyValuePair<String, String>("Price", underlierPriceString.ToString()));
return saveParams;
}
public override void SetSaveParameters(SaveParameters saveParameters)
{
try
{
String strSelectedOption = (from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("Option") select item).FirstOrDefault().Value;
String strLatestPrice = (from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("Price") select item).FirstOrDefault().Value;
companyName = (from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("CompanyName") select item).FirstOrDefault().Value;
XmlSerializer optionSerializer = new XmlSerializer(typeof(Option));
StringReader stringReader = new StringReader(strSelectedOption);
selectedOption = (Option)optionSerializer.Deserialize(stringReader);
XmlSerializer priceSerializer = new XmlSerializer(typeof(Price));
StringReader priceReader = new StringReader(strLatestPrice);
underlierPrice = (Price)priceSerializer.Deserialize(priceReader);
optionsParams.Symbol = underlierPrice.Symbol;
optionsParams.Strike = selectedOption.Strike;
optionsParams.Contracts = (int)Math.Round((optionsParams.Cashdown / underlierPrice.Close) / 100.00, 0);
optionsParams.Premium = optionsParams.Shares*selectedOption.Bid;
optionsParams.ExpirationDate = selectedOption.Expiration;
// volatility
DateGenerator dateGenerator = new DateGenerator();
int daysToExpiration = dateGenerator.DaysBetweenActual(optionsParams.ExpirationDate, underlierPrice.Date);
prices = PricingDA.GetPrices(underlierPrice.Symbol, underlierPrice.Date, daysToExpiration);
if(DateTime.Now.Date>=optionsParams.ExpirationDate.Date)currentPrice=PricingDA.GetPrice(underlierPrice.Symbol,optionsParams.ExpirationDate);
else currentPrice = PriceCache.GetInstance().GetLatestPrice(underlierPrice.Symbol);
optionsParams.VolatilityDays = daysToExpiration;
float[] pricesAr = prices.GetPrices();
optionsParams.Volatility = Numerics.Volatility(ref pricesAr);
if(DateTime.Now.Date>=optionsParams.ExpirationDate.Date)prices=PricingDA.GetPrices(underlierPrice.Symbol,optionsParams.ExpirationDate,daysToExpiration);
else prices = PricingDA.GetPrices(underlierPrice.Symbol,daysToExpiration);
EquityPriceShocks equityPriceShocks = MarketData.MarketDataModel.EquityPriceShocks.CreateEquityPriceShocks(underlierPrice, optionsParams);
equityPriceShocksCollection = new ObservableCollection<EquityPriceShock>(equityPriceShocks);
if (null != underlierPrice) base.DisplayName = "Options Worksheet" + "(" + underlierPrice.Symbol + ")";
if (null == optionsParams || null == currentPrice) transactionGL=double.NaN;
else
{
if (optionsParams.Strike < currentPrice.Close)transactionGL=optionsParams.Premium + ((optionsParams.Strike * optionsParams.Shares) - (currentPrice.Close * optionsParams.Shares));
else transactionGL=optionsParams.Premium + ((currentPrice.Close * optionsParams.Shares) - (underlierPrice.Close * optionsParams.Shares));
}
base.OnPropertyChanged("Strike");
base.OnPropertyChanged("Bid");
base.OnPropertyChanged("Investment");
base.OnPropertyChanged("ExpirationDate");
base.OnPropertyChanged("Shares");
base.OnPropertyChanged("Contracts");
base.OnPropertyChanged("Premium");
base.OnPropertyChanged("EquityPriceShocks");
base.OnPropertyChanged("UnderlierPrice");
base.OnPropertyChanged("UnderlierPriceDate");
base.OnPropertyChanged("CurrentPrice");
base.OnPropertyChanged("CurrentPriceDate");
base.OnPropertyChanged("OpenInterest");
base.OnPropertyChanged("DisplayName");
base.OnPropertyChanged("Volatility");
base.OnPropertyChanged("ExpirationDateBackground");
base.OnPropertyChanged("Close");
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
}
}
// ******************************************************************************************************************************************************
// *************************************************************** M E N U S U P P O R T **************************************************************
// ******************************************************************************************************************************************************
public ObservableCollection<TradeBlotter.Model.MenuItem> MenuItems
{
get
{
ObservableCollection<TradeBlotter.Model.MenuItem> collection = new ObservableCollection<TradeBlotter.Model.MenuItem>();
collection.Add(new TradeBlotter.Model.MenuItem() { Text = "Display Moving Average", MenuItemClickedCommand = DisplayMovingAverage, StaysOpenOnClick = false });
collection.Add(new TradeBlotter.Model.MenuItem() { Text = "Display Bollinger Bands", MenuItemClickedCommand = DisplayBollingerBands, StaysOpenOnClick = false });
return collection;
}
}
public bool UseRealPrice
{
get { return useRealPrice; }
set { useRealPrice = value; base.OnPropertyChanged("UseRealPrice"); }
}
public ICommand DisplayMovingAverage
{
get
{
if (null == displayMovingAverageCommand)
{
displayMovingAverageCommand = new RelayCommand(param =>
{
SaveParameters saveParams = new SaveParameters();
saveParams.Add(new KeyValuePair<String, String>("Type", "TradeBlotter.ViewModels.MovingAverageViewModel"));
saveParams.Add(new KeyValuePair<String, String>("SelectedSymbol", underlierPrice.Symbol));
saveParams.Add(new KeyValuePair<String, String>("SelectedWatchList", Constants.CONST_ALL));
saveParams.Add(new KeyValuePair<String, String>("SelectedDayCount", "180"));
saveParams.Add(new KeyValuePair<String, String>("IsLegendVisible", "true"));
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}, param => { return null == underlierPrice ? false : true; });
}
return displayMovingAverageCommand;
}
}
public ICommand DisplayBollingerBands
{
get
{
if(null==displayBollingerBandCommand)
{
displayBollingerBandCommand = new RelayCommand(param =>
{
SaveParameters saveParams = new SaveParameters();
saveParams.Add(new KeyValuePair<String, String>("Type", "TradeBlotter.ViewModels.BollingerBandViewModel"));
saveParams.Add(new KeyValuePair<String, String>("SelectedSymbol", underlierPrice.Symbol));
saveParams.Add(new KeyValuePair<String, String>("SelectedWatchList", Constants.CONST_ALL));
saveParams.Add(new KeyValuePair<String, String>("SelectedDayCount", "90"));
saveParams.Add(new KeyValuePair<String, String>("SyncTradeToBand", "false"));
saveParams.Add(new KeyValuePair<String, String>("ShowTradeLabels", "true"));
saveParams.Add(new KeyValuePair<String, String>("IsLegendVisible", "true"));
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
;
}, param => { return null == underlierPrice ? false : true; });
}
return displayBollingerBandCommand;
}
}
public bool BusyIndicator
{
get { return busyIndicator; }
set
{
busyIndicator = value;
base.OnPropertyChanged("BusyIndicator");
}
}
public CompositeDataSource Close
{
get
{
if (null == prices) return null;
CompositeDataSource compositeDataSource = PricesModel.Close(prices);
return compositeDataSource;
}
}
public ObservableCollection<EquityPriceShock> EquityPriceShocks
{
get
{
return equityPriceShocksCollection;
}
set
{
equityPriceShocksCollection = value;
base.OnPropertyChanged("EquityPriceShocks");
}
}
private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
{
if (eventArgs.PropertyName.Equals("UseRealPrice"))
{
if (useRealPrice) priceTimer.Start();
else priceTimer.Stop();
}
}
public String TransactionGL
{
get
{
if (double.NaN.Equals(transactionGL)) return Constants.CONST_DASHES;
if (optionsParams.Strike < currentPrice.Close)return Utility.FormatCurrency(transactionGL);
return Utility.FormatCurrency(transactionGL);
}
}
public String Volatility
{
get
{
if (null == optionsParams) return Constants.CONST_DASHES;
return Utility.FormatNumber(optionsParams.Volatility, 2, true);
}
}
public String VolatilityDays
{
get
{
if (null == optionsParams) return Constants.CONST_DASHES;
return Utility.FormatNumber(optionsParams.VolatilityDays,0, true);
}
}
public String OpenInterest
{
get
{
if (null == selectedOption) return Constants.CONST_DASHES;
return Utility.FormatNumber(selectedOption.OpenInterest,0,true);
}
}
public String CurrentPrice
{
get
{
if (null == currentPrice) return Constants.CONST_DASHES;
return Utility.FormatCurrency(currentPrice.Close);
}
}
public String CurrentPriceDate
{
get
{
if (null == currentPrice) return Constants.CONST_DASHES;
return Utility.DateTimeToStringMMSDDSYYYYHHMMSS(currentPrice.Date);
}
}
public String LossPoint
{
get
{
if (null==selectedOption || null == underlierPrice) return Constants.CONST_DASHES;
return Utility.FormatCurrency(underlierPrice.Close-selectedOption.Bid);
}
}
public String UnderlierPrice
{
get
{
if (null == underlierPrice) return Constants.CONST_DASHES;
return Utility.FormatCurrency(underlierPrice.Close);
}
}
public String UnderlierPriceDate
{
get
{
if (null == underlierPrice) return Constants.CONST_DASHES;
return Utility.DateTimeToStringMMSDDSYYYY(underlierPrice.Date);
}
}
public String Premium
{
get
{
if (null == selectedOption) return Constants.CONST_DASHES;
return Utility.FormatCurrency(optionsParams.Premium);
}
}
public String Shares
{
get
{
if (null == selectedOption) return Constants.CONST_DASHES;
return Utility.FormatNumber(optionsParams.Shares,2,true);
}
}
public String Contracts
{
get
{
if (null == selectedOption) return Constants.CONST_DASHES;
return Utility.FormatNumber(optionsParams.Contracts, 0, true);
}
}
public String ExpirationDate
{
get
{
if (null == selectedOption) return Constants.CONST_DASHES;
return Utility.DateTimeToStringMMSDDSYYYY(selectedOption.Expiration);
}
}
public Brush TransactionGLBackground
{
get
{
if (null == underlierPrice) return null;
return underlierPrice.Date < DateTime.Now ? new SolidColorBrush(Colors.Green) : new SolidColorBrush(Colors.Red);
}
}
public Brush ExpirationDateBackground
{
get
{
return DateTime.Now.Date>=optionsParams.ExpirationDate.Date?new SolidColorBrush(Colors.Red):new SolidColorBrush(Colors.Green);
}
}
public String Strike
{
get
{
if (null == selectedOption) return Constants.CONST_DASHES;
return Utility.FormatCurrency(selectedOption.Strike);
}
}
public String Bid
{
get
{
if (null == selectedOption) return Constants.CONST_DASHES;
return Utility.FormatCurrency(selectedOption.Bid);
}
}
public String Investment
{
get
{
if (null == optionsParams) return Constants.CONST_DASHES;
return Utility.FormatCurrency(optionsParams.Cashdown);
}
}
public void OnErrorItemHandler(String symbol, String message)
{
}
public override String Title
{
get
{
if (null == companyName || null == optionsParams) return "Options Worksheet";
return companyName + " (" + optionsParams.Symbol + ")";
}
}
}
}