Changes to support MGSHMomentumView

This commit is contained in:
2025-02-10 08:02:49 -05:00
parent 549f9ca7d1
commit 230d84904a
10 changed files with 324 additions and 436 deletions

View File

@@ -84,6 +84,10 @@ This resource dictionary is used by the MainWindow.
<vw:BollingerBandView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:BollingerBandPositionViewModel}">
<vw:BollingerBandPositionView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:YieldCurveViewModel}">
<vw:YieldCurveView />
</DataTemplate>

View File

@@ -16,6 +16,7 @@ using MarketData.Generator.Momentum;
using MarketData.DataAccess;
using System.CodeDom;
using MarketData.Generator.MGSHMomentum;
using TradeBlotter.Interface;
namespace TradeBlotter.Model
{
@@ -47,7 +48,7 @@ namespace TradeBlotter.Model
base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset,null));
}
}
public class MGSHPositionModel : ModelBase
public class MGSHPositionModel : ModelBase, IPositionModel
{
private MGSHPosition position = new MGSHPosition();
private int slot;
@@ -111,6 +112,37 @@ namespace TradeBlotter.Model
Comment=position.Comment;
}
public MGSHPosition Position
{
get{return position;}
set
{
Slot=-1;
Symbol=position.Symbol;
PurchaseDate=position.PurchaseDate;
SellDate=position.SellDate;
Shares=position.Shares;
PurchasePrice=position.PurchasePrice;
CurrentPrice=position.CurrentPrice;
Volume=position.Volume;
Return1D=position.Return1D;
CumReturn252=position.CumReturn252;
IDIndicator=position.IDIndicator;
Score=position.Score;
MaxDrawdown=position.MaxDrawdown;
MaxUpside=position.MaxUpside;
Velocity=position.Velocity;
PE=position.PE;
Beta=position.Beta;
ZacksRank=position.ZacksRank;
InitialStopLimit=position.InitialStopLimit;
TrailingStopLimit=position.TrailingStopLimit;
LastStopAdjustment=position.LastStopAdjustment;
Comment=position.Comment;
this.position.R=position.R;
}
}
private void UpdateProperties()
{
base.OnPropertyChanged("CurrentPrice");

View File

@@ -110,10 +110,13 @@
<Compile Include="Cache\SymbolCache.cs" />
<Compile Include="DataAccess\TradeAddedEvenArgs.cs" />
<Compile Include="DataAccess\TradeRepository.cs" />
<Compile Include="Extensions\PortfolioTradesExtensions.cs" />
<Compile Include="Extensions\StopLimitExtensions.cs" />
<Compile Include="FloatingWindow.xaml.cs">
<DependentUpon>FloatingWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Helper\FilterEvaluator.cs" />
<Compile Include="Interface\IPositionModel.cs" />
<Compile Include="Model\BlotterTradeModel.cs" />
<Compile Include="Model\BollingerBandModel.cs" />
<Compile Include="Model\CMPositionModel.cs" />
@@ -142,8 +145,8 @@
<Compile Include="UIUtils\CMTTrendModelClosePositionDialog.xaml.cs">
<DependentUpon>CMTTrendModelClosePositionDialog.xaml</DependentUpon>
</Compile>
<Compile Include="UIUtils\CMTTrendModelEditPositionDialog.xaml.cs">
<DependentUpon>CMTTrendModelEditPositionDialog.xaml</DependentUpon>
<Compile Include="UIUtils\EditPositionDialog.xaml.cs">
<DependentUpon>EditPositionDialog.xaml</DependentUpon>
</Compile>
<Compile Include="UIUtils\ProformaAddPositionDialog.xaml.cs">
<DependentUpon>ProformaAddPositionDialog.xaml</DependentUpon>
@@ -154,6 +157,8 @@
<Compile Include="Utility\BrushCollection.cs" />
<Compile Include="Utility\CellStyles.cs" />
<Compile Include="Utility\WebBrowserUtils.cs" />
<Compile Include="ViewModels\BollingerBandPositionViewModel.cs" />
<Compile Include="ViewModels\BollingerBandViewModel.cs" />
<Compile Include="ViewModels\CMMomentumViewModel.cs" />
<Compile Include="ViewModels\CMTTrendViewModel.cs" />
<Compile Include="ViewModels\DividendRiskParityViewModel.cs" />
@@ -181,7 +186,6 @@
<Compile Include="Model\Item.cs" />
<Compile Include="Utility\UIUtils.cs" />
<Compile Include="ViewModels\AnalystRatingsViewModel.cs" />
<Compile Include="ViewModels\BollingerBandViewModel.cs" />
<Compile Include="ViewModels\CommandViewModel.cs" />
<Compile Include="ViewModels\EarningsAnnouncementViewModel.cs" />
<Compile Include="ViewModels\ETFHoldingViewModel.cs" />
@@ -213,6 +217,9 @@
<Compile Include="Views\BlotterView.xaml.cs">
<DependentUpon>BlotterView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\BollingerBandPositionView.xaml.cs">
<DependentUpon>BollingerBandPositionView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\BollingerBandView.xaml.cs">
<DependentUpon>BollingerBandView.xaml</DependentUpon>
</Compile>
@@ -340,7 +347,7 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UIUtils\CMTTrendModelEditPositionDialog.xaml">
<Page Include="UIUtils\EditPositionDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
@@ -360,9 +367,13 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\BollingerBandView.xaml">
<SubType>Designer</SubType>
<Page Include="Views\BollingerBandPositionView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\BollingerBandView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\CMMomentumView.xaml">
<SubType>Designer</SubType>

View File

@@ -1,66 +0,0 @@
<Window x:Class="TradeBlotter.UIUtils.CMTTrendModelEditPositionDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Edit Position" Height="319.586" Width="196.793"
xmlns:wpfx="http://schemas.xceed.com/wpf/xaml/toolkit"
WindowStartupLocation="CenterScreen"
SizeToContent="WidthAndHeight"
MinWidth="200"
MinHeight="340"
WindowStyle="SingleBorderWindow"
ResizeMode="CanMinimize">
<wpfx:BusyIndicator Name="BusyBar" IsBusy="{Binding Path=BusyIndicator}" BusyContent="{Binding Path=BusyContent}">
<StackPanel Margin="5" Orientation="Vertical">
<Grid DockPanel.Dock="Left" Margin="0,2,4,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="6" />
<ColumnDefinition Width="75*" />
<ColumnDefinition Width="6" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20*" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<Label Name="lblCompanyName" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3"></Label>
<Label Name="lblSymbol" Grid.Row="2" Grid.Column="0">Symbol</Label>
<TextBox Name="txtSymbol" IsEnabled="False" Grid.Row="2" IsReadOnly="True" Grid.Column="2" MinWidth="75" AcceptsReturn="true">Symbol</TextBox>
<Label Name="lblPurchaseDate" Grid.Row="3" Grid.Column="0" MinWidth="75">Purchase Date</Label>
<DatePicker Name="dpPurchaseDate" IsEnabled="False" Grid.Row="3" Grid.Column="2"></DatePicker>
<Label Name="lblPurchasePrice" Grid.Row="4" Grid.Column="0" MinWidth="75">Purchase Price</Label>
<TextBox Name="txtPurchasePrice" Grid.Row="4" Grid.Column="2" LostFocus="txtPurchasePrice__OnLostFocusHandler" KeyDown="txtPurchasePrice_OnKeyDownHandler"></TextBox>
<Label FontWeight="Bold" FontSize="10" Name="lblPurchasePriceInstructions" Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="3">(enter purchase price then hit enter key)</Label>
<Label Name="lblInitialStop" Grid.Row="6" Grid.Column="0">Initial Stop</Label>
<TextBox Name="txtInitialStop" Grid.Row="6" Grid.Column="2" MinWidth="75" LostFocus="txtInitialStop__OnLostFocusHandler" KeyDown="txtInitialStop_OnKeyDownHandler">100.00</TextBox>
<CheckBox Name="cbSyncTrailingStop" Grid.Row="7" Grid.Column="0">Sync Trailing Stop</CheckBox>
<Label FontWeight="Bold" FontSize="10" Name="lblInitialStopInstructions" Grid.Row="8" Grid.Column="0" Grid.ColumnSpan="3">(enter initial stop then hit enter key)</Label>
<Label FontWeight="Bold" FontSize="10" Name="lblInitialStopRecommendation" Grid.Row="9" Grid.Column="0" Grid.ColumnSpan="3"></Label>
<Label Name="lblTrailingStop" Grid.Row="10" Grid.Column="0">Trailing Stop</Label>
<TextBox Name="txtTrailingStop" Grid.Row="10" Grid.Column="2" MinWidth="75" LostFocus="txtTrailingStop__OnLostFocusHandler" KeyDown="txtTrailingStop_OnKeyDownHandler">100.00</TextBox>
<Label FontWeight="Bold" FontSize="10" Name="lblTrailingStopInstructions" Grid.Row="11" Grid.Column="0" Grid.ColumnSpan="3">(enter trailing stop then hit enter key)</Label>
<Button Content="_Ok" MinWidth="75" IsDefault="False" Margin="2" Name="btnOk" Click="btnOk_Click" Grid.Row="12" Grid.Column="0"/>
<Button Content="_Cancel" MinWidth="75" IsCancel="True" Margin="2" Name="btnCancel" Click="btnCancel_Click" Grid.Row="12" Grid.Column="2"/>
</Grid>
</StackPanel>
</wpfx:BusyIndicator>
</Window>

View File

@@ -1,228 +0,0 @@
using MarketData.DataAccess;
using MarketData.MarketDataModel;
using MarketData.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Media;
using Position=MarketData.Generator.CMTrend.Position;
namespace TradeBlotter.UIUtils
{
/// <summary>
/// Interaction logic for CMTTrendModelEditPositionDialog.xaml
/// </summary>
public partial class CMTTrendModelEditPositionDialog:Window
{
private ManualResetEvent manualResetEvent=new ManualResetEvent(false);
private String Symbol { get; set; }
private DateTime PurchaseDate { get; set; }
private double PurchasePrice{get;set;}
private double TrailingStop{get;set;}
private double InitialStop{get;set;}
private double PositionRiskPercentDecimal{get;set;}
private bool Result { get; set; }
private CMTTrendModelEditPositionDialog(String title,Position position)
{
this.Background=new SolidColorBrush(Colors.AliceBlue);
this.Owner=Application.Current.MainWindow;
InitializeComponent();
this.Loaded+=new RoutedEventHandler(CMTTrendModelEditPositionDialog_Loaded);
this.Closing+=Window_Closing;
dpPurchaseDate.SelectedDateChanged+=dpPurchaseDate_SelectionChanged;
Title=title;
Symbol=position.Symbol;
PurchaseDate=position.PurchaseDate;
PurchasePrice=position.PurchasePrice;
TrailingStop=position.TrailingStopLimit;
InitialStop=position.InitialStopLimit;
PositionRiskPercentDecimal=position.PositionRiskPercentDecimal;
txtSymbol.Text=Symbol;
dpPurchaseDate.SelectedDate=PurchaseDate;
lblInitialStopRecommendation.FontSize=12;
cbSyncTrailingStop.IsChecked=true;
UpdatePurchasePrice();
UpdateInitialStop();
UpdateTrailingStop();
UpdateCompanyName();
UpdateInitialStopRecommendation();
}
public ManualResetEvent Event { get { return manualResetEvent; } }
public static Position Prompt(string title,Position position)
{
CMTTrendModelEditPositionDialog mmTrendModelEditPositionDialog=new CMTTrendModelEditPositionDialog(title,position);
try { mmTrendModelEditPositionDialog.ShowDialog(); }
catch(Exception) { return null; }
mmTrendModelEditPositionDialog.Event.WaitOne();
if(mmTrendModelEditPositionDialog.Result)
{
position.PurchaseDate=mmTrendModelEditPositionDialog.PurchaseDate;
position.PurchasePrice=mmTrendModelEditPositionDialog.PurchasePrice;
position.TrailingStopLimit=mmTrendModelEditPositionDialog.TrailingStop;
position.InitialStopLimit=mmTrendModelEditPositionDialog.InitialStop;
return position;
}
return null;
}
void CMTTrendModelEditPositionDialog_Loaded(object sender,RoutedEventArgs e)
{
txtPurchasePrice.Focus();
}
private void btnOk_Click(object sender,RoutedEventArgs e)
{
Result=Validate();
if(!Result)
{
SystemSounds.Beep.Play();
return;
}
Close();
Event.Set();
return;
}
// *******************************************************************************************************************************************************************************
// ********************************************************************************** P U R C H A S E P R I C E ***************************************************************
// *******************************************************************************************************************************************************************************
private void txtPurchasePrice__OnLostFocusHandler(Object sender,RoutedEventArgs routedEventArgs)
{
HandlePurchasePriceEvents();
}
private void txtPurchasePrice_OnKeyDownHandler(object sender,KeyEventArgs e)
{
if(e.Key==Key.Return)
{
HandlePurchasePriceEvents();
}
}
private void HandlePurchasePriceEvents()
{
double value=0.00;
value=Utility.ParseCurrency(txtPurchasePrice.Text);
if(PurchasePrice.Equals(value)) return;
PurchasePrice=value;
UpdatePurchasePrice();
UpdateInitialStopRecommendation();
}
private void UpdatePurchasePrice()
{
txtPurchasePrice.Text=Utility.FormatCurrency(PurchasePrice);
}
// *******************************************************************************************************************************************************************************
// ********************************************************************************** I N I T I A L S T O P R E C O M M E N D A T I O N **************************************
// *******************************************************************************************************************************************************************************
private void UpdateInitialStopRecommendation()
{
lblInitialStopRecommendation.Content="Recommended Initial Stop: "+Utility.FormatCurrency(PurchasePrice*(1.00-PositionRiskPercentDecimal),2);
}
// *******************************************************************************************************************************************************************************
// ********************************************************************************** I N I T I A L S T O P *****************************************************************
// *******************************************************************************************************************************************************************************
private void txtInitialStop__OnLostFocusHandler(Object sender,RoutedEventArgs routedEventArgs)
{
HandleInitialStopEvents();
}
private void txtInitialStop_OnKeyDownHandler(object sender,KeyEventArgs e)
{
if(e.Key==Key.Return)
{
HandleInitialStopEvents();
}
}
private void HandleInitialStopEvents()
{
double value=0.00;
value=Utility.ParseCurrency(txtInitialStop.Text);
if(InitialStop.Equals(value)) return;
InitialStop=value;
UpdateInitialStop();
if(null!= cbSyncTrailingStop.IsChecked && cbSyncTrailingStop.IsChecked.Value)
{
TrailingStop=value;
UpdateTrailingStop();
}
}
private void UpdateInitialStop()
{
txtInitialStop.Text=Utility.FormatCurrency(InitialStop);
}
// *******************************************************************************************************************************************************************************
// ********************************************************************************** T R A I L I N G S T O P *****************************************************************
// *******************************************************************************************************************************************************************************
private void txtTrailingStop__OnLostFocusHandler(Object sender,RoutedEventArgs routedEventArgs)
{
HandleTrailingStopEvents();
}
private void txtTrailingStop_OnKeyDownHandler(object sender,KeyEventArgs e)
{
if(e.Key==Key.Return)
{
HandleTrailingStopEvents();
}
}
private void HandleTrailingStopEvents()
{
double value=0.00;
value=Utility.ParseCurrency(txtTrailingStop.Text);
if(TrailingStop.Equals(value)) return;
TrailingStop=value;
UpdateTrailingStop();
}
private void UpdateTrailingStop()
{
txtTrailingStop.Text=Utility.FormatCurrency(TrailingStop);
}
// *********************************************************************************************************************************************************************************
private void dpPurchaseDate_SelectionChanged(object sender,RoutedEventArgs e)
{
if(null==dpPurchaseDate.SelectedDate) return;
PurchaseDate=dpPurchaseDate.SelectedDate.Value;
}
// ***********************************************************************************************************************************************************************************
private void Window_Closing(object sender,System.ComponentModel.CancelEventArgs e)
{
Event.Set();
}
private void btnCancel_Click(object sender,RoutedEventArgs e)
{
Result=false;
Close();
Event.Set();
}
private bool Validate()
{
DateGenerator dateGenerator=new DateGenerator();
if(null==Symbol) return false;
if(Utility.IsEpoch(PurchaseDate)) return false;
if(!dateGenerator.IsMarketOpen(PurchaseDate))return false;
if(double.IsNaN(PurchasePrice)) return false;
if(double.IsNaN(TrailingStop)) return false;
if(double.IsNaN(InitialStop)) return false;
return true;
}
private void UpdateCompanyName()
{
CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(Symbol);
if(null==companyProfile||null==companyProfile.CompanyName) return;
lblCompanyName.Content=companyProfile.CompanyName.ToUpper();
}
}
}

View File

@@ -140,9 +140,16 @@ namespace TradeBlotter.UIUtils
{
String key;
double offset=defaultOffset;
if(portfolioTrade.IsOpen)key=portfolioTrade.Symbol+portfolioTrade.TradeDate.ToShortDateString();
else key=portfolioTrade.Symbol+portfolioTrade.SellDate.ToShortDateString();
if(tradesBySymbolAndDate.ContainsKey(key))
if (portfolioTrade.IsOpen)
{
key = portfolioTrade.Symbol + portfolioTrade.TradeDate.ToShortDateString();
}
else
{
key = portfolioTrade.Symbol + portfolioTrade.SellDate.ToShortDateString();
}
if (tradesBySymbolAndDate.ContainsKey(key))
{
if(hits>MAX_HITS)increment=5;
offset=tradesBySymbolAndDate[key]+increment;

View File

@@ -24,6 +24,7 @@ using System.Windows.Media;
using System.Windows.Threading;
using System.Windows.Forms;
using TradeBlotter.UIUtils;
using TradeBlotter.Extensions;
// Author:Sean Kessler
@@ -173,17 +174,7 @@ namespace TradeBlotter.ViewModels
{
if(saveParameters.ContainsKey("StopHistoryCount"))
{
stopLimits=new StopLimits();
int stopHistoryCount=int.Parse((from KeyValuePair<String,String> item in saveParameters where item.Key.Equals("StopHistoryCount") select item).FirstOrDefault().Value);
for(int index=0;index<stopHistoryCount;index++)
{
String strItemKey=String.Format("StopHistory_{0}",index);
String strStopHistoryItem=(from KeyValuePair<String,String> item in saveParameters where item.Key.Equals(strItemKey) select item).FirstOrDefault().Value;
NVPCollection nvpCollection=new NVPCollection(strStopHistoryItem);
StopLimit stopLimit=MarketData.MarketDataModel.StopLimit.FromNVPCollection(nvpCollection);
stopLimits.Add(stopLimit);
}
stopLimits=new StopLimits(stopLimits.OrderBy(x => x.EffectiveDate).ToList());
stopLimits = StopLimitsExtensions.FromSaveParams(saveParameters);
}
}
catch(Exception exception)

View File

@@ -28,6 +28,8 @@ using StopLimit=MarketData.MarketDataModel.StopLimit;
using TradeBlotter.UIUtils;
using MarketData.Generator.Model;
using MarketData.Generator.ModelGenerators;
using MarketData.Generator.Interface;
using TradeBlotter.Extensions;
namespace TradeBlotter.ViewModels
{
@@ -950,41 +952,60 @@ namespace TradeBlotter.ViewModels
// *************************************************************************************************************************************************************
// ********************************************************************** C O M M A N D W O R K E R S P O S I T I O N ****************************************
// *************************************************************************************************************************************************************
//public void DisplayBollingerBandCommandPosition()
//{
// String strStopLimits=null;
// MarketData.MarketDataModel.StopLimits stopLimits=GetHistoricalStopLimitsMarketDataModel();
// StringBuilder sb=new StringBuilder();
// if(null!=stopLimits && 0!=stopLimits.Count)
// {
// sb.Append(",");
// NVPCollections nvpCollections=stopLimits.ToNVPCollections();
// sb.Append("StopHistoryCount").Append(",").Append(String.Format("{0}",nvpCollections.Count)).Append(",");
// for(int index=0;index<nvpCollections.Count;index++)
// {
// sb.Append(String.Format("StopHistory_{0}",index)).Append(",").Append(nvpCollections[index].ToString());
// if(index<nvpCollections.Count-1)sb.Append(",");
// }
// }
// strStopLimits=sb.ToString();
// SaveParameters saveParams=null;
// if(null!=strStopLimits)
// {
// sb=new StringBuilder();
// sb.Append("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol,");
// sb.Append(selectedPosition.Symbol).Append(",");
// sb.Append("SelectedWatchList,{All},SelectedDayCount,");
// sb.Append(GetDayCountSelectionForBollingerBands(selectedPosition));
// sb.Append(String.IsNullOrEmpty(strStopLimits)?"":strStopLimits);
// saveParams=SaveParameters.Parse(sb.ToString());
// }
// else
// {
// saveParams=SaveParameters.Parse("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol,"+selectedPosition.Symbol+",SelectedWatchList,{All},SelectedDayCount,90");
// }
// saveParams.Referer=this;
// WorkspaceInstantiator.Invoke(saveParams);
//}
public void DisplayBollingerBandCommandPosition()
{
String strStopLimits=null;
MarketData.MarketDataModel.StopLimits stopLimits=GetHistoricalStopLimitsMarketDataModel();
StringBuilder sb=new StringBuilder();
if(null!=stopLimits && 0!=stopLimits.Count)
{
sb.Append(",");
NVPCollections nvpCollections=stopLimits.ToNVPCollections();
sb.Append("StopHistoryCount").Append(",").Append(String.Format("{0}",nvpCollections.Count)).Append(",");
for(int index=0;index<nvpCollections.Count;index++)
{
sb.Append(String.Format("StopHistory_{0}",index)).Append(",").Append(nvpCollections[index].ToString());
if(index<nvpCollections.Count-1)sb.Append(",");
}
}
strStopLimits=sb.ToString();
SaveParameters saveParams=null;
if(null!=strStopLimits)
{
sb=new StringBuilder();
MarketData.MarketDataModel.StopLimits stopLimits = GetHistoricalStopLimitsMarketDataModel();
StringBuilder sb = new StringBuilder();
SaveParameters saveParams = null;
sb = new StringBuilder();
sb.Append("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol,");
sb.Append(selectedPosition.Symbol).Append(",");
sb.Append("SelectedWatchList,{All},SelectedDayCount,");
sb.Append(GetDayCountSelectionForBollingerBands(selectedPosition));
sb.Append(String.IsNullOrEmpty(strStopLimits)?"":strStopLimits);
saveParams=SaveParameters.Parse(sb.ToString());
}
else
{
saveParams=SaveParameters.Parse("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol,"+selectedPosition.Symbol+",SelectedWatchList,{All},SelectedDayCount,90");
}
saveParams = SaveParameters.Parse(sb.ToString());
SaveParameters stopLimitParams = StopLimitsExtensions.FromStopLimits(stopLimits);
saveParams.AddRange(stopLimitParams);
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
private int GetDayCountSelectionForBollingerBands(CMTPositionModel selectedPosition)
{
DateGenerator dateGenerator=new DateGenerator();
@@ -1061,10 +1082,11 @@ namespace TradeBlotter.ViewModels
MessageBox.Show(strMessage,"Close Position");
LoadSessionFile();
}
public void EditPositionCommand(CMTPositionModel selectedPosition)
{
Position clonedPosition=Position.Clone(selectedPosition.Position);
Position changedPosition=CMTTrendModelEditPositionDialog.Prompt("Edit Position",clonedPosition);
IPosition changedPosition=EditPositionDialog.Prompt("Edit Position",clonedPosition);
if(null==changedPosition) return;
CMTTrendModel mmTrendModel=new CMTTrendModel();
if(!mmTrendModel.EditPosition(changedPosition.Symbol,changedPosition.PurchaseDate,changedPosition.PurchasePrice,changedPosition.InitialStopLimit,changedPosition.TrailingStopLimit,pathFileName))
@@ -1515,7 +1537,9 @@ namespace TradeBlotter.ViewModels
if(null==sessionParams||null==selectedPosition) return null;
DateGenerator dateGenerator=new DateGenerator();
MarketData.MarketDataModel.StopLimits marketDataModelStopLimits=new MarketData.MarketDataModel.StopLimits();
MarketData.Generator.Model.StopLimits stopLimits=new MarketData.Generator.Model.StopLimits((from MarketData.Generator.Model.StopLimit stopLimit in sessionParams.StopLimits where stopLimit.Symbol.Equals(selectedPosition.Symbol) select stopLimit).OrderByDescending(x => x.AnalysisDate).ToList());
MarketData.Generator.Model.StopLimits stopLimits=new MarketData.Generator.Model.StopLimits(
(from MarketData.Generator.Model.StopLimit stopLimit in sessionParams.StopLimits where stopLimit.Symbol.Equals(selectedPosition.Symbol)
select stopLimit).OrderByDescending(x => x.AnalysisDate).ToList());
MarketData.MarketDataModel.StopLimit initialStopLimit=new MarketData.MarketDataModel.StopLimit();
initialStopLimit.Symbol=selectedPosition.Symbol;

View File

@@ -26,6 +26,9 @@ using MarketData.Generator.Momentum;
using TradeBlotter.UIUtils;
using MarketData.Generator.Model;
using MarketData.Generator.MGSHMomentum;
using MarketData.Generator.Interface;
using StopLimit=MarketData.MarketDataModel.StopLimit;
using TradeBlotter.Extensions;
namespace TradeBlotter.ViewModels
{
@@ -88,6 +91,8 @@ namespace TradeBlotter.ViewModels
private RelayCommand movingAverageCommandPosition;
private RelayCommand displayHistoricalCommandPosition;
private RelayCommand displayHeadlinesCommandPosition;
private RelayCommand editPositionCommandPosition;
// chart plotter
private bool showAsGainLoss=true;
private bool isLegendVisible=false;
@@ -157,7 +162,10 @@ namespace TradeBlotter.ViewModels
// **************************************************************************************************************************************************************************
public bool BusyIndicator
{
get { return busyIndicator; }
get
{
return busyIndicator;
}
set
{
busyIndicator = value;
@@ -166,8 +174,15 @@ namespace TradeBlotter.ViewModels
}
public String BusyContent
{
get{return busyContent;}
set{busyContent=value;base.OnPropertyChanged("BusyContent");}
get
{
return busyContent;
}
set
{
busyContent=value;
base.OnPropertyChanged("BusyContent");
}
}
// **************************************************************************************************************************************************************************
public ObservableCollection<MenuItem> CandidateMenuItems
@@ -210,12 +225,15 @@ namespace TradeBlotter.ViewModels
collection.Add(new MenuItem() { Text = "Display DCF Valuation", MenuItemClickedCommand = DisplayDCFValuationPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Add to Watchlist", MenuItemClickedCommand = AddToWatchListPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text = "Remove from Watchlist", MenuItemClickedCommand = RemoveFromWatchListPosition, StaysOpenOnClick = false });
collection.Add(new MenuItem() { Text="Edit Position...",MenuItemClickedCommand=EditPosition,StaysOpenOnClick=false });
return collection;
}
}
private void OnMomentumViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
{
}
// ************************************************************************************************************************************************
// ************************************************************************************************************************************************
// ************************************************************************************************************************************************
@@ -224,9 +242,8 @@ namespace TradeBlotter.ViewModels
get
{
if(null==pathFileName)return "MGSHMomentum Model";
String fileName=Path.GetFileName(pathFileName);
fileName=Utility.BetweenString(fileName,null,".");
return "MGSHMomentum Model ("+fileName+")";
String pureFileName = Utility.GetFileNameNoExtension(pathFileName);
return "MGSHMomentum Model ("+pureFileName+")";
}
}
public override String Title
@@ -836,6 +853,22 @@ namespace TradeBlotter.ViewModels
return removeFromWatchListCommandPosition;
}
}
public ICommand EditPosition
{
get
{
if(editPositionCommandPosition==null)
{
editPositionCommandPosition=new RelayCommand(param => this.EditPositionCommand(selectedPosition),param =>
{
if(null==selectedPosition||null==selectedPosition.Symbol||!Utility.IsEpoch(selectedPosition.SellDate)) return false;
return true;
});
}
return editPositionCommandPosition;
}
}
// *************************************************************************************************************************************************************
// ******************************************************************* I C O M M A N D S E S S I O N *********************************************************
// *************************************************************************************************************************************************************
@@ -919,57 +952,74 @@ namespace TradeBlotter.ViewModels
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
// *************************************************************************************************************************************************************
// ********************************************************************** C O M M A N D W O R K E R S P O S I T I O N ****************************************
// *************************************************************************************************************************************************************
//public void DisplayBollingerBandCommandPosition()
//{
// SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,90");
// saveParams.Referer=this;
// WorkspaceInstantiator.Invoke(saveParams);
//}
// *************************************************************************************************************************************************************
// ********************************************************************** C O M M A N D W O R K E R S P O S I T I O N ****************************************
// *************************************************************************************************************************************************************
public void EditPositionCommand(MGSHPositionModel selectedPosition)
{
MGSHPosition clonedPosition = MGSHPosition.Clone(selectedPosition.Position);
IPosition changedPosition = EditPositionDialog.Prompt("Edit Position", clonedPosition);
if (null == changedPosition) return;
MGSHMomentumBacktest mgshMomentumBacktest = new MGSHMomentumBacktest();
if (!mgshMomentumBacktest.EditPosition(changedPosition.Symbol, changedPosition.PurchaseDate, changedPosition.PurchasePrice, changedPosition.InitialStopLimit, changedPosition.TrailingStopLimit, pathFileName))
{
MessageBox.Show("Failed to edit the position, check log for details.", "Edit Position");
return;
}
if (!selectedPosition.TrailingStopLimit.Equals(changedPosition.TrailingStopLimit))
{
selectedPosition.TrailingStopLimit = changedPosition.TrailingStopLimit;
selectedPosition.LastStopAdjustment = DateTime.Now.Date;
StopLimit stopLimit = PortfolioDA.GetStopLimit(changedPosition.Symbol);
if (null == stopLimit)
{
stopLimit = new StopLimit();
stopLimit.Symbol = changedPosition.Symbol;
stopLimit.StopType = StopLimitConstants.STOP_QUOTE;
stopLimit.Shares = changedPosition.Shares;
}
stopLimit.StopPrice = changedPosition.TrailingStopLimit;
PortfolioDA.InsertUpdateStopLimit(stopLimit);
}
selectedPosition.PurchaseDate = changedPosition.PurchaseDate;
selectedPosition.PurchasePrice = changedPosition.PurchasePrice;
selectedPosition.TrailingStopLimit = changedPosition.TrailingStopLimit;
selectedPosition.InitialStopLimit = changedPosition.InitialStopLimit;
String strMessage = String.Format("Edited Position for {0} Purchase Date:{1} Purchase Price:{2}, Trailing Stop:{3}. A backup was created.",
selectedPosition.Symbol, selectedPosition.PurchaseDate.ToShortDateString(), Utility.FormatCurrency(selectedPosition.PurchasePrice), Utility.FormatCurrency(selectedPosition.TrailingStopLimit));
MessageBox.Show(strMessage, "Edit Position");
}
public void DisplayBollingerBandCommandPosition()
{
String strStopLimits = null;
MarketData.MarketDataModel.StopLimits stopLimits = GetHistoricalStopLimitsMarketDataModel();
StringBuilder sb = new StringBuilder();
if (null != stopLimits && 0 != stopLimits.Count)
{
sb.Append(",");
NVPCollections nvpCollections = stopLimits.ToNVPCollections();
sb.Append("StopHistoryCount").Append(",").Append(String.Format("{0}", nvpCollections.Count)).Append(",");
for (int index = 0; index < nvpCollections.Count; index++)
{
sb.Append(String.Format("StopHistory_{0}", index)).Append(",").Append(nvpCollections[index].ToString());
if (index < nvpCollections.Count - 1) sb.Append(",");
}
}
strStopLimits = sb.ToString();
SaveParameters saveParams = null;
if (null != strStopLimits)
{
sb = new StringBuilder();
sb.Append("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol,");
sb.Append("Type,TradeBlotter.ViewModels.BollingerBandPositionViewModel,SelectedSymbol,");
sb.Append(selectedPosition.Symbol).Append(",");
sb.Append("SelectedWatchList,{All},SelectedDayCount,");
sb.Append(GetDayCountSelectionForBollingerBands(selectedPosition));
sb.Append(String.IsNullOrEmpty(strStopLimits) ? "" : strStopLimits);
saveParams = SaveParameters.Parse(sb.ToString());
} else
{
saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,90");
}
SaveParameters stopLimitParams = StopLimitsExtensions.FromStopLimits(stopLimits);
saveParams.AddRange(stopLimitParams);
SaveParameters portfolioTradesParams = PortfolioTradesExtensions.FromPosition(selectedPosition);
saveParams.AddRange(portfolioTradesParams);
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
private int GetDayCountSelectionForBollingerBands(MGSHPositionModel selectedPosition)
{
DateGenerator dateGenerator=new DateGenerator();
int daysBetween=dateGenerator.DaysBetween(selectedPosition.PurchaseDate,DateTime.Today);
DateTime maxDate = PricingDA.GetLatestDate(selectedPosition.Symbol);
if(!selectedPosition.IsActivePosition)
{
maxDate = selectedPosition.SellDate;
}
int daysBetween=dateGenerator.DaysBetween(selectedPosition.PurchaseDate, maxDate);
if(daysBetween<90)return 90;
if(daysBetween<180)return 180;
if(daysBetween<360)return 360;
@@ -978,8 +1028,6 @@ namespace TradeBlotter.ViewModels
return 3600;
}
public void DisplayAnalystRatingsCommandPosition()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.AnalystRatingsViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All}");
@@ -1157,14 +1205,25 @@ namespace TradeBlotter.ViewModels
}
else LoadSessionFile();
}
public bool LoadSessionFile()
{
BusyIndicator = true;
BusyContent = $"Loading {Utility.GetFileNameNoExtension(pathFileName)}...";
Task workerTask = Task.Factory.StartNew(() =>
{
try
{
if(!MGSHSessionManager.IsValidSessionFile(pathFileName))return false;
initialPath=Path.GetDirectoryName(pathFileName);
sessionParams=MGSHSessionManager.RestoreSession(pathFileName);
if(null==sessionParams){ MessageBox.Show(String.Format("Unable to open {0}",pathFileName));pathFileName=null;return false;}
if(null==sessionParams)
{
MessageBox.Show(String.Format("Unable to open {0}",pathFileName));
pathFileName=null;
return false;
}
modelStatistics=MGSHMomentumBacktest.GetModelStatistics(sessionParams);
modelPerformanceSeries=MGSHMomentumBacktest.GetModelPerformance(sessionParams);
configuration=sessionParams.Configuration;
@@ -1175,10 +1234,22 @@ namespace TradeBlotter.ViewModels
positions=new MGSHPositionModelCollection();
positions.Add(sessionParams.ActivePositions); // active positions will go into their assigned slot
positions.Add(sessionParams.AllPositions);
// positions.Add(sessionParams.HedgePositions, -1); // hedge positions will go into slot -1
//// positions.Add(sessionParams.HedgePositions, -1); // hedge positions will go into slot -1
UpdatePositionPrices(false);
UpdatePositionRSI3(true);
RunPerformance();
return true;
}
catch(Exception exception)
{
MessageBox.Show(String.Format("Unable to open {0}",pathFileName));
pathFileName=null;
return false;
}
});
workerTask.ContinueWith(continuation =>
{
BusyIndicator=false;
base.OnPropertyChanged("Parameters");
base.OnPropertyChanged("SelectedParameter");
base.OnPropertyChanged("ParameterValue");
@@ -1191,14 +1262,11 @@ namespace TradeBlotter.ViewModels
base.OnPropertyChanged("ModelExpectation");
base.OnPropertyChanged("ExpectationColor");
base.OnPropertyChanged("ExpectationDescription");
base.OnPropertyChanged("ReloadEnabled");
});
return true;
}
catch(Exception exception)
{
System.Windows.MessageBox.Show(String.Format("Exception {0}",exception.ToString()),"Error",MessageBoxButton.OK,MessageBoxImage.Exclamation);
return false;
}
}
private void RunPerformance()
{
if(null==sessionParams)return;
@@ -1309,31 +1377,23 @@ namespace TradeBlotter.ViewModels
{
if (null == sessionParams || null == selectedPosition) return null;
DateGenerator dateGenerator = new DateGenerator();
MarketData.MarketDataModel.StopLimits marketDataModelStopLimits = new MarketData.MarketDataModel.StopLimits();
MarketData.Generator.Model.StopLimits stopLimits = default;
if (selectedPosition.IsActivePosition)
{
stopLimits = new MarketData.Generator.Model.StopLimits((from MarketData.Generator.Model.StopLimit stopLimit in sessionParams.StopLimits
where stopLimit.Symbol.Equals(selectedPosition.Symbol) && stopLimit.AnalysisDate > selectedPosition.PurchaseDate select stopLimit).
MarketData.Generator.Model.StopLimits stopLimits =
new MarketData.Generator.Model.StopLimits((from MarketData.Generator.Model.StopLimit stopLimit in sessionParams.StopLimits
where stopLimit.StopLimitId.Equals(selectedPosition.Symbol + Utility.DateTimeToStringYYYYMMDDMMSSTT(selectedPosition.PurchaseDate)) select stopLimit).
OrderByDescending(x => x.AnalysisDate).ToList());
} else
{
stopLimits = new MarketData.Generator.Model.StopLimits((from MarketData.Generator.Model.StopLimit stopLimit in sessionParams.StopLimits
where stopLimit.Symbol.Equals(selectedPosition.Symbol) && stopLimit.AnalysisDate > selectedPosition.PurchaseDate
&& stopLimit.AnalysisDate <= selectedPosition.SellDate select stopLimit).
OrderByDescending(x => x.AnalysisDate).ToList());
}
MarketData.MarketDataModel.StopLimit initialStopLimit = new MarketData.MarketDataModel.StopLimit();
initialStopLimit.Symbol = selectedPosition.Symbol;
initialStopLimit.Shares = 0;
initialStopLimit.StopPrice = selectedPosition.InitialStopLimit;
initialStopLimit.StopType = StopLimitConstants.STOP_QUOTE;
initialStopLimit.EffectiveDate = dateGenerator.FindNextBusinessDay(selectedPosition.PurchaseDate);
initialStopLimit.EffectiveDate = selectedPosition.PurchaseDate;
initialStopLimit.Active = 1;
marketDataModelStopLimits.Add(initialStopLimit);
foreach (MarketData.Generator.Model.StopLimit stopLimit in stopLimits)
{
MarketData.MarketDataModel.StopLimit marketDataModelStopLimit = new MarketData.MarketDataModel.StopLimit();
@@ -1345,11 +1405,64 @@ namespace TradeBlotter.ViewModels
marketDataModelStopLimit.Active = 1;
marketDataModelStopLimits.Add(marketDataModelStopLimit);
}
return marketDataModelStopLimits;
}
// ****************************************************************************************************************************************************************
// *************************************************************************** T O O L T I P C A L L O U T S *****************************************************
// ****************************************************************************************************************************************************************
public String ToolTipTrailingStop
{
get
{
StringBuilder sb=new StringBuilder();
if(null==selectedPosition) return "Please select a position by clicking on a row.";
sb.Append("[TrailingStop]=([TrailingStopLimit])").Append("\n");
sb.Append(Utility.FormatCurrency(selectedPosition.TrailingStopLimit)).Append("=").Append(Utility.FormatCurrency(selectedPosition.TrailingStopLimit)).Append("\n");
List<MarketData.Generator.Model.StopLimit> stopLimits=GetHistoricalStopLimits();
if(selectedPosition.TrailingStopLimit > selectedPosition.PurchasePrice)
{
sb.Append("Riskless Gain").Append(" = ");
sb.Append(String.Format("(Trailing Stop - Purchase Price) * Shares"));
sb.Append("\n");
sb.Append(String.Format("{0}",Utility.FormatCurrency((selectedPosition.TrailingStopLimit-selectedPosition.PurchasePrice)*selectedPosition.Shares)));
sb.Append(String.Format("=({0}-{1})*{2}",Utility.FormatCurrency(selectedPosition.TrailingStopLimit),Utility.FormatCurrency(selectedPosition.PurchasePrice),Utility.FormatNumber(selectedPosition.Shares,3)));
sb.Append("\n");
}
if(null!=stopLimits && 0!=stopLimits.Count)
{
sb.Append("Stop History").Append("\n");
foreach(MarketData.Generator.Model.StopLimit stopLimit in stopLimits)
{
sb.Append(String.Format("Analysis Date:{0} New Stop:{1} Previous Stop:{2}",Utility.DateTimeToStringMMSDDSYYYY(stopLimit.AnalysisDate),Utility.FormatCurrency(stopLimit.NewStop),Utility.FormatCurrency(stopLimit.PreviousStop)));
sb.Append("\n");
}
}
return sb.ToString();
}
}
public String ToolTipInitialStop
{
get
{
StringBuilder sb=new StringBuilder();
if(null==selectedPosition) return "Please select a position by clicking on a row.";
sb.Append("[InitialStop]=([InitialStopLimit])").Append("\n");
sb.Append(Utility.FormatCurrency(selectedPosition.InitialStopLimit)).Append("=").Append(Utility.FormatCurrency(selectedPosition.InitialStopLimit));
return sb.ToString();
}
}
// ************************************************************** T O O L T I P H E L P E R S **************************************************************
public MarketData.Generator.Model.StopLimits GetHistoricalStopLimits()
{
if(null==sessionParams||null==selectedPosition) return null;
MarketData.Generator.Model.StopLimits stopLimits=new MarketData.Generator.Model.StopLimits(
(from MarketData.Generator.Model.StopLimit stopLimit in sessionParams.StopLimits where stopLimit.StopLimitId.Equals(selectedPosition.Symbol + Utility.DateTimeToStringYYYYMMDDMMSSTT(selectedPosition.PurchaseDate)) select stopLimit)
.OrderByDescending(x => x.AnalysisDate).ToList());
return stopLimits;
}
}
}

View File

@@ -222,7 +222,7 @@
<telerik:GridViewColumn.ToolTipTemplate>
<DataTemplate >
<StackPanel Orientation="Horizontal" >
<TextBlock Background="LemonChiffon" MaxWidth="1000" TextWrapping="Wrap" Text="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type vw:CMTTrendView}},Path=DataContext.ToolTipInitialStop}"/>
<TextBlock Background="LemonChiffon" MaxWidth="1000" TextWrapping="Wrap" Text="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type vw:MGSHMomentumView}},Path=DataContext.ToolTipInitialStop}"/>
</StackPanel>
</DataTemplate>
</telerik:GridViewColumn.ToolTipTemplate>
@@ -237,7 +237,7 @@
<telerik:GridViewColumn.ToolTipTemplate>
<DataTemplate >
<StackPanel Orientation="Horizontal" >
<TextBlock Background="LemonChiffon" MaxWidth="1000" TextWrapping="Wrap" Text="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type vw:CMTTrendView}},Path=DataContext.ToolTipTrailingStop}"/>
<TextBlock Background="LemonChiffon" MaxWidth="1000" TextWrapping="Wrap" Text="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type vw:MGSHMomentumView}},Path=DataContext.ToolTipTrailingStop}"/>
</StackPanel>
</DataTemplate>
</telerik:GridViewColumn.ToolTipTemplate>