/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using NUnit.Framework; using QuantConnect.Data; using QuantConnect.Data.Market; using QuantConnect.Securities; using System; using System.Collections.Generic; using System.Linq; namespace QuantConnect.Tests.Common.Securities { [TestFixture] public class SecurityHoldingTests { [Test] public void ComputesUnrealizedProfit() { var security = GetSecurity(Symbols.SPY, Resolution.Daily); var holding = new SecurityHolding(security, new IdentityCurrencyConverter(Currencies.USD)); var last = 100m; var bid = 99m; var ask = 101m; var orderFee = 1m; security.SetMarketPrice(new Tick(DateTime.Now, security.Symbol, last, bid, ask)); // Long scenario: expected unrealized profit take the bid price var quantity = 100m; var expected = (bid - last) * quantity - orderFee; holding.SetHoldings(last, quantity); Assert.AreEqual(expected, holding.UnrealizedProfit); // Short scenario: expected unrealized profit take the ask price quantity = -100m; expected = (ask - last) * quantity - orderFee; holding.SetHoldings(last, quantity); Assert.AreEqual(expected, holding.UnrealizedProfit); } [Test] public void Raises_QuantityChanged_WhenSetHoldingsCalled() { var arguments = new List(); var security = GetSecurity(Symbols.SPY, Resolution.Daily); security.Holdings.QuantityChanged += (sender, args) => arguments.Add(args); // invoke int overload var firstPrice = 100m; int firstQuantity = 100; security.Holdings.SetHoldings(firstPrice, firstQuantity); // invoke decimal overload var secondPrice = 101m; var secondQuantity = 200m; security.Holdings.SetHoldings(secondPrice, secondQuantity); Assert.AreEqual(2, arguments.Count); var first = arguments.First(); Assert.AreEqual(security, first.Security); Assert.AreEqual(0, first.PreviousQuantity); Assert.AreEqual(0, first.PreviousAveragePrice); var second = arguments.Last(); Assert.AreEqual(security, second.Security); Assert.AreEqual(firstQuantity, second.PreviousQuantity); Assert.AreEqual(firstPrice, second.PreviousAveragePrice); } private Security GetSecurity(Symbol symbol, Resolution resolution) { var subscriptionDataConfig = new SubscriptionDataConfig( typeof(T), symbol, resolution, TimeZones.Utc, TimeZones.Utc, true, true, false); var security = new Security( SecurityExchangeHours.AlwaysOpen(TimeZones.Utc), subscriptionDataConfig, new Cash(Currencies.USD, 0, 1m), SymbolProperties.GetDefault(Currencies.USD), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ); var reference = DateTime.Now; var referenceUtc = reference.ConvertToUtc(subscriptionDataConfig.DataTimeZone); var timeKeeper = new TimeKeeper(referenceUtc); security.SetLocalTimeKeeper(timeKeeper.GetLocalTimeKeeper(subscriptionDataConfig.DataTimeZone)); return security; } } }