OptionLab is...\n\n... a Python library designed as a research tool for quickly evaluating options \nstrategy ideas. It is intended for a wide range of users, from individuals learning \nabout options trading to developers of quantitative strategies.
\n\nOptionLab calculations can produce a number of useful outputs:
\n\n\nthe profit/loss profile of the strategy on a user-defined target date,
\nthe range of stock prices for which the strategy is profitable,
\nthe Greeks associated with each leg of the strategy,
\nthe resulting debit or credit on the trading account,
\nthe maximum and minimum returns within a specified lower and higher price range \nof the underlying asset,
\nthe expected profit and expected loss, and
\nan estimate of the strategy's probability of profit.
\n
\n\nThe probability of profit (PoP) of the strategy on the user-defined target date \nis calculated analytically by default using the Black-Scholes model. Alternatively, \nthe user can provide an array of terminal underlying asset prices obtained from \nother sources (e.g., the Heston model, a Laplace distribution, or a Machine Learning/Deep Learning model) \nto be used in the calculations instead of the Black-Scholes model. This allows \nOptionLab to function as a calculator that supports a variety of pricing \nmodels.
\n\nAn advanced feature of OptionLab that provides great flexibility in building \ncomplex dynamic strategies is the ability to include previously created positions \nas legs in a new strategy. Popular strategies that can benefit from this feature \ninclude the Wheel and Covered Call strategies.
\n\nOptionLab is not...
\n\n... a platform for direct order execution. This capability has not been and \nprobably will not be implemented.
\n\nBacktesting and trade simulation using Monte Carlo have also not (yet) been \nimplemented in the API.
\n\nThat being said, nothing prevents OptionLab from being integrated into an \noptions quant trader's workflow alongside other tools.
\n\nInstallation
\n\nThe easiest way to install OptionLab is using pip:
\n\npip install optionlab\n
\n\nQuickstart
\n\nOptionLab is designed with ease of use in mind. An options strategy can be \ndefined and evaluated with just a few lines of Python code. The API is streamlined, \nand the learning curve is minimal.
\n\nThe evaluation of a strategy is done by calling the optionlab.engine.run_strategy \nfunction provided by the library. This function receives the input data either \nas a dictionary or an optionlab.models.Inputs object.
\n\nFor example, let's say we wanted to calculate the probability of profit for naked \ncalls on Apple stocks expiring on December 17, 2021. The strategy setup consisted \nof selling 100 175.00 strike calls for 1.15 each on November 22, 2021.
\n\nThe input data for this strategy can be provided in a dictionary as follows:
\n\n\n
input_data = {\n "stock_price": 164.04,\n "start_date": "2021-11-22",\n "target_date": "2021-12-17",\n "volatility": 0.272,\n "interest_rate": 0.0002,\n "min_stock": 120,\n "max_stock": 200,\n "strategy": [\n {\n "type": "call",\n "strike": 175.0,\n "premium": 1.15,\n "n": 100,\n "action":"sell"\n }\n ],\n}\n
\n
\n\nAlternatively, the input data could be defined as the optionlab.models.Inputs \nobject below:
\n\n\n
from optionlab import Inputs\n\ninput_data = Inputs(\n stock_price = 164.04,\n start_date = "2021-11-22",\n target_date = "2021-12-17",\n volatility = 0.272,\n interest_rate = 0.0002,\n min_stock = 120,\n max_stock = 200,\n strategy = [\n {\n "type": "call",\n "strike": 175.0,\n "premium": 1.15,\n "n": 100,\n "action":"sell"\n }\n ],\n)\n
\n
\n\nIn both cases, the strategy itself is a list of dictionaries, where each dictionary\ndefines a leg in the strategy. The fields in a leg, depending on the type of the\nleg, are described in optionlab.models.Stock, optionlab.models.Option, and\noptionlab.models.ClosedPosition.
\n\nAfter defining the input data, we pass it to the run_strategy function as shown \nbelow:
\n\n\n
from optionlab import run_strategy, plot_pl\n\nout = run_strategy(input_data)\n\nprint(out)\n\nplot_pl(out)\n
\n
\n\nThe variable out is an optionlab.models.Outputs object that contains the \nresults from the calculations. By calling print with out as an argument, \nthese results are displayed on screen.
\n\nThe optionlab.plot.plot_pl function, in turn, takes an optionlab.models.Outputs \nobject as its argument and plots the profit/loss diagram for the strategy.
\n\nExamples
\n\nExamples for a number of popular options trading strategies can be found as \nJupyter notebooks in the examples \ndirectory.
\n"}, {"fullname": "optionlab.VERSION", "modulename": "optionlab", "qualname": "VERSION", "kind": "variable", "doc": "\n", "default_value": "'1.4.3'"}, {"fullname": "optionlab.black_scholes", "modulename": "optionlab.black_scholes", "kind": "module", "doc": "This module defines functions that calculate quantities, such as option prices\nand the Greeks, related to the Black-Scholes model.
\n"}, {"fullname": "optionlab.black_scholes.get_bs_info", "modulename": "optionlab.black_scholes", "qualname": "get_bs_info", "kind": "function", "doc": "Provides information about call and put options calculated using the Black-Scholes\nformula.
\n\nParameters
\n\ns: stock price.
\n\nx: strike price(s).
\n\nr: annualized risk-free interest rate.
\n\nvol: annualized volatility.
\n\nyears_to_maturity: time remaining to maturity, in years.
\n\ny: annualized dividend yield.
\n\nReturns
\n\nInformation calculated using the Black-Scholes formula.
\n", "signature": "(\ts: float,\tx: float | numpy.ndarray,\tr: float,\tvol: float,\tyears_to_maturity: float,\ty: float = 0.0) -> optionlab.models.BlackScholesInfo:", "funcdef": "def"}, {"fullname": "optionlab.black_scholes.get_option_price", "modulename": "optionlab.black_scholes", "qualname": "get_option_price", "kind": "function", "doc": "Returns the price of an option.
\n\nParameters
\n\noption_type: either 'call' or 'put'.
\n\ns0: spot price(s) of the underlying asset.
\n\nx: strike price(s).
\n\nr: annualize risk-free interest rate.
\n\nyears_to_maturity: time remaining to maturity, in years.
\n\nd1: d1 in Black-Scholes formula.
\n\nd2: d2 in Black-Scholes formula.
\n\ny: annualized dividend yield.
\n\nReturns
\n\nOption price(s).
\n", "signature": "(\toption_type: Literal['call', 'put'],\ts0: float | numpy.ndarray,\tx: float | numpy.ndarray,\tr: float,\tyears_to_maturity: float,\td1: float | numpy.ndarray,\td2: float | numpy.ndarray,\ty: float = 0.0) -> float | numpy.ndarray:", "funcdef": "def"}, {"fullname": "optionlab.black_scholes.get_delta", "modulename": "optionlab.black_scholes", "qualname": "get_delta", "kind": "function", "doc": "Returns the option's Greek Delta.
\n\nParameters
\n\noption_type: either 'call' or 'put'.
\n\nd1: d1 in Black-Scholes formula.
\n\nyears_to_maturity: time remaining to maturity, in years.
\n\ny: annualized dividend yield.
\n\nReturns
\n\nOption's Greek Delta.
\n", "signature": "(\toption_type: Literal['call', 'put'],\td1: float | numpy.ndarray,\tyears_to_maturity: float,\ty: float = 0.0) -> float | numpy.ndarray:", "funcdef": "def"}, {"fullname": "optionlab.black_scholes.get_gamma", "modulename": "optionlab.black_scholes", "qualname": "get_gamma", "kind": "function", "doc": "Returns the option's Greek Gamma.
\n\nParameters
\n\ns0: spot price of the underlying asset.
\n\nvol: annualized volatitily.
\n\nyears_to_maturity: time remaining to maturity, in years.
\n\nd1: d1 in Black-Scholes formula.
\n\ny: annualized divident yield.
\n\nReturns
\n\nOption's Greek Gamma.
\n", "signature": "(\ts0: float,\tvol: float,\tyears_to_maturity: float,\td1: float | numpy.ndarray,\ty: float = 0.0) -> float | numpy.ndarray:", "funcdef": "def"}, {"fullname": "optionlab.black_scholes.get_theta", "modulename": "optionlab.black_scholes", "qualname": "get_theta", "kind": "function", "doc": "Returns the option's Greek Theta.
\n\nParameters
\n\noption_type: either 'call' or 'put'.
\n\ns0: spot price of the underlying asset.
\n\nx: strike price(s).
\n\nr: annualized risk-free interest rate.
\n\nvol: annualized volatility.
\n\nyears_to_maturity: time remaining to maturity, in years.
\n\nd1: d1 in Black-Scholes formula.
\n\nd2: d2 in Black-Scholes formula.
\n\ny: annualized dividend yield.
\n\nReturns
\n\nOption's Greek Theta.
\n", "signature": "(\toption_type: Literal['call', 'put'],\ts0: float,\tx: float | numpy.ndarray,\tr: float,\tvol: float,\tyears_to_maturity: float,\td1: float | numpy.ndarray,\td2: float | numpy.ndarray,\ty: float = 0.0) -> float | numpy.ndarray:", "funcdef": "def"}, {"fullname": "optionlab.black_scholes.get_vega", "modulename": "optionlab.black_scholes", "qualname": "get_vega", "kind": "function", "doc": "Returns the option's Greek Vega.
\n\nParameters
\n\ns0: spot price of the underlying asset.
\n\nyears_to_maturity: time remaining to maturity, in years.
\n\nd1: d1 in Black-Scholes formula.
\n\ny: annualized dividend yield.
\n\nReturns
\n\nOption's Greek Vega.
\n", "signature": "(\ts0: float,\tyears_to_maturity: float,\td1: float | numpy.ndarray,\ty: float = 0.0) -> float | numpy.ndarray:", "funcdef": "def"}, {"fullname": "optionlab.black_scholes.get_rho", "modulename": "optionlab.black_scholes", "qualname": "get_rho", "kind": "function", "doc": "Returns the option's Greek Rho.
\n\nParameters
\n\noption_type: either 'call' or 'put'.
\n\nx: strike price(s).
\n\nr: annualized risk-free interest rate.
\n\nyears_to_maturity: time remaining to maturity, in years.
\n\nd2: d2 in Black-Scholes formula.
\n\nReturns
\n\nOption's Greek Rho.
\n", "signature": "(\toption_type: Literal['call', 'put'],\tx: float | numpy.ndarray,\tr: float,\tyears_to_maturity: float,\td2: float | numpy.ndarray) -> float | numpy.ndarray:", "funcdef": "def"}, {"fullname": "optionlab.black_scholes.get_d1", "modulename": "optionlab.black_scholes", "qualname": "get_d1", "kind": "function", "doc": "Returns d1 used in Black-Scholes formula.
\n\nParameters
\n\ns0: spot price(s) of the underlying asset.
\n\nx: strike price(s).
\n\nr: annualized risk-free interest rate.
\n\nvol: annualized volatility(ies).
\n\nyears_to_maturity: time remaining to maturity, in years.
\n\ny: annualized divident yield.
\n\nReturns
\n\nd1 in Black-Scholes formula.
\n", "signature": "(\ts0: float | numpy.ndarray,\tx: float | numpy.ndarray,\tr: float,\tvol: float | numpy.ndarray,\tyears_to_maturity: float,\ty: float = 0.0) -> float | numpy.ndarray:", "funcdef": "def"}, {"fullname": "optionlab.black_scholes.get_d2", "modulename": "optionlab.black_scholes", "qualname": "get_d2", "kind": "function", "doc": "Returns d2 used in Black-Scholes formula.
\n\nParameters
\n\ns0: spot price(s) of the underlying asset.
\n\nx: strike price(s).
\n\nr: annualized risk-free interest rate.
\n\nvol: annualized volatility(ies).
\n\nyears_to_maturity: time remaining to maturity, in years.
\n\ny: annualized divident yield.
\n\nReturns
\n\nd2 in Black-Scholes formula.
\n", "signature": "(\ts0: float | numpy.ndarray,\tx: float | numpy.ndarray,\tr: float,\tvol: float | numpy.ndarray,\tyears_to_maturity: float,\ty: float = 0.0) -> float | numpy.ndarray:", "funcdef": "def"}, {"fullname": "optionlab.black_scholes.get_implied_vol", "modulename": "optionlab.black_scholes", "qualname": "get_implied_vol", "kind": "function", "doc": "Returns the implied volatility of an option.
\n\nParameters
\n\noption_type: either 'call' or 'put'.
\n\noprice: market price of an option.
\n\ns0: spot price of the underlying asset.
\n\nx: strike price.
\n\nr: annualized risk-free interest rate.
\n\nyears_to_maturity: time remaining to maturity, in years.
\n\ny: annualized dividend yield.
\n\nReturns
\n\nOption's implied volatility.
\n", "signature": "(\toption_type: Literal['call', 'put'],\toprice: float,\ts0: float,\tx: float,\tr: float,\tyears_to_maturity: float,\ty: float = 0.0) -> float:", "funcdef": "def"}, {"fullname": "optionlab.black_scholes.get_itm_probability", "modulename": "optionlab.black_scholes", "qualname": "get_itm_probability", "kind": "function", "doc": "Returns the probability(ies) that the option(s) will expire in-the-money (ITM).
\n\nParameters
\n\noption_type: either 'call' or 'put'.
\n\nd2: d2 in Black-Scholes formula.
\n\nyears_to_maturity: time remaining to maturity, in years.
\n\ny: annualized dividend yield.
\n\nReturns
\n\nProbability(ies) that the option(s) will expire in-the-money (ITM).
\n", "signature": "(\toption_type: Literal['call', 'put'],\td2: float | numpy.ndarray,\tyears_to_maturity: float,\ty: float = 0.0) -> float | numpy.ndarray:", "funcdef": "def"}, {"fullname": "optionlab.engine", "modulename": "optionlab.engine", "kind": "module", "doc": "This module defines the run_strategy function.
\n\nGiven input data provided as either an optionlab.models.Inputs object or a dictionary,\nrun_strategy returns the results of an options strategy calculation (e.g., the\nprobability of profit on the target date) as an optionlab.models.Outputs object.
\n"}, {"fullname": "optionlab.engine.run_strategy", "modulename": "optionlab.engine", "qualname": "run_strategy", "kind": "function", "doc": "Runs the calculation for a strategy.
\n\nParameters
\n\ninputs_data: input data used in the strategy calculation.
\n\nReturns
\n\nOutput data from the strategy calculation.
\n", "signature": "(inputs_data: optionlab.models.Inputs | dict) -> optionlab.models.Outputs:", "funcdef": "def"}, {"fullname": "optionlab.models", "modulename": "optionlab.models", "kind": "module", "doc": "This module primarily implements Pydantic models that represent inputs and outputs \nof strategy calculations. It also implements constants and custom types.
\n\nFrom the user's point of view, the two most important classes that they will use \nto provide input and subsequently process calculation results are Inputs and \nOutputs, respectively.
\n"}, {"fullname": "optionlab.models.OptionType", "modulename": "optionlab.models", "qualname": "OptionType", "kind": "variable", "doc": "Option type in a strategy leg.
\n", "default_value": "typing.Literal['call', 'put']"}, {"fullname": "optionlab.models.Action", "modulename": "optionlab.models", "qualname": "Action", "kind": "variable", "doc": "Action taken in in a strategy leg.
\n", "default_value": "typing.Literal['buy', 'sell']"}, {"fullname": "optionlab.models.StrategyLegType", "modulename": "optionlab.models", "qualname": "StrategyLegType", "kind": "variable", "doc": "Type of strategy leg.
\n", "default_value": "typing.Union[typing.Literal['stock'], typing.Literal['call', 'put'], typing.Literal['closed']]"}, {"fullname": "optionlab.models.TheoreticalModel", "modulename": "optionlab.models", "qualname": "TheoreticalModel", "kind": "variable", "doc": "Theoretical model used in probability of profit (PoP) calculations.
\n", "default_value": "typing.Literal['black-scholes', 'array']"}, {"fullname": "optionlab.models.Range", "modulename": "optionlab.models", "qualname": "Range", "kind": "variable", "doc": "Range boundaries.
\n", "default_value": "tuple[float, float]"}, {"fullname": "optionlab.models.FloatOrNdarray", "modulename": "optionlab.models", "qualname": "FloatOrNdarray", "kind": "variable", "doc": "Float or numpy array custom type.
\n", "default_value": "float | numpy.ndarray"}, {"fullname": "optionlab.models.Stock", "modulename": "optionlab.models", "qualname": "Stock", "kind": "class", "doc": "Defines the attributes of a stock leg in a strategy.
\n", "bases": "pydantic.main.BaseModel"}, {"fullname": "optionlab.models.Stock.type", "modulename": "optionlab.models", "qualname": "Stock.type", "kind": "variable", "doc": "It must be 'stock'.
\n", "annotation": ": Literal['stock']"}, {"fullname": "optionlab.models.Stock.n", "modulename": "optionlab.models", "qualname": "Stock.n", "kind": "variable", "doc": "Number of shares.
\n", "annotation": ": int"}, {"fullname": "optionlab.models.Stock.action", "modulename": "optionlab.models", "qualname": "Stock.action", "kind": "variable", "doc": "Either 'buy' or 'sell'.
\n", "annotation": ": Literal['buy', 'sell']"}, {"fullname": "optionlab.models.Stock.prev_pos", "modulename": "optionlab.models", "qualname": "Stock.prev_pos", "kind": "variable", "doc": "Stock price effectively paid or received in a previously opened position.
\n\n\nIf positive, the position remains open and the payoff calculation considers\nthis price instead of the current stock price.
\nIf negative, the position is closed and the difference between this price \nand the current price is included in the payoff calculation.
\n
\n\nThe default is None, which means this stock position is not a previously \nopened position.
\n", "annotation": ": Optional[float]"}, {"fullname": "optionlab.models.Stock.model_config", "modulename": "optionlab.models", "qualname": "Stock.model_config", "kind": "variable", "doc": "Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
\n", "annotation": ": ClassVar[pydantic.config.ConfigDict]", "default_value": "{}"}, {"fullname": "optionlab.models.Stock.model_fields", "modulename": "optionlab.models", "qualname": "Stock.model_fields", "kind": "variable", "doc": "Metadata about the fields defined on the model,\nmapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
\n\nThis replaces Model.__fields__ from Pydantic V1.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.FieldInfo]]", "default_value": "{'type': FieldInfo(annotation=Literal['stock'], required=False, default='stock'), 'n': FieldInfo(annotation=int, required=True, metadata=[Gt(gt=0)]), 'action': FieldInfo(annotation=Literal['buy', 'sell'], required=True), 'prev_pos': FieldInfo(annotation=Union[float, NoneType], required=False, default=None)}"}, {"fullname": "optionlab.models.Stock.model_computed_fields", "modulename": "optionlab.models", "qualname": "Stock.model_computed_fields", "kind": "variable", "doc": "A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.ComputedFieldInfo]]", "default_value": "{}"}, {"fullname": "optionlab.models.Option", "modulename": "optionlab.models", "qualname": "Option", "kind": "class", "doc": "Defines the attributes of an option leg in a strategy.
\n", "bases": "pydantic.main.BaseModel"}, {"fullname": "optionlab.models.Option.type", "modulename": "optionlab.models", "qualname": "Option.type", "kind": "variable", "doc": "Either 'call' or 'put'.
\n", "annotation": ": Literal['call', 'put']"}, {"fullname": "optionlab.models.Option.strike", "modulename": "optionlab.models", "qualname": "Option.strike", "kind": "variable", "doc": "Strike price.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Option.premium", "modulename": "optionlab.models", "qualname": "Option.premium", "kind": "variable", "doc": "Option premium.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Option.action", "modulename": "optionlab.models", "qualname": "Option.action", "kind": "variable", "doc": "Either 'buy' or 'sell'.
\n", "annotation": ": Literal['buy', 'sell']"}, {"fullname": "optionlab.models.Option.n", "modulename": "optionlab.models", "qualname": "Option.n", "kind": "variable", "doc": "Number of options.
\n", "annotation": ": int"}, {"fullname": "optionlab.models.Option.prev_pos", "modulename": "optionlab.models", "qualname": "Option.prev_pos", "kind": "variable", "doc": "Premium effectively paid or received in a previously opened position.
\n\n\nIf positive, the position remains open and the payoff calculation considers\nthis price instead of the current price of the option.
\nIf negative, the position is closed and the difference between this price \nand the current price is included in the payoff calculation.
\n
\n\nThe default is None, which means this option position is not a previously \nopened position.
\n", "annotation": ": Optional[float]"}, {"fullname": "optionlab.models.Option.expiration", "modulename": "optionlab.models", "qualname": "Option.expiration", "kind": "variable", "doc": "Expiration date or number of days remaining to expiration.
\n\nThe default is None, which means the expiration is the same as Inputs.target_date \nor Inputs.days_to_target_date.
\n", "annotation": ": datetime.date | int | None"}, {"fullname": "optionlab.models.Option.model_config", "modulename": "optionlab.models", "qualname": "Option.model_config", "kind": "variable", "doc": "Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
\n", "annotation": ": ClassVar[pydantic.config.ConfigDict]", "default_value": "{}"}, {"fullname": "optionlab.models.Option.model_fields", "modulename": "optionlab.models", "qualname": "Option.model_fields", "kind": "variable", "doc": "Metadata about the fields defined on the model,\nmapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
\n\nThis replaces Model.__fields__ from Pydantic V1.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.FieldInfo]]", "default_value": "{'type': FieldInfo(annotation=Literal['call', 'put'], required=True), 'strike': FieldInfo(annotation=float, required=True, metadata=[Gt(gt=0)]), 'premium': FieldInfo(annotation=float, required=True, metadata=[Gt(gt=0)]), 'action': FieldInfo(annotation=Literal['buy', 'sell'], required=True), 'n': FieldInfo(annotation=int, required=True, metadata=[Gt(gt=0)]), 'prev_pos': FieldInfo(annotation=Union[float, NoneType], required=False, default=None), 'expiration': FieldInfo(annotation=Union[date, int, NoneType], required=False, default=None)}"}, {"fullname": "optionlab.models.Option.model_computed_fields", "modulename": "optionlab.models", "qualname": "Option.model_computed_fields", "kind": "variable", "doc": "A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.ComputedFieldInfo]]", "default_value": "{}"}, {"fullname": "optionlab.models.ClosedPosition", "modulename": "optionlab.models", "qualname": "ClosedPosition", "kind": "class", "doc": "Defines the attributes of a previously closed position in a strategy.
\n", "bases": "pydantic.main.BaseModel"}, {"fullname": "optionlab.models.ClosedPosition.type", "modulename": "optionlab.models", "qualname": "ClosedPosition.type", "kind": "variable", "doc": "It must be 'closed'.
\n", "annotation": ": Literal['closed']"}, {"fullname": "optionlab.models.ClosedPosition.prev_pos", "modulename": "optionlab.models", "qualname": "ClosedPosition.prev_pos", "kind": "variable", "doc": "The total amount of the closed position.
\n\n\nIf positive, it resulted in a profit.
\nIf negative, it incurred a loss.
\n
\n\nThis amount will be added to the payoff and taken into account in the strategy \ncalculations.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.ClosedPosition.model_config", "modulename": "optionlab.models", "qualname": "ClosedPosition.model_config", "kind": "variable", "doc": "Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
\n", "annotation": ": ClassVar[pydantic.config.ConfigDict]", "default_value": "{}"}, {"fullname": "optionlab.models.ClosedPosition.model_fields", "modulename": "optionlab.models", "qualname": "ClosedPosition.model_fields", "kind": "variable", "doc": "Metadata about the fields defined on the model,\nmapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
\n\nThis replaces Model.__fields__ from Pydantic V1.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.FieldInfo]]", "default_value": "{'type': FieldInfo(annotation=Literal['closed'], required=False, default='closed'), 'prev_pos': FieldInfo(annotation=float, required=True)}"}, {"fullname": "optionlab.models.ClosedPosition.model_computed_fields", "modulename": "optionlab.models", "qualname": "ClosedPosition.model_computed_fields", "kind": "variable", "doc": "A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.ComputedFieldInfo]]", "default_value": "{}"}, {"fullname": "optionlab.models.StrategyLeg", "modulename": "optionlab.models", "qualname": "StrategyLeg", "kind": "variable", "doc": "Leg in a strategy.
\n", "default_value": "optionlab.models.Stock | optionlab.models.Option | optionlab.models.ClosedPosition"}, {"fullname": "optionlab.models.TheoreticalModelInputs", "modulename": "optionlab.models", "qualname": "TheoreticalModelInputs", "kind": "class", "doc": "Inputs for calculations, such as the probability of profit (PoP).
\n", "bases": "pydantic.main.BaseModel"}, {"fullname": "optionlab.models.TheoreticalModelInputs.stock_price", "modulename": "optionlab.models", "qualname": "TheoreticalModelInputs.stock_price", "kind": "variable", "doc": "Stock price.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.TheoreticalModelInputs.volatility", "modulename": "optionlab.models", "qualname": "TheoreticalModelInputs.volatility", "kind": "variable", "doc": "Annualized volatility of the underlying asset.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.TheoreticalModelInputs.years_to_target_date", "modulename": "optionlab.models", "qualname": "TheoreticalModelInputs.years_to_target_date", "kind": "variable", "doc": "Time remaining until target date, in years.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.TheoreticalModelInputs.model_config", "modulename": "optionlab.models", "qualname": "TheoreticalModelInputs.model_config", "kind": "variable", "doc": "Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
\n", "annotation": ": ClassVar[pydantic.config.ConfigDict]", "default_value": "{}"}, {"fullname": "optionlab.models.TheoreticalModelInputs.model_fields", "modulename": "optionlab.models", "qualname": "TheoreticalModelInputs.model_fields", "kind": "variable", "doc": "Metadata about the fields defined on the model,\nmapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
\n\nThis replaces Model.__fields__ from Pydantic V1.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.FieldInfo]]", "default_value": "{'stock_price': FieldInfo(annotation=float, required=True, metadata=[Gt(gt=0.0)]), 'volatility': FieldInfo(annotation=float, required=True, metadata=[Gt(gt=0.0)]), 'years_to_target_date': FieldInfo(annotation=float, required=True, metadata=[Ge(ge=0.0)])}"}, {"fullname": "optionlab.models.TheoreticalModelInputs.model_computed_fields", "modulename": "optionlab.models", "qualname": "TheoreticalModelInputs.model_computed_fields", "kind": "variable", "doc": "A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.ComputedFieldInfo]]", "default_value": "{}"}, {"fullname": "optionlab.models.BlackScholesModelInputs", "modulename": "optionlab.models", "qualname": "BlackScholesModelInputs", "kind": "class", "doc": "Defines the input data for the calculations using the Black-Scholes model.
\n", "bases": "TheoreticalModelInputs"}, {"fullname": "optionlab.models.BlackScholesModelInputs.model", "modulename": "optionlab.models", "qualname": "BlackScholesModelInputs.model", "kind": "variable", "doc": "It must be 'black-scholes'.
\n", "annotation": ": Literal['black-scholes']"}, {"fullname": "optionlab.models.BlackScholesModelInputs.interest_rate", "modulename": "optionlab.models", "qualname": "BlackScholesModelInputs.interest_rate", "kind": "variable", "doc": "Annualized risk-free interest rate.
\n\nThe default is 0.0.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.BlackScholesModelInputs.dividend_yield", "modulename": "optionlab.models", "qualname": "BlackScholesModelInputs.dividend_yield", "kind": "variable", "doc": "Annualized dividend yield.
\n\nThe default is 0.0.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.BlackScholesModelInputs.model_config", "modulename": "optionlab.models", "qualname": "BlackScholesModelInputs.model_config", "kind": "variable", "doc": "Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
\n", "annotation": ": ClassVar[pydantic.config.ConfigDict]", "default_value": "{}"}, {"fullname": "optionlab.models.BlackScholesModelInputs.model_fields", "modulename": "optionlab.models", "qualname": "BlackScholesModelInputs.model_fields", "kind": "variable", "doc": "Metadata about the fields defined on the model,\nmapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
\n\nThis replaces Model.__fields__ from Pydantic V1.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.FieldInfo]]", "default_value": "{'stock_price': FieldInfo(annotation=float, required=True, metadata=[Gt(gt=0.0)]), 'volatility': FieldInfo(annotation=float, required=True, metadata=[Gt(gt=0.0)]), 'years_to_target_date': FieldInfo(annotation=float, required=True, metadata=[Ge(ge=0.0)]), 'model': FieldInfo(annotation=Literal['black-scholes'], required=False, default='black-scholes'), 'interest_rate': FieldInfo(annotation=float, required=False, default=0.0, metadata=[Ge(ge=0.0)]), 'dividend_yield': FieldInfo(annotation=float, required=False, default=0.0, metadata=[Ge(ge=0.0), Le(le=1.0)])}"}, {"fullname": "optionlab.models.BlackScholesModelInputs.model_computed_fields", "modulename": "optionlab.models", "qualname": "BlackScholesModelInputs.model_computed_fields", "kind": "variable", "doc": "A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.ComputedFieldInfo]]", "default_value": "{}"}, {"fullname": "optionlab.models.LaplaceInputs", "modulename": "optionlab.models", "qualname": "LaplaceInputs", "kind": "class", "doc": "Defines the input data for the calculations using a log-Laplace distribution of\nstock prices.
\n", "bases": "TheoreticalModelInputs"}, {"fullname": "optionlab.models.LaplaceInputs.model", "modulename": "optionlab.models", "qualname": "LaplaceInputs.model", "kind": "variable", "doc": "It must be 'laplace'.
\n", "annotation": ": Literal['laplace']"}, {"fullname": "optionlab.models.LaplaceInputs.mu", "modulename": "optionlab.models", "qualname": "LaplaceInputs.mu", "kind": "variable", "doc": "Annualized return of the underlying asset.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.LaplaceInputs.model_config", "modulename": "optionlab.models", "qualname": "LaplaceInputs.model_config", "kind": "variable", "doc": "Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
\n", "annotation": ": ClassVar[pydantic.config.ConfigDict]", "default_value": "{}"}, {"fullname": "optionlab.models.LaplaceInputs.model_fields", "modulename": "optionlab.models", "qualname": "LaplaceInputs.model_fields", "kind": "variable", "doc": "Metadata about the fields defined on the model,\nmapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
\n\nThis replaces Model.__fields__ from Pydantic V1.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.FieldInfo]]", "default_value": "{'stock_price': FieldInfo(annotation=float, required=True, metadata=[Gt(gt=0.0)]), 'volatility': FieldInfo(annotation=float, required=True, metadata=[Gt(gt=0.0)]), 'years_to_target_date': FieldInfo(annotation=float, required=True, metadata=[Ge(ge=0.0)]), 'model': FieldInfo(annotation=Literal['laplace'], required=False, default='laplace'), 'mu': FieldInfo(annotation=float, required=True)}"}, {"fullname": "optionlab.models.LaplaceInputs.model_computed_fields", "modulename": "optionlab.models", "qualname": "LaplaceInputs.model_computed_fields", "kind": "variable", "doc": "A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.ComputedFieldInfo]]", "default_value": "{}"}, {"fullname": "optionlab.models.ArrayInputs", "modulename": "optionlab.models", "qualname": "ArrayInputs", "kind": "class", "doc": "Defines the input data for the calculations when using an array of strategy\nreturns.
\n", "bases": "pydantic.main.BaseModel"}, {"fullname": "optionlab.models.ArrayInputs.model", "modulename": "optionlab.models", "qualname": "ArrayInputs.model", "kind": "variable", "doc": "It must be 'array'.
\n", "annotation": ": Literal['array']"}, {"fullname": "optionlab.models.ArrayInputs.array", "modulename": "optionlab.models", "qualname": "ArrayInputs.array", "kind": "variable", "doc": "Array of strategy returns.
\n", "annotation": ": numpy.ndarray"}, {"fullname": "optionlab.models.ArrayInputs.model_config", "modulename": "optionlab.models", "qualname": "ArrayInputs.model_config", "kind": "variable", "doc": "Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
\n", "default_value": "{'arbitrary_types_allowed': True}"}, {"fullname": "optionlab.models.ArrayInputs.model_fields", "modulename": "optionlab.models", "qualname": "ArrayInputs.model_fields", "kind": "variable", "doc": "Metadata about the fields defined on the model,\nmapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
\n\nThis replaces Model.__fields__ from Pydantic V1.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.FieldInfo]]", "default_value": "{'model': FieldInfo(annotation=Literal['array'], required=False, default='array'), 'array': FieldInfo(annotation=ndarray, required=True)}"}, {"fullname": "optionlab.models.ArrayInputs.model_computed_fields", "modulename": "optionlab.models", "qualname": "ArrayInputs.model_computed_fields", "kind": "variable", "doc": "A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.ComputedFieldInfo]]", "default_value": "{}"}, {"fullname": "optionlab.models.Inputs", "modulename": "optionlab.models", "qualname": "Inputs", "kind": "class", "doc": "Defines the input data for a strategy calculation.
\n", "bases": "pydantic.main.BaseModel"}, {"fullname": "optionlab.models.Inputs.stock_price", "modulename": "optionlab.models", "qualname": "Inputs.stock_price", "kind": "variable", "doc": "Spot price of the underlying.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Inputs.volatility", "modulename": "optionlab.models", "qualname": "Inputs.volatility", "kind": "variable", "doc": "Annualized volatility.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Inputs.interest_rate", "modulename": "optionlab.models", "qualname": "Inputs.interest_rate", "kind": "variable", "doc": "Annualized risk-free interest rate.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Inputs.min_stock", "modulename": "optionlab.models", "qualname": "Inputs.min_stock", "kind": "variable", "doc": "Minimum value of the stock in the stock price domain.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Inputs.max_stock", "modulename": "optionlab.models", "qualname": "Inputs.max_stock", "kind": "variable", "doc": "Maximum value of the stock in the stock price domain.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Inputs.strategy", "modulename": "optionlab.models", "qualname": "Inputs.strategy", "kind": "variable", "doc": "A list of strategy legs.
\n", "annotation": ": list[optionlab.models.Stock | optionlab.models.Option | optionlab.models.ClosedPosition]"}, {"fullname": "optionlab.models.Inputs.dividend_yield", "modulename": "optionlab.models", "qualname": "Inputs.dividend_yield", "kind": "variable", "doc": "Annualized dividend yield.
\n\nThe default is 0.0.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Inputs.profit_target", "modulename": "optionlab.models", "qualname": "Inputs.profit_target", "kind": "variable", "doc": "Target profit level.
\n\nThe default is None, which means it is not calculated.
\n", "annotation": ": Optional[float]"}, {"fullname": "optionlab.models.Inputs.loss_limit", "modulename": "optionlab.models", "qualname": "Inputs.loss_limit", "kind": "variable", "doc": "Limit loss level.
\n\nThe default is None, which means it is not calculated.
\n", "annotation": ": Optional[float]"}, {"fullname": "optionlab.models.Inputs.opt_commission", "modulename": "optionlab.models", "qualname": "Inputs.opt_commission", "kind": "variable", "doc": "Brokerage commission for options transactions.
\n\nThe default is 0.0.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Inputs.stock_commission", "modulename": "optionlab.models", "qualname": "Inputs.stock_commission", "kind": "variable", "doc": "Brokerage commission for stocks transactions.
\n\nThe default is 0.0.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Inputs.discard_nonbusiness_days", "modulename": "optionlab.models", "qualname": "Inputs.discard_nonbusiness_days", "kind": "variable", "doc": "Discards weekends and holidays when counting the number of days between\ntwo dates.
\n\nThe default is True.
\n", "annotation": ": bool"}, {"fullname": "optionlab.models.Inputs.business_days_in_year", "modulename": "optionlab.models", "qualname": "Inputs.business_days_in_year", "kind": "variable", "doc": "Number of business days in a year.
\n\nThe default is 252.
\n", "annotation": ": int"}, {"fullname": "optionlab.models.Inputs.country", "modulename": "optionlab.models", "qualname": "Inputs.country", "kind": "variable", "doc": "Country whose holidays will be counted if discard_nonbusinessdays is\nset to True.
\n\nThe default is 'US'.
\n", "annotation": ": str"}, {"fullname": "optionlab.models.Inputs.start_date", "modulename": "optionlab.models", "qualname": "Inputs.start_date", "kind": "variable", "doc": "Start date in the calculations.
\n\nIf not provided, days_to_target_date must be provided.
\n", "annotation": ": datetime.date | None"}, {"fullname": "optionlab.models.Inputs.target_date", "modulename": "optionlab.models", "qualname": "Inputs.target_date", "kind": "variable", "doc": "Target date in the calculations.
\n\nIf not provided, days_to_target_date must be provided.
\n", "annotation": ": datetime.date | None"}, {"fullname": "optionlab.models.Inputs.days_to_target_date", "modulename": "optionlab.models", "qualname": "Inputs.days_to_target_date", "kind": "variable", "doc": "Days remaining to the target date.
\n\nIf not provided, start_date and target_date must be provided.
\n", "annotation": ": int"}, {"fullname": "optionlab.models.Inputs.model", "modulename": "optionlab.models", "qualname": "Inputs.model", "kind": "variable", "doc": "Theoretical model used in the calculations of probability of profit.
\n\nIt can be 'black-scholes' or 'array'.
\n", "annotation": ": Literal['black-scholes', 'array']"}, {"fullname": "optionlab.models.Inputs.array", "modulename": "optionlab.models", "qualname": "Inputs.array", "kind": "variable", "doc": "Array of terminal stock prices.
\n\nThe default is an empty array.
\n", "annotation": ": numpy.ndarray"}, {"fullname": "optionlab.models.Inputs.model_config", "modulename": "optionlab.models", "qualname": "Inputs.model_config", "kind": "variable", "doc": "Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
\n", "default_value": "{'arbitrary_types_allowed': True}"}, {"fullname": "optionlab.models.Inputs.model_fields", "modulename": "optionlab.models", "qualname": "Inputs.model_fields", "kind": "variable", "doc": "Metadata about the fields defined on the model,\nmapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
\n\nThis replaces Model.__fields__ from Pydantic V1.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.FieldInfo]]", "default_value": "{'stock_price': FieldInfo(annotation=float, required=True, metadata=[Gt(gt=0.0)]), 'volatility': FieldInfo(annotation=float, required=True, metadata=[Ge(ge=0.0)]), 'interest_rate': FieldInfo(annotation=float, required=True, metadata=[Ge(ge=0.0)]), 'min_stock': FieldInfo(annotation=float, required=True, metadata=[Ge(ge=0.0)]), 'max_stock': FieldInfo(annotation=float, required=True, metadata=[Ge(ge=0.0)]), 'strategy': FieldInfo(annotation=list[Union[Stock, Option, ClosedPosition]], required=True, metadata=[MinLen(min_length=1)]), 'dividend_yield': FieldInfo(annotation=float, required=False, default=0.0, metadata=[Ge(ge=0.0)]), 'profit_target': FieldInfo(annotation=Union[float, NoneType], required=False, default=None), 'loss_limit': FieldInfo(annotation=Union[float, NoneType], required=False, default=None), 'opt_commission': FieldInfo(annotation=float, required=False, default=0.0), 'stock_commission': FieldInfo(annotation=float, required=False, default=0.0), 'discard_nonbusiness_days': FieldInfo(annotation=bool, required=False, default=True), 'business_days_in_year': FieldInfo(annotation=int, required=False, default=252), 'country': FieldInfo(annotation=str, required=False, default='US'), 'start_date': FieldInfo(annotation=Union[date, NoneType], required=False, default=None), 'target_date': FieldInfo(annotation=Union[date, NoneType], required=False, default=None), 'days_to_target_date': FieldInfo(annotation=int, required=False, default=0, metadata=[Ge(ge=0)]), 'model': FieldInfo(annotation=Literal['black-scholes', 'array'], required=False, default='black-scholes'), 'array': FieldInfo(annotation=ndarray, required=False, default_factory=init_empty_array)}"}, {"fullname": "optionlab.models.Inputs.model_computed_fields", "modulename": "optionlab.models", "qualname": "Inputs.model_computed_fields", "kind": "variable", "doc": "A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.ComputedFieldInfo]]", "default_value": "{}"}, {"fullname": "optionlab.models.BlackScholesInfo", "modulename": "optionlab.models", "qualname": "BlackScholesInfo", "kind": "class", "doc": "Defines the data returned by a calculation using the Black-Scholes model.
\n", "bases": "pydantic.main.BaseModel"}, {"fullname": "optionlab.models.BlackScholesInfo.call_price", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.call_price", "kind": "variable", "doc": "Price of a call option.
\n", "annotation": ": float | numpy.ndarray"}, {"fullname": "optionlab.models.BlackScholesInfo.put_price", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.put_price", "kind": "variable", "doc": "Price of a put option.
\n", "annotation": ": float | numpy.ndarray"}, {"fullname": "optionlab.models.BlackScholesInfo.call_delta", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.call_delta", "kind": "variable", "doc": "Delta of a call option.
\n", "annotation": ": float | numpy.ndarray"}, {"fullname": "optionlab.models.BlackScholesInfo.put_delta", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.put_delta", "kind": "variable", "doc": "Delta of a put option.
\n", "annotation": ": float | numpy.ndarray"}, {"fullname": "optionlab.models.BlackScholesInfo.call_theta", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.call_theta", "kind": "variable", "doc": "Theta of a call option.
\n", "annotation": ": float | numpy.ndarray"}, {"fullname": "optionlab.models.BlackScholesInfo.put_theta", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.put_theta", "kind": "variable", "doc": "Theta of a put option.
\n", "annotation": ": float | numpy.ndarray"}, {"fullname": "optionlab.models.BlackScholesInfo.gamma", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.gamma", "kind": "variable", "doc": "Gamma of an option.
\n", "annotation": ": float | numpy.ndarray"}, {"fullname": "optionlab.models.BlackScholesInfo.vega", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.vega", "kind": "variable", "doc": "Vega of an option.
\n", "annotation": ": float | numpy.ndarray"}, {"fullname": "optionlab.models.BlackScholesInfo.call_rho", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.call_rho", "kind": "variable", "doc": "Rho of a call option.
\n", "annotation": ": float | numpy.ndarray"}, {"fullname": "optionlab.models.BlackScholesInfo.put_rho", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.put_rho", "kind": "variable", "doc": "Rho of a put option.
\n", "annotation": ": float | numpy.ndarray"}, {"fullname": "optionlab.models.BlackScholesInfo.call_itm_prob", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.call_itm_prob", "kind": "variable", "doc": "Probability of expiring in-the-money probability of a call option.
\n", "annotation": ": float | numpy.ndarray"}, {"fullname": "optionlab.models.BlackScholesInfo.put_itm_prob", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.put_itm_prob", "kind": "variable", "doc": "Probability of expiring in-the-money of a put option.
\n", "annotation": ": float | numpy.ndarray"}, {"fullname": "optionlab.models.BlackScholesInfo.model_config", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.model_config", "kind": "variable", "doc": "Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
\n", "default_value": "{'arbitrary_types_allowed': True}"}, {"fullname": "optionlab.models.BlackScholesInfo.model_fields", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.model_fields", "kind": "variable", "doc": "Metadata about the fields defined on the model,\nmapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
\n\nThis replaces Model.__fields__ from Pydantic V1.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.FieldInfo]]", "default_value": "{'call_price': FieldInfo(annotation=Union[float, ndarray], required=True), 'put_price': FieldInfo(annotation=Union[float, ndarray], required=True), 'call_delta': FieldInfo(annotation=Union[float, ndarray], required=True), 'put_delta': FieldInfo(annotation=Union[float, ndarray], required=True), 'call_theta': FieldInfo(annotation=Union[float, ndarray], required=True), 'put_theta': FieldInfo(annotation=Union[float, ndarray], required=True), 'gamma': FieldInfo(annotation=Union[float, ndarray], required=True), 'vega': FieldInfo(annotation=Union[float, ndarray], required=True), 'call_rho': FieldInfo(annotation=Union[float, ndarray], required=True), 'put_rho': FieldInfo(annotation=Union[float, ndarray], required=True), 'call_itm_prob': FieldInfo(annotation=Union[float, ndarray], required=True), 'put_itm_prob': FieldInfo(annotation=Union[float, ndarray], required=True)}"}, {"fullname": "optionlab.models.BlackScholesInfo.model_computed_fields", "modulename": "optionlab.models", "qualname": "BlackScholesInfo.model_computed_fields", "kind": "variable", "doc": "A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.ComputedFieldInfo]]", "default_value": "{}"}, {"fullname": "optionlab.models.Outputs", "modulename": "optionlab.models", "qualname": "Outputs", "kind": "class", "doc": "Defines the output data from a strategy calculation.
\n", "bases": "pydantic.main.BaseModel"}, {"fullname": "optionlab.models.Outputs.probability_of_profit", "modulename": "optionlab.models", "qualname": "Outputs.probability_of_profit", "kind": "variable", "doc": "Probability of the strategy yielding at least $0.01.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Outputs.profit_ranges", "modulename": "optionlab.models", "qualname": "Outputs.profit_ranges", "kind": "variable", "doc": "A list of minimum and maximum stock prices defining ranges in which the\nstrategy makes at least $0.01.
\n", "annotation": ": list[tuple[float, float]]"}, {"fullname": "optionlab.models.Outputs.expected_profit", "modulename": "optionlab.models", "qualname": "Outputs.expected_profit", "kind": "variable", "doc": "Expected profit when the strategy is profitable.
\n\nThe default is None.
\n", "annotation": ": Optional[float]"}, {"fullname": "optionlab.models.Outputs.expected_loss", "modulename": "optionlab.models", "qualname": "Outputs.expected_loss", "kind": "variable", "doc": "Expected loss when the strategy is not profitable.
\n\nThe default is None.
\n", "annotation": ": Optional[float]"}, {"fullname": "optionlab.models.Outputs.per_leg_cost", "modulename": "optionlab.models", "qualname": "Outputs.per_leg_cost", "kind": "variable", "doc": "List of leg costs.
\n", "annotation": ": list[float]"}, {"fullname": "optionlab.models.Outputs.strategy_cost", "modulename": "optionlab.models", "qualname": "Outputs.strategy_cost", "kind": "variable", "doc": "Total strategy cost.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Outputs.minimum_return_in_the_domain", "modulename": "optionlab.models", "qualname": "Outputs.minimum_return_in_the_domain", "kind": "variable", "doc": "Minimum return of the strategy within the stock price domain.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Outputs.maximum_return_in_the_domain", "modulename": "optionlab.models", "qualname": "Outputs.maximum_return_in_the_domain", "kind": "variable", "doc": "Maximum return of the strategy within the stock price domain.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Outputs.implied_volatility", "modulename": "optionlab.models", "qualname": "Outputs.implied_volatility", "kind": "variable", "doc": "List of implied volatilities, one per strategy leg.
\n", "annotation": ": list[float]"}, {"fullname": "optionlab.models.Outputs.in_the_money_probability", "modulename": "optionlab.models", "qualname": "Outputs.in_the_money_probability", "kind": "variable", "doc": "List of probabilities of legs expiring in-the-money (ITM).
\n", "annotation": ": list[float]"}, {"fullname": "optionlab.models.Outputs.delta", "modulename": "optionlab.models", "qualname": "Outputs.delta", "kind": "variable", "doc": "List of Delta values, one per strategy leg.
\n", "annotation": ": list[float]"}, {"fullname": "optionlab.models.Outputs.gamma", "modulename": "optionlab.models", "qualname": "Outputs.gamma", "kind": "variable", "doc": "List of Gamma values, one per strategy leg.
\n", "annotation": ": list[float]"}, {"fullname": "optionlab.models.Outputs.theta", "modulename": "optionlab.models", "qualname": "Outputs.theta", "kind": "variable", "doc": "List of Theta values, one per strategy leg.
\n", "annotation": ": list[float]"}, {"fullname": "optionlab.models.Outputs.vega", "modulename": "optionlab.models", "qualname": "Outputs.vega", "kind": "variable", "doc": "List of Vega values, one per strategy leg.
\n", "annotation": ": list[float]"}, {"fullname": "optionlab.models.Outputs.rho", "modulename": "optionlab.models", "qualname": "Outputs.rho", "kind": "variable", "doc": "List of Rho values, one per strategy leg.
\n", "annotation": ": list[float]"}, {"fullname": "optionlab.models.Outputs.probability_of_profit_target", "modulename": "optionlab.models", "qualname": "Outputs.probability_of_profit_target", "kind": "variable", "doc": "Probability of the strategy yielding at least the profit target.
\n\nThe default is 0.0.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Outputs.profit_target_ranges", "modulename": "optionlab.models", "qualname": "Outputs.profit_target_ranges", "kind": "variable", "doc": "List of minimum and maximum stock prices defining ranges in which the\nstrategy makes at least the profit target.
\n\nThe default is [].
\n", "annotation": ": list[tuple[float, float]]"}, {"fullname": "optionlab.models.Outputs.probability_of_loss_limit", "modulename": "optionlab.models", "qualname": "Outputs.probability_of_loss_limit", "kind": "variable", "doc": "Probability of the strategy losing at least the loss limit.
\n\nThe default is 0.0.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.Outputs.loss_limit_ranges", "modulename": "optionlab.models", "qualname": "Outputs.loss_limit_ranges", "kind": "variable", "doc": "List of minimum and maximum stock prices defining ranges where the\nstrategy loses at least the loss limit.
\n\nThe default is [].
\n", "annotation": ": list[tuple[float, float]]"}, {"fullname": "optionlab.models.Outputs.model_config", "modulename": "optionlab.models", "qualname": "Outputs.model_config", "kind": "variable", "doc": "Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
\n", "annotation": ": ClassVar[pydantic.config.ConfigDict]", "default_value": "{}"}, {"fullname": "optionlab.models.Outputs.model_fields", "modulename": "optionlab.models", "qualname": "Outputs.model_fields", "kind": "variable", "doc": "Metadata about the fields defined on the model,\nmapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
\n\nThis replaces Model.__fields__ from Pydantic V1.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.FieldInfo]]", "default_value": "{'probability_of_profit': FieldInfo(annotation=float, required=True), 'profit_ranges': FieldInfo(annotation=list[tuple[float, float]], required=True), 'expected_profit': FieldInfo(annotation=Union[float, NoneType], required=False, default=None), 'expected_loss': FieldInfo(annotation=Union[float, NoneType], required=False, default=None), 'per_leg_cost': FieldInfo(annotation=list[float], required=True), 'strategy_cost': FieldInfo(annotation=float, required=True), 'minimum_return_in_the_domain': FieldInfo(annotation=float, required=True), 'maximum_return_in_the_domain': FieldInfo(annotation=float, required=True), 'implied_volatility': FieldInfo(annotation=list[float], required=True), 'in_the_money_probability': FieldInfo(annotation=list[float], required=True), 'delta': FieldInfo(annotation=list[float], required=True), 'gamma': FieldInfo(annotation=list[float], required=True), 'theta': FieldInfo(annotation=list[float], required=True), 'vega': FieldInfo(annotation=list[float], required=True), 'rho': FieldInfo(annotation=list[float], required=True), 'probability_of_profit_target': FieldInfo(annotation=float, required=False, default=0.0), 'profit_target_ranges': FieldInfo(annotation=list[tuple[float, float]], required=False, default=[]), 'probability_of_loss_limit': FieldInfo(annotation=float, required=False, default=0.0), 'loss_limit_ranges': FieldInfo(annotation=list[tuple[float, float]], required=False, default=[]), 'inputs': FieldInfo(annotation=Inputs, required=True), 'data': FieldInfo(annotation=EngineDataResults, required=True)}"}, {"fullname": "optionlab.models.Outputs.model_computed_fields", "modulename": "optionlab.models", "qualname": "Outputs.model_computed_fields", "kind": "variable", "doc": "A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.ComputedFieldInfo]]", "default_value": "{}"}, {"fullname": "optionlab.models.PoPOutputs", "modulename": "optionlab.models", "qualname": "PoPOutputs", "kind": "class", "doc": "Defines the output data from a probability of profit (PoP) calculation.
\n", "bases": "pydantic.main.BaseModel"}, {"fullname": "optionlab.models.PoPOutputs.probability_of_reaching_target", "modulename": "optionlab.models", "qualname": "PoPOutputs.probability_of_reaching_target", "kind": "variable", "doc": "Probability that the strategy return will be equal or greater than the\ntarget.
\n\nThe default is 0.0.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.PoPOutputs.probability_of_missing_target", "modulename": "optionlab.models", "qualname": "PoPOutputs.probability_of_missing_target", "kind": "variable", "doc": "Probability that the strategy return will be less than the target.
\n\nThe default is 0.0.
\n", "annotation": ": float"}, {"fullname": "optionlab.models.PoPOutputs.reaching_target_range", "modulename": "optionlab.models", "qualname": "PoPOutputs.reaching_target_range", "kind": "variable", "doc": "Range of stock prices where the strategy return is equal or greater than\nthe target.
\n\nThe default is [].
\n", "annotation": ": list[tuple[float, float]]"}, {"fullname": "optionlab.models.PoPOutputs.missing_target_range", "modulename": "optionlab.models", "qualname": "PoPOutputs.missing_target_range", "kind": "variable", "doc": "Range of stock prices where the strategy return is less than the target.
\n\nThe default is [].
\n", "annotation": ": list[tuple[float, float]]"}, {"fullname": "optionlab.models.PoPOutputs.expected_return_above_target", "modulename": "optionlab.models", "qualname": "PoPOutputs.expected_return_above_target", "kind": "variable", "doc": "Expected value of the strategy return when the return is equal or greater\nthan the target.
\n\nThe default is None.
\n", "annotation": ": Optional[float]"}, {"fullname": "optionlab.models.PoPOutputs.expected_return_below_target", "modulename": "optionlab.models", "qualname": "PoPOutputs.expected_return_below_target", "kind": "variable", "doc": "Expected value of the strategy return when the return is less than the\ntarget.
\n\nThe default is None.
\n", "annotation": ": Optional[float]"}, {"fullname": "optionlab.models.PoPOutputs.model_config", "modulename": "optionlab.models", "qualname": "PoPOutputs.model_config", "kind": "variable", "doc": "Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
\n", "annotation": ": ClassVar[pydantic.config.ConfigDict]", "default_value": "{}"}, {"fullname": "optionlab.models.PoPOutputs.model_fields", "modulename": "optionlab.models", "qualname": "PoPOutputs.model_fields", "kind": "variable", "doc": "Metadata about the fields defined on the model,\nmapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
\n\nThis replaces Model.__fields__ from Pydantic V1.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.FieldInfo]]", "default_value": "{'probability_of_reaching_target': FieldInfo(annotation=float, required=False, default=0.0), 'probability_of_missing_target': FieldInfo(annotation=float, required=False, default=0.0), 'reaching_target_range': FieldInfo(annotation=list[tuple[float, float]], required=False, default=[]), 'missing_target_range': FieldInfo(annotation=list[tuple[float, float]], required=False, default=[]), 'expected_return_above_target': FieldInfo(annotation=Union[float, NoneType], required=False, default=None), 'expected_return_below_target': FieldInfo(annotation=Union[float, NoneType], required=False, default=None)}"}, {"fullname": "optionlab.models.PoPOutputs.model_computed_fields", "modulename": "optionlab.models", "qualname": "PoPOutputs.model_computed_fields", "kind": "variable", "doc": "A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
\n", "annotation": ": ClassVar[Dict[str, pydantic.fields.ComputedFieldInfo]]", "default_value": "{}"}, {"fullname": "optionlab.plot", "modulename": "optionlab.plot", "kind": "module", "doc": "This module implements the plot_pl function, which displays the profit/loss diagram \nof an options trading strategy.
\n"}, {"fullname": "optionlab.plot.plot_pl", "modulename": "optionlab.plot", "qualname": "plot_pl", "kind": "function", "doc": "Displays the strategy's profit/loss diagram.
\n\nParameters
\n\noutputs: output data from a strategy calculation with optionlab.engine.run_strategy.
\n\nReturns
\n\nNone.
\n", "signature": "(outputs: optionlab.models.Outputs) -> None:", "funcdef": "def"}, {"fullname": "optionlab.price_array", "modulename": "optionlab.price_array", "kind": "module", "doc": "This module defines the create_price_array function, which calculates terminal \nprices from numerical simulations of multiple stock paths.
\n\nThe terminal price array can later be used to calculate the probability of profit \n(PoP) of a strategy using the optionlab.engine.run_strategy function.
\n"}, {"fullname": "optionlab.price_array.create_price_array", "modulename": "optionlab.price_array", "qualname": "create_price_array", "kind": "function", "doc": "Generates terminal stock prices.
\n\nParameters
\n\ninputs_data: input data used to generate the terminal stock prices.
\n\nn: number of terminal stock prices.
\n\nseed: seed for random number generation.
\n\nReturns
\n\nArray of terminal prices.
\n", "signature": "(\tinputs_data: optionlab.models.BlackScholesModelInputs | optionlab.models.LaplaceInputs | dict,\tn: int = 100000,\tseed: int | None = None) -> numpy.ndarray:", "funcdef": "def"}, {"fullname": "optionlab.support", "modulename": "optionlab.support", "kind": "module", "doc": "This module implements a number of helper functions that are not intended to be \ncalled directly by users, but rather support functionalities within the \noptionlab.engine.run_strategy function.
\n"}, {"fullname": "optionlab.support.get_pl_profile", "modulename": "optionlab.support", "qualname": "get_pl_profile", "kind": "function", "doc": "Returns the profit/loss profile and cost of an options trade at expiration.
\n\nParameters
\n\noption_type: either 'call' or 'put'.
\n\naction: either 'buy' or 'sell'.
\n\nx: strike price.
\n\nval: option price.
\n\nn: number of options.
\n\ns: array of stock prices.
\n\ncommission: brokerage commission.
\n\nReturns
\n\nProfit/loss profile and cost of an option trade at expiration.
\n", "signature": "(\toption_type: Literal['call', 'put'],\taction: Literal['buy', 'sell'],\tx: float,\tval: float,\tn: int,\ts: numpy.ndarray,\tcommission: float = 0.0) -> tuple[numpy.ndarray, float]:", "funcdef": "def"}, {"fullname": "optionlab.support.get_pl_profile_stock", "modulename": "optionlab.support", "qualname": "get_pl_profile_stock", "kind": "function", "doc": "Returns the profit/loss profile and cost of a stock position.
\n\nParameters
\n\ns0: initial stock price.
\n\naction: either 'buy' or 'sell'.
\n\nn: number of shares.
\n\ns: array of stock prices.
\n\ncommission: brokerage commission.
\n\nReturns
\n\nProfit/loss profile and cost of a stock position.
\n", "signature": "(\ts0: float,\taction: Literal['buy', 'sell'],\tn: int,\ts: numpy.ndarray,\tcommission: float = 0.0) -> tuple[numpy.ndarray, float]:", "funcdef": "def"}, {"fullname": "optionlab.support.get_pl_profile_bs", "modulename": "optionlab.support", "qualname": "get_pl_profile_bs", "kind": "function", "doc": "Returns the profit/loss profile and cost of an options trade on a target date\nbefore expiration using the Black-Scholes model for option pricing.
\n\nParameters
\n\noption_type: either 'call' or 'put'.
\n\naction: either 'buy' or 'sell'.
\n\nx: strike price.
\n\nval: initial option price.
\n\nr: annualized risk-free interest rate.
\n\ntarget_to_maturity_years: time remaining to maturity from the target date,\nin years.
\n\nvolatility: annualized volatility of the underlying asset.
\n\nn: number of options.
\n\ns: array of stock prices.
\n\ny: annualized dividend yield.
\n\ncommission: brokerage commission.
\n\nReturns
\n\nProfit/loss profile and cost of an option trade before expiration.
\n", "signature": "(\toption_type: Literal['call', 'put'],\taction: Literal['buy', 'sell'],\tx: float,\tval: float,\tr: float,\ttarget_to_maturity_years: float,\tvolatility: float,\tn: int,\ts: numpy.ndarray,\ty: float = 0.0,\tcommission: float = 0.0) -> tuple[float | numpy.ndarray, float]:", "funcdef": "def"}, {"fullname": "optionlab.support.create_price_seq", "modulename": "optionlab.support", "qualname": "create_price_seq", "kind": "function", "doc": "Generates a sequence of stock prices from a minimum to a maximum price with\nincrement $0.01.
\n\nParameters
\n\nmin_price: minimum stock price in the range.
\n\nmax_price: maximum stock price in the range.
\n\nReturns
\n\nArray of sequential stock prices.
\n", "signature": "(min_price: float, max_price: float) -> numpy.ndarray:", "funcdef": "def"}, {"fullname": "optionlab.support.get_pop", "modulename": "optionlab.support", "qualname": "get_pop", "kind": "function", "doc": "Estimates the probability of profit (PoP) of an options trading strategy.
\n\nParameters
\n\ns: array of stock prices.
\n\nprofit: array of profits and losses.
\n\ninputs_data: input data used to estimate the probability of profit.
\n\ntarget: target return.
\n\nReturns
\n\nOutputs of a probability of profit (PoP) calculation.
\n", "signature": "(\ts: numpy.ndarray,\tprofit: numpy.ndarray,\tinputs_data: optionlab.models.BlackScholesModelInputs | optionlab.models.ArrayInputs,\ttarget: float = 0.01) -> optionlab.models.PoPOutputs:", "funcdef": "def"}, {"fullname": "optionlab.utils", "modulename": "optionlab.utils", "kind": "module", "doc": "This module defines utility functions.
\n"}, {"fullname": "optionlab.utils.get_nonbusiness_days", "modulename": "optionlab.utils", "qualname": "get_nonbusiness_days", "kind": "function", "doc": "Returns the number of non-business days (i.e., weekends and holidays) between\nthe start and end date.
\n\nParameters
\n\nstart_date: start date.
\n\nend_date: end date.
\n\ncountry: country of the stock exchange.
\n\nReturns
\n\nNumber of weekends and holidays between the start and end date.
\n", "signature": "(\tstart_date: datetime.date,\tend_date: datetime.date,\tcountry: str = 'US') -> int:", "funcdef": "def"}, {"fullname": "optionlab.utils.get_pl", "modulename": "optionlab.utils", "qualname": "get_pl", "kind": "function", "doc": "Returns the stock prices and the corresponding profit/loss profile of either\na leg or the whole strategy.
\n\nParameters
\n\noutputs: output data from a strategy calculation.
\n\nleg: index of a strategy leg. The default is None, which means the whole\nstrategy.
\n\nReturns
\n\nArray of stock prices and array or profits/losses.
\n", "signature": "(\toutputs: optionlab.models.Outputs,\tleg: int | None = None) -> tuple[numpy.ndarray, numpy.ndarray]:", "funcdef": "def"}, {"fullname": "optionlab.utils.pl_to_csv", "modulename": "optionlab.utils", "qualname": "pl_to_csv", "kind": "function", "doc": "Saves the stock prices and corresponding profit/loss profile of either a leg\nor the whole strategy to a CSV file.
\n\nParameters
\n\noutputs: output data from a strategy calculation.
\n\nfilename: name of the CSV file.
\n\nleg: index of a strategy leg. The default is None, which means the whole\nstrategy.
\n\nReturns
\n\nNone.
\n", "signature": "(\toutputs: optionlab.models.Outputs,\tfilename: str = 'pl.csv',\tleg: int | None = None) -> None:", "funcdef": "def"}];
+
+ // mirrored in build-search-index.js (part 1)
+ // Also split on html tags. this is a cheap heuristic, but good enough.
+ elasticlunr.tokenizer.setSeperator(/[\s\-.;&_'"=,()]+|<[^>]*>/);
+
+ let searchIndex;
+ if (docs._isPrebuiltIndex) {
+ console.info("using precompiled search index");
+ searchIndex = elasticlunr.Index.load(docs);
+ } else {
+ console.time("building search index");
+ // mirrored in build-search-index.js (part 2)
+ searchIndex = elasticlunr(function () {
+ this.pipeline.remove(elasticlunr.stemmer);
+ this.pipeline.remove(elasticlunr.stopWordFilter);
+ this.addField("qualname");
+ this.addField("fullname");
+ this.addField("annotation");
+ this.addField("default_value");
+ this.addField("signature");
+ this.addField("bases");
+ this.addField("doc");
+ this.setRef("fullname");
+ });
+ for (let doc of docs) {
+ searchIndex.addDoc(doc);
+ }
+ console.timeEnd("building search index");
+ }
+
+ return (term) => searchIndex.search(term, {
+ fields: {
+ qualname: {boost: 4},
+ fullname: {boost: 2},
+ annotation: {boost: 2},
+ default_value: {boost: 2},
+ signature: {boost: 2},
+ bases: {boost: 2},
+ doc: {boost: 1},
+ },
+ expand: true
+ });
+})();
\ No newline at end of file
diff --git a/examples/black_scholes_calculator.ipynb b/examples/black_scholes_calculator.ipynb
index e3eaa4f..23a46d7 100644
--- a/examples/black_scholes_calculator.ipynb
+++ b/examples/black_scholes_calculator.ipynb
@@ -43,7 +43,7 @@
"output_type": "stream",
"text": [
"Python version: 3.11.9 | packaged by Anaconda, Inc. | (main, Apr 19 2024, 16:40:41) [MSC v.1916 64 bit (AMD64)]\n",
- "OptionLab version: 1.4.2\n"
+ "OptionLab version: 1.4.3\n"
]
}
],
@@ -106,7 +106,7 @@
"output_type": "stream",
"text": [
"CPU times: total: 0 ns\n",
- "Wall time: 0 ns\n"
+ "Wall time: 4 ms\n"
]
}
],
diff --git a/examples/calendar_spread.ipynb b/examples/calendar_spread.ipynb
index 9def504..61f4d24 100644
--- a/examples/calendar_spread.ipynb
+++ b/examples/calendar_spread.ipynb
@@ -47,7 +47,7 @@
"output_type": "stream",
"text": [
"Python version: 3.11.9 | packaged by Anaconda, Inc. | (main, Apr 19 2024, 16:40:41) [MSC v.1916 64 bit (AMD64)]\n",
- "OptionLab version: 1.4.2\n"
+ "OptionLab version: 1.4.3\n"
]
}
],
@@ -119,8 +119,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "CPU times: total: 406 ms\n",
- "Wall time: 492 ms\n"
+ "CPU times: total: 375 ms\n",
+ "Wall time: 485 ms\n"
]
}
],
diff --git a/examples/call_spread.ipynb b/examples/call_spread.ipynb
index 53478e0..444aad2 100644
--- a/examples/call_spread.ipynb
+++ b/examples/call_spread.ipynb
@@ -164,8 +164,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "CPU times: total: 29.4 s\n",
- "Wall time: 30.4 s\n"
+ "CPU times: total: 39.8 s\n",
+ "Wall time: 42.4 s\n"
]
}
],
@@ -269,7 +269,7 @@
{
"data": {
"text/plain": [
- "[]"
+ "[]"
]
},
"execution_count": 9,
@@ -383,8 +383,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "CPU times: total: 29.6 s\n",
- "Wall time: 30.9 s\n"
+ "CPU times: total: 39.5 s\n",
+ "Wall time: 42.3 s\n"
]
}
],
@@ -488,7 +488,7 @@
{
"data": {
"text/plain": [
- "[]"
+ "[]"
]
},
"execution_count": 15,
diff --git a/examples/covered_call.ipynb b/examples/covered_call.ipynb
index 7070cce..cdb97de 100644
--- a/examples/covered_call.ipynb
+++ b/examples/covered_call.ipynb
@@ -54,7 +54,7 @@
"output_type": "stream",
"text": [
"Python version: 3.11.9 | packaged by Anaconda, Inc. | (main, Apr 19 2024, 16:40:41) [MSC v.1916 64 bit (AMD64)]\n",
- "OptionLab version: 1.4.2\n"
+ "OptionLab version: 1.4.3\n"
]
}
],
@@ -119,8 +119,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "CPU times: total: 203 ms\n",
- "Wall time: 205 ms\n"
+ "CPU times: total: 281 ms\n",
+ "Wall time: 258 ms\n"
]
}
],
@@ -142,7 +142,7 @@
{
"data": {
"text/plain": [
- ""
+ ""
]
},
"execution_count": 5,
diff --git a/examples/naked_call.ipynb b/examples/naked_call.ipynb
index c49af50..56ab09c 100644
--- a/examples/naked_call.ipynb
+++ b/examples/naked_call.ipynb
@@ -46,7 +46,7 @@
"output_type": "stream",
"text": [
"Python version: 3.11.9 | packaged by Anaconda, Inc. | (main, Apr 19 2024, 16:40:41) [MSC v.1916 64 bit (AMD64)]\n",
- "OptionLab version: 1.4.2\n"
+ "OptionLab version: 1.4.3\n"
]
}
],
@@ -116,8 +116,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "CPU times: total: 141 ms\n",
- "Wall time: 125 ms\n"
+ "CPU times: total: 328 ms\n",
+ "Wall time: 338 ms\n"
]
}
],
diff --git a/optionlab.png b/optionlab.png
new file mode 100644
index 0000000..bea8eff
Binary files /dev/null and b/optionlab.png differ
diff --git a/optionlab/__init__.py b/optionlab/__init__.py
index d680080..2ace2d7 100644
--- a/optionlab/__init__.py
+++ b/optionlab/__init__.py
@@ -1,61 +1,209 @@
-import typing
-
-
-VERSION = "1.4.2"
-
-
-if typing.TYPE_CHECKING:
- # import of virtually everything is supported via `__getattr__` below,
- # but we need them here for type checking and IDE support
- from .models import (
- Inputs,
- OptionType,
- Option,
- Outputs,
- ClosedPosition,
- ArrayInputs,
- TheoreticalModelInputs,
- BlackScholesModelInputs,
- LaplaceInputs,
- BlackScholesInfo,
- TheoreticalModel,
- FloatOrNdarray,
- StrategyLeg,
- StrategyType,
- Stock,
- Action,
- )
- from .black_scholes import (
- get_itm_probability,
- get_implied_vol,
- get_option_price,
- get_d1,
- get_d2,
- get_bs_info,
- get_vega,
- get_delta,
- get_gamma,
- get_theta,
- get_rho,
- )
- from .engine import run_strategy
- from .plot import plot_pl
- from .price_array import create_price_array
- from .support import (
- get_pl_profile,
- get_pl_profile_stock,
- get_pl_profile_bs,
- create_price_seq,
- get_pop,
- )
- from .utils import (
- get_nonbusiness_days,
- get_pl,
- pl_to_csv,
- )
+"""
+## OptionLab is...
+... a Python library designed as a research tool for quickly evaluating options
+strategy ideas. It is intended for a wide range of users, from individuals learning
+about options trading to developers of quantitative strategies.
+
+**OptionLab** calculations can produce a number of useful outputs:
+
+- the profit/loss profile of the strategy on a user-defined target date,
+
+- the range of stock prices for which the strategy is profitable,
+
+- the Greeks associated with each leg of the strategy,
+
+- the resulting debit or credit on the trading account,
+
+- the maximum and minimum returns within a specified lower and higher price range
+of the underlying asset,
+
+- the expected profit and expected loss, and
+
+- an estimate of the strategy's probability of profit.
+
+The probability of profit (PoP) of the strategy on the user-defined target date
+is calculated analytically by default using the Black-Scholes model. Alternatively,
+the user can provide an array of terminal underlying asset prices obtained from
+other sources (e.g., the Heston model, a Laplace distribution, or a Machine Learning/Deep Learning model)
+to be used in the calculations instead of the Black-Scholes model. This allows
+**OptionLab** to function as a calculator that supports a variety of pricing
+models.
+
+An advanced feature of **OptionLab** that provides great flexibility in building
+complex dynamic strategies is the ability to include previously created positions
+as legs in a new strategy. Popular strategies that can benefit from this feature
+include the Wheel and Covered Call strategies.
+
+## OptionLab is not...
+
+... a platform for direct order execution. This capability has not been and
+probably will not be implemented.
+
+Backtesting and trade simulation using Monte Carlo have also not (yet) been
+implemented in the API.
+
+That being said, nothing prevents **OptionLab** from being integrated into an
+options quant trader's workflow alongside other tools.
+
+## Installation
+
+The easiest way to install **OptionLab** is using **pip**:
+
+```
+pip install optionlab
+```
+
+## Quickstart
+
+**OptionLab** is designed with ease of use in mind. An options strategy can be
+defined and evaluated with just a few lines of Python code. The API is streamlined,
+and the learning curve is minimal.
+
+The evaluation of a strategy is done by calling the `optionlab.engine.run_strategy`
+function provided by the library. This function receives the input data either
+as a dictionary or an `optionlab.models.Inputs` object.
+
+For example, let's say we wanted to calculate the probability of profit for naked
+calls on Apple stocks expiring on December 17, 2021. The strategy setup consisted
+of selling 100 175.00 strike calls for 1.15 each on November 22, 2021.
+
+The input data for this strategy can be provided in a dictionary as follows:
+
+```python
+input_data = {
+ "stock_price": 164.04,
+ "start_date": "2021-11-22",
+ "target_date": "2021-12-17",
+ "volatility": 0.272,
+ "interest_rate": 0.0002,
+ "min_stock": 120,
+ "max_stock": 200,
+ "strategy": [
+ {
+ "type": "call",
+ "strike": 175.0,
+ "premium": 1.15,
+ "n": 100,
+ "action":"sell"
+ }
+ ],
+}
+```
+
+Alternatively, the input data could be defined as the `optionlab.models.Inputs`
+object below:
+
+```python
+from optionlab import Inputs
+
+input_data = Inputs(
+ stock_price = 164.04,
+ start_date = "2021-11-22",
+ target_date = "2021-12-17",
+ volatility = 0.272,
+ interest_rate = 0.0002,
+ min_stock = 120,
+ max_stock = 200,
+ strategy = [
+ {
+ "type": "call",
+ "strike": 175.0,
+ "premium": 1.15,
+ "n": 100,
+ "action":"sell"
+ }
+ ],
+)
+```
+
+In both cases, the strategy itself is a list of dictionaries, where each dictionary
+defines a leg in the strategy. The fields in a leg, depending on the type of the
+leg, are described in `optionlab.models.Stock`, `optionlab.models.Option`, and
+`optionlab.models.ClosedPosition`.
+
+After defining the input data, we pass it to the `run_strategy` function as shown
+below:
+
+```python
+from optionlab import run_strategy, plot_pl
+
+out = run_strategy(input_data)
+
+print(out)
+
+plot_pl(out)
+```
+
+The variable `out` is an `optionlab.models.Outputs` object that contains the
+results from the calculations. By calling `print` with `out` as an argument,
+these results are displayed on screen.
+
+The `optionlab.plot.plot_pl` function, in turn, takes an `optionlab.models.Outputs`
+object as its argument and plots the profit/loss diagram for the strategy.
+
+## Examples
+
+Examples for a number of popular options trading strategies can be found as
+Jupyter notebooks in the [examples](https://github.com/rgaveiga/optionlab/tree/main/examples)
+directory.
+"""
+
+from .models import (
+ Inputs,
+ OptionType,
+ Option,
+ Outputs,
+ ClosedPosition,
+ ArrayInputs,
+ TheoreticalModelInputs,
+ BlackScholesModelInputs,
+ LaplaceInputs,
+ BlackScholesInfo,
+ TheoreticalModel,
+ FloatOrNdarray,
+ StrategyLeg,
+ StrategyLegType,
+ Stock,
+ Action,
+)
+from .black_scholes import (
+ get_itm_probability,
+ get_implied_vol,
+ get_option_price,
+ get_d1,
+ get_d2,
+ get_bs_info,
+ get_vega,
+ get_delta,
+ get_gamma,
+ get_theta,
+ get_rho,
+)
+from .engine import run_strategy
+from .plot import plot_pl
+from .price_array import create_price_array
+from .support import (
+ get_pl_profile,
+ get_pl_profile_stock,
+ get_pl_profile_bs,
+ create_price_seq,
+ get_pop,
+)
+from .utils import (
+ get_nonbusiness_days,
+ get_pl,
+ pl_to_csv,
+)
+
+
+VERSION = "1.4.3"
+
+__docformat__ = "markdown"
__version__ = VERSION
-__all__ = (
+
+
+ALL = (
# models
"Inputs",
"OptionType",
@@ -70,7 +218,7 @@
"TheoreticalModel",
"FloatOrNdarray",
"StrategyLeg",
- "StrategyType",
+ "StrategyLegType",
"Stock",
"Action",
# engine
@@ -102,70 +250,8 @@
"get_pl",
"pl_to_csv",
)
-
-# A mapping of {: (package, )} defining dynamic imports
-_dynamic_imports: "dict[str, tuple[str, str]]" = {
- # models
- "Inputs": (__package__, ".models"),
- "Outputs": (__package__, ".models"),
- "OptionType": (__package__, ".models"),
- "Option": (__package__, ".models"),
- "ClosedPosition": (__package__, ".models"),
- "ArrayInputs": (__package__, ".models"),
- "TheoreticalModelInputs": (__package__, ".models"),
- "BlackScholesModelInputs": (__package__, ".models"),
- "LaplaceInputs": (__package__, ".models"),
- "BlackScholesInfo": (__package__, ".models"),
- "TheoreticalModel": (__package__, ".models"),
- "FloatOrNdarray": (__package__, ".models"),
- "StrategyLeg": (__package__, ".models"),
- "StrategyType": (__package__, ".models"),
- "Stock": (__package__, ".models"),
- "Action": (__package__, ".models"),
- # engine
- "run_strategy": (__package__, ".engine"),
- # support
- "get_pl_profile": (__package__, ".support"),
- "get_pl_profile_stock": (__package__, ".support"),
- "get_pl_profile_bs": (__package__, ".support"),
- "create_price_seq": (__package__, ".support"),
- "get_pop": (__package__, ".support"),
- # black_scholes
- "get_d1": (__package__, ".black_scholes"),
- "get_d2": (__package__, ".black_scholes"),
- "get_option_price": (__package__, ".black_scholes"),
- "get_itm_probability": (__package__, ".black_scholes"),
- "get_implied_vol": (__package__, ".black_scholes"),
- "get_bs_info": (__package__, ".black_scholes"),
- "get_vega": (__package__, ".black_scholes"),
- "get_delta": (__package__, ".black_scholes"),
- "get_gamma": (__package__, ".black_scholes"),
- "get_theta": (__package__, ".black_scholes"),
- "get_rho": (__package__, ".black_scholes"),
- # plot
- "plot_pl": (__package__, ".plot"),
- # price_array
- "create_price_array": (__package__, ".price_array"),
- # utils
- "get_nonbusiness_days": (__package__, ".utils"),
- "get_pl": (__package__, ".utils"),
- "pl_to_csv": (__package__, ".utils"),
-}
-
-
-def __getattr__(attr_name: str) -> object:
- dynamic_attr = _dynamic_imports[attr_name]
-
- package, module_name = dynamic_attr
-
- from importlib import import_module
-
- if module_name == "__module__":
- return import_module(f".{attr_name}", package=package)
- else:
- module = import_module(module_name, package=package)
- return getattr(module, attr_name)
+"""@private"""
def __dir__() -> "list[str]":
- return list(__all__)
+ return list(ALL)
diff --git a/optionlab/black_scholes.py b/optionlab/black_scholes.py
index 3c9c394..5a12d6d 100644
--- a/optionlab/black_scholes.py
+++ b/optionlab/black_scholes.py
@@ -1,3 +1,8 @@
+"""
+This module defines functions that calculate quantities, such as option prices
+and the Greeks, related to the Black-Scholes model.
+"""
+
from __future__ import division
from scipy import stats
@@ -21,24 +26,21 @@ def get_bs_info(
Parameters
----------
- s : float
- Stock price.
- x : float | numpy.ndarray
- Strike price(s).
- r : float
- Annualized risk-free interest rate.
- vol : float
- Annualized volatility.
- years_to_maturity : float
- Time remaining to maturity, in years.
- y : float, optional
- Annualized dividend yield. The default is 0.0.
+ `s`: stock price.
+
+ `x`: strike price(s).
+
+ `r`: annualized risk-free interest rate.
+
+ `vol`: annualized volatility.
+
+ `years_to_maturity`: time remaining to maturity, in years.
+
+ `y`: annualized dividend yield.
Returns
-------
- BlackScholesInfo
- Information calculated using the Black-Scholes formula. See the documentation
- for `BlackScholesInfo`.
+ Information calculated using the Black-Scholes formula.
"""
d1 = get_d1(s, x, r, vol, years_to_maturity, y)
@@ -87,27 +89,25 @@ def get_option_price(
Parameters
----------
- option_type : str
- `OptionType` literal value, which must be either **call** or **put**.
- s0 : float | numpy.ndarray
- Spot price(s) of the underlying asset.
- x : float | numpy.ndarray
- Strike price(s).
- r : float
- Annualize risk-free interest rate.
- years_to_maturity : float
- Time remaining to maturity, in years.
- d1 : float | numpy.ndarray
- `d1` in Black-Scholes formula.
- d2 : float | numpy.ndarray
- `d2` in Black-Scholes formula.
- y : float, optional
- Annualized dividend yield. The default is 0.0.
+ `option_type`: either *'call'* or *'put'*.
+
+ `s0`: spot price(s) of the underlying asset.
+
+ `x`: strike price(s).
+
+ `r`: annualize risk-free interest rate.
+
+ `years_to_maturity`: time remaining to maturity, in years.
+
+ `d1`: `d1` in Black-Scholes formula.
+
+ `d2`: `d2` in Black-Scholes formula.
+
+ `y`: annualized dividend yield.
Returns
-------
- float | numpy.ndarray
- Option price(s).
+ Option price(s).
"""
s = s0 * exp(-y * years_to_maturity)
@@ -139,19 +139,17 @@ def get_delta(
Parameters
----------
- option_type : str
- `OptionType` literal value, which must be either **call** or **put**.
- d1 : float | numpy.ndarray
- `d1` in Black-Scholes formula.
- years_to_maturity : float
- Time remaining to maturity, in years.
- y : float, optional
- Annualized dividend yield. The default is 0.0.
+ `option_type`: either *'call'* or *'put'*.
+
+ `d1`: `d1` in Black-Scholes formula.
+
+ `years_to_maturity`: time remaining to maturity, in years.
+
+ `y`: annualized dividend yield.
Returns
-------
- float | numpy.ndarray
- Option's Greek Delta.
+ Option's Greek Delta.
"""
yfac = exp(-y * years_to_maturity)
@@ -176,21 +174,19 @@ def get_gamma(
Parameters
----------
- s0 : float
- Spot price of the underlying asset.
- vol : float
- Annualized volatitily.
- years_to_maturity : float
- Time remaining to maturity, in years.
- d1 : float | numpy.ndarray
- `d1` in Black-Scholes formula.
- y : float, optional
- Annualized divident yield. The default is 0.0.
+ `s0`: spot price of the underlying asset.
+
+ `vol`: annualized volatitily.
+
+ `years_to_maturity`: time remaining to maturity, in years.
+
+ `d1`: `d1` in Black-Scholes formula.
+
+ `y`: annualized divident yield.
Returns
-------
- float | numpy.ndarray
- Option's Greek Gamma.
+ Option's Greek Gamma.
"""
yfac = exp(-y * years_to_maturity)
@@ -216,29 +212,27 @@ def get_theta(
Parameters
----------
- option_type : str
- `OptionType` literal value, which must be either **call** or **put**.
- s0 : float
- Spot price of the underlying asset.
- x : float | numpy.ndarray
- Strike price(s).
- r : float
- Annualized risk-free interest rate.
- vol : float
- Annualized volatility.
- years_to_maturity : float
- Time remaining to maturity, in years.
- d1 : float | numpy.ndarray
- `d1` in Black-Scholes formula.
- d2 : float | numpy.ndarray
- `d2` in Black-Scholes formula.
- y : float, optional
- Annualized dividend yield. The default is 0.0.
+ `option_type`: either *'call'* or *'put'*.
+
+ `s0`: spot price of the underlying asset.
+
+ `x`: strike price(s).
+
+ `r`: annualized risk-free interest rate.
+
+ `vol`: annualized volatility.
+
+ `years_to_maturity`: time remaining to maturity, in years.
+
+ `d1`: `d1` in Black-Scholes formula.
+
+ `d2`: `d2` in Black-Scholes formula.
+
+ `y`: annualized dividend yield.
Returns
-------
- float | numpy.ndarray
- Option's Greek Theta.
+ Option's Greek Theta.
"""
s = s0 * exp(-y * years_to_maturity)
@@ -272,19 +266,17 @@ def get_vega(
Parameters
----------
- s0 : float
- Spot price of the underlying asset.
- years_to_maturity : float
- Time remaining to maturity, in years.
- d1 : float | numpy.ndarray
- `d1` in Black-Scholes formula.
- y : float, optional
- Annualized dividend yield. The default is 0.0.
+ `s0`: spot price of the underlying asset.
+
+ `years_to_maturity`: time remaining to maturity, in years.
+
+ `d1`: `d1` in Black-Scholes formula.
+
+ `y`: annualized dividend yield.
Returns
-------
- float | numpy.ndarray
- Option's Greek Vega.
+ Option's Greek Vega.
"""
s = s0 * exp(-y * years_to_maturity)
@@ -306,21 +298,19 @@ def get_rho(
Parameters
----------
- option_type : OptionType
- `OptionType` literal value, which must be either **call** or **put**.
- x : float | numpy.ndarray
- Strike price(s).
- r : float
- Annualized risk-free interest rate.
- years_to_maturity : float
- Time remaining to maturity, in years.
- d2 : float | numpy.ndarray
- `d2` in Black-Scholes formula.
+ `option_type`: either *'call'* or *'put'*.
+
+ `x`: strike price(s).
+
+ `r`: annualized risk-free interest rate.
+
+ `years_to_maturity`: time remaining to maturity, in years.
+
+ `d2`: `d2` in Black-Scholes formula.
Returns
-------
- float | numpy.ndarray
- Option's Greek Rho.
+ Option's Greek Rho.
"""
if option_type == "call":
@@ -356,23 +346,21 @@ def get_d1(
Parameters
----------
- s0 : float | numpy.ndarray
- Spot price(s) of the underlying asset.
- x : float | numpy.ndarray
- Strike price(s).
- r : float
- Annualized risk-free interest rate.
- vol : float | numpy.ndarray
- Annualized volatility(ies).
- years_to_maturity : float
- Time remaining to maturity, in years.
- y : float, optional
- Annualized divident yield. The default is 0.0.
+ `s0`: spot price(s) of the underlying asset.
+
+ `x`: strike price(s).
+
+ `r`: annualized risk-free interest rate.
+
+ `vol`: annualized volatility(ies).
+
+ `years_to_maturity`: time remaining to maturity, in years.
+
+ `y`: annualized divident yield.
Returns
-------
- float | numpy.ndarray
- `d1` in Black-Scholes formula.
+ `d1` in Black-Scholes formula.
"""
return (log(s0 / x) + (r - y + vol * vol / 2.0) * years_to_maturity) / (
@@ -393,23 +381,21 @@ def get_d2(
Parameters
----------
- s0 : float | numpy.ndarray
- Spot price(s) of the underlying asset.
- x : float | numpy.ndarray
- Strike price(s).
- r : float
- Annualized risk-free interest rate.
- vol : float | numpy.ndarray
- Annualized volatility(ies).
- years_to_maturity : float
- Time remaining to maturity, in years.
- y : float, optional
- Annualized divident yield. The default is 0.0.
+ `s0`: spot price(s) of the underlying asset.
+
+ `x`: strike price(s).
+
+ `r`: annualized risk-free interest rate.
+
+ `vol`: annualized volatility(ies).
+
+ `years_to_maturity`: time remaining to maturity, in years.
+
+ `y`: annualized divident yield.
Returns
-------
- float | numpy.ndarray
- `d2` in Black-Scholes formula.
+ `d2` in Black-Scholes formula.
"""
return (log(s0 / x) + (r - y - vol * vol / 2.0) * years_to_maturity) / (
@@ -431,25 +417,23 @@ def get_implied_vol(
Parameters
----------
- option_type : str
- `OptionType` literal value, which must be either **call** or **put**.
- oprice : float
- Market price of an option.
- s0 : float
- Spot price of the underlying asset.
- x : float
- Strike price.
- r : float
- Annualized risk-free interest rate.
- years_to_maturity : float
- Time remaining to maturity, in years.
- y : float, optional
- Annualized dividend yield. The default is 0.0.
+ `option_type`: either *'call'* or *'put'*.
+
+ `oprice`: market price of an option.
+
+ `s0`: spot price of the underlying asset.
+
+ `x`: strike price.
+
+ `r`: annualized risk-free interest rate.
+
+ `years_to_maturity`: time remaining to maturity, in years.
+
+ `y`: annualized dividend yield.
Returns
-------
- float
- Implied volatility of the option.
+ Option's implied volatility.
"""
vol = 0.001 * arange(1, 1001)
@@ -469,23 +453,21 @@ def get_itm_probability(
y: float = 0.0,
) -> FloatOrNdarray:
"""
- Returns the In-The-Money probability of an option.
+ Returns the probability(ies) that the option(s) will expire in-the-money (ITM).
Parameters
----------
- option_type : str
- `OptionType` literal value, which must be either **call** or **put**.
- d2 : float | numpy.ndarray
- `d2` in Black-Scholes formula.
- years_to_maturity : float
- Time remaining to maturity, in years.
- y : float, optional
- Annualized dividend yield. The default is 0.0.
+ `option_type`: either *'call'* or *'put'*.
+
+ `d2`: `d2` in Black-Scholes formula.
+
+ `years_to_maturity`: time remaining to maturity, in years.
+
+ `y`: annualized dividend yield.
Returns
-------
- float | numpy.ndarray
- In-The-Money probability(ies).
+ Probability(ies) that the option(s) will expire in-the-money (ITM).
"""
yfac = exp(-y * years_to_maturity)
diff --git a/optionlab/engine.py b/optionlab/engine.py
index 90d4278..93051a4 100644
--- a/optionlab/engine.py
+++ b/optionlab/engine.py
@@ -1,3 +1,11 @@
+"""
+This module defines the `run_strategy` function.
+
+Given input data provided as either an `optionlab.models.Inputs` object or a dictionary,
+`run_strategy` returns the results of an options strategy calculation (e.g., the
+probability of profit on the target date) as an `optionlab.models.Outputs` object.
+"""
+
from __future__ import division
from __future__ import print_function
@@ -36,15 +44,11 @@ def run_strategy(inputs_data: Inputs | dict) -> Outputs:
Parameters
----------
- inputs_data : Inputs | dict
- Input data used in the strategy calculation. See the documentation for
- `Inputs` for more details.
+ `inputs_data`: input data used in the strategy calculation.
Returns
-------
- Outputs
- Output data from the strategy calculation. See the documentation for
- `Outputs` for more details.
+ Output data from the strategy calculation.
"""
inputs = (
@@ -177,7 +181,7 @@ def _run(data: EngineData) -> EngineData:
if inputs.model == "array":
data.strategy_profit_mc += data.profit_mc[i]
- if inputs.model in ("normal", "black-scholes"):
+ if inputs.model == "black-scholes":
pop_inputs = BlackScholesModelInputs(
stock_price=inputs.stock_price,
volatility=inputs.volatility,
diff --git a/optionlab/models.py b/optionlab/models.py
index fcc4b9b..20b0e47 100644
--- a/optionlab/models.py
+++ b/optionlab/models.py
@@ -1,3 +1,12 @@
+"""
+This module primarily implements Pydantic models that represent inputs and outputs
+of strategy calculations. It also implements constants and custom types.
+
+From the user's point of view, the two most important classes that they will use
+to provide input and subsequently process calculation results are `Inputs` and
+`Outputs`, respectively.
+"""
+
import datetime as dt
from typing import Literal, Optional
@@ -5,136 +14,163 @@
from pydantic import BaseModel, Field, field_validator, model_validator, ConfigDict
OptionType = Literal["call", "put"]
+"""Option type in a strategy leg."""
+
Action = Literal["buy", "sell"]
-StrategyType = Literal["stock"] | OptionType | Literal["closed"]
+"""Action taken in in a strategy leg."""
+
+StrategyLegType = Literal["stock"] | OptionType | Literal["closed"]
+"""Type of strategy leg."""
+
+TheoreticalModel = Literal["black-scholes", "array"]
+"""
+Theoretical model used in probability of profit (PoP) calculations.
+"""
+
Range = tuple[float, float]
-TheoreticalModel = Literal["black-scholes", "normal", "array"]
+"""Range boundaries."""
+
FloatOrNdarray = float | np.ndarray
+"""Float or numpy array custom type."""
def init_empty_array() -> np.ndarray:
+ """@private"""
+
return np.array([])
-class BaseLeg(BaseModel):
+class Stock(BaseModel):
+ """Defines the attributes of a stock leg in a strategy."""
+
+ type: Literal["stock"] = "stock"
+ """It must be *'stock'*."""
+
n: int = Field(gt=0)
- action: Action
- prev_pos: Optional[float] = None
+ """Number of shares."""
+ action: Action
+ """Either *'buy'* or *'sell'*."""
-class Stock(BaseLeg):
+ prev_pos: Optional[float] = None
"""
- Defines the attributes of a stock leg in a strategy.
-
- Attributes
- ----------
- type : str
- It must be **stock**.
- n : int
- Number of shares.
- action : str
- `Action` literal value, which must be either **buy** or **sell**.
- prev_pos : float, optional
- Stock price effectively paid or received in a previously opened position.
- If positive, the position remains open and the payoff calculation considers
- this price instead of the current stock price. If negative, the position
- is closed and the difference between this price and the current price is
- included in the payoff calculation. The default is None, which means this
- stock position is not a previously opened position.
+ Stock price effectively paid or received in a previously opened position.
+
+ - If positive, the position remains open and the payoff calculation considers
+ this price instead of the current stock price.
+
+ - If negative, the position is closed and the difference between this price
+ and the current price is included in the payoff calculation.
+
+ The default is `None`, which means this stock position is not a previously
+ opened position.
"""
- type: Literal["stock"] = "stock"
-
-class Option(BaseLeg):
- """
- Defines the attributes of an option leg in a strategy.
-
- Attributes
- ----------
- type : str
- `OptionType` literal value, which must be either **call** or **put**.
- strike : float
- Strike price.
- premium : float
- Option premium.
- n : int
- Number of options.
- action : str
- `Action` literal value, which must be either **buy** or **sell**.
- prev_pos : float | None, optional
- Premium effectively paid or received in a previously opened position. If
- positive, the position remains open and the payoff calculation considers
- this price instead of the current price of the option. If negative, the
- position is closed and the difference between this price and the current
- price is included in the payoff calculation. The default is None, which
- means this option position is not a previously opened position.
- expiration : str | int | None, optional
- Expiration date or number of days remaining to maturity. The default is
- None.
- """
+class Option(BaseModel):
+ """Defines the attributes of an option leg in a strategy."""
type: OptionType
+ """Either *'call'* or *'put'*."""
+
strike: float = Field(gt=0)
+ """Strike price."""
+
premium: float = Field(gt=0)
+ """Option premium."""
+
+ action: Action
+ """Either *'buy'* or *'sell'*."""
+
+ n: int = Field(gt=0)
+ """Number of options."""
+
+ prev_pos: Optional[float] = None
+ """
+ Premium effectively paid or received in a previously opened position.
+
+ - If positive, the position remains open and the payoff calculation considers
+ this price instead of the current price of the option.
+
+ - If negative, the position is closed and the difference between this price
+ and the current price is included in the payoff calculation.
+
+ The default is `None`, which means this option position is not a previously
+ opened position.
+ """
+
expiration: dt.date | int | None = None
+ """
+ Expiration date or number of days remaining to expiration.
+
+ The default is `None`, which means the expiration is the same as `Inputs.target_date`
+ or `Inputs.days_to_target_date`.
+ """
@field_validator("expiration")
def validate_expiration(cls, v: dt.date | int | None) -> dt.date | int | None:
+ """@private"""
+
if isinstance(v, int) and v <= 0:
raise ValueError("If expiration is an integer, it must be greater than 0.")
return v
class ClosedPosition(BaseModel):
- """
- Defines the attributes of a previously closed position in a strategy.
-
- Attributes
- ----------
- type : str
- It must be **closed**.
- prev_pos : float
- The total amount of the closed position. If positive, it resulted in a
- profit; if negative, it incurred a loss.
- """
+ """Defines the attributes of a previously closed position in a strategy."""
type: Literal["closed"] = "closed"
+ """It must be *'closed'*."""
+
prev_pos: float
+ """
+ The total amount of the closed position.
+
+ - If positive, it resulted in a profit.
+
+ - If negative, it incurred a loss.
+
+ This amount will be added to the payoff and taken into account in the strategy
+ calculations.
+ """
StrategyLeg = Stock | Option | ClosedPosition
+"""Leg in a strategy."""
class TheoreticalModelInputs(BaseModel):
+ """Inputs for calculations, such as the probability of profit (PoP)."""
+
stock_price: float = Field(gt=0.0)
+ """Stock price."""
+
volatility: float = Field(gt=0.0)
+ """Annualized volatility of the underlying asset."""
+
years_to_target_date: float = Field(ge=0.0)
+ """Time remaining until target date, in years."""
class BlackScholesModelInputs(TheoreticalModelInputs):
- """
- Defines the input data for the calculations using the Black-Scholes model.
-
- Attributes
- ----------
- model : str
- It must be either **black-scholes** or **normal**.
- stock_price : float
- Stock price.
- volatility : float
- Annualized volatility of the underlying asset.
- years_to_target_date : float
- Time remaining until target date, in years.
- interest_rate : float, optional
- Annualized risk-free interest rate. The default is 0.0.
- dividend_yield : float, optional
- Annualized dividend yield. The default is 0.0.
- """
-
- model: Literal["black-scholes", "normal"] = "black-scholes"
+ """Defines the input data for the calculations using the Black-Scholes model."""
+
+ model: Literal["black-scholes"] = "black-scholes"
+ """It must be *'black-scholes'*."""
+
interest_rate: float = Field(0.0, ge=0.0)
+ """
+ Annualized risk-free interest rate.
+
+ The default is 0.0.
+ """
+
dividend_yield: float = Field(0.0, ge=0.0, le=1.0)
+ """
+ Annualized dividend yield.
+
+ The default is 0.0.
+ """
__hash__ = object.__hash__
@@ -143,23 +179,13 @@ class LaplaceInputs(TheoreticalModelInputs):
"""
Defines the input data for the calculations using a log-Laplace distribution of
stock prices.
-
- Attributes
- ----------
- model : str
- It must be **laplace**.
- stock_price : float
- Stock price.
- mu : float
- Annualized return of the underlying asset.
- volatility : float
- Annualized volatility of the underlying asset.
- years_to_target_date : float
- Time remaining until target date, in years.
"""
model: Literal["laplace"] = "laplace"
+ """It must be '*laplace*'."""
+
mu: float
+ """Annualized return of the underlying asset."""
__hash__ = object.__hash__
@@ -168,23 +194,21 @@ class ArrayInputs(BaseModel):
"""
Defines the input data for the calculations when using an array of strategy
returns.
-
- Attributes
- ----------
- model : str
- It must be **array**.
- array : numpy.ndarray
- Array of strategy returns.
"""
model: Literal["array"] = "array"
+ """It must be *'array*'."""
+
array: np.ndarray
+ """Array of strategy returns."""
model_config = ConfigDict(arbitrary_types_allowed=True)
@field_validator("array", mode="before")
@classmethod
def validate_arrays(cls, v: np.ndarray | list[float]) -> np.ndarray:
+ """@private"""
+
arr = np.asarray(v)
if arr.shape[0] == 0:
raise ValueError("The array is empty!")
@@ -192,84 +216,126 @@ def validate_arrays(cls, v: np.ndarray | list[float]) -> np.ndarray:
class Inputs(BaseModel):
- """
- Defines the input data for a strategy calculation.
-
- Attributes
- ----------
- stock_price : float
- Spot price of the underlying.
- volatility : float
- Annualized volatility.
- interest_rate : float
- Annualized risk-free interest rate.
- min_stock : float
- Minimum value of the stock in the stock price domain.
- max_stock : float
- Maximum value of the stock in the stock price domain.
- strategy : list[StrategyLeg]
- A list of strategy legs.
- dividend_yield : float, optional
- Annualized dividend yield. The default is 0.0.
- profit_target : float, optional
- Target profit level. The default is None, which means it is not
- calculated.
- loss_limit : float, optional
- Limit loss level. The default is None, which means it is not calculated.
- opt_commission : float
- Brokerage commission for options transactions. The default is 0.0.
- stock_commission : float
- Brokerage commission for stocks transactions. The default is 0.0.
- discard_nonbusiness_days : bool, optional
- Discards weekends and holidays when counting the number of days between
- two dates. The default is True.
- business_days_in_year : int, optional
- Number of business days in a year. The default is 252.
- country : str, optional
- Country whose holidays will be counted if `discard_nonbusinessdays` is
- set to True. The default is **US**.
- start_date : datetime.date, optional
- Start date in the calculations. If not provided, `days_to_target_date`
- must be provided.
- target_date : datetime.date, optional
- Target date in the calculations. If not provided, `days_to_target_date`
- must be provided.
- days_to_target_date : int, optional
- Days remaining to the target date. If not provided, `start_date` and
- `target_date` must be provided.
- model : str, optional
- Theoretical model used in the calculations of probability of profit. It
- can be **black-scholes** (the same as **normal**) or **array**. The default
- is **black-scholes**.
- array : numpy.ndarray, optional
- Array of terminal stock prices. The default is an empty array.
- """
+ """Defines the input data for a strategy calculation."""
stock_price: float = Field(gt=0.0)
+ """Spot price of the underlying."""
+
volatility: float = Field(ge=0.0)
+ """Annualized volatility."""
+
interest_rate: float = Field(ge=0.0)
+ """Annualized risk-free interest rate."""
+
min_stock: float = Field(ge=0.0)
+ """Minimum value of the stock in the stock price domain."""
+
max_stock: float = Field(ge=0.0)
+ """Maximum value of the stock in the stock price domain."""
+
strategy: list[StrategyLeg] = Field(..., min_length=1)
+ """A list of strategy legs."""
+
dividend_yield: float = Field(0.0, ge=0.0)
+ """
+ Annualized dividend yield.
+
+ The default is 0.0.
+ """
+
profit_target: Optional[float] = None
+ """
+ Target profit level.
+
+ The default is `None`, which means it is not calculated.
+ """
+
loss_limit: Optional[float] = None
+ """
+ Limit loss level.
+
+ The default is `None`, which means it is not calculated.
+ """
+
opt_commission: float = 0.0
+ """
+ Brokerage commission for options transactions.
+
+ The default is 0.0.
+ """
+
stock_commission: float = 0.0
+ """
+ Brokerage commission for stocks transactions.
+
+ The default is 0.0.
+ """
+
discard_nonbusiness_days: bool = True
+ """
+ Discards weekends and holidays when counting the number of days between
+ two dates.
+
+ The default is `True`.
+ """
+
business_days_in_year: int = 252
+ """
+ Number of business days in a year.
+
+ The default is 252.
+ """
+
country: str = "US"
+ """
+ Country whose holidays will be counted if `discard_nonbusinessdays` is
+ set to `True`.
+
+ The default is '*US*'.
+ """
+
start_date: dt.date | None = None
+ """
+ Start date in the calculations.
+
+ If not provided, `days_to_target_date` must be provided.
+ """
+
target_date: dt.date | None = None
+ """
+ Target date in the calculations.
+
+ If not provided, `days_to_target_date` must be provided.
+ """
+
days_to_target_date: int = Field(0, ge=0)
+ """
+ Days remaining to the target date.
+
+ If not provided, `start_date` and `target_date` must be provided.
+ """
+
model: TheoreticalModel = "black-scholes"
+ """
+ Theoretical model used in the calculations of probability of profit.
+
+ It can be *'black-scholes'* or *'array*'.
+ """
+
array: np.ndarray = Field(default_factory=init_empty_array)
+ """
+ Array of terminal stock prices.
+
+ The default is an empty array.
+ """
model_config = ConfigDict(arbitrary_types_allowed=True)
@field_validator("strategy")
@classmethod
def validate_strategy(cls, v: list[StrategyLeg]) -> list[StrategyLeg]:
+ """@private"""
+
types = [strategy.type for strategy in v]
if types.count("closed") > 1:
raise ValueError("Only one position of type 'closed' is allowed!")
@@ -277,6 +343,8 @@ def validate_strategy(cls, v: list[StrategyLeg]) -> list[StrategyLeg]:
@model_validator(mode="after")
def validate_dates(self) -> "Inputs":
+ """@private"""
+
expiration_dates = [
strategy.expiration
for strategy in self.strategy
@@ -303,6 +371,8 @@ def validate_dates(self) -> "Inputs":
@model_validator(mode="after")
def validate_model_array(self) -> "Inputs":
+ """@private"""
+
if self.model != "array":
return self
elif self.array is None:
@@ -317,50 +387,50 @@ def validate_model_array(self) -> "Inputs":
class BlackScholesInfo(BaseModel):
- """
- Defines the data returned by a calculation using the Black-Scholes model.
-
- Attributes
- ----------
- call_price : float | numpy.ndarray
- Price of a call option.
- put_price : float | numpy.ndarray
- Price of a put option.
- call_delta : float | numpy.ndarray
- Delta of a call option.
- put_delta : float | numpy.ndarray
- Delta of a put option.
- gamma : float | numpy.ndarray
- Gamma of an option.
- vega : float | numpy.ndarray
- Vega of an option.
- call_rho : float | numpy.ndarray
- Rho of a call option.
- put_rho : float | numpy.ndarray
- Rho of a put option.
- call_itm_prob : float | numpy.ndarray
- In-the-money probability of a call option.
- put_itm_prob : float | numpy.ndarray
- In-the-money probability of a put option.
- """
+ """Defines the data returned by a calculation using the Black-Scholes model."""
call_price: FloatOrNdarray
+ """Price of a call option."""
+
put_price: FloatOrNdarray
+ """Price of a put option."""
+
call_delta: FloatOrNdarray
+ """Delta of a call option."""
+
put_delta: FloatOrNdarray
+ """Delta of a put option."""
+
call_theta: FloatOrNdarray
+ """Theta of a call option."""
+
put_theta: FloatOrNdarray
+ """Theta of a put option."""
+
gamma: FloatOrNdarray
+ """Gamma of an option."""
+
vega: FloatOrNdarray
+ """Vega of an option."""
+
call_rho: FloatOrNdarray
+ """Rho of a call option."""
+
put_rho: FloatOrNdarray
+ """Rho of a put option."""
+
call_itm_prob: FloatOrNdarray
+ """Probability of expiring in-the-money probability of a call option."""
+
put_itm_prob: FloatOrNdarray
+ """Probability of expiring in-the-money of a put option."""
model_config = ConfigDict(arbitrary_types_allowed=True)
class EngineDataResults(BaseModel):
+ """@private"""
+
stock_price_array: np.ndarray
terminal_stock_prices: np.ndarray = Field(default_factory=init_empty_array)
profit: np.ndarray = Field(default_factory=init_empty_array)
@@ -371,12 +441,14 @@ class EngineDataResults(BaseModel):
premium: list[float] = []
n: list[int] = []
action: list[Action | Literal["n/a"]] = []
- type: list[StrategyType] = []
+ type: list[StrategyLegType] = []
model_config = ConfigDict(arbitrary_types_allowed=True)
class EngineData(EngineDataResults):
+ """@private"""
+
inputs: Inputs
previous_position: list[float] = []
use_bs: list[bool] = []
@@ -404,80 +476,123 @@ class EngineData(EngineDataResults):
class Outputs(BaseModel):
"""
Defines the output data from a strategy calculation.
-
- Attributes
- ----------
- probability_of_profit : float
- Probability of the strategy yielding at least $0.01.
- profit_ranges : list[Range]
- A list of minimum and maximum stock prices defining ranges in which the
- strategy makes at least $0.01.
- expected_profit : float, optional
- Expected profit when the strategy is profitable. The default is None.
- expected_loss : float, optional
- Expected loss when the strategy is not profitable. The default is None.
- strategy_cost : float
- Total strategy cost.
- per_leg_cost : list[float]
- A list of costs, one per strategy leg.
- implied_volatility : list[float]
- List of implied volatilities, one per strategy leg.
- in_the_money_probability : list[float]
- List of ITM probabilities, one per strategy leg.
- delta : list[float]
- List of Delta values, one per strategy leg.
- gamma : list[float]
- List of Gamma values, one per strategy leg.
- theta : list[float]
- List of Theta values, one per strategy leg.
- vega : list[float]
- List of Vega values, one per strategy leg.
- rho : list[float]
- List of Rho values, one per strategy leg.
- minimum_return_in_the_domain : float
- Minimum return of the strategy within the stock price domain.
- maximum_return_in_the_domain : float
- Maximum return of the strategy within the stock price domain.
- probability_of_profit_target : float, optional
- Probability of the strategy yielding at least the profit target. The
- default is 0.0.
- profit_target_ranges : list[Range], optional
- List of minimum and maximum stock prices defining ranges in which the
- strategy makes at least the profit target. The default is [].
- probability_of_loss_limit : float, optional
- Probability of the strategy losing at least the loss limit. The default
- is 0.0.
- loss_limit_ranges : list[Range], optional
- List of minimum and maximum stock prices defining ranges where the
- strategy loses at least the loss limit. The default is [].
- data : EngineDataResults
- Further data from the strategy calculation that can be used in the
- post-processing of the outputs.
- inputs : Inputs
- Input data used in the strategy calculation.
"""
- inputs: Inputs
- data: EngineDataResults
probability_of_profit: float
+ """
+ Probability of the strategy yielding at least $0.01.
+ """
+
profit_ranges: list[Range]
+ """
+ A list of minimum and maximum stock prices defining ranges in which the
+ strategy makes at least $0.01.
+ """
+
expected_profit: Optional[float] = None
+ """
+ Expected profit when the strategy is profitable.
+
+ The default is `None`.
+ """
+
expected_loss: Optional[float] = None
+ """
+ Expected loss when the strategy is not profitable.
+
+ The default is `None`.
+ """
+
per_leg_cost: list[float]
+ """
+ List of leg costs.
+ """
+
strategy_cost: float
+ """
+ Total strategy cost.
+ """
+
minimum_return_in_the_domain: float
+ """
+ Minimum return of the strategy within the stock price domain.
+ """
+
maximum_return_in_the_domain: float
+ """
+ Maximum return of the strategy within the stock price domain.
+ """
+
implied_volatility: list[float]
+ """
+ List of implied volatilities, one per strategy leg.
+ """
+
in_the_money_probability: list[float]
+ """
+ List of probabilities of legs expiring in-the-money (ITM).
+ """
+
delta: list[float]
+ """
+ List of Delta values, one per strategy leg.
+ """
+
gamma: list[float]
+ """
+ List of Gamma values, one per strategy leg.
+ """
+
theta: list[float]
+ """
+ List of Theta values, one per strategy leg.
+ """
+
vega: list[float]
+ """
+ List of Vega values, one per strategy leg.
+ """
+
rho: list[float]
+ """
+ List of Rho values, one per strategy leg.
+ """
+
probability_of_profit_target: float = 0.0
+ """
+ Probability of the strategy yielding at least the profit target.
+
+ The default is 0.0.
+ """
+
profit_target_ranges: list[Range] = []
+ """
+ List of minimum and maximum stock prices defining ranges in which the
+ strategy makes at least the profit target.
+
+ The default is [].
+ """
+
probability_of_loss_limit: float = 0.0
+ """
+ Probability of the strategy losing at least the loss limit.
+
+ The default is 0.0.
+ """
+
loss_limit_ranges: list[Range] = []
+ """
+ List of minimum and maximum stock prices defining ranges where the
+ strategy loses at least the loss limit.
+
+ The default is [].
+ """
+
+ inputs: Inputs
+ """@private"""
+
+ data: EngineDataResults
+ """@private"""
def __str__(self):
s = ""
@@ -495,32 +610,50 @@ def __str__(self):
class PoPOutputs(BaseModel):
"""
Defines the output data from a probability of profit (PoP) calculation.
-
- Attributes
- ----------
- probability_of_reaching_target : float, optional
- Probability that the strategy return will be equal or greater than the
- target. The default is 0.0.
- probability_of_missing_target : float, optional
- Probability that the strategy return will be less than the target. The
- default is 0.0.
- reaching_target_range : list[Range], optional
- Range of stock prices where the strategy return is equal or greater than
- the target. The default is [].
- missing_target_range : list[Range], optional
- Range of stock prices where the strategy return is less than the target.
- The default is [].
- expected_return_above_target : float, optional
- Expected value of the strategy return when the return is equal or greater
- than the target. The default is None.
- expected_return_below_target : float, optional
- Expected value of the strategy return when the return is less than the
- target. The default is None.
"""
probability_of_reaching_target: float = 0.0
+ """
+ Probability that the strategy return will be equal or greater than the
+ target.
+
+ The default is 0.0.
+ """
+
probability_of_missing_target: float = 0.0
+ """
+ Probability that the strategy return will be less than the target.
+
+ The default is 0.0.
+ """
+
reaching_target_range: list[Range] = []
+ """
+ Range of stock prices where the strategy return is equal or greater than
+ the target.
+
+ The default is [].
+ """
+
missing_target_range: list[Range] = []
+ """
+ Range of stock prices where the strategy return is less than the target.
+
+ The default is [].
+ """
+
expected_return_above_target: Optional[float] = None
+ """
+ Expected value of the strategy return when the return is equal or greater
+ than the target.
+
+ The default is `None`.
+ """
+
expected_return_below_target: Optional[float] = None
+ """
+ Expected value of the strategy return when the return is less than the
+ target.
+
+ The default is `None`.
+ """
diff --git a/optionlab/plot.py b/optionlab/plot.py
index 97f6bf8..c23f5f4 100644
--- a/optionlab/plot.py
+++ b/optionlab/plot.py
@@ -1,3 +1,8 @@
+"""
+This module implements the `plot_pl` function, which displays the profit/loss diagram
+of an options trading strategy.
+"""
+
from __future__ import division
from __future__ import print_function
@@ -14,12 +19,11 @@ def plot_pl(outputs: Outputs) -> None:
Parameters
----------
- outputs : Outputs
- Output data from a strategy calculation.
+ `outputs`: output data from a strategy calculation with `optionlab.engine.run_strategy`.
Returns
-------
- None.
+ `None`.
"""
st = outputs.data
diff --git a/optionlab/price_array.py b/optionlab/price_array.py
index 6ec7c4c..8f9781a 100644
--- a/optionlab/price_array.py
+++ b/optionlab/price_array.py
@@ -1,3 +1,11 @@
+"""
+This module defines the `create_price_array` function, which calculates terminal
+prices from numerical simulations of multiple stock paths.
+
+The terminal price array can later be used to calculate the probability of profit
+(PoP) of a strategy using the `optionlab.engine.run_strategy` function.
+"""
+
from functools import lru_cache
import numpy as np
@@ -18,18 +26,15 @@ def create_price_array(
Parameters
----------
- inputs_data : BlackScholesModelInputs | LaplaceInputs | dict
- Input data used to generate the terminal stock prices. See the documentation
- for `BlackScholesModelInputs` and `LaplaceInputs` for more details.
- n : int, optional
- Number of terminal stock prices. The default is 100,000.
- seed : int | None, optional
- Seed for random number generation. The default is None.
+ `inputs_data`: input data used to generate the terminal stock prices.
+
+ `n`: number of terminal stock prices.
+
+ `seed`: seed for random number generation.
Returns
-------
- numpy.ndarray
- Array of terminal prices.
+ Array of terminal prices.
"""
inputs: BlackScholesModelInputs | LaplaceInputs
@@ -37,7 +42,7 @@ def create_price_array(
if isinstance(inputs_data, dict):
input_type = inputs_data["model"]
- if input_type in ("black-scholes", "normal"):
+ if input_type == "black-scholes":
inputs = BlackScholesModelInputs.model_validate(inputs_data)
elif input_type == "laplace":
inputs = LaplaceInputs.model_validate(inputs_data)
@@ -55,7 +60,7 @@ def create_price_array(
np_seed_number(seed)
- if input_type in ("black-scholes", "normal"):
+ if input_type == "black-scholes":
arr = _get_array_price_from_BS(inputs, n)
elif input_type == "laplace":
arr = _get_array_price_from_laplace(inputs, n)
diff --git a/optionlab/support.py b/optionlab/support.py
index 69ff2e0..bb32aad 100644
--- a/optionlab/support.py
+++ b/optionlab/support.py
@@ -1,3 +1,9 @@
+"""
+This module implements a number of helper functions that are not intended to be
+called directly by users, but rather support functionalities within the
+`optionlab.engine.run_strategy` function.
+"""
+
from __future__ import division
from functools import lru_cache
@@ -35,25 +41,23 @@ def get_pl_profile(
Parameters
----------
- option_type : str
- `OptionType` literal value, which must be either **call** or **put**.
- action : str
- `Action` literal value, which must be either **buy** or **sell**.
- x : float
- Strike price.
- val : float
- Option price.
- n : int
- Number of options.
- s : numpy.ndarray
- Array of stock prices.
- commission : float, optional
- Brokerage commission. The default is 0.0.
+ `option_type`: either *'call'* or *'put'*.
+
+ `action`: either *'buy'* or *'sell'*.
+
+ `x`: strike price.
+
+ `val`: option price.
+
+ `n`: number of options.
+
+ `s`: array of stock prices.
+
+ `commission`: brokerage commission.
Returns
-------
- tuple[numpy.ndarray, float]
- Profit/loss profile and cost of an option trade at expiration.
+ Profit/loss profile and cost of an option trade at expiration.
"""
if action == "buy":
@@ -80,21 +84,19 @@ def get_pl_profile_stock(
Parameters
----------
- s0 : float
- Initial stock price.
- action : str
- `Action` literal value, which must be either **buy** or **sell**.
- n : int
- Number of shares.
- s : numpy.ndarray
- Array of stock prices.
- commission : float, optional
- Brokerage commission. The default is 0.0.
+ `s0`: initial stock price.
+
+ `action`: either *'buy'* or *'sell'*.
+
+ `n`: number of shares.
+
+ `s`: array of stock prices.
+
+ `commission`: brokerage commission.
Returns
-------
- tuple[numpy.ndarray, float]
- Profit/loss profile and cost of a stock position.
+ Profit/loss profile and cost of a stock position.
"""
if action == "buy":
@@ -126,33 +128,32 @@ def get_pl_profile_bs(
Parameters
----------
- option_type : str
- `OptionType` literal value, which must be either **call** or **put**.
- action : str
- `Action` literal value, which must be either **buy** or **sell**.
- x : float
- Strike price.
- val : float
- Initial option price.
- r : float
- Annualized risk-free interest rate.
- target_to_maturity_years : float
- Time remaining to maturity from the target date, in years.
- volatility : float
- Annualized volatility of the underlying asset.
- n : int
- Number of options.
- s : numpy.ndarray
- Array of stock prices.
- y : float, optional
- Annualized dividend yield. The default is 0.0.
- commission : float, optional
- Brokerage commission. The default is 0.0.
+ `option_type`: either *'call'* or *'put'*.
+
+ `action`: either *'buy'* or *'sell'*.
+
+ `x`: strike price.
+
+ `val`: initial option price.
+
+ `r`: annualized risk-free interest rate.
+
+ `target_to_maturity_years`: time remaining to maturity from the target date,
+ in years.
+
+ `volatility`: annualized volatility of the underlying asset.
+
+ `n`: number of options.
+
+ `s`: array of stock prices.
+
+ `y`: annualized dividend yield.
+
+ `commission`: brokerage commission.
Returns
-------
- tuple[numpy.ndarray, float]
- Profit/loss profile and cost of an option trade before expiration.
+ Profit/loss profile and cost of an option trade before expiration.
"""
if action == "buy":
@@ -182,15 +183,13 @@ def create_price_seq(min_price: float, max_price: float) -> np.ndarray:
Parameters
----------
- min_price : float
- Minimum stock price in the range.
- max_price : float
- Maximum stock price in the range.
+ `min_price`: minimum stock price in the range.
+
+ `max_price`: maximum stock price in the range.
Returns
-------
- numpy.ndarray
- Array of sequential stock prices.
+ Array of sequential stock prices.
"""
if max_price > min_price:
@@ -210,20 +209,17 @@ def get_pop(
Parameters
----------
- s : numpy.ndarray
- Array of stock prices.
- profit : numpy.ndarray
- Array of profits and losses.
- inputs_data : BlackScholesModelInputs | ArrayInputs
- Input data used to estimate the probability of profit. See the documentation
- for `BlackScholesModelInputs` and `ArrayInputs` for more details.
- target : float, optional
- Return target. The default is 0.01.
+ `s`: array of stock prices.
+
+ `profit`: array of profits and losses.
+
+ `inputs_data`: input data used to estimate the probability of profit.
+
+ `target`: target return.
Returns
-------
- PoPOutputs
- Outputs. See the documentation for `PoPOutputs` for more details.
+ Outputs of a probability of profit (PoP) calculation.
"""
probability_of_reaching_target: float
@@ -270,21 +266,19 @@ def _get_pl_option(
Parameters
----------
- option_type : str
- `OptionType` literal value, which must be either **call** or **put**.
- opvalue : float
- Option price.
- action : str
- `Action` literal value, which must be either **buy** or **sell**.
- s : numpy.ndarray
- Array of stock prices.
- x : float
- Strike price.
+ `option_type`: either *'call'* or *'put'*.
+
+ `opvalue`: option price.
+
+ `action`: either *'buy'* or *'sell'*.
+
+ `s`: array of stock prices.
+
+ `x`: strike price.
Returns
-------
- numpy.ndarray
- Profit or loss profile of an option leg at expiration.
+ Profit or loss profile of an option leg at expiration.
"""
if action == "sell":
@@ -301,17 +295,15 @@ def _get_payoff(option_type: OptionType, s: np.ndarray, x: float) -> np.ndarray:
Parameters
----------
- option_type : str
- `OptionType` literal value, which must be either **call** or **put**.
- s : numpy.ndarray
- Array of stock prices.
- x : float
- Strike price.
+ `option_type`: either *'call'* or *'put'*.
+
+ `s`: array of stock prices.
+
+ `x`: strike price.
Returns
-------
- numpy.ndarray
- Payoff of an option leg at expiration.
+ Payoff of an option leg at expiration.
"""
if option_type == "call":
@@ -328,17 +320,15 @@ def _get_pl_stock(s0: float, action: Action, s: np.ndarray) -> np.ndarray:
Parameters
----------
- s0 : float
- Spot price of the underlying asset.
- action : str
- `Action` literal value, which must be either **buy** or **sell**.
- s : numpy.ndarray
- Array of stock prices.
+ `s0`: spot price of the underlying asset.
+
+ `action`: either *'buy'* or *'sell'*.
+
+ `s`: array of stock prices.
Returns
-------
- numpy.ndarray
- Profit or loss profile of a stock position.
+ Profit or loss profile of a stock position.
"""
if action == "sell":
@@ -361,22 +351,20 @@ def _get_pop_bs(
Parameters
----------
- s : numpy.ndarray
- Array of stock prices.
- profit : numpy.ndarray
- Array of profits and losses.
- inputs : BlackScholesModelInputs
- Input data used to estimate the probability of profit. See the documentation
- for `BlackScholesModelInputs` for more details.
- profit_range : tuple[list[Range], list[Range]]
- Tuple of lists of stock price pairs defining the profit and loss ranges.
+ `s`: array of stock prices.
+
+ `profit`: array of profits and losses.
+
+ `inputs`: input data used to estimate the probability of profit.
+
+ `profit_range`: lists of stock price pairs defining the profit and loss
+ ranges.
Returns
-------
- tuple[float, float | None, float, float | None]
- Probability of reaching the return target, expected value above the target,
- probability of missing the return target, and expected value below the
- target.
+ Probability of reaching the return target, expected value above the target,
+ probability of missing the return target, and expected value below the
+ target.
"""
expected_return_above_target = None
@@ -427,18 +415,15 @@ def _get_pop_array(
Parameters
----------
- inputs : ArrayInputs
- Input data used to estimate the probability of profit. See the documentation
- for `ArrayInputs` for more details.
- target : float
- Return target.
+ `inputs`: input data used to estimate the probability of profit.
+
+ `target`: target return.
Returns
-------
- tuple[float, float | None, float, float | None]
- Probability of reaching the return target, expected value above the target,
- probability of missing the return target, and expected value below the
- target.
+ Probability of reaching the target return, expected value above the target,
+ probability of missing the target return, and expected value below the
+ target.
"""
if inputs.array.shape[0] == 0:
@@ -465,23 +450,21 @@ def _get_profit_range(
s: np.ndarray, profit: np.ndarray, target: float = 0.01
) -> tuple[list[Range], list[Range]]:
"""
- Returns a tuple of lists of stock price ranges: one representing the ranges
- where the options trade returns are equal to or greater than the target, and
- the other representing the ranges where they fall short.
+ Returns lists of stock price ranges: one representing the ranges where the
+ options trade returns are equal to or greater than the target, and the other
+ representing the ranges where they fall short.
Parameters
----------
- s : numpy.ndarray
- Array of stock prices.
- profit : numpy.ndarray
- Array of profits and losses.
- target : float, optional
- Profit target. The default is 0.01.
+ `s`: array of stock prices.
+
+ `profit`: array of profits and losses.
+
+ `target`: target profit.
Returns
-------
- tuple(list[Range], list[Range])
- Tuple of lists of stock price pairs.
+ Lists of stock price pairs.
"""
profit_range = []
@@ -551,15 +534,13 @@ def _get_sign_changes(profit: np.ndarray, target: float) -> list[int]:
Parameters
----------
- profit : np.ndarray
- Array of profits and losses.
- target : float
- Profit target.
+ `profit`: array of profits and losses.
+
+ `target`: target profit.
Returns
-------
- list[int]
- List of indices.
+ List of indices.
"""
p_temp = profit - target + 1e-10
diff --git a/optionlab/utils.py b/optionlab/utils.py
index 3f60c0f..0ae970f 100644
--- a/optionlab/utils.py
+++ b/optionlab/utils.py
@@ -1,3 +1,7 @@
+"""
+This module defines utility functions.
+"""
+
from __future__ import division
import datetime as dt
@@ -20,19 +24,15 @@ def get_nonbusiness_days(
Parameters
----------
- start_date : datetime.date
- Start date.
- end_date : datetime.date
- End date.
- country : str, optional
- Country of the stock exchange. A list of available countries can be found
- in the `holidays library documentation `_.
- The default value is 'US'.
+ `start_date`: start date.
+
+ `end_date`: end date.
+
+ `country`: country of the stock exchange.
Returns
-------
- int
- Number of weekends and holidays between the start and end date.
+ Number of weekends and holidays between the start and end date.
"""
if end_date > start_date:
@@ -59,15 +59,14 @@ def get_pl(outputs: Outputs, leg: int | None = None) -> tuple[np.ndarray, np.nda
Parameters
----------
- outputs : Outputs
- Output data from a strategy calculation.
- leg : int | None, optional
- Index of a strategy leg. The default is None, which means the whole strategy.
+ `outputs`: output data from a strategy calculation.
+
+ `leg`: index of a strategy leg. The default is `None`, which means the whole
+ strategy.
Returns
-------
- tuple[numpy.ndarray, numpy.ndarray]
- Array of stock prices and array or profits/losses.
+ Array of stock prices and array or profits/losses.
"""
if outputs.data.profit.size > 0 and leg and leg < outputs.data.profit.shape[0]:
@@ -85,16 +84,16 @@ def pl_to_csv(
Parameters
----------
- outputs : Outputs
- Output data from a strategy calculation.
- filename : str, optional
- Name of the CSV file. The default is 'pl.csv'.
- leg : int | None, optional
- Index of a strategy leg. The default is None, which means the whole strategy.
+ `outputs`: output data from a strategy calculation.
+
+ `filename`: name of the CSV file.
+
+ `leg`: index of a strategy leg. The default is `None`, which means the whole
+ strategy.
Returns
-------
- None.
+ `None`.
"""
if outputs.data.profit.size > 0 and leg and leg < outputs.data.profit.shape[0]:
diff --git a/pyproject.toml b/pyproject.toml
index d81087f..cf63314 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "optionlab"
-version = "1.4.2"
+version = "1.4.3"
description = "Python library for evaluating options trading strategies"
authors = ["Roberto Gomes, PhD "]
readme = "README.md"
diff --git a/tests/test_core.py b/tests/test_core.py
index 4c81ccb..85d9811 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -1,9 +1,9 @@
import pytest
-from optionlab.models import Inputs, Outputs, BlackScholesModelInputs, LaplaceInputs
-from optionlab.engine import run_strategy
-from optionlab.price_array import create_price_array
-from optionlab.black_scholes import get_bs_info
+from optionlab import Inputs, Outputs, BlackScholesModelInputs, LaplaceInputs
+from optionlab import run_strategy
+from optionlab import create_price_array
+from optionlab import get_bs_info
COVERED_CALL_RESULT = {
diff --git a/tests/test_misc.py b/tests/test_misc.py
index e6b90f9..40609b8 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -98,7 +98,7 @@ def test_cache_price_samples():
sample3 = create_price_array(
inputs_data={
- "model": "normal",
+ "model": "black-scholes",
"stock_price": stock_price,
"volatility": volatility,
"interest_rate": interest_rate,