Mercurial > public > python-black-scholes
changeset 1:b853194dc28b
add methods for eu call option
author | Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com> |
---|---|
date | Mon, 15 Nov 2021 23:14:41 +0100 |
parents | e5f3f855e6f9 |
children | 3eb56c7efd31 |
files | .idea/.gitignore .idea/fucking-black-scholes.iml .idea/inspectionProfiles/Project_Default.xml .idea/inspectionProfiles/profiles_settings.xml .idea/misc.xml .idea/modules.xml .idea/other.xml .idea/vcs.xml README_ES.md fbs/__init__.py fbs/helpers.py fbs/main.py requirements.txt tests/__init__.py tests/test_helpers.py tests/test_main.py |
diffstat | 14 files changed, 200 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.idea/.gitignore Mon Nov 15 23:14:41 2021 +0100 @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Zeppelin ignored files +/ZeppelinRemoteNotebooks/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.idea/fucking-black-scholes.iml Mon Nov 15 23:14:41 2021 +0100 @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="PYTHON_MODULE" version="4"> + <component name="NewModuleRootManager"> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/fbs" isTestSource="false" /> + <excludeFolder url="file://$MODULE_DIR$/venv" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.idea/inspectionProfiles/Project_Default.xml Mon Nov 15 23:14:41 2021 +0100 @@ -0,0 +1,38 @@ +<component name="InspectionProjectProfileManager"> + <profile version="1.0"> + <option name="myName" value="Project Default" /> + <inspection_tool class="PyArgumentEqualDefaultInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> + <inspection_tool class="PyAugmentAssignmentInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> + <inspection_tool class="PyBehaveInspection" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="PyClassicStyleClassInspection" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="ourVersions"> + <value> + <list size="2"> + <item index="0" class="java.lang.String" itemvalue="2.7" /> + <item index="1" class="java.lang.String" itemvalue="3.10" /> + </list> + </value> + </option> + </inspection_tool> + <inspection_tool class="PyMandatoryEncodingInspection" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="PyMissingTypeHintsInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> + <inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="ignoredPackages"> + <value> + <list size="1"> + <item index="0" class="java.lang.String" itemvalue="httpretty" /> + </list> + </value> + </option> + </inspection_tool> + <inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="ignoredIdentifiers"> + <list> + <option value="src.handlers.sentiment.secrets_controller" /> + <option value="flask.Flask" /> + </list> + </option> + </inspection_tool> + </profile> +</component> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.idea/inspectionProfiles/profiles_settings.xml Mon Nov 15 23:14:41 2021 +0100 @@ -0,0 +1,6 @@ +<component name="InspectionProjectProfileManager"> + <settings> + <option name="USE_PROJECT_PROFILE" value="false" /> + <version value="1.0" /> + </settings> +</component> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.idea/misc.xml Mon Nov 15 23:14:41 2021 +0100 @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8 (fucking-black-scholes)" project-jdk-type="Python SDK" /> +</project> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.idea/modules.xml Mon Nov 15 23:14:41 2021 +0100 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectModuleManager"> + <modules> + <module fileurl="file://$PROJECT_DIR$/.idea/fucking-black-scholes.iml" filepath="$PROJECT_DIR$/.idea/fucking-black-scholes.iml" /> + </modules> + </component> +</project> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.idea/other.xml Mon Nov 15 23:14:41 2021 +0100 @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="PySciProjectComponent"> + <option name="PY_SCI_VIEW_SUGGESTED" value="true" /> + </component> +</project> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.idea/vcs.xml Mon Nov 15 23:14:41 2021 +0100 @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="GitSharedSettings"> + <option name="FORCE_PUSH_PROHIBITED_PATTERNS"> + <list> + <option value="main" /> + </list> + </option> + </component> +</project> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README_ES.md Mon Nov 15 23:14:41 2021 +0100 @@ -0,0 +1,1 @@ +# fucking-black-scholes model \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fbs/helpers.py Mon Nov 15 23:14:41 2021 +0100 @@ -0,0 +1,62 @@ +""" +Helper methods +""" + +import math +import numpy as np +from scipy.stats import norm + + +class Option: + def __init__(self, spot_price, exercise_price, risk_free_rate, std, expiration): + """ + :param spot_price: spot price of the underlying asset at t0, float, required + :param exercise_price: exercise price of the option, float, required + :param risk_free_rate: float, required + :param std: standard deviation of the return rate of P, float, required + :param expiration: time to expiration, float, required + :return: None + """ + + self.s = spot_price + self.k = exercise_price + self.r = risk_free_rate + self.std = std + self.t = expiration + + def compute_eu_call_price(self): + """ + Determine the value of an European call option + :return: + """ + + d1 = self.compute_d1() + d2 = self.compute_d2() + + price = self.s * norm.cdf(d1) - self.k * math.exp(- self.r * self.t) * norm.cdf(d2) + + return price + + def compute_d1(self): + """ + Determine d1 coefficient + :return: float + """ + + numerator = (np.log(self.s / self.k) + (self.r + (self.std**2 / 2)) * self.t) + denominator = self.std * np.sqrt(self.t) + + d1 = numerator / denominator + + return d1 + + def compute_d2(self): + """ + Determine d2 coefficient + :return: float + """ + + d1 = self.compute_d1() + d2 = d1 - self.std * np.sqrt(self.t) + + return d2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fbs/main.py Mon Nov 15 23:14:41 2021 +0100 @@ -0,0 +1,6 @@ +def main(): + pass + + +if __name__ == '__main__': + main()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/requirements.txt Mon Nov 15 23:14:41 2021 +0100 @@ -0,0 +1,2 @@ +numpy~=1.21.4 +scipy~=1.7.2 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test_helpers.py Mon Nov 15 23:14:41 2021 +0100 @@ -0,0 +1,30 @@ +from unittest import TestCase +from fbs.helpers import Option + + +class TestOption(TestCase): + option = Option( + spot_price=20.00, + exercise_price=21.00, + risk_free_rate=0.05, + std=0.25, + expiration=0.5 # 6 month (half year) + ) + + def test_compute_eu_call_price(self): + price = self.option.compute_eu_call_price() + price = round(price, 2) + + self.assertEqual(price, 1.20, 'EU call price is not equal to 1.20') + + def test_compute_d1(self): + d1 = self.option.compute_d1() + d1 = round(d1, 2) + + self.assertEqual(d1, -0.05, 'D1 coefficient is not equal to -0.05') + + def test_compute_d2(self): + d2 = self.option.compute_d2() + d2 = round(d2, 2) + + self.assertEqual(d2, -0.22, 'D2 coefficient is now equal to -0.22')