Add an eviction policy to the GBPriceCache.
Some checks failed
Build .NET Project / build (push) Has been cancelled
Some checks failed
Build .NET Project / build (push) Has been cancelled
This commit is contained in:
51
MarketData/MarketData/Models/runcmmomentumbacktest.sh
Executable file
51
MarketData/MarketData/Models/runcmmomentumbacktest.sh
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/bin/bash
|
||||
|
||||
# IDENTICAL RUN TO TEST8B. THE MODEL WAS RUN A 2ND TIME WITH DATABASE UPDATES TO BRING IT CURRENT.
|
||||
# THE PREVIOUS DATABASE ONLY CONTAINED DATA THROUGH 07/2025. THE NEW IMPORT
|
||||
# MAKES DATA AVAILABLE UP TO EARLY MARCH 2026
|
||||
# CNNClient.Model.CNNClient.Model.convnext upscaling 224 for the convneXt pretrained model and adding ^VIX volatility and using 90 days
|
||||
# THIS TEST USED A 25% REWARD FOR A POSITIVE PREDICTION
|
||||
# CNN TEST
|
||||
export DOTNET_ROOT=/opt/dotnet
|
||||
|
||||
CNNDAYCOUNT=90
|
||||
VERSION=05
|
||||
USEMAXPOSITIONBUCKETWEIGHT=TRUE
|
||||
USEMAXPOSITIONBUCKETWEIGHTMAXWEIGHT=.65
|
||||
USEOVEREXTENDEDINDICATOR=TRUE
|
||||
DAYS=10
|
||||
VIOLATIONS=1
|
||||
MARGINPERCENT=1.00
|
||||
STARTDATE=10-31-2019
|
||||
CNNREWARD=.25
|
||||
PATHSESSIONFILE="CM${STARTDATE}_OI_${DAYS}_${VIOLATIONS}_MPBW_65_USEOV${USEOVEREXTENDEDINDICATOR}_V${VERSION}.TXT"
|
||||
|
||||
if [ -f "$PATHSESSIONFILE" ]; then
|
||||
rm "$PATHSESSIONFILE"
|
||||
echo "Deleted existing session file: $PATHSESSIONFILE"
|
||||
else
|
||||
echo "Session file not found, proceeding: $PATHSESSIONFILE"
|
||||
fi
|
||||
|
||||
# echo "RUNCMBACKTEST /USECNN:TRUE /USECNNCLIENT:TRUE /USECNNDAYCOUNT:${CNNDAYCOUNT} /USECNNHOST:127.0.0.1:5000 /USECNNREWARDPERCENTDECIMAL:${CNNREWARD} /USEMAXPOSITIONBUCKETWEIGHT:${USEMAXPOSITIONBUCKETWEIGHT} /USEMAXPOSITIONBUCKETWEIGHTMAXWEIGHT:${USEMAXPOSITIONBUCKETWEIGHTMAXWEIGHT} /STARTDATE:${STARTDATE} /MAXPOSITIONS:3 /INITIALCASH:10000 /HOLDINGPERIOD:3 /TARGETBETA:1 /SESSIONFILE:${PATHSESSIONFILE} /USEOVEREXTENDEDINDICATOR:${USEOVEREXTENDEDINDICATOR} /USEOVEREXTENDEDINDICATORDAYS:${DAYS} /USEOVEREXTENDEDINDICATORVIOLATIONTHRESHHOLD:${VIOLATIONS} /USEOVEREXTENDEDINDICATORMARGINPERCENT:${MARGINPERCENT}"
|
||||
|
||||
/home/pi/ARM64/MarketData/MarketData/bin/Debug/net8.0/mk RUNCMBACKTEST \
|
||||
/USECNN:TRUE \
|
||||
/USECNNCLIENT:TRUE \
|
||||
/USECNNDAYCOUNT:${CNNDAYCOUNT} \
|
||||
/USECNNHOST:10.0.0.240:5000 \
|
||||
/USECNNREWARDPERCENTDECIMAL:${CNNREWARD} \
|
||||
/USEMAXPOSITIONBUCKETWEIGHT:${USEMAXPOSITIONBUCKETWEIGHT} \
|
||||
/USEMAXPOSITIONBUCKETWEIGHTMAXWEIGHT:${USEMAXPOSITIONBUCKETWEIGHTMAXWEIGHT} \
|
||||
/STARTDATE:${STARTDATE} \
|
||||
/MAXPOSITIONS:3 \
|
||||
/INITIALCASH:10000 \
|
||||
/HOLDINGPERIOD:3 \
|
||||
/TARGETBETA:1 \
|
||||
/SESSIONFILE:${PATHSESSIONFILE} \
|
||||
/USEOVEREXTENDEDINDICATOR:${USEOVEREXTENDEDINDICATOR} \
|
||||
/USEOVEREXTENDEDINDICATORDAYS:${DAYS} \
|
||||
/USEOVEREXTENDEDINDICATORVIOLATIONTHRESHHOLD:${VIOLATIONS} \
|
||||
/USEOVEREXTENDEDINDICATORMARGINPERCENT:${MARGINPERCENT}
|
||||
|
||||
exit 0
|
||||
@@ -46,6 +46,7 @@ namespace MarketData.Cache
|
||||
private Thread cacheMonitorThread = null;
|
||||
private volatile bool threadRun = true;
|
||||
private Object thisLock = new Object();
|
||||
private static volatile bool isShutdown = false;
|
||||
|
||||
private CacheSnapshot snapshot;
|
||||
private DateGenerator dateGenerator = new DateGenerator();
|
||||
@@ -61,10 +62,16 @@ namespace MarketData.Cache
|
||||
cacheMonitorThread.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetInstance
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ObjectDisposedException"></exception>
|
||||
public static GBPriceCache GetInstance()
|
||||
{
|
||||
lock (typeof(GBPriceCache))
|
||||
{
|
||||
if (isShutdown) throw new ObjectDisposedException(nameof(GBPriceCache), "Cache has been shut down.");
|
||||
if (null == priceCacheInstance)
|
||||
{
|
||||
priceCacheInstance = new GBPriceCache();
|
||||
@@ -81,11 +88,17 @@ namespace MarketData.Cache
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuts down the cache and stops the monitor thread. This is a full application-level
|
||||
/// shutdown. Callers should always access the cache via GetInstance() and not hold
|
||||
/// long-lived references to the instance.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
lock (thisLock)
|
||||
{
|
||||
if (null == priceCacheInstance || !threadRun) return;
|
||||
isShutdown = true;
|
||||
threadRun = false;
|
||||
if (null != cacheMonitorThread)
|
||||
{
|
||||
@@ -97,33 +110,6 @@ namespace MarketData.Cache
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearCacheOnOrBefore(DateTime onOrBeforeDate, bool collect = false)
|
||||
{
|
||||
lock (thisLock)
|
||||
{
|
||||
Dictionary<String, PricesByDate> newPriceCache = new Dictionary<String, PricesByDate>();
|
||||
foreach (KeyValuePair<String, PricesByDate> entry in snapshot.PriceCache)
|
||||
{
|
||||
String symbol = entry.Key;
|
||||
PricesByDate filteredPrices = new PricesByDate();
|
||||
PricesByDate existingPrices = entry.Value;
|
||||
foreach (KeyValuePair<DateTime, Price> kvp in existingPrices)
|
||||
{
|
||||
if (kvp.Key >= onOrBeforeDate)
|
||||
{
|
||||
filteredPrices.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
}
|
||||
if (filteredPrices.Count > 0)
|
||||
{
|
||||
newPriceCache.Add(symbol, filteredPrices);
|
||||
}
|
||||
}
|
||||
UpdateSnapshot(newPriceCache, snapshot.RealTimePriceCache, snapshot.NullCache);
|
||||
if (collect) GC.Collect();
|
||||
}
|
||||
}
|
||||
|
||||
public Price GetPriceOrLatestAvailable(String symbol, DateTime date)
|
||||
{
|
||||
Price price = GetPrice(symbol, date);
|
||||
@@ -294,6 +280,38 @@ namespace MarketData.Cache
|
||||
return pricesByDate.ContainsKey(date);
|
||||
}
|
||||
|
||||
public void ClearCacheOnOrBefore(DateTime onOrBeforeDate, bool collect = false)
|
||||
{
|
||||
lock (thisLock)
|
||||
{
|
||||
UpdateSnapshot(BuildEvictedPriceCache(onOrBeforeDate), snapshot.RealTimePriceCache, new Dictionary<String, bool>());
|
||||
if (collect) GC.Collect();
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<String, PricesByDate> BuildEvictedPriceCache(DateTime onOrBeforeDate)
|
||||
{
|
||||
Dictionary<String, PricesByDate> newPriceCache = new Dictionary<String, PricesByDate>();
|
||||
foreach (KeyValuePair<String, PricesByDate> entry in snapshot.PriceCache)
|
||||
{
|
||||
String symbol = entry.Key;
|
||||
PricesByDate filteredPrices = new PricesByDate();
|
||||
PricesByDate existingPrices = entry.Value;
|
||||
foreach (KeyValuePair<DateTime, Price> kvp in existingPrices)
|
||||
{
|
||||
if (kvp.Key >= onOrBeforeDate)
|
||||
{
|
||||
filteredPrices.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
}
|
||||
if (filteredPrices.Count > 0)
|
||||
{
|
||||
newPriceCache.Add(symbol, filteredPrices);
|
||||
}
|
||||
}
|
||||
return newPriceCache;
|
||||
}
|
||||
|
||||
private void ThreadProc()
|
||||
{
|
||||
int quantums = 0;
|
||||
@@ -302,18 +320,25 @@ namespace MarketData.Cache
|
||||
while (threadRun)
|
||||
{
|
||||
Thread.Sleep(quantumInterval);
|
||||
if(!threadRun)break;
|
||||
if (!threadRun) break;
|
||||
quantums += quantumInterval;
|
||||
if (quantums > cacheRefreshAfter)
|
||||
{
|
||||
quantums = 0;
|
||||
lock (thisLock)
|
||||
{
|
||||
UpdateSnapshot(snapshot.PriceCache, new Dictionary<String, Price>(), snapshot.NullCache);
|
||||
DateTime maxDate = snapshot.PriceCache.Values.SelectMany(p => p.Keys).DefaultIfEmpty(DateTime.MinValue).Max();
|
||||
if (maxDate != DateTime.MinValue)
|
||||
{
|
||||
DateTime evictBefore = dateGenerator.GenerateHistoricalDates(maxDate, 252).Min();
|
||||
MDTrace.WriteLine(LogLevel.DEBUG, $"GBPriceCache, clearing cache on or before {evictBefore.ToShortDateString()}");
|
||||
UpdateSnapshot(BuildEvictedPriceCache(evictBefore), new Dictionary<String, Price>(), new Dictionary<String, bool>());
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSnapshot(Dictionary<String, PricesByDate> newPriceCache,Dictionary<String, Price> newRealtimePriceCache, Dictionary<String, bool> newNullCache)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma warning disable SYSLIB0014
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.IO.Compression;
|
||||
@@ -1843,18 +1844,27 @@ namespace MarketData.Integration
|
||||
return webRequest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// IsMovedException - MovedPermanently, Found, RedirectKeepVerb, PermanentRedirect will all return a "Location" in the response
|
||||
/// That we will forward the request to.
|
||||
/// </summary>
|
||||
/// <param name="webException"></param>
|
||||
/// <returns></returns>
|
||||
private static bool IsMovedException(WebException webException)
|
||||
{
|
||||
if(webException.Status.Equals(WebExceptionStatus.ProtocolError))
|
||||
if (webException.Status.Equals(WebExceptionStatus.ProtocolError))
|
||||
{
|
||||
HttpWebResponse response = webException.Response as HttpWebResponse;
|
||||
if(response.StatusCode.Equals(HttpStatusCode.MovedPermanently))
|
||||
if (response.StatusCode.Equals(HttpStatusCode.MovedPermanently) ||
|
||||
response.StatusCode.Equals(HttpStatusCode.Found) ||
|
||||
response.StatusCode.Equals(HttpStatusCode.RedirectKeepVerb) ||
|
||||
response.StatusCode.Equals(HttpStatusCode.PermanentRedirect))
|
||||
{
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the proxy for the specified service or null if it is not congfigured to use the proxy
|
||||
@@ -1921,3 +1931,4 @@ namespace MarketData.Integration
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore SYSLIB0014
|
||||
|
||||
Reference in New Issue
Block a user