Changes for MGSHBacktest model.

Code cleanup.
This commit is contained in:
2025-02-10 07:57:00 -05:00
parent 36b10b4824
commit 0db4473632
16 changed files with 378 additions and 78 deletions

View File

@@ -1,17 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
using MarketData.MarketDataModel;
using MarketData.DataAccess;
using MarketData.Utils;
using System.Linq;
using MarketData.Helper;
using MarketData.Numerical;
using System.Reflection;
using MarketData.Generator.Interface;
namespace MarketData.Generator.CMTrend
{
public class Position
public class Position : IPosition
{
public Position()
{

View File

@@ -8,10 +8,7 @@ using MarketData.Utils;
using System.Linq;
using MarketData.Helper;
using MarketData.Numerical;
using System.Threading;
using MarketData.Integration;
using MarketData.Cache;
using System.IO;
using MarketData.Generator.Indicators;
using MarketData.Generator.Model;
using StopLimit=MarketData.Generator.Model.StopLimit;

View File

@@ -283,6 +283,7 @@ namespace MarketData.Generator.MGSHMomentum
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("*****************************************************************************************"));
StopLimit newStopLimit=new StopLimit
{
StopLimitId=position.Symbol + Utility.DateTimeToStringYYYYMMDDMMSSTT(position.PurchaseDate),
Symbol=position.Symbol,
AnalysisDate=analysisDate,
PreviousStop=0.00==position.TrailingStopLimit?position.InitialStopLimit:position.TrailingStopLimit,

View File

@@ -22,12 +22,13 @@ namespace MarketData.Generator.MGSHMomentum
private MGSHConfiguration Configuration{get;set;}
private int HoldingPeriod{get{return Configuration.HoldingPeriod;}}
private int MaxPositions{get{return Configuration.MaxPositions;}}
private List<String> NoTradeSymbols{get{return Utility.ToList(Configuration.NoTradeSymbols);}}
private int MaxPricingExceptions{get{return Configuration.MaxPricingExceptions;}}
//private List<String> NoTradeSymbols{get{return Utility.ToList(Configuration.NoTradeSymbols);}}
private MGSHActivePositions ActivePositions{get;set;}
// private SMSNotifications SMSNotifications{get;set;}
private StopLimits StopLimits{get;set;}
private MGSHPositions AllPositions{get;set;}
private MGSHPositions HedgePositions{get;set;}
private MGSHPricingExceptions PricingExceptions{get;set;}
private int Cycle{get;set;}
private DateTime TradeDate{get;set;}
private DateTime StartDate{get;set;}
@@ -118,6 +119,61 @@ namespace MarketData.Generator.MGSHMomentum
}
}
// ******************************************************************************************************************************************************
// *************************************************************************** E D I T ******************************************************************
// ******************************************************************************************************************************************************
public bool EditPosition(String symbol,DateTime purchaseDate,double purchasePrice,double initialStop,double trailingStop,String sessionFile)
{
if (!MGSHSessionManager.IsValidSessionFile(sessionFile))
{
MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Invalid session file '{0}'.", sessionFile));
return false;
}
PathSessionFileName = sessionFile;
MGSHSessionParams sessionParams=MGSHSessionManager.RestoreSession(PathSessionFileName);
Configuration = sessionParams.Configuration;
TradeDate = sessionParams.TradeDate;
StartDate = sessionParams.StartDate;
AnalysisDate = sessionParams.AnalysisDate;
Cycle=sessionParams.Cycle;
sessionParams.LastUpdated = DateTime.Now;
//sessionParams.CMTParams.AnalysisDate=DateTime.Now;
StopLimits=sessionParams.StopLimits;
ActivePositions=sessionParams.ActivePositions;
AllPositions=sessionParams.AllPositions;
HedgePositions=sessionParams.HedgePositions;
CashBalance=sessionParams.CashBalance;
NonTradeableCash=sessionParams.NonTradeableCash;
HedgeCashBalance=sessionParams.HedgeCashBalance;
PricingExceptions=sessionParams.PricingExceptions;
if(!BackupSession())return false;
MGSHPositions activePositions = ActivePositions.GetPositions();
MGSHPosition position = activePositions.Where(x => x.Symbol.Equals(symbol) && x.PurchaseDate.Equals(purchaseDate)).FirstOrDefault();
if (null == position)
{
MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Cannot locate position for symbol '{0}' purchased on {1}.", symbol, purchaseDate.ToShortDateString()));
return false;
}
if (!position.PurchaseDate.Equals(purchaseDate)) position.PurchaseDate = purchaseDate;
if (!position.TrailingStopLimit.Equals(trailingStop)) position.TrailingStopLimit = trailingStop;
if (!position.InitialStopLimit.Equals(initialStop)) position.InitialStopLimit = initialStop;
if (!position.PurchasePrice.Equals(purchasePrice))
{
MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Adjusting Cash for Position for symbol '{0}' purchased on {1}. Original Price: {2} New Price: {3} Change in Cash: {4}", symbol, purchaseDate.ToShortDateString(), Utility.FormatCurrency(position.PurchasePrice), Utility.FormatCurrency(purchasePrice), Utility.FormatCurrency((position.PurchasePrice - purchasePrice) * position.Shares)));
MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Adjusting R for Position for symbol '{0}' purchased on {1}. Original R: {2} New R: {3} ", symbol, purchaseDate.ToShortDateString(), Utility.FormatNumber(position.R, 2), Utility.FormatNumber(position.PositionRiskPercentDecimal * purchasePrice)));
CashBalance += (position.PurchasePrice - purchasePrice) * position.Shares;
position.Comment = (null == position.Comment ? "" : position.Comment + ".") + String.Format("Price changed on {0} from {1} to {2}", DateTime.Now.ToShortDateString(), Utility.FormatCurrency(position.PurchasePrice), Utility.FormatCurrency(purchasePrice));
position.PurchasePrice = purchasePrice;
}
SaveSession();
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Position for symbol '{0}' purchased on {1} has been modified and saved.",symbol,purchaseDate.ToShortDateString()));
return true;
}
// ******************************************************************************************************************************************************
// **************************************************************** S T A T I S T I C S ******************************************************************
// ******************************************************************************************************************************************************
// Calcualtes the expectation for the model ( Percent of Winning Trades * Average Gain)/(Percent Losing Trades * Average Loss)
// The expectation should be above zero
// Using the AllPositions collection ignored open positions and active hedge positions
@@ -308,6 +364,7 @@ namespace MarketData.Generator.MGSHMomentum
ActivePositions=new MGSHActivePositions();
AllPositions=new MGSHPositions();
HedgePositions=new MGSHPositions();
PricingExceptions=new MGSHPricingExceptions();
StartDate=paramStartDate;
TradeDate=paramStartDate;
AnalysisDate=paramAnalysisDate;
@@ -450,14 +507,16 @@ namespace MarketData.Generator.MGSHMomentum
if(CashBalance-positions.Exposure<=0.00)
{
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("********** Insufficient funds to make additional purchases.**************"));
return;
}
MDTrace.WriteLine(LogLevel.DEBUG,"********************** B U Y ********************");
if(!ActivePositions.ContainsKey(slotIndex))ActivePositions.Add(slotIndex, positions);
else ActivePositions[slotIndex].AddRange(positions);
CashBalance-=positions.Exposure;
SetInitialStopLimitsForNewPositions(TradeDate, positions);
ActivePositions[slotIndex].Display();
else
{
MDTrace.WriteLine(LogLevel.DEBUG,"********************** B U Y ********************");
if(!ActivePositions.ContainsKey(slotIndex))ActivePositions.Add(slotIndex, positions);
else ActivePositions[slotIndex].AddRange(positions);
CashBalance-=positions.Exposure;
SetInitialStopLimitsForNewPositions(TradeDate, positions);
ActivePositions[slotIndex].Display();
}
UpdateStopLimitsForActivePositions(TradeDate);
DisplayBalance();
}
@@ -582,7 +641,8 @@ namespace MarketData.Generator.MGSHMomentum
shortPosition.PurchasePrice = shortPositionPrice.Close;
shortPosition.CurrentPrice = shortPositionPrice.Close;
shortPosition.InitialStopLimit = shortPosition.PurchasePrice - ( shortPosition.PurchasePrice * Configuration.HedgeRiskPercentDecimal);
shortPosition.R = shortPosition.PurchasePrice - shortPosition.InitialStopLimit;
shortPosition.PositionRiskPercentDecimal = Configuration.HedgeRiskPercentDecimal; // The risk percent
shortPosition.R = shortPosition.PositionRiskPercentDecimal * shortPosition.PurchasePrice; // PositionRiskPercentDecimal*PurchasePrice
shortPosition.TrailingStopLimit = shortPosition.InitialStopLimit;
shortPosition.LastStopAdjustment = Utility.Epoch;
shortPosition.Shares = (int)Math.Floor(cashAllocation / shortPositionPrice.Close);
@@ -685,7 +745,8 @@ namespace MarketData.Generator.MGSHMomentum
foreach(MGSHPosition position in positions)
{
position.InitialStopLimit = position.PurchasePrice - (position.PurchasePrice * Configuration.StopLimitRiskPercentDecimal);
position.R = position.PurchasePrice - position.InitialStopLimit;
position.PositionRiskPercentDecimal = Configuration.StopLimitRiskPercentDecimal; // = position.PurchasePrice - position.InitialStopLimit;
position.R = position.PositionRiskPercentDecimal * position.PurchasePrice; // PositionRiskPercentDecimal*PurchasePrice
position.TrailingStopLimit = position.InitialStopLimit;
position.LastStopAdjustment = Utility.Epoch;
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Initial stop limit for {0} on {1} with PurchsePrice:{2} is {3}, Shares:{4} Risk:{5}%",
@@ -718,10 +779,23 @@ namespace MarketData.Generator.MGSHMomentum
foreach(MGSHPosition position in positions)
{
Price price=GBPriceCache.GetInstance().GetPrice(position.Symbol,analysisDate);
// Incorporate Pricing Exceptions
if(null==price)
{
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateStopLimitsForActivePositions] No price for {0} on {1}. Cannot evaluate stop limit.",position.Symbol,analysisDate.ToShortDateString()));
int exceptionCount=AddPricingException(position.Symbol);
if(exceptionCount>MaxPricingExceptions)
{
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateStopLimitsForActivePositions] Selling {0} on {1} because price exceptions exceeds maximum of {2}",position.Symbol,analysisDate.ToShortDateString(),MaxPricingExceptions));
price=GBPriceCache.GetInstance().GetPriceOrLatestAvailable(position.Symbol,analysisDate);
position.SellDate=analysisDate;
position.CurrentPrice=price.Close;
position.Comment="Close due to pricing exceptions.";
CashBalance+=position.MarketValue;
AllPositions.Add(position);
closedPositions.Add(position);
}
else MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateStopLimitsForActivePositions] Cannot determine price for {0} on {1}",position.Symbol,analysisDate.ToShortDateString()));
continue;
}
@@ -733,6 +807,7 @@ namespace MarketData.Generator.MGSHMomentum
}
position.CurrentPrice = price.Close;
RemovePricingException(position.Symbol);
if(price.Low < position.TrailingStopLimit && !position.PurchaseDate.Equals(analysisDate))
{
position.SellDate = analysisDate;
@@ -741,10 +816,10 @@ namespace MarketData.Generator.MGSHMomentum
CashBalance += position.MarketValue;
AllPositions.Add(position);
closedPositions.Add(position);
}
else if(price.Low > position.PurchasePrice) // If the Low price is above our purchase price then re-evaluate the stop
}
else if (price.Low > position.PurchasePrice) // If the Low price is above our purchase price then re-evaluate the stop
{
EvaluateStopPrice(analysisDate,price,position);
EvaluateStopPrice(analysisDate, price, position);
}
}
}
@@ -777,9 +852,9 @@ namespace MarketData.Generator.MGSHMomentum
// only adjust stops if we are trending up
Prices prices=GBPriceCache.GetInstance().GetPrices(position.Symbol,analysisDate,Configuration.StopLimitPriceTrendDays);
PriceTrendIndicatorResult priceTrendIndicatorResult=PriceTrendIndicator.IsUptrend(prices,Configuration.StopLimitPriceTrendDays);
if(!priceTrendIndicatorResult.IsUpTrend)
if (!priceTrendIndicatorResult.IsUpTrend)
{
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} does not have upward price trend (higher highs and higher lows for {1} consecutive days), will not adjust stop price",position.Symbol,Configuration.StopLimitPriceTrendDays));
MDTrace.WriteLine(LogLevel.DEBUG, String.Format("{0} does not have upward price trend (higher highs and higher lows for {1} consecutive days), will not adjust stop price", position.Symbol, Configuration.StopLimitPriceTrendDays));
return changed;
}
@@ -793,7 +868,7 @@ namespace MarketData.Generator.MGSHMomentum
{
trailingStopScaled=GetStopLimitWithScalingAverageTrueRange(analysisDate,currentPrice,position,trailingStop);
trailingStop=Math.Max(trailingStop,trailingStopScaled);
if(trailingStop>=currentPrice.Low||trailingStop>=currentPrice.Close)
if(trailingStop>=currentPrice.Low || trailingStop>=currentPrice.Close)
{
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The calculated trailing stop for {0} of {1} would be higher than the Low/Close of {2}.",position.Symbol,Utility.FormatCurrency(trailingStop),Utility.FormatCurrency(currentPrice.Low)));
return changed;
@@ -804,10 +879,18 @@ namespace MarketData.Generator.MGSHMomentum
return changed;
}
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("****************************** A D J U S T S T O P L I M I T ************************"));
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Adjusting StopLimit after {0} days for {1} from {2} to {3}. Purchase Price: {4} Current Price:{5} Spread:{6} Shares:{7}",daysHeld,position.Symbol,Utility.FormatCurrency(position.TrailingStopLimit),Utility.FormatCurrency(trailingStop),Utility.FormatCurrency(position.PurchasePrice),Utility.FormatCurrency(currentPrice.Close),Utility.FormatPercent((currentPrice.Close-trailingStop)/trailingStop),Utility.FormatNumber(position.Shares,2)));
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Adjusting StopLimit after {0} days for {1} from {2} to {3}. Purchase Price: {4} Current Price:{5} Spread:{6} Shares:{7}",
daysHeld,
position.Symbol,Utility.FormatCurrency(position.TrailingStopLimit),
Utility.FormatCurrency(trailingStop),
Utility.FormatCurrency(position.PurchasePrice),
Utility.FormatCurrency(currentPrice.Close),
Utility.FormatPercent((currentPrice.Close-trailingStop)/trailingStop),
Utility.FormatNumber(position.Shares,2)));
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("*****************************************************************************************"));
StopLimit newStopLimit=new StopLimit
{
StopLimitId=position.Symbol + Utility.DateTimeToStringYYYYMMDDMMSSTT(position.PurchaseDate),
Symbol=position.Symbol,
AnalysisDate=analysisDate,
PreviousStop=0.00==position.TrailingStopLimit?position.InitialStopLimit:position.TrailingStopLimit,
@@ -846,6 +929,7 @@ namespace MarketData.Generator.MGSHMomentum
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("****************************************************************************************"));
StopLimit newStopLimit=new StopLimit
{
StopLimitId=position.Symbol + Utility.DateTimeToStringYYYYMMDDMMSSTT(position.PurchaseDate),
Symbol=position.Symbol,
AnalysisDate=analysisDate,
PreviousStop=0.00==position.TrailingStopLimit?position.InitialStopLimit:position.TrailingStopLimit,
@@ -891,15 +975,46 @@ namespace MarketData.Generator.MGSHMomentum
return stopLimit;
}
// **********************************************************************************************************************************************************
// ***************************************************** S T O P L I M I T C O L L E C T I O N M A I N T E N A N C E ***********************************
// **********************************************************************************************************************************************************
// **************************************************************************************************************************************
// ************************************************** S T O P L I M I T C O L L E C T I O N M A I N T E N A N C E ******************
// **************************************************************************************************************************************
private void AddStopLimit(StopLimit stopLimit)
{
if(null == StopLimits)StopLimits = new StopLimits();
StopLimits.Add(stopLimit);
}
// ************************************************************************************************************************************************
// ********************************************* P R I C I N G E X C E P T I O N C O L L E C T I O N M A I N T E N A N C E ******************
// ************************************************************************************************************************************************
private int AddPricingException(String symbol)
{
MGSHPricingException pricingException = PricingExceptions.Where(x => x.Symbol.Equals(symbol)).FirstOrDefault();
if (null == pricingException)
{
pricingException = new MGSHPricingException(symbol, 1);
PricingExceptions.Add(pricingException);
PricingExceptions.Add(pricingException);
}
else pricingException.ExceptionCount++;
return pricingException.ExceptionCount;
}
private void RemovePricingException(String symbol)
{
MGSHPricingException pricingException = PricingExceptions.Where(x => x.Symbol.Equals(symbol)).FirstOrDefault();
if (null == pricingException) return;
PricingExceptions.Remove(pricingException);
}
private bool HasPricingException(String symbol)
{
MGSHPricingException pricingException = PricingExceptions.Where(x => x.Symbol.Equals(symbol)).FirstOrDefault();
if (null == pricingException) return false;
return true;
}
// ******************************************************************************************************************************************************
// ******************************************************************************************************************************************************
// ******************************************************************************************************************************************************
@@ -1185,6 +1300,7 @@ namespace MarketData.Generator.MGSHMomentum
AllPositions=sessionParams.AllPositions;
HedgePositions=sessionParams.HedgePositions;
StopLimits=sessionParams.StopLimits;
PricingExceptions = sessionParams.PricingExceptions;
Cycle=sessionParams.Cycle;
CashBalance=sessionParams.CashBalance;
NonTradeableCash=sessionParams.NonTradeableCash;
@@ -1211,9 +1327,33 @@ namespace MarketData.Generator.MGSHMomentum
sessionParams.HedgePositions=HedgePositions;
sessionParams.Cycle=Cycle;
sessionParams.StopLimits=StopLimits;
sessionParams.PricingExceptions=PricingExceptions;
sessionParams.CashBalance=CashBalance;
sessionParams.NonTradeableCash=NonTradeableCash;
sessionManager.SaveSession(sessionParams,PathSessionFileName);
}
public bool BackupSession()
{
String[] parts=PathSessionFileName.Split('.');
String backupFileName=parts[0]+"_"+Utility.DateTimeToStringYYYYMMDDMMSSTT(DateTime.Now)+".bak";
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Saving session to '{0}'",backupFileName));
MGSHSessionParams sessionParams=new MGSHSessionParams();
MGSHSessionManager sessionManager=new MGSHSessionManager();
sessionParams.LastUpdated=Today();
sessionParams.TradeDate=TradeDate;
sessionParams.StartDate=StartDate;
sessionParams.AnalysisDate=AnalysisDate;
sessionParams.Configuration=Configuration;
sessionParams.ActivePositions=ActivePositions;
sessionParams.AllPositions=AllPositions;
sessionParams.HedgePositions=HedgePositions;
sessionParams.Cycle=Cycle;
sessionParams.StopLimits=StopLimits;
sessionParams.PricingExceptions=PricingExceptions;
sessionParams.CashBalance=CashBalance;
sessionParams.NonTradeableCash=NonTradeableCash;
return sessionManager.SaveSession(sessionParams,backupFileName);
}
}
}

View File

@@ -35,6 +35,9 @@ namespace MarketData.Generator.MGSHMomentum
// Manage buying and selling
public bool KeepSlotPositions{get;set;} // if this setting is true then we never sell slot positions, allowing the trailing stop to eventually invoke a sell.
// Pricing Exceptions
public int MaxPricingExceptions{get;set;} // This is the pricing exception limit. If we have this many of exceptions then we will sell the security at the last known good price.
// Fundamental screenings
public double MarketCapLowerLimit{get;set;}
@@ -121,6 +124,8 @@ namespace MarketData.Generator.MGSHMomentum
// Manage buying and selling
KeepSlotPositions=true; // The default is true to retain legacy functionality
MaxPricingExceptions=3; // The maximum number of pricing exceptions. If exceeded then the security will be sold at the last known good price
// Other settings
UseEBITDAScreen=true; // true is the default
UseRevenuePerShareScreen=true; // true is the default
@@ -203,6 +208,8 @@ namespace MarketData.Generator.MGSHMomentum
nvpCollection.Add(new NVP("HedgeCloseAboveSMANDays",HedgeCloseAboveSMANDays.ToString()));
nvpCollection.Add(new NVP("HedgeBandBreakCheckDays",HedgeBandBreakCheckDays.ToString()));
nvpCollection.Add(new NVP("MaxPricingExceptions",MaxPricingExceptions.ToString()));
return nvpCollection;
}
public static MGSHConfiguration FromNVPCollection(NVPCollection nvpCollection)
@@ -240,6 +247,7 @@ namespace MarketData.Generator.MGSHMomentum
mgConfiguration.UseFallbackCandidate=nvpDictionary["UseFallbackCandidate"].Get<Boolean>();
mgConfiguration.FallbackCandidate=nvpDictionary["FallbackCandidate"].Get<String>();
mgConfiguration.FallbackCandidateBestOf=nvpDictionary["FallbackCandidateBestOf"].Get<String>();
mgConfiguration.MaxPricingExceptions=nvpDictionary["MaxPricingExceptions"].Get<int>();
if(nvpDictionary.ContainsKey("QualityIndicatorType")) mgConfiguration.QualityIndicatorType=nvpDictionary["QualityIndicatorType"].Get<String>();
else mgConfiguration.QualityIndicatorType=MGSHQualityIndicator.ToString(MGSHQualityIndicator.QualityType.IDIndicator);
@@ -283,6 +291,8 @@ namespace MarketData.Generator.MGSHMomentum
public void DisplayConfiguration()
{
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Verbose,{0}",Verbose));
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MaxPricingExceptions,{0}",MaxPricingExceptions));
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("KeepSlotPositions,{0}",KeepSlotPositions));
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Holding Period,{0}",HoldingPeriod));
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MaxPositions,{0}",MaxPositions));

View File

@@ -2,10 +2,11 @@
using System.Collections.Generic;
using MarketData.Utils;
using System.Linq;
using MarketData.Generator.Interface;
namespace MarketData.Generator.MGSHMomentum
{
public class MGSHPosition
public class MGSHPosition : IPosition
{
public MGSHPosition()
{
@@ -33,9 +34,40 @@ namespace MarketData.Generator.MGSHMomentum
InitialStopLimit = position.InitialStopLimit;
TrailingStopLimit = position.TrailingStopLimit;
LastStopAdjustment = position.LastStopAdjustment;
PositionRiskPercentDecimal = position.PositionRiskPercentDecimal;
R = position.R;
if(null!=position.Comment)Comment=string.Copy(position.Comment);
}
public static MGSHPosition Clone(MGSHPosition positionToClone)
{
MGSHPosition position = new MGSHPosition();
position.Symbol = positionToClone.Symbol;
position.PurchaseDate = positionToClone.PurchaseDate;
position.SellDate=positionToClone.SellDate;
position.Shares=positionToClone.Shares;
position.PurchasePrice=positionToClone.PurchasePrice;
position.CurrentPrice=positionToClone.CurrentPrice;
position.Volume=positionToClone.Volume;
position.Return1D=positionToClone.Return1D;
position.ZacksRank=positionToClone.ZacksRank;
position.CumReturn252=positionToClone.CumReturn252;
position.IDIndicator=positionToClone.IDIndicator;
position.Score=positionToClone.Score;
position.MaxDrawdown=positionToClone.MaxDrawdown;
position.MaxUpside=positionToClone.MaxUpside;
position.Velocity=positionToClone.Velocity;
position.PE=positionToClone.PE;
position.Beta=positionToClone.Beta;
position.InitialStopLimit=positionToClone.InitialStopLimit;
position.TrailingStopLimit=positionToClone.TrailingStopLimit;
position.LastStopAdjustment=positionToClone.LastStopAdjustment;
position.PositionRiskPercentDecimal=positionToClone.PositionRiskPercentDecimal;
position.R=positionToClone.R;
position.Comment=positionToClone.Comment;
return position;
}
public String Symbol{get;set;}
public DateTime PurchaseDate{get;set;}
public DateTime SellDate{get;set;}
@@ -60,7 +92,8 @@ namespace MarketData.Generator.MGSHMomentum
public double InitialStopLimit {get; set; }
public double TrailingStopLimit {get; set; }
public DateTime LastStopAdjustment {get; set; }
public double R {get; set; }
public double PositionRiskPercentDecimal {get; set; }
public double R { get; set; }
public String Comment {get; set; }
public virtual NVPCollection ToNVPCollection()
@@ -86,6 +119,7 @@ namespace MarketData.Generator.MGSHMomentum
nvpCollection.Add(new NVP("InitialStopLimit", InitialStopLimit.ToString()));
nvpCollection.Add(new NVP("TrailingStopLimit", TrailingStopLimit.ToString()));
nvpCollection.Add(new NVP("LastStopAdjustment", LastStopAdjustment.ToString()));
nvpCollection.Add(new NVP("PositionRiskPercentDecimal", PositionRiskPercentDecimal.ToString()));
nvpCollection.Add(new NVP("R", R.ToString()));
nvpCollection.Add(new NVP("Comment", Comment?.ToString()));
return nvpCollection;
@@ -121,6 +155,8 @@ namespace MarketData.Generator.MGSHMomentum
else position.LastStopAdjustment=Utility.Epoch;
if(nvpDictionary.ContainsKey("Comment")) position.Comment=nvpDictionary["Comment"].Get<String>();
else position.Comment=null;
if(nvpDictionary.ContainsKey("PositionRiskPercentDecimal")) position.PositionRiskPercentDecimal=nvpDictionary["PositionRiskPercentDecimal"].Get<double>();
else position.PositionRiskPercentDecimal=double.NaN;
if(nvpDictionary.ContainsKey("R")) position.R=nvpDictionary["R"].Get<double>();
else position.R=double.NaN;
return position;

View File

@@ -64,6 +64,11 @@ namespace MarketData.Generator.MGSHMomentum
streamWriter.WriteLine((new NVP("TotalHedgePositions",nvpHedgePositionsStringList.Count.ToString())).ToString());
foreach(String str in nvpHedgePositionsStringList)streamWriter.WriteLine(str);
NVPCollections pricingExceptionsCollections=sessionParams.PricingExceptions.ToNVPCollections();
List<String> nvpPricingExceptionsCollectionsStringList=pricingExceptionsCollections.ToList();
streamWriter.WriteLine((new NVP("TotalPricingExceptions",nvpPricingExceptionsCollectionsStringList.Count.ToString())).ToString());
foreach(String str in nvpPricingExceptionsCollectionsStringList)streamWriter.WriteLine(str);
streamWriter.Flush();
outStream.Flush();
streamWriter.Close();
@@ -126,6 +131,7 @@ namespace MarketData.Generator.MGSHMomentum
if(2.00==version)
{
// stop limits
int totalStopLimits=(new NVP(streamReader.ReadLine())).Get<int>();
sessionParams.StopLimits=new StopLimits();
for(int stopLimitIndex=0;stopLimitIndex<totalStopLimits;stopLimitIndex++)
@@ -134,6 +140,7 @@ namespace MarketData.Generator.MGSHMomentum
sessionParams.StopLimits.AddFromNVPCollection(nvpCollection);
}
// hedges
int totalHedgePositions = (new NVP(streamReader.ReadLine())).Get<int>();
NVPCollections nvpHedgeCollections=new NVPCollections();
for(int hedgePositionIndex=0;hedgePositionIndex<totalHedgePositions;hedgePositionIndex++)
@@ -142,7 +149,18 @@ namespace MarketData.Generator.MGSHMomentum
nvpHedgeCollections.Add(nvpCollection);
}
sessionParams.HedgePositions=MGSHPositions.FromNVPCollections(nvpHedgeCollections);
}
// pricing exceptions
int totalPricingExceptions = (new NVP(streamReader.ReadLine())).Get<int>();
NVPCollections nvpPricingExceptionsCollections=new NVPCollections();
for(int pricingExceptionIndex=0;pricingExceptionIndex<totalPricingExceptions;pricingExceptionIndex++)
{
NVPCollection nvpCollection=new NVPCollection(streamReader.ReadLine());
nvpPricingExceptionsCollections.Add(nvpCollection);
}
sessionParams.PricingExceptions=MGSHPricingExceptions.FromNVPCollections(nvpPricingExceptionsCollections);
} // version
inStream.Close();
inStream.Dispose();

View File

@@ -17,6 +17,7 @@ namespace MarketData.Generator.MGSHMomentum
public double NonTradeableCash { get; set; }
public StopLimits StopLimits { get; set;}
public MGSHPositions HedgePositions { get; set; }
public MGSHPricingExceptions PricingExceptions{ get; set; }
public int Cycle { get; set; }
// This gets AllPositions+Positions+HedgePositions

View File

@@ -5,6 +5,10 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
/// <summary>
/// This StopLimit class is used by models and the UI
/// </summary>
namespace MarketData.Generator.Model
{
public class StopLimits:List<StopLimit>
@@ -53,6 +57,7 @@ namespace MarketData.Generator.Model
this.CurrentPriceLow=stopLimit.CurrentPriceLow;
this.CurrentPriceClose=stopLimit.CurrentPriceClose;
this.PriceTrendIndicatorSlope=stopLimit.PriceTrendIndicatorSlope;
this.StopLimitId=stopLimit.StopLimitId;
}
public StopLimit(String symbol,DateTime analysisDate,double previousStop,double newStop,double currentPriceLow,double currentPriceClose,double priceTrendIndicatorSlope)
{
@@ -71,15 +76,17 @@ namespace MarketData.Generator.Model
public double CurrentPriceLow{get;set;}
public double CurrentPriceClose{get;set;}
public double PriceTrendIndicatorSlope{get;set;}
public String StopLimitId {get;set;}
public static String Header()
{
StringBuilder sb=new StringBuilder();
sb.Append("Symbol,AnalysisDate,PreviousStop,NewStop,CurrentPriceLow,CurrentPriceClose,PriceTrendIndicatorSlope");
sb.Append("Id,Symbol,AnalysisDate,PreviousStop,NewStop,CurrentPriceLow,CurrentPriceClose,PriceTrendIndicatorSlope");
return sb.ToString();
}
public override String ToString()
{
StringBuilder sb=new StringBuilder();
sb.Append(null==StopLimitId?"":StopLimitId).Append(",");
sb.Append(Symbol).Append(",");
sb.Append(AnalysisDate.ToShortDateString()).Append(",");
sb.Append(Utility.FormatCurrency(PreviousStop)).Append(",");
@@ -99,6 +106,7 @@ namespace MarketData.Generator.Model
nvpCollection.Add(new NVP("CurrentPriceLow",CurrentPriceLow.ToString()));
nvpCollection.Add(new NVP("CurrentPriceClose",CurrentPriceClose.ToString()));
nvpCollection.Add(new NVP("PriceTrendIndicatorSlope",PriceTrendIndicatorSlope.ToString()));
nvpCollection.Add(new NVP("StopLimitId",StopLimitId==null?"":StopLimitId));
return nvpCollection;
}
public static StopLimit FromNVPCollection(NVPCollection nvpCollection)
@@ -113,6 +121,7 @@ namespace MarketData.Generator.Model
stopLimit.CurrentPriceLow=nvpDictionary["CurrentPriceLow"].Get<double>();
stopLimit.CurrentPriceClose=nvpDictionary["CurrentPriceClose"].Get<double>();
stopLimit.PriceTrendIndicatorSlope=nvpDictionary["PriceTrendIndicatorSlope"].Get<double>();
if(nvpDictionary.ContainsKey("StopLimitId"))stopLimit.StopLimitId=nvpDictionary["StopLimitId"].Get<String>();
return stopLimit;
}
}