Add the MGSHMomentumHelper

This commit is contained in:
2025-02-06 16:50:01 -05:00
parent 0a5c5a9594
commit 47ccedf1fb
4 changed files with 388 additions and 13 deletions

View File

@@ -25,6 +25,7 @@ using System.Data;
using MarketData.CNNProcessing;
using MySql.Data.MySqlClient;
using MarketData.Generator.MovingAverage;
using MarketData.Generator.MGSHMomentum;
namespace MarketData
{
@@ -190,6 +191,10 @@ namespace MarketData
MDTrace.WriteLine(LogLevel.DEBUG," MGCLOSEPOSITION /SESSIONFILE: /SYMBOL: /PURCHASEDATE: /SELLPRICE: /SELLDATE: sells the specified position in the session file with either the supplied sell date and sell price.");
MDTrace.WriteLine(LogLevel.DEBUG," MGUPDATEPRICE /SYMBOL: /TRADEDATE: /PRICE: /SESSIONFILE:");
MDTrace.WriteLine(LogLevel.DEBUG," RUNBACKTEST /STARTDATE: /MAXPOSITIONS: /INITIALCASH: /HOLDINGPERIOD: /{ENDDATE}: /SESSIONFILE:");
MDTrace.WriteLine(LogLevel.DEBUG,"********** M G S H M O M E N T U M *********");
MDTrace.WriteLine(LogLevel.DEBUG," MGSHSESSION /SESSIONFILE:");
MDTrace.WriteLine(LogLevel.DEBUG," MGSHRUNBACKTEST /USEHEDGING: /HEDGEINITIALCASH: /USESTOPLIMITS: /KEEPSLOTPOSITIONS: /STARTDATE: /MAXPOSITIONS: /INITIALCASH: /HOLDINGPERIOD: /{ENDDATE}: /SESSIONFILE: ");
MDTrace.WriteLine(LogLevel.DEBUG," MGSHRUNDAILY /SESSIONFILE: /TRADEDATE:");
MDTrace.WriteLine(LogLevel.DEBUG, "*********** C L E N O W M O M E N T U M (C M M O M E N T U M )************");
MDTrace.WriteLine(LogLevel.DEBUG, " RUNCMBACKTEST /STARTDATE: /MAXPOSITIONS: /INITIALCASH: /HOLDINGPERIOD: /{USEBINBASEDPOSITIONSIZING}: /{USEBINBASEDPOSITIONSIZINGNUMBINS}: /{TARGETBETA}: /{ENDDATE}: /SESSIONFILE: /{USECNN}: /{USECNNHOST}: /{USECNNDAYCOUNT}:");
MDTrace.WriteLine(LogLevel.DEBUG, " CMSESSION /SESSIONFILE:");
@@ -758,6 +763,212 @@ namespace MarketData
outStream.Close();
outStream.Dispose();
}
// *****************************************************************************************************************************************************
public static void HedgeTest()
{
String hedgeShortSymbol="SH";
double initialRiskPercentDecimal=.12;
double cash=10000;
double cashToInvest=3000;
double totalGainLoss=0.00;
bool hedgeOn=false;
int totalWinners=0;
int totalLosers=0;
int hedgeStopLimitScalingVolatilityDays=14;
int hedgeMinDaysBetweenStopAdjustments=1;
MGSHPosition position = default;
MDTrace.WriteLine(LogLevel.DEBUG,"START");
DateTime analysisStartDate=DateTime.Parse("01/31/2018");
// DateTime analysisStartDate=DateTime.Parse("01/01/2011");
// DateTime analysisStartDate=DateTime.Parse("06/06/2018");
DateTime analysisEndDate=DateTime.Parse("12/31/2024");
Prices prices = PricingDA.GetPrices(hedgeShortSymbol);
prices=new Prices(prices.Where(x => x.Date > analysisStartDate).ToList());
BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices);
BollingerBandElementsByDate bollingerBandElementsByDate = bollingerBands.GetBollingerBandElementsByDate();
PricesByDate pricesByDate = prices.GetPricesByDate();
List<DateTime> dates = new List<DateTime>(pricesByDate.Keys);
MGSHPositions AllPositions = new MGSHPositions();
MarketData.Generator.Model.StopLimits StopLimits = new MarketData.Generator.Model.StopLimits();
HedgeManager hedgeManager = new HedgeManager(){Verbose=true};
for(int dateIndex=dates.Count-1;dateIndex>=0;dateIndex--)
{
DateTime analysisDate = dates[dateIndex];
if(analysisDate > analysisEndDate)break;
if(!bollingerBandElementsByDate.ContainsKey(analysisDate))continue;
BollingerBandElement bollingerBandElement = bollingerBandElementsByDate[analysisDate];
if(!hedgeOn && hedgeManager.IsOpenHedgeIndicator(analysisDate))
{
hedgeOn=true;
position = new MGSHPosition();
position.Symbol=hedgeShortSymbol;
position.PurchasePrice = bollingerBandElement.Close;
position.PurchaseDate = analysisDate;
position.SellDate=Utility.Epoch;
position.InitialStopLimit=position.PurchasePrice/(1.00+initialRiskPercentDecimal);
position.TrailingStopLimit=position.InitialStopLimit;
position.LastStopAdjustment=Utility.Epoch;
position.R=initialRiskPercentDecimal;
double cashAllocation = Math.Min(cash, cashToInvest);
position.Shares=(int)(cashAllocation/bollingerBandElement.Close);
cash-=position.Shares*bollingerBandElement.Close;
// This is for the simulation so that I can see the initial position as a stop limit in the UI
MarketData.Generator.Model.StopLimit stopLimit = new MarketData.Generator.Model.StopLimit()
{
Symbol=hedgeShortSymbol,
AnalysisDate=analysisDate,
PreviousStop=position.PurchasePrice,
NewStop=position.TrailingStopLimit,
CurrentPriceLow=0.00,
CurrentPriceClose=0.00,
PriceTrendIndicatorSlope=0.00
};
StopLimits.Add(stopLimit);
MDTrace.WriteLine(LogLevel.DEBUG,$"Hedge BUY {analysisDate.ToShortDateString()} {Utility.FormatNumber(position.Shares,2)} shares @ {Utility.FormatCurrency(bollingerBandElement.Close)} Exposure:{Utility.FormatCurrency(position.Shares*bollingerBandElement.Close)}");
}
else if(hedgeOn) // This will check for stop loss violation and close the position
{
Price price = GBPriceCache.GetInstance().GetPrice(hedgeShortSymbol, analysisDate);
if(null == price)
{
MDTrace.WriteLine(LogLevel.DEBUG,$"No price for {hedgeShortSymbol} on {analysisDate.ToShortDateString()}");
continue;
}
if(price.Close<position.TrailingStopLimit)
{
hedgeOn=false;
position.SellDate= analysisDate;
position.CurrentPrice=position.TrailingStopLimit; //bollingerBandElement.Close;
position.Comment=$"Closed to to stop loss {position.Shares} shares @ {Utility.FormatCurrency(position.CurrentPrice)}";
if(position.GainLoss>0)totalWinners++;
else totalLosers++;
totalGainLoss+=position.GainLoss;
cash+=position.MarketValue;
MDTrace.WriteLine(LogLevel.DEBUG,$"Hedge SELL {analysisDate.ToShortDateString()} {Utility.FormatNumber(position.Shares,2)} shares @ {Utility.FormatCurrency(position.CurrentPrice)} Gain/Loss:{Utility.FormatCurrency(position.GainLoss)} Gain/Loss(%):{Utility.FormatPercent(position.GainLossPcnt,2)}");
MDTrace.WriteLine(LogLevel.DEBUG,"**************************************************");
AllPositions.Add(position);
MarketData.Generator.Model.StopLimit stopLimit = new MarketData.Generator.Model.StopLimit()
{
Symbol=hedgeShortSymbol,
AnalysisDate=analysisDate,
PreviousStop=position.PurchasePrice,
NewStop=position.CurrentPrice,
CurrentPriceLow=0.00,
CurrentPriceClose=0.00,
PriceTrendIndicatorSlope=0.00
};
StopLimits.Add(stopLimit);
}
else if(hedgeManager.IsLowerBandBreakIndicator(analysisDate, position))
{
MarketData.Generator.Model.StopLimit stopLimit = hedgeManager.EvaluateStopPriceHedge(analysisDate, position, hedgeStopLimitScalingVolatilityDays, hedgeMinDaysBetweenStopAdjustments);
if(null != stopLimit)StopLimits.Add(stopLimit);
}
}
}
MGSHSessionParams sessionParams = new MGSHSessionParams();
sessionParams.LastUpdated=DateTime.Now;
sessionParams.TradeDate=DateTime.Now;
sessionParams.StartDate=DateTime.Now;
sessionParams.AnalysisDate=DateTime.Now;
sessionParams.Configuration=new MGSHConfiguration();
sessionParams.ActivePositions=new MGSHActivePositions();
sessionParams.AllPositions=AllPositions;
sessionParams.CashBalance=cash;
sessionParams.NonTradeableCash=0.00;
sessionParams.StopLimits=StopLimits;
sessionParams.HedgePositions= new MGSHPositions();
sessionParams.Cycle = 0;
MGSHSessionManager mgSession = new MGSHSessionManager();
mgSession.SaveSession(sessionParams,"MGSH_PROTO_20250128_2.TXT");
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Total Gain/Loss:{Utility.FormatCurrency(totalGainLoss)}"));
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Cash:{Utility.FormatCurrency(cash)}"));
MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Open:{hedgeOn}"));
return;
}
// ****************************************************************************************************************************************************************
public static void CrossoverExample()
{
// Crossover examples.
// Example 1
//List<String> symbols = PricingDA.GetSymbols();
//List<MovingAverageCrossover> crossovers = new MovingAverageCrossovers();
//DateTime analysisDate = DateTime.Parse("12/31/2024");
//for (int index = 0; index < symbols.Count; index++)
//{
// if (0 == (index % 500)) Console.WriteLine($"Working on {index}");
// String symbol = symbols[index];
// Prices prices = GBPriceCache.GetInstance().GetPrices(symbol, analysisDate, 252);
// MovingAverageCrossovers movingAverageCrossovers = ExponentialMovingAverageCrossover.GetMovingAverageCrossovers(prices, .05); // 5%
// movingAverageCrossovers = new MovingAverageCrossovers(movingAverageCrossovers.Where(x => x.EventDate.Equals(analysisDate)).ToList());
// crossovers.AddRange(movingAverageCrossovers);
//}
//foreach (MovingAverageCrossover movingAverageCrossover in crossovers)
//{
// Console.WriteLine(movingAverageCrossover.ToString());
//}
// Example 2
//String symbol = "SH";
//DateTime analysisDate = DateTime.Parse("12/31/2024");
//Prices prices = GBPriceCache.GetInstance().GetPrices(symbol, analysisDate, 252);
//MovingAverageCrossovers movingAverageCrossovers = ExponentialMovingAverageCrossover.GetMovingAverageCrossovers(prices, .025);
//foreach (MovingAverageCrossover movingAverageCrossover in movingAverageCrossovers)
//{
// Console.WriteLine(movingAverageCrossover.ToString());
//}
//DMAPrices fastDMAPrices = MovingAverageGenerator.GenerateExponentialMovingAverage(prices, 9);
//DMAPrices slowDMAPrices=MovingAverageGenerator.GenerateExponentialMovingAverage(prices, 41);
//DMAPricesByDate fastDMAPricesByDate=fastDMAPrices.GetDMAPricesByDate();
//DMAPricesByDate slowDMAPricesByDate=slowDMAPrices.GetDMAPricesByDate();
//List<DateTime> availableDates = new List<DateTime>(slowDMAPricesByDate.Keys);
//availableDates.Sort((a, b) => DateTime.Compare(a,b)); // earliest date should be in the lowest index, most recent date should be in the highest 2024[0], 2025[1], 2026[2] for example
//StreamWriter streamWriter = new StreamWriter(new FileStream("MovingAverage.csv",FileMode.Create));
//streamWriter.WriteLine("Date,Fast,Slow");
//foreach(DateTime date in availableDates)
//{
// DMAPrice fastDMAPrice = fastDMAPricesByDate[date];
// DMAPrice slowDMAPrice = slowDMAPricesByDate[date];
// streamWriter.WriteLine($"{date.ToShortDateString()},{fastDMAPrice.AVGPrice},{slowDMAPrice.AVGPrice}");
//}
//streamWriter.Flush();
//streamWriter.Close();
//streamWriter.Dispose();
// Example 3
//DateTime beginDate = DateTime.Parse("12/31/2018");
//DateTime stopDate = DateTime.Parse("12/31/2024");
//String symbol="^VIX";
//DateGenerator dateGenerator = new DateGenerator();
//while(beginDate<=stopDate)
//{
// Prices prices = GBPriceCache.GetInstance().GetPrices(symbol, beginDate, 252);
// MovingAverageCrossovers movingAverageCrossovers = ExponentialMovingAverageCrossover.GetMovingAverageCrossovers(prices, .025, 20, 50); // 1.75%
// if(null != movingAverageCrossovers && movingAverageCrossovers.Count>0 && movingAverageCrossovers[0].EventDate.Equals(beginDate))
// {
// MDTrace.WriteLine(LogLevel.DEBUG,$"Found a crossover {movingAverageCrossovers[0].ToString()}");
// }
// beginDate = dateGenerator.FindNextBusinessDay(beginDate);
//}
}
@@ -771,19 +982,40 @@ namespace MarketData
Trace.Listeners.Add(new TextWriterTraceListener(strLogFile));
DateTime currentDate=DateTime.Now;
Prices prices = new Prices();
prices.Add(new Price(){Date=DateTime.Parse("1/28/2025"),Open=10,High=10,Low=10,Close=10});
prices.Add(new Price(){Date=DateTime.Parse("1/29/2025"),Open=15,High=15,Low=15,Close=15});
prices.Add(new Price(){Date=DateTime.Parse("1/30/2025"),Open=5,High=5,Low=5,Close=5});
prices.Add(new Price(){Date=DateTime.Parse("1/31/2025"),Open=20,High=20,Low=20,Close=20});
prices.Add(new Price(){Date=DateTime.Parse("2/1/2025"),Open=10,High=10,Low=10,Close=10});
prices.Add(new Price(){Date=DateTime.Parse("2/2/2025"),Open=25,High=25,Low=25,Close=25});
prices.Add(new Price(){Date=DateTime.Parse("2/3/2025"),Open=30,High=30,Low=30,Close=30});
DMAPrices dmaPrices = MovingAverageGenerator.GenerateMovingAverage(prices, 2);
DMAPrices emaPrices = MovingAverageGenerator.GenerateExponentialMovingAverage(prices, 2);
// CompanyProfile c1 = MarketDataHelper.GetCompanyProfile("AAME");
CompanyProfiles companyProfiles = CompanyProfileDA.GetCompanyProfiles();
List<String> symbols = companyProfiles.Select(x => x.Symbol).ToList();
foreach(String symbol in symbols)
{
CompanyProfile companyProfile = MarketDataHelper.GetCompanyProfile(symbol);
if (null != companyProfile) {
MDTrace.WriteLine(LogLevel.DEBUG, $"Symbol:{symbol} Sector:{companyProfile.Sector} Industry:{companyProfile.Industry} Description:{companyProfile.Description}");
MDTrace.WriteLine(LogLevel.DEBUG, "");
}
Thread.Sleep(2000);
}
// CompanyProfile companyProfile = MarketDataHelper.GetCompanyProfile("MOD");
//PortfolioTrades portfolioTrades = PortfolioDA.GetOpenTrades();
//List<String> symbols = portfolioTrades.Select(x => x.Symbol).Distinct().ToList();
//for (int rindex=0; rindex<symbols.Count; rindex++)
//{
// String symbol = symbols[rindex];
// CompanyProfile companyProfile = MarketDataHelper.GetCompanyProfile(symbol);
// if (null != companyProfile)
// {
// MDTrace.WriteLine(LogLevel.DEBUG, $"Symbol:{symbol} Sector:{companyProfile.Sector} Industry:{companyProfile.Industry} Description:{companyProfile.Description}");
// MDTrace.WriteLine(LogLevel.DEBUG,"");
// }
// Thread.Sleep(1000);
//}
DateTime maxHolidayDate =HolidayDA.GetMaxHolidayDate();
if(currentDate>maxHolidayDate)
@@ -1461,7 +1693,22 @@ namespace MarketData
Program.HandleCMTSession(args);
}
// *************************************************************************************************************************************************************************************************************************
// ************************************************************************************************** M G M O M E N T U M *************************************************************************************************
// ************************************************************************************************** M G S H M O M E N T U M *************************************************************************************************
// *************************************************************************************************************************************************************************************************************************
else if(arg.Equals("MGSHSESSION"))
{
MGSHMomentumHelper.HandleMGSHSession(args);
}
else if(arg.Equals("MGSHRUNBACKTEST"))
{
MGSHMomentumHelper.HandleMGSHRunBacktest(args);
}
else if(arg.Equals("MGSHRUNDAILY"))
{
MGSHMomentumHelper.HandleMGSHRunDaily(args);
}
// *************************************************************************************************************************************************************************************************************************
// ************************************************************************************************** M G M O M E N T U M *************************************************************************************************
// *************************************************************************************************************************************************************************************************************************
else if (arg.Equals("RUNMOMENTUM"))
{
@@ -2011,7 +2258,7 @@ namespace MarketData
ThreadPool.QueueUserWorkItem(delegate
{
UpdateAnalystPriceTarget(); // finance.yahoo.com
UpdateAnalystPriceTarget(); // MarketBeat
GetETFHoldings(); // finance.yahoo.com
resetEvents[STAGE_9].Set();
});