296 lines
11 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|