Add the MGSHMomentumHelper
This commit is contained in:
271
Program.cs
271
Program.cs
@@ -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();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user