diff --git a/PortfolioManager/Dialogs/EditPositionDialog.axaml b/PortfolioManager/Dialogs/EditPositionDialog.axaml
index 0c1a6f9..04751a7 100644
--- a/PortfolioManager/Dialogs/EditPositionDialog.axaml
+++ b/PortfolioManager/Dialogs/EditPositionDialog.axaml
@@ -3,7 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
- xmlns:vm="using:PortfolioManager.Dialogs"
+ xmlns:vm="using:PortfolioManager.Dialogs"
x:Class="PortfolioManager.Dialogs.EditPositionDialog"
x:DataType="vm:EditPositionDialogViewModel"
Title="Edit Position Dialog"
@@ -42,13 +42,15 @@
-
+
-
+
+
Sync Trailing Stop
@@ -56,7 +58,7 @@
-
+
diff --git a/PortfolioManager/Dialogs/EditPositionDialogViewModel.cs b/PortfolioManager/Dialogs/EditPositionDialogViewModel.cs
index 45fc51a..d7f6f3f 100644
--- a/PortfolioManager/Dialogs/EditPositionDialogViewModel.cs
+++ b/PortfolioManager/Dialogs/EditPositionDialogViewModel.cs
@@ -1,10 +1,12 @@
using System;
+using System.Text;
using System.Threading.Tasks;
using Avalonia.Controls;
using CommunityToolkit.Mvvm.Input;
using MarketData.DataAccess;
using MarketData.Generator.Interface;
using MarketData.MarketDataModel;
+using MarketData.Numerical;
using MarketData.Utils;
using PortfolioManager.ViewModels;
@@ -92,9 +94,21 @@ namespace PortfolioManager.Dialogs
{
get
{
- return "Recommended Initial Stop: " + Utility.FormatCurrency(sourcePosition.PurchasePrice * (1.00 - sourcePosition.PositionRiskPercentDecimal), 2);
+ StringBuilder sb = new StringBuilder();
+ sb.Append("Recommended Initial Stop: ").Append(Utility.FormatCurrency(Numerics.Discount(sourcePosition.PurchasePrice,sourcePosition.PositionRiskPercentDecimal), 2));
+ sb.Append(" = Discount(").Append(Utility.FormatCurrency(sourcePosition.PurchasePrice,2)).Append(",").Append(Utility.FormatPercent(sourcePosition.PositionRiskPercentDecimal,2)).Append(")");
+
+ return sb.ToString();
}
}
+
+ public String InitialStopRecommendationDescription
+ {
+ get
+ {
+ return "InitialStopRecommendationDescription";
+ }
+ }
public String TrailingStopLimit
{
diff --git a/PortfolioManager/Renderers/BollingerBandRenderer.cs b/PortfolioManager/Renderers/BollingerBandRenderer.cs
index f8b264e..9fb9dae 100644
--- a/PortfolioManager/Renderers/BollingerBandRenderer.cs
+++ b/PortfolioManager/Renderers/BollingerBandRenderer.cs
@@ -24,59 +24,10 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace PortfolioManager.Renderers
{
- public class MarkerItem
- {
- public MarkerItem(double markerDate, double markerPrice)
- {
- MarkerDate = markerDate;
- MarkerPrice = markerPrice;
- }
-
- public double MarkerDate { get; set; }
-
- public double MarkerPrice { get; set; }
- }
-
- public class TextMarkerManager : List
- {
- private DateGenerator dateGenerator = new DateGenerator();
- private const double DATE_SPREAD_PCNT = 10.0; // PERCENT
- private const double PRICE_SPREAD_PCNT = 10.0; // PERCENT
-
- public Coordinates GetBestMarkerLocation(double markerDate, double markerPrice,OffsetDictionary offsetDictionary,double verticalAdjustmentFactor)
- {
- if(!IsOverlapped(markerDate,markerPrice,offsetDictionary))
- {
- Add(new MarkerItem(markerDate, markerPrice));
- return new Coordinates(){X=markerDate,Y=markerPrice};
- }
- Add(new MarkerItem(markerDate, markerPrice-verticalAdjustmentFactor));
- return new Coordinates(){X=markerDate,Y=markerPrice-verticalAdjustmentFactor};
- }
-
- private bool IsOverlapped(double markerDate, double markerPrice,OffsetDictionary offsetDictionary)
- {
- foreach(MarkerItem markerItem in this)
- {
- double markerItemDate = markerItem.MarkerDate;
- double markerItemPrice = markerItem.MarkerPrice;
- double minDate = markerItemDate - offsetDictionary.HorizontalSpread*(DATE_SPREAD_PCNT/100.0);
- double maxDate = markerItemDate + offsetDictionary.HorizontalSpread*(DATE_SPREAD_PCNT/100.0);
- double minPrice = markerItemPrice - offsetDictionary.VerticalSpread*(PRICE_SPREAD_PCNT/100.0);
- double maxPrice = markerItemPrice + offsetDictionary.VerticalSpread*(PRICE_SPREAD_PCNT/100.0);
-
- if(markerDate>=minDate && markerDate<=maxDate && markerPrice >=minPrice && markerPrice<=maxPrice)
- {
- return true;
- }
- }
- return false;
- }
- }
-
-
-// *********************************************************************************************************************************************
-
+ ///
+ /// BollingerBandRenderer - Renders the ScottPlot for the Bollinger Bands
+ /// If external stop limits are provided then the renderer will use those otherwise the renderer will look up using StopLimitDA
+ ///
public class BollingerBandRenderer : ModelBase
{
private String selectedSymbol = default;
@@ -89,8 +40,8 @@ namespace PortfolioManager.Renderers
private bool showInsiderTransactions = true;
private bool showLeastSquares = true;
private bool syncTradeToBand = true;
- private StopLimit stopLimit = default;
- private StopLimits stopLimits = default;
+ private StopLimit stopLimit = default; // StopLimits that the renderer has located using StopLimitDA
+ private StopLimits externalStopLimits = default; // StopLimits that are provided to the renderer externally by a model
private PortfolioTrades portfolioTrades = default;
private PortfolioTrades portfolioTradesLots = default;
private Prices prices = default;
@@ -289,10 +240,10 @@ namespace PortfolioManager.Renderers
///
private void GenerateStopLimits()
{
- if (null == stopLimits && null == zeroPrice) return;
- if (null != stopLimits)
+ if (null == externalStopLimits && null == zeroPrice) return;
+ if (null != externalStopLimits)
{
- StopLimits = StopLimitCompositeModel.CreateCompositeDataSource(stopLimits);
+ StopLimits = StopLimitCompositeModel.CreateCompositeDataSource(externalStopLimits);
}
else if (null != stopLimit && null != zeroPrice)
{
@@ -313,16 +264,16 @@ namespace PortfolioManager.Renderers
if(!showTradeLabels)return;
// Add the text marker
- if (null != stopLimits)
+ if (null != externalStopLimits)
{
- for (int index = 0; index < stopLimits.Count; index++)
+ for (int index = 0; index < externalStopLimits.Count; index++)
{
- StopLimit limit = stopLimits[index];
+ StopLimit limit = externalStopLimits[index];
StringBuilder sb = new StringBuilder();
sb.Append(limit.StopType).Append(" ");
sb.Append(Utility.FormatCurrency(limit.StopPrice));
- if (index == stopLimits.Count - 1)
+ if (index == externalStopLimits.Count - 1)
{
Price latestPrice = prices[0];
double percentOffsetFromLow = ((latestPrice.Low - limit.StopPrice) / limit.StopPrice);
@@ -573,11 +524,11 @@ namespace PortfolioManager.Renderers
{
get
{
- return stopLimits;
+ return externalStopLimits;
}
set
{
- stopLimits = value;
+ externalStopLimits = value;
base.OnPropertyChanged("ExternalStopLimits");
}
}
diff --git a/PortfolioManager/Renderers/MarkerItem.cs b/PortfolioManager/Renderers/MarkerItem.cs
new file mode 100644
index 0000000..ec9cec2
--- /dev/null
+++ b/PortfolioManager/Renderers/MarkerItem.cs
@@ -0,0 +1,16 @@
+
+namespace PortfolioManager.Renderers
+{
+ public class MarkerItem
+ {
+ public MarkerItem(double markerDate, double markerPrice)
+ {
+ MarkerDate = markerDate;
+ MarkerPrice = markerPrice;
+ }
+
+ public double MarkerDate { get; set; }
+
+ public double MarkerPrice { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/PortfolioManager/Renderers/TextMarkerManager.cs b/PortfolioManager/Renderers/TextMarkerManager.cs
new file mode 100644
index 0000000..cea0622
--- /dev/null
+++ b/PortfolioManager/Renderers/TextMarkerManager.cs
@@ -0,0 +1,43 @@
+using System.Collections.Generic;
+using MarketData.Utils;
+using ScottPlot;
+
+namespace PortfolioManager.Renderers
+{
+ public class TextMarkerManager : List
+ {
+ private DateGenerator dateGenerator = new DateGenerator();
+ private const double DATE_SPREAD_PCNT = 10.0; // PERCENT
+ private const double PRICE_SPREAD_PCNT = 10.0; // PERCENT
+
+ public Coordinates GetBestMarkerLocation(double markerDate, double markerPrice,OffsetDictionary offsetDictionary,double verticalAdjustmentFactor)
+ {
+ if(!IsOverlapped(markerDate,markerPrice,offsetDictionary))
+ {
+ Add(new MarkerItem(markerDate, markerPrice));
+ return new Coordinates(){X=markerDate,Y=markerPrice};
+ }
+ Add(new MarkerItem(markerDate, markerPrice-verticalAdjustmentFactor));
+ return new Coordinates(){X=markerDate,Y=markerPrice-verticalAdjustmentFactor};
+ }
+
+ private bool IsOverlapped(double markerDate, double markerPrice,OffsetDictionary offsetDictionary)
+ {
+ foreach(MarkerItem markerItem in this)
+ {
+ double markerItemDate = markerItem.MarkerDate;
+ double markerItemPrice = markerItem.MarkerPrice;
+ double minDate = markerItemDate - offsetDictionary.HorizontalSpread*(DATE_SPREAD_PCNT/100.0);
+ double maxDate = markerItemDate + offsetDictionary.HorizontalSpread*(DATE_SPREAD_PCNT/100.0);
+ double minPrice = markerItemPrice - offsetDictionary.VerticalSpread*(PRICE_SPREAD_PCNT/100.0);
+ double maxPrice = markerItemPrice + offsetDictionary.VerticalSpread*(PRICE_SPREAD_PCNT/100.0);
+
+ if(markerDate>=minDate && markerDate<=maxDate && markerPrice >=minPrice && markerPrice<=maxPrice)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}