/* * 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 System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; using QuantConnect.Algorithm; using QuantConnect.Data.Market; using QuantConnect.Orders; using QuantConnect.Orders.Fees; using QuantConnect.Securities; using QuantConnect.Securities.Option; using QuantConnect.Securities.Option.StrategyMatcher; using QuantConnect.Securities.Positions; using QuantConnect.Tests.Engine.DataFeeds; namespace QuantConnect.Tests.Common.Securities { [TestFixture] public class OptionStrategyPositionGroupBuyingPowerModelTests { private QCAlgorithm _algorithm; private SecurityPortfolioManager _portfolio; private QuantConnect.Securities.Equity.Equity _equity; private Option _callOption; private Option _putOption; [SetUp] public void Setup() { _algorithm = new AlgorithmStub(); _algorithm.SetCash(1000000); _algorithm.SetSecurityInitializer(security => security.FeeModel = new ConstantFeeModel(0)); _portfolio = _algorithm.Portfolio; _equity = _algorithm.AddEquity("SPY"); var strike = 200m; var expiry = new DateTime(2016, 1, 15); var callOptionSymbol = Symbols.CreateOptionSymbol("SPY", OptionRight.Call, strike, expiry); _callOption = _algorithm.AddOptionContract(callOptionSymbol); var putOptionSymbol = Symbols.CreateOptionSymbol("SPY", OptionRight.Put, strike, expiry); _putOption = _algorithm.AddOptionContract(putOptionSymbol); } /// /// All these test cases are based on the assumption that the initial cash is 1,000,000. /// /// The formula used for the order quantity is: /// - Staying in the same position side: (cash - initial quantity * unit initial margin) / (unit initial margin + premium) /// - Reversing the position side: (cash + initial quantity * unit initial margin) / (unit initial margin + premium) /// // option strategy definition, initial quantity, order quantity, expected result private static readonly TestCaseData[] HasSufficientBuyingPowerForOrderTestCases = new[] { // Initial margin requirement|premium for NakedCall with quantities 1 and -1 are 19400|0 and 0|11200 respectively new TestCaseData(OptionStrategyDefinitions.NakedCall, 0, (1000000 - 0 * 19400) / (19400 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.NakedCall, 0, (1000000 - 0 * 19400) / (19400 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.NakedCall, 0, -(1000000 + 0 * 0) / (0 + 11200), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.NakedCall, 0, -(1000000 + 0 * 0) / (0 + 11200) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.NakedCall, 20, (1000000 - 20 * 19400) / (19400 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.NakedCall, 20, (1000000 - 20 * 19400) / (19400 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.NakedCall, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.NakedCall, 20, -(1000000 + 20 * 0) / (0 + 11200), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.NakedCall, 20, -(1000000 + 20 * 0) / (0 + 11200) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.NakedCall, -20, (1000000 + 20 * 19400) / (19400 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.NakedCall, -20, (1000000 + 20 * 19400) / (19400 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.NakedCall, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.NakedCall, -20, -(1000000 - 20 * 0) / (0 + 11200), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.NakedCall, -20, -(1000000 - 20 * 0) / (0 + 11200) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for NakedPut with quantities 1 and -1 are 3002|0 and 0|2 respectively new TestCaseData(OptionStrategyDefinitions.NakedPut, 0, (1000000 - 0 * 3002) / (3002 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.NakedPut, 0, (1000000 - 0 * 3002) / (3002 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.NakedPut, 0, -(1000000 + 0 * 0) / (0 + 2), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.NakedPut, 0, -(1000000 + 0 * 0) / (0 + 2) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.NakedPut, 20, (1000000 - 20 * 3002) / (3002 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.NakedPut, 20, (1000000 - 20 * 3002) / (3002 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.NakedPut, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.NakedPut, 20, -(1000000 + 20 * 0) / (0 + 2), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.NakedPut, 20, -(1000000 + 20 * 0) / (0 + 2) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.NakedPut, -20, (1000000 + 20 * 3002) / (3002 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.NakedPut, -20, (1000000 + 20 * 3002) / (3002 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.NakedPut, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.NakedPut, -20, -(1000000 - 20 * 0) / (0 + 2), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.NakedPut, -20, -(1000000 - 20 * 0) / (0 + 2) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for CoveredCall with quantities 1 and -1 are 19210|0 and 10250|11200 respectively new TestCaseData(OptionStrategyDefinitions.CoveredCall, 0, (1000000 - 0 * 19210) / (19210 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.CoveredCall, 0, (1000000 - 0 * 19210) / (19210 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.CoveredCall, 0, -(1000000 + 0 * 10250) / (10250 + 11200), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.CoveredCall, 0, -(1000000 + 0 * 10250) / (10250 + 11200) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.CoveredCall, 20, (1000000 - 20 * 19210) / (19210 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.CoveredCall, 20, (1000000 - 20 * 19210) / (19210 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.CoveredCall, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.CoveredCall, 20, -(1000000 + 20 * 10250) / (10250 + 11200), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.CoveredCall, 20, -(1000000 + 20 * 10250) / (10250 + 11200) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.CoveredCall, -20, (1000000 + 20 * 19210) / (19210 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.CoveredCall, -20, (1000000 + 20 * 19210) / (19210 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.CoveredCall, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.CoveredCall, -20, -(1000000 - 20 * 10250) / (10250 + 11200), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.CoveredCall, -20, -(1000000 - 20 * 10250) / (10250 + 11200) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ProtectiveCall with quantities 1 and -1 are 10250|11200 and 19210|0 respectively new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 0, (1000000 - 0 * 10250) / (10250 + 11200), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 0, (1000000 - 0 * 10250) / (10250 + 11200) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 0, -(1000000 + 0 * 19210) / (19210 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 0, -(1000000 + 0 * 19210) / (19210 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 20, (1000000 - 20 * 10250) / (10250 + 11200), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 20, (1000000 - 20 * 10250) / (10250 + 11200) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 20, -(1000000 + 20 * 19210) / (19210 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 20, -(1000000 + 20 * 19210) / (19210 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -20, (1000000 + 20 * 10250) / (10250 + 11200), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -20, (1000000 + 20 * 10250) / (10250 + 11200) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -20, -(1000000 - 20 * 19210) / (19210 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -20, -(1000000 - 20 * 19210) / (19210 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for CoveredPut with quantities 1 and -1 are 10250|0 and 10250|2 respectively new TestCaseData(OptionStrategyDefinitions.CoveredPut, 0, (1000000 - 0 * 10250) / (10250 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.CoveredPut, 0, (1000000 - 0 * 10250) / (10250 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.CoveredPut, 0, -(1000000 - 0 * 10250) / (10250 + 2), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.CoveredPut, 0, -(1000000 - 0 * 10250) / (10250 + 2) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.CoveredPut, 20, (1000000 - 20 * 10250) / (10250 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.CoveredPut, 20, (1000000 - 20 * 10250) / (10250 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.CoveredPut, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.CoveredPut, 20, -(1000000 + 20 * 10250) / (10250 + 2), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.CoveredPut, 20, -(1000000 + 20 * 10250) / (10250 + 2) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.CoveredPut, -20, (1000000 + 20 * 10250) / (10250 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.CoveredPut, -20, (1000000 + 20 * 10250) / (10250 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.CoveredPut, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.CoveredPut, -20, -(1000000 - 20 * 10250) / (10250 + 2), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.CoveredPut, -20, -(1000000 - 20 * 10250) / (10250 + 2) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ProtectivePut with quantities 1 and -1 are 10250|2 and 10250|0 respectively new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 0, (1000000 - 0 * 10250) / (10250 + 2), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 0, (1000000 - 0 * 10250) / (10250 + 2) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 0, -(1000000 + 0 * 10250) / (10250 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 0, -(1000000 + 0 * 10250) / (10250 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 20, (1000000 - 20 * 10250) / (10250 + 2), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 20, (1000000 - 20 * 10250) / (10250 + 2) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 20, -(1000000 + 20 * 10250) / (10250 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 20, -(1000000 + 20 * 10250) / (10250 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -20, (1000000 + 20 * 10250) / (10250 + 2), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -20, (1000000 + 20 * 10250) / (10250 + 2) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -20, -(1000000 - 20 * 10250) / (10250 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -20, -(1000000 - 20 * 10250) / (10250 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ProtectiveCollar with quantities 1 and -1 are 26231|0 and 26231|1 respectively new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 0, (1000000 - 0 * 26231) / (26231 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 0, (1000000 - 0 * 26231) / (26231 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 0, -(1000000 + 0 * 26231) / (26231 + 1), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 0, -(1000000 + 0 * 26231) / (26231 + 1) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 20, (1000000 - 20 * 26231) / (26231 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 20, (1000000 - 20 * 26231) / (26231 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 20, -(1000000 + 20 * 26231) / (26231 + 1), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 20, -(1000000 + 20 * 26231) / (26231 + 1) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -20, (1000000 + 20 * 26231) / (26231 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -20, (1000000 + 20 * 26231) / (26231 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -20, -(1000000 - 20 * 26231) / (26231 + 1), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -20, -(1000000 - 20 * 26231) / (26231 + 1) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for Conversion with quantities 1 and -1 are 26295|0 and 26231|146 respectively new TestCaseData(OptionStrategyDefinitions.Conversion, 0, (1000000 - 0 * 26295) / (26295 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.Conversion, 0, (1000000 - 0 * 26295) / (26295 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.Conversion, 0, -(1000000 + 0 * 26231) / (26231 + 146), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.Conversion, 0, -(1000000 + 0 * 26231) / (26231 + 146) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.Conversion, 20, (1000000 - 20 * 26295) / (26295 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.Conversion, 20, (1000000 - 20 * 26295) / (26295 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.Conversion, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.Conversion, 20, -(1000000 + 20 * 26231) / (26231 + 146), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.Conversion, 20, -(1000000 + 20 * 26231) / (26231 + 146) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.Conversion, -20, (1000000 + 20 * 26295) / (26295 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.Conversion, -20, (1000000 + 20 * 26295) / (26295 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.Conversion, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.Conversion, -20, -(1000000 - 20 * 26231) / (26231 + 146), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.Conversion, -20, -(1000000 - 20 * 26231) / (26231 + 146) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ReverseConversion with quantities 1 and -1 are 26231|146 and 26295|0 respectively new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 0, (1000000 - 0 * 26231) / (26231 + 146), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 0, (1000000 - 0 * 26231) / (26231 + 146) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 0, -(1000000 + 0 * 26295) / (26295 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 0, -(1000000 + 0 * 26295) / (26295 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 20, (1000000 - 20 * 26231) / (26231 + 146), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 20, (1000000 - 20 * 26231) / (26231 + 146) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 20, -(1000000 + 20 * 26295) / (26295 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 20, -(1000000 + 20 * 26295) / (26295 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -20, (1000000 + 20 * 26231) / (26231 + 146), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -20, (1000000 + 20 * 26231) / (26231 + 146) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -20, -(1000000 - 20 * 26295) / (26295 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -20, -(1000000 - 20 * 26295) / (26295 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for BearCallSpread with quantities 1 and -1 are 1000|0 and 0|1200 respectively new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 0, (1000000 - 0 * 1000) / (1000 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 0, (1000000 - 0 * 1000) / (1000 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 0, -(1000000 + 0 * 0) / (0 + 1200), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 0, -(1000000 + 0 * 0) / (0 + 1200) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 20, (1000000 - 20 * 1000) / (1000 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 20, (1000000 - 20 * 1000) / (1000 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 20, -(1000000 + 20 * 0) / (0 + 1200), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 20, -(1000000 + 20 * 0) / (0 + 1200) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -20, (1000000 + 20 * 1000) / (1000 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -20, (1000000 + 20 * 1000) / (1000 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -20, -(1000000 - 20 * 0) / (0 + 1200), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -20, -(1000000 - 20 * 0) / (0 + 1200) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for BearPutSpread with quantities 1 and -1 are 0|1 and 1000|0 respectively new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 0, (1000000 - 0 * 0) / (0 + 1), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 0, (1000000 - 0 * 0) / (0 + 1) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 0, -(1000000 + 0 * 1000) / (1000 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 0, -(1000000 + 0 * 1000) / (1000 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 20, (1000000 - 20 * 0) / (0 + 1), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 20, (1000000 - 20 * 0) / (0 + 1) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 20, -(1000000 + 20 * 1000) / (1000 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 20, -(1000000 + 20 * 1000) / (1000 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -20, (1000000 + 20 * 0) / (0 + 1), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -20, (1000000 + 20 * 0) / (0 + 1) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -20, -(1000000 - 20 * 1000) / (1000 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -20, -(1000000 - 20 * 1000) / (1000 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for BullCallSpread with quantities 1 and -1 are 0|1200 and 1000|0 respectively new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 0, (1000000 - 0 * 0) / (0 + 1200), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 0, (1000000 - 0 * 0) / (0 + 1200) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 0, -(1000000 + 0 * 1000) / (1000 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 0, -(1000000 + 0 * 1000) / (1000 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 20, (1000000 - 20 * 0) / (0 + 1200), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 20, (1000000 - 20 * 0) / (0 + 1200) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 20, -(1000000 + 20 * 1000) / (1000 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 20, -(1000000 + 20 * 1000) / (1000 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -20, (1000000 + 20 * 0) / (0 + 1200), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -20, (1000000 + 20 * 0) / (0 + 1200) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -20, -(1000000 - 20 * 1000) / (1000 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -20, -(1000000 - 20 * 1000) / (1000 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for BullPutSpread with quantities 1 and -1 are 1000|0 and 0|1 respectively new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 0, (1000000 - 0 * 1000) / (1000 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 0, (1000000 - 0 * 1000) / (1000 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 0, -(1000000 + 0 * 0) / (0 + 1), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 0, -(1000000 + 0 * 0) / (0 + 1) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 20, (1000000 - 20 * 1000) / (1000 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 20, (1000000 - 20 * 1000) / (1000 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 20, -(1000000 + 20 * 0) / (0 + 1), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 20, -(1000000 + 20 * 0) / (0 + 1) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -20, (1000000 + 20 * 1000) / (1000 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -20, (1000000 + 20 * 1000) / (1000 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -20, -(1000000 - 20 * 0) / (0 + 1), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -20, -(1000000 - 20 * 0) / (0 + 1) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for Straddle with quantities 1 and -1 are 0|11202 and 19402|0 respectively new TestCaseData(OptionStrategyDefinitions.Straddle, 0, (1000000 - 0 * 0) / (0 + 11202), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.Straddle, 0, (1000000 - 0 * 0) / (0 + 11202) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.Straddle, 0, -(1000000 + 0 * 19402) / (19402 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.Straddle, 0, -(1000000 + 0 * 19402) / (19402 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.Straddle, 20, (1000000 - 20 * 0) / (0 + 11202), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.Straddle, 20, (1000000 - 20 * 0) / (0 + 11202) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.Straddle, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.Straddle, 20, -(1000000 + 20 * 19402) / (19402 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.Straddle, 20, -(1000000 + 20 * 19402) / (19402 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.Straddle, -20, (1000000 + 20 * 0) / (0 + 11202), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.Straddle, -20, (1000000 + 20 * 0) / (0 + 11202) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.Straddle, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.Straddle, -20, -(1000000 - 20 * 19402) / (19402 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.Straddle, -20, -(1000000 - 20 * 19402) / (19402 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ShortStraddle with quantities 1 and -1 are 19402|0 and 0|11202 respectively new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 0, (1000000 - 0 * 19402) / (19402 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 0, (1000000 - 0 * 19402) / (19402 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 0, -(1000000 + 0 * 0) / (0 + 11202), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 0, -(1000000 + 0 * 0) / (0 + 11202) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 20, (1000000 - 20 * 19402) / (19402 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 20, (1000000 - 20 * 19402) / (19402 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 20, -(1000000 + 20 * 0) / (0 + 11202), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 20, -(1000000 + 20 * 0) / (0 + 11202) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -20, (1000000 + 20 * 19402) / (19402 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -20, (1000000 + 20 * 19402) / (19402 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -20, -(1000000 - 20 * 0) / (0 + 11202), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -20, -(1000000 - 20 * 0) / (0 + 11202) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for Strangle with quantities 1 and -1 are 0|10002 and 18202|0 respectively new TestCaseData(OptionStrategyDefinitions.Strangle, 0, (1000000 - 0 * 0) / (0 + 10002), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.Strangle, 0, (1000000 - 0 * 0) / (0 + 10002) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.Strangle, 0, -(1000000 + 0 * 18202) / (18202 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.Strangle, 0, -(1000000 + 0 * 18202) / (18202 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.Strangle, 20, (1000000 - 20 * 0) / (0 + 10002), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.Strangle, 20, (1000000 - 20 * 0) / (0 + 10002) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.Strangle, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.Strangle, 20, -(1000000 + 20 * 18202) / (18202 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.Strangle, 20, -(1000000 + 20 * 18202) / (18202 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.Strangle, -20, (1000000 + 20 * 0) / (0 + 10002), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.Strangle, -20, (1000000 + 20 * 0) / (0 + 10002) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.Strangle, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.Strangle, -20, -(1000000 - 20 * 18202) / (18202 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.Strangle, -20, -(1000000 - 20 * 18202) / (18202 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ShortStrangle with quantities 1 and -1 are 18202|0 and 0|10002 respectively new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 0, (1000000 - 0 * 18202) / (18202 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 0, (1000000 - 0 * 18202) / (18202 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 0, -(1000000 + 0 * 0) / (0 + 10002), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 0, -(1000000 + 0 * 0) / (0 + 10002) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 20, (1000000 - 20 * 18202) / (18202 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 20, (1000000 - 20 * 18202) / (18202 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 20, -(1000000 + 20 * 0) / (0 + 10002), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 20, -(1000000 + 20 * 0) / (0 + 10002) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -20, (1000000 + 20 * 18202) / (18202 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -20, (1000000 + 20 * 18202) / (18202 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -20, -(1000000 - 20 * 0) / (0 + 10002), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -20, -(1000000 - 20 * 0) / (0 + 10002) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ButterflyCall with quantities 1 and -1 are 0|400 and 1000|0 respectively new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 0, (1000000 - 0 * 0) / (0 + 400), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 0, (1000000 - 0 * 0) / (0 + 400) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 0, -(1000000 + 0 * 1000) / (1000 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 0, -(1000000 + 0 * 1000) / (1000 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 20, (1000000 - 20 * 0) / (0 + 400), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 20, (1000000 - 20 * 0) / (0 + 400) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 20, -(1000000 + 20 * 1000) / (1000 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 20, -(1000000 + 20 * 1000) / (1000 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -20, (1000000 + 20 * 0) / (0 + 400), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -20, (1000000 + 20 * 0) / (0 + 400) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -20, -(1000000 - 20 * 1000) / (1000 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -20, -(1000000 - 20 * 1000) / (1000 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ShortButterflyCall with quantities 1 and -1 are 1000|0 and 0|400 respectively new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 0, (1000000 - 0 * 1000) / (1000 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 0, (1000000 - 0 * 1000) / (1000 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 0, -(1000000 + 0 * 0) / (0 + 400), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 0, -(1000000 + 0 * 0) / (0 + 400) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 20, (1000000 - 20 * 1000) / (1000 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 20, (1000000 - 20 * 1000) / (1000 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 20, -(1000000 + 20 * 0) / (0 + 400), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 20, -(1000000 + 20 * 0) / (0 + 400) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -20, (1000000 + 20 * 1000) / (1000 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -20, (1000000 + 20 * 1000) / (1000 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -20, -(1000000 - 20 * 0) / (0 + 400), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -20, -(1000000 - 20 * 0) / (0 + 400) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ButterflyPut with quantities 1 and -1 are 0|1 and 1000|0 respectively new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 0, (1000000 - 0 * 0) / (0 + 1), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 0, (1000000 - 0 * 0) / (0 + 1) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 0, -(1000000 + 0 * 1000) / (1000 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 0, -(1000000 + 0 * 1000) / (1000 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 20, (1000000 - 20 * 0) / (0 + 1), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 20, (1000000 - 20 * 0) / (0 + 1) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 20, -(1000000 + 20 * 1000) / (1000 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 20, -(1000000 + 20 * 1000) / (1000 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -20, (1000000 + 20 * 0) / (0 + 1), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -20, (1000000 + 20 * 0) / (0 + 1) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -20, -(1000000 - 20 * 1000) / (1000 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -20, -(1000000 - 20 * 1000) / (1000 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ShortButterflyPut with quantities 1 and -1 are 1000|0 and 0|1 respectively new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 0, (1000000 - 0 * 1000) / (1000 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 0, (1000000 - 0 * 1000) / (1000 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 0, -(1000000 + 0 * 0) / (0 + 1), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 0, -(1000000 + 0 * 0) / (0 + 1) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 20, (1000000 - 20 * 1000) / (1000 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 20, (1000000 - 20 * 1000) / (1000 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 20, -(1000000 + 20 * 0) / (0 + 1), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 20, -(1000000 + 20 * 0) / (0 + 1) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -20, (1000000 + 20 * 1000) / (1000 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -20, (1000000 + 20 * 1000) / (1000 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -20, -(1000000 - 20 * 0) / (0 + 1), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -20, -(1000000 - 20 * 0) / (0 + 1) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for CallCalendarSpread with quantities 1 and -1 are 0|200 and 19400|0 respectively new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 0, (1000000 - 0 * 0) / (0 + 200), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 0, (1000000 - 0 * 0) / (0 + 200) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 0, -(1000000 + 0 * 19400) / (19400 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 0, -(1000000 + 0 * 19400) / (19400 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 20, (1000000 - 20 * 0) / (0 + 200), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 20, (1000000 - 20 * 0) / (0 + 200) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 20, -(1000000 + 20 * 19400) / (19400 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 20, -(1000000 + 20 * 19400) / (19400 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -20, (1000000 + 20 * 0) / (0 + 200), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -20, (1000000 + 20 * 0) / (0 + 200) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -20, -(1000000 - 20 * 19400) / (19400 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -20, -(1000000 - 20 * 19400) / (19400 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ShortCallCalendarSpread with quantities 1 and -1 are 19400|0 and 0|200 respectively new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 0, (1000000 - 0 * 19400) / (19400 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 0, (1000000 - 0 * 19400) / (19400 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 0, -(1000000 + 0 * 0) / (0 + 200), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 0, -(1000000 + 0 * 0) / (0 + 200) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 20, (1000000 - 20 * 19400) / (19400 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 20, (1000000 - 20 * 19400) / (19400 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 20, -(1000000 + 20 * 0) / (0 + 200), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 20, -(1000000 + 20 * 0) / (0 + 200) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -20, (1000000 + 20 * 19400) / (19400 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -20, (1000000 + 20 * 19400) / (19400 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -20, -(1000000 - 20 * 0) / (0 + 200), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -20, -(1000000 - 20 * 0) / (0 + 200) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for PutCalendarSpread with quantities 1 and -1 are 0|1 and 3002|0 respectively new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 0, (1000000 - 0 * 0) / (0 + 1), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 0, (1000000 - 0 * 0) / (0 + 1) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 0, -(1000000 + 0 * 3002) / (3002 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 0, -(1000000 + 0 * 3002) / (3002 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 20, (1000000 - 20 * 0) / (0 + 1), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 20, (1000000 - 20 * 0) / (0 + 1) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 20, -(1000000 + 20 * 3002) / (3002 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 20, -(1000000 + 20 * 3002) / (3002 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -20, (1000000 + 20 * 0) / (0 + 1), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -20, (1000000 + 20 * 0) / (0 + 1) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -20, -(1000000 - 20 * 3002) / (3002 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -20, -(1000000 - 20 * 3002) / (3002 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ShortPutCalendarSpread with quantities 1 and -1 are 3002|0 and 0|1 respectively new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 0, (1000000 - 0 * 3002) / (3002 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 0, (1000000 - 0 * 3002) / (3002 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 0, -(1000000 + 0 * 0) / (0 + 1), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 0, -(1000000 + 0 * 0) / (0 + 1) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 20, (1000000 - 20 * 3002) / (3002 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 20, (1000000 - 20 * 3002) / (3002 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 20, -(1000000 + 20 * 0) / (0 + 1), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 20, -(1000000 + 20 * 0) / (0 + 1) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -20, (1000000 + 20 * 3002) / (3002 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -20, (1000000 + 20 * 3002) / (3002 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -20, -(1000000 - 20 * 0) / (0 + 1), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -20, -(1000000 - 20 * 0) / (0 + 1) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for IronButterfly with quantities 1 and -1 are 1000|0 and 0|801 respectively new TestCaseData(OptionStrategyDefinitions.IronButterfly, 0, (1000000 - 0 * 1000) / (1000 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.IronButterfly, 0, (1000000 - 0 * 1000) / (1000 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.IronButterfly, 0, -(1000000 + 0 * 0) / (0 + 801), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.IronButterfly, 0, -(1000000 + 0 * 0) / (0 + 801) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.IronButterfly, 20, (1000000 - 20 * 1000) / (1000 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.IronButterfly, 20, (1000000 - 20 * 1000) / (1000 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.IronButterfly, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.IronButterfly, 20, -(1000000 + 20 * 0) / (0 + 801), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.IronButterfly, 20, -(1000000 + 20 * 0) / (0 + 801) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.IronButterfly, -20, (1000000 + 20 * 1000) / (1000 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.IronButterfly, -20, (1000000 + 20 * 1000) / (1000 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.IronButterfly, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.IronButterfly, -20, -(1000000 - 20 * 0) / (0 + 801), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.IronButterfly, -20, -(1000000 - 20 * 0) / (0 + 801) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ShortIronButterfly with quantities 1 and -1 are 0|801 and 1000|0 respectively new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 0, (1000000 - 0 * 0) / (0 + 801), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 0, (1000000 - 0 * 0) / (0 + 801) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 0, -(1000000 + 0 * 1000) / (1000 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 0, -(1000000 + 0 * 1000) / (1000 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 20, (1000000 - 20 * 0) / (0 + 801), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 20, (1000000 - 20 * 0) / (0 + 801) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 20, -(1000000 + 20 * 1000) / (1000 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 20, -(1000000 + 20 * 1000) / (1000 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -20, (1000000 + 20 * 0) / (0 + 801), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -20, (1000000 + 20 * 0) / (0 + 801) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -20, -(1000000 - 20 * 1000) / (1000 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -20, -(1000000 - 20 * 1000) / (1000 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for IronCondor with quantities 1 and -1 are 1000|0 and 0|1001 respectively new TestCaseData(OptionStrategyDefinitions.IronCondor, 0, (1000000 - 0 * 1000) / (1000 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.IronCondor, 0, (1000000 - 0 * 1000) / (1000 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.IronCondor, 0, -(1000000 + 0 * 0) / (0 + 1001), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.IronCondor, 0, -(1000000 + 0 * 0) / (0 + 1001) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.IronCondor, 20, (1000000 - 20 * 1000) / (1000 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.IronCondor, 20, (1000000 - 20 * 1000) / (1000 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.IronCondor, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.IronCondor, 20, -(1000000 + 20 * 0) / (0 + 1001), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.IronCondor, 20, -(1000000 + 20 * 0) / (0 + 1001) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.IronCondor, -20, (1000000 + 20 * 1000) / (1000 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.IronCondor, -20, (1000000 + 20 * 1000) / (1000 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.IronCondor, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.IronCondor, -20, -(1000000 - 20 * 0) / (0 + 1001), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.IronCondor, -20, -(1000000 - 20 * 0) / (0 + 1001) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ShortIronCondor with quantities 1 and -1 are 0|1001 and 1000|0 respectively new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 0, (1000000 - 0 * 0) / (0 + 1001), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 0, (1000000 - 0 * 0) / (0 + 1001) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 0, -(1000000 + 0 * 1000) / (1000 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 0, -(1000000 + 0 * 1000) / (1000 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 20, (1000000 - 20 * 0) / (0 + 1001), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 20, (1000000 - 20 * 0) / (0 + 1001) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 20, -(1000000 + 20 * 1000) / (1000 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 20, -(1000000 + 20 * 1000) / (1000 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -20, (1000000 + 20 * 0) / (0 + 1001), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -20, (1000000 + 20 * 0) / (0 + 1001) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -20, -(1000000 - 20 * 1000) / (1000 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -20, -(1000000 - 20 * 1000) / (1000 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for BoxSpread with quantities 1 and -1 are 0|2003 and 2000|0 respectively new TestCaseData(OptionStrategyDefinitions.BoxSpread, 0, (1000000 - 0 * 0) / (0 + 2003), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.BoxSpread, 0, (1000000 - 0 * 0) / (0 + 2003) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BoxSpread, 0, -(1000000 + 0 * 2000) / (2000 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.BoxSpread, 0, -(1000000 + 0 * 2000) / (2000 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BoxSpread, 20, (1000000 - 20 * 0) / (0 + 2003), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.BoxSpread, 20, (1000000 - 20 * 0) / (0 + 2003) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BoxSpread, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.BoxSpread, 20, -(1000000 + 20 * 2000) / (2000 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.BoxSpread, 20, -(1000000 + 20 * 2000) / (2000 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BoxSpread, -20, (1000000 + 20 * 0) / (0 + 2003), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.BoxSpread, -20, (1000000 + 20 * 0) / (0 + 2003) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BoxSpread, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.BoxSpread, -20, -(1000000 - 20 * 2000) / (2000 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.BoxSpread, -20, -(1000000 - 20 * 2000) / (2000 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ShortBoxSpread with quantities 1 and -1 are 2000|0 and 0|2003 respectively new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 0, (1000000 - 0 * 2000) / (2000 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 0, (1000000 - 0 * 2000) / (2000 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 0, -(1000000 + 0 * 0) / (0 + 2003), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 0, -(1000000 + 0 * 0) / (0 + 2003) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 20, (1000000 - 20 * 2000) / (2000 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 20, (1000000 - 20 * 2000) / (2000 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 20, -(1000000 + 20 * 0) / (0 + 2003), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 20, -(1000000 + 20 * 0) / (0 + 2003) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -20, (1000000 + 20 * 2000) / (2000 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -20, (1000000 + 20 * 2000) / (2000 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -20, -(1000000 - 20 * 0) / (0 + 2003), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -20, -(1000000 - 20 * 0) / (0 + 2003) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for JellyRoll with quantities 1 and -1 are 11448|84 and 11537|0 respectively new TestCaseData(OptionStrategyDefinitions.JellyRoll, 0, (1000000 - 0 * 11448) / (11448 + 84), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.JellyRoll, 0, (1000000 - 0 * 11448) / (11448 + 84) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.JellyRoll, 0, -(1000000 + 0 * 11537) / (11537 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.JellyRoll, 0, -(1000000 + 0 * 11537) / (11537 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.JellyRoll, 20, (1000000 - 20 * 11448) / (11448 + 84), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.JellyRoll, 20, (1000000 - 20 * 11448) / (11448 + 84) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.JellyRoll, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.JellyRoll, 20, -(1000000 + 20 * 11537) / (11537 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.JellyRoll, 20, -(1000000 + 20 * 11537) / (11537 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.JellyRoll, -20, (1000000 + 20 * 11448) / (11448 + 84), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.JellyRoll, -20, (1000000 + 20 * 11448) / (11448 + 84) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.JellyRoll, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.JellyRoll, -20, -(1000000 - 20 * 11537) / (11537 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.JellyRoll, -20, -(1000000 - 20 * 11537) / (11537 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for ShortJellyRoll with quantities 1 and -1 are 11537|0 and 11448|84 respectively new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 0, (1000000 - 0 * 11537) / (11537 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 0, (1000000 - 0 * 11537) / (11537 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 0, -(1000000 + 0 * 11448) / (11448 + 84), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 0, -(1000000 + 0 * 11448) / (11448 + 84) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 20, (1000000 - 20 * 11537) / (11537 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 20, (1000000 - 20 * 11537) / (11537 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 20, -(1000000 + 20 * 11448) / (11448 + 84), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 20, -(1000000 + 20 * 11448) / (11448 + 84) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -20, (1000000 + 20 * 11537) / (11537 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -20, (1000000 + 20 * 11537) / (11537 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -20, -(1000000 - 20 * 11448) / (11448 + 84), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -20, -(1000000 - 20 * 11448) / (11448 + 84) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for BearCallLadder with quantities 1 and -1 are 400|0 and 10407|252 respectively new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 0, (1000000 - 0 * 400) / (400 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 0, (1000000 - 0 * 400) / (400 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 0, -(1000000 + 0 * 10407) / (10407 + 252), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 0, -(1000000 + 0 * 10407) / (10407 + 252) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 20, (1000000 - 20 * 400) / (400 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 20, (1000000 - 20 * 400) / (400 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 20, -(1000000 + 20 * 10407) / (10407 + 252), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 20, -(1000000 + 20 * 10407) / (10407 + 252) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -20, (1000000 + 20 * 400) / (400 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -20, (1000000 + 20 * 400) / (400 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -20, -(1000000 - 20 * 10407) / (10407 + 252), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -20, -(1000000 - 20 * 10407) / (10407 + 252) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for BearPutLadder with quantities 1 and -1 are 10533|346 and 400|0 respectively new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 0, (1000000 - 0 * 10533) / (10533 + 346), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 0, (1000000 - 0 * 10533) / (10533 + 346) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 0, -(1000000 + 0 * 400) / (400 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 0, -(1000000 + 0 * 400) / (400 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 20, (1000000 - 20 * 10533) / (10533 + 346), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 20, (1000000 - 20 * 10533) / (10533 + 346) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 20, -(1000000 + 20 * 400) / (400 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 20, -(1000000 + 20 * 400) / (400 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -20, (1000000 + 20 * 10533) / (10533 + 346), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -20, (1000000 + 20 * 10533) / (10533 + 346) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -20, -(1000000 - 20 * 400) / (400 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -20, -(1000000 - 20 * 400) / (400 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for BullCallLadder with quantities 1 and -1 are 10407|252 and 400|0 respectively new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 0, (1000000 - 0 * 10407) / (10407 + 252), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 0, (1000000 - 0 * 10407) / (10407 + 252) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 0, -(1000000 + 0 * 400) / (400 + 0), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 0, -(1000000 + 0 * 400) / (400 + 0) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 20, (1000000 - 20 * 10407) / (10407 + 252), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 20, (1000000 - 20 * 10407) / (10407 + 252) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 20, -(1000000 + 20 * 400) / (400 + 0), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 20, -(1000000 + 20 * 400) / (400 + 0) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -20, (1000000 + 20 * 10407) / (10407 + 252), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -20, (1000000 + 20 * 10407) / (10407 + 252) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -20, -(1000000 - 20 * 400) / (400 + 0), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -20, -(1000000 - 20 * 400) / (400 + 0) - 1, false), // -20 to max short + 1 // Initial margin requirement|premium for BullPutLadder with quantities 1 and -1 are 400|0 and 10533|346 respectively new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 0, (1000000 - 0 * 400) / (400 + 0), true), // 0 to max long new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 0, (1000000 - 0 * 400) / (400 + 0) + 1, false), // 0 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 0, -(1000000 + 0 * 10533) / (10533 + 346), true), // 0 to max short new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 0, -(1000000 + 0 * 10533) / (10533 + 346) - 1, false), // 0 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 20, (1000000 - 20 * 400) / (400 + 0), true), // 20 to max long new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 20, (1000000 - 20 * 400) / (400 + 0) + 1, false), // 20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 20, -20, true), // 20 to 0 new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 20, -(1000000 + 20 * 10533) / (10533 + 346), true), // 20 to max short new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 20, -(1000000 + 20 * 10533) / (10533 + 346) - 1, false), // 20 to max short + 1 new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -20, (1000000 + 20 * 400) / (400 + 0), true), // -20 to max long new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -20, (1000000 + 20 * 400) / (400 + 0) + 1, false), // -20 to max long + 1 new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -20, 20, true), // -20 to 0 new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -20, -(1000000 - 20 * 10533) / (10533 + 346), true), // -20 to max short new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -20, -(1000000 - 20 * 10533) / (10533 + 346) - 1, false), // -20 to max short + 1 }; [TestCaseSource(nameof(HasSufficientBuyingPowerForOrderTestCases))] public void HasSufficientBuyingPowerForOrder(OptionStrategyDefinition optionStrategy, int initialPositionQuantity, int orderQuantity, bool expectedResult) { _algorithm.SetCash(1000000); var initialPositionGroup = SetUpOptionStrategy(optionStrategy, initialPositionQuantity); var orders = GetPositionGroupOrders(initialPositionGroup, initialPositionQuantity != 0 ? initialPositionQuantity : 1, orderQuantity); Assert.IsTrue(_portfolio.Positions.TryCreatePositionGroup(orders, out var ordersPositionGroup)); var result = initialPositionGroup.BuyingPowerModel.HasSufficientBuyingPowerForOrder( new HasSufficientPositionGroupBuyingPowerForOrderParameters(_portfolio, ordersPositionGroup, orders)); Assert.AreEqual(expectedResult, result.IsSufficient, result.Reason); } [Test] public void HasSufficientBuyingPowerForReducingStrategyOrder() { const decimal price = 1m; const decimal underlyingPrice = 200m; _equity.SetMarketPrice(new Tick { Value = underlyingPrice }); _callOption.SetMarketPrice(new Tick { Value = price }); _putOption.SetMarketPrice(new Tick { Value = price }); var initialHoldingsQuantity = -10; _callOption.Holdings.SetHoldings(1.5m, initialHoldingsQuantity); _putOption.Holdings.SetHoldings(1m, initialHoldingsQuantity); _algorithm.SetCash(_portfolio.TotalMarginUsed * 0.95m); var quantity = -initialHoldingsQuantity / 2; var orders = GetStrategyOrders(quantity); Assert.IsTrue(_portfolio.Positions.TryCreatePositionGroup(orders, out var positionGroup)); var hasSufficientBuyingPowerResult = positionGroup.BuyingPowerModel.HasSufficientBuyingPowerForOrder( new HasSufficientPositionGroupBuyingPowerForOrderParameters(_portfolio, positionGroup, orders)); Assert.IsTrue(hasSufficientBuyingPowerResult.IsSufficient); } // Increasing short position [TestCase(-10, -11)] // Decreasing short position [TestCase(-10, -9)] // Liquidating [TestCase(-10, 0)] public void PositionGroupOrderQuantityCalculationForDeltaBuyingPowerFromShortPosition(int initialHoldingsQuantity, int finalPositionQuantity) { _algorithm.SetCash(100000); // Just making sure we start from a short position var absQuantity = Math.Abs(initialHoldingsQuantity); initialHoldingsQuantity = -absQuantity; SetUpOptionStrategy(initialHoldingsQuantity); var positionGroup = _portfolio.Positions.Groups.Single(); var expectedQuantity = initialHoldingsQuantity - finalPositionQuantity; var usedMargin = _portfolio.TotalMarginUsed; var marginPerNakedShortUnit = usedMargin / absQuantity; var deltaBuyingPower = expectedQuantity * marginPerNakedShortUnit; // Add a small buffer to avoid precision errors that occur when converting the delta buying power request into a target one deltaBuyingPower *= finalPositionQuantity < initialHoldingsQuantity ? 1.001m : 0.999m; ComputeAndAssertQuantityForDeltaBuyingPower(positionGroup, expectedQuantity, deltaBuyingPower); } // Increasing position [TestCase(10, 11)] // Decreasing position [TestCase(10, 9)] // Liquidating [TestCase(10, 0)] public void PositionGroupOrderQuantityCalculationForDeltaBuyingPowerFromLongPosition(int initialHoldingsQuantity, int finalPositionQuantity) { _algorithm.SetCash(100000); // Just making sure we start from a long position initialHoldingsQuantity = Math.Abs(initialHoldingsQuantity); var positionGroup = SetUpOptionStrategy(OptionStrategyDefinitions.CoveredCall, initialHoldingsQuantity); var expectedQuantity = finalPositionQuantity - initialHoldingsQuantity; var usedMargin = _portfolio.TotalMarginUsed; var marginPerLongUnit = Math.Abs(positionGroup.BuyingPowerModel.GetInitialMarginRequirement(_portfolio, positionGroup) / initialHoldingsQuantity); var shortUnitGroup = positionGroup.WithQuantity(-1, _portfolio.Positions); var marginPerNakedShortUnit = Math.Abs(shortUnitGroup.BuyingPowerModel.GetInitialMarginRequirement(_portfolio, shortUnitGroup)); var deltaBuyingPower = finalPositionQuantity >= 0 //Going even longer / Going "less" long/ Liquidating ? expectedQuantity * marginPerLongUnit // Going short from long : -usedMargin + Math.Abs(finalPositionQuantity) * marginPerNakedShortUnit; var initialMarginRequirement = positionGroup.BuyingPowerModel.GetInitialMarginRequirement(_portfolio, positionGroup); var maintenanceMargin = positionGroup.BuyingPowerModel.GetMaintenanceMargin(_portfolio, positionGroup); // Adjust the delta buying power: // GetMaximumLotsForDeltaBuyingPower will add the delta buying power to the maintenance margin and used that as a target margin, // but then GetMaximumLotsForTargetBuyingPower will work with initial margin requirement so we make sure the resulting quantity // can be ordered. In order to match this, we need to adjust the delta buying power by the difference between the initial margin // requirement and maintenance margin. deltaBuyingPower += initialMarginRequirement - maintenanceMargin; ComputeAndAssertQuantityForDeltaBuyingPower(positionGroup, expectedQuantity, deltaBuyingPower); } [TestCase(-10, 1, +1)] [TestCase(-10, 1, -1)] [TestCase(-10, 0.5, +1)] [TestCase(-10, 0.5, -1)] [TestCase(-10, 2, +1)] [TestCase(-10, 2, -1)] [TestCase(10, 1, +1)] [TestCase(10, 1, -1)] [TestCase(10, 0.5, +1)] [TestCase(10, 0.5, -1)] [TestCase(10, 2, +1)] [TestCase(10, 2, -1)] public void OrderQuantityCalculation(int initialHoldingsQuantity, decimal targetMarginPercent, int targetMarginDirection) { // The targetMarginDirection whether we want to go in the same direction as the holdings: // +1: short will go shorter and long will go longer // -1: short will go towards long and vice-versa var positionGroup = SetUpOptionStrategy(OptionStrategyDefinitions.CoveredCall, initialHoldingsQuantity); var currentUsedMargin = Math.Abs(positionGroup.BuyingPowerModel.GetInitialMarginRequirement(_portfolio, positionGroup)); var longUnitGroup = positionGroup.CreateUnitGroup(_portfolio.Positions); var longUnitMargin = Math.Abs(longUnitGroup.BuyingPowerModel.GetInitialMarginRequirement(_portfolio, longUnitGroup)); var expectedQuantity = 0m; var finalPositionQuantity = 0m; var targetFinalMargin = 0m; // Going to the opposite side if (targetMarginPercent > 1 && targetMarginDirection == -1) { var shortUnitGroup = positionGroup.WithQuantity(-1, _portfolio.Positions); var shortUnitMargin = Math.Abs(shortUnitGroup.BuyingPowerModel.GetInitialMarginRequirement(_portfolio, shortUnitGroup)); finalPositionQuantity = Math.Floor(-currentUsedMargin / shortUnitMargin); expectedQuantity = -Math.Abs(initialHoldingsQuantity) + finalPositionQuantity; targetFinalMargin = finalPositionQuantity * shortUnitMargin; } else { expectedQuantity = Math.Abs(initialHoldingsQuantity * targetMarginPercent) * Math.Sign(targetMarginDirection); finalPositionQuantity = initialHoldingsQuantity + Math.Sign(initialHoldingsQuantity) * expectedQuantity; targetFinalMargin = Math.Abs(finalPositionQuantity * longUnitMargin); } var quantity = (positionGroup.BuyingPowerModel as OptionStrategyPositionGroupBuyingPowerModel).GetPositionGroupOrderQuantity(_portfolio, positionGroup, currentUsedMargin, targetFinalMargin, longUnitGroup, longUnitMargin, out _); // Liquidating if (targetFinalMargin == 0) { // Should always be negative when liquidating (or reducing) Assert.AreEqual(-Math.Abs(initialHoldingsQuantity), quantity); } // Reducing the position else if (targetFinalMargin < currentUsedMargin) { Assert.Less(quantity, 0); } // Increasing the position else { Assert.Greater(quantity, 0); } Assert.AreEqual(expectedQuantity, quantity); } /// /// Test cases for the method. /// /// TODO: We should come back and revisit these test cases to make sure they are correct. /// The approximate values from IB for the prices used in the test are in the comments. /// For instance, see the test case for the CoveredCall strategy. The margin values do not match IB's values. /// /// Test cases marked as explicit will fail if ran, they have an approximate expected value based on IB's margin requirements. /// private static readonly TestCaseData[] InitialMarginRequirementsTestCases = new[] { // OptionStrategyDefinition, initialHoldingsQuantity, expectedInitialMarginRequirement new TestCaseData(OptionStrategyDefinitions.NakedCall, 1, 21200m), // IB: 21200 new TestCaseData(OptionStrategyDefinitions.NakedCall, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.NakedPut, 1, 3000m), // IB: 3000 new TestCaseData(OptionStrategyDefinitions.NakedPut, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.CoveredCall, 1, 19000m), // IB: 19325 new TestCaseData(OptionStrategyDefinitions.CoveredCall, -1, 12000m), // IB: 12338.58 new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 1, 12000m), // IB: inverted covered call new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -1, 19000m), // IB: covered call new TestCaseData(OptionStrategyDefinitions.CoveredPut, 1, 12000m), // IB: 12331.38 new TestCaseData(OptionStrategyDefinitions.CoveredPut, -1, 10000m), // IB: 10276.15 new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 1, 10000m), // IB: inverted covered put new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -1, 12000m), // IB: covered put new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 1, 26231m), // IB: 26231 new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -1, 26231m), // IB: same as long new TestCaseData(OptionStrategyDefinitions.Conversion, 1, 26295m), // IB: 26295 new TestCaseData(OptionStrategyDefinitions.Conversion, -1, 26230m), // IB: reverse conversion new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 1, 26231m), // IB: 26231 new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -1, 26295m), // IB: conversion new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.Straddle, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.Straddle, -1, 20000m), // IB: 20624 new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 1, 20000m), // IB: 20624 new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.Strangle, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.Strangle, -1, 21000m), // IB: 20752 new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 1, 21000m), // IB: 20752 new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -1, 20000m), // IB: 20537 new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 1, 20000m), // IB: 20537 new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -1, 3000m), // IB: 3121 new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 1, 3000m), // IB: 3121 new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.IronButterfly, 1, 1000m), // IB: 1010 note: 1% commission new TestCaseData(OptionStrategyDefinitions.IronButterfly, -1, 0m), // IB: short iron butterfly new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -1, 1000m), // IB: iron butterfly new TestCaseData(OptionStrategyDefinitions.IronCondor, 1, 1000m), // IB: 1001 new TestCaseData(OptionStrategyDefinitions.IronCondor, -1, 0m), // IB: short iron condor new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -1, 1000m), // IB: iron condor new TestCaseData(OptionStrategyDefinitions.BoxSpread, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.BoxSpread, -1, 2000m), // IB: short box spread new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 1, 2000m), // IB: 2000 new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -1, 0m), // IB: box spread new TestCaseData(OptionStrategyDefinitions.JellyRoll, 1, 11447.5m), // IB: 11459 new TestCaseData(OptionStrategyDefinitions.JellyRoll, -1, 11537.2m), // IB: short jelly roll new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 1, 11537.2m), // IB: 11589 new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -1, 11447.5m), // IB: jelly roll new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 1, 400m), // IB: 400 new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -1, 10407.04m), // IB: BullCallLadder new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 1, 10407.04m), // IB: 10407.04 new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -1, 400m), // IB: BearCallLadder new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 1, 10532.56m), // IB: 10532.56 new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -1, 400m), // IB: BullPutLadder new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 1, 400m), // IB: 400 new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -1, 10532.56m), // IB: BearPutLadder }; [TestCaseSource(nameof(InitialMarginRequirementsTestCases))] public void GetsInitialMarginRequirement(OptionStrategyDefinition optionStrategyDefinition, int quantity, decimal expectedInitialMarginRequirement) { var positionGroup = SetUpOptionStrategy(optionStrategyDefinition, quantity); var initialMarginRequirement = (OptionInitialMargin)positionGroup.BuyingPowerModel.GetInitialMarginRequirement( new PositionGroupInitialMarginParameters(_portfolio, positionGroup)); Assert.AreEqual((double)expectedInitialMarginRequirement, (double)initialMarginRequirement.ValueWithoutPremium, (double)(0.2m * expectedInitialMarginRequirement)); } private static readonly TestCaseData[] CoveredCallInitialMarginRequirementsTestCases = new[] { // OptionStrategyDefinition, initialHoldingsQuantity, expectedInitialMarginRequirement, option strike new TestCaseData(OptionStrategyDefinitions.CoveredCall, 2, 53700m, 200), // IB: 53,714 new TestCaseData(OptionStrategyDefinitions.CoveredCall, 2, 38000m, 300), // IB: 38,756 new TestCaseData(OptionStrategyDefinitions.CoveredCall, 2, 23000m, 400), // IB: 23,752 new TestCaseData(OptionStrategyDefinitions.CoveredCall, 2, 21000m, 500), // IB: 20,939 }; [TestCaseSource(nameof(CoveredCallInitialMarginRequirementsTestCases))] public void CoveredCallInitialMarginRequirement(OptionStrategyDefinition optionStrategyDefinition, int quantity, decimal expectedInitialMarginRequirement, int strike) { var positionGroup = SetUpOptionStrategy(optionStrategyDefinition, quantity, strike); var initialMarginRequirement = positionGroup.BuyingPowerModel.GetInitialMarginRequirement( new PositionGroupInitialMarginParameters(_portfolio, positionGroup)); Assert.AreEqual((double)expectedInitialMarginRequirement, (double)initialMarginRequirement.Value, (double)(0.2m * expectedInitialMarginRequirement)); } /// /// Test cases for the method. /// /// TODO: We should come back and revisit these test cases to make sure they are correct. /// The approximate values from IB for the prices used in the test are in the comments. /// For instance, see the test case for the CoveredCall strategy. The margin values do not match IB's values. /// /// Test cases marked as explicit will fail if ran, they have an approximate expected value based on IB's margin requirements. /// private static readonly TestCaseData[] MaintenanceMarginTestCases = new[] { // OptionStrategyDefinition, initialHoldingsQuantity, expectedMaintenanceMargin new TestCaseData(OptionStrategyDefinitions.NakedCall, 1, 21200m), // IB: 21200 new TestCaseData(OptionStrategyDefinitions.NakedCall, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.NakedPut, 1, 3000m), // IB: 3000 new TestCaseData(OptionStrategyDefinitions.NakedPut, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.CoveredCall, 1, 19000m), // IB: 19325 new TestCaseData(OptionStrategyDefinitions.CoveredCall, -1, 3000m), // IB: 3000 new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 1, 3000m), // IB: inverted covered call new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -1, 19000m), // IB: covered call new TestCaseData(OptionStrategyDefinitions.CoveredPut, 1, 10250m), // IB: 12000m new TestCaseData(OptionStrategyDefinitions.CoveredPut, -1, 10000m), // IB: 10276 new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 1, 10000m), // IB: inverted covered Put new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -1, 10250m), // IB: covered Put new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 1, 6202m), // IB: 6202 new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -1, 6202m), // IB: same as long new TestCaseData(OptionStrategyDefinitions.Conversion, 1, 5303m), // IB: 5303 new TestCaseData(OptionStrategyDefinitions.Conversion, -1, 5240m), // IB: reverse conversion new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 1, 5240m), // IB: 5240 new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -1, 5303m), // IB: conversion new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 1, 1000m), // IB: 10000 new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.Straddle, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.Straddle, -1, 20000m), // IB: 20624 new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 1, 20000m), // IB: 20624 new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.Strangle, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.Strangle, -1, 21000m), // IB: 20752 new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 1, 21000m), // IB: 20752 new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 1, 1000m), // IB: 1000 new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -1, 20000m), // IB: 20537 new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 1, 20000m), // IB: 20537 new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -1, 3000m), // IB: 3121 new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 1, 3000m), // IB: 3121 new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.IronButterfly, 1, 1000m), // IB: 1010 note: 1% commission new TestCaseData(OptionStrategyDefinitions.IronButterfly, -1, 0m), // IB: short iron butterfly new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -1, 1000m), // IB: iron butterfly new TestCaseData(OptionStrategyDefinitions.IronCondor, 1, 1000m), // IB: 1017.62 new TestCaseData(OptionStrategyDefinitions.IronCondor, -1, 0m), // IB: short iron condor new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -1, 1000m), // IB: iron condor new TestCaseData(OptionStrategyDefinitions.BoxSpread, 1, 0m), // IB: 0 new TestCaseData(OptionStrategyDefinitions.BoxSpread, -1, 2000m), // IB: short box spread new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 1, 2000m), // IB: 2000 new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -1, 0m), // IB: box spread new TestCaseData(OptionStrategyDefinitions.JellyRoll, 1, 11447.5m), // IB: 11459 new TestCaseData(OptionStrategyDefinitions.JellyRoll, -1, 11537.2m), // IB: short jelly roll new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 1, 11537.2m), // IB: 11589 new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -1, 11447.5m), // IB: jelly roll new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 1, 400m), // IB: 400 new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -1, 10407.04m), // IB: BullCallLadder new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 1, 10407.04m), // IB: 10407.04 new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -1, 400m), // IB: BearCallLadder new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 1, 10532.56m), // IB: 10532.56 new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -1, 400m), // IB: BullPutLadder new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 1, 400m), // IB: 400 new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -1, 10532.56m), // IB: BearPutLadder }; [TestCaseSource(nameof(MaintenanceMarginTestCases))] public void GetsMaintenanceMargin(OptionStrategyDefinition optionStrategyDefinition, int quantity, decimal expectedMaintenanceMargin) { var positionGroup = SetUpOptionStrategy(optionStrategyDefinition, quantity); var maintenanceMargin = positionGroup.BuyingPowerModel.GetMaintenanceMargin( new PositionGroupMaintenanceMarginParameters(_portfolio, positionGroup)); Assert.AreEqual((double)expectedMaintenanceMargin, (double)maintenanceMargin.Value, (double)(0.2m * expectedMaintenanceMargin)); } /// /// TODO: Revisit the explicit test cases when we can take into account premium for strategies with zero margin. /// // option strategy definition, initial position quantity, final position quantity private static readonly TestCaseData[] OrderQuantityForDeltaBuyingPowerTestCases = new[] { // Initial margin requirement (including premium) for NakedCall with quantity 10 and -10 is 194000 and 112000 respectively new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, 194000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, -194000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, -194000m, -10), new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, -194000m - 112000m, -20), // Going from 10 to -10 new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, 112000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, -112000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, -112000m, -10), new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, -112000m - 194000m, -20), // Going from -10 to 10 // Initial margin requirement (including premium) for NakedPut with quantity 10 and -10 is 30020 and 20 respectively new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, 30020m / 10, +1), new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, -30020m / 10, -1), new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, -30020m, -10), new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, -30020m - 20m, -20), // Going from 10 to -10 new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, 20m / 10, +1), new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, -20m / 10, -1), new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, -20m, -10), new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, -20m - 30020m, -20), // Going from -10 to 10 // Initial margin requirement (including premium) for CoveredCall with quantity 10 and -10 is 192100 and 214500 respectively new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, 192100m / 10, +1), new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, -192100m / 10, -1), new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, -192100m, -10), new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, -192100m - 214500m, -20), // Going from 10 to -10 new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, 214500m / 10, +1), new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, -214500m / 10, -1), new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, -214500m, -10), new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, -214500m - 192100m, -20), // Going from -10 to 10 // Initial margin requirement (including premium) for ProtectiveCall with quantity 10 and -10 is 214500 and 192100 respectively new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, 214500m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, -214500m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, -214500m, -10), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, -214500m - 192100m, -20), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, 192100m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, -192100m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, -192100m, -10), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, -192100m - 214500m, -20), // Initial margin requirement (including premium) for CoveredPut with quantity 10 and -10 is 102500 and 102520 respectively new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, 102500m / 10, +1), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, -102500m / 10, -1), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, -102500m, -10), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, -102500m - 102520m, -20), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, 102520m / 10, +1), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, -102520m / 10, -1), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, -102520m, -10), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, -102520m - 102500m, -20), // Initial margin requirement (including premium) for ProtectivePut with quantity 10 and -10 is 102520 and 102500 respectively new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, 102520m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, -102520m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, -102520m, -10), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, -102520m - 102500m, -20), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, 102500m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, -102500m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, -102500m, -10), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, -102500m - 102520m, -20), // Initial margin requirement (including premium) for ProtectiveCollar with quantity 10 and -10 is 262310 and 262318 respectively new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, 262310m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, -262310m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, -262310m, -10), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, -262310m - 262318m, -20), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, 262318m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, -262318m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, -262318m - 262310m, -20), // Initial margin requirement (including premium) for Conversion with quantity 10 and -10 is 262945 and 263778 respectively new TestCaseData(OptionStrategyDefinitions.Conversion, 10, 262945m / 10, +1), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, -262945m / 10, -1), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, -262945m, -10), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, -262945m - 263778m, -20), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, 263778m / 10, +1), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, -263778m / 10, -1), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, -263778m, -10), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, -263778m - 262945m, -20), // Initial margin requirement (including premium) for ReverseConversion with quantity 10 and -10 is 263768 and 262915 respectively new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, 263768m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, -263768m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, -263768m, -10), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, -263768m - 262915m, -20), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, 262915m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, -262915m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, -262915m, -10), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, -262915m - 263768m, -20), // Initial margin requirement (including premium) for BearCallSpread with quantity 10 and -10 is 10000 and 12000 respectively new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, 10000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, -10000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, -10000m, -10), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, -10000m - 12000m, -20), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, 12000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, -12000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, -12000m, -10), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, -12000m - 10000m, -20), // Initial margin requirement (including premium) for BearPutSpread with quantity 10 and -10 is 10 and 10000 respectively new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, 10m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, -10m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, -10m, -10), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, -10m - 10000m, -20), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, 10000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, -10000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, -10000m, -10), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, -10000m - 10m, -20), // Initial margin requirement (including premium) for BullCallSpread with quantity 10 and -10 is 12000 and 10000 respectively new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, 12000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, -12000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, -12000m, -10), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, -12000m - 10000m, -20), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, 10000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, -10000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, -10000m, -10), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, -10000m - 12000m, -20), // Initial margin requirement (including premium) for BullPutSpread with quantity 10 and -10 is 10000 and 10 respectively new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, 10000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, -10000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, -10000m, -10), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, -10000m - 10m, -20), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, 10m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, -10m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, -10m, -10), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, -10m - 10000m, -20), // Initial margin requirement (including premium) for Straddle with quantity 10 and -10 is 112020 and 194020 respectively new TestCaseData(OptionStrategyDefinitions.Straddle, 10, 112020m / 10, +1), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, -112020m / 10, -1), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, -112020m, -10), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, -112020m - 194020m, -20), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, 194020m / 10, +1), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, -194020m / 10, -1), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, -194020m, -10), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, -194020m - 112020m, -20), // Initial margin requirement (including premium) for ShortStraddle with quantity 10 and -10 is 194020 and 112020 respectively new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, 194020m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, -194020m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, -194020m, -10), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, -194020m - 112020m, -20), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, 112020m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, -112020m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, -112020m, -10), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, -112020m - 194020m, -20), // Initial margin requirement (including premium) for Strangle with quantity 10 and -10 is 100020 and 182020 respectively new TestCaseData(OptionStrategyDefinitions.Strangle, 10, 100020m / 10, +1), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, -100020m / 10, -1), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, -100020m, -10), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, -100020m - 182020m, -20), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, 182020m / 10, +1), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, -182020m / 10, -1), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, -182020m, -10), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, -182020m - 100020m, -20), // Initial margin requirement (including premium) for ShortStrangle with quantity 10 and -10 is 182020 and 100020 respectively new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, 182020m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, -182020m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, -182020m, -10), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, -182020m - 100020m, -20), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, 100020m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, -100020m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, -100020m, -10), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, -100020m - 182020m, -20), // Initial margin requirement (including premium) for ButterflyCall with quantity 10 and -10 is 4000 and 10000 respectively new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, 4000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, -4000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, -4000m, -10), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, -4000m - 10000m, -20), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, 10000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, -10000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, -10000m, -10), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, -10000m - 4000m, -20), // Initial margin requirement (including premium) for ShortButterflyCall with quantity 10 and -10 is 10000 and 4000 respectively new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, 10000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, -10000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, -10000m, -10), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, -10000m - 4000m, -20), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, 4000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, -4000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, -4000m, -10), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, -4000m - 10000m, -20), // Initial margin requirement (including premium) for ButterflyPut with quantity 10 and -10 is 10 and 10000 respectively new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, 10m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, -10m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, -10m, -10), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, -10m - 10000m, -20), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, 10000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, -10000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, -10000m, -10), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, -10000m - 10m, -20), // Initial margin requirement (including premium) for ShortButterflyPut with quantity 10 and -10 is 10000 and 10 respectively new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, 10000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, -10000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, -10000m, -10), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, -10000m - 10m, -20), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, 10m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, -10m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, -10m, -10), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, -10m - 10000m, -20), // Initial margin requirement (including premium) for CallCalendarSpread with quantity 10 and -10 is 2000 and 194000 respectively new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, 2000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, -2000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, -2000m, -10), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, -2000m - 194000m, -20), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, 194000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, -194000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, -194000m, -10), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, -194000m - 2000m, -20), // Initial margin requirement (including premium) for ShortCallCalendarSpread with quantity 10 and -10 is 194000 and 2000 respectively new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, 194000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, -194000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, -194000m, -10), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, -194000m - 2000m, -20), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, 2000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, -2000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, -2000m, -10), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, -2000m - 194000m, -20), // Initial margin requirement (including premium) for PutCalendarSpread with quantity 10 and -10 is 10 and 30020 respectively new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, 10m / 10, +1), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, -10m / 10, -1), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, -10m, -10), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, -10m - 30020m, -20), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, 30020m / 10, +1), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, -30020m / 10, -1), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, -30020m, -10), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, -30020m - 10m, -20), // Initial margin requirement (including premium) for ShortPutCalendarSpread with quantity 10 and -10 is 30020 and 10 respectively new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, 30020m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, -30020m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, -30020m, -10), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, -30020m - 10m, -20), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, 10m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, -10m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, -10m, -10), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, -10m - 30020m, -20), // Initial margin requirement (including premium) for IronButterfly with quantity 10 and -10 is 10000 and 8010 respectively new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, 10000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, -10000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, -10000m, -10), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, -10000m - 8010m, -20), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, 8010m / 10, +1), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, -8010m / 10, -1), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, -8010m, -10), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, -8010m - 10000m, -20), // Initial margin requirement (including premium) for ShortIronButterfly with quantity 10 and -10 is 8010 and 10000 respectively new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, 8010m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, -8010m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, -8010m, -10), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, -8010m - 10000m, -20), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, 10000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, -10000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, -10000m, -10), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, -10000m - 8010m, -20), // Initial margin requirement (including premium) for IronCondor with quantity 10 and -10 is 10000 and 10010 respectively new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, 10000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, -10000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, -10000m, -10), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, -10000m - 10010m, -20), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, 10010m / 10, +1), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, -10010m / 10, -1), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, -10010m, -10), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, -10010m - 10000m, -20), // Initial margin requirement (including premium) for ShortIronCondor with quantity 10 and -10 is 10010 and 10000 respectively new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, 10010m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, -10010m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, -10010m, -10), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, -10010m - 10000m, -20), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, 10000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, -10000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, -10000m, -10), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, -10000m - 10010m, -20), // Initial margin requirement (including premium) for BoxSpread with quantity 10 and -10 is 20030 and 20000 respectively new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, 20030m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, -20030m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, -20030m, -10), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, -20030m - 20000m, -20), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, 20000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, -20000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, -20000m, -10), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, -20000m - 20030m, -20), // Initial margin requirement (including premium) for ShortBoxSpread with quantity 10 and -10 is 20000 and 20030 respectively new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, 20000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, -20000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, -20000m, -10), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, -20000m - 20030m, -20), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, 20030m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, -20030m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, -20030m, -10), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, -20030m - 20000m, -20), // Initial margin requirement (including premium) for JellyRoll with quantity 10 and -10 is 115319 and 115372 respectively new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, 115319m / 10, +1), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, -115319m / 10, -1), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, -115319m, -10), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, -115319m - 115372m, -20), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, 115372m / 10, +1), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, -115372m / 10, -1), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, -115372m, -10), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, -115372m - 115319m, -20), // Initial margin requirement (including premium) for ShortJellyRoll with quantity 10 and -10 is 115372 and 115319 respectively new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, 115372m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, -115372m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, -115372m, -10), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, -115372m - 115319m, -20), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, 115319m / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, -115319m / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, -115319m, -10), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, -115319m - 115372m, -20), // Initial margin requirement (including premium) for BearCallLadder with quantity 10 and -10 is 4000 and 106590.4 respectively new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, 4000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, -4000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, -4000m, -10), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, -4000m - 106590.4m, -20), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, 106590.4m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, -106590.4m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, -106590.4m, -10), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, -106590.4m - 4000m, -20), // Initial margin requirement (including premium) for BearPutLadder with quantity 10 and -10 is 108789.6 and 4000 respectively new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, 108789.6m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, -108789.6m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, -108789.6m, -10), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, -108789.6m - 4000m, -20), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, 4000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, -4000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, -4000m, -10), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, -4000m - 108789.6m, -20), // Initial margin requirement (including premium) for BullCallLadder with quantity 10 and -10 is 106590.4 and 4000 respectively new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, 106590.4m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, -106590.4m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, -106590.4m, -10), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, -106590.4m - 4000m, -20), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, 4000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, -4000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, -4000m, -10), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, -4000m - 106590.4m, -20), // Initial margin requirement (including premium) for BullPutLadder with quantity 10 and -10 is 4000 and 108789.6 respectively new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, 4000m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, -4000m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, -4000m, -10), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, -4000m - 108789.6m, -20), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, 108789.6m / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, -108789.6m / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, -108789.6m, -10), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, -108789.6m - 4000m, -20), }; [TestCaseSource(nameof(OrderQuantityForDeltaBuyingPowerTestCases))] public void PositionGroupOrderQuantityCalculationForDeltaBuyingPower(OptionStrategyDefinition optionStrategyDefinition, int initialPositionQuantity, decimal deltaBuyingPower, int expectedQuantity) { var positionGroup = SetUpOptionStrategy(optionStrategyDefinition, initialPositionQuantity); var initialMarginRequirement = positionGroup.BuyingPowerModel.GetInitialMarginRequirement(_portfolio, positionGroup); var maintenanceMargin = positionGroup.BuyingPowerModel.GetMaintenanceMargin(_portfolio, positionGroup); // Adjust the delta buying power: // GetMaximumLotsForDeltaBuyingPower will add the delta buying power to the maintenance margin and used that as a target margin, // but then GetMaximumLotsForTargetBuyingPower will work with initial margin requirement so we make sure the resulting quantity // can be ordered. In order to match this, we need to adjust the delta buying power by the difference between the initial margin // requirement and maintenance margin. deltaBuyingPower += initialMarginRequirement - maintenanceMargin; if (expectedQuantity != -Math.Abs(initialPositionQuantity)) // Not liquidating { // Add a small buffer to avoid rounding errors var usedMargin = _portfolio.TotalMarginUsed; deltaBuyingPower *= deltaBuyingPower > 0 || Math.Abs(deltaBuyingPower) > usedMargin ? 1.00001m : 0.99999m; } var result = positionGroup.BuyingPowerModel.GetMaximumLotsForDeltaBuyingPower(new GetMaximumLotsForDeltaBuyingPowerParameters( _portfolio, positionGroup, deltaBuyingPower, minimumOrderMarginPortfolioPercentage: 0)); Assert.IsFalse(result.IsError); Assert.AreEqual(expectedQuantity, result.NumberOfLots); // Expected quantity is 0 for test cases where no buying power is used, // it should return 0 regardless of the delta, with the proper message if (expectedQuantity == 0) { Assert.AreEqual(Messages.PositionGroupBuyingPowerModel.DeltaCannotBeApplied, result.Reason); } } private static TestCaseData[] OrderQuantityForDeltaBuyingPowerWithCustomPositionGroupParameterTestCases() { return OrderQuantityForDeltaBuyingPowerTestCases .SelectMany(testCaseData => { var testCases = new List(2); foreach (var referencePositionSideSign in new[] { +1, -1 }) { var args = testCaseData.OriginalArguments.ToList(); args.Add(referencePositionSideSign); var data = new TestCaseData(args.ToArray()); if (testCaseData.RunState == NUnit.Framework.Interfaces.RunState.Explicit) { data.Explicit(); } testCases.Add(data); } return testCases; }) .ToArray(); } /// /// Tests with reference position group in /// same and opposite side of the existing position group. /// /// The reference position group is not necessarily in the same side as the position group in the portfolio, it could be the inverted. /// So the consumer needs the result relative to that position group instead of the one being held. /// [TestCaseSource(nameof(OrderQuantityForDeltaBuyingPowerWithCustomPositionGroupParameterTestCases))] public void PositionGroupOrderQuantityCalculationForDeltaBuyingPowerWithCustomPositionGroupParameter( OptionStrategyDefinition optionStrategyDefinition, int initialPositionQuantity, decimal deltaBuyingPower, int expectedQuantity, int referencePositionSideSign) { var currentPositionGroup = SetUpOptionStrategy(optionStrategyDefinition, initialPositionQuantity); var initialMarginRequirement = currentPositionGroup.BuyingPowerModel.GetInitialMarginRequirement(_portfolio, currentPositionGroup); var maintenanceMargin = currentPositionGroup.BuyingPowerModel.GetMaintenanceMargin(_portfolio, currentPositionGroup); // Adjust the delta buying power: // GetMaximumLotsForDeltaBuyingPower will add the delta buying power to the maintenance margin and used that as a target margin, // but then GetMaximumLotsForTargetBuyingPower will work with initial margin requirement so we make sure the resulting quantity // can be ordered. In order to match this, we need to adjust the delta buying power by the difference between the initial margin // requirement and maintenance margin. deltaBuyingPower += initialMarginRequirement - maintenanceMargin; if (expectedQuantity != -Math.Abs(initialPositionQuantity)) // Not liquidating { // Add a small buffer to avoid rounding errors var usedMargin = _portfolio.TotalMarginUsed; deltaBuyingPower *= deltaBuyingPower > 0 || Math.Abs(deltaBuyingPower) > usedMargin ? 1.00001m : 0.99999m; } // Using a reference position with in the same position side as the one in the portfolio var referencePositionGroup = new PositionGroup(currentPositionGroup.BuyingPowerModel, 1, currentPositionGroup.Select(position => new Position(position.Symbol, referencePositionSideSign * Math.Sign(position.Quantity) * position.UnitQuantity, position.UnitQuantity)).ToArray()); var result = currentPositionGroup.BuyingPowerModel.GetMaximumLotsForDeltaBuyingPower(new GetMaximumLotsForDeltaBuyingPowerParameters( _portfolio, referencePositionGroup, referencePositionSideSign * deltaBuyingPower, minimumOrderMarginPortfolioPercentage: 0)); Assert.IsFalse(result.IsError); Assert.AreEqual(referencePositionSideSign * expectedQuantity, result.NumberOfLots); // Expected quantity is 0 for test cases where no buying power is used, // it should return 0 regardless of the delta, with the proper message if (expectedQuantity == 0) { Assert.AreEqual(Messages.PositionGroupBuyingPowerModel.DeltaCannotBeApplied, result.Reason); } } /// /// TODO: Revisit the explicit test cases when we can take into account premium for strategies with zero margin. /// // option strategy definition, initial position quantity, target buying power percent, expected quantity private static readonly TestCaseData[] OrderQuantityForTargetBuyingPowerTestCases = new[] { // Initial margin requirement (including premium) for NakedCall with quantity 10 and -10 is 194000m and 112000m respectively new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, 194000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, 194000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, -112000m, -20), // Going from 10 to -10 new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, 112000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, 112000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, -194000m, -20), // Going from -10 to 10 // Initial margin requirement (including premium) for NakedPut with quantity 10 and -10 is 30020m and 20m respectively new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, 30020m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, 30020m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, -20m, -20), // Going from 10 to -10 new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, 20m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, 20m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, -30020m, -20), // Going from -10 to 10 // Initial margin requirement (including premium) for CoveredCall with quantity 10 and -10 is 192100m and 214500m respectively new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, 192100m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, 192100m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, -214500m, -20), // Going from 10 to -10 new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, 214500m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, 214500m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, -192100m, -20), // Going from -10 to 10 // Initial margin requirement (including premium) for ProtectiveCall with quantity 10 and -10 is 214500m and 192100m respectively new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, 214500m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, 214500m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, -192100m, -20), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, 192100m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, 192100m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, -214500m, -20), // Initial margin requirement (including premium) for CoveredPut with quantity 10 and -10 is 102500m and 102520m respectively new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, 102500m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, 102500m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, -102520m, -20), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, 102520m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, 102520m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, -102500m, -20), // Initial margin requirement (including premium) for ProtectivePut with quantity 10 and -10 is 102520m and 102500m respectively new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, 102520m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, 102520m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, -102500m, -20), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, 102500m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, 102500m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, -102520m, -20), // Initial margin requirement (including premium) for ProtectiveCollar with quantity 10 and -10 is 262310m and 262318m respectively new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, 262310m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, 262310m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, -262318m, -20), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, 262318m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, 262318m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, -262310m, -20), // Initial margin requirement (including premium) for Conversion with quantity 10 and -10 is 262945m and 263778m respectively new TestCaseData(OptionStrategyDefinitions.Conversion, 10, 262945m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, 262945m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, -263778m, -20), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, 263778m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, 263778m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, -262945m, -20), // Initial margin requirement (including premium) for ReverseConversion with quantity 10 and -10 is 263768m and 262915m respectively new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, 263768m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, 263768m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, -262915m, -20), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, 262915m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, 262915m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, -263768m, -20), // Initial margin requirement (including premium) for BearCallSpread with quantity 10 and -10 is 10000 and 12000 respectively new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, 10000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, 10000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, -12000m, -20), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, 12000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, 12000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, -10000m, -20), // Initial margin requirement (including premium) for BearPutSpread with quantity 10 and -10 is 10 and 10000 respectively new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, 10m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, 10m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, -10000m, -20), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, 10000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, 10000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, -10m, -20), // Initial margin requirement (including premium) for BullCallSpread with quantity 10 and -10 is 12000 and 10000 respectively new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, 12000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, 12000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, -10000m, -20), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, 10000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, 10000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, -12000m, -20), // Initial margin requirement (including premium) for BullPutSpread with quantity 10 and -10 is 10000 and 10 respectively new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, 10000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, 10000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, -10m, -20), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, 10m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, 10m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, -10000m, -20), // Initial margin requirement (including premium) for Straddle with quantity 10 and -10 is 112020 and 194020 respectively new TestCaseData(OptionStrategyDefinitions.Straddle, 10, 112020m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, 112020m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, -194020m, -20), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, 194020m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, 194020m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, -112020m, -20), // Initial margin requirement (including premium) for ShortStraddle with quantity 10 and -10 is 194020 and 112020 respectively new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, 194020m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, 194020m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, -112020m, -20), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, 112020m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, 112020m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, -194020m, -20), // Initial margin requirement (including premium) for Strangle with quantity 10 and -10 is 100020 and 182020 respectively new TestCaseData(OptionStrategyDefinitions.Strangle, 10, 100020m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, 100020m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, -182020m, -20), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, 182020m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, 182020m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, -100020m, -20), // Initial margin requirement (including premium) for ShortStrangle with quantity 10 and -10 is 182020 and 100020 respectively new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, 182020m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, 182020m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, -100020m, -20), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, 100020m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, 100020m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, -182020m, -20), // Initial margin requirement (including premium) for ButterflyCall with quantity 10 and -10 is 4000 and 10000 respectively new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, 4000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, 4000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, -10000m, -20), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, 10000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, 10000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, -4000m, -20), // Initial margin requirement (including premium) for ShortButterflyCall with quantity 10 and -10 is 10000 and 4000 respectively new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, 10000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, 10000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, -4000m, -20), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, 4000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, 4000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, -10000m, -20), // Initial margin requirement (including premium) for ButterflyPut with quantity 10 and -10 is 10 and 10000 respectively new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, 10m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, 10m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, -10000m, -20), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, 10000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, 10000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, -10m, -20), // Initial margin requirement (including premium) for ShortButterflyPut with quantity 10 and -10 is 10000 and 10 respectively new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, 10000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, 10000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, -10m, -20), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, 10m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, 10m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, -10000m, -20), // Initial margin requirement (including premium) for CallCalendarSpread with quantity 10 and -10 is 2000 and 194000 respectively new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, 2000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, 2000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, -194000m, -20), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, 194000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, 194000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, -2000m, -20), // Initial margin requirement (including premium) for ShortCallCalendarSpread with quantity 10 and -10 is 194000 and 2000 respectively new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, 194000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, 194000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, -2000m, -20), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, 2000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, 2000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, -194000m, -20), // Initial margin requirement (including premium) for PutCalendarSpread with quantity 10 and -10 is 10 and 30020 respectively new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, 10m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, 10m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, -30020m, -20), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, 30020m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, 30020m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, -10m, -20), // Initial margin requirement (including premium) for ShortPutCalendarSpread with quantity 10 and -10 is 30020 and 10 respectively new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, 30020m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, 30020m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, -10m, -20), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, 10m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, 10m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, -30020m, -20), // Initial margin requirement (including premium) for IronButterfly with quantity 10 and -10 is 10000 and 8010 respectively new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, 10000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, 10000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, -8010m, -20), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, 8010m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, 8010m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, -10000m, -20), // Initial margin requirement (including premium) for ShortIronButterfly with quantity 10 and -10 is 8010 and 10000 respectively new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, 8010m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, 8010m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, -10000m, -20), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, 10000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, 10000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, -8010m, -20), // Initial margin requirement (including premium) for IronCondor with quantity 10 and -10 is 10000 and 10010 respectively new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, 10000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, 10000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, -10010m, -20), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, 10010m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, 10010m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, -10000m, -20), // Initial margin requirement (including premium) for ShortIronCondor with quantity 10 and -10 is 10010 and 10000 respectively new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, 10010m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, 10010m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, -10000m, -20), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, 10000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, 10000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, -10010m, -20), // Initial margin requirement (including premium) for BoxSpread with quantity 10 and -10 is 20030 and 20000 respectively new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, 20030m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, 20030m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, -20000m, -20), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, 20000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, 20000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, -20030m, -20), // Initial margin requirement (including premium) for ShortBoxSpread with quantity 10 and -10 is 20000 and 20030 respectively new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, 20000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, 20000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, -20030m, -20), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, 20030m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, 20030m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, -20000m, -20), // Initial margin requirement (including premium) for JellyRoll with quantity 10 and -10 is 115319 and 115372 respectively new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, 115319m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, 115319m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, -115372m, -20), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, 115372m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, 115372m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, -115319m, -20), // Initial margin requirement (including premium) for ShortJellyRoll with quantity 10 and -10 is 115319 and 115372 respectively new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, 115372m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, 115372m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, -115319m, -20), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, 115319m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, 115319m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, -115372m, -20), // Initial margin requirement (including premium) for BearCallLadder with quantity 10 and -10 is 4000 and 106590.4 respectively new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, 4000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, 4000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, -106590.4m, -20), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, 106590.4m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, 106590.4m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, -4000m, -20), // Initial margin requirement (including premium) for BearPutLadder with quantity 10 and -10 is 108789.6 and 4000 respectively new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, 108789.6m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, 108789.6m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, -4000m, -20), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, 4000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, 4000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, -108789.6m, -20), // Initial margin requirement (including premium) for BullCallLadder with quantity 10 and -10 is 4000 and 106590.4 respectively new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, 106590.4m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, 106590.4m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, -4000m, -20), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, 4000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, 4000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, -106590.4m, -20), // Initial margin requirement (including premium) for BullPutLadder with quantity 10 and -10 is 108789.6 and 4000 respectively new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, 4000m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, 4000m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, -108789.6m, -20), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, 108789.6m * 11 / 10, +1), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, 108789.6m * 9 / 10, -1), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, 0m, -10), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, -4000m, -20), }; [TestCaseSource(nameof(OrderQuantityForTargetBuyingPowerTestCases))] public void PositionGroupOrderQuantityCalculationForTargetBuyingPower(OptionStrategyDefinition optionStrategyDefinition, int initialPositionQuantity, decimal targetBuyingPower, int expectedQuantity) { var positionGroup = SetUpOptionStrategy(optionStrategyDefinition, initialPositionQuantity); targetBuyingPower *= 1.0001m; // Add a small buffer to avoid rounding errors var targetBuyingPowerPercent = targetBuyingPower / _portfolio.TotalPortfolioValue; var quantity = positionGroup.BuyingPowerModel.GetMaximumLotsForTargetBuyingPower(new GetMaximumLotsForTargetBuyingPowerParameters( _portfolio, positionGroup, targetBuyingPowerPercent, minimumOrderMarginPortfolioPercentage: 0)).NumberOfLots; Assert.AreEqual(expectedQuantity, quantity); } private static TestCaseData[] OrderQuantityForTargetBuyingPowerWithCustomPositionGroupParameterTestCases() { return OrderQuantityForTargetBuyingPowerTestCases .SelectMany(testCaseData => { var testCases = new List(2); foreach (var referencePositionSideSign in new[] { +1, -1 }) { var args = testCaseData.OriginalArguments.ToList(); args.Add(referencePositionSideSign); var data = new TestCaseData(args.ToArray()); if (testCaseData.RunState == NUnit.Framework.Interfaces.RunState.Explicit) { data.Explicit(); } testCases.Add(data); } return testCases; }) .ToArray(); } /// /// Tests with reference position group in /// same and opposite side of the existing position group. /// /// The reference position group is not necessarily in the same side as the position group in the portfolio, it could be the inverted. /// So the consumer needs the result relative to that position group instead of the one being held. /// [TestCaseSource(nameof(OrderQuantityForTargetBuyingPowerWithCustomPositionGroupParameterTestCases))] public void PositionGroupOrderQuantityCalculationForTargetBuyingPowerWithCustomPositionGroupParameter( OptionStrategyDefinition optionStrategyDefinition, int initialPositionQuantity, decimal targetBuyingPower, int expectedQuantity, int referenceGroupSideSign) { var currentPositionGroup = SetUpOptionStrategy(optionStrategyDefinition, initialPositionQuantity); targetBuyingPower *= 1.0001m; // Add a small buffer to avoid rounding errors var targetBuyingPowerPercent = targetBuyingPower / _portfolio.TotalPortfolioValue; var referencePositionGroup = new PositionGroup(currentPositionGroup.BuyingPowerModel, 1, currentPositionGroup.Select(position => new Position(position.Symbol, referenceGroupSideSign * Math.Sign(position.Quantity) * position.UnitQuantity, position.UnitQuantity)).ToArray()); var quantity = currentPositionGroup.BuyingPowerModel.GetMaximumLotsForTargetBuyingPower(new GetMaximumLotsForTargetBuyingPowerParameters( _portfolio, referencePositionGroup, referenceGroupSideSign * targetBuyingPowerPercent, minimumOrderMarginPortfolioPercentage: 0)).NumberOfLots; Assert.AreEqual(referenceGroupSideSign * expectedQuantity, quantity); } /// /// Starting from the "initial position quantity", we want to get to a new position with "initial position quantity" + "order quantity". /// /// These test cases assume a starting margin/cash of 1M. /// The expected buying power test case parameter is left explicitly calculated as a constant in order to make it clearer. /// private static readonly TestCaseData[] PositionGroupBuyingPowerTestCases = new[] { // Going from 10 to 11. // Expected buying power for going longer: // (1000000 initial cash - 185000 used margin) margin remaining new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, 1, 1000000m - 185000m), // Going from 10 to 9. // Expected buying power for reducing, closing or going short: // (1000000 initial cash - 185000 used margin) margin remaining + 185000 used margin + 192100 initial margin requirement new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, -1, (1000000m - 185000m) + 185000m + 192100m), // Going from 10 to 0. new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, -10, (1000000m - 185000m) + 185000m + 192100m), // Going from 10 to -10. new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, -20, (1000000m - 185000m) + 185000m + 192100m), // Expected buying power for going shorter: // (1000000 initial cash - 30000 used margin) margin remaining new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, -1, 1000000m - 30000m), // Expected buying power for reducing, closing or going long: // (1000000 initial cash - 30000 used margin) margin remaining + 30000 used margin + 102500 initial margin requirement new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, 1, (1000000m - 30000m) + 30000m + 214500m), new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, 10, (1000000m - 30000m) + 30000m + 214500m), new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, 20, (1000000m - 30000m) + 30000m + 214500m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, +1, 1000000m - 30000m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, -1, (1000000m - 30000m) + 30000m + 214500m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, -10, (1000000m - 30000m) + 30000m + 214500m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, -20, (1000000m - 30000m) + 30000m + 214500m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, -1, 1000000m - 185000m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, 1, (1000000m - 185000m) + 185000m + 192100m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, 10, (1000000m - 185000m) + 185000m + 192100m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, 20, (1000000m - 185000m) + 185000m + 192100m), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, 1, 1000000m - 102500m), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, -1, (1000000m - 102500m) + 102500m + 102500m), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, -10, (1000000m - 102500m) + 102500m + 102500m), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, -20, (1000000m - 102500m) + 102500m + 102500m), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, -1, 1000000m - 102500m), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, 1, (1000000m - 102500m) + 102500m + 102520m), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, 10, (1000000m - 102500m) + 102500m + 102520m), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, 20, (1000000m - 102500m) + 102500m + 102520m), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, 1, 1000000m - 102500m), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, -1, (1000000m - 102500m) + 102500m + 102520m), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, -10, (1000000m - 102500m) + 102500m + 102520m), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, -20, (1000000m - 102500m) + 102500m + 102520m), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, -1, 1000000m - 102500m), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, 1, (1000000m - 102500m) + 102500m + 102500m), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, 10, (1000000m - 102500m) + 102500m + 102500m), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, 20, (1000000m - 102500m) + 102500m + 102500m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, 1, 1000000m - 62020m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, -1, (1000000m - 62020m) + 62020m + 262318m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, -10, (1000000m - 62020m) + 62020m + 262318m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, -20, (1000000m - 62020m) + 62020m + 262318m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, -1, 1000000m - 62020m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, 1, (1000000m - 62020m) + 62020m + 262310m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, 10, (1000000m - 62020m) + 62020m + 262310m), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, 20, (1000000m - 62020m) + 62020m + 262310m), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, 1, 1000000m - 53030m), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, -1, (1000000m - 53030m) + 53030m + 262945m), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, -10, (1000000m - 53030m) + 53030m + 262945m), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, -20, (1000000m - 53030m) + 53030m + 262945m), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, -1, 1000000m - 52400m), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, 1, (1000000m - 52400m) + 52400m + 263778m), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, 10, (1000000m - 52400m) + 52400m + 263778m), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, 20, (1000000m - 52400m) + 52400m + 263778m), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, 1, 1000000m - 52400m), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, -1, (1000000m - 52400m) + 52400m + 263768m), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, -10, (1000000m - 52400m) + 52400m + 263768m), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, -20, (1000000m - 52400m) + 52400m + 263768m), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, -1, 1000000m - 53010m), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, 1, (1000000m - 53010m) + 53010m + 262915m), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, 10, (1000000m - 53010m) + 53010m + 262915m), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, 20, (1000000m - 53010m) + 53010m + 262915m), new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, +1, 1000000m - 194000m), new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, -1, (1000000m - 194000m) + 194000m + 194000m), new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, -10, (1000000m - 194000m) + 194000m + 194000m), new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, -20, (1000000m - 194000m) + 194000m + 194000m), new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, -1, 1000000m - 0m), new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, 1, (1000000m - 0m) + 0m + 112000m), new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, 10, (1000000m - 0m) + 0m + 112000m), new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, 20, (1000000m - 0m) + 0m + 112000m), new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, +1, 1000000m - 30020m), new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, -1, (1000000m - 30020m) + 30020m + 30020m), new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, -10, (1000000m - 30020m) + 30020m + 30020m), new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, -20, (1000000m - 30020m) + 30020m + 30020m), new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, -1, 1000000m - 0m), new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, 1, (1000000m - 0m) + 0m + 20m), new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, 10, (1000000m - 0m) + 0m + 20m), new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, 20, (1000000m - 0m) + 0m + 20m), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, 1, 1000000m - 10000m), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, -1, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, -10, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, -20, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, -1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, 1, (1000000m - 0) + 0 + 12000m), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, 10, (1000000m - 0) + 0 + 12000m), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, 20, (1000000m - 0) + 0 + 12000m), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, 1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, -1, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, -10, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, -20, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, -1, 1000000m - 10000m), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, 1, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, 10, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, 20, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, 1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, -1, (1000000m - 0) + 0 + 12000m), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, -10, (1000000m - 0) + 0 + 12000m), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, -20, (1000000m - 0) + 0 + 12000m), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, -1, 1000000m - 10000m), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, 1, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, 10, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, 20, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, 1, 1000000m - 10000m), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, -1, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, -10, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, -20, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, -1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, 1, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, 10, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, 20, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, 1, 1000000m - 0m), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, -1, (1000000m - 0m) + 0m + 112020m), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, -10, (1000000m - 0m) + 0m + 112020m), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, -20, (1000000m - 0m) + 0m + 112020m), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, -1, 1000000m - 194020m), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, 1, (1000000m - 194020m) + 194020m + 194020m), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, 10, (1000000m - 194020m) + 194020m + 194020m), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, 20, (1000000m - 194020m) + 194020m + 194020m), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, +1, 1000000m - 194020m), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, -1, (1000000m - 194020m) + 194020m + 194020m), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, -10, (1000000m - 194020m) + 194020m + 194020m), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, -20, (1000000m - 194020m) + 194020m + 194020m), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, -1, 1000000m - 0m), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, 1, (1000000m - 0m) + 0m + 112020m), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, 10, (1000000m - 0m) + 0m + 112020m), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, 20, (1000000m - 0m) + 0m + 112020m), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, 1, 1000000m - 0m), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, -1, (1000000m - 0m) + 0m + 100020m), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, -10, (1000000m - 0m) + 0m + 100020m), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, -20, (1000000m - 0m) + 0m + 100020m), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, -1, 1000000m - 182020m), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, 1, (1000000m - 182020m) + 182020m + 182020m), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, 10, (1000000m - 182020m) + 182020m + 182020m), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, 20, (1000000m - 182020m) + 182020m + 182020m), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, 1, 1000000m - 182020m), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, -1, (1000000m - 182020m) + 182020m + 182020m), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, -10, (1000000m - 182020m) + 182020m + 182020m), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, -20, (1000000m - 182020m) + 182020m + 182020m), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, -1, 1000000m - 0m), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, 1, (1000000m - 0m) + 0m + 100020m), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, 10, (1000000m - 0m) + 0m + 100020m), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, 20, (1000000m - 0m) + 0m + 100020m), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, 1, 1000000m - 0m), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, -1, (1000000m - 0m) + 0m + 4000m), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, -10, (1000000m - 0m) + 0m + 4000m), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, -20, (1000000m - 0m) + 0m + 4000m), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, -1, 1000000m - 10000m), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, 1, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, 10, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, 20, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, 1, 1000000m - 10000m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, -1, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, -10, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, -20, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, -1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, 1, (1000000m - 0) + 0 + 4000m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, 10, (1000000m - 0) + 0 + 4000m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, 20, (1000000m - 0) + 0 + 4000m), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, 1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, -1, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, -10, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, -20, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, -1, 1000000m - 10000m), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, 1, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, 10, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, 20, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, 1, 1000000m - 10000m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, -1, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, -10, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, -20, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, -1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, 1, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, 10, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, 20, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, 1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, -1, (1000000m - 0) + 0 + 2000m), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, -10, (1000000m - 0) + 0 + 2000m), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, -20, (1000000m - 0) + 0 + 2000m), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, -1, 1000000m - 194000m), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, 1, (1000000m - 194000m) + 194000m + 194000m), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, 10, (1000000m - 194000m) + 194000m + 194000m), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, 20, (1000000m - 194000m) + 194000m + 194000m), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, 1, 1000000m - 194000m), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, -1, (1000000m - 194000m) + 194000m + 194000m), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, -10, (1000000m - 194000m) + 194000m + 194000m), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, -20, (1000000m - 194000m) + 194000m + 194000m), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, -1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, 1, (1000000m - 0) + 0 + 2000m), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, 10, (1000000m - 0) + 0 + 2000m), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, 20, (1000000m - 0) + 0 + 2000m), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, 1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, -1, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, -10, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, -20, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, -1, 1000000m - 30020m), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, 1, (1000000m - 30020m) + 30020m + 30020m), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, 10, (1000000m - 30020m) + 30020m + 30020m), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, 20, (1000000m - 30020m) + 30020m + 30020m), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, 1, 1000000m - 30020m), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, -1, (1000000m - 30020m) + 30020m + 30020m), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, -10, (1000000m - 30020m) + 30020m + 30020m), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, -20, (1000000m - 30020m) + 30020m + 30020m), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, -1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, 1, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, 10, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, 20, (1000000m - 0) + 0 + 10m), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, 1, 1000000m - 10000m), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, -1, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, -10, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, -20, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, -1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, 1, (1000000m - 0) + 0 + 8010m), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, 10, (1000000m - 0) + 0 + 8010m), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, 20, (1000000m - 0) + 0 + 8010m), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, 1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, -1, (1000000m - 0) + 0 + 8010m), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, -10, (1000000m - 0) + 0 + 8010m), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, -20, (1000000m - 0) + 0 + 8010m), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, -1, 1000000m - 10000m), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, 1, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, 10, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, 20, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, 1, 1000000m - 10000m), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, -1, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, -10, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, -20, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, -1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, 1, (1000000m - 0) + 0 + 10010m), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, 10, (1000000m - 0) + 0 + 10010m), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, 20, (1000000m - 0) + 0 + 10010m), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, 1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, -1, (1000000m - 0) + 0 + 10010m), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, -10, (1000000m - 0) + 0 + 10010m), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, -20, (1000000m - 0) + 0 + 10010m), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, -1, 1000000m - 10000m), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, 1, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, 10, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, 20, (1000000m - 10000m) + 10000m + 10000m), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, 1, 1000000m - 0m), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, -1, (1000000m - 0m) + 0m + 20030m), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, -10, (1000000m - 0m) + 0m + 20030m), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, -20, (1000000m - 0m) + 0m + 20030m), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, -1, 1000000m - 20000m), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, 1, (1000000m - 20000m) + 20000m + 20000m), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, 10, (1000000m - 20000m) + 20000m + 20000m), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, 20, (1000000m - 20000m) + 20000m + 20000m), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, 1, 1000000m - 20000m), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, -1, (1000000m - 20000m) + 20000m + 20000m), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, -10, (1000000m - 20000m) + 20000m + 20000m), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, -20, (1000000m - 20000m) + 20000m + 20000m), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, -1, 1000000m - 0), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, 1, (1000000m - 0) + 0 + 20030m), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, 10, (1000000m - 0) + 0 + 20030m), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, 20, (1000000m - 0) + 0 + 20030m), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, 1, 1000000m - 114475m), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, -1, (1000000m - 115319m) + 115319m + 115319m), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, -10, (1000000m - 115319m) + 115319m + 115319m), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, -20, (1000000m - 115319m) + 115319m + 115319m), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, -1, 1000000m - 115372m), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, 1, (1000000m - 115372m) + 115372m + 115372m), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, 10, (1000000m - 115372m) + 115372m + 115372m), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, 20, (1000000m - 115372m) + 115372m + 115372m), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, 1, 1000000m - 115372m), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, -1, (1000000m - 115372m) + 115372m + 115372m), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, -10, (1000000m - 115372m) + 115372m + 115372m), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, -20, (1000000m - 115372m) + 115372m + 115372m), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, -1, 1000000m - 114475m), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, 1, (1000000m - 115319m) + 115319m + 115319m), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, 10, (1000000m - 115319m) + 115319m + 115319m), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, 20, (1000000m - 115319m) + 115319m + 115319m), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, 1, 1000000m - 4000m), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, -1, (1000000m - 4000m) + 4000m + 4000m), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, -10, (1000000m - 4000m) + 4000m + 4000m), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, -20, (1000000m - 4000m) + 4000m + 4000m), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, -1, 1000000m - 104070.4m), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, 1, (1000000m - 106590.4m) + 106590.4m + 106590.4m), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, 10, (1000000m - 106590.4m) + 106590.4m + 106590.4m), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, 20, (1000000m - 106590.4m) + 106590.4m + 106590.4m), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, 1, 1000000m - 105325.6m), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, -1, (1000000m - 108789.6m) + 108789.6m + 108789.6m), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, -10, (1000000m - 108789.6m) + 108789.6m + 108789.6m), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, -20, (1000000m - 108789.6m) + 108789.6m + 108789.6m), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, -1, 1000000m - 4000m), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, 1, (1000000m - 4000m) + 4000m + 4000m), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, 10, (1000000m - 4000m) + 4000m + 4000m), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, 20, (1000000m - 4000m) + 4000m + 4000m), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, 1, 1000000m - 104070.4m), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, -1, (1000000m - 106590.4m) + 106590.4m + 106590.4m), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, -10, (1000000m - 106590.4m) + 106590.4m + 106590.4m), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, -20, (1000000m - 106590.4m) + 106590.4m + 106590.4m), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, -1, 1000000m - 4000m), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, 1, (1000000m - 4000m) + 4000m + 4000m), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, 10, (1000000m - 4000m) + 4000m + 4000m), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, 20, (1000000m - 4000m) + 4000m + 4000m), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, 1, 1000000m - 4000m), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, -1, (1000000m - 4000m) + 4000m + 4000m), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, -10, (1000000m - 4000m) + 4000m + 4000m), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, -20, (1000000m - 4000m) + 4000m + 4000m), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, -1, 1000000m - 105325.6m), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, 1, (1000000m - 108789.6m) + 108789.6m + 108789.6m), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, 10, (1000000m - 108789.6m) + 108789.6m + 108789.6m), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, 20, (1000000m - 108789.6m) + 108789.6m + 108789.6m), }; [TestCaseSource(nameof(PositionGroupBuyingPowerTestCases))] public void BuyingPowerForPositionGroupCalculation(OptionStrategyDefinition optionStrategyDefinition, int initialPositionQuantity, int orderQuantity, decimal expectedBuyingPower) { var initialPositionGroup = SetUpOptionStrategy(optionStrategyDefinition, initialPositionQuantity, updateCashbook: true); var orderPositionGroup = initialPositionGroup.WithQuantity(Math.Abs(orderQuantity), _portfolio.Positions); var orderDirection = Math.Sign(initialPositionQuantity) == Math.Sign(orderQuantity) ? OrderDirection.Buy : OrderDirection.Sell; var buyingPower = initialPositionGroup.BuyingPowerModel.GetPositionGroupBuyingPower(new PositionGroupBuyingPowerParameters( _portfolio, orderPositionGroup, orderDirection)); Assert.That(buyingPower.Value, Is.EqualTo(expectedBuyingPower).Within(1e-18)); } [Test] public void BuyingPowerForStrategyStartingFromOptionPositionInSameDirection() { // 1. Sell a call option // 2. Get the available buying power for the long call var expiration = new DateTime(2023, 05, 19); var spy = _algorithm.AddEquity("SPY"); spy.SetMarketPrice(new Tick { Value = 400m }); var spyMay19_300Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 300, expiration)); spyMay19_300Call.SetMarketPrice(new Tick { Value = 110m }); var spyMay19_350Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 350, expiration)); spyMay19_350Call.SetMarketPrice(new Tick { Value = 100m }); // 1. Sell a call option spyMay19_300Call.Holdings.SetHoldings(spyMay19_300Call.Price, -1); var initialPositionGroup = _portfolio.Positions.Groups.Single(); var finalPositionGroup = new PositionGroup(new OptionStrategyPositionGroupBuyingPowerModel( OptionStrategies.BearCallSpread(spyMay19_300Call.Symbol.Canonical, spyMay19_300Call.StrikePrice, spyMay19_350Call.StrikePrice, expiration)), 1, initialPositionGroup.Positions.Single(), new Position(spyMay19_350Call.Symbol, 1, 1)); // 2. Get the available buying power for the long call var buyingPower = finalPositionGroup.BuyingPowerModel.GetPositionGroupBuyingPower(new PositionGroupBuyingPowerParameters( _portfolio, finalPositionGroup, OrderDirection.Buy)).Value; Assert.AreEqual(_portfolio.MarginRemaining, buyingPower); } [Test] public void BuyingPowerForStrategyStartingFromOptionPositionInOppositeDirection() { // 1. Buy 10 call options // 2. Get the available buying power for the resulting "what-if" position group after buying 5 bear call spreads // with the short call in the holdings as the long leg (reducing the existing position) var expiration = new DateTime(2023, 05, 19); var spy = _algorithm.AddEquity("SPY"); spy.SetMarketPrice(new Tick { Value = 400m }); var spyMay19_300Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 300, expiration)); spyMay19_300Call.SetMarketPrice(new Tick { Value = 110m }); var spyMay19_350Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 350, expiration)); spyMay19_350Call.SetMarketPrice(new Tick { Value = 100m }); // 1. Buy 10 call options spyMay19_300Call.Holdings.SetHoldings(spyMay19_300Call.Price, 10); // Buying 4 bear call with spyMay19_300Call as the short leg and spyMay19_350Call as the long leg, // would leave us with 6 spyMay19_300Call and 4 spyMay19_350Call, so the resolved position group will be a long call // (for spyMay19_350Call) var finalPositionGroup = new PositionGroup(new OptionStrategyPositionGroupBuyingPowerModel( OptionStrategies.NakedCall(spyMay19_350Call.Symbol.Canonical, spyMay19_350Call.StrikePrice, expiration)), 6, new Position(spyMay19_350Call.Symbol, 6, 1)); // 2. Get the available buying power var initialPositionGroup = _portfolio.Positions.Groups.Single(); var buyingPower = finalPositionGroup.BuyingPowerModel.GetPositionGroupBuyingPower(new PositionGroupBuyingPowerParameters( _portfolio, finalPositionGroup, OrderDirection.Buy)).Value; var expectedBuyingPower = _portfolio.MarginRemaining + initialPositionGroup.BuyingPowerModel.GetMaintenanceMargin(new PositionGroupMaintenanceMarginParameters(_portfolio, initialPositionGroup)); Assert.AreEqual(expectedBuyingPower, buyingPower); } [Test] [Explicit] public void BuyingPowerForStrategyStartingFromOptionPositionInOppositeDirectionAndLiquidating() { // 1. Buy 10 call options // 2. Get the available buying power for the resulting "what-if" position group after buying 5 bear call spreads // with the short call in the holdings as the long leg (reducing the existing position) var expiration = new DateTime(2023, 05, 19); var spy = _algorithm.AddEquity("SPY"); spy.SetMarketPrice(new Tick { Value = 400m }); var spyMay19_300Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 300, expiration)); spyMay19_300Call.SetMarketPrice(new Tick { Value = 110m }); var spyMay19_350Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 350, expiration)); spyMay19_350Call.SetMarketPrice(new Tick { Value = 100m }); // 1. Buy 10 call options spyMay19_300Call.Holdings.SetHoldings(spyMay19_300Call.Price, 10); var initialPositionGroup = _portfolio.Positions.Groups.Single(); // Buying 12 bear call with spyMay19_300Call as the short leg and spyMay19_350Call as the long leg, // would leave us with -2 spyMay19_300Call (since holdings is 10) and 12 spyMay19_350Call, // so the resolved position group will be a bear call with quantity -2 var quantity = 10 - 12; var finalPositionGroup = initialPositionGroup.WithQuantity(quantity, _portfolio.Positions); // 2. Get the available buying power var buyingPower = finalPositionGroup.BuyingPowerModel.GetPositionGroupBuyingPower(new PositionGroupBuyingPowerParameters( _portfolio, finalPositionGroup, OrderDirection.Buy)).Value; var expectedBuyingPower = _portfolio.MarginRemaining + initialPositionGroup.BuyingPowerModel.GetMaintenanceMargin(new PositionGroupMaintenanceMarginParameters(_portfolio, initialPositionGroup)); Assert.AreEqual(expectedBuyingPower, buyingPower); } [Test] public void BuyingPowerForOptionStartingFromStrategyWithALegInSameDirection() { // 1. Buy 10 bear call spreads // 2. Get the available buying power for increasing one of the legs var expiration = new DateTime(2023, 05, 19); var spy = _algorithm.AddEquity("SPY"); spy.SetMarketPrice(new Tick { Value = 400m }); var spyMay19_300Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 300, expiration)); spyMay19_300Call.SetMarketPrice(new Tick { Value = 110m }); var spyMay19_350Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 350, expiration)); spyMay19_350Call.SetMarketPrice(new Tick { Value = 100m }); // 1. Buy 10 bear call spreads spyMay19_300Call.Holdings.SetHoldings(spyMay19_300Call.Price, -10); spyMay19_350Call.Holdings.SetHoldings(spyMay19_350Call.Price, +10); var initialPositionGroup = _portfolio.Positions.Groups.Single(); Assert.AreEqual(OptionStrategyDefinitions.BearCallSpread.Name, initialPositionGroup.BuyingPowerModel.ToString()); // 2. Get the available buying power for increasing one of the legs. // The resulting position group will be the same as the initial one // since we are only increasing the short leg but that won't affect the group var finalPositionGroup = initialPositionGroup; var buyingPower = finalPositionGroup.BuyingPowerModel.GetPositionGroupBuyingPower(new PositionGroupBuyingPowerParameters( _portfolio, finalPositionGroup, OrderDirection.Buy)).Value; Assert.AreEqual(_portfolio.MarginRemaining, buyingPower); } [Test] [Explicit] public void BuyingPowerForOptionStartingFromStrategyWithALegInTheOppositeDirection() { // 1. Buy 10 bear call spreads // 2. Get the available buying power for reducing one of the legs var expiration = new DateTime(2023, 05, 19); var spy = _algorithm.AddEquity("SPY"); spy.SetMarketPrice(new Tick { Value = 400m }); var spyMay19_300Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 300, expiration)); spyMay19_300Call.SetMarketPrice(new Tick { Value = 110m }); var spyMay19_350Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 350, expiration)); spyMay19_350Call.SetMarketPrice(new Tick { Value = 100m }); // 1. Buy 10 bear call spreads spyMay19_300Call.Holdings.SetHoldings(spyMay19_300Call.Price, -10); spyMay19_350Call.Holdings.SetHoldings(spyMay19_350Call.Price, +10); var initialPositionGroup = _portfolio.Positions.Groups.Single(); Assert.AreEqual(OptionStrategyDefinitions.BearCallSpread.Name, initialPositionGroup.BuyingPowerModel.ToString()); // 2. Get the available buying power for reducing one of the legs // If we want to reduce the short leg, by 5, the whole bear call will be reduced to 5 and the options separated into two groups var quantity = -10 + 5; var finalPositionGroup = initialPositionGroup.WithQuantity(quantity, _portfolio.Positions); var buyingPower = finalPositionGroup.BuyingPowerModel.GetPositionGroupBuyingPower(new PositionGroupBuyingPowerParameters( _portfolio, finalPositionGroup, OrderDirection.Buy)).Value; var expectedBuyingPower = _portfolio.MarginRemaining + initialPositionGroup.BuyingPowerModel.GetMaintenanceMargin(new PositionGroupMaintenanceMarginParameters(_portfolio, initialPositionGroup)); Assert.AreEqual(expectedBuyingPower, buyingPower); } [Test] [Explicit] public void BuyingPowerForOptionStartingFromStrategyWithALegInTheOppositeDirectionAndLiquidating() { // 1. Buy 10 bear call spreads // 2. Get the available buying power for reducing one of the legs var expiration = new DateTime(2023, 05, 19); var spy = _algorithm.AddEquity("SPY"); spy.SetMarketPrice(new Tick { Value = 400m }); var spyMay19_300Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 300, expiration)); spyMay19_300Call.SetMarketPrice(new Tick { Value = 110m }); var spyMay19_350Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 350, expiration)); spyMay19_350Call.SetMarketPrice(new Tick { Value = 100m }); // 1. Buy 10 bear call spreads spyMay19_300Call.Holdings.SetHoldings(spyMay19_300Call.Price, -10); spyMay19_350Call.Holdings.SetHoldings(spyMay19_350Call.Price, +10); var initialPositionGroup = _portfolio.Positions.Groups.Single(); Assert.AreEqual(OptionStrategyDefinitions.BearCallSpread.Name, initialPositionGroup.BuyingPowerModel.ToString()); // 2. Get the available buying power for reducing one of the legs // If we want to order 20 of the short call (buy 20 of the call), // the whole bear call group will be eliminated and the options separated into two groups. // The resulting group for the order will be a naked call var quantity = -10 + 20; var finalPositionGroup = new PositionGroup(new OptionStrategyPositionGroupBuyingPowerModel( OptionStrategies.NakedCall(spyMay19_300Call.Symbol.Canonical, spyMay19_300Call.StrikePrice, expiration)), quantity, new Position(spyMay19_300Call.Symbol, quantity, 1)); var buyingPower = finalPositionGroup.BuyingPowerModel.GetPositionGroupBuyingPower(new PositionGroupBuyingPowerParameters( _portfolio, finalPositionGroup, OrderDirection.Buy)).Value; var expectedBuyingPower = _portfolio.MarginRemaining + initialPositionGroup.BuyingPowerModel.GetMaintenanceMargin(new PositionGroupMaintenanceMarginParameters(_portfolio, initialPositionGroup)); Assert.AreEqual(expectedBuyingPower, buyingPower); } private static readonly TestCaseData[] ReservedBuyingPowerImpactTestCases = new[] { // option strategy definition, initial position quantity, new position quantity // Starting from the "initial position quantity", we want to get the buying power available for an order that would get us to // the "new position quantity" (if we don't take into account the initial position). new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, 1), // Going from 10 to 11 new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, -1), // Going from 10 to 9 new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, -10), // Going from 10 to 0 new TestCaseData(OptionStrategyDefinitions.NakedCall, 10, -20), // Going from 10 to -10 new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, -1), new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, 1), new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, 10), new TestCaseData(OptionStrategyDefinitions.NakedCall, -10, 20), new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, 1), // Going from 10 to 11 new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, -1), // Going from 10 to 9 new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, -10), // Going from 10 to 0 new TestCaseData(OptionStrategyDefinitions.NakedPut, 10, -20), // Going from 10 to -10 new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, -1), new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, 1), new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, 10), new TestCaseData(OptionStrategyDefinitions.NakedPut, -10, 20), new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, 1), // Going from 10 to 11 new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, -1), // Going from 10 to 9 new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, -10), // Going from 10 to 0 new TestCaseData(OptionStrategyDefinitions.CoveredCall, 10, -20), // Going from 10 to -10 new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, -1), new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, 1), new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, 10), new TestCaseData(OptionStrategyDefinitions.CoveredCall, -10, 20), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, 1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, -10), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, 10, -20), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, 1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, 10), new TestCaseData(OptionStrategyDefinitions.ProtectiveCall, -10, 20), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, 1), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, -1), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, -10), new TestCaseData(OptionStrategyDefinitions.CoveredPut, 10, -20), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, -1), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, 1), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, 10), new TestCaseData(OptionStrategyDefinitions.CoveredPut, -10, 20), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, 1), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, -10), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, 10, -20), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, 1), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, 10), new TestCaseData(OptionStrategyDefinitions.ProtectivePut, -10, 20), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, 1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, -10), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, 10, -20), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, -1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, 1), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, 10), new TestCaseData(OptionStrategyDefinitions.ProtectiveCollar, -10, 20), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, 1), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, -1), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, -10), new TestCaseData(OptionStrategyDefinitions.Conversion, 10, -20), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, -1), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, 1), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, 10), new TestCaseData(OptionStrategyDefinitions.Conversion, -10, 20), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, 1), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, -1), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, -10), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, 10, -20), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, -1), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, 1), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, 10), new TestCaseData(OptionStrategyDefinitions.ReverseConversion, -10, 20), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, 1), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, -1), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, -10), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, 10, -20), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, -1), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, 1), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, 10), new TestCaseData(OptionStrategyDefinitions.BearCallSpread, -10, 20), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, 1), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, -1), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, -10), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, 10, -20), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, -1), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, 1), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, 10), new TestCaseData(OptionStrategyDefinitions.BearPutSpread, -10, 20), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, 1), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, -1), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, -10), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, 10, -20), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, -1), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, 1), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, 10), new TestCaseData(OptionStrategyDefinitions.BullCallSpread, -10, 20), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, 1), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, -1), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, -10), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, 10, -20), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, -1), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, 1), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, 10), new TestCaseData(OptionStrategyDefinitions.BullPutSpread, -10, 20), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, 1), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, -1), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, -10), new TestCaseData(OptionStrategyDefinitions.Straddle, 10, -20), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, -1), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, 1), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, 10), new TestCaseData(OptionStrategyDefinitions.Straddle, -10, 20), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, 1), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, -10), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, 10, -20), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, -1), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, 1), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, 10), new TestCaseData(OptionStrategyDefinitions.ShortStraddle, -10, 20), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, 1), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, -1), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, -10), new TestCaseData(OptionStrategyDefinitions.Strangle, 10, -20), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, -1), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, 1), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, 10), new TestCaseData(OptionStrategyDefinitions.Strangle, -10, 20), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, 1), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, -10), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, 10, -20), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, -1), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, 1), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, 10), new TestCaseData(OptionStrategyDefinitions.ShortStrangle, -10, 20), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, 1), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, -1), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, -10), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, 10, -20), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, -1), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, 1), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, 10), new TestCaseData(OptionStrategyDefinitions.ButterflyCall, -10, 20), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, 1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, -10), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, 10, -20), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, -1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, 1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, 10), new TestCaseData(OptionStrategyDefinitions.ShortButterflyCall, -10, 20), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, 1), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, -1), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, -10), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, 10, -20), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, -1), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, 1), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, 10), new TestCaseData(OptionStrategyDefinitions.ButterflyPut, -10, 20), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, 1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, -10), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, 10, -20), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, -1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, 1), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, 10), new TestCaseData(OptionStrategyDefinitions.ShortButterflyPut, -10, 20), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, 1), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, -1), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, -10), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, 10, -20), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, -1), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, 1), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, 10), new TestCaseData(OptionStrategyDefinitions.CallCalendarSpread, -10, 20), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, 1), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, -10), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, 10, -20), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, -1), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, 1), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, 10), new TestCaseData(OptionStrategyDefinitions.ShortCallCalendarSpread, -10, 20), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, 1), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, -1), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, -10), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, 10, -20), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, -1), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, 1), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, 10), new TestCaseData(OptionStrategyDefinitions.PutCalendarSpread, -10, 20), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, 1), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, -10), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, 10, -20), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, -1), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, 1), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, 10), new TestCaseData(OptionStrategyDefinitions.ShortPutCalendarSpread, -10, 20), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, 1), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, -1), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, -10), new TestCaseData(OptionStrategyDefinitions.IronButterfly, 10, -20), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, -1), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, 1), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, 10), new TestCaseData(OptionStrategyDefinitions.IronButterfly, -10, 20), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, 1), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, -10), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, 10, -20), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, -1), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, 1), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, 10), new TestCaseData(OptionStrategyDefinitions.ShortIronButterfly, -10, 20), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, 1), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, -1), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, -10), new TestCaseData(OptionStrategyDefinitions.IronCondor, 10, -20), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, -1), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, 1), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, 10), new TestCaseData(OptionStrategyDefinitions.IronCondor, -10, 20), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, 1), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, -10), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, 10, -20), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, -1), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, 1), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, 10), new TestCaseData(OptionStrategyDefinitions.ShortIronCondor, -10, 20), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, 1), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, -1), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, -10), new TestCaseData(OptionStrategyDefinitions.BoxSpread, 10, -20), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, -1), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, 1), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, 10), new TestCaseData(OptionStrategyDefinitions.BoxSpread, -10, 20), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, 1), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, -10), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, 10, -20), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, -1), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, 1), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, 10), new TestCaseData(OptionStrategyDefinitions.ShortBoxSpread, -10, 20), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, 1), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, -1), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, -10), new TestCaseData(OptionStrategyDefinitions.JellyRoll, 10, -20), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, -1), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, 1), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, 10), new TestCaseData(OptionStrategyDefinitions.JellyRoll, -10, 20), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, 1), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, -1), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, -10), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, 10, -20), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, -1), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, 1), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, 10), new TestCaseData(OptionStrategyDefinitions.ShortJellyRoll, -10, 20), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, 1), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, -1), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, -10), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, 10, -20), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, -1), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, 1), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, 10), new TestCaseData(OptionStrategyDefinitions.BearCallLadder, -10, 20), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, 1), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, -1), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, -10), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, 10, -20), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, -1), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, 1), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, 10), new TestCaseData(OptionStrategyDefinitions.BearPutLadder, -10, 20), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, 1), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, -1), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, -10), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, 10, -20), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, -1), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, 1), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, 10), new TestCaseData(OptionStrategyDefinitions.BullCallLadder, -10, 20), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, 1), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, -1), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, -10), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, 10, -20), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, -1), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, 1), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, 10), new TestCaseData(OptionStrategyDefinitions.BullPutLadder, -10, 20), }; [TestCaseSource(nameof(ReservedBuyingPowerImpactTestCases))] public void ReservedBuyingPowerImpactCalculation(OptionStrategyDefinition optionStrategyDefinition, int initialPositionQuantity, int newGroupQuantity) { var initialMargin = _portfolio.MarginRemaining; var initialPositionGroup = SetUpOptionStrategy(optionStrategyDefinition, initialPositionQuantity); var finalQuantity = initialPositionQuantity + newGroupQuantity; var sign = Math.Sign(finalQuantity) == Math.Sign(initialPositionQuantity) ? 1 : -1; var finalPositionGroup = finalQuantity != 0 ? initialPositionGroup.WithQuantity(sign * Math.Abs(finalQuantity), _portfolio.Positions) : PositionGroup.Empty(null); var orders = GetPositionGroupOrders(initialPositionGroup, initialPositionQuantity, newGroupQuantity); var buyingPowerImpact = initialPositionGroup.BuyingPowerModel.GetReservedBuyingPowerImpact(new ReservedBuyingPowerImpactParameters(_portfolio, finalPositionGroup, orders)); var usedMargin = initialPositionGroup.BuyingPowerModel.GetReservedBuyingPowerForPositionGroup( new ReservedBuyingPowerForPositionGroupParameters(_portfolio, initialPositionGroup)).AbsoluteUsedBuyingPower; foreach (var contemplatedChangePosition in buyingPowerImpact.ContemplatedChanges) { var position = finalPositionGroup.SingleOrDefault(p => contemplatedChangePosition.Symbol == p.Symbol); Assert.IsNotNull(position); Assert.AreEqual(position.Quantity, contemplatedChangePosition.Quantity); } var expectedContemplatedInitialMarginRequirement = finalQuantity != 0 ? ((OptionInitialMargin)finalPositionGroup.BuyingPowerModel.GetInitialMarginRequirement( new PositionGroupInitialMarginParameters(_portfolio, finalPositionGroup))).ValueWithoutPremium : 0m; var ordersPositions = orders.Select(o => o.CreatePositions(_portfolio.Securities)).SelectMany(p => p); var orderGroup = _portfolio.Positions.ResolvePositionGroups(new PositionCollection(ordersPositions)).Single(); var orderGroupInitialMargin = (OptionInitialMargin)orderGroup.BuyingPowerModel.GetInitialMarginRequirement( new PositionGroupInitialMarginParameters(_portfolio, orderGroup)); // Use Value-ValueWithoutPremium difference instead of Premium because when premium is negative, // it is not added to initial margin requirements since it is credited to the account expectedContemplatedInitialMarginRequirement += orderGroupInitialMargin.Value - orderGroupInitialMargin.ValueWithoutPremium; var expectedDelta = expectedContemplatedInitialMarginRequirement - usedMargin; Assert.That(buyingPowerImpact.Delta, Is.EqualTo(expectedDelta).Within(1e-18)); Assert.That(buyingPowerImpact.Current, Is.EqualTo(usedMargin).Within(1e-18)); Assert.That(buyingPowerImpact.Contemplated, Is.EqualTo(expectedContemplatedInitialMarginRequirement).Within(1e-18)); } private List GetStrategyOrders(decimal quantity) { var groupOrderManager = new GroupOrderManager(1, 2, quantity); return new List() { Order.CreateOrder(new SubmitOrderRequest( OrderType.ComboMarket, _callOption.Type, _callOption.Symbol, 1m.GetOrderLegGroupQuantity(groupOrderManager), 0, 0, _algorithm.Time, "", groupOrderManager: groupOrderManager)), Order.CreateOrder(new SubmitOrderRequest( OrderType.ComboMarket, _putOption.Type, _putOption.Symbol, 1m.GetOrderLegGroupQuantity(groupOrderManager), 0, 0, _algorithm.Time, "", groupOrderManager: groupOrderManager)) }; } private void SetUpOptionStrategy(int initialHoldingsQuantity) { const decimal price = 1.5m; const decimal underlyingPrice = 300m; _equity.SetMarketPrice(new Tick { Value = underlyingPrice }); _callOption.SetMarketPrice(new Tick { Value = price }); _putOption.SetMarketPrice(new Tick { Value = price }); _callOption.Holdings.SetHoldings(1m, initialHoldingsQuantity); _putOption.Holdings.SetHoldings(1m, initialHoldingsQuantity); Assert.AreEqual(1, _portfolio.Positions.Groups.Count); var positionGroup = _portfolio.Positions.Groups.First(); Assert.AreEqual(initialHoldingsQuantity < 0 ? OptionStrategyDefinitions.ShortStraddle.Name : OptionStrategyDefinitions.Straddle.Name, positionGroup.BuyingPowerModel.ToString()); var callOptionPosition = positionGroup.Positions.Single(x => x.Symbol == _callOption.Symbol); Assert.AreEqual(initialHoldingsQuantity, callOptionPosition.Quantity); var putOptionPosition = positionGroup.Positions.Single(x => x.Symbol == _putOption.Symbol); Assert.AreEqual(initialHoldingsQuantity, putOptionPosition.Quantity); } private void ComputeAndAssertQuantityForDeltaBuyingPower(IPositionGroup positionGroup, decimal expectedQuantity, decimal deltaBuyingPower) { var quantity = positionGroup.BuyingPowerModel.GetMaximumLotsForDeltaBuyingPower(new GetMaximumLotsForDeltaBuyingPowerParameters( _portfolio, positionGroup, deltaBuyingPower, minimumOrderMarginPortfolioPercentage: 0)).NumberOfLots; Assert.AreEqual(expectedQuantity, quantity); } private List GetPositionGroupOrders(IPositionGroup positionGroup, decimal initialPositionGroupQuantity, decimal quantity) { var groupOrderManager = new GroupOrderManager(1, positionGroup.Count, quantity); return positionGroup.Positions.Select(position => Order.CreateOrder(new SubmitOrderRequest( OrderType.ComboMarket, position.Symbol.SecurityType, position.Symbol, (position.Quantity / initialPositionGroupQuantity).GetOrderLegGroupQuantity(groupOrderManager), 0, 0, _algorithm.Time, "", groupOrderManager: groupOrderManager))).ToList(); } private IPositionGroup SetUpOptionStrategy(OptionStrategyDefinition optionStrategyDefinition, int initialHoldingsQuantity, int? strike = null, bool updateCashbook = true) { if (initialHoldingsQuantity == 0) { var group = SetUpOptionStrategy(optionStrategyDefinition, 1, updateCashbook: false); foreach (var position in group.Positions) { var security = _algorithm.Securities[position.Symbol]; security.Holdings.SetHoldings(0, 0); } Assert.AreEqual(0, _portfolio.Positions.Groups.Count); return group; } var may172023 = new DateTime(2023, 05, 17); var may192023 = new DateTime(2023, 05, 19); var spyMay19_300Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 300, may192023)); spyMay19_300Call.SetMarketPrice(new Tick { Value = 112m }); var spyMay19_310Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 310, may192023)); spyMay19_310Call.SetMarketPrice(new Tick { Value = 100m }); var spyMay19_320Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 320, may192023)); spyMay19_320Call.SetMarketPrice(new Tick { Value = 92m }); var spyMay19_330Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 330, may192023)); spyMay19_330Call.SetMarketPrice(new Tick { Value = 82m }); var spyMay17_200Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 200, may172023)); spyMay17_200Call.SetMarketPrice(new Tick { Value = 220m }); var spyMay17_400Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 400, may172023)); spyMay17_400Call.SetMarketPrice(new Tick { Value = 28m }); var spyMay17_300Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 300, may172023)); spyMay17_300Call.SetMarketPrice(new Tick { Value = 110m }); var spyMay17_500Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 500, may172023)); spyMay17_500Call.SetMarketPrice(new Tick { Value = 0.04m }); var spyMay19_300Put = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Put, 300, may192023)); spyMay19_300Put.SetMarketPrice(new Tick { Value = 0.02m }); var spyMay19_310Put = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Put, 310, may192023)); spyMay19_310Put.SetMarketPrice(new Tick { Value = 0.03m }); var spyMay19_320Put = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Put, 320, may192023)); spyMay19_320Put.SetMarketPrice(new Tick { Value = 0.05m }); var spyMay17_300Put = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Put, 300, may172023)); spyMay17_300Put.SetMarketPrice(new Tick { Value = 0.01m }); var jun212024 = new DateTime(2024, 06, 21); var spyJun21_534Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 534, jun212024)); spyJun21_534Call.SetMarketPrice(new Tick { Value = 0.01m }); var spyJun21_524Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 524, jun212024)); spyJun21_524Call.SetMarketPrice(new Tick { Value = 2.29m }); var spyJun21_542Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 542, jun212024)); spyJun21_542Call.SetMarketPrice(new Tick { Value = 3.047m }); var spyJun21_546Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 546, jun212024)); spyJun21_546Call.SetMarketPrice(new Tick { Value = 2.53m }); var spyJun21_550Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 550, jun212024)); spyJun21_550Call.SetMarketPrice(new Tick { Value = 0.01m }); var spyJun21_554Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 554, jun212024)); spyJun21_554Call.SetMarketPrice(new Tick { Value = 1e-25m }); var spyJun21_524Put = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Put, 524, jun212024)); spyJun21_524Put.SetMarketPrice(new Tick { Value = 0.827m }); var spyJun21_514Put = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Put, 514, jun212024)); spyJun21_514Put.SetMarketPrice(new Tick { Value = 0.018m }); var spyJun21_542Put = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Put, 542, jun212024)); spyJun21_542Put.SetMarketPrice(new Tick { Value = 2.994m }); var jul192024 = new DateTime(2024, 07, 19); var spyJul19_542Call = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Call, 542, jul192024)); spyJul19_542Call.SetMarketPrice(new Tick { Value = 6.972m }); var spyJul19_542Put = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Put, 542, jul192024)); spyJul19_542Put.SetMarketPrice(new Tick { Value = 6.075m }); var spyJun21_544Put = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Put, 544, jun212024)); spyJun21_544Put.SetMarketPrice(new Tick { Value = 1e-25m }); var spyJun21_548Put = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Put, 548, jun212024)); spyJun21_548Put.SetMarketPrice(new Tick { Value = 0.02m }); var spyJun21_552Put = _algorithm.AddOptionContract(Symbols.CreateOptionSymbol("SPY", OptionRight.Put, 552, jun212024)); spyJun21_552Put.SetMarketPrice(new Tick { Value = 3.484m }); _equity.SetMarketPrice(new Tick { Value = 410m }); _equity.SetLeverage(4); var expectedPositionGroupBPMStrategy = optionStrategyDefinition.Name; if (optionStrategyDefinition.Name == OptionStrategyDefinitions.NakedCall.Name) { var optionContract = spyMay19_300Call; optionContract.Holdings.SetHoldings(optionContract.Price, -initialHoldingsQuantity); } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.NakedPut.Name) { var optionContract = spyMay19_300Put; optionContract.Holdings.SetHoldings(optionContract.Price, -initialHoldingsQuantity); } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.CoveredCall.Name) { _equity.Holdings.SetHoldings(_equity.Price, initialHoldingsQuantity * _callOption.ContractMultiplier); var optionContract = spyMay19_300Call; if (strike.HasValue) { switch (strike.Value) { case 200: optionContract = spyMay17_200Call; break; case 300: optionContract = spyMay17_300Call; break; case 400: optionContract = spyMay17_400Call; break; case 500: optionContract = spyMay17_500Call; break; } } optionContract.Holdings.SetHoldings(optionContract.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ProtectiveCall.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ProtectiveCall.Name) { _equity.Holdings.SetHoldings(_equity.Price, -initialHoldingsQuantity * _callOption.ContractMultiplier); spyMay19_300Call.Holdings.SetHoldings(spyMay19_300Call.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.CoveredCall.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.CoveredPut.Name) { _equity.Holdings.SetHoldings(_equity.Price, -initialHoldingsQuantity * _putOption.ContractMultiplier); spyMay19_300Put.Holdings.SetHoldings(spyMay19_300Put.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ProtectivePut.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ProtectivePut.Name) { _equity.Holdings.SetHoldings(_equity.Price, initialHoldingsQuantity * _putOption.ContractMultiplier); spyMay19_300Put.Holdings.SetHoldings(spyMay19_300Put.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.CoveredPut.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ProtectiveCollar.Name) { _equity.SetMarketPrice(new Tick { Value = 524.62m }); _equity.SetLeverage(2); _equity.Holdings.SetHoldings(_equity.Price, initialHoldingsQuantity * _putOption.ContractMultiplier); spyJun21_534Call.Holdings.SetHoldings(spyJun21_534Call.Price, -initialHoldingsQuantity); spyJun21_514Put.Holdings.SetHoldings(spyJun21_514Put.Price, initialHoldingsQuantity); } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.Conversion.Name) { _equity.SetMarketPrice(new Tick { Value = 524.63m }); _equity.SetLeverage(2); _equity.Holdings.SetHoldings(_equity.Price, initialHoldingsQuantity * _putOption.ContractMultiplier); spyJun21_524Call.Holdings.SetHoldings(spyJun21_524Call.Price, -initialHoldingsQuantity); spyJun21_524Put.Holdings.SetHoldings(spyJun21_524Put.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ReverseConversion.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ReverseConversion.Name) { _equity.SetMarketPrice(new Tick { Value = 524.61m }); _equity.SetLeverage(2); _equity.Holdings.SetHoldings(_equity.Price, -initialHoldingsQuantity * _putOption.ContractMultiplier); spyJun21_524Call.Holdings.SetHoldings(spyJun21_524Call.Price, initialHoldingsQuantity); spyJun21_524Put.Holdings.SetHoldings(spyJun21_524Put.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.Conversion.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.BearCallSpread.Name) { var shortCallOption = spyMay19_300Call; var longCallOption = spyMay19_310Call; shortCallOption.Holdings.SetHoldings(shortCallOption.Price, -initialHoldingsQuantity); longCallOption.Holdings.SetHoldings(longCallOption.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.BullCallSpread.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.BearPutSpread.Name) { var longPutOption = spyMay19_310Put; var shortPutOption = spyMay19_300Put; longPutOption.Holdings.SetHoldings(longPutOption.Price, initialHoldingsQuantity); shortPutOption.Holdings.SetHoldings(shortPutOption.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.BullPutSpread.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.BullCallSpread.Name) { var shortCallOption = spyMay19_310Call; var longCallOption = spyMay19_300Call; longCallOption.Holdings.SetHoldings(longCallOption.Price, initialHoldingsQuantity); shortCallOption.Holdings.SetHoldings(shortCallOption.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.BearCallSpread.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.BullPutSpread.Name) { var longPutOption = spyMay19_300Put; var shortPutOption = spyMay19_310Put; longPutOption.Holdings.SetHoldings(longPutOption.Price, initialHoldingsQuantity); shortPutOption.Holdings.SetHoldings(shortPutOption.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.BearPutSpread.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.Straddle.Name) { spyMay19_300Call.Holdings.SetHoldings(spyMay19_300Call.Price, initialHoldingsQuantity); spyMay19_300Put.Holdings.SetHoldings(spyMay19_300Put.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ShortStraddle.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ShortStraddle.Name) { spyMay19_300Call.Holdings.SetHoldings(spyMay19_300Call.Price, -initialHoldingsQuantity); spyMay19_300Put.Holdings.SetHoldings(spyMay19_300Put.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.Straddle.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.Strangle.Name) { spyMay19_310Call.Holdings.SetHoldings(spyMay19_310Call.Price, initialHoldingsQuantity); spyMay19_300Put.Holdings.SetHoldings(spyMay19_300Put.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ShortStrangle.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ShortStrangle.Name) { spyMay19_310Call.Holdings.SetHoldings(spyMay19_310Call.Price, -initialHoldingsQuantity); spyMay19_300Put.Holdings.SetHoldings(spyMay19_300Put.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.Strangle.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ButterflyCall.Name) { var lowerStrikeCallOption = spyMay19_300Call; var middleStrikeCallOption = spyMay19_310Call; var upperStrikeCallOption = spyMay19_320Call; lowerStrikeCallOption.Holdings.SetHoldings(lowerStrikeCallOption.Price, initialHoldingsQuantity); middleStrikeCallOption.Holdings.SetHoldings(middleStrikeCallOption.Price, -2 * initialHoldingsQuantity); upperStrikeCallOption.Holdings.SetHoldings(upperStrikeCallOption.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ShortButterflyCall.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ShortButterflyCall.Name) { var lowerStrikeCallOption = spyMay19_300Call; var middleStrikeCallOption = spyMay19_310Call; var upperStrikeCallOption = spyMay19_320Call; lowerStrikeCallOption.Holdings.SetHoldings(lowerStrikeCallOption.Price, -initialHoldingsQuantity); middleStrikeCallOption.Holdings.SetHoldings(middleStrikeCallOption.Price, 2 * initialHoldingsQuantity); upperStrikeCallOption.Holdings.SetHoldings(middleStrikeCallOption.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ButterflyCall.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ButterflyPut.Name) { var lowerStrikePutOption = spyMay19_300Put; var middleStrikePutOption = spyMay19_310Put; var upperStrikePutOption = spyMay19_320Put; lowerStrikePutOption.Holdings.SetHoldings(lowerStrikePutOption.Price, initialHoldingsQuantity); middleStrikePutOption.Holdings.SetHoldings(middleStrikePutOption.Price, -2 * initialHoldingsQuantity); upperStrikePutOption.Holdings.SetHoldings(upperStrikePutOption.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ShortButterflyPut.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ShortButterflyPut.Name) { var lowerStrikePutOption = spyMay19_300Put; var middleStrikePutOption = spyMay19_310Put; var upperStrikePutOption = spyMay19_320Put; lowerStrikePutOption.Holdings.SetHoldings(lowerStrikePutOption.Price, -initialHoldingsQuantity); middleStrikePutOption.Holdings.SetHoldings(middleStrikePutOption.Price, 2 * initialHoldingsQuantity); upperStrikePutOption.Holdings.SetHoldings(upperStrikePutOption.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ButterflyPut.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.CallCalendarSpread.Name) { var longCallOption = spyMay19_300Call; var shortCallOption = spyMay17_300Call; longCallOption.Holdings.SetHoldings(longCallOption.Price, initialHoldingsQuantity); shortCallOption.Holdings.SetHoldings(shortCallOption.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ShortCallCalendarSpread.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ShortCallCalendarSpread.Name) { var longCallOption = spyMay19_300Call; var shortCallOption = spyMay17_300Call; longCallOption.Holdings.SetHoldings(longCallOption.Price, -initialHoldingsQuantity); shortCallOption.Holdings.SetHoldings(shortCallOption.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.CallCalendarSpread.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.PutCalendarSpread.Name) { var longPutOption = spyMay19_300Put; var shortPutOption = spyMay17_300Put; longPutOption.Holdings.SetHoldings(longPutOption.Price, initialHoldingsQuantity); shortPutOption.Holdings.SetHoldings(shortPutOption.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ShortPutCalendarSpread.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ShortPutCalendarSpread.Name) { var longPutOption = spyMay19_300Put; var shortPutOption = spyMay17_300Put; longPutOption.Holdings.SetHoldings(longPutOption.Price, -initialHoldingsQuantity); shortPutOption.Holdings.SetHoldings(shortPutOption.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.PutCalendarSpread.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.IronButterfly.Name) { var longPutOption = spyMay19_300Put; var shortPutOption = spyMay19_310Put; var shortCallOption = spyMay19_310Call; var longCallOption = spyMay19_320Call; longPutOption.Holdings.SetHoldings(longPutOption.Price, initialHoldingsQuantity); shortPutOption.Holdings.SetHoldings(shortPutOption.Price, -initialHoldingsQuantity); shortCallOption.Holdings.SetHoldings(shortCallOption.Price, -initialHoldingsQuantity); longCallOption.Holdings.SetHoldings(longCallOption.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ShortIronButterfly.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ShortIronButterfly.Name) { var shortPutOption = spyMay19_300Put; var longPutOption = spyMay19_310Put; var longCallOption = spyMay19_310Call; var shortCallOption = spyMay19_320Call; shortPutOption.Holdings.SetHoldings(shortPutOption.Price, -initialHoldingsQuantity); longPutOption.Holdings.SetHoldings(longPutOption.Price, initialHoldingsQuantity); longCallOption.Holdings.SetHoldings(longCallOption.Price, initialHoldingsQuantity); shortCallOption.Holdings.SetHoldings(shortCallOption.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.IronButterfly.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.IronCondor.Name) { var longPutOption = spyMay19_300Put; var shortPutOption = spyMay19_310Put; var shortCallOption = spyMay19_320Call; var longCallOption = spyMay19_330Call; longPutOption.Holdings.SetHoldings(longPutOption.Price, initialHoldingsQuantity); shortPutOption.Holdings.SetHoldings(shortPutOption.Price, -initialHoldingsQuantity); shortCallOption.Holdings.SetHoldings(shortCallOption.Price, -initialHoldingsQuantity); longCallOption.Holdings.SetHoldings(longCallOption.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ShortIronCondor.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ShortIronCondor.Name) { var shortPutOption = spyMay19_300Put; var longPutOption = spyMay19_310Put; var longCallOption = spyMay19_320Call; var shortCallOption = spyMay19_330Call; shortPutOption.Holdings.SetHoldings(shortPutOption.Price, -initialHoldingsQuantity); longPutOption.Holdings.SetHoldings(longPutOption.Price, initialHoldingsQuantity); longCallOption.Holdings.SetHoldings(longCallOption.Price, initialHoldingsQuantity); shortCallOption.Holdings.SetHoldings(shortCallOption.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.IronCondor.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.BoxSpread.Name) { var longPutOption = spyMay19_320Put; var shortPutOption = spyMay19_300Put; var shortCallOption = spyMay19_320Call; var longCallOption = spyMay19_300Call; longPutOption.Holdings.SetHoldings(longPutOption.Price, initialHoldingsQuantity); shortPutOption.Holdings.SetHoldings(shortPutOption.Price, -initialHoldingsQuantity); shortCallOption.Holdings.SetHoldings(shortCallOption.Price, -initialHoldingsQuantity); longCallOption.Holdings.SetHoldings(longCallOption.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ShortBoxSpread.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ShortBoxSpread.Name) { var longPutOption = spyMay19_300Put; var shortPutOption = spyMay19_320Put; var shortCallOption = spyMay19_300Call; var longCallOption = spyMay19_320Call; longPutOption.Holdings.SetHoldings(longPutOption.Price, initialHoldingsQuantity); shortPutOption.Holdings.SetHoldings(shortPutOption.Price, -initialHoldingsQuantity); shortCallOption.Holdings.SetHoldings(shortCallOption.Price, -initialHoldingsQuantity); longCallOption.Holdings.SetHoldings(longCallOption.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.BoxSpread.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.JellyRoll.Name) { _equity.SetMarketPrice(new Tick { Value = 542m }); var shortCallOption = spyJun21_542Call; var longPutOption = spyJun21_542Put; var longCallOption = spyJul19_542Call; var shortPutOption = spyJul19_542Put; shortCallOption.Holdings.SetHoldings(shortCallOption.Price, -initialHoldingsQuantity); longPutOption.Holdings.SetHoldings(longPutOption.Price, initialHoldingsQuantity); longCallOption.Holdings.SetHoldings(longCallOption.Price, initialHoldingsQuantity); shortPutOption.Holdings.SetHoldings(shortPutOption.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.ShortJellyRoll.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.ShortJellyRoll.Name) { _equity.SetMarketPrice(new Tick { Value = 542m }); var longCallOption = spyJun21_542Call; var shortPutOption = spyJun21_542Put; var shortCallOption = spyJul19_542Call; var longPutOption = spyJul19_542Put; longCallOption.Holdings.SetHoldings(longCallOption.Price, initialHoldingsQuantity); shortPutOption.Holdings.SetHoldings(shortPutOption.Price, -initialHoldingsQuantity); shortCallOption.Holdings.SetHoldings(shortCallOption.Price, -initialHoldingsQuantity); longPutOption.Holdings.SetHoldings(longPutOption.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.JellyRoll.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.BearCallLadder.Name) { _equity.SetMarketPrice(new Tick { Value = 548.392m }); var lowStrikeOption = spyJun21_546Call; var middleStrikeOption = spyJun21_550Call; var highStrikeOption = spyJun21_554Call; lowStrikeOption.Holdings.SetHoldings(lowStrikeOption.Price, -initialHoldingsQuantity); middleStrikeOption.Holdings.SetHoldings(middleStrikeOption.Price, initialHoldingsQuantity); highStrikeOption.Holdings.SetHoldings(highStrikeOption.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.BullCallLadder.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.BearPutLadder.Name) { _equity.SetMarketPrice(new Tick { Value = 548.343m }); var lowStrikeOption = spyJun21_544Put; var middleStrikeOption = spyJun21_548Put; var highStrikeOption = spyJun21_552Put; lowStrikeOption.Holdings.SetHoldings(lowStrikeOption.Price, -initialHoldingsQuantity); middleStrikeOption.Holdings.SetHoldings(middleStrikeOption.Price, -initialHoldingsQuantity); highStrikeOption.Holdings.SetHoldings(highStrikeOption.Price, initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.BullPutLadder.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.BullCallLadder.Name) { _equity.SetMarketPrice(new Tick { Value = 548.392m }); var lowStrikeOption = spyJun21_546Call; var middleStrikeOption = spyJun21_550Call; var highStrikeOption = spyJun21_554Call; lowStrikeOption.Holdings.SetHoldings(lowStrikeOption.Price, initialHoldingsQuantity); middleStrikeOption.Holdings.SetHoldings(middleStrikeOption.Price, -initialHoldingsQuantity); highStrikeOption.Holdings.SetHoldings(highStrikeOption.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.BearCallLadder.Name; } } else if (optionStrategyDefinition.Name == OptionStrategyDefinitions.BullPutLadder.Name) { _equity.SetMarketPrice(new Tick { Value = 548.343m }); var lowStrikeOption = spyJun21_544Put; var middleStrikeOption = spyJun21_548Put; var highStrikeOption = spyJun21_552Put; lowStrikeOption.Holdings.SetHoldings(lowStrikeOption.Price, initialHoldingsQuantity); middleStrikeOption.Holdings.SetHoldings(middleStrikeOption.Price, initialHoldingsQuantity); highStrikeOption.Holdings.SetHoldings(highStrikeOption.Price, -initialHoldingsQuantity); if (initialHoldingsQuantity < 0) { expectedPositionGroupBPMStrategy = OptionStrategyDefinitions.BearPutLadder.Name; } } var positionGroup = _portfolio.Positions.Groups.Single(); Assert.AreEqual(expectedPositionGroupBPMStrategy, positionGroup.BuyingPowerModel.ToString()); if (updateCashbook) { // Update the cashbook after setting up the holdings for the strategy. // We would need to wire too many things up in order to emulate the engine and update the cashbook automatically. foreach (var position in positionGroup) { _portfolio.CashBook.Single().Value.AddAmount(-_portfolio.Securities[position.Symbol].Holdings.HoldingsValue); } } return positionGroup; } } }