Initial Commit

This commit is contained in:
2025-03-25 21:42:32 -04:00
parent c266eecfeb
commit 30c33d3cfd
247 changed files with 60107 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using MarketData.MarketDataModel;
using MarketData.Utils;
using MarketData.DataAccess;
using MarketData.Numerical;
using MarketData.Cache;
namespace MarketData.Generator.ModelGenerators
{
public class EdgeRatioGenerator
{
private EdgeRatioGenerator()
{
}
public static EdgeRatioResult CalculateEdgeRatio(String symbol,DateTime purchaseDate,double purchasePrice,DateTime asOf)
{
EdgeRatioResult edgeRatioResult=new EdgeRatioResult();
DateGenerator dateGenerator=new DateGenerator();
DateTime lastBusinesDate=dateGenerator.GetPrevBusinessDay(asOf);
Dictionary<DateTime,TrueRangeResult> trueRangeResults=new Dictionary<DateTime,TrueRangeResult>();
double[] mae=null;
double[] mfe=null;
double[] atr=null;
try
{
List<DateTime> seriesDates=dateGenerator.GenerateHistoricalDates(purchaseDate,asOf);
mae=new double[seriesDates.Count];
mfe=new double[seriesDates.Count];
atr=new double[seriesDates.Count];
double sumMAEPlusATR=0.00;
double sumMFEPlusATR=0.00;
double averageMAE=0.00;
double averageMFE=0.00;
asOf=dateGenerator.GetPrevBusinessDay(asOf);
for(int index=0;index<seriesDates.Count;index++)
{
DateTime seriesDate=seriesDates[index];
Price seriesPrice=null;
if(seriesDate.Date.Equals(lastBusinesDate.Date))seriesPrice=PricingDA.GetPrice(symbol,seriesDate); // ensure we always get a hot price for last business date, other price may originate from cache
else seriesPrice=GBPriceCache.GetInstance().GetPrice(symbol,seriesDate);
if(null==seriesPrice)
{
edgeRatioResult.Message=String.Format("Price not available for {0} on {1}",symbol,seriesDate.ToShortDateString());
return edgeRatioResult;
}
mfe[index]=(seriesPrice.High-purchasePrice)<0.00?0.00:(seriesPrice.High-purchasePrice);
mae[index]=(purchasePrice-seriesPrice.Low)<0.00?0.00:(purchasePrice-seriesPrice.Low);
atr[index]=TrueRangeGenerator.GenerateAverageTrueRange(symbol,seriesDate).AverageTrueRange;
}
for(int index=0;index<seriesDates.Count;index++)
{
sumMAEPlusATR+=(mae[index]+atr[index]);
sumMFEPlusATR+=(mfe[index]+atr[index]);
}
averageMAE=sumMAEPlusATR/(double)seriesDates.Count;
averageMFE=sumMFEPlusATR/(double)seriesDates.Count;
edgeRatioResult.EdgeRatio=averageMFE/averageMAE;
edgeRatioResult.Success=true;
edgeRatioResult.Message=String.Format("EdgeRatio for {0} purchased on {1} @ {2} from {3} -> {4}",symbol,purchaseDate.ToShortDateString(),Utility.FormatCurrency(purchasePrice),purchaseDate.ToShortDateString(),asOf.ToShortDateString());
return edgeRatioResult;
}
catch(Exception exception)
{
edgeRatioResult.Message=exception.ToString();
return edgeRatioResult;
}
}
}
public class EdgeRatioResult
{
public EdgeRatioResult()
{
Success=false;
EdgeRatio=double.NaN;
Message=null;
}
public double EdgeRatio{get;set;}
public bool Success{get;set;}
public String Message{get;set;}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using MarketData.MarketDataModel;
using MarketData.Utils;
using MarketData.DataAccess;
using MarketData.Numerical;
namespace MarketData.Generator.ModelGenerators
{
public class TrueRangeGenerator
{
private TrueRangeGenerator()
{
}
// Prices : Where most recent price is at lowest index
public static TrueRangeResult GenerateAverageTrueRange(String symbol, DateTime startDate, int atrDays = 14)
{
Prices prices = PricingDA.GetPrices(symbol, startDate, atrDays + 1);
if (null == prices || prices.Count < 2 || 0 == prices[0].Close) return null;
double[] values = new double[prices.Count - 1];
for (int index = 0; index < prices.Count - 1; index++)
{
Price price = prices[index];
Price prevPrice = prices[index + 1];
double levelA = price.High - price.Low;
double levelB = Math.Abs(price.High - prevPrice.Close);
double levelC = Math.Abs(price.Low - prevPrice.Close);
values[index] = Math.Max(levelA, levelB);
values[index] = Math.Max(values[index], levelC);
}
double averageTrueRange = Numerics.Mean(ref values);
return new TrueRangeResult(averageTrueRange, (averageTrueRange / prices[0].Close) * 2.00);
}
}
public class TrueRangeResult
{
public TrueRangeResult()
{
}
public TrueRangeResult(double averageTrueRange,double shortTermVolatility)
{
AverageTrueRange=averageTrueRange;
ShortTermVolatility=shortTermVolatility;
}
public double AverageTrueRange{get;set;}
public double ShortTermVolatility{get;set;}
}
}

View File

@@ -0,0 +1,50 @@
using MarketData.Generator.MovingAverage;
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.ModelGenerators
{
// Calculates Volatility as 3x Average True Range
public class VolatilityGenerator
{
public static double CalculateVolatility(String symbol,DateTime date,int movingAverageDays=10)
{
return CalculateVolatility(symbol,date,movingAverageDays,3.00);
}
public static double CalculateVolatility(String symbol,DateTime date,int movingAverageDays,double atrMultiplier)
{
double volatility=double.NaN;
DateGenerator dateGenerator=new DateGenerator();
Dictionary<DateTime,double> trueRangeCollectionByDate=new Dictionary<DateTime,double>();
List<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(date,(movingAverageDays+1)*2); // most recent date in lowest index, we need to generate (items+1)
for(int dateIndex=0;dateIndex<historicalDates.Count;dateIndex++)
{
DateTime historicalDate=historicalDates[dateIndex];
TrueRangeResult trueRangeResult=TrueRangeGenerator.GenerateAverageTrueRange(symbol,historicalDate);
if(null==trueRangeResult)continue;
trueRangeCollectionByDate.Add(historicalDate,trueRangeResult.AverageTrueRange);
}
if(movingAverageDays>trueRangeCollectionByDate.Count) return volatility;
historicalDates=new List<DateTime>(trueRangeCollectionByDate.Keys.OrderByDescending(x=>x.Date));
Prices prices=new Prices();
foreach(DateTime historicalDate in historicalDates)
{
Price price=new Price();
price.Symbol=symbol;
price.Date=historicalDate;
price.Close=trueRangeCollectionByDate[historicalDate];
prices.Add(price);
}
DMAPrices emaPrices=MovingAverageGenerator.GenerateExponentialMovingAverage(prices,movingAverageDays);
if(null==emaPrices||0==emaPrices.Count)return volatility;
volatility=emaPrices[0].AVGPrice*atrMultiplier;
return volatility;
}
}
}