Fix Backtest runs VS production run. Align dates.
This commit is contained in:
@@ -328,10 +328,19 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
StartDate=StartDate-timeSpan;
|
||||
TradeDate=dateGenerator.GetCurrentMonthEnd(StartDate);
|
||||
}
|
||||
if(null!=PathSessionFileName)sessionParams=RestoreSession();
|
||||
if(null!=PathSessionFileName)
|
||||
{
|
||||
sessionParams=RestoreSession();
|
||||
DateTime currentMonthEndDate = dateGenerator.GetCurrentMonthEnd(TradeDate);
|
||||
if(TradeDate!=currentMonthEndDate)
|
||||
{
|
||||
TradeDate=currentMonthEndDate;
|
||||
AnalysisDate=TradeDate;
|
||||
}
|
||||
}
|
||||
if(null!=sessionParams)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Using session file {0}, Last updated {1}",paramPathSessionFileName,sessionParams.LastUpdated));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Using session file {0}, Last updated {1}, Current Trade Date: {2}",paramPathSessionFileName,sessionParams.LastUpdated.ToShortDateString(),TradeDate.ToShortDateString()));
|
||||
}
|
||||
Configuration.DisplayConfiguration();
|
||||
DisplayBalance();
|
||||
@@ -349,24 +358,34 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
{
|
||||
SellAndBuySlotPositions(slotIndex);
|
||||
}
|
||||
// Check if we are configured to use any of the daily strategies
|
||||
ManageHedgedPositions(TradeDate);
|
||||
DateTime nextBusinessDay = dateGenerator.FindNextBusinessDay(TradeDate);
|
||||
DateTime nextMonthEndDate = dateGenerator.GetNextMonthEnd(TradeDate);
|
||||
|
||||
// if the TradeDate and AnalysisDate are equal then set the trade date to the next business day and exit the cycle
|
||||
if(TradeDate.Equals(AnalysisDate))
|
||||
{
|
||||
TradeDate = nextBusinessDay;
|
||||
break;
|
||||
}
|
||||
|
||||
// This will enter the daily cycle which we need for backtesting
|
||||
if(Configuration.UseStopLimits || Configuration.UseHedging)
|
||||
{
|
||||
DateTime nextMonthEndDate = dateGenerator.GetNextMonthEnd(TradeDate);
|
||||
if(nextMonthEndDate > TradeDate && nextMonthEndDate<=AnalysisDate)
|
||||
if(nextMonthEndDate >= AnalysisDate)
|
||||
{
|
||||
if(null!=PathSessionFileName)SaveSession();
|
||||
UpdateDaily(dateGenerator.FindNextBusinessDay(TradeDate),nextMonthEndDate,paramPathSessionFileName);
|
||||
nextMonthEndDate=dateGenerator.FindNextBusinessDay(AnalysisDate);
|
||||
}
|
||||
TradeDate = nextBusinessDay;
|
||||
SaveSession();
|
||||
UpdateDaily(nextBusinessDay,nextMonthEndDate,AnalysisDate,paramPathSessionFileName); // This will save the session file
|
||||
sessionParams = RestoreSession();
|
||||
}
|
||||
Cycle++;
|
||||
TradeDate = dateGenerator.GetNextMonthEnd(TradeDate);
|
||||
if (TradeDate>AnalysisDate)break;
|
||||
} // WHILE TRUE
|
||||
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,$"RUN COMPLETE FOR ANALYSIS DATE {AnalysisDate.ToShortDateString()}.");
|
||||
if(null!=PathSessionFileName)SaveSession();
|
||||
if(null==sessionParams)sessionParams=RestoreSession();
|
||||
DisplayStatistics(sessionParams);
|
||||
for(int slotIndex=0;slotIndex<HoldingPeriod;slotIndex++)
|
||||
{
|
||||
if(!ActivePositions.ContainsKey(slotIndex)||0==ActivePositions[slotIndex].Count())continue;
|
||||
@@ -378,13 +397,10 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
CashBalance+=slotPositions.MarketValue;
|
||||
ActivePositions[slotIndex].Clear();
|
||||
}
|
||||
DisplayStatistics(sessionParams);
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,"************** A L L P O S I T I O N S *************");
|
||||
AllPositions=new MGSHPositions((from MGSHPosition position in AllPositions orderby position.PurchaseDate ascending select position).ToList());
|
||||
AllPositions.Display();
|
||||
MDTrace.WriteLine(LogLevel.DEBUG, "************** T O P G A I N E R S *************");
|
||||
AllPositions.DisplayTopFive();
|
||||
MDTrace.WriteLine(LogLevel.DEBUG, "************** T O P L O S E R S *************");
|
||||
AllPositions.DisplayBottomFive();
|
||||
DisplayBalance();
|
||||
backTestResult.Success=true;
|
||||
backTestResult.CashBalance=CashBalance;
|
||||
@@ -397,8 +413,9 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
public void BuySlotPositions(int slotIndex)
|
||||
{
|
||||
MGSHPositions positions = null;
|
||||
positions=BuyPositions(TradeDate,AnalysisDate,CashBalance/((double)HoldingPeriod-(double)ActivePositions.Count),SymbolsHeld(TradeDate));
|
||||
positions=BuyPositions(slotIndex, TradeDate, AnalysisDate, CashBalance/((double)HoldingPeriod-(double)ActivePositions.Count), SymbolsHeld(TradeDate));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG, "******************** B U Y ********************");
|
||||
MDTrace.WriteLine(LogLevel.DEBUG, $"SLOT:{slotIndex}");
|
||||
if(CashBalance-positions.Exposure<0.00)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("********** Insufficient funds to make additional purchases.**************"));
|
||||
@@ -429,7 +446,7 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
int positionsToFill = MaxPositions-slotPositions.Count;
|
||||
double cashAllocation = (CashBalance / ((HoldingPeriod * MaxPositions) - ActivePositions.GetCount()))*positionsToFill; // split the cash between the total positions we can own less the number of positions we have
|
||||
MGSHPositions positions = null;
|
||||
positions=BuyPositions(TradeDate,AnalysisDate,cashAllocation,SymbolsHeld(TradeDate), positionsToFill);
|
||||
positions=BuyPositions(slotIndex, TradeDate,AnalysisDate,cashAllocation,SymbolsHeld(TradeDate), positionsToFill);
|
||||
if(CashBalance-positions.Exposure<=0.00)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("********** Insufficient funds to make additional purchases.**************"));
|
||||
@@ -455,36 +472,47 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
// ********************************************************************************************************************************************************
|
||||
/// <summary>
|
||||
/// Entry point for daily runs. Make sure for daily runs that startDate=endDate=Trading Date after market close
|
||||
/// The system does not process endDate. (i.e.) startDate < endDate
|
||||
/// </summary>
|
||||
/// <param name="startDate">{ORIGINAL START DATE}</param>
|
||||
/// <param name="endDate">{TODAY}</param>
|
||||
/// <param name="paramPathSessionFileName">The session file name</param>
|
||||
/// <returns></returns>
|
||||
public MGSHBacktestResult UpdateDaily(DateTime startDate,DateTime endDate,String pathSessionFileName)
|
||||
public MGSHBacktestResult UpdateDaily(DateTime startDate, DateTime endDate, DateTime analysisDate, String pathSessionFileName)
|
||||
{
|
||||
DateGenerator dateGenerator = new DateGenerator();
|
||||
PathSessionFileName = pathSessionFileName;
|
||||
|
||||
RestoreSession();
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("************** U P D A T E D A I L Y {0} < {1}",startDate.ToShortDateString(),endDate.ToShortDateString()));
|
||||
AnalysisDate=analysisDate;
|
||||
|
||||
if(startDate != TradeDate)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,$"Unexpectd StartDate. Start Date:{startDate.ToShortDateString()} Trade Date:{TradeDate.ToShortDateString()}");
|
||||
return new MGSHBacktestResult(false, CashBalance);
|
||||
}
|
||||
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("************** U P D A T E D A I L Y **************"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Trade Date:{TradeDate.ToShortDateString()} Analysis Date:{AnalysisDate.ToShortDateString()}"));
|
||||
|
||||
while(startDate < endDate)
|
||||
{
|
||||
bool changed = false;
|
||||
TradeDate=startDate;
|
||||
if(Configuration.UseStopLimits)
|
||||
{
|
||||
changed = UpdateStopLimitsForActivePositions(startDate);
|
||||
UpdateStopLimitsForActivePositions(startDate);
|
||||
}
|
||||
|
||||
if(Configuration.UseHedging)
|
||||
{
|
||||
changed = ManageHedgedPositions(startDate) ? true : changed;
|
||||
ManageHedgedPositions(startDate);
|
||||
}
|
||||
// if(changed)DisplayBalance();
|
||||
|
||||
DisplayBalance();
|
||||
startDate = dateGenerator.FindNextBusinessDay(startDate);
|
||||
TradeDate = startDate;
|
||||
}
|
||||
if(null!=PathSessionFileName)SaveSession();
|
||||
SaveSession();
|
||||
return new MGSHBacktestResult(true, CashBalance);
|
||||
}
|
||||
// *******************************************************************************************************************************************************
|
||||
@@ -567,7 +595,7 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Initial stop limit for {0} on {1} with PurchsePrice:{2} is {3}, Shares:{4} Risk:{5}%",
|
||||
shortPosition.Symbol,
|
||||
shortPosition.PurchaseDate,
|
||||
shortPosition.PurchaseDate.ToShortDateString(),
|
||||
Utility.FormatCurrency(shortPosition.PurchasePrice,2),
|
||||
Utility.FormatCurrency(shortPosition.InitialStopLimit,2),
|
||||
Utility.FormatNumber(shortPosition.Shares,2),
|
||||
@@ -662,7 +690,7 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
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}%",
|
||||
position.Symbol,
|
||||
position.PurchaseDate,
|
||||
position.PurchaseDate.ToShortDateString(),
|
||||
Utility.FormatCurrency(position.PurchasePrice,2),
|
||||
Utility.FormatCurrency(position.InitialStopLimit,2),
|
||||
Utility.FormatNumber(position.Shares,2),
|
||||
@@ -731,7 +759,6 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
ActivePositions.Remove(position);
|
||||
}
|
||||
}
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("*************************************************************************************************",analysisDate.ToShortDateString()));
|
||||
if(closedPositions.Count>0)return true;
|
||||
return false;
|
||||
}
|
||||
@@ -946,12 +973,12 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
// ************************************************************************************************************************************************************
|
||||
// *********************************************************** B U Y S L O T P O S I T I O N S ************************************************************
|
||||
// ************************************************************************************************************************************************************
|
||||
private MGSHPositions BuyPositions(DateTime tradeDate, DateTime analysisDate, double cash, List<String> symbolsHeld, double maxPositions=double.NaN)
|
||||
private MGSHPositions BuyPositions(int slotIndex, DateTime tradeDate, DateTime analysisDate, double cash, List<String> symbolsHeld, double maxPositions=double.NaN)
|
||||
{
|
||||
MGSHPositions positions = new MGSHPositions();
|
||||
if(double.IsNaN(maxPositions))maxPositions=MaxPositions;
|
||||
if(0==maxPositions)return positions;
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"BUY POSITIONS: TRADE DATE:{TradeDate.ToShortDateString()} CASH:{Utility.FormatCurrency(cash)} POSITIONS TO FILL:{maxPositions}"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"BUY POSITIONS: SLOT:{slotIndex} TRADE DATE:{TradeDate.ToShortDateString()} CASH:{Utility.FormatCurrency(cash)} POSITIONS TO FILL:{maxPositions}"));
|
||||
int positionCount = 0;
|
||||
if (Configuration.BenchmarkMode) return BuyBenchmarkPositions(tradeDate, cash);
|
||||
MGSHMomentumCandidates momentumCandidates = MGSHMomentumGenerator.GenerateMomentum(tradeDate, symbolsHeld, Configuration);
|
||||
@@ -1059,10 +1086,10 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Total Trades:{modelStatistics.TotalTrades}"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Winning Trades:{modelStatistics.WinningTrades}"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Losing Trades:{modelStatistics.LosingTrades}"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Average Winning Trade Percent Gain:{modelStatistics.AverageWinningTradePercentGain}%"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Average Losing Trade Percent Loss:{modelStatistics.AverageLosingTradePercentLoss}%"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Winning Trades Percent:{modelStatistics.WinningTradesPercent}%"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Losing Trades Percent:{modelStatistics.LosingTradesPercent}%"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Average Winning Trade Percent Gain:{Utility.FormatNumber(modelStatistics.AverageWinningTradePercentGain,2)}%"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Average Losing Trade Percent Loss:{Utility.FormatNumber(modelStatistics.AverageLosingTradePercentLoss,2)}%"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Winning Trades Percent:{Utility.FormatNumber(modelStatistics.WinningTradesPercent,2)}%"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Losing Trades Percent:{Utility.FormatNumber(modelStatistics.LosingTradesPercent,2)}%"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Expectancy:{Utility.FormatNumber(modelStatistics.Expectancy,2)}"));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("**************************************************************"));
|
||||
}
|
||||
|
||||
@@ -140,8 +140,7 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
// Fallback candidate settings
|
||||
UseFallbackCandidate=true; // True is the default
|
||||
FallbackCandidate="SHV"; // "SHV" ICE U.S. Treasury Short Bond Index, "AGG" Barclays U.S. Aggregate Bond Index - AGG can have a slighty better return but is more volatile
|
||||
FallbackCandidateBestOf="SHV,AGG,ACWX"; // if set then the fallback candidate is selected as the best 252 day return in this comma seperated list (i.e.) "SHV,ACWX,AGG"
|
||||
// SHV,NEAR,BIL,GSY,AGG,ACWX,GSY,SCHF,IXUS,DBEF,IEFA
|
||||
FallbackCandidateBestOf="SHV,NEAR,BIL,GSY,AGG,ACWX,GSY,SCHF,IXUS,DBEF,IEFA,TLT"; // if set then the fallback candidate is selected as the best 252 day return in this comma seperated list (i.e.) "SHV,ACWX,AGG,SHV,NEAR,BIL,GSY,AGG,ACWX,GSY,SCHF,IXUS,DBEF,IEFA
|
||||
// Set the QualityIndicator type to the ScoreIndicator by default.
|
||||
QualityIndicatorType=MGSHQualityIndicator.ToString(MGSHQualityIndicator.QualityType.ScoreIndicator);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user