From f394d8064f5bd60e82ff7a05565b16d70a9c25f5 Mon Sep 17 00:00:00 2001 From: Anil Sorathiya Date: Wed, 11 Dec 2024 11:20:45 +0000 Subject: [PATCH 1/5] add data quality tests --- .../quickstart_option_pricing_models.ipynb | 183 +++++++++++++++--- ...start_option_pricing_models_quantlib.ipynb | 104 +++++++++- 2 files changed, 251 insertions(+), 36 deletions(-) diff --git a/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb b/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb index cb4a370a8..b7446349d 100644 --- a/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb +++ b/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb @@ -33,9 +33,11 @@ "- [Initialize the ValidMind Library](#toc3_) \n", "- [Initialize the Python environment](#toc4_) \n", " - [Preview the documentation template](#toc4_1_) \n", - "- [Model development](#toc6_) \n", + "- [Model development](#toc5_) \n", + "- [Data preparation](#toc6_) \n", " - [Synthetic data generation](#toc6_1_)\n", - " - [Model Calibration](#toc6_2_) \n", + " - [Data quality](#toc6_2_)\n", + " - [Model Calibration](#toc6_3_) \n", "- [Model Evaluation](#toc7_) \n", " - [Benchmark Testing](#toc7_1_) \n", " - [Sensitivity Testing](#toc7_2_) \n", @@ -248,7 +250,8 @@ "id": "6d6a8447", "metadata": {}, "source": [ - "\n", + "\n", + "\n", "## Model development" ] }, @@ -395,6 +398,16 @@ " return np.exp(-self.r * self.T) * np.mean(payoffs)" ] }, + { + "cell_type": "markdown", + "id": "20f01365", + "metadata": {}, + "source": [ + "\n", + "\n", + "## Data Preparation" + ] + }, { "cell_type": "markdown", "id": "2e0c78b4", @@ -413,11 +426,13 @@ "source": [ "def generate_synthetic_market_data(model, strikes, maturities):\n", " market_prices = []\n", + " market_data = []\n", " for K, T in zip(strikes, maturities):\n", " model.K = K\n", " model.T = T\n", " market_prices.append(model.price_option(10000, 100))\n", - " return market_prices\n" + " market_data.append({\"strike\": K, \"option_price\": model.price_option(10000, 100)})\n", + " return market_prices, market_data\n" ] }, { @@ -443,16 +458,142 @@ "true_rho = -0.5\n", "\n", "# Synthetic data generation parameters\n", - "strikes = [90, 95, 100, 105, 110]\n", - "maturities = [0.5, 1.0, 1.5, 2.0, 2.5]\n", + "strikes = list(np.linspace(75, 150, 25))\n", + "maturities = list(np.linspace(0.2, 3.0, 25))\n", "\n", "# Generate synthetic market data using the true parameters\n", "bs_model = BlackScholesModel(S0, K, T, r, true_sigma)\n", - "bs_market_prices = generate_synthetic_market_data(bs_model, strikes, maturities)\n", + "bs_market_prices, bs_market_data = generate_synthetic_market_data(bs_model, strikes, maturities)\n", "\n", "\n", "sv_model = StochasticVolatilityModel(S0, K, T, r, true_v0, true_kappa, true_theta, true_xi, true_rho)\n", - "sv_market_prices = generate_synthetic_market_data(sv_model, strikes, maturities)\n" + "sv_market_prices, sv_market_data = generate_synthetic_market_data(sv_model, strikes, maturities)\n" + ] + }, + { + "cell_type": "markdown", + "id": "2ee57be7", + "metadata": {}, + "source": [ + "### Initialize the ValidMind datasets\n", + "\n", + "Before you can run tests, you must first initialize a ValidMind dataset object using the [`init_dataset`](https://docs.validmind.ai/validmind/validmind.html#init_dataset) function from the ValidMind (`vm`) module." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "78cf5317", + "metadata": {}, + "outputs": [], + "source": [ + "bs_market_data_df = pd.DataFrame(bs_market_data)\n", + "vm_bs_market_data = vm.init_dataset(\n", + " dataset=bs_market_data_df,\n", + " input_id=\"sv_market_data\",\n", + ")\n", + "\n", + "sv_market_data_df = pd.DataFrame(sv_market_data)\n", + "vm_sv_market_data = vm.init_dataset(\n", + " dataset=sv_market_data_df,\n", + " input_id=\"sv_market_data\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "e2079eda", + "metadata": {}, + "source": [ + "### Data Quality\n", + "Let's check quality of the data using outliers and missing data tests." + ] + }, + { + "cell_type": "markdown", + "id": "8dfc7cc3", + "metadata": {}, + "source": [ + "#### Isolation Forest Outliers Test\n", + "Let's detects anomalies in the dataset using the Isolation Forest algorithm, visualized through scatter plots." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9eb91453", + "metadata": {}, + "outputs": [], + "source": [ + "result = run_test(\n", + " \"validmind.data_validation.IsolationForestOutliers:BlackScholes\",\n", + " inputs={\n", + " \"dataset\": vm_bs_market_data,\n", + " },\n", + " title=\"Outliers detection using Isolation Forest for BlackScholes\",\n", + ")\n", + "result.log()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "62c5dfad", + "metadata": {}, + "outputs": [], + "source": [ + "result = run_test(\n", + " \"validmind.data_validation.IsolationForestOutliers:StochasticVolatility\",\n", + " inputs={\n", + " \"dataset\": vm_sv_market_data,\n", + " },\n", + " title=\"Outliers detection using Isolation Forest for StochasticVolatility\",\n", + ")\n", + "result.log()" + ] + }, + { + "cell_type": "markdown", + "id": "048caf26", + "metadata": {}, + "source": [ + "##### Missing Values Test\n", + "Let's evaluates dataset quality by ensuring the missing value ratio across all features does not exceed a set threshold." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "805ddb1c", + "metadata": {}, + "outputs": [], + "source": [ + "result = run_test(\n", + " \"validmind.data_validation.MissingValues:BlackScholes\",\n", + " inputs={\n", + " \"dataset\": vm_bs_market_data,\n", + " },\n", + " title=\"Missing Values detection for BlackScholes\",\n", + ")\n", + "result.log()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "950e5b39", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "result = run_test(\n", + " \"validmind.data_validation.MissingValues:StochasticVolatility\",\n", + " inputs={\n", + " \"dataset\": vm_sv_market_data,\n", + " },\n", + " title=\"MissingValues detection for StochasticVolatility\",\n", + ")\n", + "result.log()" ] }, { @@ -468,7 +609,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 14, "id": "5e709e0e", "metadata": {}, "outputs": [], @@ -566,7 +707,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 16, "id": "ac733262", "metadata": {}, "outputs": [], @@ -647,7 +788,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 18, "id": "80492c82", "metadata": {}, "outputs": [], @@ -678,7 +819,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 19, "id": "b2115371", "metadata": {}, "outputs": [], @@ -702,7 +843,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 20, "id": "f6c98fbe", "metadata": {}, "outputs": [], @@ -767,16 +908,6 @@ ")" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "b30e1b5a", - "metadata": {}, - "outputs": [], - "source": [ - "\n" - ] - }, { "cell_type": "markdown", "id": "fe2c8f65", @@ -836,7 +967,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 23, "id": "7bdd02ed", "metadata": {}, "outputs": [], @@ -963,12 +1094,12 @@ " \"S0\": [S0],\n", " \"T\": [T],\n", " \"r\": [r],\n", - " \"sigma\": list(np.linspace(0.1, 0.8, 10)),\n", + " \"sigma\": list(np.linspace(0.2, 0.8, 10)),\n", " },\n", ")\n", "result.log()\n", "plot_results(\n", - " pd.DataFrame(result.metric.summary.results[0].data),\n", + " pd.DataFrame(result.tables[0].data),\n", " params={\n", " \"x\": \"sigma\",\n", " \"y\":\"Option price\",\n", diff --git a/notebooks/code_samples/capital_markets/quickstart_option_pricing_models_quantlib.ipynb b/notebooks/code_samples/capital_markets/quickstart_option_pricing_models_quantlib.ipynb index 559b21889..32f9cbce2 100644 --- a/notebooks/code_samples/capital_markets/quickstart_option_pricing_models_quantlib.ipynb +++ b/notebooks/code_samples/capital_markets/quickstart_option_pricing_models_quantlib.ipynb @@ -73,7 +73,8 @@ "- [Initialize the ValidMind Library](#toc3_) \n", "- [Initialize the Python environment](#toc4_) \n", " - [Preview the documentation template](#toc4_1_) \n", - "- [Data preparation](#toc5_) \n", + "- [Data preparation](#toc5_)\n", + " - [Data quality](#toc5_1_)\n", "- [Model development](#toc6_) \n", " - [Model Calibration](#toc6_1_) \n", "- [Model Evaluation](#toc7_) \n", @@ -246,7 +247,7 @@ " # api_key=\"...\",\n", " # api_secret=\"...\",\n", " # model=\"...\",\n", - ")" + ")\n" ] }, { @@ -423,11 +424,94 @@ "outputs": [], "source": [ "ticker = \"MSFT\"\n", - "expiration_date = \"2024-12-06\" # Example expiration date in 'YYYY-MM-DD' form\n", + "expiration_date = \"2024-12-13\" # Example expiration date in 'YYYY-MM-DD' form\n", "\n", "market_data = get_market_data(ticker=ticker, expiration_date_str=expiration_date)" ] }, + { + "cell_type": "markdown", + "id": "ebdc4336", + "metadata": {}, + "source": [ + "### Initialize the ValidMind datasets\n", + "\n", + "Before you can run tests, you must first initialize a ValidMind dataset object using the [`init_dataset`](https://docs.validmind.ai/validmind/validmind.html#init_dataset) function from the ValidMind (`vm`) module." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "fc11db86", + "metadata": {}, + "outputs": [], + "source": [ + "vm_market_data = vm.init_dataset(\n", + " dataset=market_data,\n", + " input_id=\"market_data\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "8d3e119e", + "metadata": {}, + "source": [ + "\n", + "\n", + "### Data Quality\n", + "Let's check quality of the data using outliers and missing data tests." + ] + }, + { + "cell_type": "markdown", + "id": "886e1b88", + "metadata": {}, + "source": [ + "#### Isolation Forest Outliers Test\n", + "Let's detects anomalies in the dataset using the Isolation Forest algorithm, visualized through scatter plots." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c6fe3def", + "metadata": {}, + "outputs": [], + "source": [ + "result = run_test(\n", + " \"validmind.data_validation.IsolationForestOutliers\",\n", + " inputs={\n", + " \"dataset\": vm_market_data,\n", + " },\n", + " title=\"Outliers detection using Isolation Forest\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Missing Values Test\n", + "Let's evaluates dataset quality by ensuring the missing value ratio across all features does not exceed a set threshold." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3180e5fc", + "metadata": {}, + "outputs": [], + "source": [ + "result = run_test(\n", + " \"validmind.data_validation.MissingValues\",\n", + " inputs={\n", + " \"dataset\": vm_market_data,\n", + " },\n", + " title=\"Missing Values detection\",\n", + ")" + ] + }, { "cell_type": "markdown", "id": "1db5f835", @@ -440,7 +524,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 12, "id": "d28df598", "metadata": {}, "outputs": [], @@ -459,7 +543,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 13, "id": "dc070da8", "metadata": {}, "outputs": [], @@ -637,7 +721,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 15, "id": "810cf887", "metadata": {}, "outputs": [], @@ -724,7 +808,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 17, "id": "80492c82", "metadata": {}, "outputs": [], @@ -783,7 +867,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 18, "id": "4862005d", "metadata": {}, "outputs": [], @@ -810,7 +894,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 19, "id": "b2115371", "metadata": {}, "outputs": [], @@ -877,7 +961,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 21, "id": "b977f2e3", "metadata": {}, "outputs": [], From 2871c742902d25aaa60318f4b7baf09e60cb8659 Mon Sep 17 00:00:00 2001 From: Anil Sorathiya Date: Thu, 12 Dec 2024 22:11:53 +0000 Subject: [PATCH 2/5] Create graphs from test output using post_process function --- .../quickstart_option_pricing_models.ipynb | 342 ++++++++++++------ 1 file changed, 235 insertions(+), 107 deletions(-) diff --git a/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb b/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb index b7446349d..e8c7cc742 100644 --- a/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb +++ b/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb @@ -190,7 +190,7 @@ " # api_key=\"...\",\n", " # api_secret=\"...\",\n", " # model=\"...\",\n", - ")\n" + ")" ] }, { @@ -509,6 +509,91 @@ "Let's check quality of the data using outliers and missing data tests." ] }, + { + "cell_type": "markdown", + "id": "8f52ac93", + "metadata": {}, + "source": [ + "#### Outliers detection using IQR method\n", + "Let's visualizes the distribution of outliers in the option_price feature using the Interquartile Range (IQR) method." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f1c1ab6f", + "metadata": {}, + "outputs": [], + "source": [ + "result = run_test(\n", + " \"validmind.data_validation.IQROutliersBarPlot:BlackScholes\",\n", + " inputs={\n", + " \"dataset\": vm_bs_market_data,\n", + " },\n", + " title=\"Outliers detection using IQR method for BlackScholes\",\n", + ")\n", + "result.log()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b5e8654", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "\n", + "\n", + "\n", + "result = run_test(\n", + " \"validmind.data_validation.IQROutliersTable:BlackScholes\",\n", + " inputs={\n", + " \"dataset\": vm_bs_market_data,\n", + " },\n", + " title=\"Outliers table using IQR method for BlackScholes\",\n", + ")\n", + "result.log()\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d96f10c7", + "metadata": {}, + "outputs": [], + "source": [ + "result = run_test(\n", + " \"validmind.data_validation.IQROutliersBarPlot:StochasticVolatility\",\n", + " inputs={\n", + " \"dataset\": vm_sv_market_data,\n", + " },\n", + " title=\"Outliers detection using IQR method for StochasticVolatility\",\n", + ")\n", + "result.log()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d5b821d3", + "metadata": {}, + "outputs": [], + "source": [ + "result = run_test(\n", + " \"validmind.data_validation.IQROutliersTable:StochasticVolatility\",\n", + " inputs={\n", + " \"dataset\": vm_sv_market_data,\n", + " },\n", + " title=\"Outliers table using IQR method for StochasticVolatility\",\n", + ")\n", + "result.log()" + ] + }, { "cell_type": "markdown", "id": "8dfc7cc3", @@ -609,7 +694,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 18, "id": "5e709e0e", "metadata": {}, "outputs": [], @@ -707,7 +792,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 20, "id": "ac733262", "metadata": {}, "outputs": [], @@ -788,11 +873,12 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 22, "id": "80492c82", "metadata": {}, "outputs": [], "source": [ + "\n", "@vm.test(\"my_custom_tests.Sensitivity\")\n", "def sensitivity_test(model_type, S0, T, r, N, M, strike=None, barrier=None, sigma=None, v0=None, kappa=None,theta=None, xi=None, rho=None):\n", " \"\"\"\n", @@ -819,7 +905,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 23, "id": "b2115371", "metadata": {}, "outputs": [], @@ -838,25 +924,58 @@ "id": "9a798ff8", "metadata": {}, "source": [ - "##### Common plot function" + "##### Common plot function\n", + "Let's create a line plot using the default result output data and log it by passing the function through the `post_process_fn` parameter in the `run_test()` method." ] }, { "cell_type": "code", - "execution_count": 20, - "id": "f6c98fbe", + "execution_count": 24, + "id": "d96969b7", "metadata": {}, "outputs": [], "source": [ - "def plot_results(df, params: dict = None):\n", - " fig2 = plt.figure(figsize=(10, 6))\n", - " plt.plot(df[params[\"x\"]], df[params[\"y\"]], label=params[\"label\"])\n", - " plt.xlabel(params[\"xlabel\"])\n", - " plt.ylabel(params[\"ylabel\"])\n", - " plt.title(params[\"title\"])\n", - " plt.legend()\n", - " plt.grid(True)\n", - " plt.show() " + "from plotly_express import bar\n", + "from validmind.vm_models.figure import Figure\n", + "from validmind.vm_models.result import TestResult\n", + "import plotly.graph_objects as go\n", + "import random\n", + "\n", + "def process_results(result: TestResult):\n", + " # Convert to DataFrame\n", + " df = pd.DataFrame(result.tables[0].data)\n", + " \n", + " # Get the first two column names\n", + " x_col = df.columns[0]\n", + " y_col = df.columns[1]\n", + " \n", + " # Create figure\n", + " fig = go.Figure()\n", + " fig.add_trace(\n", + " go.Scatter(\n", + " x=df[x_col],\n", + " y=df[y_col],\n", + " mode='lines',\n", + " name=y_col # Use y-axis column name as trace name\n", + " )\n", + " )\n", + " \n", + " fig.update_layout(\n", + " xaxis_title=x_col,\n", + " yaxis_title=y_col,\n", + " showlegend=True,\n", + " template=\"plotly_white\"\n", + " )\n", + "\n", + " result.add_figure(\n", + " Figure(\n", + " figure=fig,\n", + " key=\"sensitivity_plot_\" + str(random.randint(0, 1000000)),\n", + " ref_id=result.ref_id,\n", + " )\n", + " )\n", + "\n", + " return result" ] }, { @@ -893,19 +1012,9 @@ " \"xi\": [0.1],\n", " \"rho\": [-0.5],\n", " },\n", + " post_process_fn= process_results\n", ")\n", - "result.log()\n", - "plot_results(\n", - " pd.DataFrame(result.tables[0].data),\n", - " params={\n", - " \"x\": \"strike\",\n", - " \"y\":\"Option price\",\n", - " \"label\":\"Option price\",\n", - " \"xlabel\":\"strike\",\n", - " \"ylabel\":\"option price\",\n", - " \"title\":\"Knockout Option Price - Strike Level sensitivity\",\n", - " }\n", - ")" + "result.log()" ] }, { @@ -941,19 +1050,10 @@ " \"xi\": [0.1],\n", " \"rho\": [-0.5],\n", " },\n", + " post_process_fn=process_results\n", + "\n", ")\n", - "result.log()\n", - "plot_results(\n", - " pd.DataFrame(result.tables[0].data),\n", - " params={\n", - " \"x\": \"barrier\",\n", - " \"y\":\"Option price\",\n", - " \"label\":\"Option price\",\n", - " \"xlabel\":\"barrier\",\n", - " \"ylabel\":\"option price\",\n", - " \"title\":\"Knockout Option Price - Barrier Level Sensitivity\",\n", - " }\n", - ")" + "result.log()" ] }, { @@ -967,7 +1067,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 27, "id": "7bdd02ed", "metadata": {}, "outputs": [], @@ -994,9 +1094,83 @@ "metadata": {}, "source": [ "##### Rho (correlation) and Theta (long term vol) stress test\n", + "First, we create a surface plot to visualize the option price with respect to two variables." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "77d49b6a", + "metadata": {}, + "outputs": [], + "source": [ + "def two_parameters_stress_surface_plot(result: TestResult):\n", + " import plotly.graph_objects as go\n", + " import numpy as np\n", + " import pandas as pd\n", + " # Convert to DataFrame\n", + " data = pd.DataFrame(result.tables[0].data)\n", + " \n", + " # Get column names (assuming first column is x, next two are y1 and y2)\n", + " z_col = data.columns[2]\n", + " x_col = data.columns[0]\n", + " y_col = data.columns[1]\n", + " \n", + " # Get unique values for x and y\n", + " x_unique = np.sort(data[x_col].unique())\n", + " y_unique = np.sort(data[y_col].unique())\n", + " \n", + " # Create meshgrid\n", + " X, Y = np.meshgrid(x_unique, y_unique)\n", + " \n", + " # Create Z matrix\n", + " Z = np.zeros_like(X)\n", + " for i, x_val in enumerate(x_unique):\n", + " for j, y_val in enumerate(y_unique):\n", + " mask = (data[x_col] == x_val) & (data[y_col] == y_val)\n", + " if mask.any():\n", + " Z[j, i] = data.loc[mask, z_col].iloc[0]\n", + " \n", + " # Create the 3D surface plot\n", + " fig = go.Figure(data=[go.Surface(x=X, y=Y, z=Z)])\n", + " \n", + " # Update the layout\n", + " fig.update_layout(\n", + " title=f'3D Surface Plot of {z_col}',\n", + " scene=dict(\n", + " xaxis_title=x_col,\n", + " yaxis_title=y_col,\n", + " zaxis_title=z_col,\n", + " camera=dict(\n", + " up=dict(x=0, y=0, z=1),\n", + " center=dict(x=0, y=0, z=0),\n", + " eye=dict(x=1.5, y=1.5, z=1.5)\n", + " )\n", + " ),\n", + " width=900,\n", + " height=700,\n", + " margin=dict(l=65, r=50, b=65, t=90)\n", + " )\n", + "\n", + " result.add_figure(\n", + " Figure(\n", + " figure=fig,\n", + " key=\"sensitivity_plot_\" + str(random.randint(0, 1000000)),\n", + " ref_id=result.ref_id,\n", + " )\n", + " )\n", + "\n", + " return result" + ] + }, + { + "cell_type": "markdown", + "id": "6b586190", + "metadata": {}, + "source": [ "Let's evaluates the sensitivity of a model's output to changes in the correlation parameter (rho) and the long-term variance parameter (theta) within a stochastic volatility framework.\n", "\n", - "This test is useful for understanding how variations in these parameters affect the model's valuation, which is crucial for risk management and model validation.\n" + "This test is useful for understanding how variations in these parameters affect the model's valuation, which is crucial for risk management and model validation." ] }, { @@ -1021,10 +1195,11 @@ " \"r\": [r],\n", " \"v0\": [0.2],\n", " \"kappa\": [2],\n", - " \"theta\": [0, 0.2, 0.4],\n", + " \"theta\": list(np.linspace(0,0.8, 10)),\n", " \"xi\": [0.1],\n", - " \"rho\": [-1, -0.5, 0, 0.5, 1],\n", + " \"rho\": list(np.linspace(-1,0.8, 10)),\n", " },\n", + " post_process_fn=two_parameters_stress_surface_plot\n", ")\n", "result.log()\n" ] @@ -1044,6 +1219,8 @@ "metadata": {}, "outputs": [], "source": [ + "\n", + "\n", "result = run_test(\n", " \"my_custom_tests.Stressing:TheRhoAndXiParameters\",\n", " param_grid={\n", @@ -1058,9 +1235,10 @@ " \"v0\": [0.2],\n", " \"kappa\": [2],\n", " \"theta\": [0.2],\n", - " \"xi\": [0, 0.2, 0.4],\n", - " \"rho\": [-1, -0.5, 0, 0.5, 1],\n", + " \"xi\": list(np.linspace(0,0.8, 10)),\n", + " \"rho\": list(np.linspace(-1,0.8, 10)),\n", " },\n", + " post_process_fn=two_parameters_stress_surface_plot\n", ")\n", "result.log()\n" ] @@ -1096,19 +1274,9 @@ " \"r\": [r],\n", " \"sigma\": list(np.linspace(0.2, 0.8, 10)),\n", " },\n", + " post_process_fn=process_results\n", ")\n", - "result.log()\n", - "plot_results(\n", - " pd.DataFrame(result.tables[0].data),\n", - " params={\n", - " \"x\": \"sigma\",\n", - " \"y\":\"Option price\",\n", - " \"label\":\"Option price\",\n", - " \"xlabel\":\"Sigma\",\n", - " \"ylabel\":\"Option price\",\n", - " \"title\":\"Knockout Option Price - Stress sigma\",\n", - " }\n", - ")" + "result.log()\n" ] }, { @@ -1145,19 +1313,9 @@ " \"xi\": [0.1],\n", " \"rho\": [-0.5],\n", " },\n", + " post_process_fn=process_results\n", ")\n", - "result.log()\n", - "plot_results(\n", - " pd.DataFrame(result.tables[0].data),\n", - " params={\n", - " \"x\": \"kappa\",\n", - " \"y\":\"Option price\",\n", - " \"label\":\"Option price\",\n", - " \"xlabel\":\"kappa\",\n", - " \"ylabel\":\"option price\",\n", - " \"title\":\"Knockout Option Price - stress kappa\",\n", - " }\n", - ")" + "result.log()\n" ] }, { @@ -1193,19 +1351,9 @@ " \"xi\": [0.1],\n", " \"rho\": [-0.5],\n", " },\n", + " post_process_fn=process_results\n", ")\n", - "result.log()\n", - "plot_results(\n", - " pd.DataFrame(result.tables[0].data),\n", - " params={\n", - " \"x\": \"theta\",\n", - " \"y\":\"Option price\",\n", - " \"label\":\"Option price\",\n", - " \"xlabel\":\"theta\",\n", - " \"ylabel\":\"option price\",\n", - " \"title\":\"Knockout Option Price - stress theta\",\n", - " }\n", - ")" + "result.log()\n" ] }, { @@ -1241,19 +1389,9 @@ " \"xi\": list(np.linspace(0.05, 0.95, 10)),\n", " \"rho\": [-0.5],\n", " },\n", + " post_process_fn=process_results\n", ")\n", - "result.log()\n", - "plot_results(\n", - " pd.DataFrame(result.tables[0].data),\n", - " params={\n", - " \"x\": \"xi\",\n", - " \"y\":\"Option price\",\n", - " \"label\":\"Option price\",\n", - " \"xlabel\":\"xi\",\n", - " \"ylabel\":\"option price\",\n", - " \"title\":\"Knockout Option Price - stress xi\",\n", - " }\n", - ")" + "result.log()\n" ] }, { @@ -1289,19 +1427,9 @@ " \"xi\": [0.1],\n", " \"rho\": list(np.linspace(-1.0, 1.0, 20)),\n", " },\n", + " post_process_fn=process_results\n", ")\n", - "result.log()\n", - "plot_results(\n", - " pd.DataFrame(result.tables[0].data),\n", - " params={\n", - " \"x\": \"rho\",\n", - " \"y\":\"Option price\",\n", - " \"label\":\"Option price\",\n", - " \"xlabel\":\"rho\",\n", - " \"ylabel\":\"option price\",\n", - " \"title\":\"Knockout Option Price - stress rho\",\n", - " }\n", - ")" + "result.log()\n" ] }, { From d897ef0b035e77497917d571093c5f808864a9a3 Mon Sep 17 00:00:00 2001 From: Anil Sorathiya Date: Thu, 12 Dec 2024 22:14:26 +0000 Subject: [PATCH 3/5] format notebook --- .../quickstart_option_pricing_models.ipynb | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb b/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb index e8c7cc742..67fa924e6 100644 --- a/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb +++ b/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb @@ -542,10 +542,6 @@ "metadata": {}, "outputs": [], "source": [ - "\n", - "\n", - "\n", - "\n", "result = run_test(\n", " \"validmind.data_validation.IQROutliersTable:BlackScholes\",\n", " inputs={\n", @@ -553,11 +549,7 @@ " },\n", " title=\"Outliers table using IQR method for BlackScholes\",\n", ")\n", - "result.log()\n", - "\n", - "\n", - "\n", - "\n" + "result.log()" ] }, { @@ -660,7 +652,7 @@ " },\n", " title=\"Missing Values detection for BlackScholes\",\n", ")\n", - "result.log()\n" + "result.log()" ] }, { From e7aa512170312cd78c12ff70ef0727231bfd6432 Mon Sep 17 00:00:00 2001 From: Anil Sorathiya Date: Mon, 16 Dec 2024 14:51:12 +0000 Subject: [PATCH 4/5] add greeks tests --- .../quickstart_option_pricing_models.ipynb | 427 +++++++++++++++++- 1 file changed, 424 insertions(+), 3 deletions(-) diff --git a/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb b/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb index 67fa924e6..7e72afaa0 100644 --- a/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb +++ b/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb @@ -934,6 +934,7 @@ "import random\n", "\n", "def process_results(result: TestResult):\n", + "\n", " # Convert to DataFrame\n", " df = pd.DataFrame(result.tables[0].data)\n", " \n", @@ -980,6 +981,35 @@ "This test is crucial for understanding how variations in strike prices affect the valuation of financial derivatives, particularly options." ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "bb8f1cab", + "metadata": {}, + "outputs": [], + "source": [ + "result = run_test(\n", + " \"my_custom_tests.Sensitivity:S0\",\n", + " param_grid={\n", + " \"model_type\": ['SV'],\n", + " \"N\": [N],\n", + " \"M\": [M],\n", + " \"strike\":[strike_range[0]],\n", + " \"barrier\": [barrier_range[0]],\n", + " \"S0\": list(np.linspace(S0-20, S0+20, 20)),\n", + " \"T\": [T],\n", + " \"r\": [r],\n", + " \"v0\": [0.2],\n", + " \"kappa\": [2],\n", + " \"theta\": [0.2],\n", + " \"xi\": [0.1],\n", + " \"rho\": [-0.5],\n", + " },\n", + " post_process_fn= process_results\n", + ")\n", + "result.log()" + ] + }, { "cell_type": "code", "execution_count": null, @@ -1050,16 +1080,407 @@ }, { "cell_type": "markdown", - "id": "14fd2cd8", + "id": "35d6d3cc", "metadata": {}, "source": [ "\n", + "#### Greeks " + ] + }, + { + "cell_type": "markdown", + "id": "07cd8d2d", + "metadata": {}, + "source": [ + "### Delta" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "31befc58", + "metadata": {}, + "outputs": [], + "source": [ + "@vm.test(\"my_custom_tests.GreeksDelta\")\n", + "def calculate_delta(model_type, S0, T, r, N, M, strike=None, barrier=None, \n", + " sigma=None, v0=None, kappa=None, theta=None, xi=None, rho=None, \n", + " h=0.001): # h is the step size for finite difference\n", + " \"\"\"\n", + " Calculate delta using finite difference method.\n", + " Delta = (V(S0 + h) - V(S0 - h)) / (2h)\n", + " where V is the option price and h is a small increment\n", + " \"\"\"\n", + " # Initialize the model with S0 + h\n", + " if model_type == 'BS':\n", + " model_up = BlackScholesModel(S0 + h, strike, T, r, sigma)\n", + " model_down = BlackScholesModel(S0 - h, strike, T, r, sigma)\n", + " else:\n", + " model_up = StochasticVolatilityModel(S0 + h, strike, T, r, v0, kappa, theta, xi, rho)\n", + " model_down = StochasticVolatilityModel(S0 - h, strike, T, r, v0, kappa, theta, xi, rho)\n", + " \n", + "\n", + " # Calculate option prices for up and down moves\n", + " knockout_up = KnockoutOption(model_up, S0 + h, strike, T, r, barrier)\n", + " knockout_down = KnockoutOption(model_down, S0 - h, strike, T, r, barrier)\n", + " \n", + " price_up = knockout_up.price_knockout_option(N, M)\n", + " price_down = knockout_down.price_knockout_option(N, M)\n", + " \n", + " # Calculate delta using central difference\n", + " delta = (price_up - price_down) / (2 * h)\n", + " df = pd.DataFrame({\"Delta\": [delta], \"Price_Up\": [price_up], \"Price_Down\": [price_down], \"h\": [h]})\n", + " return df\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a4305e12", + "metadata": {}, + "outputs": [], + "source": [ + "# To analyze delta sensitivity to underlying price changes\n", + "result = run_test(\n", + " \"my_custom_tests.GreeksDelta\",\n", + " param_grid={\n", + " \"model_type\": ['SV'],\n", + " \"N\": [1000000],\n", + " \"M\": [M],\n", + " \"strike\":[strike_range[0]],\n", + " \"barrier\": [barrier_range[0]],\n", + " \"S0\": list(np.linspace(S0-20, S0+20, 20)),\n", + " \"T\": [T],\n", + " \"r\": [r],\n", + " \"v0\": [0.2],\n", + " \"kappa\": [2],\n", + " \"theta\": [0.2],\n", + " \"xi\": [0.1],\n", + " \"rho\": [-0.5],\n", + " \"h\": [0.001]\n", + " },\n", + "post_process_fn=process_results # Using the plotting function defined earlier\n", + ")\n", + "result.log()" + ] + }, + { + "cell_type": "markdown", + "id": "27beb54f", + "metadata": {}, + "source": [ + "### Gamma" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b1878011", + "metadata": {}, + "outputs": [], + "source": [ + "@vm.test(\"my_custom_tests.GreeksGamma\")\n", + "def calculate_gamma(model_type, S0, T, r, N, M, strike=None, barrier=None, \n", + " sigma=None, v0=None, kappa=None, theta=None, xi=None, rho=None, \n", + " h=0.01): # h is the step size for finite difference\n", + " \"\"\"\n", + " Calculate gamma using finite difference method.\n", + " Gamma = (V(S0 + h) - 2V(S0) + V(S0 - h)) / h^2\n", + " where V is the option price and h is a small increment\n", + " \"\"\"\n", + " # Initialize the models with S0 + h, S0, and S0 - h\n", + " if model_type == 'BS':\n", + " model_up = BlackScholesModel(S0 + h, strike, T, r, sigma)\n", + " model_center = BlackScholesModel(S0, strike, T, r, sigma)\n", + " model_down = BlackScholesModel(S0 - h, strike, T, r, sigma)\n", + " else:\n", + " model_up = StochasticVolatilityModel(S0 + h, strike, T, r, v0, kappa, theta, xi, rho)\n", + " model_center = StochasticVolatilityModel(S0, strike, T, r, v0, kappa, theta, xi, rho)\n", + " model_down = StochasticVolatilityModel(S0 - h, strike, T, r, v0, kappa, theta, xi, rho)\n", + " \n", + " # Calculate option prices for up, center, and down moves\n", + " knockout_up = KnockoutOption(model_up, S0 + h, strike, T, r, barrier)\n", + " knockout_center = KnockoutOption(model_center, S0, strike, T, r, barrier)\n", + " knockout_down = KnockoutOption(model_down, S0 - h, strike, T, r, barrier)\n", + " \n", + " price_up = knockout_up.price_knockout_option(N, M)\n", + " price_center = knockout_center.price_knockout_option(N, M)\n", + " price_down = knockout_down.price_knockout_option(N, M)\n", + " \n", + " # Calculate gamma using second-order central difference\n", + " gamma = (price_up - 2*price_center + price_down) / (h * h)\n", + " \n", + " df = pd.DataFrame({\n", + " \"Gamma\": [gamma], \n", + " \"Price_Up\": [price_up], \n", + " \"Price_Center\": [price_center],\n", + " \"Price_Down\": [price_down], \n", + " \"h\": [h]\n", + " })\n", + " return df\n", + "\n", + "# To analyze gamma sensitivity to underlying price changes\n", + "result = run_test(\n", + " \"my_custom_tests.GreeksGamma\",\n", + " param_grid={\n", + " \"model_type\": ['SV'],\n", + " \"N\": [1000000],\n", + " \"M\": [M],\n", + " \"strike\":[strike_range[0]],\n", + " \"barrier\": [barrier_range[0]],\n", + " \"S0\": list(np.linspace(S0-20, S0+20, 20)),\n", + " \"T\": [T],\n", + " \"r\": [r],\n", + " \"v0\": [0.2],\n", + " \"kappa\": [2],\n", + " \"theta\": [0.2],\n", + " \"xi\": [0.1],\n", + " \"rho\": [-0.5],\n", + " \"h\": [0.1]\n", + " },\n", + " post_process_fn=process_results # Using the plotting function defined earlier\n", + ")\n", + "result.log()" + ] + }, + { + "cell_type": "markdown", + "id": "58ee0864", + "metadata": {}, + "source": [ + "### Theta" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "20fa7300", + "metadata": {}, + "outputs": [], + "source": [ + "@vm.test(\"my_custom_tests.GreeksTheta\")\n", + "def calculate_theta(model_type, S0, T, r, N, M, strike=None, barrier=None, \n", + " sigma=None, v0=None, kappa=None, theta=None, xi=None, rho=None, \n", + " dt=1/365): # dt is typically one day\n", + " \"\"\"\n", + " Calculate theta using finite difference method.\n", + " Theta = (V(t + dt) - V(t)) / dt\n", + " where V is the option price and dt is a small time increment (typically 1 day)\n", + " \"\"\"\n", + " # Initialize the models with T and T + dt\n", + " if model_type == 'BS':\n", + " model_current = BlackScholesModel(S0, strike, T, r, sigma)\n", + " model_future = BlackScholesModel(S0, strike, T + dt, r, sigma)\n", + " else:\n", + " model_current = StochasticVolatilityModel(S0, strike, T, r, v0, kappa, theta, xi, rho)\n", + " model_future = StochasticVolatilityModel(S0, strike, T + dt, r, v0, kappa, theta, xi, rho)\n", + " \n", + " # Calculate option prices for current and future time\n", + " knockout_current = KnockoutOption(model_current, S0, strike, T, r, barrier)\n", + " knockout_future = KnockoutOption(model_future, S0, strike, T + dt, r, barrier)\n", + " \n", + " price_current = knockout_current.price_knockout_option(N, M)\n", + " price_future = knockout_future.price_knockout_option(N, M)\n", + " \n", + " # Calculate theta using forward difference\n", + " # Note: We divide by dt and multiply by -1 since theta represents the negative rate of change\n", + " theta_value = -1 * (price_future - price_current) / dt\n", + " \n", + " df = pd.DataFrame({\n", + " \"Theta\": [theta_value], \n", + " \"Price_Current\": [price_current],\n", + " \"Price_Future\": [price_future],\n", + " \"dt\": [dt]\n", + " })\n", + " return df\n", + "\n", + "# Example usage to analyze theta sensitivity across different underlying prices\n", + "result = run_test(\n", + " \"my_custom_tests.GreeksTheta\",\n", + " param_grid={\n", + " \"model_type\": ['SV'],\n", + " \"N\": [1000000],\n", + " \"M\": [M],\n", + " \"strike\":[strike_range[0]],\n", + " \"barrier\": [barrier_range[0]],\n", + " \"S0\": list(np.linspace(S0-20, S0+20, 20)),\n", + " \"T\": [T],\n", + " \"r\": [r],\n", + " \"v0\": [0.2],\n", + " \"kappa\": [2],\n", + " \"theta\": [0.2],\n", + " \"xi\": [0.1],\n", + " \"rho\": [-0.5],\n", + " \"dt\": [1/365] # One day time step\n", + " },\n", + " post_process_fn=process_results # Using the plotting function defined earlier\n", + ")\n", + "result.log()" + ] + }, + { + "cell_type": "markdown", + "id": "c4b3386e", + "metadata": {}, + "source": [ + "### Vega" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ffb40f67", + "metadata": {}, + "outputs": [], + "source": [ + "@vm.test(\"my_custom_tests.GreeksVega\")\n", + "def calculate_vega(model_type, S0, T, r, N, M, strike=None, barrier=None, \n", + " sigma=None, v0=None, kappa=None, theta=None, xi=None, rho=None, \n", + " h=0.001): # h is the step size for finite difference\n", + " \"\"\"\n", + " Calculate vega using finite difference method.\n", + " For Black-Scholes: Vega = (V(σ + h) - V(σ - h)) / (2h)\n", + " For Stochastic Vol: Vega = (V(v0 + h) - V(v0 - h)) / (2h)\n", + " where V is the option price and h is a small increment in volatility\n", + " \"\"\"\n", + " if model_type == 'BS':\n", + " # For Black-Scholes, perturb sigma\n", + " model_up = BlackScholesModel(S0, strike, T, r, sigma + h)\n", + " model_down = BlackScholesModel(S0, strike, T, r, sigma - h)\n", + " else:\n", + " # For Stochastic Volatility, perturb v0\n", + " model_up = StochasticVolatilityModel(S0, strike, T, r, v0 + h, kappa, theta, xi, rho)\n", + " model_down = StochasticVolatilityModel(S0, strike, T, r, v0 - h, kappa, theta, xi, rho)\n", + " \n", + " # Calculate option prices for up and down moves in volatility\n", + " knockout_up = KnockoutOption(model_up, S0, strike, T, r, barrier)\n", + " knockout_down = KnockoutOption(model_down, S0, strike, T, r, barrier)\n", + " \n", + " price_up = knockout_up.price_knockout_option(N, M)\n", + " price_down = knockout_down.price_knockout_option(N, M)\n", + " \n", + " # Calculate vega using central difference\n", + " vega = (price_up - price_down) / (2 * h)\n", + " \n", + " df = pd.DataFrame({\n", + " \"Vega\": [vega], \n", + " \"Price_Up\": [price_up], \n", + " \"Price_Down\": [price_down], \n", + " \"h\": [h]\n", + " })\n", + " return df\n", + "\n", + "# Example usage to analyze vega sensitivity across different underlying prices\n", + "result = run_test(\n", + " \"my_custom_tests.GreeksVega\",\n", + " param_grid={\n", + " \"model_type\": ['SV'],\n", + " \"N\": [1000000],\n", + " \"M\": [M],\n", + " \"strike\":[strike_range[0]],\n", + " \"barrier\": [barrier_range[0]],\n", + " \"S0\": list(np.linspace(S0-20, S0+20, 20)),\n", + " \"T\": [T],\n", + " \"r\": [r],\n", + " \"v0\": [0.2],\n", + " \"kappa\": [2],\n", + " \"theta\": [0.2],\n", + " \"xi\": [0.1],\n", + " \"rho\": [-0.5],\n", + " \"h\": [0.0001] # Small step size for better accuracy\n", + " },\n", + " post_process_fn=process_results # Using the plotting function defined earlier\n", + ")\n", + "result.log()" + ] + }, + { + "cell_type": "markdown", + "id": "f917f36f", + "metadata": {}, + "source": [ + "### Rho" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "618efa93", + "metadata": {}, + "outputs": [], + "source": [ + "@vm.test(\"my_custom_tests.GreeksRho\")\n", + "def calculate_rho(model_type, S0, T, r, N, M, strike=None, barrier=None, \n", + " sigma=None, v0=None, kappa=None, theta=None, xi=None, rho=None, \n", + " h=0.0001): # h is the step size for finite difference\n", + " \"\"\"\n", + " Calculate rho using finite difference method.\n", + " Rho = (V(r + h) - V(r - h)) / (2h)\n", + " where V is the option price and h is a small increment in interest rate\n", + " \"\"\"\n", + " # Initialize the models with r + h and r - h\n", + " if model_type == 'BS':\n", + " model_up = BlackScholesModel(S0, strike, T, r + h, sigma)\n", + " model_down = BlackScholesModel(S0, strike, T, r - h, sigma)\n", + " else:\n", + " model_up = StochasticVolatilityModel(S0, strike, T, r + h, v0, kappa, theta, xi, rho)\n", + " model_down = StochasticVolatilityModel(S0, strike, T, r - h, v0, kappa, theta, xi, rho)\n", + " \n", + " # Calculate option prices for up and down moves in interest rate\n", + " knockout_up = KnockoutOption(model_up, S0, strike, T, r + h, barrier)\n", + " knockout_down = KnockoutOption(model_down, S0, strike, T, r - h, barrier)\n", + " \n", + " price_up = knockout_up.price_knockout_option(N, M)\n", + " price_down = knockout_down.price_knockout_option(N, M)\n", + " \n", + " # Calculate rho using central difference\n", + " rho_value = (price_up - price_down) / (2 * h)\n", + " \n", + " df = pd.DataFrame({\n", + " \"Rho\": [rho_value], \n", + " \"Price_Up\": [price_up], \n", + " \"Price_Down\": [price_down], \n", + " \"h\": [h]\n", + " })\n", + " return df\n", + "\n", + "# Example usage to analyze rho sensitivity across different underlying prices\n", + "result = run_test(\n", + " \"my_custom_tests.GreeksRho\",\n", + " param_grid={\n", + " \"model_type\": ['SV'],\n", + " \"N\": [1000000],\n", + " \"M\": [M],\n", + " \"strike\":[strike_range[0]],\n", + " \"barrier\": [barrier_range[0]],\n", + " \"S0\": list(np.linspace(S0-20, S0+20, 20)),\n", + " \"T\": [T],\n", + " \"r\": [r],\n", + " \"v0\": [0.2],\n", + " \"kappa\": [2],\n", + " \"theta\": [0.2],\n", + " \"xi\": [0.1],\n", + " \"rho\": [-0.5],\n", + " \"h\": [0.0001] # Small step size for better accuracy\n", + " },\n", + " post_process_fn=process_results # Using the plotting function defined earlier\n", + ")\n", + "result.log()" + ] + }, + { + "cell_type": "markdown", + "id": "14fd2cd8", + "metadata": {}, + "source": [ + "\n", "#### Stress Testing" ] }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 34, "id": "7bdd02ed", "metadata": {}, "outputs": [], @@ -1091,7 +1512,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 35, "id": "77d49b6a", "metadata": {}, "outputs": [], From f1033ade5cfecb7bde4ab2e21a42818a188fa4f6 Mon Sep 17 00:00:00 2001 From: Anil Sorathiya Date: Mon, 16 Dec 2024 16:12:45 +0000 Subject: [PATCH 5/5] update greeks description --- .../quickstart_option_pricing_models.ipynb | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb b/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb index 7e72afaa0..c1b70c85c 100644 --- a/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb +++ b/notebooks/code_samples/capital_markets/quickstart_option_pricing_models.ipynb @@ -40,8 +40,9 @@ " - [Model Calibration](#toc6_3_) \n", "- [Model Evaluation](#toc7_) \n", " - [Benchmark Testing](#toc7_1_) \n", - " - [Sensitivity Testing](#toc7_2_) \n", - " - [Stress Testing](#toc7_3_) \n", + " - [Sensitivity Testing](#toc7_2_) \n", + " - [Greeks](#toc7_3_) \n", + " - [Stress Testing](#toc7_4_) \n", "- [Next steps](#toc8_) \n", " - [Work with your model documentation](#toc8_1_) \n", " - [Discover more learning resources](#toc8_2_) \n", @@ -1084,7 +1085,8 @@ "metadata": {}, "source": [ "\n", - "#### Greeks " + "#### Greeks \n", + "These Greeks are crucial for traders and risk managers as they provide insights into the risk and potential price movements of options and derivatives, allowing for more informed decision-making and risk management strategies." ] }, { @@ -1092,7 +1094,8 @@ "id": "07cd8d2d", "metadata": {}, "source": [ - "### Delta" + "### Delta\n", + "Let's measures the sensitivity of the option's price to a change in the price of the underlying asset. It indicates how much the price of an option is expected to move per $1 change in the underlying asset's price." ] }, { @@ -1170,7 +1173,8 @@ "id": "27beb54f", "metadata": {}, "source": [ - "### Gamma" + "### Gamma\n", + "Let's measures the rate of change of Delta with respect to changes in the underlying asset's price. It indicates the curvature of the option's price relative to the underlying asset's price." ] }, { @@ -1249,7 +1253,8 @@ "id": "58ee0864", "metadata": {}, "source": [ - "### Theta" + "### Theta\n", + "Let's measures the sensitivity of the option's price to the passage of time, also known as time decay. It indicates how much the price of an option is expected to decrease as the option approaches its expiration date." ] }, { @@ -1324,7 +1329,8 @@ "id": "c4b3386e", "metadata": {}, "source": [ - "### Vega" + "### Vega\n", + "Let's measures the sensitivity of the option's price to changes in the volatility of the underlying asset. It indicates how much the price of an option is expected to change with a 1% change in the underlying asset's volatility." ] }, { @@ -1400,7 +1406,8 @@ "id": "f917f36f", "metadata": {}, "source": [ - "### Rho" + "### Rho\n", + "Let's measures the sensitivity of the option's price to changes in the interest rate. It indicates how much the price of an option is expected to change with a 1% change in interest rates.\n" ] }, {