911 lines
33 KiB
C#
911 lines
33 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.Threading.Tasks;
|
|
using System.Threading;
|
|
using System.Windows.Input;
|
|
using System.Windows.Forms;
|
|
using System.Xml.Serialization;
|
|
using System.Windows.Media;
|
|
using MarketData;
|
|
using MarketData.Utils;
|
|
using MarketData.MarketDataModel;
|
|
using MarketData.Generator;
|
|
using MarketData.DataAccess;
|
|
using MarketData.Helper;
|
|
using MarketData.Numerical;
|
|
using TradeBlotter.DataAccess;
|
|
using TradeBlotter.Command;
|
|
using TradeBlotter.Model;
|
|
using TradeBlotter.Cache;
|
|
using Microsoft.Research.DynamicDataDisplay.DataSources;
|
|
using System.IO;
|
|
|
|
namespace TradeBlotter.ViewModels
|
|
{
|
|
public class OptionsViewModel : WorkspaceViewModel
|
|
{
|
|
private enum Tasks{SelectedSymbol,SelectedItem,CheckBoxFullHistory,CheckBoxCallPutRatio,SelectedExpirationDate,SelectedOptionType,SelectedWatchList,SelectedRiskFreeRateType,SelectedVolatilityDays};
|
|
private Dictionary<Tasks,Semaphore> semaphorePool=new Dictionary<Tasks,Semaphore>();
|
|
private RelayCommand launchOptionsWorksheetCommand = null;
|
|
private BollingerBands bollingerBands;
|
|
private Prices prices;
|
|
private String symbol;
|
|
private double volatility;
|
|
private List<String> symbols;
|
|
private List<String> watchLists;
|
|
private String selectedWatchList;
|
|
private RelayCommand updateCommand;
|
|
private List<String> optionTypes;
|
|
private String selectedOptionType;
|
|
private ObservableCollection<Option> optionModels = new ObservableCollection<Option>();
|
|
private ObservableCollection<Item> expirationDates=new ObservableCollection<Item>();
|
|
private Options options = null;
|
|
private List<String> riskFreeRateTypes;
|
|
private String selectedRiskFreeRateType;
|
|
private double selectedRiskFreeRate;
|
|
private DateTime selectedRiskFreeRateDate=DateTime.MinValue;
|
|
private List<Int32> volatilityDays =null;
|
|
private Int32 selectedVolatilityDays;
|
|
private String companyName;
|
|
private Option selectedItem = null;
|
|
private bool busyIndicator = false;
|
|
private Item selectedExpirationDate = null;
|
|
private bool checkBoxFullHistory = false;
|
|
private bool checkBoxFullHistoryEnabled=false;
|
|
private bool checkBoxCallPutRatio=true;
|
|
private bool checkBoxCallPutRatioEnabled=true;
|
|
private bool useLeastSquaresFit=false;
|
|
// private bool showOnlyCallPutRatio=true;
|
|
|
|
public OptionsViewModel()
|
|
{
|
|
semaphorePool.Add(Tasks.SelectedSymbol,new Semaphore(1,1));
|
|
semaphorePool.Add(Tasks.SelectedItem,new Semaphore(1,1));
|
|
semaphorePool.Add(Tasks.CheckBoxFullHistory,new Semaphore(1,1));
|
|
semaphorePool.Add(Tasks.CheckBoxCallPutRatio,new Semaphore(1,1));
|
|
semaphorePool.Add(Tasks.SelectedExpirationDate,new Semaphore(1,1));
|
|
semaphorePool.Add(Tasks.SelectedOptionType,new Semaphore(1,1));
|
|
semaphorePool.Add(Tasks.SelectedWatchList,new Semaphore(1,1));
|
|
semaphorePool.Add(Tasks.SelectedRiskFreeRateType,new Semaphore(1,1));
|
|
semaphorePool.Add(Tasks.SelectedVolatilityDays,new Semaphore(1,1));
|
|
|
|
base.DisplayName = "Options";
|
|
watchLists = WatchListDA.GetWatchLists();
|
|
watchLists.Insert(0, Constants.CONST_ALL);
|
|
selectedWatchList = watchLists.Find(x => x.Equals("Valuations"));
|
|
symbols = WatchListDA.GetWatchList(selectedWatchList);
|
|
symbols = OptionsDA.GetOptionsSymbolIn(symbols);
|
|
volatilityDays = new List<Int32>();
|
|
volatilityDays.Add(15);
|
|
volatilityDays.Add(30);
|
|
volatilityDays.Add(60);
|
|
volatilityDays.Add(90);
|
|
volatilityDays.Add(120);
|
|
volatilityDays.Add(180);
|
|
volatilityDays.Add(360);
|
|
selectedVolatilityDays = volatilityDays[0];
|
|
optionTypes = new List<String>();
|
|
optionTypes.Add("Put");
|
|
optionTypes.Add("Call");
|
|
selectedOptionType = optionTypes[0];
|
|
riskFreeRateTypes = YieldCurveData.GetRateTypesString();
|
|
selectedRiskFreeRateType = riskFreeRateTypes[3];
|
|
YieldCurve yieldCurve=YieldCurveDA.GetYieldCurve(1);
|
|
selectedRiskFreeRateDate = yieldCurve[0].Date;
|
|
selectedRiskFreeRate = yieldCurve[0].GetRate(selectedRiskFreeRateType);
|
|
base.OnPropertyChanged("RiskFreeRateTypes");
|
|
base.OnPropertyChanged("SelectedRiskFreeRateType");
|
|
base.OnPropertyChanged("SelectedRiskFreeRate");
|
|
base.OnPropertyChanged("SelectedRiskFreeRateDate");
|
|
base.OnPropertyChanged("VolatilityDays");
|
|
base.OnPropertyChanged("SelectedVolatilityDays");
|
|
PropertyChanged += OnOptionsViewModelPropertyChanged;
|
|
}
|
|
public override SaveParameters GetSaveParameters()
|
|
{
|
|
return null;
|
|
}
|
|
public override void SetSaveParameters(SaveParameters saveParameters)
|
|
{
|
|
}
|
|
public override bool CanPersist()
|
|
{
|
|
return false;
|
|
}
|
|
public ObservableCollection<TradeBlotter.Model.MenuItem> MenuItems
|
|
{
|
|
get
|
|
{
|
|
ObservableCollection<TradeBlotter.Model.MenuItem> collection = new ObservableCollection<TradeBlotter.Model.MenuItem>();
|
|
collection.Add(new TradeBlotter.Model.MenuItem() { Text = "Launch Options Worksheet", MenuItemClickedCommand = LaunchOptionsWorksheet, StaysOpenOnClick = false });
|
|
return collection;
|
|
}
|
|
}
|
|
public ICommand LaunchOptionsWorksheet
|
|
{
|
|
get
|
|
{
|
|
if (null == launchOptionsWorksheetCommand)
|
|
{
|
|
launchOptionsWorksheetCommand = new RelayCommand(param =>
|
|
{
|
|
Price latestPrice=PriceCache.GetInstance().GetLatestPrice(selectedItem.Symbol);
|
|
if(null==latestPrice)latestPrice=PricingDA.GetPrice(selectedItem.Symbol);
|
|
SaveParameters saveParams = new SaveParameters();
|
|
XmlSerializer optionSerializer = new XmlSerializer(selectedItem.GetType());
|
|
StringWriter optionStringWriter = new StringWriter();
|
|
optionSerializer.Serialize(optionStringWriter, selectedItem);
|
|
|
|
XmlSerializer priceSerializer = new XmlSerializer(typeof(Price));
|
|
StringWriter priceWriter = new StringWriter();
|
|
priceSerializer.Serialize(priceWriter, latestPrice);
|
|
|
|
saveParams.Add(new KeyValuePair<String, String>("Type", "TradeBlotter.ViewModels.OptionsWorksheetViewModel"));
|
|
saveParams.Add(new KeyValuePair<String, String>("Option",optionStringWriter.ToString()));
|
|
saveParams.Add(new KeyValuePair<String, String>("CompanyName", companyName));
|
|
saveParams.Add(new KeyValuePair<String, String>("Price", priceWriter.ToString()));
|
|
saveParams.Referer=this;
|
|
WorkspaceInstantiator.Invoke(saveParams);
|
|
}, param => { return true; });
|
|
}
|
|
return launchOptionsWorksheetCommand;
|
|
}
|
|
}
|
|
public bool BusyIndicator
|
|
{
|
|
get { return busyIndicator; }
|
|
set { busyIndicator = value; base.OnPropertyChanged("BusyIndicator"); }
|
|
}
|
|
// ***************************************************************************************************************************************************************
|
|
// *************************************************************** M A I N E V E N T H A N D L E R ***********************************************************
|
|
// ***************************************************************************************************************************************************************
|
|
private void OnOptionsViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
|
|
{
|
|
try
|
|
{
|
|
if(eventArgs.PropertyName.Equals("CheckBoxCallPutRatio"))
|
|
{
|
|
HandleCheckBoxCallPutRatio();
|
|
}
|
|
if (eventArgs.PropertyName.Equals("CheckBoxFullHistory"))
|
|
{
|
|
HandleCheckBoxFullHistory();
|
|
}
|
|
if (eventArgs.PropertyName.Equals("SelectedSymbol") && null != symbol)
|
|
{
|
|
HandleSelectedSymbol();
|
|
}
|
|
else if (eventArgs.PropertyName.Equals("SelectedExpirationDate"))
|
|
{
|
|
HandleSelectedExpirationDate();
|
|
}
|
|
else if (eventArgs.PropertyName.Equals("SelectedOptionType") && null != symbol)
|
|
{
|
|
HandleSelectedOptionType();
|
|
}
|
|
else if (eventArgs.PropertyName.Equals("SelectedWatchList"))
|
|
{
|
|
HandleSelectedWatchList();
|
|
}
|
|
else if (eventArgs.PropertyName.Equals("SelectedRiskFreeRateType"))
|
|
{
|
|
HandleSelectedRiskFreeRateType();
|
|
}
|
|
else if (eventArgs.PropertyName.Equals("SelectedVolatilityDays"))
|
|
{
|
|
HandleSelectedVolatilityDays();
|
|
}
|
|
else if (eventArgs.PropertyName.Equals("SelectedItem"))
|
|
{
|
|
HandleSelectedItem();
|
|
}
|
|
else if(eventArgs.PropertyName.Equals("LeastSquaresFit"))
|
|
{
|
|
base.OnPropertyChanged("LeastSquares");
|
|
}
|
|
}
|
|
catch(Exception /*e*/)
|
|
{
|
|
}
|
|
finally
|
|
{
|
|
}
|
|
}
|
|
private void HandleCheckBoxCallPutRatio()
|
|
{
|
|
try
|
|
{
|
|
semaphorePool[Tasks.CheckBoxCallPutRatio].WaitOne();
|
|
if(!checkBoxCallPutRatioEnabled)return;
|
|
SelectedItem=null;
|
|
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("OnOptionsViewModelPropertyChanged:CheckBoxCallPutRatio:{0}", symbol));
|
|
base.OnPropertyChanged("SelectedSymbol");
|
|
}
|
|
finally
|
|
{
|
|
semaphorePool[Tasks.CheckBoxCallPutRatio].Release();
|
|
}
|
|
}
|
|
private void HandleCheckBoxFullHistory()
|
|
{
|
|
try
|
|
{
|
|
semaphorePool[Tasks.CheckBoxFullHistory].WaitOne();
|
|
if(!checkBoxFullHistoryEnabled)return;
|
|
SelectedItem=null;
|
|
MDTrace.WriteLine(LogLevel.DEBUG, String.Format("OnOptionsViewModelPropertyChanged:CheckBoxFullHistory:{0}", symbol));
|
|
base.OnPropertyChanged("SelectedSymbol");
|
|
}
|
|
finally
|
|
{
|
|
semaphorePool[Tasks.CheckBoxFullHistory].Release();
|
|
}
|
|
}
|
|
private void HandleSelectedSymbol()
|
|
{
|
|
try
|
|
{
|
|
semaphorePool[Tasks.SelectedSymbol].WaitOne();
|
|
MDTrace.WriteLine(LogLevel.DEBUG, String.Format("OnOptionsViewModelPropertyChanged:SelectedSymbol:{0}", symbol));
|
|
checkBoxFullHistoryEnabled=true;
|
|
SelectedItem=null;
|
|
BusyIndicator = true;
|
|
base.DisplayName="Options"+"("+symbol+")";
|
|
Task workerTask = Task.Factory.StartNew(() =>
|
|
{
|
|
companyName = PricingDA.GetNameForSymbol(SelectedSymbol);
|
|
if(checkBoxFullHistory)options=OptionsDA.GetOptions(symbol);
|
|
else options = OptionsDA.GetOptions(symbol,DateTime.Now);
|
|
if (null == options || 0 == options.Count)
|
|
{
|
|
App.Current.Dispatcher.Invoke((Action)delegate
|
|
{
|
|
optionModels.Clear();
|
|
expirationDates.Clear();
|
|
});
|
|
base.OnPropertyChanged("AllOptions");
|
|
base.OnPropertyChanged("ExpirationDates");
|
|
return;
|
|
}
|
|
PutCallRatioHelper.CalculatePutCallRatios(options);
|
|
if(checkBoxCallPutRatio)options=new Options((from Option option in options where (option.Type.Equals(OptionTypeEnum.CallOption) && !option.CallPutRatio.Equals(double.NaN))||(option.Type.Equals(OptionTypeEnum.PutOption) && !option.PutCallRatio.Equals(double.NaN)) select option).ToList());
|
|
IEnumerable<Option> selectedOptions = null;
|
|
OptionTypeEnum optionType = selectedOptionType.Equals("Call") ? OptionTypeEnum.CallOption : OptionTypeEnum.PutOption;
|
|
selectedOptions = from option in options where option.Type.Equals(optionType) select option;
|
|
if(!selectedOptions.Any())
|
|
{
|
|
App.Current.Dispatcher.Invoke((Action)delegate
|
|
{
|
|
optionModels.Clear();
|
|
expirationDates.Clear();
|
|
});
|
|
base.OnPropertyChanged("AllOptions");
|
|
base.OnPropertyChanged("ExpirationDates");
|
|
return;
|
|
}
|
|
var selection = from option in selectedOptions select option.Expiration;
|
|
IEnumerable<DateTime> distinctDates = selection.Distinct();
|
|
App.Current.Dispatcher.Invoke((Action)delegate
|
|
{
|
|
expirationDates.Clear();
|
|
for (int index = 0; index < distinctDates.Count<DateTime>(); index++)
|
|
{
|
|
expirationDates.Add(new Item(Utility.DateTimeToStringMMHDDHYYYY(distinctDates.ElementAt(index))));
|
|
}
|
|
selectedExpirationDate=expirationDates[0];
|
|
});
|
|
UpdateOptionValues();
|
|
});
|
|
workerTask.ContinueWith((continuation) =>
|
|
{
|
|
BusyIndicator = false;
|
|
UpdateGraphs();
|
|
base.OnPropertyChanged("DisplayName");
|
|
base.OnPropertyChanged("ExpirationDates");
|
|
base.OnPropertyChanged("SelectedExpirationDate");
|
|
base.OnPropertyChanged("UnderlyingPrice");
|
|
base.OnPropertyChanged("PricingDate");
|
|
base.OnPropertyChanged("Title");
|
|
base.OnPropertyChanged("CheckBoxFullHistoryEnabled");
|
|
base.OnPropertyChanged("CheckBoxCallPutRatioEnabled");
|
|
});
|
|
}
|
|
finally
|
|
{
|
|
semaphorePool[Tasks.SelectedSymbol].Release();
|
|
}
|
|
}
|
|
private void HandleSelectedExpirationDate()
|
|
{
|
|
try
|
|
{
|
|
semaphorePool[Tasks.SelectedExpirationDate].WaitOne();
|
|
MDTrace.WriteLine(String.Format("OnOptionsViewModelPropertyChanged:SelectedExpirationDate:{0}", symbol));
|
|
selectedItem = null;
|
|
IEnumerable<Option> selectedOptions = null;
|
|
if (null == options || null == selectedExpirationDate)
|
|
{
|
|
MDTrace.WriteLine("null == options || null==selectedExpirationDate");
|
|
bollingerBands = null;
|
|
UpdateGraphs();
|
|
return;
|
|
}
|
|
MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Selected Expiration Date:{0}", selectedExpirationDate.Value));
|
|
selectedOptions = from option in options where option.Expiration.Date.Equals(DateTime.Parse(selectedExpirationDate.Value).Date) select option;
|
|
if (null != selectedOptionType)
|
|
{
|
|
OptionTypeEnum optionType = selectedOptionType.Equals("Call") ? OptionTypeEnum.CallOption : OptionTypeEnum.PutOption;
|
|
selectedOptions = from option in selectedOptions where option.Type.Equals(optionType) select option;
|
|
}
|
|
optionModels = new ObservableCollection<Option>(selectedOptions);
|
|
Option topItem = optionModels.FirstOrDefault();
|
|
if (topItem.Expiration < DateTime.Now) prices = PricingDA.GetPrices(symbol, topItem.Expiration, selectedVolatilityDays);
|
|
else prices = PricingDA.GetPrices(symbol, selectedVolatilityDays);
|
|
if (selectedVolatilityDays < 40)
|
|
{
|
|
Prices bollingerBandPrices = null;
|
|
if (topItem.Expiration < DateTime.Now) bollingerBandPrices = PricingDA.GetPrices(symbol, topItem.Expiration, 40);
|
|
else bollingerBandPrices = PricingDA.GetPrices(symbol, 40);
|
|
bollingerBands = BollingerBandGenerator.GenerateBollingerBands(bollingerBandPrices);
|
|
if (null != bollingerBandPrices) MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Bollinger Band Prices(<40) - {0} Min:{1} Max:{2}", symbol, bollingerBandPrices[0].Date, bollingerBandPrices[bollingerBandPrices.Count - 1].Date));
|
|
else MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No price for {0}",symbol));
|
|
}
|
|
else
|
|
{
|
|
if(null!=prices)MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Bollinger Band Prices - {0} Min:{1} Max:{2}", symbol, prices[0].Date, prices[prices.Count - 1].Date));
|
|
else MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No prices for symbol {0}", symbol));
|
|
bollingerBands = BollingerBandGenerator.GenerateBollingerBands(prices);
|
|
}
|
|
if (null != prices && 0 != prices.Count)
|
|
{
|
|
float[] closingPrices = prices.GetPrices();
|
|
volatility = Numerics.Volatility(ref closingPrices);
|
|
base.OnPropertyChanged("Volatility");
|
|
}
|
|
UpdateOptionValues();
|
|
UpdateGraphs();
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
|
|
}
|
|
finally
|
|
{
|
|
semaphorePool[Tasks.SelectedExpirationDate].Release();
|
|
}
|
|
}
|
|
private void HandleSelectedOptionType()
|
|
{
|
|
try
|
|
{
|
|
semaphorePool[Tasks.SelectedOptionType].WaitOne();
|
|
MDTrace.WriteLine(LogLevel.DEBUG, String.Format("OnOptionsViewModelPropertyChanged:SelectedOptionType:{0}", selectedOptionType));
|
|
SelectedItem=null;
|
|
BusyIndicator = true;
|
|
Task workerTask = Task.Factory.StartNew(() =>
|
|
{
|
|
IEnumerable<Option> selectedOptions = null;
|
|
OptionTypeEnum optionType = selectedOptionType.Equals("Call") ? OptionTypeEnum.CallOption : OptionTypeEnum.PutOption;
|
|
if (null == options || 0 == options.Count) return;
|
|
selectedOptions = from option in options where option.Type.Equals(optionType) select option;
|
|
selectedOptions = from option in selectedOptions where option.Expiration.Date.Equals(DateTime.Parse(selectedExpirationDate.Value).Date) select option;
|
|
Option newSelection=selectedOptions.FirstOrDefault();
|
|
optionModels = new ObservableCollection<Option>(selectedOptions);
|
|
UpdateOptionValues();
|
|
});
|
|
workerTask.ContinueWith((continuation) =>
|
|
{
|
|
BusyIndicator = false;
|
|
base.OnPropertyChanged("SelectedItem");
|
|
UpdateGraphs();
|
|
});
|
|
}
|
|
finally
|
|
{
|
|
semaphorePool[Tasks.SelectedOptionType].Release();
|
|
}
|
|
}
|
|
private void HandleSelectedWatchList()
|
|
{
|
|
try
|
|
{
|
|
semaphorePool[Tasks.SelectedWatchList].WaitOne();
|
|
MDTrace.WriteLine(LogLevel.DEBUG, "OnOptionsViewModelPropertyChanged:SelectedWatchList");
|
|
// if (selectedWatchList.Equals(Constants.CONST_ALL)) symbols = PricingDA.GetSymbols();
|
|
if (selectedWatchList.Equals(Constants.CONST_ALL)) symbols = SymbolCache.GetInstance().GetSymbols();
|
|
else symbols = WatchListDA.GetWatchList(selectedWatchList);
|
|
symbols = OptionsDA.GetOptionsSymbolIn(symbols);
|
|
base.OnPropertyChanged("Symbols");
|
|
}
|
|
finally
|
|
{
|
|
semaphorePool[Tasks.SelectedWatchList].Release();
|
|
}
|
|
}
|
|
private void HandleSelectedRiskFreeRateType()
|
|
{
|
|
try
|
|
{
|
|
semaphorePool[Tasks.SelectedRiskFreeRateType].WaitOne();
|
|
MDTrace.WriteLine(LogLevel.DEBUG, "OnOptionsViewModelPropertyChanged:SelectedRiskFreeRateType");
|
|
YieldCurve yieldCurve = YieldCurveDA.GetYieldCurve(1);
|
|
selectedRiskFreeRate = yieldCurve[0].GetRate(selectedRiskFreeRateType);
|
|
selectedRiskFreeRateDate = yieldCurve[0].Date;
|
|
UpdateOptionValues();
|
|
base.OnPropertyChanged("SelectedRiskFreeRate");
|
|
base.OnPropertyChanged("SelectedRiskFreeRateDate");
|
|
}
|
|
finally
|
|
{
|
|
semaphorePool[Tasks.SelectedRiskFreeRateType].Release();
|
|
}
|
|
}
|
|
public void HandleSelectedVolatilityDays()
|
|
{
|
|
try
|
|
{
|
|
semaphorePool[Tasks.SelectedVolatilityDays].WaitOne();
|
|
MDTrace.WriteLine(LogLevel.DEBUG, "OnOptionsViewModelPropertyChanged:SelectedVolatilityDays");
|
|
DateTime expirationDate=DateTime.Parse(selectedExpirationDate.Value);
|
|
if(expirationDate<DateTime.Now)prices=PricingDA.GetPrices(symbol,expirationDate,selectedVolatilityDays);
|
|
else prices = PricingDA.GetPrices(symbol, selectedVolatilityDays);
|
|
if (null != prices && 0 != prices.Count)
|
|
{
|
|
float[] closingPrices = prices.GetPrices();
|
|
volatility = Numerics.Volatility(ref closingPrices);
|
|
base.OnPropertyChanged("Volatility");
|
|
}
|
|
if (selectedVolatilityDays < 40)
|
|
{
|
|
Prices bollingerBandPrices=null;
|
|
if(expirationDate<DateTime.Now)bollingerBandPrices=PricingDA.GetPrices(symbol,expirationDate,40);
|
|
else bollingerBandPrices = PricingDA.GetPrices(symbol, 40);
|
|
bollingerBands = BollingerBandGenerator.GenerateBollingerBands(bollingerBandPrices);
|
|
}
|
|
else bollingerBands = BollingerBandGenerator.GenerateBollingerBands(prices);
|
|
UpdateOptionValues();
|
|
UpdateGraphs();
|
|
}
|
|
finally
|
|
{
|
|
semaphorePool[Tasks.SelectedVolatilityDays].Release();
|
|
}
|
|
}
|
|
private void HandleSelectedItem()
|
|
{
|
|
try
|
|
{
|
|
semaphorePool[Tasks.SelectedItem].WaitOne();
|
|
if(null==selectedItem)return;
|
|
MDTrace.WriteLine(LogLevel.DEBUG, "OnOptionsViewModelPropertyChanged:SelectedItem");
|
|
base.OnPropertyChanged("SelectedOptionStrikePoints");
|
|
}
|
|
finally
|
|
{
|
|
semaphorePool[Tasks.SelectedItem].Release();
|
|
}
|
|
}
|
|
public Boolean LeastSquaresFit
|
|
{
|
|
get
|
|
{
|
|
return useLeastSquaresFit;
|
|
}
|
|
set
|
|
{
|
|
useLeastSquaresFit = value;
|
|
base.OnPropertyChanged("LeastSquaresFit");
|
|
}
|
|
}
|
|
// ************************************************************************************************************************************************************
|
|
// ***************************************************************************************************************************************************************
|
|
// ***************************************************************************************************************************************************************
|
|
public String RatioDescription
|
|
{
|
|
get
|
|
{
|
|
if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
|
|
StringBuilder sb=new StringBuilder();
|
|
sb.Append("The contrarian viewpoint is to trade against the positions of option traders. \nA high put/call ratio may indicate a buying opportunity while a low put/call ration may indicate a pullback.\n");
|
|
if(selectedOptionType.Equals("Put"))
|
|
{
|
|
Option option=optionModels.OrderByDescending(x=>x.PutCallRatio).First();
|
|
sb.Append(String.Format("The highest put/call ratio for {0} {1} expiry is the {2} strike.",selectedItem.Symbol,Utility.DateTimeToStringMMHDDHYYYY(selectedItem.Expiration),Utility.FormatCurrency(option.Strike)));
|
|
}
|
|
else
|
|
{
|
|
Option option=optionModels.OrderByDescending(x=>x.CallPutRatio).First();
|
|
sb.Append(String.Format("The highest call/put ratio for {0} {1} expiry is the {2} strike.",selectedItem.Symbol,Utility.DateTimeToStringMMHDDHYYYY(selectedItem.Expiration),Utility.FormatCurrency(option.Strike)));
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
public ObservableCollection<Option> AllOptions
|
|
{
|
|
get { return optionModels; }
|
|
}
|
|
public List<String> OptionTypes
|
|
{
|
|
get
|
|
{
|
|
return optionTypes;
|
|
}
|
|
}
|
|
public String SelectedOptionType
|
|
{
|
|
get { return selectedOptionType; }
|
|
set{selectedOptionType=value;base.OnPropertyChanged("SelectedOptionType");}
|
|
}
|
|
public ObservableCollection<Item> ExpirationDates
|
|
{
|
|
get
|
|
{
|
|
return expirationDates;
|
|
}
|
|
}
|
|
public List<String> Symbols
|
|
{
|
|
get
|
|
{
|
|
return symbols;
|
|
}
|
|
}
|
|
public String SelectedSymbol
|
|
{
|
|
get { return symbol; }
|
|
set
|
|
{
|
|
if (value == symbol || String.IsNullOrEmpty(value)) return;
|
|
symbol = value;
|
|
checkBoxFullHistory=false;
|
|
base.OnPropertyChanged("CheckBoxFullHistory");
|
|
base.OnPropertyChanged("SelectedSymbol");
|
|
}
|
|
}
|
|
public override String Title
|
|
{
|
|
get
|
|
{
|
|
if (null == companyName || null == SelectedSymbol) return null;
|
|
return companyName+" ("+SelectedSymbol+")";
|
|
}
|
|
}
|
|
public List<String> WatchListNames
|
|
{
|
|
get
|
|
{
|
|
return watchLists;
|
|
}
|
|
set { ;}
|
|
}
|
|
public String SelectedWatchList
|
|
{
|
|
get { return selectedWatchList; }
|
|
set { selectedWatchList = value; base.OnPropertyChanged("SelectedWatchList"); }
|
|
}
|
|
|
|
public List<String> RiskFreeRateTypes
|
|
{
|
|
get
|
|
{
|
|
return riskFreeRateTypes;
|
|
}
|
|
}
|
|
public String SelectedRiskFreeRateType
|
|
{
|
|
get
|
|
{
|
|
return selectedRiskFreeRateType;
|
|
}
|
|
set
|
|
{
|
|
selectedRiskFreeRateType = value;
|
|
base.OnPropertyChanged("SelectedRiskFreeRateType");
|
|
}
|
|
}
|
|
public double SelectedRiskFreeRate
|
|
{
|
|
get
|
|
{
|
|
return selectedRiskFreeRate;
|
|
}
|
|
set
|
|
{
|
|
selectedRiskFreeRate = value;
|
|
base.OnPropertyChanged("SelectedRiskFreeRate");
|
|
}
|
|
}
|
|
public DateTime SelectedRiskFreeRateDate
|
|
{
|
|
get
|
|
{
|
|
return selectedRiskFreeRateDate;
|
|
}
|
|
set
|
|
{
|
|
selectedRiskFreeRateDate = value;
|
|
base.OnPropertyChanged("SelectedRiskFreeRateDate");
|
|
}
|
|
}
|
|
public List<Int32> VolatilityDays
|
|
{
|
|
get
|
|
{
|
|
return volatilityDays;
|
|
}
|
|
}
|
|
public Int32 SelectedVolatilityDays
|
|
{
|
|
get
|
|
{
|
|
return selectedVolatilityDays;
|
|
}
|
|
set
|
|
{
|
|
selectedVolatilityDays = value;
|
|
base.OnPropertyChanged("SelectedVolatilityDays");
|
|
}
|
|
}
|
|
public String UnderlyingPrice
|
|
{
|
|
get
|
|
{
|
|
if (null == prices || 0 == prices.Count) return Constants.CONST_DASHES;
|
|
return Utility.FormatCurrency(prices[0].Close);
|
|
}
|
|
}
|
|
public String PricingDate
|
|
{
|
|
get
|
|
{
|
|
if (null == prices || 0 == prices.Count) return Constants.CONST_DASHES;
|
|
return Utility.DateTimeToStringMMSDDSYYYY(prices[0].Date);
|
|
}
|
|
}
|
|
public String Volatility
|
|
{
|
|
get
|
|
{
|
|
if (double.IsNaN(volatility)) return Constants.CONST_DASHES;
|
|
return Utility.FormatNumber(volatility);
|
|
}
|
|
}
|
|
private void Update()
|
|
{
|
|
try
|
|
{
|
|
BusyIndicator = true;
|
|
Task workerTask=Task.Factory.StartNew(()=>
|
|
{
|
|
if (null == symbol) return;
|
|
Options options = MarketDataHelper.GetOptions(symbol);
|
|
if (null == options || 0 == options.Count) return;
|
|
if (OptionsDA.AddOptions(options)) MessageBox.Show(String.Format("Added {0} records for {1}", options.Count, symbol));
|
|
else MessageBox.Show(String.Format("Failed to add options chain for {0}", symbol));
|
|
});
|
|
workerTask.ContinueWith((continuation) =>
|
|
{
|
|
BusyIndicator = false;
|
|
base.OnPropertyChanged("SelectedSymbol");
|
|
});
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
BusyIndicator = false;
|
|
MessageBox.Show(exception.ToString());
|
|
}
|
|
}
|
|
private bool CanUpdate
|
|
{
|
|
get { return true; }
|
|
}
|
|
public ICommand UpdateCommand
|
|
{
|
|
get
|
|
{
|
|
if (updateCommand == null)
|
|
{
|
|
updateCommand = new RelayCommand(param => this.Update(), param => this.CanUpdate);
|
|
}
|
|
return updateCommand;
|
|
}
|
|
}
|
|
private void UpdateOptionValues()
|
|
{
|
|
if (null == optionModels) return;
|
|
DateGenerator dateGenerator = new DateGenerator();
|
|
foreach(Option option in optionModels)
|
|
{
|
|
int days = dateGenerator.DaysBetween(option.Expiration, prices[0].Date);
|
|
double fractionOfYear = days / 360.00;
|
|
double optionValue = BlackScholesOptionPricingModel.GetPrice(option.Type, prices[0].Close, option.Strike, fractionOfYear, selectedRiskFreeRate/100.00, volatility);
|
|
option.OptionValue = optionValue;
|
|
option.MoneyType.SetMoney(prices[0].Close, option.Strike);
|
|
}
|
|
if(checkBoxCallPutRatio)optionModels = new ObservableCollection<Option>(optionModels.OrderByDescending(x=>x.Ratio));
|
|
else optionModels = new ObservableCollection<Option>(optionModels.OrderByDescending(x=>x.Strike));
|
|
base.OnPropertyChanged("AllOptions");
|
|
}
|
|
// BollingerBands
|
|
private void UpdateGraphs()
|
|
{
|
|
base.OnPropertyChanged("SelectedOptionStrikePoints");
|
|
base.OnPropertyChanged("OptionStrikePoints");
|
|
base.OnPropertyChanged("K");
|
|
base.OnPropertyChanged("KL1");
|
|
base.OnPropertyChanged("L");
|
|
base.OnPropertyChanged("LP1");
|
|
base.OnPropertyChanged("High");
|
|
base.OnPropertyChanged("Low");
|
|
base.OnPropertyChanged("Close");
|
|
base.OnPropertyChanged("SMAN");
|
|
base.OnPropertyChanged("LeastSquares");
|
|
}
|
|
public CompositeDataSource K
|
|
{
|
|
get
|
|
{
|
|
CompositeDataSource compositeDataSource = BollingerBandModel.K(bollingerBands);
|
|
return compositeDataSource;
|
|
}
|
|
}
|
|
public CompositeDataSource KL1
|
|
{
|
|
get
|
|
{
|
|
CompositeDataSource compositeDataSource = BollingerBandModel.KL1(bollingerBands);
|
|
return compositeDataSource;
|
|
}
|
|
}
|
|
public CompositeDataSource L
|
|
{
|
|
get
|
|
{
|
|
CompositeDataSource compositeDataSource = BollingerBandModel.L(bollingerBands);
|
|
return compositeDataSource;
|
|
}
|
|
}
|
|
public CompositeDataSource LP1
|
|
{
|
|
get
|
|
{
|
|
CompositeDataSource compositeDataSource = BollingerBandModel.LP1(bollingerBands);
|
|
return compositeDataSource;
|
|
}
|
|
}
|
|
public CompositeDataSource High
|
|
{
|
|
get
|
|
{
|
|
CompositeDataSource compositeDataSource = BollingerBandModel.High(bollingerBands);
|
|
return compositeDataSource;
|
|
}
|
|
}
|
|
public CompositeDataSource Low
|
|
{
|
|
get
|
|
{
|
|
CompositeDataSource compositeDataSource = BollingerBandModel.Low(bollingerBands);
|
|
return compositeDataSource;
|
|
}
|
|
}
|
|
public CompositeDataSource Close
|
|
{
|
|
get
|
|
{
|
|
CompositeDataSource compositeDataSource = BollingerBandModel.Close(bollingerBands);
|
|
return compositeDataSource;
|
|
}
|
|
}
|
|
public CompositeDataSource SMAN
|
|
{
|
|
get
|
|
{
|
|
CompositeDataSource compositeDataSource = BollingerBandModel.SMAN(bollingerBands);
|
|
return compositeDataSource;
|
|
}
|
|
}
|
|
public CompositeDataSource LeastSquares
|
|
{
|
|
get
|
|
{
|
|
if(!useLeastSquaresFit||null==bollingerBands||null==selectedExpirationDate||null==selectedExpirationDate.Value)return null;
|
|
CompositeDataSource compositeDataSourceLeastSquares=null;
|
|
compositeDataSourceLeastSquares=BollingerBandModel.LeastSquaresExtend(bollingerBands,DateTime.Parse(selectedExpirationDate.Value));
|
|
return compositeDataSourceLeastSquares;
|
|
}
|
|
}
|
|
// ***************************************************************************************************
|
|
public CompositeDataSource OptionStrikePoints
|
|
{
|
|
get
|
|
{
|
|
if(null==selectedExpirationDate || null==selectedOptionType)return new CompositeDataSource();
|
|
OptionTypeEnum optionType = selectedOptionType.Equals("Call") ? OptionTypeEnum.CallOption : OptionTypeEnum.PutOption;
|
|
List<Option> optionsList = (from option in options where option.Expiration.Date.Equals(DateTime.Parse(selectedExpirationDate.Value).Date) && option.Type.Equals(optionType) select option).ToList();
|
|
OptionStrikes optionStrikes = new OptionStrikes();
|
|
foreach (Option option in optionsList) optionStrikes.Add(new OptionStrike(option.Expiration,option.Strike));
|
|
CompositeDataSource compositeDataSource = OptionStrikeModel.OptionStrikes(optionStrikes);
|
|
return compositeDataSource;
|
|
}
|
|
}
|
|
public CompositeDataSource SelectedOptionStrikePoints
|
|
{
|
|
get
|
|
{
|
|
if (null == selectedItem)return new CompositeDataSource();
|
|
MDTrace.WriteLine(LogLevel.DEBUG, "SelectedOptionStrikePoints:returning composite");
|
|
OptionStrikes optionStrikes = new OptionStrikes();
|
|
optionStrikes.Add(new OptionStrike(selectedItem.Expiration, selectedItem.Strike));
|
|
CompositeDataSource compositeDataSource = OptionStrikeModel.OptionStrikes(optionStrikes);
|
|
return compositeDataSource;
|
|
}
|
|
}
|
|
//***********************************************************
|
|
public Option SelectedItem
|
|
{
|
|
get
|
|
{
|
|
return selectedItem;
|
|
}
|
|
set
|
|
{
|
|
selectedItem = value;
|
|
base.OnPropertyChanged("SelectedItem");
|
|
}
|
|
}
|
|
public Item SelectedExpirationDate
|
|
{
|
|
get
|
|
{
|
|
return selectedExpirationDate;
|
|
}
|
|
set
|
|
{
|
|
selectedExpirationDate = value;
|
|
base.OnPropertyChanged("SelectedExpirationDate");
|
|
}
|
|
}
|
|
|
|
public bool CheckBoxCallPutRatioEnabled
|
|
{
|
|
get{return checkBoxCallPutRatioEnabled;}
|
|
}
|
|
public bool CheckBoxCallPutRatio
|
|
{
|
|
get
|
|
{
|
|
return checkBoxCallPutRatio;
|
|
}
|
|
set
|
|
{
|
|
checkBoxCallPutRatio=value;
|
|
base.OnPropertyChanged("CheckBoxCallPutRatio");
|
|
}
|
|
}
|
|
// ************************************************
|
|
public bool CheckBoxFullHistoryEnabled
|
|
{
|
|
get{return checkBoxFullHistoryEnabled;}
|
|
}
|
|
public bool CheckBoxFullHistory
|
|
{
|
|
get
|
|
{
|
|
return checkBoxFullHistory;
|
|
}
|
|
set
|
|
{
|
|
checkBoxFullHistory=value;
|
|
base.OnPropertyChanged("CheckBoxFullHistory");
|
|
}
|
|
}
|
|
// ************************************************
|
|
}
|
|
}
|