Files
TradeBlotter/ViewModels/TradeModelViewModel.cs
2024-05-24 15:12:29 -04:00

296 lines
11 KiB
C#

using System;
using System.Windows.Input;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Threading.Tasks;
using System.Windows;
using System.Linq;
using System.Text;
using MarketData;
using MarketData.Utils;
using MarketData.DataAccess;
using MarketData.MarketDataModel;
using MarketData.Generator;
using TradeBlotter.DataAccess;
using TradeBlotter.Command;
using TradeBlotter.Cache;
using TradeBlotter.Model;
namespace TradeBlotter.ViewModels
{
public class TradeModelViewModel : WorkspaceViewModel
{
private RelayCommand runModelCommand;
private List<String> watchLists;
private String selectedWatchList;
private List<String> symbols;
private String selectedSymbol;
private DateTime? selectedStartDate;
private Items models = new Items();
private int selectedModelIndex = 0;
private int selectedSymbolIndex = 0;
private double stopLossThreshold;
private int stopLossDays;
private double investment = 10000;
private TradeResultList tradeResults = null;
private ObservableCollection<TradeResultSummary> tradeResultSummary = null;
private bool busyIndicator = false;
public TradeModelViewModel()
{
DateGenerator dateGenerator=new DateGenerator();
base.DisplayName = "TradeModel";
PropertyChanged += OnTradeModelViewModelPropertyChanged;
watchLists = WatchListDA.GetWatchLists();
watchLists.Insert(0, Constants.CONST_ALL);
selectedWatchList = watchLists.Find(x => x.Equals("Valuations"));
models.Add(new Item("MACD(8,17,9)"));
models.Add(new Item("MACD(12,26,9)"));
models.Add(new Item("Swing Trade"));
models.Add(new Item("Band Break"));
selectedModelIndex = 0;
selectedStartDate = new DateTime(DateTime.Now.Year, 1, 1);
base.OnPropertyChanged("SelectedModelIndex");
base.OnPropertyChanged("SelectedWatchList");
base.OnPropertyChanged("SelectedSymbolIndex");
}
public override SaveParameters GetSaveParameters()
{
return null;
}
public override void SetSaveParameters(SaveParameters saveParameters)
{
}
public override bool CanPersist()
{
return false;
}
protected override void OnDispose()
{
}
public bool BusyIndicator
{
get {return busyIndicator; }
set { busyIndicator = false; }
}
private void OnTradeModelViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
{
if (eventArgs.PropertyName.Equals("SelectedModelIndex") || (eventArgs.PropertyName.Equals("SelectedModel") && null != selectedSymbol))
{
}
else if (eventArgs.PropertyName.Equals("SelectedSymbol") || (eventArgs.PropertyName.Equals("SelectedDayCount") && null != selectedSymbol))
{
}
else if (eventArgs.PropertyName.Equals("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);
base.OnPropertyChanged("Symbols");
selectedSymbolIndex = 0;
base.OnPropertyChanged("SelectedSymbolIndex");
}
}
public IList<Item> Models
{
get
{
return models;
}
}
public int SelectedModelIndex
{
get { return selectedModelIndex; }
set
{
selectedModelIndex = value;
base.OnPropertyChanged("SelectedModelIndex");
}
}
public int SelectedSymbolIndex
{
get { return selectedSymbolIndex; }
set
{
selectedSymbolIndex = value;
base.OnPropertyChanged("SelectedSymbolIndex");
}
}
public List<String> Symbols
{
get
{
return symbols;
}
}
public String SelectedSymbol
{
get { return selectedSymbol; }
set
{
if (value == selectedSymbol || String.IsNullOrEmpty(value)) return;
selectedSymbol = value;
selectedSymbol = selectedSymbol.ToUpper();
base.OnPropertyChanged("SelectedSymbol");
}
}
public List<String> WatchListNames
{
get
{
return watchLists;
}
set { ;}
}
public String SelectedWatchList
{
get { return selectedWatchList; }
set { selectedWatchList = value; base.OnPropertyChanged("SelectedWatchList"); }
}
public DateTime? SelectedStartDate
{
get { return selectedStartDate; }
set
{
DateTime today = DateTime.Now;
selectedStartDate = value;
if (selectedStartDate.Value.Date >= today.Date)
{
MessageBox.Show("start date must be less than today", "Error");
DateGenerator dateGenerator = new DateGenerator();
selectedStartDate = dateGenerator.GenerateHistoricalDate(DateTime.Now, 2);
base.OnPropertyChanged("SelectedStartDate");
return;
}
base.OnPropertyChanged("SelectedStartDate");
}
}
public double StopLossThreshold
{
get { return stopLossThreshold; }
set { stopLossThreshold = value; base.OnPropertyChanged("StopLossThreshold"); }
}
public int StopLossDays
{
get { return stopLossDays; }
set { stopLossDays = value; base.OnPropertyChanged("StopLossDays"); }
}
public double Investment
{
get { return investment; }
set { investment = value; base.OnPropertyChanged("Investment"); }
}
//**************************************************************************************************************************
//******************************************************** R U N M O D E L ***************************************************
//**************************************************************************************************************************
public ObservableCollection<TradeBlotter.Model.TradeResult> TradeResults
{
get
{
return null==tradeResults?null:new ObservableCollection<TradeBlotter.Model.TradeResult>(tradeResults);
}
}
public ObservableCollection<TradeResultSummary> TradeResultsSummary
{
get
{
return tradeResultSummary;
}
}
private void RunModel()
{
String selectedModel=models[selectedModelIndex].Value;
if (selectedModel.Equals("MACD(8,17,9)") || selectedModel.Equals("MACD(12,26,9)")) RunMACDModel(selectedModel);
else MessageBox.Show(selectedModel+" is not supported.");
}
private void RunMACDModel(String selctedModel)
{
DateGenerator dateGenerator = new DateGenerator();
MACDSetup macdSetup = null;
DateRange tradeDates = new DateRange(selectedStartDate.Value, DateTime.Now);
if (double.IsNaN(stopLossThreshold)) stopLossThreshold = 0;
try
{
BusyIndicator = true;
Task workerTask = Task.Factory.StartNew(() =>
{
DateTime latestPricingDate = PricingDA.GetLatestDate(selectedSymbol);
String companyName = PricingDA.GetNameForSymbol(selectedSymbol);
if (models[selectedModelIndex].Value.Equals("MACD(8,17,9)")) macdSetup = new MACDSetup(8, 17, 9);
else if (models[selectedModelIndex].Value.Equals("MACD(12,26,9)")) macdSetup = new MACDSetup(12, 26, 9);
DateTime historicalDate = dateGenerator.GenerateHistoricalDate(selectedStartDate.Value, macdSetup.Slow);
if (latestPricingDate < historicalDate)
{
MessageBox.Show("The historical date you are trying to run is later than the latest date for which prices are available.");
return;
}
if (selectedStartDate.Value > DateTime.Now)
{
MessageBox.Show("The start date must be in the past.");
return;
}
Dictionary<DateTime, Price> pricesByDate = new Dictionary<DateTime, Price>();
Prices prices = PricingDA.GetPrices(selectedSymbol, DateTime.Now, historicalDate);
Price latestPrice = prices[0];
DateTime startDate = prices[0].Date;
DateTime endDate = prices[prices.Count - 1].Date;
for (int index = 0; index < prices.Count; index++) pricesByDate.Add(prices[index].Date, prices[index]);
MACDSignals macdSignals = MACDGenerator.GenerateMACD(prices, macdSetup);
Signals signals = SignalGenerator.GenerateSignals(macdSignals);
Portfolio portfolio = SignalTrader.TradeSignals(tradeDates, signals, prices, investment, stopLossThreshold, stopLossDays);
tradeResults = new TradeResultList();
for (int index = 0; index < portfolio.Trades.Count; index++)
{
ModelTrade modelTrade = portfolio.Trades[index];
TradeBlotter.Model.TradeResult tradeResult = new TradeBlotter.Model.TradeResult(modelTrade.TradeDate, modelTrade.Type.Equals(ModelTrade.TradeType.Buy) ? "Buy" : "Sell", modelTrade.Symbol, modelTrade.Shares, modelTrade.Price, modelTrade.GainLoss, modelTrade.Return,modelTrade.Exposure,modelTrade.DaysHeld, modelTrade.Comment);
tradeResults.Add(tradeResult);
}
tradeResults.Sort();
tradeResultSummary = new ObservableCollection<TradeResultSummary>();
TradeResultSummary summary = new TradeResultSummary();
summary.AverageGainLoss = portfolio.GetAverageGainLoss();
summary.AverageHoldingDays = portfolio.GetAverageHoldingDays();
summary.MaximumHoldingDays = portfolio.GetMaxHoldingDays();
summary.MinimumHoldingDays = portfolio.GetMinHoldingDays();
summary.PortfolioValue = portfolio.GetPortfolioValue(prices[0]);
summary.PortfolioReturn = portfolio.GetPortfolioReturn(prices[0]);
tradeResultSummary.Add(summary);
});
workerTask.ContinueWith((continuation) =>
{
BusyIndicator = false;
base.OnPropertyChanged("TradeResults");
base.OnPropertyChanged("TradeResultsSummary");
});
}
catch (Exception exception)
{
BusyIndicator = false;
MessageBox.Show(exception.ToString());
}
}
private bool CanRunModel
{
get
{
if (null == selectedSymbol) return false;
if (null == selectedStartDate || Utility.IsEpoch(selectedStartDate.Value)) return false;
return true;
}
}
public ICommand RunModelCommand
{
get
{
if (runModelCommand == null)
{
runModelCommand = new RelayCommand(param => this.RunModel(), param => this.CanRunModel);
}
return runModelCommand;
}
}
}
}