Files
quantconnect--lean/Tests/Indicators/IndicatorBasedOptionPriceModelTests.cs
2026-07-13 13:02:50 +08:00

120 lines
5.6 KiB
C#

/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using NUnit.Framework;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using QuantConnect.Securities;
using QuantConnect.Securities.Option;
using QuantConnect.Tests.Common;
using System;
namespace QuantConnect.Tests.Indicators
{
[TestFixture]
public class IndicatorBasedOptionPriceModelTests
{
[TestCase(true, 6.05392693521696, 0.3559978, 0.7560627, 0.0430897, 0.0663327, -1599.430292, 0.0000904)]
[TestCase(false, 5.05414551764534, 0.1427122, 0.957485, 0.0311303, 0.020584, -163.902082, 0.0000057)]
public void WorksWithAndWithoutMirrorContract([Values] bool withMirrorContract, decimal expectedTheoreticalPrice,
decimal expectedIv, decimal expectedDelta, decimal expectedGamma, decimal expectedVega,
decimal expectedTheta, decimal expectedRho)
{
GetTestData(true, true, withMirrorContract, out var option, out var contract, out var securities);
var model = new IndicatorBasedOptionPriceModel(securityProvider: securities);
var result = model.Evaluate(new OptionPriceModelParameters(option, null, contract));
var theoreticalPrice = result.TheoreticalPrice;
var iv = result.ImpliedVolatility;
var greeks = result.Greeks;
Assert.Multiple(() =>
{
Assert.AreEqual(expectedTheoreticalPrice, theoreticalPrice);
Assert.AreEqual(expectedIv, iv);
Assert.AreEqual(expectedDelta, greeks.Delta);
Assert.AreEqual(expectedGamma, greeks.Gamma);
Assert.AreEqual(expectedVega, greeks.Vega);
Assert.AreEqual(expectedTheta, greeks.Theta);
Assert.AreEqual(expectedRho, greeks.Rho);
});
}
[TestCase(false, false)]
[TestCase(true, false)]
[TestCase(false, true)]
public void WontCalculateIfMissindData(bool withUnderlyingData, bool withOptionData)
{
GetTestData(withUnderlyingData, withOptionData, true, out var option, out var contract, out var securities);
var model = new IndicatorBasedOptionPriceModel(securityProvider: securities);
var result = model.Evaluate(new OptionPriceModelParameters(option, null, contract));
Assert.AreEqual(OptionPriceModelResult.None, result);
}
private static void GetTestData(bool withUnderlying, bool withOption, bool withMirrorOption,
out Option option, out OptionContract contract, out SecurityManager securities)
{
var underlyingSymbol = Symbols.GOOG;
var date = new DateTime(2015, 11, 24);
var contractSymbol = Symbols.CreateOptionSymbol(underlyingSymbol.Value, OptionRight.Call, 745m, date);
var tz = TimeZones.NewYork;
var underlyingPrice = 750m;
var underlyingVolume = 10000;
var contractPrice = 5.05m;
var mirrorContractPrice = 1.05m;
var underlying = OptionPriceModelTests.GetEquity(underlyingSymbol, 0m, underlyingVolume, tz);
option = OptionPriceModelTests.GetOption(contractSymbol, underlying, tz);
contract = OptionPriceModelTests.GetOptionContract(contractSymbol, underlyingSymbol, date);
var time = date.Add(new TimeSpan(9, 31, 0));
var timeKeeper = new TimeKeeper(time.ConvertToUtc(tz));
securities = new SecurityManager(timeKeeper);
if (withUnderlying)
{
var underlyingData = new Tick { Symbol = underlying.Symbol, Time = time, Value = underlyingPrice, Quantity = underlyingVolume, TickType = TickType.Trade };
underlying.SetMarketPrice(underlyingData);
securities.Add(underlying);
}
if (withOption)
{
var contractData = new Tick { Symbol = contractSymbol, Time = time, Value = contractPrice, Quantity = 10, TickType = TickType.Trade };
option.SetMarketPrice(contractData);
securities.Add(option);
}
if (withMirrorOption)
{
var mirrorContractSymbol = Symbol.CreateOption(contractSymbol.Underlying,
contractSymbol.ID.Symbol,
contractSymbol.ID.Market,
contractSymbol.ID.OptionStyle,
contractSymbol.ID.OptionRight == OptionRight.Call ? OptionRight.Put : OptionRight.Call,
contractSymbol.ID.StrikePrice,
contractSymbol.ID.Date);
var mirrorContractData = new Tick { Symbol = mirrorContractSymbol, Time = time, Value = mirrorContractPrice, Quantity = 10, TickType = TickType.Trade };
var mirrorOption = OptionPriceModelTests.GetOption(mirrorContractSymbol, underlying, tz);
mirrorOption.SetMarketPrice(mirrorContractData);
securities.Add(mirrorOption);
}
}
}
}