diff --git a/Algorithm.CSharp/QuantConnect.Algorithm.CSharp.csproj b/Algorithm.CSharp/QuantConnect.Algorithm.CSharp.csproj
index b8ef6d4c9b4c..358d8f7d7de5 100644
--- a/Algorithm.CSharp/QuantConnect.Algorithm.CSharp.csproj
+++ b/Algorithm.CSharp/QuantConnect.Algorithm.CSharp.csproj
@@ -32,7 +32,7 @@
portable
-
+
diff --git a/Algorithm.Framework/QuantConnect.Algorithm.Framework.csproj b/Algorithm.Framework/QuantConnect.Algorithm.Framework.csproj
index f593ae295c0e..46d7734a7ba2 100644
--- a/Algorithm.Framework/QuantConnect.Algorithm.Framework.csproj
+++ b/Algorithm.Framework/QuantConnect.Algorithm.Framework.csproj
@@ -29,7 +29,7 @@
LICENSE
-
+
diff --git a/Algorithm.Python/QuantConnect.Algorithm.Python.csproj b/Algorithm.Python/QuantConnect.Algorithm.Python.csproj
index 83f2cff8cad8..27d959076f69 100644
--- a/Algorithm.Python/QuantConnect.Algorithm.Python.csproj
+++ b/Algorithm.Python/QuantConnect.Algorithm.Python.csproj
@@ -37,7 +37,7 @@
-
+
diff --git a/Algorithm/QuantConnect.Algorithm.csproj b/Algorithm/QuantConnect.Algorithm.csproj
index e282739d4e05..030e18be98c2 100644
--- a/Algorithm/QuantConnect.Algorithm.csproj
+++ b/Algorithm/QuantConnect.Algorithm.csproj
@@ -29,7 +29,7 @@
LICENSE
-
+
diff --git a/AlgorithmFactory/QuantConnect.AlgorithmFactory.csproj b/AlgorithmFactory/QuantConnect.AlgorithmFactory.csproj
index fb53d48b563f..c0d552c13880 100644
--- a/AlgorithmFactory/QuantConnect.AlgorithmFactory.csproj
+++ b/AlgorithmFactory/QuantConnect.AlgorithmFactory.csproj
@@ -28,7 +28,7 @@
LICENSE
-
+
diff --git a/Brokerages/BrokerageConcurrentMessageHandler.cs b/Brokerages/BrokerageConcurrentMessageHandler.cs
index cceb6cb9ac7c..d0b896f47996 100644
--- a/Brokerages/BrokerageConcurrentMessageHandler.cs
+++ b/Brokerages/BrokerageConcurrentMessageHandler.cs
@@ -172,8 +172,6 @@ private interface ILock : IDisposable
{
int CurrentWriteCount { get; }
- void EnterReadLock();
-
void ExitReadLock();
bool TryEnterReadLockImmediately();
@@ -204,8 +202,6 @@ public ReaderWriterLockWrapper()
{
_lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
}
-
- public void EnterReadLock() => _lock.EnterWriteLock();
public void ExitReadLock() => _lock.ExitWriteLock();
public bool TryEnterReadLockImmediately() => _lock.TryEnterWriteLock(0);
public void EnterWriteLock() => _lock.EnterReadLock();
@@ -230,8 +226,6 @@ public MonitorWrapper()
_lockObject = new object();
}
- public void EnterReadLock() => Monitor.Enter(_lockObject);
-
public void ExitReadLock() => Monitor.Exit(_lockObject);
public bool TryEnterReadLockImmediately() => Monitor.TryEnter(_lockObject);
diff --git a/Common/Extensions.cs b/Common/Extensions.cs
index 8bace7209c7b..9ecf5dcc33ca 100644
--- a/Common/Extensions.cs
+++ b/Common/Extensions.cs
@@ -4451,10 +4451,9 @@ public static bool IsCustomDataType(Symbol symbol, Type type)
/// Security for which we would like to make a market order
/// Quantity of the security we are seeking to trade
/// Time the order was placed
- /// This out parameter will contain the market order constructed
- public static CashAmount GetMarketOrderFees(Security security, decimal quantity, DateTime time, out MarketOrder marketOrder)
+ public static CashAmount GetMarketOrderFees(Security security, decimal quantity, DateTime time)
{
- marketOrder = new MarketOrder(security.Symbol, quantity, time);
+ var marketOrder = new MarketOrder(security.Symbol, quantity, time);
return security.FeeModel.GetOrderFee(new OrderFeeParameters(security, marketOrder)).Value;
}
diff --git a/Common/Orders/OrderSizing.cs b/Common/Orders/OrderSizing.cs
index 7fb4bc82aaa3..88e601980add 100644
--- a/Common/Orders/OrderSizing.cs
+++ b/Common/Orders/OrderSizing.cs
@@ -95,7 +95,7 @@ public static decimal GetUnorderedQuantity(IAlgorithm algorithm, IPortfolioTarge
// Adjust the order quantity taking into account the fee's
if (accountForFees && security.Symbol.SecurityType == SecurityType.Crypto && quantity > 0)
{
- var orderFee = Extensions.GetMarketOrderFees(security, quantity, algorithm.UtcTime, out _);
+ var orderFee = Extensions.GetMarketOrderFees(security, quantity, algorithm.UtcTime);
var baseCurrency = ((Crypto)security).BaseCurrency.Symbol;
if (baseCurrency == orderFee.Currency)
{
diff --git a/Common/QuantConnect.csproj b/Common/QuantConnect.csproj
index 9ba34d1e87bd..9fa973efd104 100644
--- a/Common/QuantConnect.csproj
+++ b/Common/QuantConnect.csproj
@@ -35,7 +35,7 @@
-
+
diff --git a/Common/Securities/SecurityHolding.cs b/Common/Securities/SecurityHolding.cs
index 71c0860f2793..ef441fb27a92 100644
--- a/Common/Securities/SecurityHolding.cs
+++ b/Common/Securities/SecurityHolding.cs
@@ -14,8 +14,6 @@
*/
using System;
-using QuantConnect.Orders;
-using QuantConnect.Orders.Fees;
using QuantConnect.Algorithm.Framework.Portfolio;
namespace QuantConnect.Securities
@@ -478,22 +476,26 @@ public virtual ConvertibleCashAmount GetQuantityValue(decimal quantity, decimal
/// Does not use the transaction model for market fills but should.
public virtual decimal TotalCloseProfit(bool includeFees = true, decimal? exitPrice = null, decimal? entryPrice = null, decimal? quantity = null)
{
- var quantityToUse = quantity ?? Quantity;
- if (quantityToUse == 0)
+ var quantityToUse = Quantity;
+ if (quantity.HasValue)
+ {
+ quantityToUse = quantity.Value;
+ }
+ else if (!_invested)
{
return 0;
}
- // this is in the account currency
- var orderFee = Extensions.GetMarketOrderFees(_security, -quantityToUse, _security.LocalTime.ConvertToUtc(_security.Exchange.TimeZone), out var marketOrder);
-
var feesInAccountCurrency = 0m;
if (includeFees)
{
- feesInAccountCurrency = _currencyConverter.ConvertToAccountCurrency(orderFee).Amount;
+ // this is in the account currency
+ var liquidationFees = Extensions.GetMarketOrderFees(_security, -quantityToUse, _security.LocalTime.ConvertToUtc(_security.Exchange.TimeZone));
+ feesInAccountCurrency = _currencyConverter.ConvertToAccountCurrency(liquidationFees).Amount;
}
- var price = marketOrder.Direction == OrderDirection.Sell ? _security.BidPrice : _security.AskPrice;
+ // if we are long, we would need to sell against the bid
+ var price = IsLong ? _security.BidPrice : _security.AskPrice;
if (price == 0)
{
// Bid/Ask prices can both be equal to 0. This usually happens when we request our holdings from
diff --git a/Engine/QuantConnect.Lean.Engine.csproj b/Engine/QuantConnect.Lean.Engine.csproj
index feab03df4c47..6ff44486c48d 100644
--- a/Engine/QuantConnect.Lean.Engine.csproj
+++ b/Engine/QuantConnect.Lean.Engine.csproj
@@ -41,7 +41,7 @@
-
+
diff --git a/Engine/Results/BacktestingResultHandler.cs b/Engine/Results/BacktestingResultHandler.cs
index 8e650045f446..7d6367682c20 100644
--- a/Engine/Results/BacktestingResultHandler.cs
+++ b/Engine/Results/BacktestingResultHandler.cs
@@ -400,15 +400,11 @@ protected void SendFinalResult()
/// Algorithm we're working on.
/// Algorithm starting capital for statistics calculations
/// While setting the algorithm the backtest result handler.
- public virtual void SetAlgorithm(IAlgorithm algorithm, decimal startingPortfolioValue)
+ public override void SetAlgorithm(IAlgorithm algorithm, decimal startingPortfolioValue)
{
- Algorithm = algorithm;
+ base.SetAlgorithm(algorithm, startingPortfolioValue);
Algorithm.SetStatisticsService(this);
State["Name"] = Algorithm.Name;
- StartingPortfolioValue = startingPortfolioValue;
- DailyPortfolioValue = StartingPortfolioValue;
- CumulativeMaxPortfolioValue = StartingPortfolioValue;
- AlgorithmCurrencySymbol = Currencies.GetCurrencySymbol(Algorithm.AccountCurrency);
_capacityEstimate = new CapacityEstimate(Algorithm);
_progressMonitor = new BacktestProgressMonitor(Algorithm.TimeKeeper, Algorithm.EndDate);
@@ -418,21 +414,7 @@ public virtual void SetAlgorithm(IAlgorithm algorithm, decimal startingPortfolio
ResamplePeriod = TimeSpan.FromMinutes(resampleMinutes);
Log.Trace("BacktestingResultHandler(): Sample Period Set: " + resampleMinutes.ToStringInvariant("00.00"));
- //Set the security / market types.
- var types = new List();
- foreach (var kvp in Algorithm.Securities)
- {
- var security = kvp.Value;
-
- if (!types.Contains(security.Type)) types.Add(security.Type);
- }
- SecurityType(types);
-
ConfigureConsoleTextWriter(algorithm);
-
- // Wire algorithm name and tags updates
- algorithm.NameUpdated += (sender, name) => AlgorithmNameUpdated(name);
- algorithm.TagsUpdated += (sender, tags) => AlgorithmTagsUpdated(tags);
}
///
@@ -496,18 +478,6 @@ protected override void AddToLogStore(string message)
base.AddToLogStore(messageToLog);
}
- ///
- /// Send list of security asset types the algorithm uses to browser.
- ///
- public virtual void SecurityType(List types)
- {
- var packet = new SecurityTypesPacket
- {
- Types = types
- };
- Messages.Enqueue(packet);
- }
-
///
/// Send an error message back to the browser highlighted in red with a stacktrace.
///
@@ -743,6 +713,11 @@ public virtual void ProcessSynchronousEvents(bool forceProcess = false)
{
if (Algorithm == null) return;
+ var time = Algorithm.UtcTime;
+
+ // Check to see if we should update stored portfolio values
+ UpdatePortfolioValues(time, forceProcess);
+
_capacityEstimate.UpdateMarketCapacity(forceProcess);
// Invalidate the processed days count so it gets recalculated
@@ -751,7 +726,6 @@ public virtual void ProcessSynchronousEvents(bool forceProcess = false)
// Update the equity bar
UpdateAlgorithmEquity();
- var time = Algorithm.UtcTime;
if (time > _nextSample || forceProcess)
{
//Set next sample time: 4000 samples per backtest
@@ -762,14 +736,14 @@ public virtual void ProcessSynchronousEvents(bool forceProcess = false)
//Also add the user samples / plots to the result handler tracking:
SampleRange(Algorithm.GetChartUpdates());
- }
- ProcessAlgorithmLogs();
+ ProcessAlgorithmLogs();
- //Set the running statistics:
- foreach (var pair in Algorithm.RuntimeStatistics)
- {
- RuntimeStatistic(pair.Key, pair.Value);
+ //Set the running statistics:
+ foreach (var pair in Algorithm.RuntimeStatistics)
+ {
+ RuntimeStatistic(pair.Key, pair.Value);
+ }
}
}
diff --git a/Engine/Results/BaseResultsHandler.cs b/Engine/Results/BaseResultsHandler.cs
index 7ae7e356cd38..dc774d2ab1c0 100644
--- a/Engine/Results/BaseResultsHandler.cs
+++ b/Engine/Results/BaseResultsHandler.cs
@@ -22,7 +22,6 @@
using System.Threading;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
-using QuantConnect.Configuration;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Indicators;
@@ -34,6 +33,7 @@
using QuantConnect.Packets;
using QuantConnect.Securities.Positions;
using QuantConnect.Statistics;
+using QuantConnect.Util;
namespace QuantConnect.Lean.Engine.Results
{
@@ -51,6 +51,10 @@ public abstract class BaseResultsHandler
private static readonly TextWriter StandardOut = Console.Out;
private static readonly TextWriter StandardError = Console.Error;
+ private ReferenceWrapper _portfolioValue;
+ private ReferenceWrapper _benchmarkValue;
+ private ReferenceWrapper _unrealizedProfit;
+
private string _hostName;
private Bar _currentAlgorithmEquity;
@@ -474,6 +478,59 @@ public virtual void Initialize(ResultHandlerInitializeParameters parameters)
};
}
+ ///
+ /// Set the Algorithm instance for ths result.
+ ///
+ /// Algorithm we're working on.
+ /// Algorithm starting capital for statistics calculations
+ /// While setting the algorithm the backtest result handler.
+ public virtual void SetAlgorithm(IAlgorithm algorithm, decimal startingPortfolioValue)
+ {
+ Algorithm = algorithm;
+ AlgorithmCurrencySymbol = Currencies.GetCurrencySymbol(Algorithm.AccountCurrency);
+ CumulativeMaxPortfolioValue = DailyPortfolioValue = StartingPortfolioValue = startingPortfolioValue;
+
+ _unrealizedProfit = new ReferenceWrapper(0);
+ _benchmarkValue = new ReferenceWrapper(0);
+ _portfolioValue = new ReferenceWrapper(startingPortfolioValue);
+
+ SecurityType(Algorithm.Securities.Select(x => x.Key.SecurityType).Distinct().ToList());
+
+ // Wire algorithm name and tags updates
+ algorithm.NameUpdated += (sender, name) => AlgorithmNameUpdated(name);
+ algorithm.TagsUpdated += (sender, tags) => AlgorithmTagsUpdated(tags);
+ }
+
+ ///
+ /// Send list of security asset types the algorithm uses to browser.
+ ///
+ public virtual void SecurityType(List types)
+ {
+ var packet = new SecurityTypesPacket
+ {
+ Types = types
+ };
+ Messages.Enqueue(packet);
+ }
+
+ ///
+ /// Handles updates to the algorithm's name
+ ///
+ /// The new name
+ public virtual void AlgorithmNameUpdated(string name)
+ {
+ Messages.Enqueue(new AlgorithmNameUpdatePacket(AlgorithmId, name));
+ }
+
+ ///
+ /// Handles updates to the algorithm's tags
+ ///
+ /// The new tags
+ public virtual void AlgorithmTagsUpdated(HashSet tags)
+ {
+ Messages.Enqueue(new AlgorithmTagsUpdatePacket(AlgorithmId, tags));
+ }
+
///
/// Result handler update method
///
@@ -545,7 +602,7 @@ protected decimal GetNetReturn()
{
//Some users have $0 in their brokerage account / starting cash of $0. Prevent divide by zero errors
return StartingPortfolioValue > 0 ?
- (Algorithm.Portfolio.TotalPortfolioValue - StartingPortfolioValue) / StartingPortfolioValue
+ (GetPortfolioValue() - StartingPortfolioValue) / StartingPortfolioValue
: 0;
}
@@ -560,26 +617,14 @@ protected decimal GetNetReturn()
///
/// Useful so that live trading implementation can freeze the returned value if there is no user exchange open
/// so we ignore extended market hours updates
- protected virtual decimal GetPortfolioValue()
- {
- return Algorithm.Portfolio.TotalPortfolioValue;
- }
+ protected decimal GetPortfolioValue() => _portfolioValue.Value;
///
/// Gets the current benchmark value
///
/// Useful so that live trading implementation can freeze the returned value if there is no user exchange open
/// so we ignore extended market hours updates
- /// Time to resolve benchmark value at
- protected virtual decimal GetBenchmarkValue(DateTime time)
- {
- if (Algorithm == null || Algorithm.Benchmark == null)
- {
- // this could happen if the algorithm exploded mid initialization
- return 0;
- }
- return Algorithm.Benchmark.Evaluate(time).SmartRounding();
- }
+ protected virtual decimal GetBenchmarkValue() => _benchmarkValue.Value;
///
/// Samples portfolio equity, benchmark, and daily performance
@@ -588,6 +633,10 @@ protected virtual decimal GetBenchmarkValue(DateTime time)
/// Current UTC time in the AlgorithmManager loop
public virtual void Sample(DateTime time)
{
+ // Force an update for our values before doing our daily sample
+ UpdatePortfolioValues(time);
+ UpdateBenchmarkValue(time);
+
var currentPortfolioValue = GetPortfolioValue();
var portfolioPerformance = DailyPortfolioValue == 0 ? 0 : Math.Round((currentPortfolioValue - DailyPortfolioValue) * 100 / DailyPortfolioValue, 10);
@@ -597,7 +646,7 @@ public virtual void Sample(DateTime time)
// Sample all our default charts
UpdateAlgorithmEquity();
SampleEquity(time);
- SampleBenchmark(time, GetBenchmarkValue(time));
+ SampleBenchmark(time, GetBenchmarkValue());
SamplePerformance(time, portfolioPerformance);
SampleDrawdown(time, currentPortfolioValue);
SampleSalesVolume(time);
@@ -846,11 +895,11 @@ protected SortedDictionary GetAlgorithmRuntimeStatistics(Diction
runtimeStatistics["Probabilistic Sharpe Ratio"] = "0%";
}
- runtimeStatistics["Unrealized"] = AlgorithmCurrencySymbol + Algorithm.Portfolio.TotalUnrealizedProfit.ToStringInvariant("N2");
+ runtimeStatistics["Unrealized"] = AlgorithmCurrencySymbol + _unrealizedProfit.Value.ToStringInvariant("N2");
runtimeStatistics["Fees"] = $"-{AlgorithmCurrencySymbol}{Algorithm.Portfolio.TotalFees.ToStringInvariant("N2")}";
runtimeStatistics["Net Profit"] = AlgorithmCurrencySymbol + Algorithm.Portfolio.TotalNetProfit.ToStringInvariant("N2");
runtimeStatistics["Return"] = GetNetReturn().ToStringInvariant("P");
- runtimeStatistics["Equity"] = AlgorithmCurrencySymbol + Algorithm.Portfolio.TotalPortfolioValue.ToStringInvariant("N2");
+ runtimeStatistics["Equity"] = AlgorithmCurrencySymbol + GetPortfolioValue().ToStringInvariant("N2");
runtimeStatistics["Holdings"] = AlgorithmCurrencySymbol + Algorithm.Portfolio.TotalHoldingsValue.ToStringInvariant("N2");
runtimeStatistics["Volume"] = AlgorithmCurrencySymbol + Algorithm.Portfolio.TotalSaleVolume.ToStringInvariant("N2");
@@ -1078,5 +1127,19 @@ protected void UpdateAlgorithmEquity()
{
UpdateAlgorithmEquity(CurrentAlgorithmEquity);
}
+
+ protected virtual void UpdatePortfolioValues(DateTime time, bool force = false)
+ {
+ _portfolioValue = new ReferenceWrapper(Algorithm?.Portfolio.TotalPortfolioValue ?? 0);
+ _unrealizedProfit = new ReferenceWrapper(Algorithm?.Portfolio.TotalUnrealizedProfit ?? 0);
+ }
+
+ protected virtual void UpdateBenchmarkValue(DateTime time, bool force = false)
+ {
+ if (Algorithm != null && Algorithm.Benchmark != null)
+ {
+ _benchmarkValue = new ReferenceWrapper(Algorithm.Benchmark.Evaluate(time).SmartRounding());
+ }
+ }
}
}
diff --git a/Engine/Results/LiveTradingResultHandler.cs b/Engine/Results/LiveTradingResultHandler.cs
index 7b544f55f795..71be6dd23c15 100644
--- a/Engine/Results/LiveTradingResultHandler.cs
+++ b/Engine/Results/LiveTradingResultHandler.cs
@@ -77,8 +77,6 @@ public class LiveTradingResultHandler : BaseResultsHandler, IResultHandler
private bool _sampleChartAlways;
private bool _userExchangeIsOpen;
- private ReferenceWrapper _portfolioValue;
- private ReferenceWrapper _benchmarkValue;
private DateTime _lastChartSampleLogicCheck;
private readonly Dictionary _exchangeHours;
@@ -95,9 +93,6 @@ public LiveTradingResultHandler()
_samplePortfolioPeriod = _storeInsightPeriod = TimeSpan.FromMinutes(10);
_streamedChartLimit = Config.GetInt("streamed-chart-limit", 12);
_streamedChartGroupSize = Config.GetInt("streamed-chart-group-size", 3);
-
- _portfolioValue = new ReferenceWrapper(0);
- _benchmarkValue = new ReferenceWrapper(0);
}
///
@@ -589,16 +584,6 @@ public void ErrorMessage(string message, string stacktrace = "")
AddToLogStore(message + (!string.IsNullOrEmpty(stacktrace) ? ": StackTrace: " + stacktrace : string.Empty));
}
- ///
- /// Send a list of secutity types that the algorithm trades to the browser to show the market clock - is this market open or closed!
- ///
- /// List of security types
- public void SecurityType(List types)
- {
- var packet = new SecurityTypesPacket { Types = types };
- Messages.Enqueue(packet);
- }
-
///
/// Send a runtime error back to the users browser and highlight it red.
///
@@ -713,23 +698,10 @@ protected void SampleRange(IEnumerable updates)
///
/// Algorithm object matching IAlgorithm interface
/// Algorithm starting capital for statistics calculations
- public virtual void SetAlgorithm(IAlgorithm algorithm, decimal startingPortfolioValue)
+ public override void SetAlgorithm(IAlgorithm algorithm, decimal startingPortfolioValue)
{
- Algorithm = algorithm;
+ base.SetAlgorithm(algorithm, startingPortfolioValue);
Algorithm.SetStatisticsService(this);
- DailyPortfolioValue = StartingPortfolioValue = startingPortfolioValue;
- _portfolioValue = new ReferenceWrapper(startingPortfolioValue);
- CumulativeMaxPortfolioValue = StartingPortfolioValue;
- AlgorithmCurrencySymbol = Currencies.GetCurrencySymbol(Algorithm.AccountCurrency);
-
- var types = new List();
- foreach (var kvp in Algorithm.Securities)
- {
- var security = kvp.Value;
-
- if (!types.Contains(security.Type)) types.Add(security.Type);
- }
- SecurityType(types);
// we need to forward Console.Write messages to the algorithm's Debug function
var debug = new FuncTextWriter(algorithm.Debug);
@@ -738,13 +710,8 @@ public virtual void SetAlgorithm(IAlgorithm algorithm, decimal startingPortfolio
Console.SetError(error);
UpdateAlgorithmStatus();
-
- // Wire algorithm name and tags updates
- algorithm.NameUpdated += (sender, name) => AlgorithmNameUpdated(name);
- algorithm.TagsUpdated += (sender, tags) => AlgorithmTagsUpdated(tags);
}
-
///
/// Send a algorithm status update to the user of the algorithms running state.
///
@@ -1063,7 +1030,7 @@ public virtual void ProcessSynchronousEvents(bool forceProcess = false)
var time = DateTime.UtcNow;
// Check to see if we should update stored portfolio values
- UpdatePortfolioValue(time, forceProcess);
+ UpdatePortfolioValues(time, forceProcess);
// Update the equity bar
UpdateAlgorithmEquity();
@@ -1177,39 +1144,6 @@ public override void OnSecuritiesChanged(SecurityChanges changes)
}
}
- ///
- /// Samples portfolio equity, benchmark, and daily performance
- ///
- /// Current UTC time in the AlgorithmManager loop
- public void Sample(DateTime time)
- {
- // Force an update for our values before doing our daily sample
- UpdatePortfolioValue(time);
- UpdateBenchmarkValue(time);
- base.Sample(time);
- }
-
- ///
- /// Gets the current portfolio value
- ///
- /// Useful so that live trading implementation can freeze the returned value if there is no user exchange open
- /// so we ignore extended market hours updates
- protected override decimal GetPortfolioValue()
- {
- return _portfolioValue.Value;
- }
-
- ///
- /// Gets the current benchmark value
- ///
- /// Useful so that live trading implementation can freeze the returned value if there is no user exchange open
- /// so we ignore extended market hours updates
- /// Time to resolve benchmark value at
- protected override decimal GetBenchmarkValue(DateTime time)
- {
- return _benchmarkValue.Value;
- }
-
///
/// True if user exchange are open and we should update portfolio and benchmark value
///
@@ -1273,20 +1207,20 @@ private void UpdateAlgorithmStatus()
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void UpdateBenchmarkValue(DateTime time, bool force = false)
+ protected override void UpdateBenchmarkValue(DateTime time, bool force = false)
{
if (force || UserExchangeIsOpen(time))
{
- _benchmarkValue = new ReferenceWrapper(base.GetBenchmarkValue(time));
+ base.UpdateBenchmarkValue(time, force);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void UpdatePortfolioValue(DateTime time, bool force = false)
+ protected override void UpdatePortfolioValues(DateTime time, bool force = false)
{
if (force || UserExchangeIsOpen(time))
{
- _portfolioValue = new ReferenceWrapper(base.GetPortfolioValue());
+ base.UpdatePortfolioValues(time, force);
}
}
@@ -1329,23 +1263,5 @@ public void SetSummaryStatistic(string name, string value)
{
SummaryStatistic(name, value);
}
-
- ///
- /// Handles updates to the algorithm's name
- ///
- /// The new name
- public virtual void AlgorithmNameUpdated(string name)
- {
- Messages.Enqueue(new AlgorithmNameUpdatePacket(AlgorithmId, name));
- }
-
- ///
- /// Handles updates to the algorithm's tags
- ///
- /// The new tags
- public virtual void AlgorithmTagsUpdated(HashSet tags)
- {
- Messages.Enqueue(new AlgorithmTagsUpdatePacket(AlgorithmId, tags));
- }
}
}
diff --git a/Indicators/QuantConnect.Indicators.csproj b/Indicators/QuantConnect.Indicators.csproj
index 56eda6417efa..62ffe9192c61 100644
--- a/Indicators/QuantConnect.Indicators.csproj
+++ b/Indicators/QuantConnect.Indicators.csproj
@@ -31,7 +31,7 @@
-
+
diff --git a/Report/QuantConnect.Report.csproj b/Report/QuantConnect.Report.csproj
index 7aa0f4405e3e..c81fc164aa18 100644
--- a/Report/QuantConnect.Report.csproj
+++ b/Report/QuantConnect.Report.csproj
@@ -39,7 +39,7 @@
LICENSE
-
+
diff --git a/Research/QuantConnect.Research.csproj b/Research/QuantConnect.Research.csproj
index 005c480ec416..728c5f33ec22 100644
--- a/Research/QuantConnect.Research.csproj
+++ b/Research/QuantConnect.Research.csproj
@@ -34,7 +34,7 @@
-
+
diff --git a/Tests/Engine/Results/BaseResultsHandlerTests.cs b/Tests/Engine/Results/BaseResultsHandlerTests.cs
index 1f763e3bcbc2..de1ed7e467a6 100644
--- a/Tests/Engine/Results/BaseResultsHandlerTests.cs
+++ b/Tests/Engine/Results/BaseResultsHandlerTests.cs
@@ -94,7 +94,7 @@ public void ExposureIsCalculatedEvenWhenPortfolioIsNotInvested(decimal holdingsQ
protectedMockResultHandler.Setup("SampleEquity", ItExpr.IsAny());
protectedMockResultHandler.Setup("SampleBenchmark", ItExpr.IsAny(), ItExpr.IsAny());
protectedMockResultHandler
- .Setup("GetBenchmarkValue", ItExpr.IsAny())
+ .Setup("GetBenchmarkValue")
.Returns(0m);
protectedMockResultHandler.Setup("SamplePerformance", ItExpr.IsAny(), ItExpr.IsAny());
protectedMockResultHandler.Setup("SampleDrawdown", ItExpr.IsAny(), ItExpr.IsAny());
@@ -144,7 +144,7 @@ public void ExposureIsCalculatedEvenWhenPortfolioIsNotInvested(decimal holdingsQ
// BaseResultHandler.Algorithm property accessed once by BaseResultHandler.SampleExposure()
// and once by BaseResultHandler.GetPortfolioValue() + 2 for sampling current equity value
- protectedMockResultHandler.VerifyGet("Algorithm", Times.Exactly(5));
+ protectedMockResultHandler.VerifyGet("Algorithm", Times.Exactly(6));
// Sample should've been called twice, by BaseResultHandler.SampleExposure(), once for the long and once for the short positions
protectedMockResultHandler.Verify("Sample", Times.Exactly(2), ItExpr.IsAny(), ItExpr.IsAny(),
diff --git a/Tests/Python/PythonThreadingTests.cs b/Tests/Python/PythonThreadingTests.cs
index 259dab40995f..d91b9256293e 100644
--- a/Tests/Python/PythonThreadingTests.cs
+++ b/Tests/Python/PythonThreadingTests.cs
@@ -14,10 +14,8 @@
*
*/
-using System;
using Python.Runtime;
using NUnit.Framework;
-using System.Threading;
using QuantConnect.Python;
using System.Threading.Tasks;
@@ -26,87 +24,6 @@ namespace QuantConnect.Tests.Python
[TestFixture]
public class PythonThreadingTests
{
- [TestCase("Field", false)]
- [TestCase("Func()", false)]
- [TestCase("Property", false)]
- [TestCase("Field", true)]
- [TestCase("Func()", true)]
- [TestCase("Property", true)]
- public void CallingCShapReleasesGil(string target, bool useInstance)
- {
- var lockInstance = new object();
-
- using var tookGil = new ManualResetEvent(false);
- using var tookLock = new ManualResetEvent(false);
-
- PyObject method;
- PyObject propertyWrapper;
- using (Py.GIL())
- {
- var module = PyModule.FromString("ReleaseGil", $@"
-from clr import AddReference
-AddReference('QuantConnect.Tests')
-
-from QuantConnect.Tests.Python import *
-import time
-
-def Method():
- return 1
-
-def PropertyCaller(tookGil, tookLock, useInstance):
- tookGil.Set()
- tookLock.WaitOne()
- if useInstance:
- instance = PythonThreadingTests.TestPropertyWrapper()
- return instance.Instance{target}
- else:
- return PythonThreadingTests.TestPropertyWrapper.{target}
-");
- method = module.GetAttr("Method");
- propertyWrapper = module.GetAttr("PropertyCaller");
- }
-
- TestPropertyWrapper.Func = () =>
- {
- lock (lockInstance)
- {
- Thread.Sleep(500);
- using (Py.GIL())
- {
- return method.Invoke().As();
- }
- }
- };
-
- // task1: has the GIL, go into python, go back into C# and want the C# lock, so he should release the GIL
- // task2: has the C# lock and want's the GIL
- var task1 = Task.Run(() =>
- {
- using (Py.GIL())
- {
- propertyWrapper.Invoke(tookGil, tookLock, useInstance);
- }
- });
-
- var task2 = Task.Run(() =>
- {
- lock (lockInstance)
- {
- // we take the C# lock and wait and try to get the py gil which should be taken by task 1
- tookLock.Set();
- tookGil.WaitOne();
- using (Py.GIL())
- {
- method.Invoke();
- }
- }
- });
-
- var result = Task.WaitAll(new[] { task1, task2 }, TimeSpan.FromSeconds(3));
-
- Assert.IsTrue(result);
- }
-
[Test]
public void ImportsCanBeExecutedFromDifferentThreads()
{
@@ -131,21 +48,5 @@ public void ImportsCanBeExecutedFromDifferentThreads()
}
}).Wait();
}
- public class TestPropertyWrapper
- {
- public static Func Func { get; set; }
- public static int Field => Func();
- public static int Property
- {
- get
- {
- return Func();
- }
- }
-
- public Func InstanceFunc => Func;
- public int InstanceField => Field;
- public int InstanceProperty => Property;
- }
}
}
diff --git a/Tests/QuantConnect.Tests.csproj b/Tests/QuantConnect.Tests.csproj
index 9a8a899176c6..87810318cc75 100644
--- a/Tests/QuantConnect.Tests.csproj
+++ b/Tests/QuantConnect.Tests.csproj
@@ -31,7 +31,7 @@
-
+