Add CMTRend
This commit is contained in:
18
MarketData/MarketDataLib/Generator/CMTrend/CMTActivePositions.cs
Executable file
18
MarketData/MarketDataLib/Generator/CMTrend/CMTActivePositions.cs
Executable file
@@ -0,0 +1,18 @@
|
||||
using MarketData.MarketDataModel;
|
||||
using MarketData.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MarketData.Generator.CMTrend
|
||||
{
|
||||
public class ActivePositions:Positions
|
||||
{
|
||||
public ActivePositions()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
129
MarketData/MarketDataLib/Generator/CMTrend/CMTCandidate.cs
Executable file
129
MarketData/MarketDataLib/Generator/CMTrend/CMTCandidate.cs
Executable file
@@ -0,0 +1,129 @@
|
||||
using MarketData.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MarketData.Generator.CMTrend
|
||||
{
|
||||
public class CMTCandidates : List<CMTCandidate>
|
||||
{
|
||||
public CMTCandidates()
|
||||
{
|
||||
}
|
||||
public CMTCandidates(List<CMTCandidate> cmtCandidates)
|
||||
{
|
||||
foreach(CMTCandidate cmtCandidate in cmtCandidates) Add(cmtCandidate);
|
||||
}
|
||||
public NVPCollections ToNVPCollections()
|
||||
{
|
||||
NVPCollections nvpCollections=new NVPCollections();
|
||||
foreach(CMTCandidate candidate in this)
|
||||
{
|
||||
nvpCollections.Add(candidate.ToNVPCollection());
|
||||
}
|
||||
return nvpCollections;
|
||||
}
|
||||
public static CMTCandidates FromNVPCollections(NVPCollections nvpCollections)
|
||||
{
|
||||
CMTCandidates candidates=new CMTCandidates();
|
||||
foreach(NVPCollection nvpCollection in nvpCollections)
|
||||
{
|
||||
candidates.Add(CMTCandidate.FromNVPCollection(nvpCollection));
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
public void AddFromNVPCollection(NVPCollection nvpCollection)
|
||||
{
|
||||
Add(CMTCandidate.FromNVPCollection(nvpCollection));
|
||||
}
|
||||
public new void Sort()
|
||||
{
|
||||
List<CMTCandidate> candidates=new CMTCandidates((from CMTCandidate mmCandidate in this select mmCandidate).OrderByDescending(x => x.Score).ToList());
|
||||
this.Clear();
|
||||
this.AddRange(candidates);
|
||||
}
|
||||
}
|
||||
public class CMTCandidate
|
||||
{
|
||||
public CMTCandidate()
|
||||
{
|
||||
Violation=false;
|
||||
}
|
||||
public String Symbol { get; set; }
|
||||
public DateTime AnalysisDate { get; set; }
|
||||
public double EPSSlope { get; set; }
|
||||
public double ProfitMarginSlope { get; set; }
|
||||
public double PriceSlope { get; set; }
|
||||
public double Volatility { get; set; }
|
||||
public long Volume { get; set; }
|
||||
public double RSquared{get;set;}
|
||||
public double Beta{get;set;}
|
||||
public int BetaMonths{get;set;}
|
||||
public bool Violation { get; set; }
|
||||
public double Slope { get; set; }
|
||||
public double Score { get; set; }
|
||||
public double AnnualizedReturn { get; set; }
|
||||
public double SharpeRatio { get; set; }
|
||||
public String Reason { get; set; }
|
||||
|
||||
public virtual NVPCollection ToNVPCollection()
|
||||
{
|
||||
NVPCollection nvpCollection=new NVPCollection();
|
||||
nvpCollection.Add(new NVP("Symbol",Symbol.ToString()));
|
||||
nvpCollection.Add(new NVP("AnalysisDate",AnalysisDate.ToString()));
|
||||
if(!double.IsNaN(EPSSlope)) nvpCollection.Add(new NVP("EPSSlope",EPSSlope.ToString()));
|
||||
if(!double.IsNaN(ProfitMarginSlope)) nvpCollection.Add(new NVP("ProfitMarginSlope",ProfitMarginSlope.ToString()));
|
||||
if(!double.IsNaN(PriceSlope)) nvpCollection.Add(new NVP("PriceSlope",PriceSlope.ToString()));
|
||||
if(!double.IsNaN(Volatility)) nvpCollection.Add(new NVP("Volatility",Volatility.ToString()));
|
||||
nvpCollection.Add(new NVP("Volume",Volume.ToString()));
|
||||
nvpCollection.Add(new NVP("Violation",Violation.ToString()));
|
||||
if(!double.IsNaN(Slope)) nvpCollection.Add(new NVP("Slope",Slope.ToString()));
|
||||
if(!double.IsNaN(Score)) nvpCollection.Add(new NVP("Score",Score.ToString()));
|
||||
if(!double.IsNaN(AnnualizedReturn)) nvpCollection.Add(new NVP("AnnualizedReturn",AnnualizedReturn.ToString()));
|
||||
if(!double.IsNaN(SharpeRatio)) nvpCollection.Add(new NVP("SharpeRatio",SharpeRatio.ToString()));
|
||||
if(!double.IsNaN(RSquared)) nvpCollection.Add(new NVP("RSquared",RSquared.ToString()));
|
||||
nvpCollection.Add(new NVP("BetaMonths",BetaMonths.ToString()));
|
||||
nvpCollection.Add(new NVP("Beta",Beta.ToString()));
|
||||
if(null!=Reason) nvpCollection.Add(new NVP("Reason",Reason.ToString()));
|
||||
return nvpCollection;
|
||||
}
|
||||
public static CMTCandidate FromNVPCollection(NVPCollection nvpCollection)
|
||||
{
|
||||
CMTCandidate candidate=new CMTCandidate();
|
||||
NVPDictionary nvpDictionary=nvpCollection.ToDictionary();
|
||||
if(nvpDictionary.ContainsKey("Symbol")) candidate.Symbol=nvpDictionary["Symbol"].Get<String>();
|
||||
if(nvpDictionary.ContainsKey("AnalysisDate")) candidate.AnalysisDate=nvpDictionary["AnalysisDate"].Get<DateTime>();
|
||||
if(nvpDictionary.ContainsKey("EPSSlope")) candidate.EPSSlope=nvpDictionary["EPSSlope"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("ProfitMarginSlope")) candidate.ProfitMarginSlope=nvpDictionary["ProfitMarginSlope"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("PriceSlope")) candidate.PriceSlope=nvpDictionary["PriceSlope"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("Volatility")) candidate.Volatility=nvpDictionary["Volatility"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("Volume")) candidate.Volume=nvpDictionary["Volume"].Get<long>();
|
||||
if(nvpDictionary.ContainsKey("Violation")) candidate.Violation=nvpDictionary["Violation"].Get<bool>();
|
||||
if(nvpDictionary.ContainsKey("Slope")) candidate.Slope=nvpDictionary["Slope"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("Score")) candidate.Score=nvpDictionary["Score"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("AnnualizedReturn")) candidate.AnnualizedReturn=nvpDictionary["AnnualizedReturn"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("SharpeRatio")) candidate.SharpeRatio=nvpDictionary["SharpeRatio"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("RSquared")) candidate.RSquared=nvpDictionary["RSquared"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("BetaMonths")) candidate.BetaMonths=nvpDictionary["BetaMonths"].Get<int>();
|
||||
if(nvpDictionary.ContainsKey("Beta")) candidate.Beta=nvpDictionary["Beta"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("Reason")) candidate.Reason=nvpDictionary["Reason"].Get<String>();
|
||||
return candidate;
|
||||
}
|
||||
public static String Header()
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
sb.Append("Symbol,AnalysisDate,PriceSlope,ProfitMarginSlope,EPSSlope,Volatility,Volume,Slope,Score,AnnualizedReturn,SharpeRatio,RSquared,Beta,BetaMonths");
|
||||
return sb.ToString();
|
||||
}
|
||||
public override String ToString()
|
||||
{
|
||||
StringBuilder sb=new StringBuilder();
|
||||
sb.Append(Symbol).Append(",").Append(AnalysisDate.ToShortDateString()).Append(",").Append(PriceSlope).Append(",").Append(ProfitMarginSlope).Append(",").Append(EPSSlope).Append(",").Append(Volatility).Append(",").Append(Volume).Append(",").Append(Slope).Append(",").Append(Score).Append(",").Append(AnnualizedReturn).Append(",").Append(SharpeRatio).Append(",");
|
||||
sb.Append(RSquared).Append(",").Append(Beta).Append(",").Append(BetaMonths);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
438
MarketData/MarketDataLib/Generator/CMTrend/CMTCandidateGenerator.cs
Executable file
438
MarketData/MarketDataLib/Generator/CMTrend/CMTCandidateGenerator.cs
Executable file
@@ -0,0 +1,438 @@
|
||||
using MarketData.Cache;
|
||||
using MarketData.DataAccess;
|
||||
using MarketData.Generator.MovingAverage;
|
||||
using MarketData.MarketDataModel;
|
||||
using MarketData.Numerical;
|
||||
using MarketData.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MarketData.Generator.CMTrend
|
||||
{
|
||||
public class CMTCandidateGenerator
|
||||
{
|
||||
private static readonly int PRICING_DAYS=252;
|
||||
public CMTCandidateGenerator()
|
||||
{
|
||||
}
|
||||
// *******************************************************************************************************************************************************************************
|
||||
// ******************************************************************* G E N E R A T E C A N D I D A T E - M A R C M I N E R V I N I ****************************************
|
||||
// *******************************************************************************************************************************************************************************
|
||||
public static CMTCandidate GenerateCandidate(String symbol,DateTime tradeDate,CMTParams cmtParams,List<String> symbolsHeld=null)
|
||||
{
|
||||
CMTCandidate cmtCandidate=new CMTCandidate();
|
||||
|
||||
try
|
||||
{
|
||||
// Check MarketCap
|
||||
Fundamental fundamental=FundamentalDA.GetFundamentalMaxDate(symbol,tradeDate);
|
||||
if(null==fundamental)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("No fundamental for {0}.",symbol);
|
||||
return cmtCandidate;
|
||||
}
|
||||
if(!(fundamental.MarketCap>=cmtParams.MarketCapLowerLimit))
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("MarketCapLowerLimit constraint violation for {0}.",symbol);
|
||||
return cmtCandidate;
|
||||
}
|
||||
// Check if the symbol is held in any open positions
|
||||
if(null!=symbolsHeld&&symbolsHeld.Any(x => x.Equals(symbol, StringComparison.CurrentCultureIgnoreCase)))
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("{0} is already held.",symbol);
|
||||
return cmtCandidate;
|
||||
}
|
||||
// No trade symbols
|
||||
if(null!=cmtParams.NoTradeSymbolsList&&cmtParams.NoTradeSymbolsList.Any(x => x.Equals(symbol, StringComparison.CurrentCultureIgnoreCase)))
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("{0} is in the No-Trade list.",symbol);
|
||||
return cmtCandidate;
|
||||
}
|
||||
// Equity check
|
||||
CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol);
|
||||
if(null==companyProfile)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("No company profile found for {0}.",symbol);
|
||||
return cmtCandidate;
|
||||
}
|
||||
if(!companyProfile.IsEquity)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("{0} is not an equity. {1}.",symbol,companyProfile.SecurityType);
|
||||
return cmtCandidate;
|
||||
}
|
||||
// Sector Check
|
||||
if(cmtParams.UseTradeOnlySectors)
|
||||
{
|
||||
List<String> validSectors=Utility.ToList(cmtParams.UseTradeOnlySectorsSectors);
|
||||
if(null==companyProfile.Sector)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("Invalid sector for {0}. Found {1} expected one of {2}.",symbol,null==companyProfile.Sector?"(Null)":companyProfile.Sector,Utility.ListToString(validSectors.ToList<String>()));
|
||||
return cmtCandidate;
|
||||
}
|
||||
if(!validSectors.Any(x => x.Equals(companyProfile.Sector)))
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("Invalid sector for {0}. Found {1} expected one of {2}.",symbol,null==companyProfile.Sector?"(Null)":companyProfile.Sector,Utility.ListToString(validSectors.ToList<String>()));
|
||||
return cmtCandidate;
|
||||
}
|
||||
}
|
||||
// setup for trend analysis
|
||||
Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,tradeDate,PRICING_DAYS);
|
||||
if(null==prices||prices.Count<PRICING_DAYS)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason=String.Format("Insufficient pricing history, {0} days required.",PRICING_DAYS);
|
||||
return cmtCandidate;
|
||||
}
|
||||
// Current Price Check
|
||||
Price currentPrice=prices[0];
|
||||
if(currentPrice.Date!=tradeDate)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason="pricing date!=trade date.";
|
||||
return cmtCandidate;
|
||||
}
|
||||
// Liquidity check - if any day has volume < MinVolume then we reject it
|
||||
int belowThreshholdVolumeCount=(from Price xPrice in prices where xPrice.Volume<cmtParams.MinVolume select xPrice).Count();
|
||||
if(cmtParams.LiquidityCheck&&belowThreshholdVolumeCount>0)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason=String.Format("Insufficient liquidity.");
|
||||
return cmtCandidate;
|
||||
}
|
||||
// Setup for the moving averages checks
|
||||
Prices prices50=new Prices(prices.Take(50).ToList());
|
||||
Prices prices15=new Prices(prices.Take(15).ToList());
|
||||
Prices prices150=new Prices(prices.Take(150).ToList());
|
||||
Prices prices200=new Prices(prices.Take(200).ToList());
|
||||
|
||||
DMAPrices dma50Prices=MovingAverageGenerator.GenerateMovingAverage(prices50,prices50.Count);
|
||||
DMAPrices dma150Prices=MovingAverageGenerator.GenerateMovingAverage(prices150,prices150.Count);
|
||||
DMAPrices dma200Prices=MovingAverageGenerator.GenerateMovingAverage(prices200,prices200.Count);
|
||||
|
||||
double dma50Close=dma50Prices[0].AVGPrice;
|
||||
double dma150Close=dma150Prices[0].AVGPrice;
|
||||
double dma200Close=dma200Prices[0].AVGPrice;
|
||||
double volatility=prices15.Volatility();
|
||||
|
||||
// Trend #1 check. Check that current price is greater than 150 day moving average and current price is greater than 200 day moving average
|
||||
if(currentPrice.Close<dma150Close)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason="Trend#1 Violation : currentPrice.Close<=dma150Close.";
|
||||
return cmtCandidate;
|
||||
}
|
||||
if(currentPrice.Close<dma200Close)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason="Trend#1 Violation : currentPrice.Close<=dma200Close.";
|
||||
return cmtCandidate;
|
||||
}
|
||||
// Trend #2 check. Check that 150 day moving average is greater than the 200 day moving average
|
||||
if(dma150Close<dma200Close)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason="Trend#2 Violation : dma150Close<=dma200Close.";
|
||||
return cmtCandidate;
|
||||
}
|
||||
|
||||
// Trend #4 check : The 50 day moving average must be greater than the 150 day moving average
|
||||
if(dma50Close<=dma150Close)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason="Trend#4 Violation : (dma50Close<=dma150Close)&&(dma50Close<=dma200Close).";
|
||||
return cmtCandidate;
|
||||
}
|
||||
|
||||
// Trend #4a check : The 50 day moving average must be greater than the 200 day moving average
|
||||
if(dma50Close<=dma200Close)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason="Trend#4a Violation : dma50Close<=dma200Close.";
|
||||
return cmtCandidate;
|
||||
}
|
||||
|
||||
// Trend #5 check : The current price must be greater than the 50 day moving average
|
||||
if(currentPrice.Close<=dma50Close)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason="Trend#5 Violation : currentPrice.Close<=dma50Close.";
|
||||
return cmtCandidate;
|
||||
}
|
||||
|
||||
// Trend #6 check. Evaluate the MinPercentReturnOver52WeekLow
|
||||
double weekLow52=prices.Min(x => x.Close);
|
||||
double latestClose=currentPrice.Close;
|
||||
double percentReturnOver52WeekLow=((latestClose-weekLow52)/weekLow52)*100.00;
|
||||
if(percentReturnOver52WeekLow<cmtParams.MinPercentReturnOver52WeekLow)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason=String.Format("Trend#6 Violation : percentReturnOver52WeekLow<={0}.",cmtParams.MinPercentReturnOver52WeekLow);
|
||||
return cmtCandidate;
|
||||
}
|
||||
|
||||
// Trend #7 check. Evaluate the MinPercentReturnProximityTo52WeekHigh
|
||||
double weekHigh52=prices.Max(x => x.Close);
|
||||
double percentReturnProximityTo52WeekHigh=double.NaN;
|
||||
if(latestClose<weekHigh52) percentReturnProximityTo52WeekHigh=((weekHigh52-latestClose)/latestClose)*100.00;
|
||||
else percentReturnProximityTo52WeekHigh=((latestClose-weekHigh52)/weekHigh52)*100.00;
|
||||
if(latestClose<weekHigh52&&percentReturnProximityTo52WeekHigh>cmtParams.MinPercentReturnProximityTo52WeekHigh)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason=String.Format("Trend#7 Violation :PercentReturnProximityTo52WeekHigh<{0}.",cmtParams.MinPercentReturnProximityTo52WeekHigh);
|
||||
return cmtCandidate;
|
||||
}
|
||||
|
||||
// Trend #8 check. Evaluate the RSI
|
||||
// generate a 14 day standard RSI with 30 days of pricing data
|
||||
RSICollection rsiCollection=RSIGenerator.GenerateRSI(symbol,currentPrice.Date,30);
|
||||
if(null==rsiCollection||0==rsiCollection.Count||rsiCollection[rsiCollection.Count-1].RSI<cmtParams.MinRSI)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason=String.Format("Trend#8 Violation : rsiCollection[rsiCollection.Count-1].RSI<{0}.",cmtParams.MinRSI);
|
||||
return cmtCandidate;
|
||||
}
|
||||
|
||||
// Trend #3 check : check required days of increasing 200 day moving averages
|
||||
DateGenerator dateGenerator=new DateGenerator();
|
||||
List<double> dma200List=new List<double>();
|
||||
DateTime historicalDate=dateGenerator.GenerateHistoricalDate(currentPrice.Date,cmtParams.DMA200Horizon+10);
|
||||
List<DateTime> historicalDates=PricingDA.GetPricingDatesBetween(historicalDate,currentPrice.Date);
|
||||
historicalDates=historicalDates.Take(cmtParams.DMA200Horizon).ToList();
|
||||
if(historicalDates.Count<cmtParams.DMA200Horizon)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason=String.Format("Trend#3a Violation : Insufficient data to calulate DMA(200). Requires {0} days of DMA(200)",cmtParams.DMA200Horizon);
|
||||
return cmtCandidate;
|
||||
}
|
||||
foreach(DateTime date in historicalDates)
|
||||
{
|
||||
Prices historicalPrices=GBPriceCache.GetInstance().GetPrices(symbol,date,MovingAverageGenerator.DayCount200);
|
||||
if(null==historicalPrices||historicalPrices.Count<MovingAverageGenerator.DayCount200) continue;
|
||||
dma200Prices=MovingAverageGenerator.GenerateMovingAverage(historicalPrices,MovingAverageGenerator.DayCount200);
|
||||
dma200List.Insert(0,dma200Prices[0].AVGPrice); // The lowest index should wind up with most historical price. This way we calculate the proper slope
|
||||
}
|
||||
double[] averages=dma200List.ToArray();
|
||||
double slope=Numerics.Slope(ref averages);
|
||||
if(slope<=0)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason=String.Format("Trend#3 Violation : Slope of {0} days of 200DMA >0.",cmtParams.DMA200Horizon);
|
||||
return cmtCandidate;
|
||||
}
|
||||
// Trend check ensure that prices are trending higher
|
||||
if(cmtParams.UsePriceSlopeIndicator)
|
||||
{
|
||||
int dayCount=cmtParams.UsePriceSlopeIndicatorDays;
|
||||
Prices pricesTrend=GBPriceCache.GetInstance().GetPrices(symbol,tradeDate,dayCount);
|
||||
double[] pricesLow=Numerics.ToDouble(pricesTrend.GetPricesLow());
|
||||
LeastSquaresResult lsr=LeastSquaresHelper.CalculateLeastSquares(pricesLow);
|
||||
if(lsr.Slope<=0.00)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("Price trend violation {0}. The {1} pricing slope is {2}",symbol,dayCount,Utility.FormatNumber(lsr.Slope,6));
|
||||
return cmtCandidate;
|
||||
}
|
||||
}
|
||||
// Filter penny stocks - don't trade anything less than $1.00
|
||||
if(currentPrice.Close<1.00||currentPrice.Open<1.00)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("Penny stock violation {0} Close price is {1}, Open price is ",symbol,Utility.FormatCurrency(currentPrice.Close),Utility.FormatCurrency(currentPrice.Open));
|
||||
return cmtCandidate;
|
||||
}
|
||||
// Capture latest Volume - we'll do a min check later on
|
||||
cmtCandidate.Volume=currentPrice.Volume;
|
||||
|
||||
// Daily Return Check
|
||||
float[] dailyReturns=prices.GetReturns(); // First we build the returns (before we reverse the pricing direction)
|
||||
if(HasReturnViolation(dailyReturns,cmtParams.DailyReturnLimit)) // Check the return stream. If any daily return exceeds DailyReturnLimit then we discard.
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("Daily return violation for {0}. A daily return exceeded {1}%.",symbol,cmtParams.DailyReturnLimit);
|
||||
return cmtCandidate;
|
||||
}
|
||||
|
||||
// check for outliers in the return stream
|
||||
if((from float value in dailyReturns where Math.Abs(value)>cmtParams.DailyReturnLimit select value).Count()>0)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("Outlier encountered in return stream for {0}. Limit {1}",symbol,cmtParams.DailyReturnLimit);
|
||||
return cmtCandidate;
|
||||
}
|
||||
|
||||
// EBITDA screen
|
||||
bool UseEBITDAScreen=true;
|
||||
if(UseEBITDAScreen&&(double.IsNaN(fundamental.EBITDA)||fundamental.EBITDA<=0))
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason="Trend#14 Violation : EBITDA";
|
||||
return cmtCandidate;
|
||||
}
|
||||
|
||||
bool UsePEScreen=true;
|
||||
if(UsePEScreen&&(double.IsNaN(fundamental.PE))||fundamental.PE<=0.00)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason="Trend#14 Violation : UsePEScreen";
|
||||
return cmtCandidate;
|
||||
}
|
||||
|
||||
// Setup for next tests
|
||||
double profitMarginSlope=double.NaN;
|
||||
DateTime minDate=DateTime.MinValue;
|
||||
DateTime maxDate=DateTime.MinValue;
|
||||
float[] values;
|
||||
// Revenue per share screen
|
||||
bool UseRevenuePerShareScreen=true;
|
||||
if(UseRevenuePerShareScreen&&(double.IsNaN(fundamental.RevenuePerShare)||fundamental.RevenuePerShare<0.00))
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason="Trend#14 Violation : Revenue Per Share";
|
||||
return cmtCandidate;
|
||||
}
|
||||
// Trend#9 - My check Increasing EPS
|
||||
double epsSlope=double.NaN;
|
||||
if(companyProfile.IsEquity&&cmtParams.EPSCheck)
|
||||
{
|
||||
TimeSeriesCollection epsTimeSeries=FundamentalDA.GetEPS(symbol,currentPrice.Date);
|
||||
if(null==epsTimeSeries||epsTimeSeries.Count<3)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason="Trend#9 Violation : No EPS time series to perform check.";
|
||||
return cmtCandidate;
|
||||
}
|
||||
epsTimeSeries=new TimeSeriesCollection(epsTimeSeries.Take(3).ToList());
|
||||
minDate=epsTimeSeries.Min(x => x.AsOf);
|
||||
maxDate=epsTimeSeries.Max(x => x.AsOf);
|
||||
values=epsTimeSeries.ToFloat();
|
||||
values=Numerics.Reverse(ref values);
|
||||
epsSlope=Numerics.Slope(values);
|
||||
if(epsSlope<=0)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason="Trend#9 Violation : epsSlope<=0.";
|
||||
return cmtCandidate;
|
||||
}
|
||||
}
|
||||
|
||||
// Trend#10 - My check - Increasing profit margin
|
||||
if(companyProfile.IsEquity&&cmtParams.ProfitMarginCheck)
|
||||
{
|
||||
TimeSeriesCollection profitMarginTimeSeries=IncomeStatementDA.GetProfitMarginMaxAsOf(symbol,currentPrice.Date,IncomeStatement.PeriodType.Quarterly);
|
||||
if(null==profitMarginTimeSeries||profitMarginTimeSeries.Count<3)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason="Trend#10 Violation : No Profit Margin series to perform check.";
|
||||
return cmtCandidate;
|
||||
}
|
||||
profitMarginTimeSeries=new TimeSeriesCollection(profitMarginTimeSeries.Take(3).ToList());
|
||||
minDate=profitMarginTimeSeries.Min(x => x.AsOf);
|
||||
maxDate=profitMarginTimeSeries.Max(x => x.AsOf);
|
||||
values=profitMarginTimeSeries.ToFloat();
|
||||
values=Numerics.Reverse(ref values);
|
||||
profitMarginSlope=Numerics.Slope(values);
|
||||
if(profitMarginSlope<=0)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason="Trend#10 Violation : profitMarginSlope<=0.";
|
||||
return cmtCandidate;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the Score
|
||||
prices.Reverse(); // Reverse the series here.
|
||||
double[] logPrices=null;
|
||||
logPrices=new double[prices.Count];
|
||||
for(int index=0;index<prices.Count;index++)
|
||||
{
|
||||
Price price=prices[index];
|
||||
logPrices[index]=Math.Log(price.Close);
|
||||
}
|
||||
LeastSquaresResultWithR2 leastSquaresResult=LeastSquaresHelper.CalculateLeastSquaresWithR2(logPrices);
|
||||
cmtCandidate=new CMTCandidate();
|
||||
cmtCandidate.EPSSlope=epsSlope;
|
||||
cmtCandidate.PriceSlope=leastSquaresResult.Slope;
|
||||
cmtCandidate.ProfitMarginSlope=profitMarginSlope;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.AnalysisDate=tradeDate;
|
||||
cmtCandidate.Slope=leastSquaresResult.Slope;
|
||||
cmtCandidate.Volatility=volatility;
|
||||
cmtCandidate.AnnualizedReturn=Math.Pow(Math.Exp(cmtCandidate.Slope),252); //cmCandidate.AnnualizedReturn=Math.Pow(1.00+cmCandidate.Slope,252);
|
||||
if(cmtCandidate.Slope<0) cmtCandidate.AnnualizedReturn*=-1.00; // preserve the sign of the slope
|
||||
cmtCandidate.Score=leastSquaresResult.RSquared*cmtCandidate.AnnualizedReturn; // The greater the score the higher the rank
|
||||
cmtCandidate.RSquared=leastSquaresResult.RSquared;
|
||||
cmtCandidate.Beta=BetaGenerator.Beta(symbol,tradeDate,cmtParams.BetaMonths);
|
||||
cmtCandidate.BetaMonths=cmtParams.BetaMonths;
|
||||
if(double.IsNaN(cmtCandidate.Beta))
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("Unable to calculate {0} month beta for {1} ",cmtParams.BetaMonths,symbol);
|
||||
return cmtCandidate;
|
||||
}
|
||||
if(cmtCandidate.Beta<=0.00)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("Beta for {0} is less than or equal to zero {1}",symbol,cmtCandidate.Beta);
|
||||
return cmtCandidate;
|
||||
}
|
||||
if(cmtParams.UseMaxBeta&&cmtCandidate.Beta>cmtParams.MaxBeta)
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("Beta for {0} exceeds maximum allowed. Candidate beta {1}, Max Beta:{2}",symbol,cmtCandidate.Beta,cmtParams.MaxBeta);
|
||||
return cmtCandidate;
|
||||
}
|
||||
cmtCandidate.SharpeRatio=SharpeRatioGenerator.GenerateSharpeRatio(cmtCandidate.Symbol,tradeDate);
|
||||
if(double.IsNaN(cmtCandidate.SharpeRatio))
|
||||
{
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Reason=String.Format("Unable to calculate Sharpe Ratio for {0}",symbol);
|
||||
return cmtCandidate;
|
||||
}
|
||||
return cmtCandidate;
|
||||
}
|
||||
catch(Exception exception)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
|
||||
cmtCandidate.Violation=true;
|
||||
cmtCandidate.Symbol=symbol;
|
||||
cmtCandidate.Reason=exception.ToString();
|
||||
return cmtCandidate;
|
||||
}
|
||||
}
|
||||
private static bool HasReturnViolation(float[] dailyReturns,double dailyReturnLimit)
|
||||
{
|
||||
foreach(float dailyReturn in dailyReturns) if(Math.Abs(dailyReturn)>dailyReturnLimit) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
MarketData/MarketDataLib/Generator/CMTrend/CMTGeneratorResult.cs
Executable file
24
MarketData/MarketDataLib/Generator/CMTrend/CMTGeneratorResult.cs
Executable file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MarketData.Generator.CMTrend
|
||||
{
|
||||
public class CMTGeneratorResult
|
||||
{
|
||||
public CMTGeneratorResult()
|
||||
{
|
||||
Success=false;
|
||||
CMTCandidates=new CMTCandidates();
|
||||
CMTCandidatesWithViolation=new CMTCandidates();
|
||||
Messages=new List<String>();
|
||||
}
|
||||
public CMTCandidates CMTCandidates { get; set; }
|
||||
public CMTCandidates CMTCandidatesWithViolation { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public List<String> Messages { get; set; }
|
||||
public String LastMessage { get { if(null==Messages||0==Messages.Count) return ""; else return Messages[0]; } }
|
||||
}
|
||||
}
|
||||
31
MarketData/MarketDataLib/Generator/CMTrend/CMTMACDIndicator.cs
Executable file
31
MarketData/MarketDataLib/Generator/CMTrend/CMTMACDIndicator.cs
Executable file
@@ -0,0 +1,31 @@
|
||||
using MarketData.Cache;
|
||||
using MarketData.MarketDataModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MarketData.Generator.CMTrend
|
||||
{
|
||||
public class CMTMACDIndicator
|
||||
{
|
||||
private CMTMACDIndicator()
|
||||
{
|
||||
}
|
||||
public static bool IsMACDDowntrend(DateTime tradeDate,String symbol,CMTParams parameters)
|
||||
{
|
||||
Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,tradeDate,parameters.MACDSignalDays*3);
|
||||
if(null==prices||!prices[0].Date.Date.Equals(tradeDate.Date)) return true;
|
||||
MACDSetup macdSetup=new MACDSetup(parameters.MACDSetup);
|
||||
MACDSignals macdSignals=MACDGenerator.GenerateMACD(prices,macdSetup);
|
||||
Signals signalsMACD=SignalGenerator.GenerateSignals(macdSignals);
|
||||
signalsMACD=new Signals(signalsMACD.Take(parameters.MACDSignalDays).ToList());
|
||||
int weakSellSignalCount=(from Signal signal in signalsMACD where signal.IsWeakSell() select signal).Count();
|
||||
int strongSellSignalCount=(from Signal signal in signalsMACD where signal.IsStrongSell() select signal).Count();
|
||||
if(parameters.MACDRejectWeakSells&&weakSellSignalCount>0) return true;
|
||||
if(parameters.MACDRejectStrongSells&&strongSellSignalCount>0) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
376
MarketData/MarketDataLib/Generator/CMTrend/CMTParams.cs
Executable file
376
MarketData/MarketDataLib/Generator/CMTrend/CMTParams.cs
Executable file
@@ -0,0 +1,376 @@
|
||||
using MarketData.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MarketData.Generator.CMTrend
|
||||
{
|
||||
public class CMTParams
|
||||
{
|
||||
public CMTParams()
|
||||
{
|
||||
SuspendTrading=false; // If this flag is set to true then no new positions will be opned.
|
||||
UsePriceSlopeIndicator=true; // If this flag is set to true then enforce positive slope on prices over UserPriceSlopeIndicatorDays
|
||||
UsePriceSlopeIndicatorDays=252; // The number of pricing days to use for the slope.
|
||||
BetaMonths=6; // The number of months to use for Beta
|
||||
AnalysisDate=DateTime.Now.Date; // The analysis date of the run
|
||||
MarketCapLowerLimit=500000000; // MarketCap lower limit 50,0000,000
|
||||
TradeDate=DateTime.Now; // The current trade date
|
||||
SidewaysDetection=false; // Detect stock that are going nowhere. If we've held the stock for SidewaysAfterDays AND we've never adjusted the stop AND we can break even THEN we sell.
|
||||
SidewaysAfterDays=30; // Sideways detection days.
|
||||
MaxDailyPositions=3; // This is the maximum number of positions to pick up per analysis date. The default is 3
|
||||
MaxOpenPositions=3; // This is the maximum number of open positions. I have tested this with 3 and had good results.
|
||||
NoTradeSymbols="CLCT,PRSC,CMD,STAY,GBTC,YOKU,PNY,RFMD,ASAZY,USMO,VNR,STB,XIV,SYNT"; // ASAZY came up as candidate during 3/30 run but not available on Robinhood
|
||||
OnlyTradeSymbols=""; // This should be a comma separated list of symbols which would serve as the universe of symbols to trade. If null or empty then we trade everything in security master
|
||||
InitialCash=10000; // The initial cash
|
||||
TotalRiskPercentDecimal=.05; // Total Risk of Initial Cash. The default is .02. I've been testing with .05
|
||||
PositionRiskPercentDecimal=.12; // Risk per position - This will determine where the stop is placed. The default is .12
|
||||
CheckOutliersInReturnStream=true; // If enabled then we check the return and ensure that no daily return exceeds DailyReturnLimit
|
||||
DailyReturnLimit=.25; // If any single day return in the price stream exceeds this amount we toss it out. The default is .25
|
||||
MinRSI=70; // The minimum RSI in order to consider the candidate. Default is 70
|
||||
MinDaysBetweenReholding=30; // After selling a security we must wait this number of days before acting on a new buy signal . The default is 15
|
||||
EquityOnly=false; // If set to true then ETFs are excluded
|
||||
MinPercentReturnProximityTo52WeekHigh=30; // The minimum acceptable percent proximity to the 52 week high. The default is within 30 percent (i.e.) current price can be below the 52 week high by this margin. The larger the number , the wider the margin
|
||||
MinPercentReturnOver52WeekLow=80; // The minimum acceptable percent return over the 52 week low. Marc recommends 80,90,100,200,300
|
||||
ProfitMarginCheck=true; // If TRUE then profit margin time series must be present and slope must be increasing
|
||||
EPSCheck=true; // If TRUE then eps time series must be present and slope must be increasing
|
||||
LiquidityCheck=true; // If TRUE then the price history is checked against MinVolume
|
||||
MinVolume=1000; // The minimum day volume in order to consider a security. This is used if LiquidityCheck is TRUE. Default is 5000
|
||||
DMA200Horizon=15; // Number of days to examine when evaluating the slope of 200 day moving averages. Default is 20 days of DMA200's
|
||||
MinDaysBetweenStopAdjustments=30; // We won't adjust a stop if the number of days between previous adjustment is less than this. Default is 60
|
||||
MinDaysBetweenInitialStopAdjustment=5; // We won't change the initial stop until this number of days has elapsed. Default is 60.
|
||||
MaxPricingExceptions=3; // 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.
|
||||
UseMarketIndicator=true; // If true then we gauge the market based upon the benchmark's moving average
|
||||
Benchmark="SPY"; // This is the benchmark security
|
||||
BenchmarkMovingAverageDays=200; // If the latest benchmark Close is below DMA(BenchmarkMovingAverageDays) then we do not purchase new securities. I tested this with 200 and then with 55. 55 was 56% better over the period tested which was 01/06/2019-05/07/2021. so I am setting this to 100.. just because.
|
||||
BenchmarkMovingAverageHorizon=5; // This is the horizon for the benchmark indicator. it must be trading above BenchmarkMovingAverageDays for BenchmarkMovingAverageHorizon days
|
||||
UseMarketIndicatorVolatility=true; // If this is true then we detect volatile market by examing lower L band breaks on the ~VIX
|
||||
UseMarketIndicatorVolatilityHorizon=60; // The horizon over which to examine lower L band breaks in ~VIX
|
||||
UseMarketIndicatorVolatilityBenchmark="^VIX"; // The benchmark to use for volatility
|
||||
UseStopLimitScaling=true; // When set to true this will scale (tighten) the stop limit as time progresses based upon an anticipated holding period of StopLimitScalingDays.
|
||||
StopLimitScalingType="AverageTrueRange"; // Acceptable types are "AverageTrueRange".
|
||||
StopLimitScalingVolatilityDays=30; // StopLimitScalingVolatilityDays=5 The StopLimitScaling takes volatility into account. This parameter specifies how many days of pricing to use for the volatility calculation.
|
||||
EvaluateStopOnUpTrend=false; // If set to true then the stop limit is only evaluated if prices are trending up.
|
||||
SellOnDMABreak=true; // If true then we look lok for breaks of all DMAs listed under DMABreak
|
||||
DMABreakValues="200"; // The defaut value is 200. This can be a comma separated list. For instance 50,100,200
|
||||
DMABreakForceBreak=false; // If this flag is set to true then we will sell a security on DMA break even if it means taking a loss on the position.
|
||||
EntryType="OverExtended,MVP,PriceTrend,VolumeTrend"; // The entry type indictor. NarrowRange, Swing, MACD, PriceTRend, VolumeTrend, ChannelBreakout. Default is "MVP,NarrowRange,MACD,PriceTrend,VolumeTrend".
|
||||
PriceTrendDays=20; // If PriceTrend is in the EntryType list then We want to see a series of higher highs and higher lows. This is the horizon for those observations. Default is 10.
|
||||
EntryHorizon=30; // For the NarrowRange entry indicator this is the number of days to consider
|
||||
MACDSetup="(12,26,9)"; // setup for MACD Entry. Default is (12,26,9)
|
||||
MACDSignalDays=5; // Number of signal days to consider. Default is 12
|
||||
MACDRejectStrongSells=true; // MACD reject. Default is false. **Used only if MACD is in the EntryType list
|
||||
MACDRejectWeakSells=true; // MACD reject. Default is true. **Used only if MACD is in the EntryType list
|
||||
VolumeTrendDays=10; // Volume trend can be used as an entry indicator. The default value is 10 days of increasing volume
|
||||
CandidateExpiryDays=180; // Candidates will be kept in the candidate pool for entry search for this many days after which they will be removed and no longer available for consideration
|
||||
ChannelBreakoutHorizon=40; // Horizon for ChannelBreakout entry
|
||||
UseOverExtendedIndicatorDays=45; // 10 This is the number of days of history to scan for OverExtension detetction. 10 gives best results in backtest
|
||||
UseOverExtendedIndicatorViolationThreshhold=1; // This is the number of items that constitute an upper band break. (i.e.) if this is set to 1 then a single band break is a violation... if 2 then >=2 band breaks are a violation etc., 1.00 gives the best results in backtest
|
||||
UseOverExtendedIndicatorMarginPercent=1; // Add this in so we can control the margin. The best value is 1.00 from backtest results
|
||||
MaxBeta=10.00; // Candidates with Beta that exceed this are rejected.
|
||||
UseMaxBeta=false; // Utilize the MaxBeta filter
|
||||
UseProfitMaximization=true; // Maximize profits when setting stop limits. What this does is to instead of using 3*ATR(20) it will use UseProfitMaximizationATRMultiplier*ATR(20) to set the stop limit for R's greater than or equal to UseProfitMaximizationRs
|
||||
UseProfitMaximizationExpression="R_THRESSHOLD=4;MAX_ATR=3;MULTIPLIER=MAX_ATR;IF(RMultiple>=R_THRESSHOLD){MULTIPLIER=1.2;}"; // The default ATR multiplier is 3 which will maintain a wider gap. 1.2 will follow more closely
|
||||
UseTradeOnlySectors=false; // If set to true then only consider companies in specified sectors
|
||||
UseTradeOnlySectorsSectors="Healthcare,Technology,Basic Materials,Consumer Defensive,Industrials";
|
||||
}
|
||||
public bool SuspendTrading{get;set;}
|
||||
public bool UsePriceSlopeIndicator{get;set;}
|
||||
public int UsePriceSlopeIndicatorDays{get;set;}
|
||||
public bool UseMarketIndicatorVolatility{get;set;}
|
||||
public int UseMarketIndicatorVolatilityHorizon{get;set;}
|
||||
public string UseMarketIndicatorVolatilityBenchmark{get;set;}
|
||||
public int BetaMonths { get; set; }
|
||||
public DateTime AnalysisDate { get; set; }
|
||||
public DateTime TradeDate { get; set; }
|
||||
public double MarketCapLowerLimit { get; set; }
|
||||
public bool SidewaysDetection { get; set; }
|
||||
public int SidewaysAfterDays { get; set; }
|
||||
public int PriceTrendDays { get; set; }
|
||||
public bool CheckOutliersInReturnStream { get; set; }
|
||||
public double DailyReturnLimit { get; set; }
|
||||
public int MaxDailyPositions { get; set; }
|
||||
public int MaxOpenPositions { get; set; }
|
||||
public String NoTradeSymbols { get; set; }
|
||||
public String OnlyTradeSymbols { get; set; }
|
||||
public double MinRSI { get; set; }
|
||||
public List<String> NoTradeSymbolsList { get { return null==NoTradeSymbols?null:Utility.ToList(NoTradeSymbols); } }
|
||||
public List<String> OnlyTradeSymbolsList { get { return null==OnlyTradeSymbols?null:Utility.ToList(OnlyTradeSymbols); } }
|
||||
public double InitialCash { get; set; }
|
||||
public double TotalRiskPercentDecimal { get; set; }
|
||||
public double PositionRiskPercentDecimal { get; set; }
|
||||
public bool EquityOnly { get; set; }
|
||||
public double MinPercentReturnProximityTo52WeekHigh { get; set; }
|
||||
public double MinPercentReturnOver52WeekLow { get; set; }
|
||||
public bool ProfitMarginCheck { get; set; }
|
||||
public bool EPSCheck { get; set; }
|
||||
public int MinDaysBetweenReholding { get; set; }
|
||||
public bool LiquidityCheck { get; set; }
|
||||
public int MinVolume { get; set; }
|
||||
public int DMA200Horizon { get; set; }
|
||||
public int MinDaysBetweenStopAdjustments { get; set; }
|
||||
public int MinDaysBetweenInitialStopAdjustment { get; set; }
|
||||
public int MaxPricingExceptions { get; set; }
|
||||
public String MACDSetup { get; set; }
|
||||
public int MACDSignalDays { get; set; }
|
||||
public bool MACDRejectStrongSells { get; set; }
|
||||
public bool MACDRejectWeakSells { get; set; }
|
||||
public bool UseMarketIndicator { get; set; }
|
||||
public String Benchmark { get; set; }
|
||||
public int BenchmarkMovingAverageDays { get; set; }
|
||||
public int BenchmarkMovingAverageHorizon { get; set; }
|
||||
public bool UseStopLimitScaling { get; set; }
|
||||
public String StopLimitScalingType { get; set; }
|
||||
public int StopLimitScalingVolatilityDays { get; set; }
|
||||
public bool SellOnDMABreak { get; set; }
|
||||
public String DMABreakValues { get; set; }
|
||||
public bool DMABreakForceBreak { get; set; }
|
||||
public List<String> DMABreakValuesCollection { get { return (!SellOnDMABreak)||(null==DMABreakValues)?new List<String>():Utility.ToList(DMABreakValues); } }
|
||||
public String EntryType { get; set; }
|
||||
public List<String> EntryTypesCollection { get { return null==EntryType?new List<String>():Utility.ToList(EntryType); } }
|
||||
public int EntryHorizon { get; set; }
|
||||
public int CandidateExpiryDays { get; set; }
|
||||
public int VolumeTrendDays { get; set; }
|
||||
public int ChannelBreakoutHorizon { get; set; }
|
||||
public int UseOverExtendedIndicatorDays { get; set; }
|
||||
public int UseOverExtendedIndicatorViolationThreshhold { get; set; }
|
||||
public double UseOverExtendedIndicatorMarginPercent { get; set; }
|
||||
public bool UseMaxBeta { get; set; }
|
||||
public double MaxBeta { get; set; }
|
||||
public bool UseProfitMaximization{get;set;}
|
||||
public string UseProfitMaximizationExpression{get;set;}
|
||||
public bool UseTradeOnlySectors{get;set;}
|
||||
public String UseTradeOnlySectorsSectors{get;set;}
|
||||
public bool EvaluateStopOnUpTrend { get; set; }
|
||||
|
||||
public void DisplayHeader()
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,"Setting,Value");
|
||||
}
|
||||
public NVPCollection ToNVPCollection()
|
||||
{
|
||||
NVPCollection nvpCollection=new NVPCollection();
|
||||
nvpCollection.Add(new NVP("SuspendTrading",SuspendTrading.ToString()));
|
||||
nvpCollection.Add(new NVP("UsePriceSlopeIndicator",UsePriceSlopeIndicator.ToString()));
|
||||
nvpCollection.Add(new NVP("UsePriceSlopeIndicatorDays",UsePriceSlopeIndicatorDays.ToString()));
|
||||
nvpCollection.Add(new NVP("AnalysisDate",AnalysisDate.ToShortDateString()));
|
||||
nvpCollection.Add(new NVP("BetaMonths",BetaMonths.ToString()));
|
||||
nvpCollection.Add(new NVP("TradeDate",TradeDate.ToShortDateString()));
|
||||
nvpCollection.Add(new NVP("MarketCapLowerLimit",MarketCapLowerLimit.ToString()));
|
||||
nvpCollection.Add(new NVP("SidewaysDetection",SidewaysDetection.ToString()));
|
||||
nvpCollection.Add(new NVP("SidewaysAfterDays",SidewaysAfterDays.ToString()));
|
||||
nvpCollection.Add(new NVP("PriceTrendDays",PriceTrendDays.ToString()));
|
||||
nvpCollection.Add(new NVP("CheckOutliersInReturnStream",CheckOutliersInReturnStream.ToString()));
|
||||
nvpCollection.Add(new NVP("DailyReturnLimit",DailyReturnLimit.ToString()));
|
||||
nvpCollection.Add(new NVP("MaxDailyPositions",MaxDailyPositions.ToString()));
|
||||
nvpCollection.Add(new NVP("MaxOpenPositions",MaxOpenPositions.ToString()));
|
||||
nvpCollection.Add(new NVP("NoTradeSymbols",NoTradeSymbols.ToString()));
|
||||
nvpCollection.Add(new NVP("OnlyTradeSymbols",OnlyTradeSymbols.ToString()));
|
||||
nvpCollection.Add(new NVP("MinRSI",MinRSI.ToString()));
|
||||
nvpCollection.Add(new NVP("InitialCash",InitialCash.ToString()));
|
||||
nvpCollection.Add(new NVP("TotalRiskPercentDecimal",TotalRiskPercentDecimal.ToString()));
|
||||
nvpCollection.Add(new NVP("PositionRiskPercentDecimal",PositionRiskPercentDecimal.ToString()));
|
||||
nvpCollection.Add(new NVP("EquityOnly",EquityOnly.ToString()));
|
||||
nvpCollection.Add(new NVP("MinPercentReturnProximityTo52WeekHigh",MinPercentReturnProximityTo52WeekHigh.ToString()));
|
||||
nvpCollection.Add(new NVP("MinPercentReturnOver52WeekLow",MinPercentReturnOver52WeekLow.ToString()));
|
||||
nvpCollection.Add(new NVP("ProfitMarginCheck",ProfitMarginCheck.ToString()));
|
||||
nvpCollection.Add(new NVP("EPSCheck",EPSCheck.ToString()));
|
||||
nvpCollection.Add(new NVP("MinDaysBetweenReholding",MinDaysBetweenReholding.ToString()));
|
||||
nvpCollection.Add(new NVP("LiquidityCheck",LiquidityCheck.ToString()));
|
||||
nvpCollection.Add(new NVP("MinVolume",MinVolume.ToString()));
|
||||
nvpCollection.Add(new NVP("DMA200Horizon",DMA200Horizon.ToString()));
|
||||
nvpCollection.Add(new NVP("MinDaysBetweenStopAdjustments",MinDaysBetweenStopAdjustments.ToString()));
|
||||
nvpCollection.Add(new NVP("MinDaysBetweenInitialStopAdjustment",MinDaysBetweenInitialStopAdjustment.ToString()));
|
||||
nvpCollection.Add(new NVP("MaxPricingExceptions",MaxPricingExceptions.ToString()));
|
||||
nvpCollection.Add(new NVP("MACDSetup",MACDSetup.ToString()));
|
||||
nvpCollection.Add(new NVP("MACDSignalDays",MACDSignalDays.ToString()));
|
||||
nvpCollection.Add(new NVP("MACDRejectStrongSells",MACDRejectStrongSells.ToString()));
|
||||
nvpCollection.Add(new NVP("MACDRejectWeakSells",MACDRejectWeakSells.ToString()));
|
||||
nvpCollection.Add(new NVP("UseMarketIndicator",UseMarketIndicator.ToString()));
|
||||
nvpCollection.Add(new NVP("Benchmark",Benchmark.ToString()));
|
||||
nvpCollection.Add(new NVP("BenchmarkMovingAverageDays",BenchmarkMovingAverageDays.ToString()));
|
||||
nvpCollection.Add(new NVP("BenchmarkMovingAverageHorizon",BenchmarkMovingAverageHorizon.ToString()));
|
||||
nvpCollection.Add(new NVP("UseMarketIndicatorVolatility",UseMarketIndicatorVolatility.ToString()));
|
||||
nvpCollection.Add(new NVP("UseMarketIndicatorVolatilityHorizon",UseMarketIndicatorVolatilityHorizon.ToString()));
|
||||
nvpCollection.Add(new NVP("UseMarketIndicatorVolatilityBenchmark",UseMarketIndicatorVolatilityBenchmark.ToString()));
|
||||
nvpCollection.Add(new NVP("UseStopLimitScaling",UseStopLimitScaling.ToString()));
|
||||
nvpCollection.Add(new NVP("StopLimitScalingType",StopLimitScalingType.ToString()));
|
||||
nvpCollection.Add(new NVP("StopLimitScalingVolatilityDays",StopLimitScalingVolatilityDays.ToString()));
|
||||
nvpCollection.Add(new NVP("SellOnDMABreak",SellOnDMABreak.ToString()));
|
||||
nvpCollection.Add(new NVP("DMABreakValues",DMABreakValues.ToString()));
|
||||
nvpCollection.Add(new NVP("DMABreakForceBreak",DMABreakForceBreak.ToString()));
|
||||
nvpCollection.Add(new NVP("EntryType",EntryType.ToString()));
|
||||
nvpCollection.Add(new NVP("EntryHorizon",EntryHorizon.ToString()));
|
||||
nvpCollection.Add(new NVP("CandidateExpiryDays",CandidateExpiryDays.ToString()));
|
||||
nvpCollection.Add(new NVP("VolumeTrendDays",VolumeTrendDays.ToString()));
|
||||
nvpCollection.Add(new NVP("ChannelBreakoutHorizon",ChannelBreakoutHorizon.ToString()));
|
||||
nvpCollection.Add(new NVP("UseOverExtendedIndicatorDays",UseOverExtendedIndicatorDays.ToString()));
|
||||
nvpCollection.Add(new NVP("UseOverExtendedIndicatorViolationThreshhold",UseOverExtendedIndicatorViolationThreshhold.ToString()));
|
||||
nvpCollection.Add(new NVP("UseOverExtendedIndicatorMarginPercent",UseOverExtendedIndicatorMarginPercent.ToString()));
|
||||
nvpCollection.Add(new NVP("MaxBeta",MaxBeta.ToString()));
|
||||
nvpCollection.Add(new NVP("UseMaxBeta",UseMaxBeta.ToString()));
|
||||
nvpCollection.Add(new NVP("UseProfitMaximization",UseProfitMaximization.ToString()));
|
||||
nvpCollection.Add(new NVP("UseProfitMaximizationExpression",UseProfitMaximizationExpression.ToString()));
|
||||
nvpCollection.Add(new NVP("UseTradeOnlySectors",UseTradeOnlySectors.ToString()));
|
||||
nvpCollection.Add(new NVP("UseTradeOnlySectorsSectors",UseTradeOnlySectorsSectors.ToString()));
|
||||
nvpCollection.Add(new NVP("EvaluateStopOnUpTrend",EvaluateStopOnUpTrend.ToString()));
|
||||
return nvpCollection;
|
||||
}
|
||||
public static CMTParams FromNVPCollection(NVPCollection nvpCollection)
|
||||
{
|
||||
CMTParams cmtParams=new CMTParams();
|
||||
NVPDictionary nvpDictionary=nvpCollection.ToDictionary();
|
||||
|
||||
if(nvpDictionary.ContainsKey("SuspendTrading"))
|
||||
{
|
||||
cmtParams.SuspendTrading=nvpDictionary["SuspendTrading"].Get<bool>();
|
||||
}
|
||||
if(nvpDictionary.ContainsKey("UsePriceSlopeIndicator"))
|
||||
{
|
||||
cmtParams.UsePriceSlopeIndicator=nvpDictionary["UsePriceSlopeIndicator"].Get<bool>();
|
||||
cmtParams.UsePriceSlopeIndicatorDays=nvpDictionary["UsePriceSlopeIndicatorDays"].Get<int>();
|
||||
}
|
||||
if(nvpDictionary.ContainsKey("UseMarketIndicatorVolatility"))
|
||||
{
|
||||
cmtParams.UseMarketIndicatorVolatility=nvpDictionary["UseMarketIndicatorVolatility"].Get<bool>();
|
||||
cmtParams.UseMarketIndicatorVolatilityHorizon=nvpDictionary["UseMarketIndicatorVolatilityHorizon"].Get<int>();
|
||||
cmtParams.UseMarketIndicatorVolatilityBenchmark=nvpDictionary["UseMarketIndicatorVolatilityBenchmark"].Get<String>();
|
||||
}
|
||||
cmtParams.AnalysisDate=nvpDictionary["AnalysisDate"].Get<DateTime>();
|
||||
cmtParams.BetaMonths=nvpDictionary["BetaMonths"].Get<int>();
|
||||
cmtParams.TradeDate=nvpDictionary["TradeDate"].Get<DateTime>();
|
||||
cmtParams.MarketCapLowerLimit=nvpDictionary["MarketCapLowerLimit"].Get<double>();
|
||||
cmtParams.SidewaysDetection=nvpDictionary["SidewaysDetection"].Get<bool>();
|
||||
cmtParams.SidewaysAfterDays=nvpDictionary["SidewaysAfterDays"].Get<int>();
|
||||
cmtParams.PriceTrendDays=nvpDictionary["PriceTrendDays"].Get<int>();
|
||||
cmtParams.CheckOutliersInReturnStream=nvpDictionary["CheckOutliersInReturnStream"].Get<bool>();
|
||||
cmtParams.DailyReturnLimit=nvpDictionary["DailyReturnLimit"].Get<double>();
|
||||
cmtParams.MaxDailyPositions=nvpDictionary["MaxDailyPositions"].Get<int>();
|
||||
cmtParams.MaxOpenPositions=nvpDictionary["MaxOpenPositions"].Get<int>();
|
||||
cmtParams.NoTradeSymbols=nvpDictionary["NoTradeSymbols"].Get<String>();
|
||||
if(nvpDictionary.ContainsKey("OnlyTradeSymbols")) cmtParams.OnlyTradeSymbols=nvpDictionary["OnlyTradeSymbols"].Get<String>();
|
||||
cmtParams.MinRSI=nvpDictionary["MinRSI"].Get<double>();
|
||||
cmtParams.InitialCash=nvpDictionary["InitialCash"].Get<Double>();
|
||||
cmtParams.TotalRiskPercentDecimal=nvpDictionary["TotalRiskPercentDecimal"].Get<double>();
|
||||
cmtParams.PositionRiskPercentDecimal=nvpDictionary["PositionRiskPercentDecimal"].Get<double>();
|
||||
cmtParams.EquityOnly=nvpDictionary["EquityOnly"].Get<bool>();
|
||||
cmtParams.MinPercentReturnProximityTo52WeekHigh=nvpDictionary["MinPercentReturnProximityTo52WeekHigh"].Get<double>();
|
||||
cmtParams.MinPercentReturnOver52WeekLow=nvpDictionary["MinPercentReturnOver52WeekLow"].Get<double>();
|
||||
cmtParams.ProfitMarginCheck=nvpDictionary["ProfitMarginCheck"].Get<bool>();
|
||||
cmtParams.EPSCheck=nvpDictionary["EPSCheck"].Get<bool>();
|
||||
cmtParams.MinDaysBetweenReholding=nvpDictionary["MinDaysBetweenReholding"].Get<int>();
|
||||
cmtParams.LiquidityCheck=nvpDictionary["LiquidityCheck"].Get<bool>();
|
||||
cmtParams.MinVolume=nvpDictionary["MinVolume"].Get<int>();
|
||||
cmtParams.DMA200Horizon=nvpDictionary["DMA200Horizon"].Get<int>();
|
||||
cmtParams.MinDaysBetweenStopAdjustments=nvpDictionary["MinDaysBetweenStopAdjustments"].Get<int>();
|
||||
cmtParams.MinDaysBetweenInitialStopAdjustment=nvpDictionary["MinDaysBetweenInitialStopAdjustment"].Get<int>();
|
||||
cmtParams.MaxPricingExceptions=nvpDictionary["MaxPricingExceptions"].Get<int>();
|
||||
cmtParams.MACDSetup=nvpDictionary["MACDSetup"].Get<String>();
|
||||
cmtParams.MACDSignalDays=nvpDictionary["MACDSignalDays"].Get<int>();
|
||||
cmtParams.MACDRejectStrongSells=nvpDictionary["MACDRejectStrongSells"].Get<bool>();
|
||||
cmtParams.MACDRejectWeakSells=nvpDictionary["MACDRejectWeakSells"].Get<bool>();
|
||||
cmtParams.UseMarketIndicator=nvpDictionary["UseMarketIndicator"].Get<bool>();
|
||||
cmtParams.Benchmark=nvpDictionary["Benchmark"].Get<String>();
|
||||
cmtParams.BenchmarkMovingAverageDays=nvpDictionary["BenchmarkMovingAverageDays"].Get<int>();
|
||||
cmtParams.BenchmarkMovingAverageHorizon=nvpDictionary["BenchmarkMovingAverageHorizon"].Get<int>();
|
||||
cmtParams.UseStopLimitScaling=nvpDictionary["UseStopLimitScaling"].Get<bool>();
|
||||
if(nvpDictionary.ContainsKey("StopLimitScalingType")) cmtParams.StopLimitScalingType=nvpDictionary["StopLimitScalingType"].Get<String>();
|
||||
cmtParams.StopLimitScalingVolatilityDays=nvpDictionary["StopLimitScalingVolatilityDays"].Get<int>();
|
||||
cmtParams.SellOnDMABreak=nvpDictionary["SellOnDMABreak"].Get<bool>();
|
||||
cmtParams.DMABreakValues=nvpDictionary["DMABreakValues"].Get<String>();
|
||||
if(nvpDictionary.ContainsKey("DMABreakForceBreak")) cmtParams.DMABreakForceBreak=nvpDictionary["DMABreakForceBreak"].Get<bool>();
|
||||
cmtParams.EntryType=nvpDictionary["EntryType"].Get<String>();
|
||||
cmtParams.EntryHorizon=nvpDictionary["EntryHorizon"].Get<int>();
|
||||
cmtParams.CandidateExpiryDays=nvpDictionary["CandidateExpiryDays"].Get<int>();
|
||||
if(nvpDictionary.ContainsKey("VolumeTrendDays")) cmtParams.VolumeTrendDays=nvpDictionary["VolumeTrendDays"].Get<int>();
|
||||
if(nvpDictionary.ContainsKey("ChannelBreakoutHorizon")) cmtParams.ChannelBreakoutHorizon=nvpDictionary["ChannelBreakoutHorizon"].Get<int>();
|
||||
cmtParams.UseOverExtendedIndicatorDays=nvpDictionary["UseOverExtendedIndicatorDays"].Get<int>();
|
||||
cmtParams.UseOverExtendedIndicatorViolationThreshhold=nvpDictionary["UseOverExtendedIndicatorViolationThreshhold"].Get<int>();
|
||||
cmtParams.UseOverExtendedIndicatorMarginPercent=nvpDictionary["UseOverExtendedIndicatorMarginPercent"].Get<double>();
|
||||
cmtParams.UseMaxBeta=nvpDictionary["UseMaxBeta"].Get<bool>();
|
||||
cmtParams.MaxBeta=nvpDictionary["MaxBeta"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("UseProfitMaximization"))
|
||||
{
|
||||
cmtParams.UseProfitMaximization=nvpDictionary["UseProfitMaximization"].Get<bool>();
|
||||
cmtParams.UseProfitMaximizationExpression=nvpDictionary["UseProfitMaximizationExpression"].Get<String>();
|
||||
}
|
||||
if(nvpDictionary.ContainsKey("UseTradeOnlySectors"))
|
||||
{
|
||||
cmtParams.UseTradeOnlySectors=nvpDictionary["UseTradeOnlySectors"].Get<bool>();
|
||||
cmtParams.UseTradeOnlySectorsSectors=nvpDictionary["UseTradeOnlySectorsSectors"].Get<String>();
|
||||
}
|
||||
if(nvpDictionary.ContainsKey("EvaluateStopOnUpTrend"))
|
||||
{
|
||||
cmtParams.EvaluateStopOnUpTrend=nvpDictionary["EvaluateStopOnUpTrend"].Get<bool>();
|
||||
}
|
||||
return cmtParams;
|
||||
}
|
||||
public void DisplayConfiguration()
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("SuspendTrading,{0}",SuspendTrading));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UsePriceSlopeIndicator,{0}",UsePriceSlopeIndicator));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UsePriceSlopeIndicatorDays,{0}",UsePriceSlopeIndicatorDays));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("AnalysisDate,{0}",AnalysisDate));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("TradeDate,{0}",TradeDate));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("SidewaysDetection,{0}",SidewaysDetection));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("SidewaysAfterDays,{0}",SidewaysAfterDays));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("PriceTrendDays,{0}",PriceTrendDays));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MaxDailyPositions,{0}",MaxDailyPositions));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MaxOpenPositions,{0}",MaxOpenPositions));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("NoTradeSymbols,{0}",NoTradeSymbols));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("OnlyTradeSymbols,{0}",OnlyTradeSymbols));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("InitialCash,{0}",InitialCash));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("TotalRiskPercentDecimal,{0}",TotalRiskPercentDecimal));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("PositionRiskPercentDecimal,{0}",PositionRiskPercentDecimal));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("CheckOutliersInReturnStream,{0}",CheckOutliersInReturnStream));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("DailyReturnLimit,{0}",DailyReturnLimit));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MinRSI,{0}",MinRSI));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MinDaysBetweenReholding,{0}",MinDaysBetweenReholding));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("EquityOnly,{0}",EquityOnly));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MinPercentReturnProximityTo52WeekHigh,{0}",MinPercentReturnProximityTo52WeekHigh));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MinPercentReturnOver52WeekLow,{0}",MinPercentReturnOver52WeekLow));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("ProfitMarginCheck,{0}",ProfitMarginCheck));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("EPSCheck,{0}",EPSCheck));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("LiquidityCheck,{0}",LiquidityCheck));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MinVolume,{0}",MinVolume));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("DMA200Horizon,{0}",DMA200Horizon));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MinDaysBetweenStopAdjustments,{0}",MinDaysBetweenStopAdjustments));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MinDaysBetweenInitialStopAdjustment,{0}",MinDaysBetweenInitialStopAdjustment));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MaxPricingExceptions,{0}",MaxPricingExceptions));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MACDSetup,{0}",MACDSetup));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MACDSignalDays,{0}",MACDSignalDays));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MACDRejectStrongSells,{0}",MACDRejectStrongSells));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MACDRejectWeakSells,{0}",MACDRejectWeakSells));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseMarketIndicator,{0}",UseMarketIndicator));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Benchmark,{0}",Benchmark));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("BenchmarkMovingAverageDays,{0}",BenchmarkMovingAverageDays));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("BenchmarkMovingAverageHorizon,{0}",BenchmarkMovingAverageHorizon));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseMarketIndicatorVolatility,{0}",UseMarketIndicatorVolatility));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseMarketIndicatorVolatilityHorizon,{0}",UseMarketIndicatorVolatilityHorizon));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseMarketIndicatorVolatilityBenchmark,{0}",UseMarketIndicatorVolatilityBenchmark));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseStopLimitScaling,{0}",UseStopLimitScaling));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("StopLimitScalingType,{0}",StopLimitScalingType));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("StopLimitScalingVolatilityDays,{0}",StopLimitScalingVolatilityDays));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("SellOnDMABreak,{0}",SellOnDMABreak));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("DMABreakValues,{0}",DMABreakValues));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("DMABreakForceBreak,{0}",DMABreakForceBreak));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("EntryType,{0}",EntryType));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("EntryHorizon,{0}",EntryHorizon));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("CandidateExpiryDays,{0}",CandidateExpiryDays));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("VolumeTrendDays,{0}",VolumeTrendDays));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("ChannelBreakoutHorizon,{0}",ChannelBreakoutHorizon));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseOverExtendedIndicatorDays,{0}",UseOverExtendedIndicatorDays.ToString()));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseOverExtendedIndicatorViolationThreshhold,{0}",UseOverExtendedIndicatorViolationThreshhold.ToString()));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseOverExtendedIndicatorMarginPercent,{0}",UseOverExtendedIndicatorMarginPercent.ToString()));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseMaxBeta,{0}",UseMaxBeta.ToString()));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MaxBeta,{0}",MaxBeta.ToString()));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MarketCapLowerLimit,{0}",MarketCapLowerLimit.ToString()));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("BetaMonths,{0}",BetaMonths.ToString()));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseProfitMaximization,{0}",UseProfitMaximization.ToString()));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseProfitMaximizationExpression,{0}",UseProfitMaximizationExpression.ToString()));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseTradeOnlySectors,{0}",UseTradeOnlySectors.ToString()));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseTradeOnlySectorsSectors,{0}",UseTradeOnlySectorsSectors.ToString()));
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("EvaluateStopOnUpTrend,{0}",EvaluateStopOnUpTrend.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
310
MarketData/MarketDataLib/Generator/CMTrend/CMTPositions.cs
Executable file
310
MarketData/MarketDataLib/Generator/CMTrend/CMTPositions.cs
Executable file
@@ -0,0 +1,310 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MarketData.MarketDataModel;
|
||||
using MarketData.Utils;
|
||||
using System.Linq;
|
||||
using MarketData.Generator.Interface;
|
||||
|
||||
namespace MarketData.Generator.CMTrend
|
||||
{
|
||||
public class Position : IPosition
|
||||
{
|
||||
public Position()
|
||||
{
|
||||
CurrentPrice=double.NaN;
|
||||
}
|
||||
public Position(Position position)
|
||||
{
|
||||
Symbol=position.Symbol;
|
||||
PurchaseDate=position.PurchaseDate;
|
||||
SellDate=position.SellDate;
|
||||
Shares=position.Shares;
|
||||
PurchasePrice=position.PurchasePrice;
|
||||
CurrentPrice=position.CurrentPrice;
|
||||
R=position.R;
|
||||
C=position.C;
|
||||
PositionRiskPercentDecimal=position.PositionRiskPercentDecimal;
|
||||
InitialStopLimit=position.InitialStopLimit;
|
||||
TrailingStopLimit=position.TrailingStopLimit;
|
||||
Volume=position.Volume;
|
||||
Volatility=position.Volatility;
|
||||
LastStopAdjustment=position.LastStopAdjustment;
|
||||
Comment=position.Comment;
|
||||
}
|
||||
public static Position Clone(Position position)
|
||||
{
|
||||
Position clonedPosition=new Position();
|
||||
clonedPosition.Symbol=position.Symbol;
|
||||
clonedPosition.PurchaseDate=position.PurchaseDate;
|
||||
clonedPosition.SellDate=position.SellDate;
|
||||
clonedPosition.Shares=position.Shares;
|
||||
clonedPosition.PurchasePrice=position.PurchasePrice;
|
||||
clonedPosition.CurrentPrice=position.CurrentPrice;
|
||||
clonedPosition.R=position.R;
|
||||
clonedPosition.C=position.C;
|
||||
clonedPosition.PositionRiskPercentDecimal=position.PositionRiskPercentDecimal;
|
||||
clonedPosition.InitialStopLimit=position.InitialStopLimit;
|
||||
clonedPosition.TrailingStopLimit=position.TrailingStopLimit;
|
||||
clonedPosition.Volume=position.Volume;
|
||||
clonedPosition.Volatility=position.Volatility;
|
||||
clonedPosition.LastStopAdjustment=position.LastStopAdjustment;
|
||||
clonedPosition.Comment=position.Comment;
|
||||
return clonedPosition;
|
||||
}
|
||||
public String Symbol { get; set; }
|
||||
public DateTime PurchaseDate { get; set; }
|
||||
public DateTime SellDate { get; set; }
|
||||
public double Shares { get; set; } // This is actual shares (round down P to the nearest whole number)
|
||||
public double PurchasePrice { get; set; }
|
||||
public double CurrentPrice { get; set; } // When the position is sold the current price will hold the sell price
|
||||
public double Exposure { get { return Shares*PurchasePrice; } } // Derived
|
||||
public double MarketValue { get { return Shares*CurrentPrice; } } // Derived
|
||||
public double GainLoss { get { return MarketValue-Exposure; } } // Derived
|
||||
public double GetGainLoss(Price currentPrice) { return (Shares*currentPrice.Close)-Exposure; } // get the gain loss based upon the given price
|
||||
public double GainLossPcnt { get { return (MarketValue-Exposure)/Exposure; } } // Derived
|
||||
public double PositionRiskPercentDecimal { get; set; } // (i.e.) .06 = 6%
|
||||
public double R { get; set; } // PositionRiskPercentDecimal*PurchasePrice
|
||||
public double C { get; set; } // AvailableCash * TotalRiskPercentDecimal
|
||||
public double P { get { return C/R; } } // Derived. This is the number of shares to buy according to risk limits
|
||||
public double TrailingStopLimit { get; set; } // This is the trailing stop limit.
|
||||
public double InitialStopLimit { get; set; } // This is the initial stop limit.
|
||||
public DateTime LastStopAdjustment { get; set; }
|
||||
public double TotalRiskExposure { get { return R*Shares; } } // This is the total risk in dollars that we are exposed to
|
||||
public double RMultiple { get { return (CurrentPrice-PurchasePrice)/R; } } // Derived.
|
||||
public String RMultipleAsString
|
||||
{
|
||||
get
|
||||
{
|
||||
return Utility.FormatNumber(RMultiple,2,false)+"R";
|
||||
}
|
||||
} // Derived.
|
||||
public double Volatility { get; set; }
|
||||
public long Volume { get; set; }
|
||||
public String Comment { get; set; }
|
||||
|
||||
public virtual NVPCollection ToNVPCollection()
|
||||
{
|
||||
NVPCollection nvpCollection=new NVPCollection();
|
||||
nvpCollection.Add(new NVP("Symbol",Symbol.ToString()));
|
||||
nvpCollection.Add(new NVP("PurchaseDate",PurchaseDate.ToString()));
|
||||
nvpCollection.Add(new NVP("SellDate",SellDate.ToString()));
|
||||
nvpCollection.Add(new NVP("Shares",Shares.ToString()));
|
||||
nvpCollection.Add(new NVP("PurchasePrice",PurchasePrice.ToString()));
|
||||
if(!double.IsNaN(CurrentPrice)) nvpCollection.Add(new NVP("CurrentPrice",CurrentPrice.ToString()));
|
||||
if(!double.IsNaN(Exposure)) nvpCollection.Add(new NVP("Exposure",Exposure.ToString()));
|
||||
if(!double.IsNaN(MarketValue)) nvpCollection.Add(new NVP("MarketValue",MarketValue.ToString()));
|
||||
if(!double.IsNaN(GainLoss)) nvpCollection.Add(new NVP("GainLoss",GainLoss.ToString()));
|
||||
if(!double.IsNaN(GainLossPcnt)) nvpCollection.Add(new NVP("GainLossPcnt",GainLossPcnt.ToString()));
|
||||
if(!double.IsNaN(PositionRiskPercentDecimal)) nvpCollection.Add(new NVP("PositionRiskDecimal",PositionRiskPercentDecimal.ToString()));
|
||||
if(!double.IsNaN(R)) nvpCollection.Add(new NVP("R",R.ToString()));
|
||||
if(!double.IsNaN(C)) nvpCollection.Add(new NVP("C",C.ToString()));
|
||||
if(!double.IsNaN(C)) nvpCollection.Add(new NVP("P",P.ToString()));
|
||||
if(!double.IsNaN(InitialStopLimit)) nvpCollection.Add(new NVP("InitialStopLimit",InitialStopLimit.ToString()));
|
||||
if(!double.IsNaN(TrailingStopLimit)) nvpCollection.Add(new NVP("TrailingStopLimit",TrailingStopLimit.ToString()));
|
||||
if(!double.IsNaN(TotalRiskExposure)) nvpCollection.Add(new NVP("TotalRiskExposure",TotalRiskExposure.ToString()));
|
||||
if(!double.IsNaN(RMultiple)) nvpCollection.Add(new NVP("RMultiple",RMultipleAsString));
|
||||
if(!double.IsNaN(Volatility)) nvpCollection.Add(new NVP("Volatility",Volatility.ToString()));
|
||||
nvpCollection.Add(new NVP("Volume",Volume.ToString()));
|
||||
nvpCollection.Add(new NVP("LastStopAdjustment",LastStopAdjustment.ToString()));
|
||||
if(null!=Comment) nvpCollection.Add(new NVP("Comment",Comment));
|
||||
return nvpCollection;
|
||||
}
|
||||
public static Position FromNVPCollection(NVPCollection nvpCollection)
|
||||
{
|
||||
Position position=new Position();
|
||||
NVPDictionary nvpDictionary=nvpCollection.ToDictionary();
|
||||
position.Symbol=nvpDictionary["Symbol"].Get<String>();
|
||||
position.PurchaseDate=nvpDictionary["PurchaseDate"].Get<DateTime>();
|
||||
position.SellDate=nvpDictionary["SellDate"].Get<DateTime>();
|
||||
position.Shares=nvpDictionary["Shares"].Get<double>();
|
||||
position.PurchasePrice=nvpDictionary["PurchasePrice"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("CurrentPrice")) position.CurrentPrice=nvpDictionary["CurrentPrice"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("R")) position.R=nvpDictionary["R"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("C")) position.C=nvpDictionary["C"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("PositionRiskDecimal")) position.PositionRiskPercentDecimal=nvpDictionary["PositionRiskDecimal"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("InitialStopLimit")) position.InitialStopLimit=nvpDictionary["InitialStopLimit"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("TrailingStopLimit")) position.TrailingStopLimit=nvpDictionary["TrailingStopLimit"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("Volatility")) position.Volatility=nvpDictionary["Volatility"].Get<double>();
|
||||
if(nvpDictionary.ContainsKey("Volume")) position.Volume=nvpDictionary["Volume"].Get<int>();
|
||||
if(nvpDictionary.ContainsKey("LastStopAdjustment")) position.LastStopAdjustment=nvpDictionary["LastStopAdjustment"].Get<DateTime>();
|
||||
if(nvpDictionary.ContainsKey("Comment")) position.Comment=nvpDictionary["Comment"].Get<String>();
|
||||
return position;
|
||||
}
|
||||
public void Display()
|
||||
{
|
||||
if(Utility.IsEpoch(SellDate)&&double.IsNaN(CurrentPrice))
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17},{18},{19},{20},{21}",
|
||||
Symbol,
|
||||
Shares,
|
||||
Utility.DateTimeToStringMMHDDHYYYY(PurchaseDate),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(PurchasePrice)),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(InitialStopLimit)),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(TrailingStopLimit)),
|
||||
Utility.AddQuotes(Utility.DateTimeToStringMMHDDHYYYY(LastStopAdjustment)),
|
||||
Utility.AddQuotes(Utility.FormatNumber(Volatility,2)),
|
||||
Utility.AddQuotes(Utility.FormatNumber(Volume,0)),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(R)),
|
||||
Utility.AddQuotes(Utility.FormatNumber(PositionRiskPercentDecimal,3)),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(C)),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(TotalRiskExposure)),
|
||||
Utility.AddQuotes(Utility.FormatNumber(RMultiple,3)),
|
||||
Utility.AddQuotes(RMultipleAsString),
|
||||
Utility.IsEpoch(SellDate)?"N/A":Utility.DateTimeToStringMMHDDHYYYY(SellDate),
|
||||
"N/A",
|
||||
Utility.AddQuotes(Utility.FormatCurrency(Exposure)),
|
||||
"N/A",
|
||||
"N/A",
|
||||
"N/A",
|
||||
null==Comment?"":Comment
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17},{18},{19},{20},{21}",
|
||||
Symbol,
|
||||
Shares,
|
||||
Utility.DateTimeToStringMMHDDHYYYY(PurchaseDate),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(PurchasePrice)),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(InitialStopLimit)),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(TrailingStopLimit)),
|
||||
Utility.IsEpoch(LastStopAdjustment)?"N/A":Utility.DateTimeToStringMMHDDHYYYY(LastStopAdjustment),
|
||||
Utility.AddQuotes(Utility.FormatNumber(Volatility,2)),
|
||||
Utility.AddQuotes(Utility.FormatNumber(Volume,0)),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(R)),
|
||||
Utility.AddQuotes(Utility.FormatNumber(PositionRiskPercentDecimal,3)),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(C)),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(TotalRiskExposure)),
|
||||
Utility.AddQuotes(Utility.FormatNumber(RMultiple,3)),
|
||||
Utility.AddQuotes(RMultipleAsString),
|
||||
Utility.IsEpoch(SellDate)?"N/A":Utility.DateTimeToStringMMHDDHYYYY(SellDate),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(CurrentPrice)),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(Exposure)),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(MarketValue)),
|
||||
Utility.AddQuotes(Utility.FormatCurrency(GainLoss)),
|
||||
Utility.FormatPercent(GainLossPcnt),
|
||||
null==Comment?"":Comment
|
||||
));
|
||||
}
|
||||
}
|
||||
public static void DisplayHeader()
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,"Symbol,Shares,Purchase Date,Purchase Price,Initial Stop Limit,Trailing Stop Limit,Last Stop Adjustment,Volatility,Volume,R,PositionRiskPercentDecimal,C,TotalRiskExposure,RMultiple,RMultipleString,Sell Date,Sell Price,Exposure,Market Value,Gain Loss,Gain Loss(%),Comment");
|
||||
}
|
||||
}
|
||||
// ****************************************************************************************************************************************************************
|
||||
public class Positions:List<Position>
|
||||
{
|
||||
public Positions()
|
||||
{
|
||||
}
|
||||
public Positions(Positions positions)
|
||||
{
|
||||
if(null==positions) return;
|
||||
foreach(Position position in positions) Add(position);
|
||||
}
|
||||
public Positions(List<Position> positions)
|
||||
{
|
||||
if(null==positions) return;
|
||||
foreach(Position position in positions) Add(position);
|
||||
}
|
||||
public Positions(Position position)
|
||||
{
|
||||
if(null==position) return;
|
||||
Add(position);
|
||||
}
|
||||
public void Add(Positions positions)
|
||||
{
|
||||
if(null==positions) return;
|
||||
foreach(Position position in positions) Add(position);
|
||||
}
|
||||
public int PositionsOn(DateTime purchaseDate)
|
||||
{
|
||||
return this.Count(x => x.PurchaseDate.Equals(purchaseDate));
|
||||
}
|
||||
public double GetExposure()
|
||||
{
|
||||
Positions openPositions=new Positions(this.Where(x => Utility.IsEpoch(x.SellDate)).ToList());
|
||||
return (from Position position in openPositions select position.PurchasePrice*position.Shares).Sum();
|
||||
}
|
||||
public double GetMarketValue()
|
||||
{
|
||||
Positions closedPositions=new Positions(this.Where(x => !Utility.IsEpoch(x.SellDate)).ToList());
|
||||
if(null==closedPositions||0==closedPositions.Count) return 0.00;
|
||||
return closedPositions.Select(x => x.CurrentPrice*x.Shares).Sum();
|
||||
}
|
||||
public List<String> GetSymbols()
|
||||
{
|
||||
return (from Position position in this select position.Symbol).Distinct().ToList();
|
||||
}
|
||||
public double GetGainLoss()
|
||||
{
|
||||
Positions closedPositions=new Positions(this.Where(x => !Utility.IsEpoch(x.SellDate)).ToList());
|
||||
if(null==closedPositions||0==closedPositions.Count) return 0.00;
|
||||
double totalMarketValue=closedPositions.Select(x => x.Shares*x.CurrentPrice).Sum();
|
||||
double totalExposure=closedPositions.Select(x => x.Shares*x.PurchasePrice).Sum();
|
||||
return totalMarketValue-totalExposure;
|
||||
}
|
||||
public double GetGainLossPercent()
|
||||
{
|
||||
Positions closedPositions=new Positions(this.Where(x => !Utility.IsEpoch(x.SellDate)).ToList());
|
||||
if(null==closedPositions||0==closedPositions.Count) return 0.00;
|
||||
double totalMarketValue=closedPositions.Select(x => x.Shares*x.CurrentPrice).Sum();
|
||||
double totalExposure=closedPositions.Select(x => x.Shares*x.PurchasePrice).Sum();
|
||||
return (totalMarketValue-totalExposure)/totalExposure;
|
||||
}
|
||||
public NVPCollections ToNVPCollections()
|
||||
{
|
||||
NVPCollections nvpCollections=new NVPCollections();
|
||||
foreach(Position position in this)
|
||||
{
|
||||
nvpCollections.Add(position.ToNVPCollection());
|
||||
}
|
||||
return nvpCollections;
|
||||
}
|
||||
public static Positions FromNVPCollections(NVPCollections nvpCollections)
|
||||
{
|
||||
Positions positions=new Positions();
|
||||
foreach(NVPCollection nvpCollection in nvpCollections)
|
||||
{
|
||||
positions.Add(Position.FromNVPCollection(nvpCollection));
|
||||
}
|
||||
return positions;
|
||||
}
|
||||
public void AddFromNVPCollection(NVPCollection nvpCollection)
|
||||
{
|
||||
Add(Position.FromNVPCollection(nvpCollection));
|
||||
}
|
||||
public void DisplayTop(int count=10)
|
||||
{
|
||||
Positions positions=new Positions(this.OrderByDescending(x => x.GainLossPcnt).Take(count).ToList());
|
||||
Position.DisplayHeader();
|
||||
for(int index=0;index<positions.Count;index++)
|
||||
{
|
||||
Position position=positions[index];
|
||||
position.Display();
|
||||
}
|
||||
}
|
||||
public void DisplayBottom(int count=10)
|
||||
{
|
||||
Positions positions=new Positions(this.OrderBy(x => x.GainLossPcnt).Take(count).ToList());
|
||||
Position.DisplayHeader();
|
||||
for(int index=0;index<positions.Count;index++)
|
||||
{
|
||||
Position position=positions[index];
|
||||
position.Display();
|
||||
}
|
||||
}
|
||||
public void Display()
|
||||
{
|
||||
Position.DisplayHeader();
|
||||
for(int index=0;index<Count;index++)
|
||||
{
|
||||
Position position=this[index];
|
||||
position.Display();
|
||||
}
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,"****************************************************************************************************************************");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
70
MarketData/MarketDataLib/Generator/CMTrend/CMTPricingExceptions.cs
Executable file
70
MarketData/MarketDataLib/Generator/CMTrend/CMTPricingExceptions.cs
Executable file
@@ -0,0 +1,70 @@
|
||||
using MarketData.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MarketData.Generator.CMTrend
|
||||
{
|
||||
public class CMTPricingExceptions:List<CMTPricingException>
|
||||
{
|
||||
public NVPCollections ToNVPCollections()
|
||||
{
|
||||
NVPCollections nvpCollections=new NVPCollections();
|
||||
foreach(CMTPricingException pricingException in this)
|
||||
{
|
||||
nvpCollections.Add(pricingException.ToNVPCollection());
|
||||
}
|
||||
return nvpCollections;
|
||||
}
|
||||
public static CMTPricingExceptions FromNVPCollections(NVPCollections nvpCollections)
|
||||
{
|
||||
CMTPricingExceptions pricingExcpetions=new CMTPricingExceptions();
|
||||
foreach(NVPCollection nvpCollection in nvpCollections)
|
||||
{
|
||||
pricingExcpetions.Add(CMTPricingException.FromNVPCollection(nvpCollection));
|
||||
}
|
||||
return pricingExcpetions;
|
||||
}
|
||||
public void AddFromNVPCollection(NVPCollection nvpCollection)
|
||||
{
|
||||
Add(CMTPricingException.FromNVPCollection(nvpCollection));
|
||||
}
|
||||
}
|
||||
public class CMTPricingException
|
||||
{
|
||||
public CMTPricingException()
|
||||
{
|
||||
}
|
||||
public CMTPricingException(CMTPricingException pricingException)
|
||||
{
|
||||
this.Symbol=pricingException.Symbol;
|
||||
this.ExceptionCount=pricingException.ExceptionCount;
|
||||
}
|
||||
public CMTPricingException(String symbol,int exceptionCount)
|
||||
{
|
||||
this.Symbol=symbol;
|
||||
this.ExceptionCount=exceptionCount;
|
||||
}
|
||||
public String Symbol { get; set; }
|
||||
public int ExceptionCount { get; set; }
|
||||
public virtual NVPCollection ToNVPCollection()
|
||||
{
|
||||
NVPCollection nvpCollection=new NVPCollection();
|
||||
nvpCollection.Add(new NVP("Symbol",Symbol.ToString()));
|
||||
nvpCollection.Add(new NVP("ExceptionCount",ExceptionCount.ToString()));
|
||||
return nvpCollection;
|
||||
}
|
||||
public static CMTPricingException FromNVPCollection(NVPCollection nvpCollection)
|
||||
{
|
||||
CMTPricingException pricingException=new CMTPricingException();
|
||||
|
||||
NVPDictionary nvpDictionary=nvpCollection.ToDictionary();
|
||||
pricingException.Symbol=nvpDictionary["Symbol"].Get<String>();
|
||||
pricingException.ExceptionCount=nvpDictionary["ExceptionCount"].Get<int>();
|
||||
return pricingException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
221
MarketData/MarketDataLib/Generator/CMTrend/CMTSessionManager.cs
Executable file
221
MarketData/MarketDataLib/Generator/CMTrend/CMTSessionManager.cs
Executable file
@@ -0,0 +1,221 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using MarketData.Utils;
|
||||
using MarketData.Generator.Model;
|
||||
|
||||
namespace MarketData.Generator.CMTrend
|
||||
{
|
||||
public class CMTSessionParams
|
||||
{
|
||||
public DateTime LastUpdated { get; set; }
|
||||
public DateTime TradeDate { get; set; }
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime AnalysisDate { get; set; }
|
||||
public CMTParams CMTParams { get; set; }
|
||||
public ActivePositions ActivePositions { get; set; }
|
||||
public Positions AllPositions { get; set; }
|
||||
public CMTCandidates Candidates { get; set; }
|
||||
public CMTPricingExceptions PricingExceptions { get; set; }
|
||||
public StopLimits StopLimits { get; set; }
|
||||
public double CashBalance { get; set; }
|
||||
public double NonTradeableCash{ get; set; }
|
||||
public double InitialCash { get; set; }
|
||||
// This gets AllPositions+Positions
|
||||
public Positions GetCombinedPositions()
|
||||
{
|
||||
Positions positions=new Positions();
|
||||
foreach(Position position in AllPositions) positions.Add(position);
|
||||
foreach(Position position in ActivePositions) positions.Add(position);
|
||||
return positions;
|
||||
}
|
||||
}
|
||||
// *****************************************************************************
|
||||
public static class CMTSessionManager
|
||||
{
|
||||
public static bool SaveSession(CMTSessionParams sessionParams,String pathSessionFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(null==pathSessionFile) return false;
|
||||
pathSessionFile=GetSessionFileName(pathSessionFile);
|
||||
FileStream outStream=new FileStream(pathSessionFile,FileMode.Create);
|
||||
StreamWriter streamWriter=new StreamWriter(outStream);
|
||||
streamWriter.WriteLine("CMTSESSIONv1.00");
|
||||
streamWriter.WriteLine((new NVP("LastUpdated",sessionParams.LastUpdated.ToString())).ToString());
|
||||
streamWriter.WriteLine((new NVP("TradeDate",sessionParams.TradeDate.ToShortDateString())).ToString());
|
||||
streamWriter.WriteLine((new NVP("StartDate",sessionParams.StartDate.ToShortDateString())).ToString());
|
||||
streamWriter.WriteLine((new NVP("AnalysisDate",sessionParams.AnalysisDate.ToShortDateString())).ToString());
|
||||
streamWriter.WriteLine((new NVP("CashBalance",sessionParams.CashBalance.ToString())).ToString());
|
||||
streamWriter.WriteLine((new NVP("NonTradeableCash",sessionParams.NonTradeableCash.ToString())).ToString());
|
||||
NVPCollection configurationCollection=sessionParams.CMTParams.ToNVPCollection();
|
||||
streamWriter.WriteLine(configurationCollection.ToString());
|
||||
|
||||
NVPCollections nvpPricingExceptionCollections=sessionParams.PricingExceptions.ToNVPCollections();
|
||||
List<String> nvpPricingExceptionCollectionsList=nvpPricingExceptionCollections.ToList();
|
||||
streamWriter.WriteLine((new NVP("PricingExceptions",nvpPricingExceptionCollectionsList.Count.ToString())).ToString());
|
||||
foreach(String str in nvpPricingExceptionCollectionsList) streamWriter.WriteLine(str);
|
||||
|
||||
NVPCollections nvpCollections=sessionParams.ActivePositions.ToNVPCollections();
|
||||
List<String> nvpActivePositionsStringList=nvpCollections.ToList();
|
||||
streamWriter.WriteLine((new NVP("TotalActivePositions",nvpActivePositionsStringList.Count.ToString())).ToString());
|
||||
foreach(String str in nvpActivePositionsStringList) streamWriter.WriteLine(str);
|
||||
|
||||
NVPCollections allPositionsCollections=sessionParams.AllPositions.ToNVPCollections();
|
||||
List<String> nvpAllCollectionsStringList=allPositionsCollections.ToList();
|
||||
streamWriter.WriteLine((new NVP("TotalPositions",nvpAllCollectionsStringList.Count.ToString())).ToString());
|
||||
foreach(String str in nvpAllCollectionsStringList) streamWriter.WriteLine(str);
|
||||
|
||||
NVPCollections allCandidatesCollections=sessionParams.Candidates.ToNVPCollections();
|
||||
List<String> nvpSetupsCollectionsStringList=allCandidatesCollections.ToList();
|
||||
streamWriter.WriteLine((new NVP("TotalCandidates",nvpSetupsCollectionsStringList.Count.ToString())).ToString());
|
||||
foreach(String str in nvpSetupsCollectionsStringList) streamWriter.WriteLine(str);
|
||||
|
||||
NVPCollections allStopLimitsCollections=sessionParams.StopLimits.ToNVPCollections();
|
||||
List<String> nvpStopLimitsCollectionsStringList=allStopLimitsCollections.ToList();
|
||||
streamWriter.WriteLine((new NVP("TotalStopLimits",nvpStopLimitsCollectionsStringList.Count.ToString())).ToString());
|
||||
foreach(String str in nvpStopLimitsCollectionsStringList) streamWriter.WriteLine(str);
|
||||
|
||||
streamWriter.Flush();
|
||||
outStream.Flush();
|
||||
streamWriter.Close();
|
||||
streamWriter.Dispose();
|
||||
outStream.Close();
|
||||
outStream.Dispose();
|
||||
return true;
|
||||
}
|
||||
catch(Exception exception)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}",exception.ToString()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public static CMTSessionParams RestoreSession(String pathSessionFile)
|
||||
{
|
||||
FileStream inStream=null;
|
||||
StreamReader streamReader=null;
|
||||
try
|
||||
{
|
||||
pathSessionFile=GetSessionFileName(pathSessionFile);
|
||||
if(!SessionAvailable(pathSessionFile)) return null;
|
||||
CMTSessionParams sessionParams=new CMTSessionParams();
|
||||
inStream=new FileStream(pathSessionFile,FileMode.Open);
|
||||
streamReader=new StreamReader(inStream);
|
||||
String versionInfo=streamReader.ReadLine();
|
||||
if(!versionInfo.StartsWith("CMTSESSION")) return null;
|
||||
double version=double.Parse(Utility.BetweenString(versionInfo,"v",null));
|
||||
if(1.00!=version) return null;
|
||||
NVP lastUpdated=new NVP(streamReader.ReadLine());
|
||||
NVP tradeDate=new NVP(streamReader.ReadLine());
|
||||
NVP startDate=new NVP(streamReader.ReadLine());
|
||||
NVP analysisDate=new NVP(streamReader.ReadLine());
|
||||
NVP cashBalance=new NVP(streamReader.ReadLine());
|
||||
NVP nonTradeableCash=new NVP(streamReader.ReadLine());
|
||||
sessionParams.LastUpdated=lastUpdated.Get<DateTime>();
|
||||
sessionParams.TradeDate=tradeDate.Get<DateTime>();
|
||||
sessionParams.StartDate=startDate.Get<DateTime>();
|
||||
sessionParams.AnalysisDate=analysisDate.Get<DateTime>();
|
||||
sessionParams.CashBalance=cashBalance.Get<double>();
|
||||
sessionParams.NonTradeableCash=nonTradeableCash.Get<double>();
|
||||
NVPCollection configurationCollection=new NVPCollection(streamReader.ReadLine());
|
||||
sessionParams.CMTParams=CMTParams.FromNVPCollection(configurationCollection);
|
||||
|
||||
int totalPricingExceptions=(new NVP(streamReader.ReadLine())).Get<int>();
|
||||
sessionParams.PricingExceptions=new CMTPricingExceptions();
|
||||
for(int pricingExceptionIndex=0;pricingExceptionIndex<totalPricingExceptions;pricingExceptionIndex++)
|
||||
{
|
||||
NVPCollection nvpCollection=new NVPCollection(streamReader.ReadLine());
|
||||
sessionParams.PricingExceptions.AddFromNVPCollection(nvpCollection);
|
||||
}
|
||||
|
||||
int totalActivePositions=(new NVP(streamReader.ReadLine())).Get<int>();
|
||||
sessionParams.ActivePositions=new ActivePositions();
|
||||
for(int positionIndex=0;positionIndex<totalActivePositions;positionIndex++)
|
||||
{
|
||||
NVPCollection nvpCollection=new NVPCollection(streamReader.ReadLine());
|
||||
sessionParams.ActivePositions.AddFromNVPCollection(nvpCollection);
|
||||
}
|
||||
|
||||
int totalPositions=(new NVP(streamReader.ReadLine())).Get<int>();
|
||||
NVPCollections nvpCollections=new NVPCollections();
|
||||
for(int positionIndex=0;positionIndex<totalPositions;positionIndex++)
|
||||
{
|
||||
NVPCollection nvpCollection=new NVPCollection(streamReader.ReadLine());
|
||||
nvpCollections.Add(nvpCollection);
|
||||
}
|
||||
|
||||
int totalCandidates=(new NVP(streamReader.ReadLine())).Get<int>();
|
||||
sessionParams.Candidates=new CMTCandidates();
|
||||
for(int setupIndex=0;setupIndex<totalCandidates;setupIndex++)
|
||||
{
|
||||
NVPCollection nvpCollection=new NVPCollection(streamReader.ReadLine());
|
||||
sessionParams.Candidates.AddFromNVPCollection(nvpCollection);
|
||||
}
|
||||
|
||||
int totalStopLimits=(new NVP(streamReader.ReadLine())).Get<int>();
|
||||
sessionParams.StopLimits=new StopLimits();
|
||||
for(int stopLimitIndex=0;stopLimitIndex<totalStopLimits;stopLimitIndex++)
|
||||
{
|
||||
NVPCollection nvpCollection=new NVPCollection(streamReader.ReadLine());
|
||||
sessionParams.StopLimits.AddFromNVPCollection(nvpCollection);
|
||||
}
|
||||
|
||||
sessionParams.AllPositions=Positions.FromNVPCollections(nvpCollections);
|
||||
inStream.Close();
|
||||
inStream.Dispose();
|
||||
inStream=null;
|
||||
streamReader.Close();
|
||||
streamReader.Dispose();
|
||||
streamReader=null;
|
||||
return sessionParams;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(null!=streamReader) streamReader.Close();
|
||||
if(null!=inStream) inStream.Close();
|
||||
}
|
||||
}
|
||||
public static String GetSessionFileName(String pathSessionFile)
|
||||
{
|
||||
if(null==pathSessionFile) return null;
|
||||
String directory=Path.GetDirectoryName(pathSessionFile);
|
||||
if("".Equals(directory)) directory=Directory.GetCurrentDirectory();
|
||||
return directory+"/"+Path.GetFileNameWithoutExtension(pathSessionFile)+".TXT";
|
||||
}
|
||||
public static bool SessionAvailable(String pathSessionFile)
|
||||
{
|
||||
return IsValidSessionFile(pathSessionFile);
|
||||
}
|
||||
public static bool IsValidSessionFile(String pathSessionFile)
|
||||
{
|
||||
FileStream inStream=null;
|
||||
StreamReader streamReader=null;
|
||||
try
|
||||
{
|
||||
if(null==pathSessionFile) return false;
|
||||
pathSessionFile=GetSessionFileName(pathSessionFile);
|
||||
if(!File.Exists(pathSessionFile)) return false;
|
||||
inStream=new FileStream(pathSessionFile,FileMode.Open);
|
||||
streamReader=new StreamReader(inStream);
|
||||
String versionInfo=streamReader.ReadLine();
|
||||
if(!versionInfo.StartsWith("CMTSESSION")) return false;
|
||||
double version=double.Parse(Utility.BetweenString(versionInfo,"v",null));
|
||||
if(1.00!=version) return false;
|
||||
return true;
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(null!=streamReader) streamReader.Close();
|
||||
if(null!=inStream) inStream.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
55
MarketData/MarketDataLib/Generator/CMTrend/CMTTrendGenerator.cs
Executable file
55
MarketData/MarketDataLib/Generator/CMTrend/CMTTrendGenerator.cs
Executable file
@@ -0,0 +1,55 @@
|
||||
using MarketData.DataAccess;
|
||||
using MarketData.MarketDataModel;
|
||||
using MarketData.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MarketData.Generator.CMTrend
|
||||
{
|
||||
public class CMTTrendGenerator
|
||||
{
|
||||
private CMTTrendGenerator()
|
||||
{
|
||||
}
|
||||
public static CMTGeneratorResult GenerateCMTCandidates(DateTime tradeDate,CMTParams cmtParams,List<String> symbolsHeld)
|
||||
{
|
||||
CMTGeneratorResult cmtGeneratorResult=new CMTGeneratorResult();
|
||||
try
|
||||
{
|
||||
List<String> symbols=PricingDA.GetSymbols();
|
||||
for(int index=0;index<symbols.Count;index++)
|
||||
{
|
||||
String symbol=symbols[index];
|
||||
if(0==(index%1000)) Console.WriteLine("Processing item {0} of {1}",index+1,symbols.Count);
|
||||
CMTCandidate cmtCandidate=CMTCandidateGenerator.GenerateCandidate(symbol,tradeDate,cmtParams,symbolsHeld);
|
||||
if(null==cmtCandidate) continue;
|
||||
if(cmtCandidate.Violation) cmtGeneratorResult.CMTCandidatesWithViolation.Add(cmtCandidate);
|
||||
else cmtGeneratorResult.CMTCandidates.Add(cmtCandidate);
|
||||
}
|
||||
if(null==cmtGeneratorResult.CMTCandidates||0==cmtGeneratorResult.CMTCandidates.Count)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GenerateCMTCandidates. No candidates generated for trade date: {0}",tradeDate));
|
||||
cmtGeneratorResult.Success=true;
|
||||
return cmtGeneratorResult;
|
||||
}
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Generated {0} candidates.",cmtGeneratorResult.CMTCandidates.Count));
|
||||
cmtGeneratorResult.CMTCandidates.Sort();
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,CMTCandidate.Header());
|
||||
foreach(CMTCandidate candidate in cmtGeneratorResult.CMTCandidates) MDTrace.WriteLine(LogLevel.DEBUG,candidate.ToString());
|
||||
cmtGeneratorResult.Success=true;
|
||||
return cmtGeneratorResult;
|
||||
}
|
||||
catch(Exception exception)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
|
||||
cmtGeneratorResult.Success=false;
|
||||
cmtGeneratorResult.Messages.Add(exception.ToString());
|
||||
return cmtGeneratorResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1746
MarketData/MarketDataLib/Generator/CMTrend/CMTTrendModel..cs
Executable file
1746
MarketData/MarketDataLib/Generator/CMTrend/CMTTrendModel..cs
Executable file
File diff suppressed because it is too large
Load Diff
14
MarketData/MarketDataLib/Generator/CMTrend/CMTrendModelResult.cs
Executable file
14
MarketData/MarketDataLib/Generator/CMTrend/CMTrendModelResult.cs
Executable file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace MarketData.Generator.CMTrend
|
||||
{
|
||||
public class CMTTrendModelResult
|
||||
{
|
||||
public CMTTrendModelResult()
|
||||
{
|
||||
}
|
||||
public double CashBalance { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public String Message { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -196,8 +196,6 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
try
|
||||
{
|
||||
if(null==pathSessionFile)return 0.00;
|
||||
// pathSessionFile=pathSessionFile.ToUpper();
|
||||
// if(!pathSessionFile.EndsWith(".TXT")&&!pathSessionFile.EndsWith(".txt"))pathSessionFile+=".txt";
|
||||
if(!File.Exists(pathSessionFile))return 0.00;
|
||||
inStream =new FileStream(pathSessionFile,FileMode.Open);
|
||||
streamReader=new StreamReader(inStream);
|
||||
@@ -223,8 +221,6 @@ namespace MarketData.Generator.MGSHMomentum
|
||||
try
|
||||
{
|
||||
if(null==pathSessionFile)return false;
|
||||
// pathSessionFile=pathSessionFile.ToUpper();
|
||||
// if(!pathSessionFile.EndsWith(".TXT")&&!pathSessionFile.EndsWith(".txt"))pathSessionFile+=".txt";
|
||||
if(!File.Exists(pathSessionFile))return false;
|
||||
inStream =new FileStream(pathSessionFile,FileMode.Open);
|
||||
streamReader=new StreamReader(inStream);
|
||||
|
||||
Reference in New Issue
Block a user