Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bffff6c296 | |||
| faded8cd55 | |||
| 09525546bf |
@@ -1,36 +1,66 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
using MarketData.MarketDataModel;
|
|
||||||
using MarketData.DataAccess;
|
|
||||||
using MarketData.Utils;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using MarketData.MarketDataModel;
|
||||||
|
using MarketData.Utils;
|
||||||
using MarketData.Helper;
|
using MarketData.Helper;
|
||||||
using MarketData.Numerical;
|
using MarketData.Numerical;
|
||||||
using System.Threading;
|
using MarketData.DataAccess;
|
||||||
|
|
||||||
|
|
||||||
// This cache is mainly used by the models. It is a short lived cache that gets cleared out every 2 minutes.
|
|
||||||
// This cache will attempt to load a price from the database if it is found in the cache.
|
|
||||||
namespace MarketData.Cache
|
namespace MarketData.Cache
|
||||||
{
|
{
|
||||||
public class GBPriceCache
|
public interface IPricingDataAccess
|
||||||
|
{
|
||||||
|
Price GetPrice(string symbol, DateTime date);
|
||||||
|
Prices GetPrices(string symbol, DateTime maxDate, DateTime minDate);
|
||||||
|
DateTime GetLatestDateOnOrBefore(string symbol, DateTime date);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class RealPricingDA : IPricingDataAccess
|
||||||
|
{
|
||||||
|
public Price GetPrice(string symbol, DateTime date) => PricingDA.GetPrice(symbol, date);
|
||||||
|
public Prices GetPrices(string symbol, DateTime maxDate, DateTime minDate) => PricingDA.GetPrices(symbol, maxDate, minDate);
|
||||||
|
public DateTime GetLatestDateOnOrBefore(string symbol, DateTime date) => PricingDA.GetLatestDateOnOrBefore(symbol, date);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CacheSnapshot
|
||||||
|
{
|
||||||
|
public Dictionary<String, PricesByDate> PriceCache { get; }
|
||||||
|
public Dictionary<String, Price> RealTimePriceCache { get; }
|
||||||
|
public Dictionary<String, bool> NullCache { get; }
|
||||||
|
|
||||||
|
public CacheSnapshot(
|
||||||
|
Dictionary<String, PricesByDate> priceCache,
|
||||||
|
Dictionary<String, Price> realTimePriceCache,
|
||||||
|
Dictionary<String, bool> nullCache)
|
||||||
|
{
|
||||||
|
PriceCache = priceCache;
|
||||||
|
RealTimePriceCache = realTimePriceCache;
|
||||||
|
NullCache = nullCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GBPriceCache : IDisposable
|
||||||
{
|
{
|
||||||
private Thread cacheMonitorThread = null;
|
private Thread cacheMonitorThread = null;
|
||||||
private volatile bool threadRun = true;
|
private volatile bool threadRun = true;
|
||||||
private Object thisLock = new Object();
|
private Object thisLock = new Object();
|
||||||
private Dictionary<String,PricesByDate> priceCache=new Dictionary<String,PricesByDate>(); // the main cache
|
|
||||||
private Dictionary<String,Price> realTimePriceCache=new Dictionary<String,Price>(); // short lived cache of realtime prices gets cleared out every cacheRefreshAfter(ms)
|
private CacheSnapshot snapshot;
|
||||||
private Dictionary<String,bool> nullCache=new Dictionary<String,bool>();
|
|
||||||
private DateGenerator dateGenerator = new DateGenerator();
|
private DateGenerator dateGenerator = new DateGenerator();
|
||||||
private static GBPriceCache priceCacheInstance = null;
|
private static GBPriceCache priceCacheInstance = null;
|
||||||
private int cacheRefreshAfter=120000; // the cache will be cleaned up after 2 minutes
|
private int cacheRefreshAfter = 120000; // 2 minutes
|
||||||
|
private SemaphoreSlim fetchSemaphore = new SemaphoreSlim(8); // max 8 concurrent DB fetches
|
||||||
|
public IPricingDataAccess PricingDataAccess { get; set; } = new RealPricingDA();
|
||||||
|
|
||||||
protected GBPriceCache()
|
protected GBPriceCache()
|
||||||
{
|
{
|
||||||
|
snapshot = new CacheSnapshot(new Dictionary<String, PricesByDate>(), new Dictionary<String, Price>(), new Dictionary<String, bool>());
|
||||||
cacheMonitorThread = new Thread(new ThreadStart(ThreadProc));
|
cacheMonitorThread = new Thread(new ThreadStart(ThreadProc));
|
||||||
cacheMonitorThread.Start();
|
cacheMonitorThread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GBPriceCache GetInstance()
|
public static GBPriceCache GetInstance()
|
||||||
{
|
{
|
||||||
lock (typeof(GBPriceCache))
|
lock (typeof(GBPriceCache))
|
||||||
@@ -42,202 +72,233 @@ namespace MarketData.Cache
|
|||||||
return priceCacheInstance;
|
return priceCacheInstance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
priceCache=new Dictionary<String,PricesByDate>();
|
snapshot = new CacheSnapshot(new Dictionary<String, PricesByDate>(), new Dictionary<String, Price>(), new Dictionary<String, bool>());
|
||||||
realTimePriceCache=new Dictionary<String,Price>();
|
|
||||||
nullCache=new Dictionary<String,bool>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
if(null==priceCacheInstance || false==threadRun)return;
|
if (null == priceCacheInstance || !threadRun) return;
|
||||||
threadRun = false;
|
threadRun = false;
|
||||||
if (null != cacheMonitorThread)
|
if (null != cacheMonitorThread)
|
||||||
{
|
{
|
||||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[GBPriceCache:Dispose]Thread state is '{0}'. Joining main thread...",Utility.ThreadStateToString(cacheMonitorThread)));
|
MDTrace.WriteLine(LogLevel.DEBUG, "[GBPriceCache:Dispose] Joining monitor thread...");
|
||||||
cacheMonitorThread.Join(5000);
|
cacheMonitorThread.Join(5000);
|
||||||
this.cacheMonitorThread=null;
|
cacheMonitorThread = null;
|
||||||
}
|
}
|
||||||
MDTrace.WriteLine(LogLevel.DEBUG,"[GBPriceCache:Dispose] End.");
|
|
||||||
priceCacheInstance = null;
|
priceCacheInstance = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearCacheOnOrBefore(DateTime onOrBeforeDate, bool collect = false)
|
public void ClearCacheOnOrBefore(DateTime onOrBeforeDate, bool collect = false)
|
||||||
{
|
{
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
MDTrace.WriteLine(LogLevel.DEBUG,"Clearing GBPriceCache cache.");
|
Dictionary<String, PricesByDate> newPriceCache = new Dictionary<String, PricesByDate>();
|
||||||
List<String> symbols=new List<String>(priceCache.Keys);
|
foreach (KeyValuePair<String, PricesByDate> entry in snapshot.PriceCache)
|
||||||
foreach(String symbol in symbols)
|
|
||||||
{
|
{
|
||||||
PricesByDate pricesByDate=priceCache[symbol];
|
String symbol = entry.Key;
|
||||||
List<DateTime> symbolDates=new List<DateTime>(pricesByDate.Keys);
|
PricesByDate filteredPrices = new PricesByDate();
|
||||||
foreach(DateTime symbolDate in symbolDates)
|
PricesByDate existingPrices = entry.Value;
|
||||||
|
foreach (KeyValuePair<DateTime, Price> kvp in existingPrices)
|
||||||
{
|
{
|
||||||
if(symbolDate<onOrBeforeDate) pricesByDate.Remove(symbolDate);
|
if (kvp.Key >= onOrBeforeDate)
|
||||||
|
{
|
||||||
|
filteredPrices.Add(kvp.Key, kvp.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MDTrace.WriteLine(LogLevel.DEBUG,"Calling garbage collector...");
|
if (filteredPrices.Count > 0)
|
||||||
|
{
|
||||||
|
newPriceCache.Add(symbol, filteredPrices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UpdateSnapshot(newPriceCache, snapshot.RealTimePriceCache, snapshot.NullCache);
|
||||||
if (collect) GC.Collect();
|
if (collect) GC.Collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Price GetPriceOrLatestAvailable(String symbol, DateTime date)
|
public Price GetPriceOrLatestAvailable(String symbol, DateTime date)
|
||||||
{
|
|
||||||
lock(thisLock)
|
|
||||||
{
|
{
|
||||||
Price price = GetPrice(symbol, date);
|
Price price = GetPrice(symbol, date);
|
||||||
if (null != price) return price;
|
if (null != price) return price;
|
||||||
DateTime latestPricingDate=PricingDA.GetLatestDateOnOrBefore(symbol,date);
|
DateTime latestPricingDate = PricingDataAccess.GetLatestDateOnOrBefore(symbol, date);
|
||||||
price = GetPrice(symbol, latestPricingDate);
|
price = GetPrice(symbol, latestPricingDate);
|
||||||
if (null != price) return price;
|
if (null != price) return price;
|
||||||
price=PricingDA.GetPrice(symbol,latestPricingDate);
|
fetchSemaphore.Wait();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
price = PricingDataAccess.GetPrice(symbol, latestPricingDate);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
fetchSemaphore.Release();
|
||||||
|
}
|
||||||
if (null !=price) AddPrice(price);
|
if (null !=price) AddPrice(price);
|
||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
public Price GetRealtimePrice(String symbol)
|
public Price GetRealtimePrice(String symbol)
|
||||||
{
|
{
|
||||||
if(realTimePriceCache.ContainsKey(symbol)) return realTimePriceCache[symbol];
|
if (snapshot.RealTimePriceCache.ContainsKey(symbol))
|
||||||
|
{
|
||||||
|
return snapshot.RealTimePriceCache[symbol];
|
||||||
|
}
|
||||||
|
|
||||||
Price price = MarketDataHelper.GetLatestPrice(symbol);
|
Price price = MarketDataHelper.GetLatestPrice(symbol);
|
||||||
if (null != price)
|
if (null != price)
|
||||||
{
|
{
|
||||||
realTimePriceCache.Add(symbol,price);
|
Dictionary<String, Price> newRealtime = new Dictionary<String, Price>(snapshot.RealTimePriceCache);
|
||||||
|
newRealtime.Add(symbol, price);
|
||||||
|
UpdateSnapshot(snapshot.PriceCache, newRealtime, snapshot.NullCache);
|
||||||
}
|
}
|
||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Price GetPrice(String symbol, DateTime date)
|
public Price GetPrice(String symbol, DateTime date)
|
||||||
{
|
|
||||||
lock(thisLock)
|
|
||||||
{
|
{
|
||||||
date = date.Date;
|
date = date.Date;
|
||||||
if (!ContainsPrice(symbol, date))
|
if (!ContainsPrice(symbol, date))
|
||||||
{
|
{
|
||||||
String key = symbol + Utility.DateTimeToStringMMHDDHYYYY(date);
|
String key = symbol + Utility.DateTimeToStringMMHDDHYYYY(date);
|
||||||
if(nullCache.ContainsKey(key)) return null;
|
if (snapshot.NullCache.ContainsKey(key))
|
||||||
Price price=PricingDA.GetPrice(symbol,date);
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
fetchSemaphore.Wait();
|
||||||
|
Price price;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
price = PricingDataAccess.GetPrice(symbol, date);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
fetchSemaphore.Release();
|
||||||
|
}
|
||||||
if (null ==price)
|
if (null ==price)
|
||||||
{
|
{
|
||||||
nullCache.Add(key,true);
|
Dictionary<String, bool> newNullCache = new Dictionary<String, bool>(snapshot.NullCache);
|
||||||
return price;
|
newNullCache.Add(key, true);
|
||||||
|
UpdateSnapshot(snapshot.PriceCache, snapshot.RealTimePriceCache, newNullCache);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddPrice(price);
|
AddPrice(price);
|
||||||
}
|
}
|
||||||
if(!priceCache.ContainsKey(symbol)) return null;
|
if (!snapshot.PriceCache.ContainsKey(symbol)) return null;
|
||||||
PricesByDate pricesByDate=priceCache[symbol];
|
PricesByDate pricesByDate = snapshot.PriceCache[symbol];
|
||||||
if(!pricesByDate.ContainsKey(date.Date)) return null;
|
if (!pricesByDate.ContainsKey(date)) return null;
|
||||||
return pricesByDate[date];
|
return pricesByDate[date];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public Prices GetPrices(String symbol, DateTime earlierDate, DateTime laterDate)
|
public Prices GetPrices(String symbol, DateTime earlierDate, DateTime laterDate)
|
||||||
{
|
{
|
||||||
DateGenerator dateGenerator = new DateGenerator();
|
DateGenerator localDateGenerator = new DateGenerator();
|
||||||
|
|
||||||
if (laterDate < earlierDate)
|
if (laterDate < earlierDate)
|
||||||
{
|
{
|
||||||
DateTime tempDate = earlierDate;
|
DateTime tempDate = earlierDate;
|
||||||
earlierDate = laterDate;
|
earlierDate = laterDate;
|
||||||
laterDate = tempDate;
|
laterDate = tempDate;
|
||||||
}
|
}
|
||||||
List<DateTime> datesList = dateGenerator.GenerateHistoricalDates(earlierDate, laterDate);
|
List<DateTime> datesList = localDateGenerator.GenerateHistoricalDates(earlierDate, laterDate);
|
||||||
datesList = datesList.Where(x => x >= earlierDate).ToList();
|
datesList = datesList.Where(x => x >= earlierDate).ToList();
|
||||||
return GetPrices(symbol, laterDate, datesList.Count);
|
return GetPrices(symbol, laterDate, datesList.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The most recent price is returned at the lowest index
|
|
||||||
public Prices GetPrices(String symbol, DateTime startDate, int dayCount)
|
public Prices GetPrices(String symbol, DateTime startDate, int dayCount)
|
||||||
{
|
|
||||||
lock(thisLock)
|
|
||||||
{
|
{
|
||||||
List<DateTime> historicalDates = dateGenerator.GenerateHistoricalDates(startDate, dayCount + 60);
|
List<DateTime> historicalDates = dateGenerator.GenerateHistoricalDates(startDate, dayCount + 60);
|
||||||
Prices prices=null;
|
List<DateTime> missingDates = new List<DateTime>();
|
||||||
List<DateTime> missingDates=null;
|
|
||||||
foreach (DateTime historicalDate in historicalDates)
|
foreach (DateTime historicalDate in historicalDates)
|
||||||
{
|
{
|
||||||
if (!ContainsPrice(symbol, historicalDate))
|
if (!ContainsPrice(symbol, historicalDate))
|
||||||
{
|
{
|
||||||
String key = symbol + Utility.DateTimeToStringMMHDDHYYYY(historicalDate);
|
String key = symbol + Utility.DateTimeToStringMMHDDHYYYY(historicalDate);
|
||||||
if(nullCache.ContainsKey(key)) continue;
|
if (!snapshot.NullCache.ContainsKey(key))
|
||||||
if(null==missingDates)missingDates=new List<DateTime>();
|
{
|
||||||
missingDates.Add(historicalDate);
|
missingDates.Add(historicalDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(null!=missingDates)
|
}
|
||||||
|
if (missingDates.Count > 0)
|
||||||
{
|
{
|
||||||
DateTime minDate=(from DateTime date in missingDates select date).Min();
|
DateTime minDate = missingDates.Min();
|
||||||
DateTime maxDate=(from DateTime date in missingDates select date).Max();
|
DateTime maxDate = missingDates.Max();
|
||||||
prices=PricingDA.GetPrices(symbol,maxDate,minDate);
|
|
||||||
foreach(Price price in prices) AddPrice(price);
|
fetchSemaphore.Wait();
|
||||||
prices=new Prices();
|
Prices loadedPrices;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
loadedPrices = PricingDataAccess.GetPrices(symbol, maxDate, minDate);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
fetchSemaphore.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Price price in loadedPrices)
|
||||||
|
{
|
||||||
|
AddPrice(price);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Prices prices = new Prices();
|
||||||
foreach (DateTime historicalDate in historicalDates)
|
foreach (DateTime historicalDate in historicalDates)
|
||||||
{
|
{
|
||||||
if(!ContainsPrice(symbol,historicalDate))
|
if (!snapshot.PriceCache.ContainsKey(symbol)) continue;
|
||||||
{
|
PricesByDate pricesByDate = snapshot.PriceCache[symbol];
|
||||||
String key=symbol+Utility.DateTimeToStringMMHDDHYYYY(historicalDate);
|
if (!pricesByDate.ContainsKey(historicalDate)) continue;
|
||||||
if(!nullCache.ContainsKey(key)) nullCache.Add(key,true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(!priceCache.ContainsKey(symbol)) continue;
|
|
||||||
PricesByDate pricesByDate=priceCache[symbol];
|
|
||||||
if(!pricesByDate.ContainsKey(historicalDate.Date)) continue;
|
|
||||||
prices.Add(pricesByDate[historicalDate]);
|
prices.Add(pricesByDate[historicalDate]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Price> ordered = prices.OrderByDescending(x => x.Date).ToList();
|
||||||
|
return new Prices(ordered.Take(dayCount).ToList());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
prices=new Prices();
|
|
||||||
foreach(DateTime historicalDate in historicalDates)
|
|
||||||
{
|
|
||||||
if(!priceCache.ContainsKey(symbol)) continue;
|
|
||||||
if(!priceCache[symbol].ContainsKey(historicalDate.Date))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
prices.Add((priceCache[symbol])[historicalDate]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Prices(prices.OrderByDescending(x => x.Date).ToList().Take(dayCount).ToList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void AddPrice(Price price)
|
private void AddPrice(Price price)
|
||||||
{
|
{
|
||||||
|
if (null == price) return;
|
||||||
|
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
if(null==price) return;
|
PricesByDate pricesByDate;
|
||||||
PricesByDate pricesByDate=null;
|
if (!snapshot.PriceCache.ContainsKey(price.Symbol))
|
||||||
if(!priceCache.ContainsKey(price.Symbol))
|
|
||||||
{
|
{
|
||||||
pricesByDate = new PricesByDate();
|
pricesByDate = new PricesByDate();
|
||||||
pricesByDate.Add(price.Date, price);
|
pricesByDate.Add(price.Date, price);
|
||||||
priceCache.Add(price.Symbol,pricesByDate);
|
Dictionary<String, PricesByDate> newCache = new Dictionary<String, PricesByDate>(snapshot.PriceCache);
|
||||||
|
newCache.Add(price.Symbol, pricesByDate);
|
||||||
|
UpdateSnapshot(newCache, snapshot.RealTimePriceCache, snapshot.NullCache);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pricesByDate=priceCache[price.Symbol];
|
pricesByDate = snapshot.PriceCache[price.Symbol];
|
||||||
if(pricesByDate.ContainsKey(price.Date.Date)) return;
|
if (!pricesByDate.ContainsKey(price.Date))
|
||||||
pricesByDate.Add(price.Date.Date,price);
|
{
|
||||||
|
pricesByDate.Add(price.Date, price);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool ContainsPrice(String symbol, DateTime date)
|
public bool ContainsPrice(String symbol, DateTime date)
|
||||||
{
|
{
|
||||||
if(!priceCache.ContainsKey(symbol)) return false;
|
if (!snapshot.PriceCache.ContainsKey(symbol)) return false;
|
||||||
PricesByDate pricesByDate=priceCache[symbol];
|
PricesByDate pricesByDate = snapshot.PriceCache[symbol];
|
||||||
if(!pricesByDate.ContainsKey(date.Date)) return false;
|
return pricesByDate.ContainsKey(date);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThreadProc()
|
private void ThreadProc()
|
||||||
{
|
{
|
||||||
int quantums = 0;
|
int quantums = 0;
|
||||||
int quantumInterval = 1000;
|
int quantumInterval = 1000;
|
||||||
|
|
||||||
while (threadRun)
|
while (threadRun)
|
||||||
{
|
{
|
||||||
Thread.Sleep(quantumInterval);
|
Thread.Sleep(quantumInterval);
|
||||||
@@ -248,13 +309,15 @@ namespace MarketData.Cache
|
|||||||
quantums = 0;
|
quantums = 0;
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
realTimePriceCache.Clear();
|
UpdateSnapshot(snapshot.PriceCache, new Dictionary<String, Price>(), snapshot.NullCache);
|
||||||
MDTrace.WriteLine(LogLevel.DEBUG,"Clearing GBPriceCache price cache.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MDTrace.WriteLine(LogLevel.DEBUG,"[GBPriceCache:ThreadProc]Thread ended.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateSnapshot(Dictionary<String, PricesByDate> newPriceCache,Dictionary<String, Price> newRealtimePriceCache, Dictionary<String, bool> newNullCache)
|
||||||
|
{
|
||||||
|
snapshot = new CacheSnapshot(newPriceCache, newRealtimePriceCache, newNullCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
using System;
|
using MarketData.MarketDataModel;
|
||||||
using System.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using MarketData.MarketDataModel;
|
|
||||||
using MarketData.Utils;
|
using MarketData.Utils;
|
||||||
using MarketData.DataAccess;
|
using MarketData.DataAccess;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
// This cache is mainly used by gainloss generator. This cache is intended to be front loaded and then used.
|
|
||||||
// This cache will not attempt to load an item that is not found. It does have a Refresh() that will reload only the most recent pricing data from the database in order to
|
|
||||||
// maintain the most updated pricing.
|
|
||||||
namespace MarketData.Cache
|
namespace MarketData.Cache
|
||||||
{
|
{
|
||||||
public class LocalPriceCache
|
public class LocalPriceCache
|
||||||
{
|
{
|
||||||
private Dictionary<String,PricesByDate> priceCache=new Dictionary<String,PricesByDate>();
|
private Dictionary<string, PricesByDate> priceCache = new Dictionary<string, PricesByDate>();
|
||||||
private static LocalPriceCache instance = null;
|
private static LocalPriceCache instance = null;
|
||||||
private DateTime latestDate = Utility.Epoch;
|
private DateTime latestDate = Utility.Epoch;
|
||||||
private Thread cacheMonitorThread = null;
|
private Thread cacheMonitorThread = null;
|
||||||
private volatile bool threadRun = true;
|
private volatile bool threadRun = true;
|
||||||
private int cacheCycle = 300000;
|
private int cacheCycle = 300000;
|
||||||
private Object thisLock=new Object();
|
private object thisLock = new object();
|
||||||
|
private object fetchLock = new object();
|
||||||
|
|
||||||
private LocalPriceCache()
|
private LocalPriceCache()
|
||||||
{
|
{
|
||||||
@@ -31,33 +31,38 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
priceCache=new Dictionary<String,PricesByDate>();
|
priceCache = new Dictionary<string, PricesByDate>();
|
||||||
RefreshLatestDate();
|
RefreshLatestDate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
Thread threadToJoin = null;
|
||||||
|
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
if(null==instance || false==threadRun)return;
|
if (instance == null || !threadRun) return;
|
||||||
threadRun = false;
|
threadRun = false;
|
||||||
if(null!=cacheMonitorThread)
|
threadToJoin = cacheMonitorThread;
|
||||||
{
|
cacheMonitorThread = null;
|
||||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LocalPriceCache:Dispose]Thread state is '{0}'. Joining main thread...",Utility.ThreadStateToString(cacheMonitorThread)));
|
|
||||||
cacheMonitorThread.Join(5000);
|
|
||||||
this.cacheMonitorThread=null;
|
|
||||||
}
|
|
||||||
MDTrace.WriteLine(LogLevel.DEBUG,"[LocalPriceCache:Dispose] End");
|
|
||||||
instance = null;
|
instance = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (threadToJoin != null)
|
||||||
|
{
|
||||||
|
MDTrace.WriteLine(LogLevel.DEBUG, $"[LocalPriceCache:Dispose] Thread state is '{Utility.ThreadStateToString(threadToJoin)}'. Joining...");
|
||||||
|
threadToJoin.Join(5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
MDTrace.WriteLine(LogLevel.DEBUG, "[LocalPriceCache:Dispose] End");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LocalPriceCache GetInstance()
|
public static LocalPriceCache GetInstance()
|
||||||
{
|
{
|
||||||
lock (typeof(LocalPriceCache))
|
lock (typeof(LocalPriceCache))
|
||||||
{
|
{
|
||||||
if(null==instance)
|
if (instance == null)
|
||||||
{
|
{
|
||||||
instance = new LocalPriceCache();
|
instance = new LocalPriceCache();
|
||||||
}
|
}
|
||||||
@@ -67,7 +72,7 @@ namespace MarketData.Cache
|
|||||||
|
|
||||||
public void RefreshLatestDate()
|
public void RefreshLatestDate()
|
||||||
{
|
{
|
||||||
lock(typeof(LocalPriceCache))
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
latestDate = PricingDA.GetLatestDate();
|
latestDate = PricingDA.GetLatestDate();
|
||||||
}
|
}
|
||||||
@@ -75,7 +80,7 @@ namespace MarketData.Cache
|
|||||||
|
|
||||||
public DateTime GetLatestDate()
|
public DateTime GetLatestDate()
|
||||||
{
|
{
|
||||||
lock(typeof(LocalPriceCache))
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
if (Utility.IsEpoch(latestDate))
|
if (Utility.IsEpoch(latestDate))
|
||||||
{
|
{
|
||||||
@@ -87,65 +92,118 @@ namespace MarketData.Cache
|
|||||||
|
|
||||||
public void Refresh()
|
public void Refresh()
|
||||||
{
|
{
|
||||||
lock(typeof(LocalPriceCache))
|
List<string> symbols;
|
||||||
|
Dictionary<string, DateTime> currentMaxDates;
|
||||||
|
|
||||||
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
List<String> symbols=new List<String>(priceCache.Keys);
|
symbols = priceCache.Keys.ToList();
|
||||||
Dictionary<String, DateTime> maxDbDates = PricingDA.GetLatestDates(symbols);
|
currentMaxDates = priceCache.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.MaxDate);
|
||||||
RefreshLatestDate();
|
}
|
||||||
foreach(String symbol in symbols)
|
|
||||||
|
if (symbols.Count == 0) return;
|
||||||
|
|
||||||
|
ConcurrentDictionary<string, PricesByDate> fullReloads = new ConcurrentDictionary<string, PricesByDate>();
|
||||||
|
ConcurrentDictionary<string, Price> singleUpdates = new ConcurrentDictionary<string, Price>();
|
||||||
|
DateTime latestDateFromDb;
|
||||||
|
|
||||||
|
lock (fetchLock)
|
||||||
{
|
{
|
||||||
PricesByDate symbolPrices=priceCache[symbol];
|
Dictionary<string, DateTime> maxDbDates = PricingDA.GetLatestDates(symbols);
|
||||||
DateTime maxDate=symbolPrices.MaxDate; // get the latest date in the cache
|
latestDateFromDb = PricingDA.GetLatestDate();
|
||||||
if(maxDbDates.ContainsKey(symbol) && !maxDbDates[symbol].Date.Equals(maxDate.Date)) // if the cache date and the database date are not equal then reload the cache
|
|
||||||
|
Parallel.ForEach(symbols, new ParallelOptions { MaxDegreeOfParallelism = 8 }, symbol =>
|
||||||
{
|
{
|
||||||
MDTrace.WriteLine(LogLevel.DEBUG,$"Cache date and Database date for {symbol} are not equal, reloading cache. Cache Date:{maxDate.ToShortDateString()} Database Date:{maxDbDates[symbol].Date.ToShortDateString()}");
|
if (!currentMaxDates.TryGetValue(symbol, out var cachedMax)) return;
|
||||||
Prices prices=PricingDA.GetPrices(symbol,symbolPrices.MinDate); // reload the prices for this symbol using the current minDate in the cache as a lower boundary
|
|
||||||
if(null==prices)continue; // if we can't load any prices for symbol then just continue
|
if (maxDbDates.TryGetValue(symbol, out var dbMax) && dbMax.Date != cachedMax.Date)
|
||||||
priceCache.Remove(symbol); // remove the pricing entries in the price cache for the symbol
|
{
|
||||||
priceCache.Add(symbol,prices.GetPricesByDate()); // reload the cache
|
Prices prices = PricingDA.GetPrices(symbol, cachedMax);
|
||||||
|
if (prices != null) fullReloads[symbol] = prices.GetPricesByDate();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MDTrace.WriteLine(LogLevel.DEBUG,$"[LocalPriceCache] Fetching latest price from database for {symbol} on {maxDate.ToShortDateString()}");
|
Price price = PricingDA.GetPrice(symbol, cachedMax);
|
||||||
Price price=PricingDA.GetPrice(symbol,maxDate); // the max date from the cache equals the max date from the database so just reload the latest price from the database
|
if (price != null) singleUpdates[symbol] = price;
|
||||||
if(null==price)continue; // if no latest price then just continue
|
|
||||||
symbolPrices.Remove(maxDate); // remove the current price associated with the max date
|
|
||||||
symbolPrices.Add(maxDate,price); // reload the latest price for maxDate(symbol) into the cache
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (thisLock)
|
||||||
|
{
|
||||||
|
latestDate = latestDateFromDb;
|
||||||
|
|
||||||
|
foreach (var kvp in fullReloads)
|
||||||
|
{
|
||||||
|
if (priceCache.TryGetValue(kvp.Key, out PricesByDate existing) && existing.MaxDate == currentMaxDates[kvp.Key])
|
||||||
|
{
|
||||||
|
priceCache[kvp.Key] = kvp.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var kvp in singleUpdates)
|
||||||
|
{
|
||||||
|
if (priceCache.TryGetValue(kvp.Key, out PricesByDate pricesByDate) && pricesByDate.MaxDate == currentMaxDates[kvp.Key])
|
||||||
|
{
|
||||||
|
// Remove the old price (if any) and add the new price properly
|
||||||
|
if (pricesByDate.ContainsKey(kvp.Value.Date))
|
||||||
|
pricesByDate.Remove(kvp.Value.Date);
|
||||||
|
pricesByDate.Add(kvp.Value.Date, kvp.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This version of Add(PortfolioTrades) will account for adding multiple lots at different times. So instead of just checking for the existance of the symbol in the cache
|
MDTrace.WriteLine(LogLevel.DEBUG, $"Full reloads: {fullReloads.Count}, Single updates: {singleUpdates.Count}");
|
||||||
// we look to see if the symbol is in the cache and what dates are available. If the date range specified in the trade are not available then we load those date ranges.
|
}
|
||||||
// This is a brute force approach always maintaining the gap between successive TradeDates in th.e portfolio trades and the maximum date for the symbol in the database.
|
|
||||||
// So while it is inefficient in terms of memory usage it alleviates the need for figuring out contiguous price sections
|
|
||||||
public void Add(PortfolioTrades portfolioTrades)
|
public void Add(PortfolioTrades portfolioTrades)
|
||||||
{
|
{
|
||||||
lock(typeof(LocalPriceCache))
|
List<string> symbols = portfolioTrades.Symbols;
|
||||||
|
Dictionary<string, DateTime> minTradeDates = symbols.ToDictionary(sym => sym, sym => portfolioTrades.GetMinTradeDate(sym));
|
||||||
|
|
||||||
|
Dictionary<string, DateTime> minCacheDates;
|
||||||
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
Profiler profiler=new Profiler();
|
minCacheDates = symbols.ToDictionary(sym => sym, sym => priceCache.ContainsKey(sym) ? priceCache[sym].MinDate : DateTime.MaxValue);
|
||||||
profiler.Start();
|
|
||||||
List<String> symbols=portfolioTrades.Symbols;
|
|
||||||
foreach(String symbol in symbols)
|
|
||||||
{
|
|
||||||
DateTime minPortfolioTradeDate=portfolioTrades.GetMinTradeDate(symbol);
|
|
||||||
if(!ContainsSymbol(symbol))
|
|
||||||
{
|
|
||||||
Prices prices=PricingDA.GetPrices(symbol,minPortfolioTradeDate);
|
|
||||||
if(null==prices)continue;
|
|
||||||
foreach(Price price in prices)Add(price);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
ConcurrentDictionary<string, Prices> fetchedPrices = new ConcurrentDictionary<string, Prices>();
|
||||||
|
|
||||||
|
Parallel.ForEach(symbols, new ParallelOptions { MaxDegreeOfParallelism = 8 }, symbol =>
|
||||||
{
|
{
|
||||||
DateTime minCacheDate=GetMinCacheDate(symbol);
|
DateTime minTradeDate = minTradeDates[symbol];
|
||||||
if(minPortfolioTradeDate<minCacheDate)
|
DateTime minCacheDate = minCacheDates[symbol];
|
||||||
|
Prices prices = null;
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Prices prices=PricingDA.GetPrices(symbol,minCacheDate,minPortfolioTradeDate); // Fill the gap by retrieving prices starting at minCache date and going back in time to minPortfolioTradeDate
|
if (minCacheDate == DateTime.MaxValue)
|
||||||
if(null==prices)continue;
|
{
|
||||||
foreach(Price price in prices)Add(price);
|
prices = PricingDA.GetPrices(symbol, minTradeDate);
|
||||||
PricesByDate p=priceCache[symbol];
|
|
||||||
}
|
}
|
||||||
|
else if (minTradeDate < minCacheDate)
|
||||||
|
{
|
||||||
|
prices = PricingDA.GetPrices(symbol, minCacheDate, minTradeDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prices != null && prices.Count > 0)
|
||||||
|
{
|
||||||
|
fetchedPrices[symbol] = prices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MDTrace.WriteLine(LogLevel.DEBUG, $"Error fetching prices for {symbol}: {ex.Message}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
lock (thisLock)
|
||||||
|
{
|
||||||
|
foreach (var kvp in fetchedPrices)
|
||||||
|
{
|
||||||
|
foreach (var price in kvp.Value)
|
||||||
|
{
|
||||||
|
Add(price);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,110 +217,164 @@ namespace MarketData.Cache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(List<String> symbols,DateTime pricingDate)
|
public void Add(List<string> symbols, DateTime pricingDate)
|
||||||
{
|
{
|
||||||
foreach(String symbol in symbols)
|
if (symbols == null || symbols.Count == 0) return;
|
||||||
|
|
||||||
|
ConcurrentDictionary<string, Price> fetchedPrices = new ConcurrentDictionary<string, Price>();
|
||||||
|
|
||||||
|
Parallel.ForEach(symbols, new ParallelOptions { MaxDegreeOfParallelism = 8 }, symbol =>
|
||||||
|
{
|
||||||
|
lock (thisLock)
|
||||||
|
{
|
||||||
|
if (ContainsPrice(symbol, pricingDate)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if(ContainsPrice(symbol,pricingDate))continue;
|
|
||||||
Price price = PricingDA.GetPrice(symbol, pricingDate);
|
Price price = PricingDA.GetPrice(symbol, pricingDate);
|
||||||
if(null==price)continue;
|
if (price != null) fetchedPrices[symbol] = price;
|
||||||
Add(price);
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MDTrace.WriteLine(LogLevel.DEBUG, $"Error fetching price for {symbol} on {pricingDate:yyyy-MM-dd}: {ex.Message}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
lock (thisLock)
|
||||||
|
{
|
||||||
|
foreach (var kvp in fetchedPrices)
|
||||||
|
{
|
||||||
|
Add(kvp.Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(Price price)
|
public void Add(Price price)
|
||||||
{
|
{
|
||||||
lock(typeof(LocalPriceCache))
|
if (price == null) return;
|
||||||
|
|
||||||
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
if(null==price)return;
|
if (!priceCache.TryGetValue(price.Symbol, out var pricesByDate))
|
||||||
if(ContainsPrice(price.Symbol,price.Date))return;
|
|
||||||
PricesByDate pricesByDate=null;
|
|
||||||
if(!priceCache.ContainsKey(price.Symbol))
|
|
||||||
{
|
{
|
||||||
pricesByDate = new PricesByDate();
|
pricesByDate = new PricesByDate();
|
||||||
pricesByDate.Add(price.Date,price);
|
priceCache[price.Symbol] = pricesByDate;
|
||||||
priceCache.Add(price.Symbol,pricesByDate);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
pricesByDate=priceCache[price.Symbol];
|
if (!pricesByDate.ContainsKey(price.Date))
|
||||||
if(pricesByDate.ContainsKey(price.Date))return;
|
|
||||||
pricesByDate.Add(price.Date,price);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public DateTime GetMinCacheDate(String symbol)
|
|
||||||
{
|
{
|
||||||
if(!ContainsSymbol(symbol))return Utility.Epoch;
|
pricesByDate.Add(price.Date, price); // must use Add() to update MinDate/MaxDate
|
||||||
PricesByDate symbolPrices=priceCache[symbol];
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime GetMinCacheDate(string symbol)
|
||||||
|
{
|
||||||
|
lock (thisLock)
|
||||||
|
{
|
||||||
|
if (!priceCache.TryGetValue(symbol, out var symbolPrices) || symbolPrices.Count == 0)
|
||||||
|
{
|
||||||
|
return Utility.Epoch;
|
||||||
|
}
|
||||||
return symbolPrices.MinDate;
|
return symbolPrices.MinDate;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void RemoveDate(DateTime date)
|
public void RemoveDate(DateTime date)
|
||||||
{
|
{
|
||||||
lock(typeof(LocalPriceCache))
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
List<String> symbols=new List<String>(priceCache.Keys);
|
foreach (var kvp in priceCache)
|
||||||
foreach(String key in symbols)
|
|
||||||
{
|
{
|
||||||
PricesByDate pricesByDate=priceCache[key];
|
kvp.Value.Remove(date);
|
||||||
if(pricesByDate.ContainsKey(date))pricesByDate.Remove(date);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
public Price GetPrice(String symbol,DateTime date)
|
|
||||||
{
|
|
||||||
lock(typeof(LocalPriceCache))
|
|
||||||
{
|
|
||||||
if(!priceCache.ContainsKey(symbol))return null;
|
|
||||||
PricesByDate pricesByDate=priceCache[symbol];
|
|
||||||
if(!pricesByDate.ContainsKey(date))return null;
|
|
||||||
return pricesByDate[date];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public bool ContainsPrice(String symbol,DateTime date)
|
|
||||||
{
|
|
||||||
lock(typeof(LocalPriceCache))
|
|
||||||
{
|
|
||||||
if(!priceCache.ContainsKey(symbol))return false;
|
|
||||||
PricesByDate pricesByDate=priceCache[symbol];
|
|
||||||
if(!pricesByDate.ContainsKey(date))return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public bool ContainsPrice(List<String> symbols,DateTime date)
|
|
||||||
{
|
|
||||||
lock(typeof(LocalPriceCache))
|
|
||||||
{
|
|
||||||
foreach(String symbol in symbols)if(!ContainsPrice(symbol,date))return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ContainsSymbol(String symbol)
|
public Prices GetPrices(string symbol, DateTime endDate, int dayCount)
|
||||||
{
|
{
|
||||||
lock(typeof(LocalPriceCache))
|
lock (thisLock)
|
||||||
|
{
|
||||||
|
if (!priceCache.TryGetValue(symbol, out var pricesByDate)) return new Prices();
|
||||||
|
|
||||||
|
DateGenerator dateGenerator = new DateGenerator();
|
||||||
|
List<DateTime> historicalDates = dateGenerator.GenerateHistoricalDates(endDate, dayCount);
|
||||||
|
|
||||||
|
Prices result = new Prices();
|
||||||
|
foreach (DateTime date in historicalDates)
|
||||||
|
{
|
||||||
|
if (pricesByDate.ContainsKey(date))
|
||||||
|
{
|
||||||
|
result.Add(pricesByDate[date]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Price GetPrice(string symbol, DateTime date)
|
||||||
|
{
|
||||||
|
lock (thisLock)
|
||||||
|
{
|
||||||
|
if (!priceCache.TryGetValue(symbol, out var pricesByDate)) return null;
|
||||||
|
return pricesByDate.TryGetValue(date, out var price) ? price : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ContainsPrice(string symbol, DateTime date)
|
||||||
|
{
|
||||||
|
lock (thisLock)
|
||||||
|
{
|
||||||
|
if (!priceCache.TryGetValue(symbol, out var pricesByDate)) return false;
|
||||||
|
return pricesByDate.ContainsKey(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ContainsPrice(List<string> symbols, DateTime date)
|
||||||
|
{
|
||||||
|
if (symbols == null || symbols.Count == 0) return false;
|
||||||
|
|
||||||
|
lock (thisLock)
|
||||||
|
{
|
||||||
|
foreach (string symbol in symbols)
|
||||||
|
{
|
||||||
|
if (!priceCache.TryGetValue(symbol, out var pricesByDate) || !pricesByDate.ContainsKey(date))
|
||||||
{
|
{
|
||||||
if(priceCache.ContainsKey(symbol))return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public long Count()
|
public bool ContainsSymbol(string symbol)
|
||||||
|
{
|
||||||
|
lock (thisLock)
|
||||||
|
{
|
||||||
|
return priceCache.ContainsKey(symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long Count()
|
||||||
|
{
|
||||||
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
long count = 0;
|
long count = 0;
|
||||||
List<String> symbols=priceCache.Keys.ToList();
|
foreach (var pricesByDate in priceCache.Values)
|
||||||
foreach(String symbol in symbols)
|
|
||||||
{
|
{
|
||||||
PricesByDate pricesByDate=priceCache[symbol];
|
|
||||||
count += pricesByDate.Count;
|
count += pricesByDate.Count;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ThreadProc()
|
private void ThreadProc()
|
||||||
{
|
{
|
||||||
int quantums = 0;
|
int quantums = 0;
|
||||||
int quantumInterval = 1000;
|
int quantumInterval = 1000;
|
||||||
long lastCount = 0;
|
long lastCount = 0;
|
||||||
|
|
||||||
while (threadRun)
|
while (threadRun)
|
||||||
{
|
{
|
||||||
Thread.Sleep(quantumInterval);
|
Thread.Sleep(quantumInterval);
|
||||||
@@ -273,11 +385,12 @@ namespace MarketData.Cache
|
|||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
lastCount = Count();
|
lastCount = Count();
|
||||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LocalPriceCache:ThreadProc] Symbols: {0}. Items in cache: {1}.",priceCache.Keys.Count,Utility.FormatNumber(lastCount,0,true)));
|
MDTrace.WriteLine(LogLevel.DEBUG, $"[LocalPriceCache:ThreadProc] Symbols: {priceCache.Keys.Count}. Items in cache: {Utility.FormatNumber(lastCount,0,true)}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LocalPriceCache:ThreadProc] Thread ended. Items in cache:{0}",Utility.FormatNumber(lastCount,0,true)));
|
|
||||||
|
MDTrace.WriteLine(LogLevel.DEBUG, $"[LocalPriceCache:ThreadProc] Thread ended. Items in cache:{Utility.FormatNumber(lastCount,0,true)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
CMTSESSIONv1.00
|
CMTSESSIONv1.00
|
||||||
LastUpdated=2/13/2026 8:56:35 PM
|
LastUpdated=2/23/2026 9:38:02 PM
|
||||||
TradeDate=2/13/2026
|
TradeDate=2/23/2026
|
||||||
StartDate=1/1/0001
|
StartDate=1/1/0001
|
||||||
AnalysisDate=2/13/2026
|
AnalysisDate=2/23/2026
|
||||||
CashBalance=4287.32
|
CashBalance=4287.32
|
||||||
NonTradeableCash=6456.42
|
NonTradeableCash=6456.42
|
||||||
SuspendTrading=False|UsePriceSlopeIndicator=True|UsePriceSlopeIndicatorDays=252|AnalysisDate=2/13/2026|BetaMonths=6|TradeDate=2/13/2026|MarketCapLowerLimit=500000000|SidewaysDetection=False|SidewaysAfterDays=30|PriceTrendDays=20|CheckOutliersInReturnStream=True|DailyReturnLimit=0.25|MaxDailyPositions=3|MaxOpenPositions=3|NoTradeSymbols=CODYY,MARUY,CSTM,CS,NATI,QADA,CRTO,GTBIF,CLCT,PRSC,CMD,STAY,GBTC,YOKU,PNY,RFMD,ASAZY,USMO,VNR,STB,XIV,SYNT,DFP|OnlyTradeSymbols=|MinRSI=70|InitialCash=10000|TotalRiskPercentDecimal=0.05|PositionRiskPercentDecimal=0.12|EquityOnly=False|MinPercentReturnProximityTo52WeekHigh=30|MinPercentReturnOver52WeekLow=80|ProfitMarginCheck=True|EPSCheck=True|MinDaysBetweenReholding=30|LiquidityCheck=True|MinVolume=1000|DMA200Horizon=15|MinDaysBetweenStopAdjustments=30|MinDaysBetweenInitialStopAdjustment=5|MaxPricingExceptions=3|MACDSetup=(12,26,9)|MACDSignalDays=5|MACDRejectStrongSells=True|MACDRejectWeakSells=True|UseMarketIndicator=True|Benchmark=SPY|BenchmarkMovingAverageDays=200|BenchmarkMovingAverageHorizon=5|UseMarketIndicatorVolatility=True|UseMarketIndicatorVolatilityHorizon=60|UseMarketIndicatorVolatilityBenchmark=^VIX|UseStopLimitScaling=True|StopLimitScalingType=AverageTrueRange|StopLimitScalingVolatilityDays=30|SellOnDMABreak=True|DMABreakValues=200|DMABreakForceBreak=False|EntryType=OverExtended,MVP,PriceTrend,VolumeTrend|EntryHorizon=30|CandidateExpiryDays=180|VolumeTrendDays=10|ChannelBreakoutHorizon=40|UseOverExtendedIndicatorDays=45|UseOverExtendedIndicatorViolationThreshhold=1|UseOverExtendedIndicatorMarginPercent=1|MaxBeta=10|UseMaxBeta=False|UseProfitMaximization=True|UseProfitMaximizationExpression=R_THRESSHOLD=4;MAX_ATR=3;MULTIPLIER=MAX_ATR;IF(RMultiple>=R_THRESSHOLD){MULTIPLIER=1.2;}|UseTradeOnlySectors=False|UseTradeOnlySectorsSectors=Healthcare,Technology,Basic Materials,Consumer Defensive,Industrials|EvaluateStopOnUpTrend=False
|
SuspendTrading=False|UsePriceSlopeIndicator=True|UsePriceSlopeIndicatorDays=252|AnalysisDate=2/23/2026|BetaMonths=6|TradeDate=2/23/2026|MarketCapLowerLimit=500000000|SidewaysDetection=False|SidewaysAfterDays=30|PriceTrendDays=20|CheckOutliersInReturnStream=True|DailyReturnLimit=0.25|MaxDailyPositions=3|MaxOpenPositions=3|NoTradeSymbols=CODYY,MARUY,CSTM,CS,NATI,QADA,CRTO,GTBIF,CLCT,PRSC,CMD,STAY,GBTC,YOKU,PNY,RFMD,ASAZY,USMO,VNR,STB,XIV,SYNT,DFP|OnlyTradeSymbols=|MinRSI=70|InitialCash=10000|TotalRiskPercentDecimal=0.05|PositionRiskPercentDecimal=0.12|EquityOnly=False|MinPercentReturnProximityTo52WeekHigh=30|MinPercentReturnOver52WeekLow=80|ProfitMarginCheck=True|EPSCheck=True|MinDaysBetweenReholding=30|LiquidityCheck=True|MinVolume=1000|DMA200Horizon=15|MinDaysBetweenStopAdjustments=30|MinDaysBetweenInitialStopAdjustment=5|MaxPricingExceptions=3|MACDSetup=(12,26,9)|MACDSignalDays=5|MACDRejectStrongSells=True|MACDRejectWeakSells=True|UseMarketIndicator=True|Benchmark=SPY|BenchmarkMovingAverageDays=200|BenchmarkMovingAverageHorizon=5|UseMarketIndicatorVolatility=True|UseMarketIndicatorVolatilityHorizon=60|UseMarketIndicatorVolatilityBenchmark=^VIX|UseStopLimitScaling=True|StopLimitScalingType=AverageTrueRange|StopLimitScalingVolatilityDays=30|SellOnDMABreak=True|DMABreakValues=200|DMABreakForceBreak=False|EntryType=OverExtended,MVP,PriceTrend,VolumeTrend|EntryHorizon=30|CandidateExpiryDays=180|VolumeTrendDays=10|ChannelBreakoutHorizon=40|UseOverExtendedIndicatorDays=45|UseOverExtendedIndicatorViolationThreshhold=1|UseOverExtendedIndicatorMarginPercent=1|MaxBeta=10|UseMaxBeta=False|UseProfitMaximization=True|UseProfitMaximizationExpression=R_THRESSHOLD=4;MAX_ATR=3;MULTIPLIER=MAX_ATR;IF(RMultiple>=R_THRESSHOLD){MULTIPLIER=1.2;}|UseTradeOnlySectors=False|UseTradeOnlySectorsSectors=Healthcare,Technology,Basic Materials,Consumer Defensive,Industrials|EvaluateStopOnUpTrend=False
|
||||||
PricingExceptions=0
|
PricingExceptions=0
|
||||||
TotalActivePositions=2
|
TotalActivePositions=2
|
||||||
Symbol=HWM|PurchaseDate=11/17/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=11|PurchasePrice=200.81|CurrentPrice=250.21|Exposure=2208.91|MarketValue=2752.31|GainLoss=543.4|GainLossPcnt=0.246003685075445|PositionRiskDecimal=0.12|R=24.0336|C=276.15|P=11.490163770721|InitialStopLimit=176.71|TrailingStopLimit=197.56385799408|TotalRiskExposure=264.3696|RMultiple=2.06R|Volatility=3.68232583999634|Volume=0|LastStopAdjustment=1/26/2026 12:00:00 AM|Comment=Price changed on 11/18/2025 from $200.28 to $200.81
|
Symbol=HWM|PurchaseDate=11/17/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=11|PurchasePrice=200.81|CurrentPrice=257.04|Exposure=2208.91|MarketValue=2827.44|GainLoss=618.53|GainLossPcnt=0.280015935461382|PositionRiskDecimal=0.12|R=24.0336|C=276.15|P=11.490163770721|InitialStopLimit=176.71|TrailingStopLimit=197.56385799408|TotalRiskExposure=264.3696|RMultiple=2.34R|Volatility=3.68232583999634|Volume=0|LastStopAdjustment=1/26/2026 12:00:00 AM|Comment=Price changed on 11/18/2025 from $200.28 to $200.81
|
||||||
Symbol=FTI|PurchaseDate=11/20/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=41|PurchasePrice=43.23|CurrentPrice=61.36|Exposure=1772.43|MarketValue=2515.76|GainLoss=743.33|GainLossPcnt=0.419384686560259|PositionRiskDecimal=0.12|R=5.2188|C=218.4595|P=41.8601019391431|InitialStopLimit=38.04|TrailingStopLimit=50.7683570289612|TotalRiskExposure=213.9708|RMultiple=3.47R|Volatility=0.825829267501831|Volume=0|LastStopAdjustment=1/26/2026 12:00:00 AM|Comment=Price changed on 11/21/2025 from $43.49 to $43.23
|
Symbol=FTI|PurchaseDate=11/20/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=41|PurchasePrice=43.23|CurrentPrice=64.25|Exposure=1772.43|MarketValue=2634.25|GainLoss=861.82|GainLossPcnt=0.486236409900532|PositionRiskDecimal=0.12|R=5.2188|C=218.4595|P=41.8601019391431|InitialStopLimit=38.04|TrailingStopLimit=50.7683570289612|TotalRiskExposure=213.9708|RMultiple=4.03R|Volatility=0.825829267501831|Volume=0|LastStopAdjustment=1/26/2026 12:00:00 AM|Comment=Price changed on 11/21/2025 from $43.49 to $43.23
|
||||||
TotalPositions=133
|
TotalPositions=133
|
||||||
Symbol=CDNS|PurchaseDate=8/25/2020 12:00:00 AM|SellDate=9/3/2020 12:00:00 AM|Shares=16|PurchasePrice=111.82|CurrentPrice=109.57|Exposure=1789.12|MarketValue=1753.12|GainLoss=-36|GainLossPcnt=-0.0201216240386335|PositionRiskDecimal=0.12|R=13.3512|C=225.6365|P=16.9000913775541|InitialStopLimit=97.9088|TrailingStopLimit=109.599856939316|TotalRiskExposure=213.6192|RMultiple=-0.17R|Volatility=2.3209912776947|Volume=1767980|LastStopAdjustment=9/2/2020 12:00:00 AM|Comment=Manual close.
|
Symbol=CDNS|PurchaseDate=8/25/2020 12:00:00 AM|SellDate=9/3/2020 12:00:00 AM|Shares=16|PurchasePrice=111.82|CurrentPrice=109.57|Exposure=1789.12|MarketValue=1753.12|GainLoss=-36|GainLossPcnt=-0.0201216240386335|PositionRiskDecimal=0.12|R=13.3512|C=225.6365|P=16.9000913775541|InitialStopLimit=97.9088|TrailingStopLimit=109.599856939316|TotalRiskExposure=213.6192|RMultiple=-0.17R|Volatility=2.3209912776947|Volume=1767980|LastStopAdjustment=9/2/2020 12:00:00 AM|Comment=Manual close.
|
||||||
Symbol=LULU|PurchaseDate=8/28/2020 12:00:00 AM|SellDate=9/4/2020 12:00:00 AM|Shares=3|PurchasePrice=377.5|CurrentPrice=370.23|Exposure=1132.5|MarketValue=1110.69|GainLoss=-21.8099999999999|GainLossPcnt=-0.0192582781456953|PositionRiskDecimal=0.12|R=45.2976|C=136.6285|P=3.01624147857723|InitialStopLimit=332.1824|TrailingStopLimit=372.562428512573|TotalRiskExposure=135.8928|RMultiple=-0.16R|Volatility=25.858959197998|Volume=2871665|LastStopAdjustment=9/2/2020 12:00:00 AM|Comment=Manual close.
|
Symbol=LULU|PurchaseDate=8/28/2020 12:00:00 AM|SellDate=9/4/2020 12:00:00 AM|Shares=3|PurchasePrice=377.5|CurrentPrice=370.23|Exposure=1132.5|MarketValue=1110.69|GainLoss=-21.8099999999999|GainLossPcnt=-0.0192582781456953|PositionRiskDecimal=0.12|R=45.2976|C=136.6285|P=3.01624147857723|InitialStopLimit=332.1824|TrailingStopLimit=372.562428512573|TotalRiskExposure=135.8928|RMultiple=-0.16R|Volatility=25.858959197998|Volume=2871665|LastStopAdjustment=9/2/2020 12:00:00 AM|Comment=Manual close.
|
||||||
@@ -144,14 +144,13 @@ Symbol=DASH|PurchaseDate=10/20/2025 12:00:00 AM|SellDate=11/6/2025 12:00:00 AM|S
|
|||||||
Symbol=HCI|PurchaseDate=11/6/2025 12:00:00 AM|SellDate=11/17/2025 12:00:00 AM|Shares=12|PurchasePrice=199.2|CurrentPrice=175.62|Exposure=2390.4|MarketValue=2107.44|GainLoss=-282.96|GainLossPcnt=-0.118373493975903|PositionRiskDecimal=0.12|R=23.4012|C=290.298|P=12.4052612686529|InitialStopLimit=175.3|TrailingStopLimit=175.3|TotalRiskExposure=280.8144|RMultiple=-1.01R|Volatility=8.70686626434326|Volume=0|LastStopAdjustment=1/1/0001 12:00:00 AM|Comment=Manual close.
|
Symbol=HCI|PurchaseDate=11/6/2025 12:00:00 AM|SellDate=11/17/2025 12:00:00 AM|Shares=12|PurchasePrice=199.2|CurrentPrice=175.62|Exposure=2390.4|MarketValue=2107.44|GainLoss=-282.96|GainLossPcnt=-0.118373493975903|PositionRiskDecimal=0.12|R=23.4012|C=290.298|P=12.4052612686529|InitialStopLimit=175.3|TrailingStopLimit=175.3|TotalRiskExposure=280.8144|RMultiple=-1.01R|Volatility=8.70686626434326|Volume=0|LastStopAdjustment=1/1/0001 12:00:00 AM|Comment=Manual close.
|
||||||
Symbol=NFLX|PurchaseDate=10/21/2025 12:00:00 AM|SellDate=11/20/2025 12:00:00 AM|Shares=10|PurchasePrice=114.35|CurrentPrice=105.51|Exposure=1143.5|MarketValue=1055.1|GainLoss=-88.3999999999999|GainLossPcnt=-0.0773065150852644|PositionRiskDecimal=0.12|R=148.962|C=201.1665|P=1.35045514963548|InitialStopLimit=100.62|TrailingStopLimit=105.51|TotalRiskExposure=1489.62|RMultiple=-0.06R|Volatility=19.877721786499|Volume=0|LastStopAdjustment=11/13/2025 12:00:00 AM|Comment=Manual close.
|
Symbol=NFLX|PurchaseDate=10/21/2025 12:00:00 AM|SellDate=11/20/2025 12:00:00 AM|Shares=10|PurchasePrice=114.35|CurrentPrice=105.51|Exposure=1143.5|MarketValue=1055.1|GainLoss=-88.3999999999999|GainLossPcnt=-0.0773065150852644|PositionRiskDecimal=0.12|R=148.962|C=201.1665|P=1.35045514963548|InitialStopLimit=100.62|TrailingStopLimit=105.51|TotalRiskExposure=1489.62|RMultiple=-0.06R|Volatility=19.877721786499|Volume=0|LastStopAdjustment=11/13/2025 12:00:00 AM|Comment=Manual close.
|
||||||
Symbol=CX|PurchaseDate=10/20/2025 12:00:00 AM|SellDate=2/5/2026 12:00:00 AM|Shares=144|PurchasePrice=9.54|CurrentPrice=11.74|Exposure=1373.76|MarketValue=1690.56|GainLoss=316.8|GainLossPcnt=0.230607966457023|PositionRiskDecimal=0.12|R=1.1472|C=166.144|P=144.825662482566|InitialStopLimit=8.4|TrailingStopLimit=12.0339285671711|TotalRiskExposure=165.1968|RMultiple=1.92R|Volatility=0.164089068770409|Volume=0|LastStopAdjustment=1/28/2026 12:00:00 AM|Comment=Manual close.
|
Symbol=CX|PurchaseDate=10/20/2025 12:00:00 AM|SellDate=2/5/2026 12:00:00 AM|Shares=144|PurchasePrice=9.54|CurrentPrice=11.74|Exposure=1373.76|MarketValue=1690.56|GainLoss=316.8|GainLossPcnt=0.230607966457023|PositionRiskDecimal=0.12|R=1.1472|C=166.144|P=144.825662482566|InitialStopLimit=8.4|TrailingStopLimit=12.0339285671711|TotalRiskExposure=165.1968|RMultiple=1.92R|Volatility=0.164089068770409|Volume=0|LastStopAdjustment=1/28/2026 12:00:00 AM|Comment=Manual close.
|
||||||
TotalCandidates=120
|
TotalCandidates=128
|
||||||
Symbol=FINMY|AnalysisDate=10/2/2025 12:00:00 AM|EPSSlope=0.0349999964237213|ProfitMarginSlope=2.26086616516113|PriceSlope=0.00448679936177329|Volatility=1.03268754482269|Volume=0|Violation=False|Slope=0.00448679936177329|Score=2.66255318366838|AnnualizedReturn=3.09774193858814|SharpeRatio=0.335718769738377|RSquared=0.859514199843871|BetaMonths=6|Beta=0.824935419784389
|
Symbol=FINMY|AnalysisDate=10/2/2025 12:00:00 AM|EPSSlope=0.0349999964237213|ProfitMarginSlope=2.26086616516113|PriceSlope=0.00448679936177329|Volatility=1.03268754482269|Volume=0|Violation=False|Slope=0.00448679936177329|Score=2.66255318366838|AnnualizedReturn=3.09774193858814|SharpeRatio=0.335718769738377|RSquared=0.859514199843871|BetaMonths=6|Beta=0.824935419784389
|
||||||
Symbol=RYCEY|AnalysisDate=10/1/2025 12:00:00 AM|EPSSlope=0.0249999910593033|ProfitMarginSlope=2.86403560638428|PriceSlope=0.00377742185948191|Volatility=0.317665636539459|Volume=0|Violation=False|Slope=0.00377742185948191|Score=2.3960549250413|AnnualizedReturn=2.59065388368147|SharpeRatio=0.325355777751677|RSquared=0.924884231017524|BetaMonths=6|Beta=1.39611806037306
|
Symbol=RYCEY|AnalysisDate=10/1/2025 12:00:00 AM|EPSSlope=0.0249999910593033|ProfitMarginSlope=2.86403560638428|PriceSlope=0.00377742185948191|Volatility=0.317665636539459|Volume=0|Violation=False|Slope=0.00377742185948191|Score=2.3960549250413|AnnualizedReturn=2.59065388368147|SharpeRatio=0.325355777751677|RSquared=0.924884231017524|BetaMonths=6|Beta=1.39611806037306
|
||||||
Symbol=TTMI|AnalysisDate=9/23/2025 12:00:00 AM|EPSSlope=0.0699999928474426|ProfitMarginSlope=0.416337013244629|PriceSlope=0.00365635399457596|Volatility=3.10769009590149|Volume=0|Violation=False|Slope=0.00365635399457596|Score=1.73840687121807|AnnualizedReturn=2.5128088887714|SharpeRatio=0.319624993971795|RSquared=0.691818179642002|BetaMonths=6|Beta=4.40428456309766
|
Symbol=TTMI|AnalysisDate=9/23/2025 12:00:00 AM|EPSSlope=0.0699999928474426|ProfitMarginSlope=0.416337013244629|PriceSlope=0.00365635399457596|Volatility=3.10769009590149|Volume=0|Violation=False|Slope=0.00365635399457596|Score=1.73840687121807|AnnualizedReturn=2.5128088887714|SharpeRatio=0.319624993971795|RSquared=0.691818179642002|BetaMonths=6|Beta=4.40428456309766
|
||||||
Symbol=SBSW|AnalysisDate=9/25/2025 12:00:00 AM|EPSSlope=0.144999995827675|ProfitMarginSlope=8.49569129943848|PriceSlope=0.00379709174022612|Volatility=0.753211140632629|Volume=0|Violation=False|Slope=0.00379709174022612|Score=1.72251869189193|AnnualizedReturn=2.60352714141071|SharpeRatio=0.241739220317797|RSquared=0.661609654262558|BetaMonths=6|Beta=1.87093907966492
|
Symbol=SBSW|AnalysisDate=9/25/2025 12:00:00 AM|EPSSlope=0.144999995827675|ProfitMarginSlope=8.49569129943848|PriceSlope=0.00379709174022612|Volatility=0.753211140632629|Volume=0|Violation=False|Slope=0.00379709174022612|Score=1.72251869189193|AnnualizedReturn=2.60352714141071|SharpeRatio=0.241739220317797|RSquared=0.661609654262558|BetaMonths=6|Beta=1.87093907966492
|
||||||
Symbol=NTES|AnalysisDate=9/15/2025 12:00:00 AM|EPSSlope=0.204999923706055|ProfitMarginSlope=1.94379615783691|PriceSlope=0.00231223761471691|Volatility=7.26750755310059|Volume=0|Violation=False|Slope=0.00231223761471691|Score=1.55371831188788|AnnualizedReturn=1.79083837998442|SharpeRatio=0.0978165524611287|RSquared=0.867592703648334|BetaMonths=6|Beta=1.22658293677365
|
Symbol=NTES|AnalysisDate=9/15/2025 12:00:00 AM|EPSSlope=0.204999923706055|ProfitMarginSlope=1.94379615783691|PriceSlope=0.00231223761471691|Volatility=7.26750755310059|Volume=0|Violation=False|Slope=0.00231223761471691|Score=1.55371831188788|AnnualizedReturn=1.79083837998442|SharpeRatio=0.0978165524611287|RSquared=0.867592703648334|BetaMonths=6|Beta=1.22658293677365
|
||||||
Symbol=SANM|AnalysisDate=10/6/2025 12:00:00 AM|EPSSlope=0.174999952316284|ProfitMarginSlope=0.24951171875|PriceSlope=0.00208239218708193|Volatility=6.52257966995239|Volume=0|Violation=False|Slope=0.00208239218708193|Score=1.2404476041886|AnnualizedReturn=1.6900579717286|SharpeRatio=0.133157857131703|RSquared=0.733967488061884|BetaMonths=6|Beta=1.12080932540038
|
Symbol=SANM|AnalysisDate=10/6/2025 12:00:00 AM|EPSSlope=0.174999952316284|ProfitMarginSlope=0.24951171875|PriceSlope=0.00208239218708193|Volatility=6.52257966995239|Volume=0|Violation=False|Slope=0.00208239218708193|Score=1.2404476041886|AnnualizedReturn=1.6900579717286|SharpeRatio=0.133157857131703|RSquared=0.733967488061884|BetaMonths=6|Beta=1.12080932540038
|
||||||
Symbol=VSEC|AnalysisDate=8/18/2025 12:00:00 AM|EPSSlope=0.479999989271164|ProfitMarginSlope=0.627522468566895|PriceSlope=0.00197968074908862|Volatility=7.79957246780396|Volume=0|Violation=False|Slope=0.00197968074908862|Score=1.23555493984458|AnnualizedReturn=1.64687499344999|SharpeRatio=0.0848111495425649|RSquared=0.750242091694071|BetaMonths=6|Beta=0.00511743208922735
|
|
||||||
Symbol=APH|AnalysisDate=9/10/2025 12:00:00 AM|EPSSlope=0.225000023841858|ProfitMarginSlope=1.02336883544922|PriceSlope=0.00218577417499694|Volatility=3.01760697364807|Volume=0|Violation=False|Slope=0.00218577417499694|Score=1.19871329173408|AnnualizedReturn=1.73466635462984|SharpeRatio=0.117857316723347|RSquared=0.691033920462406|BetaMonths=6|Beta=1.29660077545655
|
Symbol=APH|AnalysisDate=9/10/2025 12:00:00 AM|EPSSlope=0.225000023841858|ProfitMarginSlope=1.02336883544922|PriceSlope=0.00218577417499694|Volatility=3.01760697364807|Volume=0|Violation=False|Slope=0.00218577417499694|Score=1.19871329173408|AnnualizedReturn=1.73466635462984|SharpeRatio=0.117857316723347|RSquared=0.691033920462406|BetaMonths=6|Beta=1.29660077545655
|
||||||
Symbol=BVN|AnalysisDate=9/22/2025 12:00:00 AM|EPSSlope=0.0400000214576721|ProfitMarginSlope=3.35278701782227|PriceSlope=0.00178832525596272|Volatility=0.509544312953949|Volume=0|Violation=False|Slope=0.00178832525596272|Score=1.1871859154563|AnnualizedReturn=1.56934441878645|SharpeRatio=0.0627467548412755|RSquared=0.756485256674465|BetaMonths=6|Beta=0.0852063395469229
|
Symbol=BVN|AnalysisDate=9/22/2025 12:00:00 AM|EPSSlope=0.0400000214576721|ProfitMarginSlope=3.35278701782227|PriceSlope=0.00178832525596272|Volatility=0.509544312953949|Volume=0|Violation=False|Slope=0.00178832525596272|Score=1.1871859154563|AnnualizedReturn=1.56934441878645|SharpeRatio=0.0627467548412755|RSquared=0.756485256674465|BetaMonths=6|Beta=0.0852063395469229
|
||||||
Symbol=FN|AnalysisDate=11/4/2025 12:00:00 AM|EPSSlope=0.0999999046325684|ProfitMarginSlope=0.0680141448974609|PriceSlope=0.00254868146461796|Volatility=18.239673614502|Volume=0|Violation=False|Slope=0.00254868146461796|Score=1.12395010145193|AnnualizedReturn=1.90078646425663|SharpeRatio=0.156706951792266|RSquared=0.591307925738777|BetaMonths=6|Beta=1.07114601199124
|
Symbol=FN|AnalysisDate=11/4/2025 12:00:00 AM|EPSSlope=0.0999999046325684|ProfitMarginSlope=0.0680141448974609|PriceSlope=0.00254868146461796|Volatility=18.239673614502|Volume=0|Violation=False|Slope=0.00254868146461796|Score=1.12395010145193|AnnualizedReturn=1.90078646425663|SharpeRatio=0.156706951792266|RSquared=0.591307925738777|BetaMonths=6|Beta=1.07114601199124
|
||||||
@@ -172,7 +171,6 @@ Symbol=GLW|AnalysisDate=9/5/2025 12:00:00 AM|EPSSlope=0.21000000834465|ProfitMar
|
|||||||
Symbol=BWXT|AnalysisDate=10/1/2025 12:00:00 AM|EPSSlope=0.0299999713897705|ProfitMarginSlope=0.842325210571289|PriceSlope=0.00148142098327814|Volatility=5.46874237060547|Volume=0|Violation=False|Slope=0.00148142098327814|Score=0.535519927511107|AnnualizedReturn=1.45254630359425|SharpeRatio=0.0847391180072971|RSquared=0.368676665374447|BetaMonths=6|Beta=1.20408002256826
|
Symbol=BWXT|AnalysisDate=10/1/2025 12:00:00 AM|EPSSlope=0.0299999713897705|ProfitMarginSlope=0.842325210571289|PriceSlope=0.00148142098327814|Volatility=5.46874237060547|Volume=0|Violation=False|Slope=0.00148142098327814|Score=0.535519927511107|AnnualizedReturn=1.45254630359425|SharpeRatio=0.0847391180072971|RSquared=0.368676665374447|BetaMonths=6|Beta=1.20408002256826
|
||||||
Symbol=MU|AnalysisDate=10/16/2025 12:00:00 AM|EPSSlope=1.01999998092651|ProfitMarginSlope=3.93631362915039|PriceSlope=0.0017836395604108|Volatility=12.5083780288696|Volume=0|Violation=False|Slope=0.0017836395604108|Score=0.535470880696113|AnnualizedReturn=1.56749243792573|SharpeRatio=0.131165993959009|RSquared=0.341609865374982|BetaMonths=6|Beta=3.80362957802949
|
Symbol=MU|AnalysisDate=10/16/2025 12:00:00 AM|EPSSlope=1.01999998092651|ProfitMarginSlope=3.93631362915039|PriceSlope=0.0017836395604108|Volatility=12.5083780288696|Volume=0|Violation=False|Slope=0.0017836395604108|Score=0.535470880696113|AnnualizedReturn=1.56749243792573|SharpeRatio=0.131165993959009|RSquared=0.341609865374982|BetaMonths=6|Beta=3.80362957802949
|
||||||
Symbol=COLL|AnalysisDate=11/17/2025 12:00:00 AM|EPSSlope=0.285000026226044|ProfitMarginSlope=3.47329521179199|PriceSlope=0.000996351284585738|Volatility=4.86669015884399|Volume=0|Violation=False|Slope=0.000996351284585738|Score=0.498972314260969|AnnualizedReturn=1.28541358644203|SharpeRatio=-0.244881207463219|RSquared=0.388180364299792|BetaMonths=6|Beta=1.46108876190814
|
Symbol=COLL|AnalysisDate=11/17/2025 12:00:00 AM|EPSSlope=0.285000026226044|ProfitMarginSlope=3.47329521179199|PriceSlope=0.000996351284585738|Volatility=4.86669015884399|Volume=0|Violation=False|Slope=0.000996351284585738|Score=0.498972314260969|AnnualizedReturn=1.28541358644203|SharpeRatio=-0.244881207463219|RSquared=0.388180364299792|BetaMonths=6|Beta=1.46108876190814
|
||||||
Symbol=BELFB|AnalysisDate=8/25/2025 12:00:00 AM|EPSSlope=0.285000085830688|ProfitMarginSlope=0.582233428955078|PriceSlope=0.00141653955297341|Volatility=2.603111743927|Volume=0|Violation=False|Slope=0.00141653955297341|Score=0.480716598993722|AnnualizedReturn=1.4289900947802|SharpeRatio=0.119774159326474|RSquared=0.336403030888512|BetaMonths=6|Beta=2.43681291066381
|
|
||||||
Symbol=GSL|AnalysisDate=9/18/2025 12:00:00 AM|EPSSlope=0.0900001525878906|ProfitMarginSlope=0.176097869873047|PriceSlope=0.00102036281428555|Volatility=0.917586147785187|Volume=0|Violation=False|Slope=0.00102036281428555|Score=0.447266351637514|AnnualizedReturn=1.29321508181417|SharpeRatio=-0.240771308468293|RSquared=0.345856120862797|BetaMonths=6|Beta=0.967212765650389
|
Symbol=GSL|AnalysisDate=9/18/2025 12:00:00 AM|EPSSlope=0.0900001525878906|ProfitMarginSlope=0.176097869873047|PriceSlope=0.00102036281428555|Volatility=0.917586147785187|Volume=0|Violation=False|Slope=0.00102036281428555|Score=0.447266351637514|AnnualizedReturn=1.29321508181417|SharpeRatio=-0.240771308468293|RSquared=0.345856120862797|BetaMonths=6|Beta=0.967212765650389
|
||||||
Symbol=CGAU|AnalysisDate=9/25/2025 12:00:00 AM|EPSSlope=0.0750000029802322|ProfitMarginSlope=7.88293075561523|PriceSlope=0.0009970382360156|Volatility=0.387202262878418|Volume=0|Violation=False|Slope=0.0009970382360156|Score=0.429807798377358|AnnualizedReturn=1.28563612591224|SharpeRatio=-0.153030522888472|RSquared=0.334315277639216|BetaMonths=6|Beta=0.89521003942289
|
Symbol=CGAU|AnalysisDate=9/25/2025 12:00:00 AM|EPSSlope=0.0750000029802322|ProfitMarginSlope=7.88293075561523|PriceSlope=0.0009970382360156|Volatility=0.387202262878418|Volume=0|Violation=False|Slope=0.0009970382360156|Score=0.429807798377358|AnnualizedReturn=1.28563612591224|SharpeRatio=-0.153030522888472|RSquared=0.334315277639216|BetaMonths=6|Beta=0.89521003942289
|
||||||
Symbol=MD|AnalysisDate=11/17/2025 12:00:00 AM|EPSSlope=0.300000011920929|ProfitMarginSlope=3.04110622406006|PriceSlope=0.000999694216261977|Volatility=2.24461984634399|Volume=0|Violation=False|Slope=0.000999694216261977|Score=0.412248257927109|AnnualizedReturn=1.28649689922789|SharpeRatio=-0.0107905850378413|RSquared=0.320442480797681|BetaMonths=6|Beta=3.52283407368269
|
Symbol=MD|AnalysisDate=11/17/2025 12:00:00 AM|EPSSlope=0.300000011920929|ProfitMarginSlope=3.04110622406006|PriceSlope=0.000999694216261977|Volatility=2.24461984634399|Volume=0|Violation=False|Slope=0.000999694216261977|Score=0.412248257927109|AnnualizedReturn=1.28649689922789|SharpeRatio=-0.0107905850378413|RSquared=0.320442480797681|BetaMonths=6|Beta=3.52283407368269
|
||||||
@@ -184,7 +182,6 @@ Symbol=LVS|AnalysisDate=11/20/2025 12:00:00 AM|EPSSlope=0.120000004768372|Profit
|
|||||||
Symbol=HBM|AnalysisDate=9/3/2025 12:00:00 AM|EPSSlope=0.175000011920929|ProfitMarginSlope=0.490240097045898|PriceSlope=0.000729030817168273|Volatility=0.487358808517456|Volume=0|Violation=False|Slope=0.000729030817168273|Score=0.175331906747473|AnnualizedReturn=1.20167421779262|SharpeRatio=0.0685094425688964|RSquared=0.145906356441219|BetaMonths=6|Beta=2.69015248129092
|
Symbol=HBM|AnalysisDate=9/3/2025 12:00:00 AM|EPSSlope=0.175000011920929|ProfitMarginSlope=0.490240097045898|PriceSlope=0.000729030817168273|Volatility=0.487358808517456|Volume=0|Violation=False|Slope=0.000729030817168273|Score=0.175331906747473|AnnualizedReturn=1.20167421779262|SharpeRatio=0.0685094425688964|RSquared=0.145906356441219|BetaMonths=6|Beta=2.69015248129092
|
||||||
Symbol=BILI|AnalysisDate=9/15/2025 12:00:00 AM|EPSSlope=0.135000005364418|ProfitMarginSlope=1.50113868713379|PriceSlope=0.000573695565703754|Volatility=1.41854751110077|Volume=0|Violation=False|Slope=0.000573695565703754|Score=0.108280835698724|AnnualizedReturn=1.1555440621639|SharpeRatio=0.067556996898538|RSquared=0.0937055013687271|BetaMonths=6|Beta=0.725243490158731
|
Symbol=BILI|AnalysisDate=9/15/2025 12:00:00 AM|EPSSlope=0.135000005364418|ProfitMarginSlope=1.50113868713379|PriceSlope=0.000573695565703754|Volatility=1.41854751110077|Volume=0|Violation=False|Slope=0.000573695565703754|Score=0.108280835698724|AnnualizedReturn=1.1555440621639|SharpeRatio=0.067556996898538|RSquared=0.0937055013687271|BetaMonths=6|Beta=0.725243490158731
|
||||||
Symbol=MCY|AnalysisDate=10/3/2025 12:00:00 AM|EPSSlope=0.934999942779541|ProfitMarginSlope=2.7081880569458|PriceSlope=0.000598694193818475|Volatility=2.73796057701111|Volume=0|Violation=False|Slope=0.000598694193818475|Score=0.0983982079050049|AnnualizedReturn=1.16284656774647|SharpeRatio=-0.0693450586498807|RSquared=0.0846183930315889|BetaMonths=6|Beta=1.50736316396258
|
Symbol=MCY|AnalysisDate=10/3/2025 12:00:00 AM|EPSSlope=0.934999942779541|ProfitMarginSlope=2.7081880569458|PriceSlope=0.000598694193818475|Volatility=2.73796057701111|Volume=0|Violation=False|Slope=0.000598694193818475|Score=0.0983982079050049|AnnualizedReturn=1.16284656774647|SharpeRatio=-0.0693450586498807|RSquared=0.0846183930315889|BetaMonths=6|Beta=1.50736316396258
|
||||||
Symbol=VITL|AnalysisDate=8/22/2025 12:00:00 AM|EPSSlope=0.00499999523162842|ProfitMarginSlope=1.38887023925781|PriceSlope=0.000455363083461419|Volatility=4.98714113235474|Volume=0|Violation=False|Slope=0.000455363083461419|Score=0.083100854866897|AnnualizedReturn=1.12159468333037|SharpeRatio=-0.244814541455398|RSquared=0.0740916982774419|BetaMonths=6|Beta=1.21500191244139
|
|
||||||
Symbol=CSIQ|AnalysisDate=10/31/2025 12:00:00 AM|EPSSlope=0.0249999985098839|ProfitMarginSlope=7.77392435073853|PriceSlope=0.000623090718563301|Volatility=1.79284286499023|Volume=0|Violation=False|Slope=0.000623090718563301|Score=0.0807088026857748|AnnualizedReturn=1.1700176814875|SharpeRatio=-0.187760717880484|RSquared=0.0689808401725739|BetaMonths=6|Beta=1.33520035507038
|
Symbol=CSIQ|AnalysisDate=10/31/2025 12:00:00 AM|EPSSlope=0.0249999985098839|ProfitMarginSlope=7.77392435073853|PriceSlope=0.000623090718563301|Volatility=1.79284286499023|Volume=0|Violation=False|Slope=0.000623090718563301|Score=0.0807088026857748|AnnualizedReturn=1.1700176814875|SharpeRatio=-0.187760717880484|RSquared=0.0689808401725739|BetaMonths=6|Beta=1.33520035507038
|
||||||
Symbol=MUX|AnalysisDate=9/2/2025 12:00:00 AM|EPSSlope=0.155000001192093|ProfitMarginSlope=12.6074028015137|PriceSlope=0.000420282872695496|Volatility=0.892517030239105|Volume=0|Violation=False|Slope=0.000420282872695496|Score=0.0505830547931327|AnnualizedReturn=1.11172324440238|SharpeRatio=0.0664507478013526|RSquared=0.0454996826303873|BetaMonths=6|Beta=2.4677990769044
|
Symbol=MUX|AnalysisDate=9/2/2025 12:00:00 AM|EPSSlope=0.155000001192093|ProfitMarginSlope=12.6074028015137|PriceSlope=0.000420282872695496|Volatility=0.892517030239105|Volume=0|Violation=False|Slope=0.000420282872695496|Score=0.0505830547931327|AnnualizedReturn=1.11172324440238|SharpeRatio=0.0664507478013526|RSquared=0.0454996826303873|BetaMonths=6|Beta=2.4677990769044
|
||||||
Symbol=TV|AnalysisDate=9/5/2025 12:00:00 AM|EPSSlope=0.0250000059604645|ProfitMarginSlope=3.05452346801758|PriceSlope=0.000362561864863969|Volatility=0.196487531065941|Volume=0|Violation=False|Slope=0.000362561864863969|Score=0.0409861983117743|AnnualizedReturn=1.09566949779821|SharpeRatio=0.0530850799580673|RSquared=0.0374074466745106|BetaMonths=6|Beta=2.16132791096815
|
Symbol=TV|AnalysisDate=9/5/2025 12:00:00 AM|EPSSlope=0.0250000059604645|ProfitMarginSlope=3.05452346801758|PriceSlope=0.000362561864863969|Volatility=0.196487531065941|Volume=0|Violation=False|Slope=0.000362561864863969|Score=0.0409861983117743|AnnualizedReturn=1.09566949779821|SharpeRatio=0.0530850799580673|RSquared=0.0374074466745106|BetaMonths=6|Beta=2.16132791096815
|
||||||
@@ -265,6 +262,17 @@ Symbol=PSMT|AnalysisDate=2/4/2026 12:00:00 AM|EPSSlope=0.0399999618530273|Profit
|
|||||||
Symbol=DCI|AnalysisDate=2/4/2026 12:00:00 AM|EPSSlope=0.0800000429153442|ProfitMarginSlope=0.454849243164063|PriceSlope=0.00170455784568539|Volatility=1.97363579273224|Volume=0|Violation=False|Slope=0.00170455784568539|Score=1.31671434176791|AnnualizedReturn=1.53656372692812|SharpeRatio=-0.0863957755266661|RSquared=0.856921401106001|BetaMonths=6|Beta=0.807390077629777
|
Symbol=DCI|AnalysisDate=2/4/2026 12:00:00 AM|EPSSlope=0.0800000429153442|ProfitMarginSlope=0.454849243164063|PriceSlope=0.00170455784568539|Volatility=1.97363579273224|Volume=0|Violation=False|Slope=0.00170455784568539|Score=1.31671434176791|AnnualizedReturn=1.53656372692812|SharpeRatio=-0.0863957755266661|RSquared=0.856921401106001|BetaMonths=6|Beta=0.807390077629777
|
||||||
Symbol=VIV|AnalysisDate=2/5/2026 12:00:00 AM|EPSSlope=0.0150000154972076|ProfitMarginSlope=0.774349212646484|PriceSlope=0.0018972653337033|Volatility=0.896089375019073|Volume=0|Violation=False|Slope=0.0018972653337033|Score=1.34104616717728|AnnualizedReturn=1.61302429994768|SharpeRatio=0.0802914461607737|RSquared=0.831386214839278|BetaMonths=6|Beta=0.658849608391599
|
Symbol=VIV|AnalysisDate=2/5/2026 12:00:00 AM|EPSSlope=0.0150000154972076|ProfitMarginSlope=0.774349212646484|PriceSlope=0.0018972653337033|Volatility=0.896089375019073|Volume=0|Violation=False|Slope=0.0018972653337033|Score=1.34104616717728|AnnualizedReturn=1.61302429994768|SharpeRatio=0.0802914461607737|RSquared=0.831386214839278|BetaMonths=6|Beta=0.658849608391599
|
||||||
Symbol=ACA|AnalysisDate=2/10/2026 12:00:00 AM|EPSSlope=0.569999992847443|ProfitMarginSlope=2.10593795776367|PriceSlope=0.00135427268924872|Volatility=4.8927788734436|Volume=0|Violation=False|Slope=0.00135427268924872|Score=0.959654963471782|AnnualizedReturn=1.40674245753235|SharpeRatio=-0.232548548203499|RSquared=0.682182412518612|BetaMonths=6|Beta=0.558306829669136
|
Symbol=ACA|AnalysisDate=2/10/2026 12:00:00 AM|EPSSlope=0.569999992847443|ProfitMarginSlope=2.10593795776367|PriceSlope=0.00135427268924872|Volatility=4.8927788734436|Volume=0|Violation=False|Slope=0.00135427268924872|Score=0.959654963471782|AnnualizedReturn=1.40674245753235|SharpeRatio=-0.232548548203499|RSquared=0.682182412518612|BetaMonths=6|Beta=0.558306829669136
|
||||||
|
Symbol=SPHR|AnalysisDate=2/17/2026 12:00:00 AM|EPSSlope=1.34500002861023|ProfitMarginSlope=2.51224708557129|PriceSlope=0.00523907012952609|Volatility=8.95045948028564|Volume=0|Violation=False|Slope=0.00523907012952609|Score=3.20870287565322|AnnualizedReturn=3.74434114645189|SharpeRatio=0.218491066644505|RSquared=0.856947257248118|BetaMonths=6|Beta=3.21248816680421
|
||||||
|
Symbol=AEIS|AnalysisDate=2/17/2026 12:00:00 AM|EPSSlope=0.00999999046325684|ProfitMarginSlope=0.814477920532227|PriceSlope=0.00426370997524409|Volatility=22.9871597290039|Volume=0|Violation=False|Slope=0.00426370997524409|Score=2.66714040431645|AnnualizedReturn=2.92839623692391|SharpeRatio=0.421589812378226|RSquared=0.910785354347438|BetaMonths=6|Beta=3.7968120892911
|
||||||
|
Symbol=VRT|AnalysisDate=2/17/2026 12:00:00 AM|EPSSlope=0.379999995231628|ProfitMarginSlope=2.02690315246582|PriceSlope=0.00388394295179174|Volatility=23.7274208068848|Volume=0|Violation=False|Slope=0.00388394295179174|Score=2.25005270680435|AnnualizedReturn=2.66113739591567|SharpeRatio=0.122049768039598|RSquared=0.845522937018489|BetaMonths=6|Beta=4.55406437863137
|
||||||
|
Symbol=PAHC|AnalysisDate=2/17/2026 12:00:00 AM|EPSSlope=0.300000011920929|ProfitMarginSlope=3.21435642242432|PriceSlope=0.00374364997253655|Volatility=5.95380306243896|Volume=0|Violation=False|Slope=0.00374364997253655|Score=2.12819854519029|AnnualizedReturn=2.56869963711064|SharpeRatio=0.184901261217851|RSquared=0.828512027815039|BetaMonths=6|Beta=6.70791192761971
|
||||||
|
Symbol=BWA|AnalysisDate=2/17/2026 12:00:00 AM|EPSSlope=0.295000016689301|ProfitMarginSlope=1.43632125854492|PriceSlope=0.00264878087635921|Volatility=6.97055912017822|Volume=0|Violation=False|Slope=0.00264878087635921|Score=1.73266971161757|AnnualizedReturn=1.94934375656964|SharpeRatio=0.0294760197755666|RSquared=0.888847698502722|BetaMonths=6|Beta=0.749787397929552
|
||||||
|
Symbol=HWM|AnalysisDate=2/17/2026 12:00:00 AM|EPSSlope=0.0750000476837158|ProfitMarginSlope=0.679458618164063|PriceSlope=0.00226567934237701|Volatility=15.8062677383423|Volume=0|Violation=False|Slope=0.00226567934237701|Score=1.49471479981506|AnnualizedReturn=1.76994981712852|SharpeRatio=0.104874604929631|RSquared=0.844495581371914|BetaMonths=6|Beta=1.4716901369434
|
||||||
|
Symbol=TIMB|AnalysisDate=2/17/2026 12:00:00 AM|EPSSlope=0.0699999928474426|ProfitMarginSlope=1.20602607727051|PriceSlope=0.00199482432587108|Volatility=1.30688989162445|Volume=0|Violation=False|Slope=0.00199482432587108|Score=1.36503022074127|AnnualizedReturn=1.65317177427138|SharpeRatio=0.147781257421024|RSquared=0.825703802826477|BetaMonths=6|Beta=3.19165382029475
|
||||||
|
Symbol=MSGE|AnalysisDate=2/18/2026 12:00:00 AM|EPSSlope=0.190000027418137|ProfitMarginSlope=9.9661922454834|PriceSlope=0.00257838089510811|Volatility=1.4681134223938|Volume=0|Violation=False|Slope=0.00257838089510811|Score=1.72098906390133|AnnualizedReturn=1.91506580615047|SharpeRatio=0.138978808993797|RSquared=0.898657925160674|BetaMonths=6|Beta=1.34875445513012
|
||||||
|
Symbol=CRUS|AnalysisDate=2/18/2026 12:00:00 AM|EPSSlope=0.275000095367432|ProfitMarginSlope=0.257987976074219|PriceSlope=0.00138302434593785|Volatility=6.7416615486145|Volume=0|Violation=False|Slope=0.00138302434593785|Score=0.99276144864185|AnnualizedReturn=1.41697190749937|SharpeRatio=-0.160325230400514|RSquared=0.700621828412847|BetaMonths=6|Beta=4.37158193573655
|
||||||
|
Symbol=KN|AnalysisDate=2/20/2026 12:00:00 AM|EPSSlope=0.0450000166893005|ProfitMarginSlope=1.58130264282227|PriceSlope=0.0022407357950537|Volatility=1.25567162036896|Volume=0|Violation=False|Slope=0.0022407357950537|Score=1.48837295417815|AnnualizedReturn=1.75885920577315|SharpeRatio=-0.0777997706291159|RSquared=0.846214949606441|BetaMonths=6|Beta=2.73446817127298
|
||||||
|
Symbol=DHT|AnalysisDate=2/20/2026 12:00:00 AM|EPSSlope=0.0349999666213989|ProfitMarginSlope=7.21533393859863|PriceSlope=0.00126847140872784|Volatility=1.08960521221161|Volume=0|Violation=False|Slope=0.00126847140872784|Score=1.02759147711618|AnnualizedReturn=1.37665245498958|SharpeRatio=-0.164685534611809|RSquared=0.746442192720277|BetaMonths=6|Beta=1.44097492371681
|
||||||
TotalStopLimits=211
|
TotalStopLimits=211
|
||||||
Symbol=CDNS|AnalysisDate=9/2/2020 12:00:00 AM|PreviousStop=97.9088|NewStop=109.599856939316|CurrentPriceLow=113.59|CurrentPriceClose=117.09|PriceTrendIndicatorSlope=0.310654103755951|StopLimitId=
|
Symbol=CDNS|AnalysisDate=9/2/2020 12:00:00 AM|PreviousStop=97.9088|NewStop=109.599856939316|CurrentPriceLow=113.59|CurrentPriceClose=117.09|PriceTrendIndicatorSlope=0.310654103755951|StopLimitId=
|
||||||
Symbol=LULU|AnalysisDate=9/2/2020 12:00:00 AM|PreviousStop=332.1824|NewStop=372.562428512573|CurrentPriceLow=387.08|CurrentPriceClose=398.29|PriceTrendIndicatorSlope=2.77707505226135|StopLimitId=
|
Symbol=LULU|AnalysisDate=9/2/2020 12:00:00 AM|PreviousStop=332.1824|NewStop=372.562428512573|CurrentPriceLow=387.08|CurrentPriceClose=398.29|PriceTrendIndicatorSlope=2.77707505226135|StopLimitId=
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
MGSHSESSIONv2.00
|
MGSHSESSIONv2.00
|
||||||
LastUpdated=2/13/2026 8:56:00 PM
|
LastUpdated=2/23/2026 9:37:05 PM
|
||||||
TradeDate=2/17/2026
|
TradeDate=2/24/2026
|
||||||
StartDate=3/31/2025
|
StartDate=3/31/2025
|
||||||
AnalysisDate=2/13/2026
|
AnalysisDate=2/23/2026
|
||||||
Cycle=11
|
Cycle=11
|
||||||
CashBalance=2932.39
|
CashBalance=2932.39
|
||||||
NonTradeableCash=0
|
NonTradeableCash=0
|
||||||
HedgeCashBalance=3000
|
HedgeCashBalance=3000
|
||||||
Verbose=True|KeepSlotPositions=True|BenchmarkMode=False|BenchmarkModeSymbol=SPY|HoldingPeriod=3|MaxPositions=3|NoTradeSymbols=OSB,IBDRY,GBTC,YOKU,PNY,RFMD,ASAZY|NoTradeFinancialSymbols=U.S. Private Equity,U.S. Financials,U.S. Financial Services,U.S. Banking and Investment Services,Trading-Miscellaneous,Trading--Miscellaneous,Trading--Leveraged Equity,Trading--Leveraged Debt,Trading--Leveraged Commodities,Trading--Inverse Equity,Trading--Inverse Commodities,Tactical Allocation,Specialty Finance,Japan Financials,Savings & Cooperative Banks,Option Writing,Insurance Brokers,Insurance - Specialty,Insurance - Reinsurance,Insurance - Property & Casualty,Insurance - Life,Insurance - Diversified,Global Private Equity,Global Financials,Financial Services,Financial Exchanges,Financial,China Financials,Banks - Regional - US,Banks - Regional - Latin America,Banks - Global,Asset Management,Credit Services|Benchmark=SPY|MarketCapLowerLimit=1000000000|UsePEScreen=False|UseEBITDAScreen=True|UseRevenuePerShareScreen=True|UseLowSlopeBetaCheck=True|LowSlopeBetaDays=15|LowSlopeBetaThreshhold=1|UseMACD=True|MACDSetup=(12,26,9)|MACDSignalDays=12|MACDRejectStrongSellSignals=False|MACDRejectWeakSellSignals=True|UseStochastics=True|StochasticsSignalDays=3|StochasticsRejectStrongSells=True|StochasticsRejectWeakSells=True|UseFallbackCandidate=True|FallbackCandidate=SHV|FallbackCandidateBestOf=SHV,NEAR,BIL,GSY,AGG,ACWX,GSY,SCHF,IXUS,DBEF,IEFA,TLT|UseMaxPEScreen=True|MaxPE=40|StrictMaxPE=False|QualityIndicatorType=IDINDICATOR|IncludeTradeMasterForSymbolsHeld=True|UseStopLimits=True|StopLimitRiskPercentDecimal=0.2|StopLimitScalingVolatilityDays=30|MinDaysBetweenInitialStopAdjustment=30|MinDaysBetweenStopAdjustments=30|StopLimitPriceTrendDays=20|StopLimitATRMultiplier=3|UseHedging=True|HedgeBenchmarkSymbol=SPY|HedgeShortSymbol=SH|HedgeRiskPercentDecimal=0.12|HedgeMinDaysBetweenStopAdjustments=1|HedgeInitialCash=3000|HedgeCloseAboveSMANDays=10|HedgeBandBreakCheckDays=3|HedgeATRMultiplier=1|MaxPricingExceptions=3|UseBetaGenerator=True|UseBetaGeneratorMonths=24
|
Verbose=True|KeepSlotPositions=True|BenchmarkMode=False|BenchmarkModeSymbol=SPY|HoldingPeriod=3|MaxPositions=3|NoTradeSymbols=OSB,IBDRY,GBTC,YOKU,PNY,RFMD,ASAZY|NoTradeFinancialSymbols=U.S. Private Equity,U.S. Financials,U.S. Financial Services,U.S. Banking and Investment Services,Trading-Miscellaneous,Trading--Miscellaneous,Trading--Leveraged Equity,Trading--Leveraged Debt,Trading--Leveraged Commodities,Trading--Inverse Equity,Trading--Inverse Commodities,Tactical Allocation,Specialty Finance,Japan Financials,Savings & Cooperative Banks,Option Writing,Insurance Brokers,Insurance - Specialty,Insurance - Reinsurance,Insurance - Property & Casualty,Insurance - Life,Insurance - Diversified,Global Private Equity,Global Financials,Financial Services,Financial Exchanges,Financial,China Financials,Banks - Regional - US,Banks - Regional - Latin America,Banks - Global,Asset Management,Credit Services|Benchmark=SPY|MarketCapLowerLimit=1000000000|UsePEScreen=False|UseEBITDAScreen=True|UseRevenuePerShareScreen=True|UseLowSlopeBetaCheck=True|LowSlopeBetaDays=15|LowSlopeBetaThreshhold=1|UseMACD=True|MACDSetup=(12,26,9)|MACDSignalDays=12|MACDRejectStrongSellSignals=False|MACDRejectWeakSellSignals=True|UseStochastics=True|StochasticsSignalDays=3|StochasticsRejectStrongSells=True|StochasticsRejectWeakSells=True|UseFallbackCandidate=True|FallbackCandidate=SHV|FallbackCandidateBestOf=SHV,NEAR,BIL,GSY,AGG,ACWX,GSY,SCHF,IXUS,DBEF,IEFA,TLT|UseMaxPEScreen=True|MaxPE=40|StrictMaxPE=False|QualityIndicatorType=IDINDICATOR|IncludeTradeMasterForSymbolsHeld=True|UseStopLimits=True|StopLimitRiskPercentDecimal=0.2|StopLimitScalingVolatilityDays=30|MinDaysBetweenInitialStopAdjustment=30|MinDaysBetweenStopAdjustments=30|StopLimitPriceTrendDays=20|StopLimitATRMultiplier=3|UseHedging=True|HedgeBenchmarkSymbol=SPY|HedgeShortSymbol=SH|HedgeRiskPercentDecimal=0.12|HedgeMinDaysBetweenStopAdjustments=1|HedgeInitialCash=3000|HedgeCloseAboveSMANDays=10|HedgeBandBreakCheckDays=3|HedgeATRMultiplier=1|MaxPricingExceptions=3|UseBetaGenerator=True|UseBetaGeneratorMonths=24
|
||||||
TotalActivePositions=7
|
TotalActivePositions=7
|
||||||
Slot=0|Symbol=USFD|PurchaseDate=9/30/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=12|PurchasePrice=76.21|CurrentPrice=99.93|Volume=2447913|Return1D=0|CumReturn252=0|IDIndicator=-18.7250996015936|Score=0.970794577873616|Velocity=0.708823529411765|PE=33.97|Beta=1.35666771887916|InitialStopLimit=60.97|TrailingStopLimit=77.9387144756317|LastStopAdjustment=1/15/2026 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=15.324|Comment=Price changed on 10/1/2025 from $76.62 to $76.21
|
Slot=0|Symbol=USFD|PurchaseDate=9/30/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=12|PurchasePrice=76.21|CurrentPrice=96.13|Volume=2447913|Return1D=0|CumReturn252=0|IDIndicator=-18.7250996015936|Score=0.970794577873616|Velocity=0.708823529411765|PE=33.97|Beta=1.35666771887916|InitialStopLimit=60.97|TrailingStopLimit=90.4222861194611|LastStopAdjustment=2/17/2026 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=15.324|Comment=Price changed on 10/1/2025 from $76.62 to $76.21
|
||||||
Slot=0|Symbol=CAH|PurchaseDate=9/30/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=5|PurchasePrice=155.81|CurrentPrice=220.79|Volume=2414935|Return1D=0|CumReturn252=0|IDIndicator=-17.9282868525896|Score=1.45705377610136|Velocity=0.779428953080648|PE=23.64|Beta=0.628226122785001|InitialStopLimit=124.65|TrailingStopLimit=198.937214622498|LastStopAdjustment=1/30/2026 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=31.392|Comment=Price changed on 10/1/2025 from $156.96 to $155.81
|
Slot=0|Symbol=CAH|PurchaseDate=9/30/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=5|PurchasePrice=155.81|CurrentPrice=224.82|Volume=2414935|Return1D=0|CumReturn252=0|IDIndicator=-17.9282868525896|Score=1.45705377610136|Velocity=0.779428953080648|PE=23.64|Beta=0.628226122785001|InitialStopLimit=124.65|TrailingStopLimit=198.937214622498|LastStopAdjustment=1/30/2026 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=31.392|Comment=Price changed on 10/1/2025 from $156.96 to $155.81
|
||||||
Slot=0|Symbol=TPB|PurchaseDate=12/31/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=6|PurchasePrice=109|CurrentPrice=131.77|Volume=132784|Return1D=0|CumReturn252=0|IDIndicator=-15.9362549800797|Score=1.44361960940429|Velocity=0.947395388556789|PE=37.1|Beta=1.25054775125095|InitialStopLimit=87.2|TrailingStopLimit=106.557785625458|LastStopAdjustment=1/30/2026 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=21.68|Comment=Price changed on 1/2/2026 from $108.40 to $109.00
|
Slot=0|Symbol=TPB|PurchaseDate=12/31/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=6|PurchasePrice=109|CurrentPrice=135.73|Volume=132784|Return1D=0|CumReturn252=0|IDIndicator=-15.9362549800797|Score=1.44361960940429|Velocity=0.947395388556789|PE=37.1|Beta=1.25054775125095|InitialStopLimit=87.2|TrailingStopLimit=106.557785625458|LastStopAdjustment=1/30/2026 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=21.68|Comment=Price changed on 1/2/2026 from $108.40 to $109.00
|
||||||
Slot=1|Symbol=XEL|PurchaseDate=10/31/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=5|PurchasePrice=81.17|CurrentPrice=81.59|Volume=6202750|Return1D=0|CumReturn252=0|IDIndicator=-11.5537848605578|Score=0.602697377681549|Velocity=0.944803580308304|PE=22.43|Beta=-0.192317961128493|InitialStopLimit=64.936|TrailingStopLimit=64.936|LastStopAdjustment=1/1/0001 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=16.234|Comment=
|
Slot=1|Symbol=XEL|PurchaseDate=10/31/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=5|PurchasePrice=81.17|CurrentPrice=83.35|Volume=6202750|Return1D=0|CumReturn252=0|IDIndicator=-11.5537848605578|Score=0.602697377681549|Velocity=0.944803580308304|PE=22.43|Beta=-0.192317961128493|InitialStopLimit=64.936|TrailingStopLimit=77.5441425132751|LastStopAdjustment=2/23/2026 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=16.234|Comment=
|
||||||
Slot=1|Symbol=MDT|PurchaseDate=1/30/2026 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=14|PurchasePrice=102.85|CurrentPrice=99.49|Volume=6046285|Return1D=0|CumReturn252=0|IDIndicator=-10.3585657370518|Score=0.518428403011861|Velocity=0.865293185419968|PE=26.67|Beta=0.37428296833055|InitialStopLimit=82.28|TrailingStopLimit=82.28|LastStopAdjustment=1/1/0001 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=20.592|Comment=Price changed on 2/2/2026 from $102.96 to $102.85
|
Slot=1|Symbol=MDT|PurchaseDate=1/30/2026 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=14|PurchasePrice=102.85|CurrentPrice=98.61|Volume=6046285|Return1D=0|CumReturn252=0|IDIndicator=-10.3585657370518|Score=0.518428403011861|Velocity=0.865293185419968|PE=26.67|Beta=0.37428296833055|InitialStopLimit=82.28|TrailingStopLimit=82.28|LastStopAdjustment=1/1/0001 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=20.592|Comment=Price changed on 2/2/2026 from $102.96 to $102.85
|
||||||
Slot=1|Symbol=ALHC|PurchaseDate=1/30/2026 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=64|PurchasePrice=22.45|CurrentPrice=20.19|Volume=2524769|Return1D=0|CumReturn252=0|IDIndicator=-8.36653386454184|Score=0.341327585226881|Velocity=0.908249807247494|PE=0|Beta=-0.0198043736453601|InitialStopLimit=17.96|TrailingStopLimit=17.96|LastStopAdjustment=1/1/0001 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=4.506|Comment=Price changed on 2/2/2026 from $22.53 to $22.45
|
Slot=1|Symbol=ALHC|PurchaseDate=1/30/2026 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=64|PurchasePrice=22.45|CurrentPrice=19.9|Volume=2524769|Return1D=0|CumReturn252=0|IDIndicator=-8.36653386454184|Score=0.341327585226881|Velocity=0.908249807247494|PE=0|Beta=-0.0198043736453601|InitialStopLimit=17.96|TrailingStopLimit=17.96|LastStopAdjustment=1/1/0001 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=4.506|Comment=Price changed on 2/2/2026 from $22.53 to $22.45
|
||||||
Slot=2|Symbol=NFG|PurchaseDate=11/28/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=12|PurchasePrice=82.45|CurrentPrice=87.34|Volume=236813|Return1D=0|CumReturn252=0|IDIndicator=-9.56175298804781|Score=1.47874375251707|Velocity=0.658599827139153|PE=31.63|Beta=0.0443025382529758|InitialStopLimit=65.96|TrailingStopLimit=77.9947861814499|LastStopAdjustment=1/30/2026 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=16.49|Comment=
|
Slot=2|Symbol=NFG|PurchaseDate=11/28/2025 12:00:00 AM|SellDate=1/1/0001 12:00:00 AM|Shares=12|PurchasePrice=82.45|CurrentPrice=87.59|Volume=236813|Return1D=0|CumReturn252=0|IDIndicator=-9.56175298804781|Score=1.47874375251707|Velocity=0.658599827139153|PE=31.63|Beta=0.0443025382529758|InitialStopLimit=65.96|TrailingStopLimit=77.9947861814499|LastStopAdjustment=1/30/2026 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=16.49|Comment=
|
||||||
TotalPositions=17
|
TotalPositions=17
|
||||||
Symbol=MO|PurchaseDate=3/31/2025 12:00:00 AM|SellDate=5/14/2025 12:00:00 AM|Shares=18|PurchasePrice=59.91|CurrentPrice=56.15|Volume=17335180|Return1D=0|CumReturn252=0|IDIndicator=-15.9362549800797|Score=1.14749269300042|Velocity=0.967136150234742|PE=9|Beta=0.572465642401382|InitialStopLimit=47.93|TrailingStopLimit=56.1565003347397|LastStopAdjustment=5/7/2025 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=12.004|Comment=Closed due to trailing stop.
|
Symbol=MO|PurchaseDate=3/31/2025 12:00:00 AM|SellDate=5/14/2025 12:00:00 AM|Shares=18|PurchasePrice=59.91|CurrentPrice=56.15|Volume=17335180|Return1D=0|CumReturn252=0|IDIndicator=-15.9362549800797|Score=1.14749269300042|Velocity=0.967136150234742|PE=9|Beta=0.572465642401382|InitialStopLimit=47.93|TrailingStopLimit=56.1565003347397|LastStopAdjustment=5/7/2025 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=12.004|Comment=Closed due to trailing stop.
|
||||||
Symbol=EXC|PurchaseDate=3/31/2025 12:00:00 AM|SellDate=5/14/2025 12:00:00 AM|Shares=24|PurchasePrice=45.76|CurrentPrice=42.6|Volume=14993121|Return1D=0|CumReturn252=0|IDIndicator=-8.76494023904382|Score=0.405636492837393|Velocity=1|PE=18.02|Beta=0.248374476251328|InitialStopLimit=36.61|TrailingStopLimit=42.7107857322693|LastStopAdjustment=4/30/2025 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=9.216|Comment=Closed due to trailing stop.
|
Symbol=EXC|PurchaseDate=3/31/2025 12:00:00 AM|SellDate=5/14/2025 12:00:00 AM|Shares=24|PurchasePrice=45.76|CurrentPrice=42.6|Volume=14993121|Return1D=0|CumReturn252=0|IDIndicator=-8.76494023904382|Score=0.405636492837393|Velocity=1|PE=18.02|Beta=0.248374476251328|InitialStopLimit=36.61|TrailingStopLimit=42.7107857322693|LastStopAdjustment=4/30/2025 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=9.216|Comment=Closed due to trailing stop.
|
||||||
@@ -34,7 +34,7 @@ Symbol=SH|PurchaseDate=9/15/2025 12:00:00 AM|SellDate=11/20/2025 12:00:00 AM|Sha
|
|||||||
Symbol=PSO|PurchaseDate=4/30/2025 12:00:00 AM|SellDate=1/16/2026 12:00:00 AM|Shares=69|PurchasePrice=15.98|CurrentPrice=12.62|Volume=894303|Return1D=0|CumReturn252=0|IDIndicator=-11.9521912350598|Score=1.15269564166514|Velocity=0.737122557726465|PE=19.2|Beta=0.0342052512015139|InitialStopLimit=12.78|TrailingStopLimit=12.78|LastStopAdjustment=1/1/0001 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=3.25|Comment=Closed due to trailing stop.
|
Symbol=PSO|PurchaseDate=4/30/2025 12:00:00 AM|SellDate=1/16/2026 12:00:00 AM|Shares=69|PurchasePrice=15.98|CurrentPrice=12.62|Volume=894303|Return1D=0|CumReturn252=0|IDIndicator=-11.9521912350598|Score=1.15269564166514|Velocity=0.737122557726465|PE=19.2|Beta=0.0342052512015139|InitialStopLimit=12.78|TrailingStopLimit=12.78|LastStopAdjustment=1/1/0001 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=3.25|Comment=Closed due to trailing stop.
|
||||||
Symbol=NYT|PurchaseDate=8/29/2025 12:00:00 AM|SellDate=2/4/2026 12:00:00 AM|Shares=14|PurchasePrice=59.38|CurrentPrice=61.34|Volume=1582847|Return1D=0|CumReturn252=0|IDIndicator=-10.3585657370518|Score=-0.0546472654561472|Velocity=0.878823529411765|PE=30.96|Beta=0.759120105784337|InitialStopLimit=47.5|TrailingStopLimit=66.0039285755157|LastStopAdjustment=1/7/2026 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=11.968|Comment=Manual close.
|
Symbol=NYT|PurchaseDate=8/29/2025 12:00:00 AM|SellDate=2/4/2026 12:00:00 AM|Shares=14|PurchasePrice=59.38|CurrentPrice=61.34|Volume=1582847|Return1D=0|CumReturn252=0|IDIndicator=-10.3585657370518|Score=-0.0546472654561472|Velocity=0.878823529411765|PE=30.96|Beta=0.759120105784337|InitialStopLimit=47.5|TrailingStopLimit=66.0039285755157|LastStopAdjustment=1/7/2026 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=11.968|Comment=Manual close.
|
||||||
Symbol=NEU|PurchaseDate=11/28/2025 12:00:00 AM|SellDate=2/12/2026 12:00:00 AM|Shares=1|PurchasePrice=761.43|CurrentPrice=607|Volume=47592|Return1D=0|CumReturn252=0|IDIndicator=-10.7569721115538|Score=1.32888913206578|Velocity=0.735010364152827|PE=16.57|Beta=0.634028454808648|InitialStopLimit=609.14|TrailingStopLimit=609.14|LastStopAdjustment=1/1/0001 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=152.706|Comment=Closed due to trailing stop.
|
Symbol=NEU|PurchaseDate=11/28/2025 12:00:00 AM|SellDate=2/12/2026 12:00:00 AM|Shares=1|PurchasePrice=761.43|CurrentPrice=607|Volume=47592|Return1D=0|CumReturn252=0|IDIndicator=-10.7569721115538|Score=1.32888913206578|Velocity=0.735010364152827|PE=16.57|Beta=0.634028454808648|InitialStopLimit=609.14|TrailingStopLimit=609.14|LastStopAdjustment=1/1/0001 12:00:00 AM|PositionRiskPercentDecimal=0.2|R=152.706|Comment=Closed due to trailing stop.
|
||||||
TotalStopLimits=36
|
TotalStopLimits=38
|
||||||
Symbol=EXC|AnalysisDate=4/30/2025 12:00:00 AM|PreviousStop=36.61|NewStop=42.7107857322693|CurrentPriceLow=42.6|CurrentPriceClose=46.9|PriceTrendIndicatorSlope=0.0870828032493591|StopLimitId=EXC20250331120000AM
|
Symbol=EXC|AnalysisDate=4/30/2025 12:00:00 AM|PreviousStop=36.61|NewStop=42.7107857322693|CurrentPriceLow=42.6|CurrentPriceClose=46.9|PriceTrendIndicatorSlope=0.0870828032493591|StopLimitId=EXC20250331120000AM
|
||||||
Symbol=SXT|AnalysisDate=4/30/2025 12:00:00 AM|PreviousStop=59.18|NewStop=85.4177850723267|CurrentPriceLow=92.4|CurrentPriceClose=93.95|PriceTrendIndicatorSlope=0.931879639625549|StopLimitId=SXT20250331120000AM
|
Symbol=SXT|AnalysisDate=4/30/2025 12:00:00 AM|PreviousStop=59.18|NewStop=85.4177850723267|CurrentPriceLow=92.4|CurrentPriceClose=93.95|PriceTrendIndicatorSlope=0.931879639625549|StopLimitId=SXT20250331120000AM
|
||||||
Symbol=MO|AnalysisDate=5/7/2025 12:00:00 AM|PreviousStop=47.93|NewStop=56.1565003347397|CurrentPriceLow=56.16|CurrentPriceClose=60.91|PriceTrendIndicatorSlope=0.217300787568092|StopLimitId=MO20250331120000AM
|
Symbol=MO|AnalysisDate=5/7/2025 12:00:00 AM|PreviousStop=47.93|NewStop=56.1565003347397|CurrentPriceLow=56.16|CurrentPriceClose=60.91|PriceTrendIndicatorSlope=0.217300787568092|StopLimitId=MO20250331120000AM
|
||||||
@@ -71,5 +71,7 @@ Symbol=USFD|AnalysisDate=1/15/2026 12:00:00 AM|PreviousStop=73.5799289083481|New
|
|||||||
Symbol=CAH|AnalysisDate=1/30/2026 12:00:00 AM|PreviousStop=194.335500230789|NewStop=198.937214622498|CurrentPriceLow=210.01|CurrentPriceClose=212.42|PriceTrendIndicatorSlope=0.434736758470535|StopLimitId=CAH20250930120000AM
|
Symbol=CAH|AnalysisDate=1/30/2026 12:00:00 AM|PreviousStop=194.335500230789|NewStop=198.937214622498|CurrentPriceLow=210.01|CurrentPriceClose=212.42|PriceTrendIndicatorSlope=0.434736758470535|StopLimitId=CAH20250930120000AM
|
||||||
Symbol=TPB|AnalysisDate=1/30/2026 12:00:00 AM|PreviousStop=87.2|NewStop=106.557785625458|CurrentPriceLow=117.87|CurrentPriceClose=121.15|PriceTrendIndicatorSlope=0.970541477203369|StopLimitId=TPB20251231120000AM
|
Symbol=TPB|AnalysisDate=1/30/2026 12:00:00 AM|PreviousStop=87.2|NewStop=106.557785625458|CurrentPriceLow=117.87|CurrentPriceClose=121.15|PriceTrendIndicatorSlope=0.970541477203369|StopLimitId=TPB20251231120000AM
|
||||||
Symbol=NFG|AnalysisDate=1/30/2026 12:00:00 AM|PreviousStop=65.96|NewStop=77.9947861814499|CurrentPriceLow=82.54|CurrentPriceClose=83.75|PriceTrendIndicatorSlope=0.215090155601501|StopLimitId=NFG20251128120000AM
|
Symbol=NFG|AnalysisDate=1/30/2026 12:00:00 AM|PreviousStop=65.96|NewStop=77.9947861814499|CurrentPriceLow=82.54|CurrentPriceClose=83.75|PriceTrendIndicatorSlope=0.215090155601501|StopLimitId=NFG20251128120000AM
|
||||||
|
Symbol=USFD|AnalysisDate=2/17/2026 12:00:00 AM|PreviousStop=77.9387144756317|NewStop=90.4222861194611|CurrentPriceLow=96.59|CurrentPriceClose=97.11|PriceTrendIndicatorSlope=0.7435262799263|StopLimitId=USFD20250930120000AM
|
||||||
|
Symbol=XEL|AnalysisDate=2/23/2026 12:00:00 AM|PreviousStop=64.936|NewStop=77.5441425132751|CurrentPriceLow=81.78|CurrentPriceClose=83.35|PriceTrendIndicatorSlope=0.34472182393074|StopLimitId=XEL20251031120000AM
|
||||||
TotalHedgePositions=0
|
TotalHedgePositions=0
|
||||||
TotalPricingExceptions=0
|
TotalPricingExceptions=0
|
||||||
|
|||||||
Reference in New Issue
Block a user